*
* @private
* @param {string} src URL to script, will be used as the src attribute in the script tag
- * @param {Function} [callback] Callback which will be run when the script is done
+ * @return {jQuery.Promise}
*/
- function addScript( src, callback ) {
- $.ajax( {
+ function addScript( src ) {
+ return $.ajax( {
url: src,
dataType: 'script',
// Force jQuery behaviour to be for crossDomain. Otherwise jQuery would use
// text, so we'd need to $.globalEval, which then messes up line numbers.
crossDomain: true,
cache: true
- } ).always( callback );
+ } );
}
/**
return;
}
- addScript( arr[ i ], function () {
+ addScript( arr[ i ] ).always( function () {
nestedAddScript( arr, callback, i + 1 );
} );
};
}
}
- // subscribe to error streams
+ // Subscribe to error streams
mw.trackSubscribe( 'resourceloader.exception', log );
mw.trackSubscribe( 'resourceloader.assert', log );
+ /**
+ * Fired when all modules associated with the page have finished loading.
+ *
+ * @event resourceloader_loadEnd
+ * @member mw.hook
+ */
+ $( function () {
+ var loading = $.grep( mw.loader.getModuleNames(), function ( module ) {
+ return mw.loader.getState( module ) === 'loading';
+ } );
+ // In order to use jQuery.when (which stops early if one of the promises got rejected)
+ // cast any loading failures into successes. We only need a callback, not the module.
+ loading = $.map( loading, function ( module ) {
+ return mw.loader.using( module ).then( null, function () {
+ return $.Deferred().resolve();
+ } );
+ } );
+ $.when.apply( $, loading ).then( function () {
+ performance.mark( 'mwLoadEnd' );
+ mw.hook( 'resourceloader.loadEnd' ).fire();
+ } );
+ } );
+
// Attach to window and globally alias
window.mw = window.mediaWiki = mw;
}( jQuery ) );