Talk:ResourceLoader/Core modules

Jump to navigation Jump to search

About this board


Archive (until 2012)

Jdforrester (WMF) (talkcontribs)

Rather than @Nardog edit-warring, I'd invite them to explain and discuss why they want to re-design this page with its maintainers. :-)

Nardog (talkcontribs)

I just did, and you're the one who reverted it without explaining why.

The current TOC is highly user-hostile. There's not even a way to see the list of methods each module has.

Do you genuinely think it's superior? If so, care to explain?

Ciencia Al Poder (talkcontribs)

I actually like the display of 2 levels of headings instead of 1, to quickly jump to the relevant section. TOC is already floated to the right, so it's not very intrusive this way

Krinkle (talkcontribs)

This page does not provide a list of methods. That's what the API documentation is for.

Reply to "Heading selection"

Could we split the MediaWiki section somewhere?

Þjarkur (talkcontribs)

From the article's title it isn't obvious what information is contained here, and the functions of mw are not relevant to ResourceLoader. Wouldn't it be better to split it somewhere, maybe to Manual:JavaScript/mediawiki or Manual:mw? The information is also strangely split between this page and Manual:Interface/JavaScript (an article that could also do with a better name).

Reply to "Could we split the MediaWiki section somewhere?"

Access the API.edit.create function in MediaWiki 1.31.1

Summary by Jdforrester (WMF)

mediawiki.api.edit before 1.32.0

FlyDangerousO7 (talkcontribs)

I'm using the following mw.API call:

new mw.Api().create( 'Sandbox', { summary: 'Load sand particles.' }, 'Sand.');

I'm receiving an error: Uncaught TypeError: Cannot read property 'create' of undefined.

I believe that the edit module was a separate module pre-MediaWiki 1.32. I've been searching how to load the 'edit' module and access the create page function, but can't seem to find an example. I also tried to search for a git repository to backtrack the changes, but couldn't find a repository. The following documentation doesn't seem to support any other version of the API except for the newest MediaWiki version:!/api/mw.Api.plugin.edit

Does someone know how to use the create page function on MediaWiki 1.31.1?

Thank you,


Od1n (talkcontribs)

Try the following:

if ( mw.loader.getState( 'mediawiki.api.edit' ) !== null ) {
    mw.loader.load( 'mediawiki.api.edit' );

The test is to avoid triggering an error on MediaWiki 1.32 and following.

Od1n (talkcontribs)

A more complete snippet:

var moduleApiEdit = ( mw.loader.getState( 'mediawiki.api.edit' ) !== null )
    ? 'mediawiki.api.edit' // MediaWiki before 1.32
    : 'mediawiki.api';     // MediaWiki 1.32+

mw.loader.using( moduleApiEdit, function () {
    // your code
} ); (talkcontribs)

That worked exactly as excepted! Thank you for the help. :)

Is there any way to callback after using load?

Eduemoni (talkcontribs)

I am trying to load a js file under my wiki

mw.loader.load( '/w/index.php?title=MediaWiki:Slick.js&action=raw&ctype=text/javascript' );

It loads the Slick jquery plugin, then after loading it I would like to use it as a gadget, where a wildcard number of classes can become a caroussel, however after loading it I am unable to use it, because the module is not loaded yet

Od1n (talkcontribs)

You could try the following:

mw.loader.implement( 'HackyCustomModuleRegistration', [ '/w/index.php?title=MediaWiki:Slick.js&action=raw&ctype=text/javascript' ] );
mw.loader.using( 'HackyCustomModuleRegistration', function () {
    // ...
} );

However, the mw.loader.implement() method (code) is missing from the documentation, and is to be considered private.

Jack who built the house (talkcontribs)

Won't this work for you?

$.getScript( 'https://.../w/index.php?title=MediaWiki:Slick.js&action=raw&ctype=text/javascript' ).done( function () {
    // your code
} );
Erutuon (talkcontribs)

Or even shorter:

