*/
// Make calling .indexOf() on an array work on older browsers
-if ( typeof Array.prototype.indexOf === 'undefined' ) {
+if ( typeof Array.prototype.indexOf === 'undefined' ) {
Array.prototype.indexOf = function( needle ) {
for ( var i = 0; i < this.length; i++ ) {
if ( this[i] === needle ) {
};
}
// Add array comparison functionality
-if ( typeof Array.prototype.compare === 'undefined' ) {
+if ( typeof Array.prototype.compare === 'undefined' ) {
Array.prototype.compare = function( against ) {
if ( this.length != against.length ) {
return false;
}
for ( var i = 0; i < against.length; i++ ) {
- if ( this[i].compare ) {
+ if ( this[i].compare ) {
if ( !this[i].compare( against[i] ) ) {
return false;
}
this.prototypes = {
/*
* An object which allows single and multiple get/set/exists functionality on a list of key / value pairs
- *
+ *
* @param {boolean} global whether to get/set/exists values on the window object or a private object
* @param {function} parser function to perform extra processing; in the form of function( value, options )
* @param {function} fallback function to format default fallback; in the form of function( key )
/**
* Gets one or more values
- *
+ *
* If called with no arguments, all values will be returned. If a parser is in use, no parsing will take
* place when calling with no arguments or calling with an array of names.
- *
+ *
* @param {mixed} selection string name of value to get, array of string names of values to get, or object
* of name/option pairs
* @param {object} options optional set of options which are also passed to a parser if in use; only used
/**
* Sets one or multiple configuration values using a key and a value or an object of keys and values
- *
+ *
* @param {mixed} key string of name by which value will be made accessible, or object of name/value pairs
* @param {mixed} value optional value to set, only in use when key is a string
*/
/*
* List of configuration values
- *
+ *
* In legacy mode the values this object wraps will be in the global space
*/
this.config = new this.prototypes.map( LEGACY_GLOBALS );
var that = this;
/*
* Mapping of registered modules
- *
+ *
* The jquery module is pre-registered, because it must have already been provided for this object to have
* been built, and in debug mode jquery would have been provided through a unique loader request, making it
* impossible to hold back registration of jquery until after mediawiki.
- *
+ *
* Format:
* {
* 'moduleName': {
// Resolves dynamic loader function and replaces it with it's own results
if ( typeof registry[module].dependencies === 'function' ) {
registry[module].dependencies = registry[module].dependencies();
- // Ensures the module's dependencies are always in an array
+ // Ensures the module's dependencies are always in an array
if ( typeof registry[module].dependencies !== 'object' ) {
registry[module].dependencies = [registry[module].dependencies];
}
/**
* Gets a list of modules names that a module dependencies in their proper dependency order
- *
+ *
* @param mixed string module name or array of string module names
* @return list of dependencies
* @throws Error if circular reference is detected
/**
* Narrows a list of module names down to those matching a specific state. Possible states are 'undefined',
* 'registered', 'loading', 'loaded', or 'ready'
- *
+ *
* @param mixed string or array of strings of module states to filter by
* @param array list of module names to filter (optional, all modules will be used by default)
* @return array list of filtered module names
/**
* Executes a loaded module, making it ready to use
- *
+ *
* @param string module name to execute
*/
function execute( module ) {
/**
* Adds a dependencies to the queue with optional callbacks to be run when the dependencies are ready or fail
- *
+ *
* @param mixed string moulde name or array of string module names
* @param function ready callback to execute when all dependencies are ready
* @param function error callback to execute when any dependency fails
/**
* Executes a function as soon as one or more required modules are ready
- *
+ *
* @param mixed string or array of strings of modules names the callback dependencies to be ready before
* executing
* @param function callback to execute when all dependencies are ready (optional)
/**
* Loads an external script or one or more modules for future use
- *
+ *
* @param {mixed} modules either the name of a module, array of modules, or a URL of an external script or style
* @param {string} type 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
/**
* Changes the state of a module
- *
+ *
* @param mixed module string module name or object of module name/state pairs
* @param string state string state name
*/
/**
* Gets the version of a module
- *
+ *
* @param string module name of module to get version for
*/
this.version = function( module ) {
/* Extension points */
- this.util = {};
this.legacy = {};
} )( jQuery );
// Alias $j to jQuery for backwards compatibility
window.$j = jQuery;
+window.mw = mediaWiki;
\ No newline at end of file
--- /dev/null
+/*jslint white: true, browser: true, undef: true, nomen: true, eqeqeq: true, plusplus: true, bitwise: true, regexp: true, newcap: true */
+/*
+ * Utilities
+ */
+
+(function ($, mw) {
+
+ mediaWiki.util = {
+
+ /* Initialisation */
+ 'initialised' : false,
+ 'init' : function () {
+ if (this.initialised === false){
+ this.initialised = true;
+
+
+ // Set tooltipAccessKeyPrefix
+ if ( is_opera ) {
+ this.tooltipAccessKeyPrefix = 'shift-esc-';
+ } else if ( is_chrome ) {
+ this.tooltipAccessKeyPrefix = is_chrome_mac ? 'ctrl-option-' : 'alt-';
+ } else if ( !is_safari_win && is_safari && webkit_version > 526 ) {
+ this.tooltipAccessKeyPrefix = 'ctrl-alt-';
+ } else if ( !is_safari_win && ( is_safari
+ || clientPC.indexOf('mac') != -1
+ || clientPC.indexOf('konqueror') != -1 ) ) {
+ this.tooltipAccessKeyPrefix = 'ctrl-';
+ } else if ( is_ff2 ) {
+ this.tooltipAccessKeyPrefix = 'alt-shift-';
+ }
+
+
+ return true;
+ }
+ return false;
+ },
+
+ /* Main body */
+
+ /**
+ * Encodes the string like PHP's rawurlencode
+ *
+ * @param String str string to be encoded
+ */
+ 'rawurlencode' : function (str) {
+ str = (str + '').toString();
+ return encodeURIComponent(str).replace(/!/g, '%21').replace(/'/g, '%27').replace(/\(/g, '%28')
+ .replace(/\)/g, '%29').replace(/\*/g, '%2A').replace(/~/g, '%7E');
+ },
+
+ /**
+ * Encode pagetitles for use in a URL
+ * We want / and : to be included as literal characters in our title URLs
+ * as they otherwise fatally break the title
+ *
+ * @param String str string to be encoded
+ */
+ 'wikiUrlencode' : function (str) {
+ return this.rawurlencode(str).replace(/%20/g, '_').replace(/%3A/g, ':').replace(/%2F/g, '/');
+ },
+
+
+ /**
+ * Grabs the url parameter value for the given parameter
+ * Returns null if not found
+ *
+ * @param String param paramter name
+ * @param String url url to search through (optional)
+ */
+ 'getParamValue' : function (param, url) {
+ url = url ? url : document.location.href;
+ var re = new RegExp('[^#]*[&?]' + param + '=([^&#]*)'); // Get last match, stop at hash
+ var m = re.exec(url);
+ if (m && m.length > 1) {
+ return decodeURIComponent(m[1]);
+ }
+ return null;
+ },
+
+ /**
+ * Converts special characters to their HTML entities
+ *
+ * @param String str text to escape
+ * @param Bool quotes if true escapes single and double quotes aswell (by default false)
+ */
+ 'htmlEscape' : function (str, quotes) {
+ str = $('<div/>').text(str).html();
+ if (typeof quotes === 'undefined') {
+ quotes = false;
+ }
+ if (quotes === true) {
+ str = str.replace(/'/g, ''').replace(/"/g, '"');
+ }
+ return str;
+ },
+
+ /**
+ * Converts HTML entities back to text
+ *
+ * @param String str text to unescape
+ */
+ 'htmlUnescape' : function (str) {
+ return $('<div/>').html(str).text();
+ },
+
+ // Access key prefix
+ // will be re-defined based on browser/operating system detection in mw.util.init()
+ 'tooltipAccessKeyPrefix' : 'alt-',
+
+ // Regex to match accesskey tooltips
+ 'tooltipAccessKeyRegexp': /\[(ctrl-)?(alt-)?(shift-)?(esc-)?(.)\]$/,
+
+ /**
+ * Add the appropriate prefix to the accesskey shown in the tooltip.
+ * If the nodeList parameter is given, only those nodes are updated;
+ * otherwise, all the nodes that will probably have accesskeys by
+ * default are updated.
+ *
+ * @param Mixed nodeList jQuery object, or array of elements
+ */
+ 'updateTooltipAccessKeys' : function (nodeList) {
+ var $nodes;
+ if (nodeList instanceof jQuery) {
+ $nodes = nodeList;
+ } else if (nodeList) {
+ $nodes = $(nodeList);
+ } else {
+ // Rather than scanning all links, just
+ $("#column-one a, #mw-head a, #mw-panel a, #p-logo a");
+
+ // these are rare enough that no such optimization is needed
+ this.updateTooltipAccessKeys($('input'));
+ this.updateTooltipAccessKeys($('label'));
+ return;
+ }
+
+ $nodes.each(function (i) {
+ var tip = $(this).attr('title');
+ if (!!tip && mw.util.tooltipAccessKeyRegexp.exec(tip)) {
+ tip = tip.replace(mw.util.tooltipAccessKeyRegexp, '[' + tooltipAccessKeyPrefix + "$5]");
+ $(this).attr('title', tip);
+ }
+ });
+ },
+
+
+ /**
+ * Add a link to a portlet menu on the page, such as:
+ *
+ * p-cactions (Content actions), p-personal (Personal tools), p-navigation (Navigation), p-tb (Toolbox)
+ *
+ * The first three paramters are required, others are optionals. Though
+ * providing an id and tooltip is recommended.
+ *
+ * By default the new link will be added to the end of the list. To add the link before a given existing item,
+ * pass the DOM node (document.getElementById('foobar') or the jQuery-selector ('#foobar') of that item.
+ *
+ * @example mw.util.addPortletLink('p-tb', 'http://mediawiki.org/', 'MediaWiki.org', 't-mworg', 'Go to MediaWiki.org ', 'm', '#t-print')
+ *
+ * @param String portlet id of the target portlet ("p-cactions" or "p-personal" etc.)
+ * @param String href link URL
+ * @param String text link text (will be automatically lowercased by CSS for p-cactions in Monobook)
+ * @param String id id of the new item, should be unique and preferably have the appropriate prefix ("ca-", "pt-", "n-" or "t-")
+ * @param String tooltip text to show when hovering over the link, without accesskey suffix
+ * @param String accesskey accesskey to activate this link (one character, try to avoid conflicts)
+ * @param mixed nextnode DOM node or jQuery-selector of the item that the new item should be added before, should be another item in the same list
+ *
+ * @return Node the DOM node of the new item (a LI element) or null
+ */
+ 'addPortletLink' : function (portlet, href, text, id, tooltip, accesskey, nextnode) {
+ var $portlet = $('#' + portlet);
+ if ($portlet.length === 0) {
+ return null;
+ }
+ var $ul = $portlet.find('ul').eq(0);
+ if ($ul.length === 0) {
+ if ($portlet.find('div').length === 0) {
+ $portlet.append('<ul />');
+ } else {
+ $portlet.find('div').eq(-1).append('<ul />');
+ }
+ $ul = $portlet.find('ul').eq(0);
+ }
+ if ($ul.length === 0) {
+ return null;
+ }
+
+ // unhide portlet if it was hidden before
+ $portlet.removeClass('emptyPortlet');
+
+ var $link = $('<a />').attr('href', href).text(text);
+ var $item = $link.wrap('<li><span /></li>').parent().parent();
+
+ if (id) {
+ $item.attr('id', id);
+ }
+ if (accesskey) {
+ $link.attr('accesskey', accesskey);
+ tooltip += ' [' + accesskey + ']';
+ }
+ if (tooltip) {
+ $link.attr('title', tooltip);
+ }
+ if (accesskey && tooltip) {
+ this.updateTooltipAccessKeys($link);
+ }
+
+ // Append using DOM-element passing
+ if (nextnode && nextnode.parentNode == $ul.get(0)) {
+ $(nextnode).before($item);
+ } else {
+ // If the jQuery selector isn't found within the <ul>, just append it at the end
+ if ($ul.find(nextnode).length === 0) {
+ $ul.append($item);
+ } else {
+ // Append using jQuery CSS selector
+ $ul.find(nextnode).eq(0).before($item);
+ }
+ }
+
+ return $item.get(0);
+ }
+
+ };
+
+})(jQuery, mediaWiki);
+
+mediaWiki.util.init();
\ No newline at end of file