r75275 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r75274‎ | r75275 | r75276 >
Date:17:24, 23 October 2010
Author:krinkle
Status:resolved (Comments)
Tags:
Comment:
adding begin of mediaWiki.util and loading it by default + trailing whitespace cleanup in mediawiki.js
Modified paths:
  • /trunk/phase3/includes/OutputPage.php (modified) (history)
  • /trunk/phase3/resources/Resources.php (modified) (history)
  • /trunk/phase3/resources/mediawiki/mediawiki.js (modified) (history)
  • /trunk/phase3/resources/mediawiki/mediawiki.util.js (added) (history)

Diff [purge]

Index: trunk/phase3/includes/OutputPage.php
@@ -1613,6 +1613,7 @@
16141614
16151615 // Add base resources
16161616 $this->addModules( array( 'mediawiki.legacy.wikibits' ) );
 1617+ $this->addModules( array( 'mediawiki.util' ) );
16171618
16181619 // Add various resources if required
16191620 if ( $wgUseAjax ) {
Index: trunk/phase3/resources/Resources.php
@@ -326,6 +326,9 @@
327327 'scripts' => 'resources/mediawiki/mediawiki.views.history.js',
328328 'dependencies' => 'mediawiki.legacy.history',
329329 ) ),
 330+ 'mediawiki.util' => new ResourceLoaderFileModule( array(
 331+ 'scripts' => 'resources/mediawiki/mediawiki.util.js',
 332+ ) ),