$.getScript( 'https://.../w/index.php?title=MediaWiki:Slick.js&action=raw&ctype=text/javascript', function () {
    // runs if loading was successful
} );

Od1n (talkcontribs)

I thought it was a better solution… but from the jQuery.getScript() documentation (emphasis mine):

« The callback is fired once the script has been loaded but not necessarily executed. »

Erutuon (talkcontribs)

So if $.getScript(url, func) doesn't necessarily run the script before calling func, is the script run before func with $.getScript(url).done(func) or with the mw.loader version? I've used the $.getScript version that I posted without considering this issue; for whatever reason it worked fine.

Od1n (talkcontribs)

Digging inside the code of module mediawiki (and mediawiki.base), I found out the "load+execute script, then callback" code is actually very simple, see:

function addScript( src, callback ) {
    var script = document.createElement( 'script' );
    script.src = src;
    script.onload = script.onerror = function () {
        if ( script.parentNode ) {
            script.parentNode.removeChild( script );
        script = null;
        if ( callback ) {
            callback = null;
    document.head.appendChild( script );

A few notes about the code:

  • The two = null are for performance, to free memory (otherwise the objects would stay in memory forever)
  • The onerror event is not for request error, but for script execution error

So, I think the best solution would be to reuse the above snippet as standalone. Lightweight, no dependency of any kind :)

Od1n (talkcontribs)

For the sake of refs'ing, this implementation has been introduced in this commit (T192623).

Reply to "Is there any way to callback after using load?"
Prtksxna (talkcontribs)

Modules such as and mediawiki.util have documentation both on this page and on jsDuck. Should we remove the one here, link to the API docs, and copy over stuff that is missing there (or these three things in some other order)?

Od1n (talkcontribs)

I was about to post the same thing, about mediawiki.api.* submodules. Documenting the individual methods (mw.Api#isCategory, etc.) here is cluttering, cumbersome, unmaintained and outdated. Whereas we could link to specific API pages (category, etc.) which is simple to do, more convenient to read on jsDuck, and always up-to-date. Ping Krinkle (by the way, I've done a handful of edits on this page today).

Krinkle (talkcontribs)

Yeah, any outdated or duplicated documentation here is fine to remove. I've been doing that for years, but it's a slow process.

If you find any method/class documentation or usage examples that missing from, they should be added there before removing here.

If you find any migration instructions on this page that are missing from RL/MGU, they should be added there before removing here.

Reply to "Duplicating documentation"
Erutuon (talkcontribs)

I tested this code on Wiktionary and it doesn't work.

Legoktm (talkcontribs)

Can you be more specific about what you tried and what isn't working? I just tested it and it works for me.

Erutuon (talkcontribs)

I copied the code from the above link verbatim into the Wiktionary user script sandbox, and called mw.notify on the return value. Error in the console: Uncaught TypeError: api.parse is not a function.

קיפודנחש (talkcontribs)

note that even though the code says

new mw.Api();

it's not enough to load module mediawiki.api: you need to load mediawiki.api.parse, like so:

1 mw.loader.using( 'mediawiki.api.parse' )
2 .done( function() {
3     new mw.Api().parse( {
4         // like the example.
5     });
6 }); // using..done

note that loading this module, will automatically load its dependencies i.e. mediawiki.api, so you don't have to load it explicitly, though it won't harm anything to do so anyway.


Erutuon (talkcontribs)

Thanks! That solved the problem. I'm puzzled, because I had loaded mw.api, but the function parse was still not present in the mw.Api object...

קיפודנחש (talkcontribs)

mediawiki.api has several such sub-modules, e.g., edit, watch, options, and some more (and prolly more to come).

each brings some specific set of functions, to make the interaction with specific area of the api more convenient to use.

to use them, you need to load the one you need specifically. loading any of them pulls mediawiki.api with it.


Collapse and Expand buttons do not show in mw-collapsible

Ken Roy (talkcontribs)

I am testing an upgrade of MW from 1.16.5 to 1.23.10. Previously we used ToggleDisplay2 to Collapse or Expand text sections on a page. I am trying to use the jQuery:makeCollapsible replacement, but I am not getting the [Collapse] and [Expand] button links.

What am I doing wrong? Do I need to add anything the MediaWiki:common.js? or to LocalSettings.php for the jQuery:makeCollapsible to work?

Ken Roy (talkcontribs)

This appears to be an issue in the Wikitext/Preview tab only, so I have disabled the WikiEditor preview.

Reply to "Collapse and Expand buttons do not show in mw-collapsible"
Danmichaelo (talkcontribs)

Should oojs be included in the list, or is it non-default?

Legoktm (talkcontribs)

Yes, it should be included in the list, it has been included in MediaWiki core since 1.23.

Mattflaschen-WMF (talkcontribs)


Reply to "oojs" (talkcontribs)

Can anyone explain why this is a constructor? As far as I understand, it's just a convenient wrapper for $.ajax, which isn't a constructor.

Also, what is the correct way to use this when there's multiple requests? Do I have to make a variable for each request (lest jshint whine at me for using new for "side effects"), or can I just use the one? Eg:

var api = new mw.Api();

(which seems to work fine, by the way)

Mattflaschen (talkcontribs)

The class is a wrapper around $.ajax. However, one of the pieces of functionality it adds is being able to store options that apply to all requests using the object (unless overridden by the individual request). See!/api/mw.Api . Your example above is not using new for side effects. In fact, the constructor really doesn't have side effects. It creates a mw.Api object, but to use that object for a network request, you need to call further methods (which the example above does).

This post was posted by Mattflaschen, but signed as Superm401. (talkcontribs)

Alright, that seems useful in some cases. Thanks.

Reply to "mw.Api"

Can't tell what is a module name and what not

TMg (talkcontribs)

From this documentation I can't tell if I should write

  • mw.loader.using('mediawiki.user.options', fn),
  • mw.loader.using('mediaWiki.user.options', fn),
  • mw.loader.using('mw.user.options', fn),
  • mw.loader.using('user.options', fn), maybe
  • mw.loader.using('mediawiki.user', fn) or possibly
  • mw.loader.using('options', fn) (I'm pretty sure I saw this somewhere).

In short, the list is a mess. I can't tell the difference between module names and function names that are part of a module. Or is this the same? Can I use 'mediawiki.util.addCSS' as a module name even if it is a function? I can't tell. My proposed solution is to mark function calls with mediaWiki.a.b() and module names with 'mediawiki.a.b' (without the color, of course).

Also from what I know mw is a shortcut for mediaWiki and shouldn't be used in this list except for a single hint in the introduction. Or the other way around. But don't mix it, please.

Also I'm confused because it seems many of these mw.loader.using() calls are pointless. Things like mw.user.options.get() or mw.config.get() work anyway, everywhere. Under what circumstances do they not work? How to replicate these circumstances?

Mattflaschen (talkcontribs)

Bottom line, if it's a level three heading, it's a module. In the TOC, that's every heading like "d.dd some.module" (example: "1.4 mediawiki.api"). The number (1.4) is generated by the TOC, and doesn't matter except to tell you the heading depth. In the wikitext source, these have three equals signs on each side.

user.options is a little bit of an odd man odd in terms of the naming convention. However, you can see there is such a heading (currently "1.2 user.options"), and "user.options" is the module.

You can only use using with a module name, so you can not do things like using('mediawiki.util.addCSS'). Also, 'user.options' only works everywhere because something else on the page is depending on it. You get lucky like this sometimes. However, I try to explicitly depend on everything I need except two modules, 'mediawiki' and 'jquery'. Those two are always present.

The module names do look as you proposed in the TOC (except for quotes). I'm fine with adding () to the method headings. However, I don't want to invest too much work into this, since the goal is to replace it with auto-generated documentation relatively soon.

This post was posted by Mattflaschen, but signed as Superm401.

TMg (talkcontribs)

It would be very helpful to make the headings something like "Module <code>"mediawiki.api"</code>" to make things clear. Currently I can't tell the difference between the heading levels. They all look the same except for a slightly different font size. Even worse, things like "mediaWiki.config" are neither a module nor a function. "mediaWiki.config()" would be wrong. Please remove such stuff if it's neither an usable function name nor an usable module name. It doesn't add anything. It's just confusing. Also an overview of the dependencies would be helpful.

I'm not a friend of the resource loader stuff. It makes things so insanely complicated without adding much use. (It worked for years. Why change it? Do our Internet connections get slower?) Sometimes I consider the resource loader "broken by design". If no average user is able to write valid user scripts any more something must be broken.

Mattflaschen (talkcontribs)

That heading would break existing links, but you could do it if you add {{anchor}} with the old values. You kind of have a point about mediaWiki.config, but it is an object and needs to be documented somewhere.

The dependencies are in Resources.php, but generally you don't need to worry about that. You just depend on what you need. If you need to add stuff to the watchlist, you depend on You don't need to worry about what it depends on.

I think the ResourceLoader is quite useful. There are two big reasons:

  • It handles minification and concatenation quite well, and some MediaWiki message (for i18n) cases (I am working on improving this).
  • It handles dependencies properly, and if you're writing an extension, or in MW core, the dependency interface is nice (you just specify an array of dependencies in a module definition). It is currently a bit of a pain for user scripts, though you can still pass an array of dependencies to using if there's more than one you need at the same time. Improving the user script and gadget experience is an important goal.

Since the good ol' days, MW has added a lot of useful scripts with various dependency chains. Further, other major sites have gotten faster through techniques like minification, and we need to do the same. RL also has other useful side features like flipping CSS automatically for right-to-left languages.

This post was posted by Mattflaschen, but signed as Superm401.

TMg (talkcontribs)

Thank you very much for the nice answer. After fighting every possible problem while maintaining my user script (which is also used by many other users) I think I understand most parts of that crazy nesting hell. (Except for the ready() stuff. I would really like to understand that.) Everything there is required for some reason: Make sure the options are loaded. Check one of the options. If it's enabled make sure an other module is loaded. Wait for it (I think that's what the ready() does but I don't understand how). Apply the button.

However, to make this usable for an average user there needs to be a simplified way to write it like this without loosing any functionality:

if (mw.user.options.get('usebetatoolbar'))
    $('#wpTextbox1').wikiEditor('addToToolbar', /* … */);
קיפודנחש (talkcontribs)

first, you don't import "user.options", but rather the module: "mediawiki.user", which, in turn, makes the *object* mw.user.options available to you.

second, because these resources are pulled from the web, it is usually not such a great idea to serialize it the way you suggest. in principle it *is* possible to do it the way you outlined (one would have to write a "synchronized import" function, which is totally possible), but it would mean that the browser will "freeze", and do nothing else (it might be responsive to user input, but it won't be able to execute any other JS stuff) while the browser goes and pulls the module off the server, however long that takes.

in the current mode (using the "using" method), the browser sends a request to the server to pull the module "mediawiki.user", and while the server prepares and sends the module, the browser is free to go and play elsewhere and do other stuff, such as figuring out what *else* is needed, and ask for it. once the module arrives from the server, the "using" triggers execution of the inside function.

think about it like this: javascript is single-threaded. the "using" and similar methods (such as "ready") allow it to pretend to be multithreaded, in the sense that while waiting for something to happen, it can go and do other stuff instead of wait idly.


TMg (talkcontribs)

I'm sorry but I do not care. All I want to do is to add a damn button to a toolbar. It has to wait anyway no matter how this stuff is loaded. This was a single (!) line of code with the old toolbar. Add button. Done. The current copy and paste garbage required to do the same is simply insane. It's not my job to put code that clearly belongs to the MediaWiki core into my user script.

Reply to "Can't tell what is a module name and what not"