ResourceLoader/Migration guide (users)

From MediaWiki.org
< ResourceLoader(Redirected from RL/MGU)
Jump to: navigation, search
shortcut: RL/MGU

Through time the core JavaScript functions and HTML output improves functionality, introduces new methods, deprecates or changes in other aspects. This document intends to highlight the most common problems that need to be fixed.

MediaWiki 1.20[edit | edit source]

New diff styles[edit | edit source]

This version introduces a new diff view, greatly improved in clarity especially for whitespace and other small changes and colour-blind users. If your wiki has custom CSS for the diffs, they may be in conflict with the new style (as happened on ptwiki and srwiki). You are recommended to remove the old code (or if still wanted by some users, update it to work with the new layout and create a gadget for it so that users can opt-in to it still).

MediaWiki 1.19[edit | edit source]

wikitable style updates[edit | edit source]

As of MediaWiki 1.19 a few bugs have been fixed with the wikitable class (see bugzilla:30485 and bugzilla:33434 for more info). If your wiki maintains a legacy synonym of this class (e.g. "prettytable") you need to update its CSS to match the current style in core.

The current style as of 1.19 can be found here. Copy those rules to your wiki and replace "wikitable" with the synonym (example for nl.wikipedia).

If your wiki doesn't keep something like this, then no update is necessary and everything should take care of itself.

File page checkered background[edit | edit source]

Checkered background

The checkered background often applied to transparent File-namespace pages is now part of the software. Local rules like the following should be removed (because they are redundant, and actually cause an additional unnecessary HTTP request for the image)

/* Put a checker background at the image description page.
   Only visible if the image has transparent background.
*/
#file img {
  background: url("//upload.wikimedia.org/wikipedia/commons/5/5d/Checker-16x16.png") repeat;
}

MediaWiki 1.18[edit | edit source]

Protocol-relative urls[edit | edit source]

This change only applies to Wikimedia Foundation wikis.

As of MediaWiki 1.18 there is native support for protocol-relative wiki installations. This means that a wiki could be accessible from both http://example.org and https://example.org. To make it possible to a share a common cache for as much as possible, we make use of a technique called protocol-relative urls. Although browsers have supports this for ages, script writers generally aren't very familiar with it until fairly recently. Briefly explained, this means that <img src="//meta.wikimedia.org" /> when on "https://example.org" will be automatically expanded by the browser to https://meta.wikimedia.org. This is much like (for example) <img src="foobar.jpg" /> or <img src="/w/foobar.jpg" />, which are are automatically expanded to "http://mediawiki.org/w/foobar.jpg".

Depending on how the scripts were written this may require some changes to be made to your scripts. If you use the following method to detect whether the script is executed on a certain wiki, this change will break your script:

if ( wgServer === 'http://www.mediawiki.org' ) {
 // Doesn't work anymore!
}

because wgServer is now "//www.mediawiki.org". Since a few years there has been another config variable, called "wgDBname". You should use that instead to differentiate wikis, like:

if ( mw.config.get( 'wgDBname' ) === 'enwiki' ) {
 // English Wikipedia!
}

If you must use wgServer, then simply change it to :

if ( mw.config.get( 'wgServer' ) === '//en.wikipedia.org' ) {
 // English Wikipedia!
}

"Enabled by default" (Gadgets extension)[edit | edit source]

As of the version of the Gadgets extension at the MW 1.18 branchpoint, there is a new feature that allows a gadget to be opt-out instead of opt-in based. By setting "[default]" (or adding "|default" to an existing section) the gadget will be enabled by default for everybody, unless a user has specifically opted out by unticking the checkbox on Special:Preferences#mw-prefsection-gadgets.

Note that this also loads it for all anonymous users. Gadgets that are only for logged-in users should be additionally restricted by, for example, requiring certain user rights.

See also Extension:Gadgets#Options.

mw.util.wikiScript[edit | edit source]

The actual paths have not changed, but getting the path to the API and index.php has become a lot easier. This also makes the code more portable as it has no hardcoded wiki-specific paths.

This is how it used to go in many gadgets.

var foo = 'bar';
var apiUrl = '//www.mediawiki.org/w/api.php?foo=' + encodeURIComponent( foo ) + '&baz=quux';
 
$.ajax( { url: apiUrl, ... } );

Instead use something like one of the following:

