From 63601400e476c6cf43d985f3e7b9864681695ed4 Mon Sep 17 00:00:00 2001 From: Pierre Schmitz Date: Fri, 18 Jan 2013 16:46:04 +0100 Subject: Update to MediaWiki 1.20.2 this update includes: * adjusted Arch Linux skin * updated FluxBBAuthPlugin * patch for https://bugzilla.wikimedia.org/show_bug.cgi?id=44024 --- .../mediawiki.action/mediawiki.action.edit.js | 129 ++++++++++------- .../mediawiki.action.edit.preview.js | 135 ++++++++++++++++++ .../mediawiki.action.history.diff.css | 65 +++++++-- .../mediawiki.action/mediawiki.action.history.js | 6 +- .../mediawiki.action.view.dblClickEdit.js | 20 +-- .../mediawiki.action.view.metadata.js | 70 +++++----- .../mediawiki.action.view.rightClickEdit.js | 38 ++--- .../mediawiki.action.watch.ajax.js | 155 --------------------- 8 files changed, 344 insertions(+), 274 deletions(-) create mode 100644 resources/mediawiki.action/mediawiki.action.edit.preview.js delete mode 100644 resources/mediawiki.action/mediawiki.action.watch.ajax.js (limited to 'resources/mediawiki.action') diff --git a/resources/mediawiki.action/mediawiki.action.edit.js b/resources/mediawiki.action/mediawiki.action.edit.js index e685ca94..1c51c974 100644 --- a/resources/mediawiki.action/mediawiki.action.edit.js +++ b/resources/mediawiki.action/mediawiki.action.edit.js @@ -1,42 +1,74 @@ -( function ( $, mw ) { - var isReady, toolbar, currentFocused; +( function ( mw, $ ) { + var isReady, toolbar, currentFocused, queue, $toolbar, slice; isReady = false; + queue = []; + $toolbar = false; + slice = Array.prototype.slice; + + /** + * Internal helper that does the actual insertion + * of the button into the toolbar. + * See mw.toolbar.addButton for parameter documentation. + */ + function insertButton( b /* imageFile */, speedTip, tagOpen, tagClose, sampleText, imageId, selectText ) { + // Backwards compatibility + if ( typeof b !== 'object' ) { + b = { + imageFile: b, + speedTip: speedTip, + tagOpen: tagOpen, + tagClose: tagClose, + sampleText: sampleText, + imageId: imageId, + selectText: selectText + }; + } + var $image = $( '', { + width : 23, + height: 22, + src : b.imageFile, + alt : b.speedTip, + title : b.speedTip, + id : b.imageId || undefined, + 'class': 'mw-toolbar-editbutton' + } ).click( function () { + toolbar.insertTags( b.tagOpen, b.tagClose, b.sampleText, b.selectText ); + return false; + } ); + + $toolbar.append( $image ); + return true; + } toolbar = { - $toolbar: false, - buttons: [], /** - * If you want to add buttons, use - * mw.toolbar.addButton( imageFile, speedTip, tagOpen, tagClose, sampleText, imageId, selectText ); + * Add buttons to the toolbar. + * Takes care of race conditions and time-based dependencies + * by placing buttons in a queue if this method is called before + * the toolbar is created. + * @param {Object} button: Object with the following properties: + * - imageFile + * - speedTip + * - tagOpen + * - tagClose + * - sampleText + * - imageId + * - selectText + * For compatiblity, passing the above as separate arguments + * (in the listed order) is also supported. */ addButton: function () { if ( isReady ) { - toolbar.insertButton.apply( toolbar, arguments ); + insertButton.apply( toolbar, arguments ); } else { - toolbar.buttons.push( [].slice.call( arguments ) ); - } - }, - insertButton: function ( imageFile, speedTip, tagOpen, tagClose, sampleText, imageId, selectText ) { - var image = $('', { - width : 23, - height: 22, - src : imageFile, - alt : speedTip, - title : speedTip, - id : imageId || '', - 'class': 'mw-toolbar-editbutton' - } ).click( function () { - mw.toolbar.insertTags( tagOpen, tagClose, sampleText, selectText ); - return false; - } ); - - toolbar.$toolbar.append( image ); - return true; + // Convert arguments list to array + queue.push( slice.call( arguments ) ); + } }, /** - * apply tagOpen/tagClose to selection in textarea, + * Apply tagOpen/tagClose to selection in textarea, * use sampleText instead of selection if there is none. */ insertTags: function ( tagOpen, tagClose, sampleText, selectText ) { @@ -51,7 +83,8 @@ } }, - // For backwards compatibility + // For backwards compatibility, + // Called from EditPage.php, maybe in other places as well. init: function () {} }; @@ -59,29 +92,30 @@ window.addButton = toolbar.addButton; window.insertTags = toolbar.insertTags; - // Explose publicly + // Explose API publicly mw.toolbar = toolbar; $( document ).ready( function () { - var buttons, i, c, iframe; + var buttons, i, b, $iframe; // currentFocus is used to determine where to insert tags currentFocused = $( '#wpTextbox1' ); - // Populate the selector cache for $toolbar - toolbar.$toolbar = $( '#toolbar' ); + // Populate the selector cache for $toolbar + $toolbar = $( '#toolbar' ); // Legacy: Merge buttons from mwCustomEditButtons - buttons = [].concat( toolbar.buttons, window.mwCustomEditButtons ); + buttons = [].concat( queue, window.mwCustomEditButtons ); + // Clear queue + queue.length = 0; for ( i = 0; i < buttons.length; i++ ) { - if ( $.isArray( buttons[i] ) ) { - // Passes our button array as arguments - toolbar.insertButton.apply( toolbar, buttons[i] ); + b = buttons[i]; + if ( $.isArray( b ) ) { + // Forwarded arguments array from mw.toolbar.addButton + insertButton.apply( toolbar, b ); } else { - // Legacy mwCustomEditButtons is an object - c = buttons[i]; - toolbar.insertButton( c.imageFile, c.speedTip, c.tagOpen, - c.tagClose, c.sampleText, c.imageId, c.selectText ); + // Raw object from legacy mwCustomEditButtons + insertButton( b ); } } @@ -92,7 +126,7 @@ isReady = true; // Make sure edit summary does not exceed byte limit - $( '#wpSummary' ).byteLimit( 250 ); + $( '#wpSummary' ).byteLimit( 255 ); /** * Restore the edit box scroll state following a preview operation, @@ -120,15 +154,16 @@ // HACK: make currentFocused work with the usability iframe // With proper focus detection support (HTML 5!) this'll be much cleaner - iframe = $( '.wikiEditor-ui-text iframe' ); - if ( iframe.length > 0 ) { - $( iframe.get( 0 ).contentWindow.document ) + // TODO: Get rid of this WikiEditor code from MediaWiki core! + $iframe = $( '.wikiEditor-ui-text iframe' ); + if ( $iframe.length > 0 ) { + $( $iframe.get( 0 ).contentWindow.document ) // for IE - .add( iframe.get( 0 ).contentWindow.document.body ) + .add( $iframe.get( 0 ).contentWindow.document.body ) .focus( function () { - currentFocused = iframe; + currentFocused = $iframe; } ); } }); -}( jQuery, mediaWiki ) ); +}( mediaWiki, jQuery ) ); diff --git a/resources/mediawiki.action/mediawiki.action.edit.preview.js b/resources/mediawiki.action/mediawiki.action.edit.preview.js new file mode 100644 index 00000000..cddf6ccf --- /dev/null +++ b/resources/mediawiki.action/mediawiki.action.edit.preview.js @@ -0,0 +1,135 @@ +/** + * Live edit preview. + */ +( function ( mw, $ ) { + + /** + * @param {jQuery.Event} e + */ + function doLivePreview( e ) { + var $wikiPreview, copySelectors, removeSelectors, $copyElements, $spinner, + targetUrl, postData, $previewDataHolder; + + e.preventDefault(); + + $( mw ).trigger( 'LivePreviewPrepare' ); + + $wikiPreview = $( '#wikiPreview' ); + + // Show #wikiPreview if it's hidden to be able to scroll to it + // (if it is hidden, it's also empty, so nothing changes in the rendering) + $wikiPreview.show(); + + // Jump to where the preview will appear + $wikiPreview[0].scrollIntoView(); + + // List of selectors matching elements that we will + // update from from the ajax-loaded preview page. + copySelectors = [ + // Main + '#wikiPreview', + '#wikiDiff', + '#catlinks', + '.hiddencats', + '#p-lang', + // Editing-related + '.templatesUsed', + '.mw-summary-preview' + ]; + $copyElements = $( copySelectors.join( ',' ) ); + + // Not shown during normal preview, to be removed if present + removeSelectors = [ + '.mw-newarticletext' + ]; + + $( removeSelectors.join( ',' ) ).remove(); + + $spinner = $.createSpinner( { + size: 'large', + type: 'block' + }); + $wikiPreview.before( $spinner ); + $spinner.css( { + position: 'absolute', + marginTop: $spinner.height() + } ); + // Make sure preview area is at least as tall as 2x the height of the spinner. + // 1x because if its smaller, it will spin behind the edit toolbar. + // (this happens on the first preview when editPreview is still empty) + // 2x because the spinner has 1x margin top breathing room. + $wikiPreview.css( 'minHeight', $spinner.height() * 2 ); + + // Can't use fadeTo because it calls show(), and we might want to keep some elements hidden + // (e.g. empty #catlinks) + $copyElements.animate( { + opacity: 0.4 + }, 'fast' ); + + $previewDataHolder = $( '
' ); + targetUrl = $( '#editform' ).attr( 'action' ); + + // Gather all the data from the form + postData = $( '#editform' ).formToArray(); + postData.push( { + name: e.target.name, + value: '' + } ); + + // Load new preview data. + // TODO: This should use the action=parse API instead of loading the entire page + // Though that requires figuring out how to conver that raw data into proper HTML. + $previewDataHolder.load( targetUrl + ' ' + copySelectors.join( ',' ), postData, function () { + var i, $from; + // Copy the contents of the specified elements from the loaded page to the real page. + // Also copy their class attributes. + for ( i = 0; i < copySelectors.length; i++ ) { + $from = $previewDataHolder.find( copySelectors[i] ); + + $( copySelectors[i] ) + .empty() + .append( $from.contents() ) + .attr( 'class', $from.attr( 'class' ) ); + } + + $spinner.remove(); + $copyElements.animate( { + opacity: 1 + }, 'fast' ); + + $( mw ).trigger( 'LivePreviewDone', [copySelectors] ); + } ); + } + + $( document ).ready( function () { + // The following elements can change in a preview but are not output + // by the server when they're empty until the preview reponse. + // TODO: Make the server output these always (in a hidden state), so we don't + // have to fish and (hopefully) put them in the right place (since skins + // can change where they are output). + + if ( !document.getElementById( 'p-lang' ) && document.getElementById( 'p-tb' ) ) { + $( '#p-tb' ).after( + $( '
' ).prop( 'id', 'p-lang' ) + ); + } + + if ( !$( '.mw-summary-preview' ).length ) { + $( '.editCheckboxes' ).before( + $( '
' ).prop( 'className', 'mw-summary-preview' ) + ); + } + + if ( !document.getElementById( 'wikiDiff' ) && document.getElementById( 'wikiPreview' ) ) { + $( '#wikiPreview' ).after( + $( '
' ).prop( 'id', 'wikiDiff') + ); + } + + // Make sure diff styles are loaded + mw.loader.load( 'mediawiki.action.history.diff' ); + + $( document.body ).on( 'click', '#wpPreview, #wpDiff', doLivePreview ); + } ); + +}( mediaWiki, jQuery ) ); diff --git a/resources/mediawiki.action/mediawiki.action.history.diff.css b/resources/mediawiki.action/mediawiki.action.history.diff.css index 3907a5f4..10473be7 100644 --- a/resources/mediawiki.action/mediawiki.action.history.diff.css +++ b/resources/mediawiki.action/mediawiki.action.history.diff.css @@ -4,33 +4,57 @@ table.diff, td.diff-otitle, td.diff-ntitle { background-color: white; } + td.diff-otitle, td.diff-ntitle { text-align: center; } + td.diff-marker { text-align: right; + font-weight: bold; + font-size: 1.25em; } + td.diff-lineno { font-weight: bold; } + +td.diff-addedline, +td.diff-deletedline, +td.diff-context { + font-size: 88%; + vertical-align: top; + white-space: -moz-pre-wrap; + white-space: pre-wrap; +} + +td.diff-addedline, +td.diff-deletedline { + border-style: solid; + border-width: 1px 1px 1px 4px; + border-radius: 0.33em; +} + td.diff-addedline { - background: #cfc; - font-size: smaller; + border-color: #a3d3ff; } + td.diff-deletedline { - background: #ffa; - font-size: smaller; + border-color: #ffe49c; } + td.diff-context { - background: #eee; - font-size: smaller; + background: #f3f3f3; + color: #333333; + border-style: solid; + border-width: 1px 1px 1px 4px; + border-color: #e6e6e6; + border-radius: 0.33em; } + .diffchange { - color: red; font-weight: bold; - white-space: -moz-pre-wrap; - white-space: pre-wrap; text-decoration: none; } @@ -42,20 +66,39 @@ table.diff { /* Ensure that colums are of equal width */ table-layout: fixed; } + +td.diff-addedline .diffchange, +td.diff-deletedline .diffchange { + border-radius: 0.33em; + padding: 0.25em 0; +} + +td.diff-addedline .diffchange { + background: #d8ecff; +} + +td.diff-deletedline .diffchange { + background: #feeec8; +} + table.diff td { - padding: 0; + padding: 0.33em 0.66em; } + table.diff col.diff-marker { width: 2%; } + table.diff col.diff-content { width: 48%; } + table.diff td div { /* Force-wrap very long lines such as URLs or page-widening char strings.*/ word-wrap: break-word; /* As fallback (FF<3.5, Opera <10.5), scrollbars will be added for very wide cells - instead of text overflowing or widening */ + instead of text overflowing or widening + */ overflow: auto; } diff --git a/resources/mediawiki.action/mediawiki.action.history.js b/resources/mediawiki.action/mediawiki.action.history.js index 76b0e6cd..55f799e5 100644 --- a/resources/mediawiki.action/mediawiki.action.history.js +++ b/resources/mediawiki.action/mediawiki.action.history.js @@ -30,20 +30,20 @@ jQuery( document ).ready( function ( $ ) { return true; } - if ( $oldidRadio.prop( 'checked' ) ) { + if ( $oldidRadio.prop( 'checked' ) ) { oldLi = true; $li.addClass( 'selected' ); $oldidRadio.css( 'visibility', 'visible' ); $diffRadio.css( 'visibility', 'hidden' ); - } else if ( $diffRadio.prop( 'checked' ) ) { + } else if ( $diffRadio.prop( 'checked' ) ) { diffLi = true; $li.addClass( 'selected' ); $oldidRadio.css( 'visibility', 'hidden' ); $diffRadio.css( 'visibility', 'visible' ); // This list item has neither checked - } else { + } else { // We're below the selected radios if ( diffLi && oldLi ) { $oldidRadio.css( 'visibility', 'visible' ); diff --git a/resources/mediawiki.action/mediawiki.action.view.dblClickEdit.js b/resources/mediawiki.action/mediawiki.action.view.dblClickEdit.js index b1d906f6..7a9ceee5 100644 --- a/resources/mediawiki.action/mediawiki.action.view.dblClickEdit.js +++ b/resources/mediawiki.action/mediawiki.action.view.dblClickEdit.js @@ -1,12 +1,14 @@ /** * This module enables double-click-to-edit functionality */ -jQuery( document ).ready( function( $ ) { - var url = $( '#ca-edit a' ).attr( 'href' ); - if ( url ) { - mw.util.$content.dblclick( function( e ) { - e.preventDefault(); - window.location = url; - } ); - } -} ); +( function ( mw, $ ) { + $( function () { + var url = $( '#ca-edit a' ).attr( 'href' ); + if ( url ) { + mw.util.$content.dblclick( function ( e ) { + e.preventDefault(); + window.location = url; + } ); + } + } ); +}( mediaWiki, jQuery ) ); diff --git a/resources/mediawiki.action/mediawiki.action.view.metadata.js b/resources/mediawiki.action/mediawiki.action.view.metadata.js index b791cabd..ce3c674b 100644 --- a/resources/mediawiki.action/mediawiki.action.view.metadata.js +++ b/resources/mediawiki.action/mediawiki.action.view.metadata.js @@ -1,39 +1,43 @@ -// Exif metadata display for MediaWiki file uploads -// -// Add an expand/collapse link and collapse by default if set to -// (with JS disabled, user will see all items) -// +/** + * Exif metadata display for MediaWiki file uploads + * + * Add an expand/collapse link and collapse by default if set to + * (with JS disabled, user will see all items) + */ +( function ( mw, $ ) { + $( function () { + var $row, $col, $link, + showText = mw.msg( 'metadata-expand' ), + hideText = mw.msg( 'metadata-collapse' ), + $table = $( '#mw_metadata' ), + $tbody = $table.find( 'tbody' ); -jQuery( document ).ready( function( $ ) { - var showText = mw.msg( 'metadata-expand' ); - var hideText = mw.msg( 'metadata-collapse' ); + if ( !$tbody.length ) { + return; + } - var $table = $( '#mw_metadata' ); - var $tbody = $table.find( 'tbody' ); - if ( !$tbody.length ) { - return; - } + $row = $( '' ); + $col = $( '' ); - var $row = $( '' ); - var $col = $( '' ); + $link = $( '', { + text: showText, + href: '#' + }).click(function () { + if ( $table.hasClass( 'collapsed' ) ) { + $( this ).text( hideText ); + } else { + $( this ).text( showText ); + } + $table.toggleClass( 'expanded collapsed' ); + return false; + }); - var $link = $( '', { - 'text': showText, - 'href': '#' - }).click(function() { - if ( $table.hasClass( 'collapsed' ) ) { - $( this ).text( hideText ); - } else { - $( this ).text( showText ); - } - $table.toggleClass( 'expanded collapsed' ); - return false; - }); + $col.append( $link ); + $row.append( $col ); + $tbody.append( $row ); - $col.append( $link ); - $row.append( $col ); - $tbody.append( $row ); + // And collapse! + $table.addClass( 'collapsed' ); + } ); - // And collapse! - $table.addClass( 'collapsed' ); -} ); +}( mediaWiki, jQuery ) ); \ No newline at end of file diff --git a/resources/mediawiki.action/mediawiki.action.view.rightClickEdit.js b/resources/mediawiki.action/mediawiki.action.view.rightClickEdit.js index caf9a9f2..d02d4327 100644 --- a/resources/mediawiki.action/mediawiki.action.view.rightClickEdit.js +++ b/resources/mediawiki.action/mediawiki.action.view.rightClickEdit.js @@ -1,24 +1,30 @@ /* - * JavaScript to enable right click edit functionality + * JavaScript to enable right click edit functionality. + * When the user right-clicks in a heading, it will open the + * edit screen. */ -jQuery( function( $ ) { +jQuery( function ( $ ) { // Select all h1-h6 elements that contain editsection links - $( 'h1:has(.editsection a), ' + - 'h2:has(.editsection a), ' + - 'h3:has(.editsection a), ' + - 'h4:has(.editsection a), ' + - 'h5:has(.editsection a), ' + - 'h6:has(.editsection a)' - ).live( 'contextmenu', function( e ) { - // Get href of the [edit] link - var href = $(this).find( '.editsection a' ).attr( 'href' ); - // Check if target is the anchor link itself. If so, don't suppress the context menu; this - // way the reader can still do things like copy URL, open in new tab etc. - var $target = $( e.target ); - if ( !$target.is( 'a' ) && !$target.parent().is( '.editsection' ) ){ + // Don't use the ":has:(.editsection a)" selector because it performs very bad. + // http://jsperf.com/jq-1-7-2-vs-jq-1-8-1-performance-of-mw-has/2 + $( document ).on( 'contextmenu', 'h1, h2, h3, h4, h5, h6', function ( e ) { + var $edit, href; + + $edit = $( this ).find( '.editsection a' ); + if ( !$edit.length ) { + return; + } + + // Get href of the editsection link + href = $edit.prop( 'href' ); + + // Headings can contain rich text. + // Make sure to not block contextmenu events on (other) anchor tags + // inside the heading (e.g. to do things like copy URL, open in new tab, ..). + // e.target can be the heading, but it can also be anything inside the heading. + if ( href && e.target.nodeName.toLowerCase() !== 'a' ) { window.location = href; e.preventDefault(); - return false; } } ); } ); diff --git a/resources/mediawiki.action/mediawiki.action.watch.ajax.js b/resources/mediawiki.action/mediawiki.action.watch.ajax.js deleted file mode 100644 index f5f09f52..00000000 --- a/resources/mediawiki.action/mediawiki.action.watch.ajax.js +++ /dev/null @@ -1,155 +0,0 @@ -/** - * Animate watch/unwatch links to use asynchronous API requests to - * watch pages, rather than navigating to a different URI. - */ -( function ( $, mw, undefined ) { - -/** - * The name of the page to watch or unwatch. - */ -var title = mw.config.get( 'wgRelevantPageName', mw.config.get( 'wgPageName' ) ); - -/** - * Update the link text, link href attribute and (if applicable) - * "loading" class. - * - * @param $link {jQuery} Anchor tag of (un)watch link - * @param action {String} One of 'watch', 'unwatch'. - * @param state {String} [optional] 'idle' or 'loading'. Default is 'idle'. - */ -function updateWatchLink( $link, action, state ) { - // message keys 'watch', 'watching', 'unwatch' or 'unwatching'. - var msgKey = state === 'loading' ? action + 'ing' : action, - accesskeyTip = $link.attr( 'title' ).match( mw.util.tooltipAccessKeyRegexp ), - $li = $link.closest( 'li' ); - - $link - .text( mw.msg( msgKey ) ) - .attr( 'title', mw.msg( 'tooltip-ca-' + action ) + - ( accesskeyTip ? ' ' + accesskeyTip[0] : '' ) - ) - .attr( 'href', mw.util.wikiScript() + '?' + $.param({ - title: title, - action: action - }) - ); - - // Special case for vector icon - if ( $li.hasClass( 'icon' ) ) { - if ( state === 'loading' ) { - $link.addClass( 'loading' ); - } else { - $link.removeClass( 'loading' ); - } - } -} - -/** - * @todo This should be moved somewhere more accessible. - * @param url {String} - * @return {String} The extracted action, defaults to 'view'. - */ -function mwUriGetAction( url ) { - var actionPaths = mw.config.get( 'wgActionPaths' ), - key, parts, m, action; - - // @todo: Does MediaWiki give action path or query param - // precedence ? If the former, move this to the bottom - action = mw.util.getParamValue( 'action', url ); - if ( action !== null ) { - return action; - } - - for ( key in actionPaths ) { - if ( actionPaths.hasOwnProperty( key ) ) { - parts = actionPaths[key].split( '$1' ); - for ( i = 0; i < parts.length; i += 1 ) { - parts[i] = $.escapeRE( parts[i] ); - } - m = new RegExp( parts.join( '(.+)' ) ).exec( url ); - if ( m && m[1] ) { - return key; - } - - } - } - - return 'view'; -} - -$( document ).ready( function() { - var $links = $( '.mw-watchlink a, a.mw-watchlink, ' + - '#ca-watch a, #ca-unwatch a, #mw-unwatch-link1, ' + - '#mw-unwatch-link2, #mw-watch-link2, #mw-watch-link1' ); - - // Allowing people to add inline animated links is a little scary - $links = $links.filter( ':not( #bodyContent *, #content * )' ); - - $links.click( function( e ) { - var $link, api, - action = mwUriGetAction( this.href ); - - if ( action !== 'watch' && action !== 'unwatch' ) { - // Could not extract target action from link url, - // let native browsing handle it further - return true; - } - e.preventDefault(); - e.stopPropagation(); - - $link = $( this ); - - updateWatchLink( $link, action, 'loading' ); - - api = new mw.Api(); - api[action]( - title, - // Success - function( watchResponse ) { - var otherAction = action === 'watch' ? 'unwatch' : 'watch', - $li = $link.closest( 'li' ); - - mw.util.jsMessage( watchResponse.message, 'ajaxwatch' ); - - // Set link to opposite - updateWatchLink( $link, otherAction ); - - // Most common ID style - if ( $li.prop( 'id' ) === 'ca-' + otherAction || $li.prop( 'id' ) === 'ca-' + action ) { - $li.prop( 'id', 'ca-' + otherAction ); - } - - // Bug 12395 - update the watch checkbox on edit pages when the - // page is watched or unwatched via the tab. - if ( watchResponse.watched !== undefined ) { - $( '#wpWatchthis' ).prop( 'checked', true ); - } else { - $( '#wpWatchthis' ).removeProp( 'checked' ); - } - }, - // Error - function(){ - - // Reset link to non-loading mode - updateWatchLink( $link, action ); - - // Format error message - var cleanTitle = title.replace( /_/g, ' ' ); - var link = mw.html.element( - 'a', { - 'href': mw.util.wikiGetlink( title ), - 'title': cleanTitle - }, cleanTitle - ); - var html = mw.msg( 'watcherrortext', link ); - - // Report to user about the error - mw.util.jsMessage( html, 'ajaxwatch' ); - - } - ); - }); - -}); - -})( jQuery, mediaWiki ); -- cgit v1.2.2