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