eb0893b5838ba5de2e228a4346d046d7a5a2e4b6
[platal.git] / htdocs / javascript / core.js
1 /***************************************************************************
2 * Copyright (C) 2003-2011 Polytechnique.org *
3 * http://opensource.polytechnique.org/ *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the Free Software *
17 * Foundation, Inc., *
18 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
19 ***************************************************************************/
20
21 // {{{ Assertion
22
23 // }}}
24 // {{{ jQuery object extension
25
26 (function($) {
27 var assert = function(condition, text) {
28 if ($.isFunction(condition)) {
29 condition = condition();
30 }
31 if (condition) {
32 return this;
33 }
34 if (!text) {
35 throw "Assertion failed";
36 } else {
37 throw "Assertion failed: " + text;
38 }
39 };
40
41 var ajaxParams = function(onSuccess, onError, extraParameters) {
42 return $.extend({
43 success: function(data, textStatus, xhr) {
44 if (textStatus === 'success') {
45 if (onSuccess) {
46 onSuccess(data, textStatus, xhr);
47 }
48 } else if (textStatus === 'error') {
49 if (onError) {
50 onError(data, textStatus, xhr);
51 } else {
52 alert("Une error s'est produite lors du traitement de la requête.\n"
53 + "Ta session a peut-être expiré");
54 }
55 }
56 }
57 }, extraParameters);
58 };
59
60 /* Add new functions to jQuery namesapce */
61 $.extend({
62 xapiVersion: '1',
63
64 plURL: (function() {
65 var base;
66 return function(url) {
67 if (url.startsWith('http', true)) {
68 return url;
69 }
70 if (typeof base === 'undefined') {
71 base = $('head base');
72 if (base.length > 0) {
73 base = base.attr('href');
74 if (!base.endsWith('/')) {
75 base += '/';
76 }
77 } else {
78 base = '';
79 }
80 }
81 return base + url;
82 };
83 }()),
84
85 /* The goal of the following functions is to provide an AJAX API that
86 * take a different callback in case of HTTP success code (2XX) and in
87 * other cases.
88 */
89
90 xajax: function(source, method, data, onSuccess, onError, type) {
91 /* Shift argument */
92 if ($.isFunction(data)) {
93 type = type || onError;
94 onError = onSuccess;
95 onSuccess = data;
96 data = null;
97 }
98 if (onError && !$.isFunction(onError)) {
99 type = type || onError;
100 onError = null;
101 }
102
103 return $.ajax(ajaxParams(onSuccess, onError, {
104 url: $.plURL(source),
105 type: method,
106 data : data,
107 dataType: type
108 }));
109 },
110
111 xapi: function(apicall, payload, onSuccess, onError) {
112 if ($.isFunction(payload)) {
113 onError = onSuccess;
114 onSuccess = payload;
115 }
116
117 return $.ajax(ajaxParams(onSuccess, onError, {
118 url: $.plURL('api/' + $.xapiVersion + '/' + apicall),
119 type: 'POST',
120 data: JSON.stringify(payload),
121 dataType: 'json',
122 contentType: 'text/javascript'
123 }));
124 },
125
126 xget: function(source, data, onSuccess, onError, type) {
127 return $.xajax(source, 'GET', data, onSuccess, onError, type);
128 },
129
130 xgetJSON: function(source, data, onSuccess, onError) {
131 return $.xget(source, data, onSuccess, onError, 'json');
132 },
133
134 xgetScript: function(source, onSuccess, onError) {
135 return $.xget(source, null, onSuccess, onError, 'script');
136 },
137
138 xgetText: function(source, data, onSuccess, onError) {
139 return $.xget(source, data, onSuccess, onError, 'text');
140 },
141
142 xpost: function(source, data, onSuccess, onError, type) {
143 return $.xajax(source, 'POST', data, onSuccess, onError, type);
144 },
145
146 closeOnEsc: function() {
147 return $(window).keydown(function (e) {
148 if (e.keyCode === 27) {
149 window.close();
150 }
151 });
152 },
153
154 dynPost: function(action, key, value) {
155 var values;
156 var k;
157 var form;
158
159 if (!$.isArray(key)) {
160 values = { };
161 values[key] = value;
162 } else {
163 values = key;
164 }
165 form = $('<form>', {
166 action: action,
167 method: 'post'
168 });
169 for (k in values) {
170 if (values.hasOwnProperty(k)) {
171 $('<input>', {
172 type: 'hidden',
173 name: k,
174 value: values[k]
175 }).appendTo(form);
176 }
177 }
178 $('body').appendTo(form);
179 form.submit();
180 },
181
182 assert: assert
183 });
184
185 /* Add new functions to jQuery objects */
186 $.fn.extend({
187 tmpMessage: function(message, success) {
188 if (success) {
189 this.html("<img src='images/icons/wand.gif' alt='' /> " + message)
190 .css('color', 'green');
191 } else {
192 this.html("<img src='images/icons/error.gif' alt='' /> " + message)
193 .css('color', 'red');
194 }
195 return this.css('fontWeight', 'bold')
196 .show()
197 .delay(1000)
198 .fadeOut(500);
199 },
200
201 updateHtml: function(source, callback) {
202 var elements = this;
203 function handler(data) {
204 elements.html(data);
205 if (callback) {
206 callback(data);
207 }
208 }
209 $.xget(source, handler, 'text');
210 return this;
211 },
212
213 successMessage: function(source, message) {
214 var elements = this;
215 $.xget(source, function() {
216 elements.tmpMessage(message, true);
217 });
218 return this;
219 },
220
221 wiki: function(text, withTitle) {
222 if (!text) {
223 return this.html('');
224 }
225 var url = 'wiki_preview';
226 if (!withTitle) {
227 url += '/notitile';
228 }
229 var $this = this;
230 $.post(url, { text: text },
231 function (data) {
232 $this.html(data);
233 }, 'text');
234 return this;
235 },
236
237 popWin: function(w, h) {
238 return this.click(function() {
239 window.open(this.href, '_blank',
240 'toolbar=0,location=0,directories=0,status=0,'
241 +'menubar=0,scrollbars=1,resizable=1,'
242 +'width='+w+',height='+h);
243 return false;
244 });
245 },
246
247 assert: assert,
248
249 assertLength: function(len) {
250 return this.assert(function() {
251 return $(this).length === len;
252 });
253 },
254
255 assertId: function(id) {
256 return this.assert(function() {
257 return $(this).attr('id') === id;
258 });
259 },
260
261 assertClass: function(clazz) {
262 return this.assert(function() {
263 return $(this).hasClass(clazz);
264 });
265 }
266 });
267 }(jQuery));
268
269 // }}}
270 // {{{ function RegExp.escape()
271
272 RegExp.escape = function(text) {
273 if (!arguments.callee.sRE) {
274 var specials = [
275 '/', '.', '*', '+', '?', '|',
276 '(', ')', '[', ']', '{', '}',
277 '\\', '^' , '$'
278 ];
279 arguments.callee.sRE = new RegExp(
280 '(\\' + specials.join('|\\') + ')', 'g'
281 );
282 }
283 return text.replace(arguments.callee.sRE, '\\$1');
284 };
285
286 // }}}
287 // {{{ String extension
288
289 String.prototype.startsWith = function(str, caseInsensitive) {
290 var cmp = this;
291
292 if (str.length > this.length) {
293 return false;
294 }
295 if (caseInsensitive) {
296 str = str.toLowerCase();
297 cmp = cmp.toLowerCase();
298 }
299 return cmp.substr(0, str.length) === str;
300 };
301
302 String.prototype.endsWith = function(str, caseInsensitive) {
303 var cmp = this;
304
305 if (str.length > this.length) {
306 return false;
307 }
308 if (caseInsensitive) {
309 str = str.toLowerCase();
310 cmp = cmp.toLowerCase();
311 }
312 return cmp.substr(cmp.length - str.length, str.length) === str;
313 };
314
315 String.prototype.htmlEntities = function() {
316 return this.replace(/&/g,'&amp;')
317 .replace(new RegExp('<','g'),'&lt;')
318 .replace(/>/g,'&gt;');
319 };
320
321 String.prototype.contains = function(str, caseInsensitive) {
322 var cmp = this;
323 if (str.length > this.length) {
324 return false;
325 }
326 if (caseInsensitive) {
327 str = str.toLowerCase();
328 cmp = cmp.toLowerCase();
329 }
330 return cmp.indexOf(str) >= 0;
331 };
332
333 // }}}
334 // {{{ PmWiki decoding
335
336 Nix = {
337 map: null,
338
339 convert: function(a) {
340 var s = '';
341 Nix.init();
342 for (i = 0; i < a.length ; i++) {
343 var b = a.charAt(i);
344 s += ((b >= 'A' && b <= 'Z') || (b >= 'a' && b <= 'z') ? Nix.map[b] : b);
345 }
346 return s;
347 },
348
349 init: function() {
350 var map;
351 var s;
352
353 if (Nix.map !== null) {
354 return;
355 }
356 map = [ ];
357 s = 'abcdefghijklmnopqrstuvwxyz';
358 for (i = 0; i < s.length; i++) {
359 map[s.charAt(i)] = s.charAt((i+13) % 26);
360 }
361 for (i=0; i< s.length; i++) {
362 map[s.charAt(i).toUpperCase()] = s.charAt((i+13) % 26).toUpperCase();
363 }
364 Nix.map = map;
365 },
366
367 decode: function(a) {
368 document.write(Nix.convert(a));
369 }
370 };
371
372 // }}}
373 // {{{ preview wiki
374
375 function previewWiki(idFrom, idTo, withTitle, idShow)
376 {
377 $('#' + idTo).wiki($('#' + idFrom).val(), withTitle);
378 if (idShow) {
379 $('#' + idShow).show();
380 }
381 }
382
383 // }}}
384
385 // vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8: