Page MenuHomePhabricator

Load site js before gadgets
Closed, DeclinedPublic

Description

Now the JavaScript is being loaded:

  1. wikibits.js and some MediaWiki stuffs
  2. Gadgets defined in user preference
  3. Site Common.js etc.

But gadgets may depend on some functions defined in site js. For example, on zhwiki, anything related to character conversion would call wgUVS() but this is defined in Common.js, so in those gadgets, we have to use addOnloadHook() for a dirty workaround... Check [[w:zh:MediaWiki:Gadget-popups.js]].

Also following up bug 20720, which says site js is loaded before gadgets. But why it's changed back.


Version: unspecified
Severity: normal

Details

Reference
bz23433

Related Objects

StatusSubtypeAssignedTask
ResolvedNone
DeclinedNone

Event Timeline

bzimport raised the priority of this task from to Medium.Nov 21 2014, 11:08 PM
bzimport set Reference to bz23433.
bzimport added a subscriber: Unknown Object (MLST).

mizusumashi wrote:

I'm sorry, but I disagree with Jimmy. I think loading site common.js after gadgets is better. Loading user scripts and gadets before site common.js is best.

I want to detect witch gadgets and/or user setteings in site common.js. Jimmy's oder makes this detection impossible. On the other hand, hooking gadget's "real" code by site common.js is not so difficult even in the current order.

Gadget A:

var gadget_a_enable = true;

Gadget B:

function gadget_b_hook () {
    // whatever you want
}
if(typeof commonHook == 'undefined'){

   commonHook = new Array();

}
commonHook[commonHook.length] = gadget_b_hook;

site commn.js ([[MediaWiki:Common.js]]):

if(typeof gadget_a_enable != 'undefined' && gadget_a_enable){
    // ... if Gadget A is enable...
}else{
    // ... if Gadget A is disable ...
}
 
if(typeof commonHook != 'undefined'){
    for(var i = 0; i < commonHook.length; i++){
        commonHook[i]();
    }
}

I think, anyone can say "But, even in Jimmy's oder, detection gadgets in 'real' code of common.js is not so diffcult too":

Gadget A:

var gadget_a_enable = true;

site commn.js ([[MediaWiki:Common.js]]):

$(document).ready(function ($){
    if(typeof gadget_a_enable != 'undefined' && gadget_a_enable){
        // ... whatevet I want ...
    }
});

But I need to say, $(document).ready somtime makes waiting for long time. Of course, if you want or need to wait that the document is ready, this is a good way. But this long time lag is not fine in some case.

mdale wrote:

The way I address this in mwEmbed is through a series of bind and triggers which give you both temporal loading flexibility and fine grain extendability of components.

Bind and triggers are a pefered way for javascript to extend and interact it offers features like ( name spacing, binding undefined target names, and with utility functions like triggerQueueCallback, "blocking" triggers.
http://svn.wikimedia.org/svnroot/mediawiki/trunk/extensions/MwEmbedSupport/MwEmbedModules/MwEmbedSupport/jquery/jquery.triggerQueueCallback.js

All the code that is loaded on every page is "loader" code. These loaders define interface entry points and setup up global bindings. For example see how timedText extends the embedPlayer interface :

http://svn.wikimedia.org/svnroot/mediawiki/trunk/extensions/TimedMediaHandler/MwEmbedModules/TimedText/TimedText.loader.js

and the mwEmbed loader:

http://svn.wikimedia.org/svnroot/mediawiki/trunk/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/EmbedPlayer.loader.js

Hopefully the example is not too specific to the video player context. The basic point is we should have defined points of extending things so the order in which things are loaded does not matter as much ( as long as all the "loader / binding" code is loaded before the "page ready" or "SetupInterfaces" event is fired. And all the triggers happen after "page ready"

$(document).ready should NOT mean waiting for a long time. It is fired once the dom is "ready" not all the images in the page are loaded. A "SetupInterfaces" and "IntefacesReady" event could also be used but in practice it happens almost the same time as DOM ready ( since you want to give every loaded javascript a chance to bind to that event before you trigger it ) ... So if you don't need more complicated interface state control $(document).ready works just as well.

ResourceLoader should have provided the desired functionality. Marking as wontfix.
If you have an JS load ordering problem, please re-open and describe the problematic scenario.