From 1234da5a71e4d023ef81074b9b4ade115aeda3c8 Mon Sep 17 00:00:00 2001 From: Leo Koppelkamm Date: Wed, 13 Jul 2011 22:15:11 +0000 Subject: [PATCH] Readd ajaxCategories from r58959 . This is just a preparation for my next commit, so that the file's history is preserved --- .../mediawiki.page.ajaxCategories.js | 326 ++++++++++++++++++ 1 file changed, 326 insertions(+) create mode 100644 resources/mediawiki.page/mediawiki.page.ajaxCategories.js diff --git a/resources/mediawiki.page/mediawiki.page.ajaxCategories.js b/resources/mediawiki.page/mediawiki.page.ajaxCategories.js new file mode 100644 index 0000000000..b46d8b3adf --- /dev/null +++ b/resources/mediawiki.page/mediawiki.page.ajaxCategories.js @@ -0,0 +1,326 @@ +loadGM( { + "ajax-add-category" : "[Add Category]", + "ajax-add-category-submit" : "[Add]", + "ajax-confirm-prompt" : "[Confirmation Text]", + "ajax-confirm-title" : "[Confirmation Title]", + "ajax-confirm-save" : "[Save]", + "ajax-add-category-summary" : "[Add category $1]", + "ajax-remove-category-summary" : "[Remove category $2]", + "ajax-confirm-actionsummary" : "[Summary]", + "ajax-error-title" : "Error", + "ajax-error-dismiss" : "OK", + "ajax-remove-category-error" : "[RemoveErr]" +} ); + +var ajaxCategories = { + handleAddLink : function( e ) { + e.preventDefault(); + + // Make sure the suggestion plugin is loaded. Load everything else while we're at it + mvJsLoader.doLoad( + ['$j.ui', '$j.ui.dialog', '$j.fn.suggestions'], + function() { + $j( '#mw-addcategory-prompt' ).toggle(); + + $j( '#mw-addcategory-input' ).suggestions( { + 'fetch':ajaxCategories.fetchSuggestions, + 'cancel': function() { + var req = ajaxCategories.request; + if ( req.abort ) + req.abort(); + } + } ); + + $j( '#mw-addcategory-input' ).suggestions(); + } + ); + }, + + fetchSuggestions : function( query ) { + var that = this; + var request = $j.ajax( { + url: wgScriptPath + '/api.php', + data: { + 'action': 'query', + 'list': 'allpages', + 'apnamespace': 14, + 'apprefix': $j( this ).val(), + 'format': 'json' + }, + dataType: 'json', + success: function( data ) { + // Process data.query.allpages into an array of titles + var pages = data.query.allpages; + var titleArr = []; + + $j.each( pages, function( i, page ) { + var title = page.title.split( ':', 2 )[1]; + titleArr.push( title ); + } ); + + $j( that ).suggestions( 'suggestions', titleArr ); + } + } ); + + ajaxCategories.request = request; + }, + + reloadCategoryList : function( response ) { + var holder = $j( '
' ); + + holder.load( + window.location.href + ' .catlinks', + function() { + $j( '.catlinks' ).replaceWith( holder.find( '.catlinks' ) ); + ajaxCategories.setupAJAXCategories(); + ajaxCategories.removeProgressIndicator( $j( '.catlinks' ) ); + } + ); + }, + + confirmEdit : function( page, fn, actionSummary, doneFn ) { + // Load jQuery UI + mvJsLoader.doLoad( + ['$j.ui', '$j.ui.dialog', '$j.fn.suggestions'], + function() { + // Produce a confirmation dialog + + var dialog = $j( '
' ); + + dialog.addClass( 'mw-ajax-confirm-dialog' ); + dialog.attr( 'title', gM( 'ajax-confirm-title' ) ); + + // Intro text. + var confirmIntro = $j( '

' ); + confirmIntro.text( gM( 'ajax-confirm-prompt' ) ); + dialog.append( confirmIntro ); + + // Summary of the action to be taken + var summaryHolder = $j( '

' ); + var summaryLabel = $j( '' ); + summaryLabel.text( gM( 'ajax-confirm-actionsummary' ) + " " ); + summaryHolder.text( actionSummary ); + summaryHolder.prepend( summaryLabel ); + dialog.append( summaryHolder ); + + // Reason textbox. + var reasonBox = $j( '' ); + reasonBox.addClass( 'mw-ajax-confirm-reason' ); + dialog.append( reasonBox ); + + // Submit button + var submitButton = $j( '' ); + submitButton.val( gM( 'ajax-confirm-save' ) ); + + var submitFunction = function() { + ajaxCategories.addProgressIndicator( dialog ); + ajaxCategories.doEdit( + page, + fn, + reasonBox.val(), + function() { + doneFn(); + dialog.dialog( 'close' ); + ajaxCategories.removeProgressIndicator( dialog ); + } + ); + }; + + var buttons = { }; + buttons[gM( 'ajax-confirm-save' )] = submitFunction; + var dialogOptions = { + 'AutoOpen' : true, + 'buttons' : buttons, + 'width' : 450 + }; + + $j( '#catlinks' ).prepend( dialog ); + dialog.dialog( dialogOptions ); + } + ); + }, + + doEdit : function( page, fn, summary, doneFn ) { + // Get an edit token for the page. + var getTokenVars = { + 'action':'query', + 'prop':'info|revisions', + 'intoken':'edit', + 'titles':page, + 'rvprop':'content|timestamp', + 'format':'json' + }; + + $j.get( wgScriptPath + '/api.php', getTokenVars, + function( reply ) { + var infos = reply.query.pages; + $j.each( + infos, + function( pageid, data ) { + var token = data.edittoken; + var timestamp = data.revisions[0].timestamp; + var oldText = data.revisions[0]['*']; + + var newText = fn( oldText ); + + if ( newText === false ) return; + + var postEditVars = { + 'action':'edit', + 'title':page, + 'text':newText, + 'summary':summary, + 'token':token, + 'basetimestamp':timestamp, + 'format':'json' + }; + + $j.post( wgScriptPath + '/api.php', postEditVars, doneFn, 'json' ); + } + ); + } + , 'json' ); + }, + + addProgressIndicator : function( elem ) { + var indicator = $j( '

' ); + + indicator.addClass( 'mw-ajax-loader' ); + + elem.append( indicator ); + }, + + removeProgressIndicator : function( elem ) { + elem.find( '.mw-ajax-loader' ).remove(); + }, + + handleCategoryAdd : function( e ) { + // Grab category text + var category = $j( '#mw-addcategory-input' ).val(); + var appendText = "\n[[" + wgFormattedNamespaces[14] + ":" + category + "]]\n"; + var summary = gM( 'ajax-add-category-summary', category ); + + ajaxCategories.confirmEdit( + wgPageName, + function( oldText ) { return oldText + appendText }, + summary, + ajaxCategories.reloadCategoryList + ); + }, + + handleDeleteLink : function( e ) { + e.preventDefault(); + + var category = $j( this ).parent().find( 'a' ).text(); + + // Build a regex that matches legal invocations of that category. + + // In theory I should escape the aliases, but there's no JS function for it + // Shouldn't have any real impact, can't be exploited or anything, so we'll + // leave it for now. + var categoryNSFragment = ''; + $j.each( wgNamespaceIds, function( name, id ) { + if ( id == 14 ) { + // Allow the first character to be any case + var firstChar = name.charAt( 0 ); + firstChar = '[' + firstChar.toUpperCase() + firstChar.toLowerCase() + ']'; + categoryNSFragment += '|' + firstChar + name.substr( 1 ); + } + } ); + categoryNSFragment = categoryNSFragment.substr( 1 ); // Remove leading | + + // Build the regex + var titleFragment = category; + + firstChar = category.charAt( 0 ); + firstChar = '[' + firstChar.toUpperCase() + firstChar.toLowerCase() + ']'; + titleFragment = firstChar + category.substr( 1 ); + var categoryRegex = '\\[\\[' + categoryNSFragment + ':' + titleFragment + '(\\|[^\\]]*)?\\]\\]'; + categoryRegex = new RegExp( categoryRegex, 'g' ); + + var summary = gM( 'ajax-remove-category-summary', category ); + + ajaxCategories.confirmEdit( + wgPageName, + function( oldText ) { + var newText = oldText.replace( categoryRegex, '' ); + + if ( newText == oldText ) { + var error = gM( 'ajax-remove-category-error' ); + ajaxCategories.showError( error ); + ajaxCategories.removeProgressIndicator( $j( '.mw-ajax-confirm-dialog' ) ); + $j( '.mw-ajax-confirm-dialog' ).dialog( 'close' ); + return false; + } + + return newText; + }, + summary, ajaxCategories.reloadCategoryList + ); + }, + + showError : function( str ) { + var dialog = $j( '
' ); + dialog.text( str ); + + $j( '#bodyContent' ).append( dialog ); + + var buttons = { }; + buttons[gM( 'ajax-error-dismiss' )] = function( e ) { + dialog.dialog( 'close' ); + }; + var dialogOptions = { + 'buttons' : buttons, + 'AutoOpen' : true, + 'title' : gM( 'ajax-error-title' ) + }; + + dialog.dialog( dialogOptions ); + }, + + setupAJAXCategories : function() { + // Only do it for articles. + if ( !wgIsArticle ) return; + + var clElement = $j( '.catlinks' ); + + // Unhide hidden category holders. + clElement.removeClass( 'catlinks-allhidden' ); + + var addLink = $j( '' ); + addLink.addClass( 'mw-ajax-addcategory' ); + + // Create [Add Category] link + addLink.text( gM( 'ajax-add-category' ) ); + addLink.attr( 'href', '#' ); + addLink.click( ajaxCategories.handleAddLink ); + clElement.append( addLink ); + + // Create add category prompt + var promptContainer = $j( '