Index: trunk/phase3/resources/mediawiki.util/mediawiki.util.test.js |
— | — | @@ -69,8 +69,12 @@ |
70 | 70 | 'function (string)'); |
71 | 71 | mw.test.addTest('\'mediawiki\'.ucFirst()', |
72 | 72 | 'Mediawiki (string)'); |
73 | | - mw.test.addTest('typeof $.fn.enableCheckboxShiftClick', |
| 73 | + mw.test.addTest('typeof String.prototype.escapeRE', |
74 | 74 | 'function (string)'); |
| 75 | + mw.test.addTest('\'.st{e}$st\'.escapeRE()', |
| 76 | + '\\.st\\{e\\}\\$st (string)'); |
| 77 | + mw.test.addTest('typeof $.fn.checkboxShiftClick', |
| 78 | + 'function (string)'); |
75 | 79 | mw.test.addTest('typeof mw.util.rawurlencode', |
76 | 80 | 'function (string)'); |
77 | 81 | mw.test.addTest('mw.util.rawurlencode(\'Test: A&B/Here\')', |
Index: trunk/phase3/resources/mediawiki.util/mediawiki.util.js |
— | — | @@ -26,13 +26,6 @@ |
27 | 27 | this.tooltipAccessKeyPrefix = 'alt-shift-'; |
28 | 28 | } |
29 | 29 | |
30 | | - // Prototype enhancements |
31 | | - if (typeof String.prototype.ucFirst === 'undefined') { |
32 | | - String.prototype.ucFirst = function () { |
33 | | - return this.substr(0, 1).toUpperCase() + this.substr(1, this.length); |
34 | | - }; |
35 | | - } |
36 | | - |
37 | 30 | // Any initialisation after the DOM is ready |
38 | 31 | $(function () { |
39 | 32 | |
— | — | @@ -62,7 +55,7 @@ |
63 | 56 | * |
64 | 57 | * @param String str string to be encoded |
65 | 58 | */ |
66 | | - 'rawurlencode' : function (str) { |
| 59 | + 'rawurlencode' : function( str ) { |
67 | 60 | str = (str + '').toString(); |
68 | 61 | return encodeURIComponent(str).replace(/!/g, '%21').replace(/'/g, '%27').replace(/\(/g, '%28') |
69 | 62 | .replace(/\)/g, '%29').replace(/\*/g, '%2A').replace(/~/g, '%7E'); |
— | — | @@ -75,7 +68,7 @@ |
76 | 69 | * |
77 | 70 | * @param String str string to be encoded |
78 | 71 | */ |
79 | | - 'wikiUrlencode' : function (str) { |
| 72 | + 'wikiUrlencode' : function( str ) { |
80 | 73 | return this.rawurlencode(str).replace(/%20/g, '_').replace(/%3A/g, ':').replace(/%2F/g, '/'); |
81 | 74 | }, |
82 | 75 | |
— | — | @@ -84,7 +77,7 @@ |
85 | 78 | * |
86 | 79 | * @param String str pagename to link to |
87 | 80 | */ |
88 | | - 'getWikilink' : function (str) { |
| 81 | + 'getWikilink' : function( str ) { |
89 | 82 | return wgServer + wgArticlePath.replace('$1', this.wikiUrlencode(str)); |
90 | 83 | }, |
91 | 84 | |
— | — | @@ -94,7 +87,7 @@ |
95 | 88 | * |
96 | 89 | * @param Mixed v the variable to check for empty ness |
97 | 90 | */ |
98 | | - 'isEmpty' : function (v) { |
| 91 | + 'isEmpty' : function( v ) { |
99 | 92 | var key; |
100 | 93 | if (v === "" || v === 0 || v === "0" || v === null || v === false || typeof v === 'undefined') { |
101 | 94 | return true; |
— | — | @@ -119,7 +112,7 @@ |
120 | 113 | * @param String param paramter name |
121 | 114 | * @param String url url to search through (optional) |
122 | 115 | */ |
123 | | - 'getParamValue' : function (param, url) { |
| 116 | + 'getParamValue' : function( param, url ) { |
124 | 117 | url = url ? url : document.location.href; |
125 | 118 | var re = new RegExp('[^#]*[&?]' + param + '=([^&#]*)'); // Get last match, stop at hash |
126 | 119 | var m = re.exec(url); |
— | — | @@ -135,7 +128,7 @@ |
136 | 129 | * @param String str text to escape |
137 | 130 | * @param Bool quotes if true escapes single and double quotes aswell (by default false) |
138 | 131 | */ |
139 | | - 'htmlEscape' : function (str, quotes) { |
| 132 | + 'htmlEscape' : function( str, quotes ) { |
140 | 133 | str = $('<div/>').text(str).html(); |
141 | 134 | if (typeof quotes === 'undefined') { |
142 | 135 | quotes = false; |
— | — | @@ -151,7 +144,7 @@ |
152 | 145 | * |
153 | 146 | * @param String str text to unescape |
154 | 147 | */ |
155 | | - 'htmlUnescape' : function (str) { |
| 148 | + 'htmlUnescape' : function( str ) { |
156 | 149 | return $('<div/>').html(str).text(); |
157 | 150 | }, |
158 | 151 | |
— | — | @@ -170,19 +163,19 @@ |
171 | 164 | * |
172 | 165 | * @param Mixed nodeList jQuery object, or array of elements |
173 | 166 | */ |
174 | | - 'updateTooltipAccessKeys' : function (nodeList) { |
| 167 | + 'updateTooltipAccessKeys' : function( nodeList ) { |
175 | 168 | var $nodes; |
176 | 169 | if (nodeList instanceof jQuery) { |
177 | 170 | $nodes = nodeList; |
178 | 171 | } else if (nodeList) { |
179 | 172 | $nodes = $(nodeList); |
180 | 173 | } else { |
181 | | - // Rather than scanning all links, just |
182 | | - $('#column-one a, #mw-head a, #mw-panel a, #p-logo a'); |
| 174 | + // Rather than scanning all links, just the elements that contain the relevant links |
| 175 | + this.updateTooltipAccessKeys( $('#column-one a, #mw-head a, #mw-panel a, #p-logo a') ); |
183 | 176 | |
184 | 177 | // these are rare enough that no such optimization is needed |
185 | | - this.updateTooltipAccessKeys($('input')); |
186 | | - this.updateTooltipAccessKeys($('label')); |
| 178 | + this.updateTooltipAccessKeys( $('input') ); |
| 179 | + this.updateTooltipAccessKeys( $('label') ); |
187 | 180 | return; |
188 | 181 | } |
189 | 182 | |
— | — | @@ -223,11 +216,13 @@ |
224 | 217 | * |
225 | 218 | * @return Node the DOM node of the new item (a LI element, or A element for older skins) or null |
226 | 219 | */ |
227 | | - 'addPortletLink' : function (portlet, href, text, id, tooltip, accesskey, nextnode) { |
| 220 | + 'addPortletLink' : function( portlet, href, text, id, tooltip, accesskey, nextnode ) { |
| 221 | + |
| 222 | + // Setup the anchor tag |
228 | 223 | var $link = $('<a />').attr('href', href).text(text); |
229 | 224 | |
230 | | - // Some skins don't have portlets |
231 | | - // Just add it to the bottom of their 'sidebar' element ignoring the specified portlet target |
| 225 | + // Some skins don't have any portlets |
| 226 | + // just add it to the bottom of their 'sidebar' element as a fallback |
232 | 227 | switch (skin) { |
233 | 228 | case 'standard' : |
234 | 229 | case 'cologneblue' : |
— | — | @@ -236,30 +231,41 @@ |
237 | 232 | case 'nostalgia' : |
238 | 233 | $("#searchform").before($link).before(' | '); |
239 | 234 | return $link.get(0); |
240 | | - default : // chick, modern, monobook, myskin, simple, vector... |
| 235 | + default : // Skins like chick, modern, monobook, myskin, simple, vector... |
241 | 236 | |
| 237 | + // Select the specified portlet |
242 | 238 | var $portlet = $('#' + portlet); |
243 | 239 | if ($portlet.length === 0) { |
244 | 240 | return null; |
245 | 241 | } |
| 242 | + // Select the first (most likely only) unordered list inside the portlet |
246 | 243 | var $ul = $portlet.find('ul').eq(0); |
| 244 | + |
| 245 | + // If it didn't have an unordered list yet, create it |
247 | 246 | if ($ul.length === 0) { |
| 247 | + // If there's no <div> inside, append it to the portlet directly |
248 | 248 | if ($portlet.find('div').length === 0) { |
249 | | - $portlet.append('<ul />'); |
| 249 | + $portlet.append('<ul/>'); |
250 | 250 | } else { |
251 | | - $portlet.find('div').eq(-1).append('<ul />'); |
| 251 | + // otherwise if there's a div (such as div.body or div.pBody) append the <ul> to last (most likely only) div |
| 252 | + $portlet.find('div').eq(-1).append('<ul/>'); |
252 | 253 | } |
| 254 | + // Select the created element |
253 | 255 | $ul = $portlet.find('ul').eq(0); |
254 | 256 | } |
| 257 | + // Just in case.. |
255 | 258 | if ($ul.length === 0) { |
256 | 259 | return null; |
257 | 260 | } |
258 | 261 | |
259 | | - // unhide portlet if it was hidden before |
| 262 | + // Unhide portlet if it was hidden before |
260 | 263 | $portlet.removeClass('emptyPortlet'); |
261 | 264 | |
| 265 | + // Wrap the anchor tag in a <span> and create a list item for it |
| 266 | + // and back up the selector to the list item |
262 | 267 | var $item = $link.wrap('<li><span /></li>').parent().parent(); |
263 | 268 | |
| 269 | + // Implement the properties passed to the function |
264 | 270 | if (id) { |
265 | 271 | $item.attr('id', id); |
266 | 272 | } |
Index: trunk/phase3/resources/mediawiki/mediawiki.js |
— | — | @@ -22,6 +22,25 @@ |
23 | 23 | } |
24 | 24 | |
25 | 25 | /* |
| 26 | + * Prototype enhancements |
| 27 | + */ |
| 28 | + |
| 29 | +// Capitalize the first character of the given string |
| 30 | +if ( typeof String.prototype.ucFirst === 'undefined' ) { |
| 31 | + String.prototype.ucFirst = function() { |
| 32 | + return this.substr(0, 1).toUpperCase() + this.substr(1, this.length); |
| 33 | + }; |
| 34 | +} |
| 35 | + |
| 36 | +// Escape all RegExp special characters such that the result can be safely used |
| 37 | +// in a RegExp as a literal. |
| 38 | +if ( typeof String.prototype.escapeRE === 'undefined' ) { |
| 39 | + String.prototype.escapeRE = function() { |
| 40 | + return this.replace (/([\\{}()|.?*+^$\[\]])/g, "\\$1"); |
| 41 | + }; |
| 42 | +} |
| 43 | + |
| 44 | +/* |
26 | 45 | * Core MediaWiki JavaScript Library |
27 | 46 | */ |
28 | 47 | |