Index: trunk/phase3/maintenance/language/messages.inc |
— | — | @@ -3475,6 +3475,7 @@ |
3476 | 3476 | 'ajax-error-dismiss', |
3477 | 3477 | 'ajax-remove-category-error', |
3478 | 3478 | 'ajax-edit-category-error', |
| 3479 | + 'ajax-category-already-present', |
3479 | 3480 | ), |
3480 | 3481 | |
3481 | 3482 | ); |
Index: trunk/phase3/languages/messages/MessagesEn.php |
— | — | @@ -4606,4 +4606,5 @@ |
4607 | 4607 | This usually occurs when the category has been added to the page in a template.', |
4608 | 4608 | 'ajax-edit-category-error' => 'It was not possible to edit this category. |
4609 | 4609 | This usually occurs when the category has been added to the page in a template.', |
| 4610 | +'ajax-category-already-present' => 'This page already has the category you specified.', |
4610 | 4611 | ); |
Index: trunk/phase3/resources/mediawiki.page/mediawiki.page.ajaxCategories.js |
— | — | @@ -7,31 +7,37 @@ |
8 | 8 | // * Add Hooks for change, delete, add |
9 | 9 | // * Add Hooks for soft redirect |
10 | 10 | // * Handle normal redirects |
11 | | -// * api.php / api.php5 |
12 | 11 | // * Simple / MultiEditMode |
13 | 12 | |
14 | 13 | ( function( $, mw ) { |
15 | | - var catLinkWrapper = '<li/>' |
| 14 | + |
| 15 | +var ajaxCategories = function ( options ) { |
| 16 | + // TODO grab these out of option object. |
| 17 | + |
| 18 | + var catLinkWrapper = '<li/>'; |
16 | 19 | var $container = $( '.catlinks' ); |
17 | 20 | |
18 | 21 | var categoryLinkSelector = '#mw-normal-catlinks li a'; |
19 | 22 | var _request; |
20 | 23 | |
21 | 24 | var _catElements = {}; |
22 | | - var _otherElements = {}; |
23 | 25 | |
24 | 26 | var namespaceIds = mw.config.get( 'wgNamespaceIds' ) |
25 | 27 | var categoryNamespaceId = namespaceIds['category']; |
26 | 28 | var categoryNamespace = mw.config.get( 'wgFormattedNamespaces' )[categoryNamespaceId]; |
27 | | - var wgScriptPath = mw.config.get( 'wgScriptPath' ); |
28 | | - |
29 | | - function _fetchSuggestions ( query ) { |
30 | | - //SYNCED |
| 29 | + |
| 30 | + |
| 31 | + /** |
| 32 | + * Helper function for $.fn.suggestion |
| 33 | + * |
| 34 | + * @param string Query string. |
| 35 | + */ |
| 36 | + _fetchSuggestions = function ( query ) { |
31 | 37 | var _this = this; |
32 | 38 | // ignore bad characters, they will be stripped out |
33 | 39 | var catName = _stripIllegals( $( this ).val() ); |
34 | 40 | var request = $.ajax( { |
35 | | - url: wgScriptPath + '/api.php', |
| 41 | + url: mw.util.wikiScript( 'api' ), |
36 | 42 | data: { |
37 | 43 | 'action': 'query', |
38 | 44 | 'list': 'allpages', |
— | — | @@ -55,13 +61,19 @@ |
56 | 62 | } ); |
57 | 63 | //TODO |
58 | 64 | _request = request; |
59 | | - } |
| 65 | + }; |
60 | 66 | |
61 | | - function _stripIllegals( cat ) { |
| 67 | + _stripIllegals = function ( cat ) { |
62 | 68 | return cat.replace( /[\x00-\x1f\x3c\x3e\x5b\x5d\x7b\x7c\x7d\x7f]+/g, '' ); |
63 | | - } |
| 69 | + }; |
64 | 70 | |
65 | | - function _insertCatDOM( cat, isHidden ) { |
| 71 | + /** |
| 72 | + * Insert a newly added category into the DOM |
| 73 | + * |
| 74 | + * @param string category name. |
| 75 | + * @param boolean isHidden (unused) |
| 76 | + */ |
| 77 | + _insertCatDOM = function ( cat, isHidden ) { |
66 | 78 | // User can implicitely state a sort key. |
67 | 79 | // Remove before display |
68 | 80 | cat = cat.replace(/\|.*/, ''); |
— | — | @@ -83,9 +95,9 @@ |
84 | 96 | $container.find( '#mw-normal-catlinks ul' ).append( $catLinkWrapper ); |
85 | 97 | } |
86 | 98 | _createCatButtons( $anchor.get(0) ); |
87 | | - } |
| 99 | + }; |
88 | 100 | |
89 | | - function _makeSuggestionBox( prefill, callback, buttonVal ) { |
| 101 | + _makeSuggestionBox = function ( prefill, callback, buttonVal ) { |
90 | 102 | // Create add category prompt |
91 | 103 | var promptContainer = $( '<div class="mw-addcategory-prompt"/>' ); |
92 | 104 | var promptTextbox = $( '<input type="text" size="45" class="mw-addcategory-input"/>' ); |
— | — | @@ -114,24 +126,38 @@ |
115 | 127 | promptContainer.append( addButton ); |
116 | 128 | |
117 | 129 | return promptContainer; |
118 | | - } |
| 130 | + }; |
119 | 131 | |
120 | | - // Create a valid link to the category. |
121 | | - function _catLink ( cat ) { |
122 | | - //SYNCED |
| 132 | + /** |
| 133 | + * Build URL for passed Category |
| 134 | + * |
| 135 | + * @param string category name. |
| 136 | + * @return string Valid URL |
| 137 | + */ |
| 138 | + _catLink = function ( cat ) { |
123 | 139 | return mw.util.wikiGetlink( categoryNamespace + ':' + $.ucFirst( cat ) ); |
124 | | - } |
| 140 | + }; |
125 | 141 | |
126 | | - function _getCats() { |
| 142 | + /** |
| 143 | + * Parse the DOM $container and build a list of |
| 144 | + * present categories |
| 145 | + * |
| 146 | + * @return array Array of all categories |
| 147 | + */ |
| 148 | + _getCats = function () { |
127 | 149 | return $container.find( categoryLinkSelector ).map( function() { return $.trim( $( this ).text() ); } ); |
128 | | - } |
| 150 | + }; |
129 | 151 | |
130 | | - function _containsCat( cat ) { |
131 | | - //TODO: SYNC |
| 152 | + /** |
| 153 | + * Check whether a passed category is present in the DOM |
| 154 | + * |
| 155 | + * @return boolean True for exists |
| 156 | + */ |
| 157 | + _containsCat = function ( cat ) { |
132 | 158 | return _getCats().filter( function() { return $.ucFirst(this) == $.ucFirst(cat); } ).length !== 0; |
133 | | - } |
| 159 | + }; |
134 | 160 | |
135 | | - function _confirmEdit ( page, fn, actionSummary, doneFn ) { |
| 161 | + _confirmEdit = function ( page, fn, actionSummary, doneFn ) { |
136 | 162 | |
137 | 163 | // Produce a confirmation dialog |
138 | 164 | var dialog = $( '<div/>' ); |
— | — | @@ -185,9 +211,9 @@ |
186 | 212 | |
187 | 213 | $( '#catlinks' ).prepend( dialog ); |
188 | 214 | dialog.dialog( dialogOptions ); |
189 | | - } |
| 215 | + }; |
190 | 216 | |
191 | | - function _doEdit ( page, fn, summary, doneFn ) { |
| 217 | + _doEdit = function ( page, fn, summary, doneFn ) { |
192 | 218 | // Get an edit token for the page. |
193 | 219 | var getTokenVars = { |
194 | 220 | 'action':'query', |
— | — | @@ -198,7 +224,7 @@ |
199 | 225 | 'format':'json' |
200 | 226 | }; |
201 | 227 | |
202 | | - $.get( wgScriptPath + '/api.php', getTokenVars, |
| 228 | + $.get( mw.util.wikiScript( 'api' ), getTokenVars, |
203 | 229 | function( reply ) { |
204 | 230 | var infos = reply.query.pages; |
205 | 231 | $.each( |
— | — | @@ -222,33 +248,48 @@ |
223 | 249 | 'format':'json' |
224 | 250 | }; |
225 | 251 | |
226 | | - $.post( wgScriptPath + '/api.php', postEditVars, doneFn, 'json' ); |
| 252 | + $.post( mw.util.wikiScript( 'api' ), postEditVars, doneFn, 'json' ); |
227 | 253 | } |
228 | 254 | ); |
229 | 255 | } |
230 | 256 | , 'json' ); |
231 | | - } |
232 | | - |
233 | | - function _addProgressIndicator ( elem ) { |
| 257 | + }; |
| 258 | + |
| 259 | + /** |
| 260 | + * Append spinner wheel to element |
| 261 | + * @param DOMObject element. |
| 262 | + */ |
| 263 | + _addProgressIndicator = function ( elem ) { |
234 | 264 | var indicator = $( '<div/>' ); |
235 | 265 | |
236 | 266 | indicator.addClass( 'mw-ajax-loader' ); |
237 | 267 | |
238 | 268 | elem.append( indicator ); |
239 | | - } |
| 269 | + }; |
240 | 270 | |
241 | | - function _removeProgressIndicator ( elem ) { |
| 271 | + /** |
| 272 | + * Find and remove spinner wheel from inside element |
| 273 | + * @param DOMObject parent element. |
| 274 | + */ |
| 275 | + _removeProgressIndicator = function ( elem ) { |
242 | 276 | elem.find( '.mw-ajax-loader' ).remove(); |
243 | | - } |
| 277 | + }; |
244 | 278 | |
245 | | - function _makeCaseInsensitiv( string ) { |
| 279 | + /** |
| 280 | + * Makes regex string caseinsensitive. |
| 281 | + * Useful when 'i' flag can't be used. |
| 282 | + * Return stuff like [Ff][Oo][Oo] |
| 283 | + * @param string Regex string. |
| 284 | + * @return string Processed regex string |
| 285 | + */ |
| 286 | + _makeCaseInsensitiv = function ( string ) { |
246 | 287 | var newString = ''; |
247 | 288 | for (var i=0; i < string.length; i++) { |
248 | 289 | newString += '[' + string[i].toUpperCase() + string[i].toLowerCase() + ']'; |
249 | | - }; |
| 290 | + } |
250 | 291 | return newString; |
251 | | - } |
252 | | - function _buildRegex ( category ) { |
| 292 | + }; |
| 293 | + _buildRegex = function ( category ) { |
253 | 294 | // Build a regex that matches legal invocations of that category. |
254 | 295 | var categoryNSFragment = ''; |
255 | 296 | $.each( namespaceIds, function( name, id ) { |
— | — | @@ -269,9 +310,9 @@ |
270 | 311 | var categoryRegex = '\\[\\[(' + categoryNSFragment + '):' + titleFragment + '(\\|[^\\]]*)?\\]\\]'; |
271 | 312 | |
272 | 313 | return new RegExp( categoryRegex, 'g' ); |
273 | | - } |
| 314 | + }; |
274 | 315 | |
275 | | - function _handleEditLink ( e ) { |
| 316 | + _handleEditLink = function ( e ) { |
276 | 317 | e.preventDefault(); |
277 | 318 | var $this = $( this ); |
278 | 319 | var $link = $this.parent().find( 'a:not(.icon)' ); |
— | — | @@ -286,15 +327,15 @@ |
287 | 328 | _catElements[category].editButton.show(); |
288 | 329 | $( this ).unbind('click').click( _handleDeleteLink ); |
289 | 330 | }); |
290 | | - } |
| 331 | + }; |
291 | 332 | |
292 | | - function _handleAddLink ( e ) { |
| 333 | + _handleAddLink = function ( e ) { |
293 | 334 | e.preventDefault(); |
294 | 335 | |
295 | 336 | $container.find( '#mw-normal-catlinks>.mw-addcategory-prompt' ).toggle(); |
296 | | - } |
| 337 | + }; |
297 | 338 | |
298 | | - function _handleDeleteLink ( e ) { |
| 339 | + _handleDeleteLink = function ( e ) { |
299 | 340 | e.preventDefault(); |
300 | 341 | |
301 | 342 | var $this = $( this ); |
— | — | @@ -326,15 +367,15 @@ |
327 | 368 | $this.parent().remove(); |
328 | 369 | } |
329 | 370 | ); |
330 | | - } |
| 371 | + }; |
331 | 372 | |
332 | | - function _handleCategoryAdd ( e ) { |
| 373 | + _handleCategoryAdd = function ( e ) { |
333 | 374 | // Grab category text |
334 | 375 | var category = $( this ).parent().find( '.mw-addcategory-input' ).val(); |
335 | 376 | category = $.ucFirst( category ); |
336 | 377 | |
337 | 378 | if ( _containsCat(category) ) { |
338 | | - // TODO add info alert |
| 379 | + _showError( mw.msg( 'ajax-category-already-present' ) ); |
339 | 380 | return; |
340 | 381 | } |
341 | 382 | var appendText = "\n[[" + categoryNamespace + ":" + category + "]]\n"; |
— | — | @@ -348,9 +389,9 @@ |
349 | 390 | _insertCatDOM( category, false ); |
350 | 391 | } |
351 | 392 | ); |
352 | | - } |
| 393 | + }; |
353 | 394 | |
354 | | - function _handleCategoryEdit ( e ) { |
| 395 | + _handleCategoryEdit = function ( e ) { |
355 | 396 | e.preventDefault(); |
356 | 397 | |
357 | 398 | // Grab category text |
— | — | @@ -407,8 +448,14 @@ |
408 | 449 | $link.show().text( categoryNew ).attr( 'href', _catLink( categoryNew ) ); |
409 | 450 | } |
410 | 451 | ); |
411 | | - } |
412 | | - function _showError ( str ) { |
| 452 | + }; |
| 453 | + |
| 454 | + /** |
| 455 | + * Open a dismissable error dialog |
| 456 | + * |
| 457 | + * @param string str The error description |
| 458 | + */ |
| 459 | + _showError = function ( str ) { |
413 | 460 | var dialog = $( '<div/>' ); |
414 | 461 | dialog.text( str ); |
415 | 462 | |
— | — | @@ -425,24 +472,40 @@ |
426 | 473 | }; |
427 | 474 | |
428 | 475 | dialog.dialog( dialogOptions ); |
429 | | - } |
| 476 | + }; |
430 | 477 | |
431 | | - function _createButton ( icon, title, category, text ){ |
432 | | - var button = $( '<a>' ).addClass( category || '' ) |
| 478 | + /** |
| 479 | + * Manufacture iconed button, with or without text |
| 480 | + * |
| 481 | + * @param string icon The icon class. |
| 482 | + * @param string title Title attribute. |
| 483 | + * @param string className (optional) Additional classes to be added to the button. |
| 484 | + * @param string text (optional) Text of button. |
| 485 | + * |
| 486 | + * @return jQueryObject The button |
| 487 | + */ |
| 488 | + _createButton = function ( icon, title, className, text ){ |
| 489 | + var $button = $( '<a>' ).addClass( className || '' ) |
433 | 490 | .attr('title', title); |
434 | 491 | |
435 | 492 | if ( text ) { |
436 | | - var icon = $( '<a>' ).addClass( 'icon ' + icon ); |
437 | | - button.addClass( 'icon-parent' ).append( icon ).append( text ); |
| 493 | + var $icon = $( '<a>' ).addClass( 'icon ' + icon ); |
| 494 | + $button.addClass( 'icon-parent' ).append( $icon ).append( text ); |
438 | 495 | } else { |
439 | | - button.addClass( 'icon ' + icon ); |
| 496 | + $button.addClass( 'icon ' + icon ); |
440 | 497 | } |
441 | | - return button; |
442 | | - } |
443 | | - function _createCatButtons ( element ) { |
| 498 | + return $button; |
| 499 | + }; |
| 500 | + |
| 501 | + /** |
| 502 | + * Append edit and remove buttons to a given category link |
| 503 | + * |
| 504 | + * @param DOMElement element Anchor element, to which the buttons should be appended. |
| 505 | + */ |
| 506 | + _createCatButtons = function( element ) { |
444 | 507 | // Create remove & edit buttons |
445 | 508 | var deleteButton = _createButton('icon-close', mw.msg( 'ajax-remove-category' ) ); |
446 | | - var editButton = _createButton('icon-edit', mw.msg( 'ajax-edit-category' ) ); |
| 509 | + var editButton = _createButton('icon-edit', mw.msg( 'ajax-edit-category' ) ); |
447 | 510 | |
448 | 511 | //Not yet used |
449 | 512 | var saveButton = _createButton('icon-tick', mw.msg( 'ajax-confirm-save' ) ).hide(); |
— | — | @@ -460,8 +523,8 @@ |
461 | 524 | deleteButton: deleteButton, |
462 | 525 | editButton : editButton |
463 | 526 | }; |
464 | | - } |
465 | | - function _setup() { |
| 527 | + }; |
| 528 | + this.setup = function () { |
466 | 529 | // Could be set by gadgets like HotCat etc. |
467 | 530 | if ( mw.config.get('disableAJAXCategories') ) { |
468 | 531 | return; |
— | — | @@ -494,10 +557,8 @@ |
495 | 558 | }); |
496 | 559 | |
497 | 560 | clElement.append( promptContainer ); |
498 | | - } |
499 | | - function _teardown() { |
500 | | - |
501 | | - } |
| 561 | + }; |
| 562 | + |
502 | 563 | _tasks = { |
503 | 564 | list : [], |
504 | 565 | executed : [], |
— | — | @@ -509,7 +570,13 @@ |
510 | 571 | //run task |
511 | 572 | this.executed.push( task ); |
512 | 573 | } |
513 | | - } |
514 | | - $(document).ready( function() {_setup()}); |
| 574 | + }; |
| 575 | +}; |
| 576 | +// Now make a new version |
| 577 | +mw.ajaxCategories = new ajaxCategories(); |
515 | 578 | |
| 579 | +// Executing only on doc.ready, so that everyone |
| 580 | +// gets a chance to set mw.config.set('disableAJAXCategories') |
| 581 | +$( document ).ready( mw.ajaxCategories.setup() ); |
| 582 | + |
516 | 583 | } )( jQuery, mediaWiki ); |
\ No newline at end of file |