adding begin of mediaWiki.util and loading it by default + trailing whitespace cleanu...
[lhc/web/wiklou.git] / resources / mediawiki / mediawiki.util.js
1 /*jslint white: true, browser: true, undef: true, nomen: true, eqeqeq: true, plusplus: true, bitwise: true, regexp: true, newcap: true */
2 /*
3 * Utilities
4 */
5
6 (function ($, mw) {
7
8 mediaWiki.util = {
9
10 /* Initialisation */
11 'initialised' : false,
12 'init' : function () {
13 if (this.initialised === false){
14 this.initialised = true;
15
16
17 // Set tooltipAccessKeyPrefix
18 if ( is_opera ) {
19 this.tooltipAccessKeyPrefix = 'shift-esc-';
20 } else if ( is_chrome ) {
21 this.tooltipAccessKeyPrefix = is_chrome_mac ? 'ctrl-option-' : 'alt-';
22 } else if ( !is_safari_win && is_safari && webkit_version > 526 ) {
23 this.tooltipAccessKeyPrefix = 'ctrl-alt-';
24 } else if ( !is_safari_win && ( is_safari
25 || clientPC.indexOf('mac') != -1
26 || clientPC.indexOf('konqueror') != -1 ) ) {
27 this.tooltipAccessKeyPrefix = 'ctrl-';
28 } else if ( is_ff2 ) {
29 this.tooltipAccessKeyPrefix = 'alt-shift-';
30 }
31
32
33 return true;
34 }
35 return false;
36 },
37
38 /* Main body */
39
40 /**
41 * Encodes the string like PHP's rawurlencode
42 *
43 * @param String str string to be encoded
44 */
45 'rawurlencode' : function (str) {
46 str = (str + '').toString();
47 return encodeURIComponent(str).replace(/!/g, '%21').replace(/'/g, '%27').replace(/\(/g, '%28')
48 .replace(/\)/g, '%29').replace(/\*/g, '%2A').replace(/~/g, '%7E');
49 },
50
51 /**
52 * Encode pagetitles for use in a URL
53 * We want / and : to be included as literal characters in our title URLs
54 * as they otherwise fatally break the title
55 *
56 * @param String str string to be encoded
57 */
58 'wikiUrlencode' : function (str) {
59 return this.rawurlencode(str).replace(/%20/g, '_').replace(/%3A/g, ':').replace(/%2F/g, '/');
60 },
61
62
63 /**
64 * Grabs the url parameter value for the given parameter
65 * Returns null if not found
66 *
67 * @param String param paramter name
68 * @param String url url to search through (optional)
69 */
70 'getParamValue' : function (param, url) {
71 url = url ? url : document.location.href;
72 var re = new RegExp('[^#]*[&?]' + param + '=([^&#]*)'); // Get last match, stop at hash
73 var m = re.exec(url);
74 if (m && m.length > 1) {
75 return decodeURIComponent(m[1]);
76 }
77 return null;
78 },
79
80 /**
81 * Converts special characters to their HTML entities
82 *
83 * @param String str text to escape
84 * @param Bool quotes if true escapes single and double quotes aswell (by default false)
85 */
86 'htmlEscape' : function (str, quotes) {
87 str = $('<div/>').text(str).html();
88 if (typeof quotes === 'undefined') {
89 quotes = false;
90 }
91 if (quotes === true) {
92 str = str.replace(/'/g, '&#039;').replace(/"/g, '&quot;');
93 }
94 return str;
95 },
96
97 /**
98 * Converts HTML entities back to text
99 *
100 * @param String str text to unescape
101 */
102 'htmlUnescape' : function (str) {
103 return $('<div/>').html(str).text();
104 },
105
106 // Access key prefix
107 // will be re-defined based on browser/operating system detection in mw.util.init()
108 'tooltipAccessKeyPrefix' : 'alt-',
109
110 // Regex to match accesskey tooltips
111 'tooltipAccessKeyRegexp': /\[(ctrl-)?(alt-)?(shift-)?(esc-)?(.)\]$/,
112
113 /**
114 * Add the appropriate prefix to the accesskey shown in the tooltip.
115 * If the nodeList parameter is given, only those nodes are updated;
116 * otherwise, all the nodes that will probably have accesskeys by
117 * default are updated.
118 *
119 * @param Mixed nodeList jQuery object, or array of elements
120 */
121 'updateTooltipAccessKeys' : function (nodeList) {
122 var $nodes;
123 if (nodeList instanceof jQuery) {
124 $nodes = nodeList;
125 } else if (nodeList) {
126 $nodes = $(nodeList);
127 } else {
128 // Rather than scanning all links, just
129 $("#column-one a, #mw-head a, #mw-panel a, #p-logo a");
130
131 // these are rare enough that no such optimization is needed
132 this.updateTooltipAccessKeys($('input'));
133 this.updateTooltipAccessKeys($('label'));
134 return;
135 }
136
137 $nodes.each(function (i) {
138 var tip = $(this).attr('title');
139 if (!!tip && mw.util.tooltipAccessKeyRegexp.exec(tip)) {
140 tip = tip.replace(mw.util.tooltipAccessKeyRegexp, '[' + tooltipAccessKeyPrefix + "$5]");
141 $(this).attr('title', tip);
142 }
143 });
144 },
145
146
147 /**
148 * Add a link to a portlet menu on the page, such as:
149 *
150 * p-cactions (Content actions), p-personal (Personal tools), p-navigation (Navigation), p-tb (Toolbox)
151 *
152 * The first three paramters are required, others are optionals. Though
153 * providing an id and tooltip is recommended.
154 *
155 * By default the new link will be added to the end of the list. To add the link before a given existing item,
156 * pass the DOM node (document.getElementById('foobar') or the jQuery-selector ('#foobar') of that item.
157 *
158 * @example mw.util.addPortletLink('p-tb', 'http://mediawiki.org/', 'MediaWiki.org', 't-mworg', 'Go to MediaWiki.org ', 'm', '#t-print')
159 *
160 * @param String portlet id of the target portlet ("p-cactions" or "p-personal" etc.)
161 * @param String href link URL
162 * @param String text link text (will be automatically lowercased by CSS for p-cactions in Monobook)
163 * @param String id id of the new item, should be unique and preferably have the appropriate prefix ("ca-", "pt-", "n-" or "t-")
164 * @param String tooltip text to show when hovering over the link, without accesskey suffix
165 * @param String accesskey accesskey to activate this link (one character, try to avoid conflicts)
166 * @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
167 *
168 * @return Node the DOM node of the new item (a LI element) or null
169 */
170 'addPortletLink' : function (portlet, href, text, id, tooltip, accesskey, nextnode) {
171 var $portlet = $('#' + portlet);
172 if ($portlet.length === 0) {
173 return null;
174 }
175 var $ul = $portlet.find('ul').eq(0);
176 if ($ul.length === 0) {
177 if ($portlet.find('div').length === 0) {
178 $portlet.append('<ul />');
179 } else {
180 $portlet.find('div').eq(-1).append('<ul />');
181 }
182 $ul = $portlet.find('ul').eq(0);
183 }
184 if ($ul.length === 0) {
185 return null;
186 }
187
188 // unhide portlet if it was hidden before
189 $portlet.removeClass('emptyPortlet');
190
191 var $link = $('<a />').attr('href', href).text(text);
192 var $item = $link.wrap('<li><span /></li>').parent().parent();
193
194 if (id) {
195 $item.attr('id', id);
196 }
197 if (accesskey) {
198 $link.attr('accesskey', accesskey);
199 tooltip += ' [' + accesskey + ']';
200 }
201 if (tooltip) {
202 $link.attr('title', tooltip);
203 }
204 if (accesskey && tooltip) {
205 this.updateTooltipAccessKeys($link);
206 }
207
208 // Append using DOM-element passing
209 if (nextnode && nextnode.parentNode == $ul.get(0)) {
210 $(nextnode).before($item);
211 } else {
212 // If the jQuery selector isn't found within the <ul>, just append it at the end
213 if ($ul.find(nextnode).length === 0) {
214 $ul.append($item);
215 } else {
216 // Append using jQuery CSS selector
217 $ul.find(nextnode).eq(0).before($item);
218 }
219 }
220
221 return $item.get(0);
222 }
223
224 };
225
226 })(jQuery, mediaWiki);
227
228 mediaWiki.util.init();