330333
331334 /* MediaWiki Legacy */
332335
Index: trunk/phase3/resources/mediawiki/mediawiki.util.js
@@ -0,0 +1,228 @@
 2+/*jslint white: true, browser: true, undef: true, nomen: true, eqeqeq: true, plusplus: true, bitwise: true, regexp: true, newcap: true */
 3+/*
 4+ * Utilities
 5+ */
 6+
 7+(function ($, mw) {
 8+
 9+ mediaWiki.util = {
 10+
 11+ /* Initialisation */
 12+ 'initialised' : false,
 13+ 'init' : function () {
 14+ if (this.initialised === false){
 15+ this.initialised = true;
 16+
 17+
 18+ // Set tooltipAccessKeyPrefix
 19+ if ( is_opera ) {
 20+ this.tooltipAccessKeyPrefix = 'shift-esc-';
 21+ } else if ( is_chrome ) {
 22+ this.tooltipAccessKeyPrefix = is_chrome_mac ? 'ctrl-option-' : 'alt-';
 23+ } else if ( !is_safari_win && is_safari && webkit_version > 526 ) {
 24+ this.tooltipAccessKeyPrefix = 'ctrl-alt-';
 25+ } else if ( !is_safari_win && ( is_safari
 26+ || clientPC.indexOf('mac') != -1
 27+ || clientPC.indexOf('konqueror') != -1 ) ) {
 28+ this.tooltipAccessKeyPrefix = 'ctrl-';
 29+ } else if ( is_ff2 ) {
 30+ this.tooltipAccessKeyPrefix = 'alt-shift-';
 31+ }
 32+
 33+
 34+ return true;
 35+ }
 36+ return false;
 37+ },
 38+
 39+ /* Main body */
 40+
 41+ /**
 42+ * Encodes the string like PHP's rawurlencode
 43+ *
 44+ * @param String str string to be encoded
 45+ */
 46+ 'rawurlencode' : function (str) {
 47+ str = (str + '').toString();
 48+ return encodeURIComponent(str).replace(/!/g, '%21').replace(/'/g, '%27').replace(/\(/g, '%28')
 49+ .replace(/\)/g, '%29').replace(/\*/g, '%2A').replace(/~/g, '%7E');
 50+ },
 51+
 52+ /**
 53+ * Encode pagetitles for use in a URL
 54+ * We want / and : to be included as literal characters in our title URLs
 55+ * as they otherwise fatally break the title
 56+ *
 57+ * @param String str string to be encoded
 58+ */
 59+ 'wikiUrlencode' : function (str) {
 60+ return this.rawurlencode(str).replace(/%20/g, '_').replace(/%3A/g, ':').replace(/%2F/g, '/');
 61+ },
 62+
 63+
 64+ /**
 65+ * Grabs the url parameter value for the given parameter
 66+ * Returns null if not found
 67+ *
 68+ * @param String param paramter name
 69+ * @param String url url to search through (optional)
 70+ */
 71+ 'getParamValue' : function (param, url) {
 72+ url = url ? url : document.location.href;
 73+ var re = new RegExp('[^#]*[&?]' + param + '=([^&#]*)'); // Get last match, stop at hash
 74+ var m = re.exec(url);
 75+ if (m && m.length > 1) {
 76+ return decodeURIComponent(m[1]);
 77+ }
 78+ return null;
 79+ },
 80+
 81+ /**
 82+ * Converts special characters to their HTML entities
 83+ *
 84+ * @param String str text to escape
 85+ * @param Bool quotes if true escapes single and double quotes aswell (by default false)
 86+ */
 87+ 'htmlEscape' : function (str, quotes) {
 88+ str = $('<div/>').text(str).html();
 89+ if (typeof quotes === 'undefined') {
 90+ quotes = false;
 91+ }
 92+ if (quotes === true) {
 93+ str = str.replace(/'/g, '&#039;').replace(/"/g, '&quot;');
 94+ }
 95+ return str;
 96+ },
 97+
 98+ /**
 99+ * Converts HTML entities back to text
 100+ *
 101+ * @param String str text to unescape
 102+ */
 103+ 'htmlUnescape' : function (str) {
 104+ return $('<div/>').html(str).text();
 105+ },
 106+
 107+ // Access key prefix
 108+ // will be re-defined based on browser/operating system detection in mw.util.init()
 109+ 'tooltipAccessKeyPrefix' : 'alt-',
 110+
 111+ // Regex to match accesskey tooltips
 112+ 'tooltipAccessKeyRegexp': /\[(ctrl-)?(alt-)?(shift-)?(esc-)?(.)\]$/,
 113+
 114+ /**
 115+ * Add the appropriate prefix to the accesskey shown in the tooltip.
 116+ * If the nodeList parameter is given, only those nodes are updated;
 117+ * otherwise, all the nodes that will probably have accesskeys by
 118+ * default are updated.
 119+ *
 120+ * @param Mixed nodeList jQuery object, or array of elements
 121+ */
 122+ 'updateTooltipAccessKeys' : function (nodeList) {
 123+ var $nodes;
 124+ if (nodeList instanceof jQuery) {
 125+ $nodes = nodeList;
 126+ } else if (nodeList) {
 127+ $nodes = $(nodeList);
 128+ } else {
 129+ // Rather than scanning all links, just
 130+ $("#column-one a, #mw-head a, #mw-panel a, #p-logo a");
 131+
 132+ // these are rare enough that no such optimization is needed
 133+ this.updateTooltipAccessKeys($('input'));
 134+ this.updateTooltipAccessKeys($('label'));
 135+ return;
 136+ }
 137+
 138+ $nodes.each(function (i) {
 139+ var tip = $(this).attr('title');
 140+ if (!!tip && mw.util.tooltipAccessKeyRegexp.exec(tip)) {
 141+ tip = tip.replace(mw.util.tooltipAccessKeyRegexp, '[' + tooltipAccessKeyPrefix + "$5]");
 142+ $(this).attr('title', tip);
 143+ }
 144+ });
 145+ },
 146+
 147+
 148+ /**
 149+ * Add a link to a portlet menu on the page, such as:
 150+ *
 151+ * p-cactions (Content actions), p-personal (Personal tools), p-navigation (Navigation), p-tb (Toolbox)
 152+ *
 153+ * The first three paramters are required, others are optionals. Though
 154+ * providing an id and tooltip is recommended.
 155+ *
 156+ * By default the new link will be added to the end of the list. To add the link before a given existing item,
 157+ * pass the DOM node (document.getElementById('foobar') or the jQuery-selector ('#foobar') of that item.
 158+ *
 159+ * @example mw.util.addPortletLink('p-tb', 'http://mediawiki.org/', 'MediaWiki.org', 't-mworg', 'Go to MediaWiki.org ', 'm', '#t-print')
 160+ *
 161+ * @param String portlet id of the target portlet ("p-cactions" or "p-personal" etc.)
 162+ * @param String href link URL
 163+ * @param String text link text (will be automatically lowercased by CSS for p-cactions in Monobook)
 164+ * @param String id id of the new item, should be unique and preferably have the appropriate prefix ("ca-", "pt-", "n-" or "t-")
 165+ * @param String tooltip text to show when hovering over the link, without accesskey suffix
 166+ * @param String accesskey accesskey to activate this link (one character, try to avoid conflicts)
 167+ * @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
 168+ *
 169+ * @return Node the DOM node of the new item (a LI element) or null
 170+ */
 171+ 'addPortletLink' : function (portlet, href, text, id, tooltip, accesskey, nextnode) {
 172+ var $portlet = $('#' + portlet);
 173+ if ($portlet.length === 0) {
 174+ return null;
 175+ }
 176+ var $ul = $portlet.find('ul').eq(0);
 177+ if ($ul.length === 0) {
 178+ if ($portlet.find('div').length === 0) {
 179+ $portlet.append('<ul />');
 180+ } else {
 181+ $portlet.find('div').eq(-1).append('<ul />');
 182+ }
 183+ $ul = $portlet.find('ul').eq(0);
 184+ }
 185+ if ($ul.length === 0) {
 186+ return null;
 187+ }
 188+
 189+ // unhide portlet if it was hidden before
 190+ $portlet.removeClass('emptyPortlet');
 191+
 192+ var $link = $('<a />').attr('href', href).text(text);
 193+ var $item = $link.wrap('<li><span /></li>').parent().parent();
 194+
 195+ if (id) {
 196+ $item.attr('id', id);
 197+ }
 198+ if (accesskey) {
 199+ $link.attr('accesskey', accesskey);
 200+ tooltip += ' [' + accesskey + ']';
 201+ }
 202+ if (tooltip) {
 203+ $link.attr('title', tooltip);
 204+ }
 205+ if (accesskey && tooltip) {
 206+ this.updateTooltipAccessKeys($link);
 207+ }
 208+
 209+ // Append using DOM-element passing
 210+ if (nextnode && nextnode.parentNode == $ul.get(0)) {
 211+ $(nextnode).before($item);
 212+ } else {
 213+ // If the jQuery selector isn't found within the <ul>, just append it at the end
 214+ if ($ul.find(nextnode).length === 0) {
 215+ $ul.append($item);
 216+ } else {
 217+ // Append using jQuery CSS selector
 218+ $ul.find(nextnode).eq(0).before($item);
 219+ }
 220+ }
 221+
 222+ return $item.get(0);
 223+ }
 224+
 225+ };
 226+
 227+})(jQuery, mediaWiki);
 228+
 229+mediaWiki.util.init();
\ No newline at end of file
Property changes on: trunk/phase3/resources/mediawiki/mediawiki.util.js
___________________________________________________________________
Added: svn:eol-style
1230 + native
Index: trunk/phase3/resources/mediawiki/mediawiki.js
@@ -3,7 +3,7 @@
44 */
55
66 // Make calling .indexOf() on an array work on older browsers
7 -if ( typeof Array.prototype.indexOf === 'undefined' ) {
 7+if ( typeof Array.prototype.indexOf === 'undefined' ) {
88 Array.prototype.indexOf = function( needle ) {
99 for ( var i = 0; i < this.length; i++ ) {
1010 if ( this[i] === needle ) {
@@ -14,13 +14,13 @@
1515 };
1616 }
1717 // Add array comparison functionality
18 -if ( typeof Array.prototype.compare === 'undefined' ) {
 18+if ( typeof Array.prototype.compare === 'undefined' ) {
1919 Array.prototype.compare = function( against ) {
2020 if ( this.length != against.length ) {
2121 return false;
2222 }
2323 for ( var i = 0; i < against.length; i++ ) {
24 - if ( this[i].compare ) {
 24+ if ( this[i].compare ) {
2525 if ( !this[i].compare( against[i] ) ) {
2626 return false;
2727 }
@@ -53,7 +53,7 @@
5454 this.prototypes = {
5555 /*
5656 * An object which allows single and multiple get/set/exists functionality on a list of key / value pairs
57 - *
 57+ *
5858 * @param {boolean} global whether to get/set/exists values on the window object or a private object
5959 * @param {function} parser function to perform extra processing; in the form of function( value, options )
6060 * @param {function} fallback function to format default fallback; in the form of function( key )
@@ -70,10 +70,10 @@
7171
7272 /**
7373 * Gets one or more values
74 - *
 74+ *
7575 * If called with no arguments, all values will be returned. If a parser is in use, no parsing will take
7676 * place when calling with no arguments or calling with an array of names.
77 - *
 77+ *
7878 * @param {mixed} selection string name of value to get, array of string names of values to get, or object
7979 * of name/option pairs
8080 * @param {object} options optional set of options which are also passed to a parser if in use; only used
@@ -120,7 +120,7 @@
121121
122122 /**
123123 * Sets one or multiple configuration values using a key and a value or an object of keys and values
124 - *
 124+ *
125125 * @param {mixed} key string of name by which value will be made accessible, or object of name/value pairs
126126 * @param {mixed} value optional value to set, only in use when key is a string
127127 */
@@ -161,7 +161,7 @@
162162
163163 /*
164164 * List of configuration values
165 - *
 165+ *
166166 * In legacy mode the values this object wraps will be in the global space
167167 */
168168 this.config = new this.prototypes.map( LEGACY_GLOBALS );
@@ -204,11 +204,11 @@
205205 var that = this;
206206 /*
207207 * Mapping of registered modules
208 - *
 208+ *
209209 * The jquery module is pre-registered, because it must have already been provided for this object to have
210210 * been built, and in debug mode jquery would have been provided through a unique loader request, making it
211211 * impossible to hold back registration of jquery until after mediawiki.
212 - *
 212+ *
213213 * Format:
214214 * {
215215 * 'moduleName': {
@@ -258,7 +258,7 @@
259259 // Resolves dynamic loader function and replaces it with it's own results
260260 if ( typeof registry[module].dependencies === 'function' ) {
261261 registry[module].dependencies = registry[module].dependencies();
262 - // Ensures the module's dependencies are always in an array
 262+ // Ensures the module's dependencies are always in an array
263263 if ( typeof registry[module].dependencies !== 'object' ) {
264264 registry[module].dependencies = [registry[module].dependencies];
265265 }
@@ -280,7 +280,7 @@
281281
282282 /**
283283 * Gets a list of modules names that a module dependencies in their proper dependency order
284 - *
 284+ *
285285 * @param mixed string module name or array of string module names
286286 * @return list of dependencies
287287 * @throws Error if circular reference is detected
@@ -311,7 +311,7 @@
312312 /**
313313 * Narrows a list of module names down to those matching a specific state. Possible states are 'undefined',
314314 * 'registered', 'loading', 'loaded', or 'ready'
315 - *
 315+ *
316316 * @param mixed string or array of strings of module states to filter by
317317 * @param array list of module names to filter (optional, all modules will be used by default)
318318 * @return array list of filtered module names
@@ -345,7 +345,7 @@
346346
347347 /**
348348 * Executes a loaded module, making it ready to use
349 - *
 349+ *
350350 * @param string module name to execute
351351 */
352352 function execute( module ) {
@@ -413,7 +413,7 @@
414414
415415 /**
416416 * Adds a dependencies to the queue with optional callbacks to be run when the dependencies are ready or fail
417 - *
 417+ *
418418 * @param mixed string moulde name or array of string module names
419419 * @param function ready callback to execute when all dependencies are ready
420420 * @param function error callback to execute when any dependency fails
@@ -621,7 +621,7 @@
622622
623623 /**
624624 * Executes a function as soon as one or more required modules are ready
625 - *
 625+ *
626626 * @param mixed string or array of strings of modules names the callback dependencies to be ready before
627627 * executing
628628 * @param function callback to execute when all dependencies are ready (optional)
@@ -658,7 +658,7 @@
659659
660660 /**
661661 * Loads an external script or one or more modules for future use
662 - *
 662+ *
663663 * @param {mixed} modules either the name of a module, array of modules, or a URL of an external script or style
664664 * @param {string} type mime-type to use if calling with a URL of an external script or style; acceptable values
665665 * are "text/css" and "text/javascript"; if no type is provided, text/javascript is assumed
@@ -717,7 +717,7 @@
718718
719719 /**
720720 * Changes the state of a module
721 - *
 721+ *
722722 * @param mixed module string module name or object of module name/state pairs
723723 * @param string state string state name
724724 */
@@ -736,7 +736,7 @@
737737
738738 /**
739739 * Gets the version of a module
740 - *
 740+ *
741741 * @param string module name of module to get version for
742742 */
743743 this.version = function( module ) {
@@ -753,7 +753,6 @@
754754
755755 /* Extension points */
756756
757 - this.util = {};
758757 this.legacy = {};
759758
760759 } )( jQuery );
@@ -767,3 +766,4 @@
768767
769768 // Alias $j to jQuery for backwards compatibility
770769 window.$j = jQuery;
 770+window.mw = mediaWiki;
\ No newline at end of file

Follow-up revisions

RevisionCommit summaryAuthorDate
r75552Fixed unfinished line from r75275, commented addPortletLink() more, moved pro...krinkle15:35, 27 October 2010
r75553Escaping parameter for regex (Follow-up r75275)krinkle15:37, 27 October 2010
r76073Fixes for r75275:...tstarling06:36, 5 November 2010
r91660Removing calls to deprecated functionality in favor of the new versions. Old ...krinkle17:52, 7 July 2011

Comments

#Comment by Catrope (talk | contribs)   12:05, 27 October 2010
+			var re = new RegExp('[^#]*[&?]' + param + '=([^&#]*)'); // Get last match, stop at hash

You would need to escape param for regex for this to work properly.

+				// Rather than scanning all links, just
+				$("#column-one a, #mw-head a, #mw-panel a, #p-logo a");

??? This looks like an unfinished comment followed by a no-op statement.

+			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);
+			}

You should comment this code a bit to describe the behavior (something like "if there is no ul and no div, create a ul. If there is a div ...")

+				if ( is_opera ) {

Where do all these is_foo vars come from? Wikibits? If so, they should be ported to use $.client

#Comment by Krinkle (talk | contribs)   23:57, 27 October 2010

(forgot to use "follow-up" in my commit msg)

These are fixed now in the follow-ups to this commit (r75552 & r75553) and the is_ variables have been ported to use $.client in r75593

#Comment by Tim Starling (talk | contribs)   04:48, 5 November 2010

Break your lines at 80-100 columns.

Status & tagging log