// Behold, mw.util.wikiScript!
var foo = 'bar';
var apiUrl = mw.util.wikiScript( 'api' ) + '?foo=' + encodeURIComponent( foo ) + '&baz=quux';
 
$.ajax( {
  url: apiUrl,
  ...
} );

Uou may also want to use $.param to automatically escape and create things properly in the query string:

// $.param is also awesome. No need for encodeURIComponent that way :)
var foo = 'bar';
var apiUrl = mw.util.wikiScript( 'api' ) + '?' + $.param({
    foo: foo,
    baz: 'quux'
});
 
$.ajax( {
  url: apiUrl,
  ...
} );

You can even use the data option of $.ajax, that abstracts away the need to deal with the query string entirely:

// No longer needed to inject the '?' or '&' in the url
$.ajax({
  url: mw.util.wikiScript( 'api' ),
  data: {
    foo: 'bar',
    baz: 'quux'
  }, ...
});

MediaWiki 1.17[edit | edit source]

  • $j has been deprecated. Use jQuery or $ instead.

jQuery[edit | edit source]

See also jQuery

As of 1.17 the jQuery library is loaded by default on all MediaWiki pages. Each MediaWiki release will keep it up to date with the latest version of jQuery. If you used to load jQuery from within your script, (e.g. from ajax.googleapis.com), make sure you remove that. If you load jQuery more than once on a page, it overwrites the earlier version. Other scripts break because they may not work with an older version of jQuery.

Also, by overwriting the jQuery object, any plugins that were bound to that object are also lost.

Tabs (vector)[edit | edit source]

In 1.17 the HTML construction for the navigation tabs has changed from <li><a><span /></a></li> to <li><span><a /></span></li>. The most common situation in which this causes problems is where scripts assume the presence of the span element when, for example, customizing the tab for "Main Page". Before 1.17 this usually meant that wikis had a different implementation for Monobook and one for Vector (or only one for each and the other was distorted).

Please use MediaWiki:mainpage-nstab or refer to Snippets/Main Page tab for a script that will work in both Vector and Monobook for 1.17.

Adding portlet links[edit | edit source]

The legacy function addPortletLink has been rewritten in the mediaWiki JS Utility library as mw.util.addPortletLink. The syntax and argument order is fully backwards compatible. The differences

  • Support for all core skins now
  • Support for simple id-selector as 'nextNode' (see documentation for details).

Some wikis may have re-defined / overwritten the addPortlinkLink function to support a few extra skins. This is no longer needed. The function definition should be removed and calls adjusted to mw.util.addPortletLink.

The legacy version of addPortlinkLink has been preserved as-is in case some edge cases would behave differently (for that reason the addPortlinkLink does not redirect to mw.util.addPortlinkLink)

Client testing[edit | edit source]

Checking which browser, platform, layout engine etc. has should now be done with jQuery.client.

  • is_safari, is_chrome etc. are deprecated
  • No need to navigator.userAgent.indexOf("MSIE 6")==-1 etc.

mw.loader[edit | edit source]

If you need certain scripts like jQuery UI's dialog or datepicker, instead of doing something like:

importStylesheetURI( mw.config.get( 'wgExtensionAssetsPath' ) + '/UsabilityInitiative/css/vector/jquery-ui-1.7.2.css' );
 
$.getScript( mw.config.get( 'wgExtensionAssetsPath' ) + '/UsabilityInitiative/js/js2stopgap/jui.combined.min.js', function () {
  MyTool.init();
} );

Instead use this:

mw.loader.using( ['jquery.ui.dialog', 'jquery.ui.datepicker'], MyTool.init );

Or if you need to delay initialization until document.ready:

mw.loader.using( ['jquery.ui.dialog', 'jquery.ui.datepicker'], function () {
  $(document).ready( MyTool.init );
});

Migrating user scripts[edit | edit source]

There are a few old wikibits functions that don't have a simple drop-in replacement yet (such as importScript()). importScriptURI does have a simple successor: mw.loader.load. Recommendation: Keep using importScript the way you do, the way you know they work. They won't go away anytime soon, certainly not before there is a good replacement.

