Let me first say that the ResourceLoader [1] is a wonderful part of the software. Thanks goes out to everyone who contributed to this project - it's made my life much better. That being said, I don't think that I and my team have figure out how to properly take advantage of its benefits.
At Vistaprint, we are currently using the ResourceLoader to load modules, some of which contain JavaScript. The dependencies are made explicit in the registering of the ResourceLoader, and they execute in the proper order on the client side. In many of these JavaScript files we wrap our code in a jQuery .ready() callback [2]. Since these JavaScript files have dependencies on one-another (as laid out in the RL,) they need to be executed in the correct order to work properly. We're finding that when using jQuery's .ready() (or similar) function, the callbacks seem to execute in different (unexepected, browser-dependent) order. This causes errors.
Using the WikiEditor extension as a specific example: Customizing the WikiEditor-toolbar is one of the specific cases where we've encountered problems. First, the WikiEditor provides no good events to bind to once the toolbar is loaded. This is not a problem because there is a documented work-around [3]. However, our JavaScript code needs to execute in the proper order, which it is not. We have about four JavaScript files that add custom toolbars, sections, and groups.
My questions: It recently dawned on me that executing our code within a $(document).ready(); callback might not be necessary as the JavaScript for each ResourceLoader module is executed in its own callback on the client-side. This should provide the necessary scope to avoid clobbering global variables along with getting executed at the proper time. Is this a correct assumption to make? Is it a good idea to avoid binding our code to jQuery's ready event?
--Daniel (User:The Scientist)
[1] http://www.mediawiki.org/wiki/ResourceLoader [2] http://docs.jquery.com/Events/ready [3] http://www.mediawiki.org/wiki/Extension:WikiEditor/Toolbar_customization#Mod...
Hi Daniel,
I'm not very experienced with ResourceLoader, but maybe 'mw.loader.using()' [1] suits your needs. You can specify a module dependency and a callback function on the client side.
Another way to keep the right execution order may be to establish some kind of "global hook system" within your own extensions. Let's say Extension2 depends on javascript code executed by Extension1. Then trigger [2] an event using jquery
$(document).trigger( 'extension1-init', [this, param1, param2] );
In Extension1 and in your Extension2 just bind [3] to this event:
$(document).on('extension1-init', function( event, extension1, param1, param2 ){ //Extension2 code, i.e. modify extension1, param1 and param2 }
-- Robert
[1] http://www.mediawiki.org/wiki/ResourceLoader/Default_modules#mw.loader.using [2] http://api.jquery.com/trigger/ [3] http://api.jquery.com/on/
-----Ursprüngliche Nachricht----- Von: wikitech-l-bounces@lists.wikimedia.org [mailto:wikitech-l-bounces@lists.wikimedia.org] Im Auftrag von Daniel Renfro Gesendet: Mittwoch, 30. Januar 2013 17:37 An: wikitech-l@wikipedia.org Betreff: [Wikitech-l] Asynchronous JavaScript execution order questions
Let me first say that the ResourceLoader [1] is a wonderful part of the software. Thanks goes out to everyone who contributed to this project - it's made my life much better. That being said, I don't think that I and my team have figure out how to properly take advantage of its benefits.
At Vistaprint, we are currently using the ResourceLoader to load modules, some of which contain JavaScript. The dependencies are made explicit in the registering of the ResourceLoader, and they execute in the proper order on the client side. In many of these JavaScript files we wrap our code in a jQuery .ready() callback [2]. Since these JavaScript files have dependencies on one-another (as laid out in the RL,) they need to be executed in the correct order to work properly. We're finding that when using jQuery's .ready() (or similar) function, the callbacks seem to execute in different (unexepected, browser-dependent) order. This causes errors.
Using the WikiEditor extension as a specific example: Customizing the WikiEditor-toolbar is one of the specific cases where we've encountered problems. First, the WikiEditor provides no good events to bind to once the toolbar is loaded. This is not a problem because there is a documented work-around [3]. However, our JavaScript code needs to execute in the proper order, which it is not. We have about four JavaScript files that add custom toolbars, sections, and groups.
My questions: It recently dawned on me that executing our code within a $(document).ready(); callback might not be necessary as the JavaScript for each ResourceLoader module is executed in its own callback on the client-side. This should provide the necessary scope to avoid clobbering global variables along with getting executed at the proper time. Is this a correct assumption to make? Is it a good idea to avoid binding our code to jQuery's ready event?
--Daniel (User:The Scientist)
[1] http://www.mediawiki.org/wiki/ResourceLoader [2] http://docs.jquery.com/Events/ready [3] http://www.mediawiki.org/wiki/Extension:WikiEditor/Toolbar_customization#Mod...
_______________________________________________ Wikitech-l mailing list Wikitech-l@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/wikitech-l
On 01/31/2013 03:08 AM, Robert Vogel wrote:
Hi Daniel,
I'm not very experienced with ResourceLoader, but maybe 'mw.loader.using()' [1] suits your needs. You can specify a module dependency and a callback function on the client side.
using is the right solution for server scripts, or potentially for as-needed dependencies (only load if the user does XYZ). However, if the server code (core or extension) knows a module will be needed, it should use OutputPage::addModules or similar to avoid unnecessary round-drips.
Another way to keep the right execution order may be to establish some kind of "global hook system" within your own extensions. Let's say Extension2 depends on javascript code executed by Extension1. Then trigger [2] an event using jquery
This is only potentially needed if there's something unusual/non-blocking about the load, such as setTimeout (see my previous email). Otherwise, ResourceLoader dependencies (and maybe object-oriented programming to help structure) should work.
Matt Flaschen
On 01/30/2013 11:36 AM, Daniel Renfro wrote:
We're finding that when using jQuery's .ready() (or similar) function, the callbacks seem to execute in different (unexepected, browser-dependent) order. This causes errors.
jQuery will execute ready events in the order bound. See e.g. http://stackoverflow.com/questions/3934570/order-of-execution-of-jquery-docu... (the mechanism in latest jQuery is now a Promise, but it's still in order).
So if the ResourceLoader dependency chain is strictly right, it should execute in order. If not, it's a bug in either jQuery or ResourceLoader.
Using the WikiEditor extension as a specific example: Customizing the WikiEditor-toolbar is one of the specific cases where we've encountered problems. First, the WikiEditor provides no good events to bind to once the toolbar is loaded.
I just added this. The event is attached to the main textbox used by the toolbar (same as the previous custom events). So to listen, do:
$( '#wpTextbox1' ).on( 'wikiEditor-toolbar-doneInitialSections', function () {
} );
WikiEditor is using eachAsync, which uses setTimeout internally. Therefore, even if a ready event is bound afterwards, it's not enough. Hence, the new event.
My questions: It recently dawned on me that executing our code within a $(document).ready(); callback might not be necessary as the JavaScript for each ResourceLoader module is executed in its own callback on the client-side.
Only in production mode, so don't rely on it. You can do your own immediately executing anonymous function like https://www.mediawiki.org/wiki/Manual:Coding_conventions/JavaScript#Closure
Is it a good idea to avoid binding our code to jQuery's ready event?
If you're not sure if your code is running after ready, bind with $(document).ready . It will be immediately executed, so you're not losing much.
Matt Flaschen
wikitech-l@lists.wikimedia.org