More mediawiki.js cleanup
[lhc/web/wiklou.git] / resources / mediawiki / mediawiki.js
index 2a65c6c..fd3f03e 100644 (file)
@@ -2,8 +2,8 @@
  * Core MediaWiki JavaScript Library
  */
 
-// Attach to window
-window.mediaWiki = new ( function( $ ) {
+// Attach to window and globally alias
+window.mw = window.mediaWiki = new ( function( $ ) {
 
        /* Private Members */
 
@@ -21,7 +21,7 @@ window.mediaWiki = new ( function( $ ) {
         * that allow both single and multiple variables at once.
         *
         * @param global boolean Whether to store the values in the global window
-        * object or a exclusively in the object property 'values'.
+        *  object or a exclusively in the object property 'values'.
         * @return Map
         */
        function Map( global ) {
@@ -29,75 +29,81 @@ window.mediaWiki = new ( function( $ ) {
                return this;
        }
 
-       /**
-        * Get the value of one or multiple a keys.
-        *
-        * If called with no arguments, all values will be returned.
-        *
-        * @param selection mixed String key or array of keys to get values for.
-        * @param fallback mixed Value to use in case key(s) do not exist (optional).
-        * @return mixed If selection was a string returns the value or null,
-        * If selection was an array, returns an object of key/values (value is null if not found),
-        * If selection was not passed or invalid, will return the 'values' object member (be careful as
-        * objects are always passed by reference in JavaScript!).
-        * @return Map
-        */
-       Map.prototype.get = function( selection, fallback ) {
-               if ( $.isArray( selection ) ) {
-                       selection = $.makeArray( selection );
-                       var results = {};
-                       for ( var i = 0; i < selection.length; i++ ) {
-                               results[selection[i]] = this.get( selection[i], fallback );
-                       }
-                       return results;
-               } else if ( typeof selection === 'string' ) {
-                       if ( this.values[selection] === undefined ) {
-                               if ( typeof fallback !== 'undefined' ) {
-                                       return fallback;
+       Map.prototype = {
+               /**
+                * Get the value of one or multiple a keys.
+                *
+                * If called with no arguments, all values will be returned.
+                *
+                * @param selection mixed String key or array of keys to get values for.
+                * @param fallback mixed Value to use in case key(s) do not exist (optional).
+                * @return mixed If selection was a string returns the value or null,
+                *  If selection was an array, returns an object of key/values (value is null if not found),
+                *  If selection was not passed or invalid, will return the 'values' object member (be careful as
+                *  objects are always passed by reference in JavaScript!).
+                * @return Values as a string or object, null if invalid/inexistant.
+                */
+               get: function( selection, fallback ) {
+                       if ( $.isArray( selection ) ) {
+                               selection = $.makeArray( selection );
+                               var results = {};
+                               for ( var i = 0; i < selection.length; i++ ) {
+                                       results[selection[i]] = this.get( selection[i], fallback );
+                               }
+                               return results;
+                       } else if ( typeof selection === 'string' ) {
+                               if ( this.values[selection] === undefined ) {
+                                       if ( fallback !== undefined ) {
+                                               return fallback;
+                                       }
+                                       return null;
                                }
-                               return null;
+                               return this.values[selection];
                        }
-                       return this.values[selection];
-               }
-               return this.values;
-       };
+                       if ( selection === undefined ) {
+                               return this.values;
+                       } else {
+                               return null; // invalid selection key
+                       }
+               },
 
-       /**
-        * Sets one or multiple key/value pairs.
-        *
-        * @param selection mixed String key or array of keys to set values for.
-        * @param value mixed Value to set (optional, only in use when key is a string)
-        * @return bool This returns true on success, false on failure.
-        */
-       Map.prototype.set = function( selection, value ) {
-               if ( $.isPlainObject( selection ) ) {
-                       for ( var s in selection ) {
-                               this.values[s] = selection[s];
+               /**
+                * Sets one or multiple key/value pairs.
+                *
+                * @param selection mixed String key or array of keys to set values for.
+                * @param value mixed Value to set (optional, only in use when key is a string)
+                * @return bool This returns true on success, false on failure.
+                */
+               set: function( selection, value ) {
+                       if ( $.isPlainObject( selection ) ) {
+                               for ( var s in selection ) {
+                                       this.values[s] = selection[s];
+                               }
+                               return true;
+                       } else if ( typeof selection === 'string' && value !== undefined ) {
+                               this.values[selection] = value;
+                               return true;
                        }
-                       return true;
-               } else if ( typeof selection === 'string' && typeof value !== 'undefined' ) {
-                       this.values[selection] = value;
-                       return true;
-               }
-               return false;
-       };
+                       return false;
+               },
 
-       /**
-        * Checks if one or multiple keys exist.
-        *
-        * @param selection mixed String key or array of keys to check
-        * @return boolean Existence of key(s)
-        */
-       Map.prototype.exists = function( selection ) {
-               if ( typeof selection === 'object' ) {
-                       for ( var s = 0; s < selection.length; s++ ) {
-                               if ( !( selection[s] in this.values ) ) {
-                                       return false;
+               /**
+                * Checks if one or multiple keys exist.
+                *
+                * @param selection mixed String key or array of keys to check
+                * @return boolean Existence of key(s)
+                */
+               exists: function( selection ) {
+                       if ( typeof selection === 'object' ) {
+                               for ( var s = 0; s < selection.length; s++ ) {
+                                       if ( !( selection[s] in this.values ) ) {
+                                               return false;
+                                       }
                                }
+                               return true;
+                       } else {
+                               return selection in this.values;
                        }
-                       return true;
-               } else {
-                       return selection in this.values;
                }
        };
 
@@ -116,94 +122,97 @@ window.mediaWiki = new ( function( $ ) {
                this.format = 'parse';
                this.map = map;
                this.key = key;
-               this.parameters = typeof parameters === 'undefined' ? [] : $.makeArray( parameters );
+               this.parameters = parameters === undefined ? [] : $.makeArray( parameters );
                return this;
        }
 
-       /**
-        * Appends (does not replace) parameters for replacement to the .parameters property.
-        *
-        * @param parameters Array
-        * @return Message
-        */
-       Message.prototype.params = function( parameters ) {
-               for ( var i = 0; i < parameters.length; i++ ) {
-                       this.parameters.push( parameters[i] );
-               }
-               return this;
-       };
+       Message.prototype = {
+               /**
+                * Appends (does not replace) parameters for replacement to the .parameters property.
+                *
+                * @param parameters Array
+                * @return Message
+                */
+               params: function( parameters ) {
+                       for ( var i = 0; i < parameters.length; i++ ) {
+                               this.parameters.push( parameters[i] );
+                       }
+                       return this;
+               },
 
-       /**
-        * Converts message object to it's string form based on the state of format.
-        *
-        * @return string Message as a string in the current form or <key> if key does not exist.
-        */
-       Message.prototype.toString = function() {
-               if ( !this.map.exists( this.key ) ) {
-                       // Return <key> if key does not exist
-                       return '<' + this.key + '>';
-               }
-               var text = this.map.get( this.key );
-               var parameters = this.parameters;
-               text = text.replace( /\$(\d+)/g, function( string, match ) {
-                       var index = parseInt( match, 10 ) - 1;
-                       return index in parameters ? parameters[index] : '$' + match;
-               } );
-
-               if ( this.format === 'plain' ) {
-                       return text;
-               }
-               if ( this.format === 'escaped' ) {
-                       // According to Message.php this needs {{-transformation, which is
-                       // still todo
-                       return mw.html.escape( text );
-               }
+               /**
+                * Converts message object to it's string form based on the state of format.
+                *
+                * @return string Message as a string in the current form or <key> if key does not exist.
+                */
+               toString: function() {
+                       if ( !this.map.exists( this.key ) ) {
+                               // Return <key> if key does not exist
+                               return '<' + this.key + '>';
+                       }
+                       var     text = this.map.get( this.key ),
+                               parameters = this.parameters;
 
-               /* This should be fixed up when we have a parser
-               if ( this.format === 'parse' && 'language' in mediaWiki ) {
-                       text = mw.language.parse( text );
-               }
-               */
-               return text;
-       };
+                       text = text.replace( /\$(\d+)/g, function( string, match ) {
+                               var index = parseInt( match, 10 ) - 1;
+                               return index in parameters ? parameters[index] : '$' + match;
+                       } );
 
-       /**
-        * Changes format to parse and converts message to string
-        *
-        * @return {string} String form of parsed message
-        */
-       Message.prototype.parse = function() {
-               this.format = 'parse';
-               return this.toString();
-       };
+                       if ( this.format === 'plain' ) {
+                               return text;
+                       }
+                       if ( this.format === 'escaped' ) {
+                               // According to Message.php this needs {{-transformation, which is
+                               // still todo
+                               return mw.html.escape( text );
+                       }
 
-       /**
-        * Changes format to plain and converts message to string
-        *
-        * @return {string} String form of plain message
-        */
-       Message.prototype.plain = function() {
-               this.format = 'plain';
-               return this.toString();
-       };
+                       /* This should be fixed up when we have a parser
+                       if ( this.format === 'parse' && 'language' in mw ) {
+                               text = mw.language.parse( text );
+                       }
+                       */
+                       return text;
+               },
 
-       /**
-        * Changes the format to html escaped and converts message to string
-        *
-        * @return {string} String form of html escaped message
-        */
-       Message.prototype.escaped = function() {
-               this.format = 'escaped';
-               return this.toString();
-       };
+               /**
+                * Changes format to parse and converts message to string
+                *
+                * @return {string} String form of parsed message
+                */
+               parse: function() {
+                       this.format = 'parse';
+                       return this.toString();
+               },
 
-       /**
-        * Checks if message exists
-        *
-        * @return {string} String form of parsed message
-        */
-       Message.prototype.exists = function() {
-               return this.map.exists( this.key );
+               /**
+                * Changes format to plain and converts message to string
+                *
+                * @return {string} String form of plain message
+                */
+               plain: function() {
+                       this.format = 'plain';
+                       return this.toString();
+               },
+
+               /**
+                * Changes the format to html escaped and converts message to string
+                *
+                * @return {string} String form of html escaped message
+                */
+               escaped: function() {
+                       this.format = 'escaped';
+                       return this.toString();
+               },
+
+               /**
+                * Checks if message exists
+                *
+                * @return {string} String form of parsed message
+                */
+               exists: function() {
+                       return this.map.exists( this.key );
+               }
        };
 
        /* Public Members */
@@ -215,7 +224,7 @@ window.mediaWiki = new ( function( $ ) {
        this.log = function() { };
 
        /**
-        * @var constructor Make the Map-class publicly available.
+        * @var constructor Make the Map constructor publicly available.
         */
        this.Map = Map;
 
@@ -246,11 +255,12 @@ window.mediaWiki = new ( function( $ ) {
         * Gets a message object, similar to wfMessage()
         *
         * @param key string Key of message to get
-        * @param parameters mixed First argument in a list of variadic arguments,
-        * each a parameter for $N replacement in messages.
+        * @param parameter_1 mixed First argument in a list of variadic arguments,
+        *  each a parameter for $N replacement in messages.
         * @return Message
         */
        this.message = function( key, parameter_1 /* [, parameter_2] */ ) {
+               var parameters;
                // Support variadic arguments
                if ( parameter_1 !== undefined ) {
                        parameters = $.makeArray( arguments );
@@ -266,7 +276,7 @@ window.mediaWiki = new ( function( $ ) {
         *
         * @param key string Key of message to get
         * @param parameters mixed First argument in a list of variadic arguments,
-        * each a parameter for $N replacement in messages.
+        *  each a parameter for $N replacement in messages.
         * @return String.
         */
        this.msg = function( key, parameters ) {
@@ -290,28 +300,27 @@ window.mediaWiki = new ( function( $ ) {
                 * mediawiki.
                 *
                 * Format:
-                *   {
-                *     'moduleName': {
-                *       'dependencies': ['required module', 'required module', ...], (or) function() {}
-                *       'state': 'registered', 'loading', 'loaded', 'ready', or 'error'
-                *       'script': function() {},
-                *       'style': 'css code string',
-                *       'messages': { 'key': 'value' },
-                *       'version': ############## (unix timestamp)
-                *     }
-                *   }
+                *      {
+                *              'moduleName': {
+                *              'dependencies': ['required module', 'required module', ...], (or) function() {}
+                *              'state': 'registered', 'loading', 'loaded', 'ready', or 'error'
+                *              'script': function() {},
+                *              'style': 'css code string',
+                *              'messages': { 'key': 'value' },
+                *              'version': ############## (unix timestamp)
+                *      }
                 */
-               var registry = {};
-               // List of modules which will be loaded as when ready
-               var batch = [];
-               // List of modules to be loaded
-               var queue = [];
-               // List of callback functions waiting for modules to be ready to be called
-               var jobs = [];
-               // Flag inidicating that document ready has occured
-               var ready = false;
-               // Selector cache for the marker element. Use getMarker() to get/use the marker!
-               var $marker = null;
+               var     registry = {},
+                       // List of modules which will be loaded as when ready
+                       batch = [],
+                       // List of modules to be loaded
+                       queue = [],
+                       // List of callback functions waiting for modules to be ready to be called
+                       jobs = [],
+                       // Flag inidicating that document ready has occured
+                       ready = false,
+                       // Selector cache for the marker element. Use getMarker() to get/use the marker!
+                       $marker = null;
 
                /* Private Methods */
 
@@ -331,7 +340,7 @@ window.mediaWiki = new ( function( $ ) {
                }
 
                function compare( a, b ) {
-                       if ( a.length != b.length ) {
+                       if ( a.length !== b.length ) {
                                return false;
                        }
                        for ( var i = 0; i < b.length; i++ ) {
@@ -351,10 +360,10 @@ window.mediaWiki = new ( function( $ ) {
                 * Generates an ISO8601 "basic" string from a UNIX timestamp
                 */
                function formatVersionNumber( timestamp ) {
-                       function pad( a, b, c ) {
-                               return [a < 10 ? '0' + a : a, b < 10 ? '0' + b : b, c < 10 ? '0' + c : c].join( '' );
-                       }
-                       var d = new Date();
+                       var     pad = function( a, b, c ) {
+                                       return [a < 10 ? '0' + a : a, b < 10 ? '0' + b : b, c < 10 ? '0' + c : c].join( '' );
+                               },
+                               d = new Date();
                        d.setTime( timestamp * 1000 );
                        return [
                                pad( d.getUTCFullYear(), d.getUTCMonth() + 1, d.getUTCDate() ), 'T',
@@ -366,7 +375,7 @@ window.mediaWiki = new ( function( $ ) {
                 * Recursively resolves dependencies and detects circular references
                 */
                function recurse( module, resolved, unresolved ) {
-                       if ( typeof registry[module] === 'undefined' ) {
+                       if ( registry[module] === undefined ) {
                                throw new Error( 'Unknown dependency: ' + module );
                        }
                        // Resolves dynamic loader function and replaces it with its own results
@@ -430,7 +439,7 @@ window.mediaWiki = new ( function( $ ) {
                 *
                 * @param states string or array of strings of module states to filter by
                 * @param modules array list of module names to filter (optional, all modules
-                *   will be used by default)
+                *  will be used by default)
                 * @return array list of filtered module names
                 */
                function filter( states, modules ) {
@@ -440,7 +449,7 @@ window.mediaWiki = new ( function( $ ) {
                        }
                        // If called without a list of modules, build and use a list of all modules
                        var list = [], module;
-                       if ( typeof modules === 'undefined' ) {
+                       if ( modules === undefined ) {
                                modules = [];
                                for ( module in registry ) {
                                        modules[modules.length] = module;
@@ -449,9 +458,9 @@ window.mediaWiki = new ( function( $ ) {
                        // Build a list of modules which are in one of the specified states
                        for ( var s = 0; s < states.length; s++ ) {
                                for ( var m = 0; m < modules.length; m++ ) {
-                                       if ( typeof registry[modules[m]] === 'undefined' ) {
+                                       if ( registry[modules[m]] === undefined ) {
                                                // Module does not exist
-                                               if ( states[s] == 'undefined' ) {
+                                               if ( states[s] === 'undefined' ) {
                                                        // OK, undefined
                                                        list[list.length] = modules[m];
                                                }
@@ -473,8 +482,7 @@ window.mediaWiki = new ( function( $ ) {
                 * @param module string module name to execute
                 */
                function execute( module, callback ) {
-                       var _fn = 'mw.loader::execute> ';
-                       if ( typeof registry[module] === 'undefined' ) {
+                       if ( registry[module] === undefined ) {
                                throw new Error( 'Module has not been registered yet: ' + module );
                        } else if ( registry[module].state === 'registered' ) {
                                throw new Error( 'Module has not been requested from the server yet: ' + module );
@@ -484,9 +492,10 @@ window.mediaWiki = new ( function( $ ) {
                                throw new Error( 'Module has already been loaded: ' + module );
                        }
                        // Add styles
+                       var style;
                        if ( $.isPlainObject( registry[module].style ) ) {
                                for ( var media in registry[module].style ) {
-                                       var style = registry[module].style[media];
+                                       style = registry[module].style[media];
                                        if ( $.isArray( style ) ) {
                                                for ( var i = 0; i < style.length; i++ ) {
                                                        getMarker().before( mw.html.element( 'link', {
@@ -496,11 +505,10 @@ window.mediaWiki = new ( function( $ ) {
                                                        } ) );
                                                }
                                        } else if ( typeof style === 'string' ) {
-                                               getMarker().before( mw.html.element(
-                                                       'style',
-                                                       { 'type': 'text/css', 'media': media },
-                                                       new mw.html.Cdata( style )
-                                               ) );
+                                               getMarker().before( mw.html.element( 'style', {
+                                                       'type': 'text/css',
+                                                       'media': media
+                                               }, new mw.html.Cdata( style ) ) );
                                        }
                                }
                        }
@@ -510,14 +518,15 @@ window.mediaWiki = new ( function( $ ) {
                        }
                        // Execute script
                        try {
-                               var script = registry[module].script;
-                               var markModuleReady = function() {
-                                       registry[module].state = 'ready';
-                                       handlePending( module );
-                                       if ( $.isFunction( callback ) ) {
-                                               callback();
-                                       }
-                               };
+                               var     script = registry[module].script,
+                                       markModuleReady = function() {
+                                               registry[module].state = 'ready';
+                                               handlePending( module );
+                                               if ( $.isFunction( callback ) ) {
+                                                       callback();
+                                               }
+                                       };
+
                                if ( $.isArray( script ) ) {
                                        var done = 0;
                                        if ( script.length === 0 ) {
@@ -527,7 +536,7 @@ window.mediaWiki = new ( function( $ ) {
                                        for ( var i = 0; i < script.length; i++ ) {
                                                registry[module].state = 'loading';
                                                addScript( script[i], function() {
-                                                       if ( ++done == script.length ) {
+                                                       if ( ++done === script.length ) {
                                                                markModuleReady();
                                                        }
                                                } );
@@ -540,7 +549,7 @@ window.mediaWiki = new ( function( $ ) {
                                // This needs to NOT use mw.log because these errors are common in production mode
                                // and not in debug mode, such as when a symbol that should be global isn't exported
                                if ( window.console && typeof window.console.log === 'function' ) {
-                                       console.log( _fn + 'Exception thrown by ' + module + ': ' + e.message );
+                                       console.log( 'mw.loader::execute> Exception thrown by ' + module + ': ' + e.message );
                                }
                                registry[module].state = 'error';
                                throw e;
@@ -569,7 +578,7 @@ window.mediaWiki = new ( function( $ ) {
                                }
                                // Execute modules who's dependencies have just been met
                                for ( var r in registry ) {
-                                       if ( registry[r].state == 'loaded' ) {
+                                       if ( registry[r].state === 'loaded' ) {
                                                if ( compare(
                                                        filter( ['ready'], registry[r].dependencies ),
                                                        registry[r].dependencies ) )
@@ -606,8 +615,7 @@ window.mediaWiki = new ( function( $ ) {
                                dependencies = [dependencies];
                                if ( dependencies[0] in registry ) {
                                        for ( var n = 0; n < registry[dependencies[0]].dependencies.length; n++ ) {
-                                               dependencies[dependencies.length] =
-                                                       registry[dependencies[0]].dependencies[n];
+                                               dependencies[dependencies.length] = registry[dependencies[0]].dependencies[n];
                                        }
                                }
                        }
@@ -616,7 +624,8 @@ window.mediaWiki = new ( function( $ ) {
                                jobs[jobs.length] = {
                                        'dependencies': filter(
                                                ['undefined', 'registered', 'loading', 'loaded'],
-                                               dependencies ),
+                                               dependencies
+                                       ),
                                        'ready': ready,
                                        'error': error
                                };
@@ -651,9 +660,9 @@ window.mediaWiki = new ( function( $ ) {
                 * to a query string of the form foo.bar,baz|bar.baz,quux
                 */
                function buildModulesString( moduleMap ) {
-                       var arr = [];
+                       var arr = [], p;
                        for ( var prefix in moduleMap ) {
-                               var p = prefix === '' ? '' : prefix + '.';
+                               p = prefix === '' ? '' : prefix + '.';
                                arr.push( p + moduleMap[prefix].join( ',' ) );
                        }
                        return arr.join( '|' );
@@ -667,15 +676,15 @@ window.mediaWiki = new ( function( $ ) {
                 * @param callback Function: Optional callback which will be run when the script is done
                 */
                function addScript( src, callback ) {
+                       var done = false, script;
                        if ( ready ) {
                                // jQuery's getScript method is NOT better than doing this the old-fassioned way
                                // because jQuery will eval the script's code, and errors will not have sane
                                // line numbers.
-                               var script = document.createElement( 'script' );
+                               script = document.createElement( 'script' );
                                script.setAttribute( 'src', src );
                                script.setAttribute( 'type', 'text/javascript' );
                                if ( $.isFunction( callback ) ) {
-                                       var done = false;
                                        // Attach handlers for all browsers -- this is based on jQuery.getScript
                                        script.onload = script.onreadystatechange = function() {
                                                if (
@@ -714,10 +723,21 @@ window.mediaWiki = new ( function( $ ) {
                 * Requests dependencies from server, loading and executing when things when ready.
                 */
                this.work = function() {
+                               // Build a list of request parameters
+                       var     base = {
+                                       'skin': mw.config.get( 'skin' ),
+                                       'lang': mw.config.get( 'wgUserLanguage' ),
+                                       'debug': mw.config.get( 'debug' )
+                               },
+                               // Extend request parameters with a list of modules in the batch
+                               requests = [],
+                               // Split into groups
+                               groups = {};
+
                        // Appends a list of modules to the batch
                        for ( var q = 0; q < queue.length; q++ ) {
                                // Only request modules which are undefined or registered
-                               if ( !( queue[q] in registry ) || registry[queue[q]].state == 'registered' ) {
+                               if ( !( queue[q] in registry ) || registry[queue[q]].state === 'registered' ) {
                                        // Prevent duplicate entries
                                        if ( $.inArray( queue[q], batch ) === -1 ) {
                                                batch[batch.length] = queue[q];
@@ -737,22 +757,12 @@ window.mediaWiki = new ( function( $ ) {
                        // Always order modules alphabetically to help reduce cache
                        // misses for otherwise identical content
                        batch.sort();
-                       // Build a list of request parameters
-                       var base = {
-                               'skin': mw.config.get( 'skin' ),
-                               'lang': mw.config.get( 'wgUserLanguage' ),
-                               'debug': mw.config.get( 'debug' )
-                       };
-                       // Extend request parameters with a list of modules in the batch
-                       var requests = [];
-                       // Split into groups
-                       var groups = {};
                        for ( var b = 0; b < batch.length; b++ ) {
-                               var group = registry[batch[b]].group;
-                               if ( !( group in groups ) ) {
-                                       groups[group] = [];
+                               var bGroup = registry[batch[b]].group;
+                               if ( !( bGroup in groups ) ) {
+                                       groups[bGroup] = [];
                                }
-                               groups[group][groups[group].length] = batch[b];
+                               groups[bGroup][groups[bGroup].length] = batch[b];
                        }
                        for ( var group in groups ) {
                                // Calculate the highest timestamp
@@ -762,28 +772,31 @@ window.mediaWiki = new ( function( $ ) {
                                                version = registry[groups[group][g]].version;
                                        }
                                }
-                               var reqBase = $.extend( { 'version': formatVersionNumber( version ) }, base );
-                               var reqBaseLength = $.param( reqBase ).length;
-                               var reqs = [];
-                               var limit = mw.config.get( 'wgResourceLoaderMaxQueryLength', -1 );
-                               // We may need to split up the request to honor the query string length limit
-                               // So build it piece by piece
-                               var l = reqBaseLength + 9; // '&modules='.length == 9
-                               var r = 0;
+
+                               var     reqBase = $.extend( { 'version': formatVersionNumber( version ) }, base ),
+                                       reqBaseLength = $.param( reqBase ).length,
+                                       reqs = [],
+                                       limit = mw.config.get( 'wgResourceLoaderMaxQueryLength', -1 ),
+                                       // We may need to split up the request to honor the query string length limit,
+                                       // so build it piece by piece.
+                                       l = reqBaseLength + 9, // '&modules='.length == 9
+                                       r = 0;
+
                                reqs[0] = {}; // { prefix: [ suffixes ] }
+
                                for ( var i = 0; i < groups[group].length; i++ ) {
-                                       // Determine how many bytes this module would add to the query string
-                                       var lastDotIndex = groups[group][i].lastIndexOf( '.' );
-                                       // Note that these substr() calls work even if lastDotIndex == -1
-                                       var prefix = groups[group][i].substr( 0, lastDotIndex );
-                                       var suffix = groups[group][i].substr( lastDotIndex + 1 );
-                                       var bytesAdded = prefix in reqs[r] ?
-                                               suffix.length + 3 : // '%2C'.length == 3
-                                               groups[group][i].length + 3; // '%7C'.length == 3
+                                               // Determine how many bytes this module would add to the query string
+                                       var     lastDotIndex = groups[group][i].lastIndexOf( '.' ),
+                                               // Note that these substr() calls work even if lastDotIndex == -1
+                                               prefix = groups[group][i].substr( 0, lastDotIndex ),
+                                               suffix = groups[group][i].substr( lastDotIndex + 1 ),
+                                               bytesAdded = prefix in reqs[r]
+                                                       ? suffix.length + 3 // '%2C'.length == 3
+                                                       : groups[group][i].length + 3; // '%7C'.length == 3
 
                                        // If the request would become too long, create a new one,
                                        // but don't create empty requests
-                                       if ( limit > 0 &&  reqs[r] != {} && l + bytesAdded > limit ) {
+                                       if ( limit > 0 && !$.isEmptyObject( reqs[r] ) && l + bytesAdded > limit ) {
                                                // This request would become too long, create a new one
                                                r++;
                                                reqs[r] = {};
@@ -836,7 +849,7 @@ window.mediaWiki = new ( function( $ ) {
                        if ( typeof module !== 'string' ) {
                                throw new Error( 'module must be a string, not a ' + typeof module );
                        }
-                       if ( typeof registry[module] !== 'undefined' ) {
+                       if ( registry[module] !== undefined ) {
                                throw new Error( 'module already implemented: ' + module );
                        }
                        // List the module as registered
@@ -844,7 +857,7 @@ window.mediaWiki = new ( function( $ ) {
                                'state': 'registered',
                                'group': typeof group === 'string' ? group : null,
                                'dependencies': [],
-                               'version': typeof version !== 'undefined' ? parseInt( version, 10 ) : 0
+                               'version': version !== undefined ? parseInt( version, 10 ) : 0
                        };
                        if ( typeof dependencies === 'string' ) {
                                // Allow dependencies to be given as a single module name
@@ -865,9 +878,9 @@ window.mediaWiki = new ( function( $ ) {
                 *
                 * @param module String: Name of module
                 * @param script Mixed: Function of module code or String of URL to be used as the src
-                * attribute when adding a script element to the body
+                *  attribute when adding a script element to the body
                 * @param style Object: Object of CSS strings keyed by media-type or Object of lists of URLs
-                * keyed by media-type
+                *  keyed by media-type
                 * @param msgs Object: List of key/value pairs to be passed through mw.messages.set
                 */
                this.implement = function( module, script, style, msgs ) {
@@ -885,13 +898,11 @@ window.mediaWiki = new ( function( $ ) {
                                throw new Error( 'msgs must be an object, not a ' + typeof msgs );
                        }
                        // Automatically register module
-                       if ( typeof registry[module] === 'undefined' ) {
+                       if ( registry[module] === undefined ) {
                                mw.loader.register( module );
                        }
                        // Check for duplicate implementation
-                       if ( typeof registry[module] !== 'undefined'
-                               && typeof registry[module].script !== 'undefined' )
-                       {
+                       if ( registry[module] !== undefined && registry[module].script !== undefined ) {
                                throw new Error( 'module already implemeneted: ' + module );
                        }
                        // Mark module as loaded
@@ -915,19 +926,18 @@ window.mediaWiki = new ( function( $ ) {
                 * Executes a function as soon as one or more required modules are ready
                 *
                 * @param dependencies string or array of strings of modules names the callback
-                *   dependencies to be ready before
-                * executing
+                *  dependencies to be ready before executing
                 * @param ready function callback to execute when all dependencies are ready (optional)
                 * @param error function callback to execute when if dependencies have a errors (optional)
                 */
                this.using = function( dependencies, ready, error ) {
+                       var tod = typeof dependencies;
                        // Validate input
-                       if ( typeof dependencies !== 'object' && typeof dependencies !== 'string' ) {
-                               throw new Error( 'dependencies must be a string or an array, not a ' +
-                                       typeof dependencies );
+                       if ( tod !== 'object' && tod !== 'string' ) {
+                               throw new Error( 'dependencies must be a string or an array, not a ' + tod );
                        }
                        // Allow calling with a single dependency as a string
-                       if ( typeof dependencies === 'string' ) {
+                       if ( tod === 'string' ) {
                                dependencies = [dependencies];
                        }
                        // Resolve entire dependency map
@@ -954,30 +964,28 @@ window.mediaWiki = new ( function( $ ) {
                 * Loads an external script or one or more modules for future use
                 *
                 * @param modules mixed either the name of a module, array of modules,
-                *   or a URL of an external script or style
+                *  or a URL of an external script or style
                 * @param type string mime-type to use if calling with a URL of an
-                *   external script or style; acceptable values are "text/css" and
-                *   "text/javascript"; if no type is provided, text/javascript is
-                *   assumed
+                *  external script or style; acceptable values are "text/css" and
+                *  "text/javascript"; if no type is provided, text/javascript is assumed.
                 */
                this.load = function( modules, type ) {
                        // Validate input
                        if ( typeof modules !== 'object' && typeof modules !== 'string' ) {
-                               throw new Error( 'modules must be a string or an array, not a ' +
-                                       typeof modules );
+                               throw new Error( 'modules must be a string or an array, not a ' + typeof modules );
                        }
                        // Allow calling with an external script or single dependency as a string
                        if ( typeof modules === 'string' ) {
                                // Support adding arbitrary external scripts
-                               if ( modules.substr( 0, 7 ) == 'http://' || modules.substr( 0, 8 ) == 'https://' ) {
+                               if ( modules.substr( 0, 7 ) === 'http://' || modules.substr( 0, 8 ) === 'https://' ) {
                                        if ( type === 'text/css' ) {
-                                               $( 'head' ).append( $( '<link />', {
+                                               $( 'head' ).append( $( '<link/>', {
                                                        rel: 'stylesheet',
                                                        type: 'text/css',
                                                        href: modules
                                                } ) );
                                                return true;
-                                       } else if ( type === 'text/javascript' || typeof type === 'undefined' ) {
+                                       } else if ( type === 'text/javascript' || type === undefined ) {
                                                addScript( modules );
                                                return true;
                                        }
@@ -1034,11 +1042,12 @@ window.mediaWiki = new ( function( $ ) {
                        }
                        return null;
                };
+
                /**
                * @deprecated use mw.loader.getVersion() instead
                */
                this.version = function() {
-                       return mediaWiki.loader.getVersion.apply( mediaWiki.loader, arguments );
+                       return mw.loader.getVersion.apply( mw.loader, arguments );
                };
 
                /**
@@ -1103,17 +1112,17 @@ window.mediaWiki = new ( function( $ ) {
                 * @param name The tag name.
                 * @param attrs An object with members mapping element names to values
                 * @param contents The contents of the element. May be either:
-                *    - string: The string is escaped.
-                *    - null or undefined: The short closing form is used, e.g. <br/>.
-                *    - this.Raw: The value attribute is included without escaping.
-                *    - this.Cdata: The value attribute is included, and an exception is
-                *      thrown if it contains an illegal ETAGO delimiter.
-                *      See http://www.w3.org/TR/1999/REC-html401-19991224/appendix/notes.html#h-B.3.2
+                *  - string: The string is escaped.
+                *  - null or undefined: The short closing form is used, e.g. <br/>.
+                *  - this.Raw: The value attribute is included without escaping.
+                *  - this.Cdata: The value attribute is included, and an exception is
+                *   thrown if it contains an illegal ETAGO delimiter.
+                *   See http://www.w3.org/TR/1999/REC-html401-19991224/appendix/notes.html#h-B.3.2
                 *
                 * Example:
-                *    var h = mw.html;
-                *    return h.element( 'div', {},
-                *        new h.Raw( h.element( 'img', {src: '<'} ) ) );
+                *      var h = mw.html;
+                *      return h.element( 'div', {},
+                *              new h.Raw( h.element( 'img', {src: '<'} ) ) );
                 * Returns <div><img src="&lt;"/></div>
                 */
                this.element = function( name, attrs, contents ) {
@@ -1121,7 +1130,7 @@ window.mediaWiki = new ( function( $ ) {
                        for ( var attrName in attrs ) {
                                s += ' ' + attrName + '="' + this.escape( attrs[attrName] ) + '"';
                        }
-                       if ( typeof contents == 'undefined' || contents === null ) {
+                       if ( contents === undefined || contents === null ) {
                                // Self close tag
                                s += '/>';
                                return s;
@@ -1156,11 +1165,9 @@ window.mediaWiki = new ( function( $ ) {
 
 // Alias $j to jQuery for backwards compatibility
 window.$j = jQuery;
-window.mw = mediaWiki;
-
-/* Auto-register from pre-loaded startup scripts */
 
-if ( $.isFunction( startUp ) ) {
+// Auto-register from pre-loaded startup scripts
+if ( jQuery.isFunction( startUp ) ) {
        startUp();
        delete startUp;
 }