One should only use mw.loader.using for demonstration purposes or when writing site scripts/user scripts (which don't have a module registry for dependencies). In most cases, when dealing with ResourceLoader modules, there is a module registry which lists the scripts, styles, dependencies etc. that should be loaded. That way ResourceLoader knows about the modules contents ahead of time and can do all kinds of optimizations. For gadgets this registry is MediaWiki:Gadgets-definition.

Dependencies[edit | edit source]

When a script depends on another module, such as jquery.ui.dialog or mediawiki.util, you will need to declare this as a "dependency". This is because modules are loaded on-demand and asynchronously (in consecutive order: all at the same time), so a script needs to make sure a module has been loaded before it can use its methods. Native modules, like gadgets, have a registry to declare these dependencies, but user scripts do not. You will need to load those modules using mw.loader.using()

Note that this has been that way since day one that MediaWiki 1.17 was deployed. The only reason scripts appeared to work without declaring dependencies was that until now, it was more likely that – before your module loads –, another module has loaded which has the same dependencies as your module.

With MediaWiki 1.19, modules and scripts are loaded in a more efficient way, therefore it is important to declare your dependencies so that ResourceLoader will make sure to load those first. Otherwise, your script will fail because any of the 100+ modules you might refer to in your code may not be loaded yet, or are never loaded at all.

Two base modules are always loaded and need not be declared. These are mediawiki and jquery.

In practice[edit | edit source]

Use mw.loader.using() to declare any modules that you need before executing the contents of "function". You can pass multiple modules as an array of strings.

mw.loader.using( ['mediawiki.util', 'jquery.ui.dialog', 'jquery.cookie'], function () {
 
    /* some other script that uses $.cookie */
 
    /* some other script that uses mw.util and $foo.dialog() */
 
} );

wg* Variables[edit | edit source]

As of MediaWiki 1.17, the global config variables are deprecated. Rationale to clear the global namespace, working towards a reality where most of the core libraries will be object oriented as part of the mediaWiki object. Configuration is managed through an instance of mw.Map in mw.config. It is also supporting the behavior of more script executing in their own local/private scope as supposed to the global scope.

Legacy globals will be kept for backwards compatibly, but people should start migrating so that they may removed in a future version of MediaWiki (Bug 33837).

if ( mw.config.exists( 'wgGlobalGroups' ) {
  // do stuff
}
 
if ( mw.config.get( 'wgPageName' ) == 'ResourceLoader' ) {
  // do stuff
}

More info: ResourceLoader/Default modules#mediaWiki.config

Ready, onload, hook[edit | edit source]

Check JavaScript deprecation overview for "addOnloadHook". Use jQuery(document).ready( function ); instead. Or $( fn ); for short.

New CSS declarations in core[edit | edit source]

Headings overflow hidden[edit | edit source]

overflow:hidden for any of h1, h2, h3, h4, h5 and/or h6 can be safely removed from stylesheets as this is now part of the core.

Italic redirects[edit | edit source]

Links to redirects appear italicized on Special:AllPages, Special:PrefixIndex, Special:Watchlist/edit and in category listings

.allpagesredirect,
.redirect-in-category,
.watchlistredir {
 font-style: italic;

Source code

wpSummary[edit | edit source]

Per bugzilla:20276, input#wpSummary's width is now set in Vector as well (instead of just Monobook).

UsabilityInitiative no more[edit | edit source]

As of 1.17 the functionality developed by the UsabilityInitiative has been extracted to stand-alone extensions. Buttons like "#pt-optin-try" no longer exist. You can enable/disable these functions like other extensions via Special:Preferences.

Scripts and styles doing things like "HideUsabilityOptIn":

#pt-optin-try {
  display: none !important;
}

Should therefore be deleted entirely as the button no longer exists.

Preformatted JS/CSS pages[edit | edit source]

It's no longer useful to wrap these pages in /* <pre> */ or // <source lang="javascript"> etc. In newer versions of MediaWiki, these pages are rendered as code automatically (including syntax highlighting when available). See also bug 4801.

Table sorter[edit | edit source]

The old table sorter in wikibits.js was removed in favour of jquery.tablesorter.

Variables such as ts_alternate_row_colors, and functions like ts_parseFloat no longer exist.

MediaWiki 1.16 and before[edit | edit source]

ImportScript[edit | edit source]

The function importScript is now part of core. Wikis that have defined this function themselves can now remove that and it will automatically use the core function now. This also goes for importStylesheet, importStylesheetURI and importScriptURI.

Make sure that before removing such local function though that the function signature is compatible with the core function and that there are no additional locally implemented arguments or features that core doesn't have (or vice versa). When in doubt, either keep it untouched or replace the function body with a compatibility call to the new core functionality (thus re-routing it instead of removing it entirely).

addPortletLink[edit | edit source]

The function addPortletLink is now part of core. Many wikis and gadgets have created functions like addLink, addLiLink, addlilink etc. these should be removed as they most likely don't support different skins (ie. only Monobook, not Vector or older skins). Be sure to check the syntax as there is no way of knowing the developer of those functions have used the same argument order.

Note: Since then it has been deprecated and moved into the mediaWiki library as mw.util.addPortletLink()

appendCSS[edit | edit source]

appendCSS is now loaded on all pages by default in wikibits.js. Any definition for the function can be removed without having to change anything else.

Note: Since then it has been deprecated and moved into the mediaWiki library as mw.util.addCSS()

CSS declarations new in core[edit | edit source]

Wikitable[edit | edit source]

.wikitable is now part of core. Although wikis should check if their version is the same (ie. different background color, or perhaps a different font-size), and if the same remove it from their .css pages.

Source code

plainlinks, plainlinksneverexpand[edit | edit source]

.plainlinks is now part of core.

.plainlinksneverexpand is redundant and should be removed and/or replaced with .plainlinks

mw-plusminus[edit | edit source]

.mw-plusminus-pos, .mw-plusminus-null, .mw-plusminus-neg are now part of core as well.

Source code

External URLs[edit | edit source]

Icons for protocols like HTTP, IRC, etc. and file types like PDF are now in-core.

Source code

Tooltip and Accesskeys[edit | edit source]

Scripts like ta['pt-userpage'] = new Array('.','My user page'); are ignored. It was deprecated in 2009. The function akeytt() no longer exists. Tooltips and accesskeys are now supported from core. The most common values that wikis used with ta[] are the same that have now been integrated into the core (ie. "." for "my user page"). They can still be modified, if really needed, by sysops in MediaWiki-messages (no need for JavaScript workarounds anymore).

As of MediaWiki 1.19 the global dummy placeholder ta = new Object(); was removed from wikibits.js. Code trying to add members to it will likely emit an exception.

Good practices[edit | edit source]

Anything not related to a particular MediaWiki version that should be noted as it is often done in a way that could or must be better.

document.write()[edit | edit source]

Do not use, will cause blank pages; instead, use jQuery to modify the document (adding elements, changing things etc.) and the import functions to load external resources. (importStylesheet, importScript, importStylesheetURI, importScriptURI, mw.loader.load, $.getScript).

Event binding[edit | edit source]

Binding events and callback functions is very tricky and it is hard to implement it in good cross-browser way that supports all browsers MediaWiki supports too.

As a good practice it is recommended to use jQuery methods for event binding. See the JavaScript deprecation overview on "addHandler" for examples on more info for this.

Encoding and escaping[edit | edit source]

When working with regexes, user input and/or urls always encode and escape!

Prototyping[edit | edit source]

It is recommended not to use any kind of prototyping on native javascript constructors (ie. String.prototype.Foobar, Regex.quote, Array.prototype.inArray etc.). Instead extend the jQuery namespace:

/* Single */
$.trimLeft = function( str ) {
	return str == null ? '' : str.toString().replace( /^\s+/, '' );
};
 
/* Multiple ones */
$.extend({
	trimLeft : function( str ) {
		return str == null ? '' : str.toString().replace( /^\s+/, '' );
	},
	trimRight : function( str ) {
		return str == null ?
				'' : str.toString().replace( /\s+$/, '' );
	}
});
 
/* Usage */
// Instead of something like:
var foo =  '  hello'.trimLeft();
// You'd now have:
var foo = $.trimLeft('  hello');

Getting URL parameter values[edit | edit source]

Functions like getURLParamValue, getParamVal, getParamValue, etc. are very common across wikis. Some are better than others (i.e. what if a parameter appears twice? (it should return the last one), does it ignore anything after the #tag?). As of 1.17 mw.util.getParamValue is available everywhere and takes these factors into account. Perform a full-text all-namespace search for these function names. If they are widely used perhaps make a note about it in the local village pump. Any site-wide scripts should be updated to use the mw.util function. If there are any serious problems with the local implementation (like not escaping the value for regex), it may be wise to redirect the function:

function getURLParamValue( p, url) {
 return mw.util.getParamValue( p, url);
}

Avoid use of !important[edit | edit source]

CSS stands for Cascading Style Sheets. Cascading means what comes later overwrites what came earlier. In most cases there is no need to use !important. See the following example:

.my-element { color: blue; }
.my-element { color: green; }

Text inside <strong class="my-element"> will now be green.

Keep gadgets central[edit | edit source]

Gadgets that are highly used across wiki (like Gadget-LiveClock.js) should be kept central (ie. Meta-Wiki or MediaWiki.org). The following is a list of gadgets that are centrally stored and

  • made compatible with 1.17
  • work in monobook and vector
  • wiki independent (ie. can be loaded on Commons, Wikipedia, Wiktionary or John Doe's Wiki without problems)

Sysops: To update a gadget on your wiki:

  • Check MediaWiki:Gadgets-definition on your wiki and find the gadget in question.
  • The part after the pipe (|) is the scriptname (eg. "UTCLiveClock.js").
  • Go to MediaWiki:Gadget-<scriptname> (eg. MediaWiki:Gadget-UTCLiveClock.js)
  • Remove everything and replace with the code in they grey area below the scriptname in the list. For an example on how this is done, check out LiveClock on Simple Wikipedia.

Gadgets[edit | edit source]

  • UTCLiveClock
    mw.loader.load('//www.mediawiki.org/w/index.php?title=MediaWiki:Gadget-UTCLiveClock.js&action=raw&ctype=text/javascript');
  • contribsrange
    mw.loader.load('//www.mediawiki.org/w/index.php?title=MediaWiki:Gadget-contribsrange.js&action=raw&ctype=text/javascript');
  • modrollback
    mw.loader.load('//www.mediawiki.org/w/index.php?title=MediaWiki:Gadget-modrollback.js&action=raw&ctype=text/javascript');
  • QPreview
    mw.loader.load('//commons.wikimedia.org/w/index.php?title=MediaWiki:Gadget-QPreview.js&action=raw&ctype=text/javascript');
  • ShortDiff
    mw.loader.load('//meta.wikimedia.org/w/index.php?title=MediaWiki:Gadget-ShortDiff.js&action=raw&ctype=text/javascript');
  • lastdiff Check Snippets/Last revision action
  • HotCat
/**
 * This imports the latest version of HotCat from Commons.
 * HotCat is a gadget to make changes to categories much easier.
 * Full documentation can be found at [[commons:Help:Gadget-HotCat]]
 */
mw.loader.load('//commons.wikimedia.org/w/index.php?title=MediaWiki:Gadget-HotCat.js&action=raw&ctype=text/javascript');
  • WikiMiniAtlas
/**
 * WikiMiniAtlas is a popup click and drag world map.
 * See [[meta:WikiMiniAtlas]] for more information.
 * Maintainers: [[w:User:Dschwen]]
 */
mw.loader.load('//meta.wikimedia.org/w/index.php?title=MediaWiki:Wikiminiatlas.js&action=raw&ctype=text/javascript');
  • Navigation Popups (MediaWiki:Gadget-popups.js and MediaWiki:Gadget-popups.css respectively)
mw.loader.load('//en.wikipedia.org/w/index.php?title=MediaWiki:Gadget-popups.js&action=raw&ctype=text/javascript');
@import url('//en.wikipedia.org/w/index.php?title=MediaWiki:Gadget-navpop.css&action=raw&ctype=text/css');

jQuery optimization[edit | edit source]

Use API instead of index.php[edit | edit source]

XML retrieved by invoking GET and POST methods on index.php is incompatible with HTML 5, which is the default as of 1.16 (and WMF sites since 17th of September, 2012). You should update code to use api.php, JSON format and jQuery.ajax immediately.

A temporary fix for problems with DOM parsing of XML retrieved via AJAX: For example the method getElementById("foobar") on a XML object from Mozilla's DOMParser stopped to work as before. Replacing the getElementById with $('#foobar', client.responseText).get(0) might work without many other changes to your code. Updating your script to the above mentioned methods is strongly recommended, however.

Conventions[edit | edit source]

See also[edit | edit source]

ResourceLoader
Documentation Features · Vocabulary · Migration guide (users) · Migration guide (developers) · Developing with ResourceLoader · Default modules · Mobile support
Project information Status updates · Version 1 Design Specification (tasks) · Version 2 Design Specification (tasks / tests) · Requirements
Other JavaScript Deprecations