|
1 /* MochiKit -> jQuery compatibility module */ |
|
2 |
|
3 function forEach(array, func) { |
|
4 for (var i=0, length=array.length; i<length; i++) { |
|
5 func(array[i]); |
|
6 } |
|
7 } |
|
8 |
|
9 function getElementsByTagAndClassName(tag, klass, root) { |
|
10 root = root || document; |
|
11 // FIXME root is not used in this compat implementation |
|
12 return jQuery(tag + '.' + klass); |
|
13 } |
|
14 |
|
15 function map(func, array) { |
|
16 // XXX jQUery tends to simplify lists with only one element : |
|
17 // >>> y = ['a:b:c'] |
|
18 // >>> jQuery.map(y, function(y) { return y.split(':');}) |
|
19 // ["a", "b", "c"] |
|
20 // where I would expect : |
|
21 // [ ["a", "b", "c"] ] |
|
22 // return jQuery.map(array, func); |
|
23 var result = []; |
|
24 for (var i=0,length=array.length;i<length;i++) { |
|
25 result.push(func(array[i])); |
|
26 } |
|
27 return result; |
|
28 } |
|
29 |
|
30 function findValue(array, element) { |
|
31 return jQuery.inArray(element, array); |
|
32 } |
|
33 |
|
34 function filter(func, array) { |
|
35 return jQuery.grep(array, func); |
|
36 } |
|
37 |
|
38 function noop() {} |
|
39 |
|
40 function addElementClass(node, klass) { |
|
41 jQuery(node).addClass(klass); |
|
42 } |
|
43 |
|
44 function toggleElementClass(node, klass) { |
|
45 jQuery(node).toggleClass(klass); |
|
46 } |
|
47 |
|
48 function removeElementClass(node, klass) { |
|
49 jQuery(node).removeClass(klass); |
|
50 } |
|
51 |
|
52 hasElementClass = jQuery.className.has |
|
53 |
|
54 |
|
55 function partial(func) { |
|
56 var args = sliceList(arguments, 1); |
|
57 return function() { |
|
58 return func.apply(null, merge(args, arguments)); |
|
59 } |
|
60 } |
|
61 |
|
62 |
|
63 function log() { |
|
64 // XXX dummy implementation |
|
65 // console.log.apply(arguments); ??? |
|
66 var args = []; |
|
67 for (var i=0; i<arguments.length; i++) { |
|
68 args.push(arguments[i]); |
|
69 } |
|
70 if (typeof(window) != "undefined" && window.console |
|
71 && window.console.log) { |
|
72 window.console.log(args.join(' ')); |
|
73 } |
|
74 } |
|
75 |
|
76 function getNodeAttribute(node, attribute) { |
|
77 return jQuery(node).attr(attribute); |
|
78 } |
|
79 |
|
80 function isArray(it){ // taken from dojo |
|
81 return it && (it instanceof Array || typeof it == "array"); |
|
82 } |
|
83 |
|
84 function isString(it){ // taken from dojo |
|
85 return !!arguments.length && it != null && (typeof it == "string" || it instanceof String); |
|
86 } |
|
87 |
|
88 |
|
89 function isArrayLike(it) { // taken from dojo |
|
90 return (it && it !== undefined && |
|
91 // keep out built-in constructors (Number, String, ...) which have length |
|
92 // properties |
|
93 !isString(it) && !jQuery.isFunction(it) && |
|
94 !(it.tagName && it.tagName.toLowerCase() == 'form') && |
|
95 (isArray(it) || isFinite(it.length))); |
|
96 } |
|
97 |
|
98 |
|
99 function getNode(node) { |
|
100 if (typeof(node) == 'string') { |
|
101 return document.getElementById(node); |
|
102 } |
|
103 return node; |
|
104 } |
|
105 |
|
106 /* safe version of jQuery('#nodeid') because we use ':' in nodeids |
|
107 * which messes with jQuery selection mechanism |
|
108 */ |
|
109 function jqNode(node) { |
|
110 node = getNode(node); |
|
111 if (node) { |
|
112 return jQuery(node); |
|
113 } |
|
114 return null; |
|
115 } |
|
116 |
|
117 function evalJSON(json) { // trust source |
|
118 return eval("(" + json + ")"); |
|
119 } |
|
120 |
|
121 function urlEncode(str) { |
|
122 if (typeof(encodeURIComponent) != "undefined") { |
|
123 return encodeURIComponent(str).replace(/\'/g, '%27'); |
|
124 } else { |
|
125 return escape(str).replace(/\+/g, '%2B').replace(/\"/g,'%22').rval.replace(/\'/g, '%27'); |
|
126 } |
|
127 } |
|
128 |
|
129 function swapDOM(dest, src) { |
|
130 dest = getNode(dest); |
|
131 var parent = dest.parentNode; |
|
132 if (src) { |
|
133 src = getNode(src); |
|
134 parent.replaceChild(src, dest); |
|
135 } else { |
|
136 parent.removeChild(dest); |
|
137 } |
|
138 return src; |
|
139 } |
|
140 |
|
141 function replaceChildNodes(node/*, nodes...*/) { |
|
142 var elem = getNode(node); |
|
143 arguments[0] = elem; |
|
144 var child; |
|
145 while ((child = elem.firstChild)) { |
|
146 elem.removeChild(child); |
|
147 } |
|
148 if (arguments.length < 2) { |
|
149 return elem; |
|
150 } else { |
|
151 for (var i=1; i<arguments.length; i++) { |
|
152 elem.appendChild(arguments[i]); |
|
153 } |
|
154 return elem; |
|
155 } |
|
156 } |
|
157 |
|
158 update = jQuery.extend; |
|
159 |
|
160 |
|
161 function createDomFunction(tag) { |
|
162 |
|
163 function builddom(params, children) { |
|
164 var node = document.createElement(tag); |
|
165 for (key in params) { |
|
166 var value = params[key]; |
|
167 if (key.substring(0, 2) == 'on') { |
|
168 // this is an event handler definition |
|
169 if (typeof value == 'string') { |
|
170 // litteral definition |
|
171 value = new Function(value); |
|
172 } |
|
173 node[key] = value; |
|
174 } else { // normal node attribute |
|
175 node.setAttribute(key, params[key]); |
|
176 } |
|
177 } |
|
178 if (children) { |
|
179 if (!isArrayLike(children)) { |
|
180 children = [children]; |
|
181 for (var i=2; i<arguments.length; i++) { |
|
182 var arg = arguments[i]; |
|
183 if (isArray(arg)) { |
|
184 children = merge(children, arg); |
|
185 } else { |
|
186 children.push(arg); |
|
187 } |
|
188 } |
|
189 } |
|
190 for (var i=0; i<children.length; i++) { |
|
191 var child = children[i]; |
|
192 if (typeof child == "string" || typeof child == "number") { |
|
193 child = document.createTextNode(child); |
|
194 } |
|
195 node.appendChild(child); |
|
196 } |
|
197 } |
|
198 return node; |
|
199 } |
|
200 return builddom; |
|
201 } |
|
202 |
|
203 A = createDomFunction('a'); |
|
204 BUTTON = createDomFunction('button'); |
|
205 BR = createDomFunction('br'); |
|
206 CANVAS = createDomFunction('canvas'); |
|
207 DD = createDomFunction('dd'); |
|
208 DIV = createDomFunction('div'); |
|
209 DL = createDomFunction('dl'); |
|
210 DT = createDomFunction('dt'); |
|
211 FIELDSET = createDomFunction('fieldset'); |
|
212 FORM = createDomFunction('form'); |
|
213 H1 = createDomFunction('H1'); |
|
214 H2 = createDomFunction('H2'); |
|
215 H3 = createDomFunction('H3'); |
|
216 H4 = createDomFunction('H4'); |
|
217 H5 = createDomFunction('H5'); |
|
218 H6 = createDomFunction('H6'); |
|
219 HR = createDomFunction('hr'); |
|
220 IMG = createDomFunction('img'); |
|
221 INPUT = createDomFunction('input'); |
|
222 LABEL = createDomFunction('label'); |
|
223 LEGEND = createDomFunction('legend'); |
|
224 LI = createDomFunction('li'); |
|
225 OL = createDomFunction('ol'); |
|
226 OPTGROUP = createDomFunction('optgroup'); |
|
227 OPTION = createDomFunction('option'); |
|
228 P = createDomFunction('p'); |
|
229 PRE = createDomFunction('pre'); |
|
230 SELECT = createDomFunction('select'); |
|
231 SPAN = createDomFunction('span'); |
|
232 STRONG = createDomFunction('strong'); |
|
233 TABLE = createDomFunction('table'); |
|
234 TBODY = createDomFunction('tbody'); |
|
235 TD = createDomFunction('td'); |
|
236 TEXTAREA = createDomFunction('textarea'); |
|
237 TFOOT = createDomFunction('tfoot'); |
|
238 TH = createDomFunction('th'); |
|
239 THEAD = createDomFunction('thead'); |
|
240 TR = createDomFunction('tr'); |
|
241 TT = createDomFunction('tt'); |
|
242 UL = createDomFunction('ul'); |
|
243 |
|
244 // cubicweb specific |
|
245 IFRAME = createDomFunction('iframe'); |
|
246 |
|
247 // dummy ultra minimalist implementation on deferred for jQuery |
|
248 function Deferred() { |
|
249 this.__init__(this); |
|
250 } |
|
251 |
|
252 jQuery.extend(Deferred.prototype, { |
|
253 __init__: function() { |
|
254 this.onSuccess = []; |
|
255 this.onFailure = []; |
|
256 this.req = null; |
|
257 }, |
|
258 |
|
259 addCallback: function(callback) { |
|
260 this.onSuccess.push([callback, sliceList(arguments, 1)]); |
|
261 return this; |
|
262 }, |
|
263 |
|
264 addErrback: function(callback) { |
|
265 this.onFailure.push([callback, sliceList(arguments, 1)]); |
|
266 return this; |
|
267 }, |
|
268 |
|
269 success: function(result) { |
|
270 try { |
|
271 for (var i=0; i<this.onSuccess.length; i++) { |
|
272 var callback = this.onSuccess[i][0]; |
|
273 var args = merge([result, this.req], this.onSuccess[i][1]); |
|
274 callback.apply(null, args); |
|
275 } |
|
276 } catch (error) { |
|
277 this.error(this.xhr, null, error); |
|
278 } |
|
279 }, |
|
280 |
|
281 error: function(xhr, status, error) { |
|
282 for (var i=0; i<this.onFailure.length; i++) { |
|
283 var callback = this.onFailure[i][0]; |
|
284 var args = merge([error, this.req], this.onFailure[i][1]); |
|
285 callback.apply(null, args); |
|
286 } |
|
287 } |
|
288 |
|
289 }); |
|
290 |
|
291 |
|
292 /** @id MochiKit.DateTime.toISOTime */ |
|
293 toISOTime = function (date, realISO/* = false */) { |
|
294 if (typeof(date) == "undefined" || date === null) { |
|
295 return null; |
|
296 } |
|
297 var hh = date.getHours(); |
|
298 var mm = date.getMinutes(); |
|
299 var ss = date.getSeconds(); |
|
300 var lst = [ |
|
301 ((realISO && (hh < 10)) ? "0" + hh : hh), |
|
302 ((mm < 10) ? "0" + mm : mm), |
|
303 ((ss < 10) ? "0" + ss : ss) |
|
304 ]; |
|
305 return lst.join(":"); |
|
306 }; |
|
307 |
|
308 _padTwo = function (n) { |
|
309 return (n > 9) ? n : "0" + n; |
|
310 }; |
|
311 |
|
312 /** @id MochiKit.DateTime.toISODate */ |
|
313 toISODate = function (date) { |
|
314 if (typeof(date) == "undefined" || date === null) { |
|
315 return null; |
|
316 } |
|
317 return [ |
|
318 date.getFullYear(), |
|
319 _padTwo(date.getMonth() + 1), |
|
320 _padTwo(date.getDate()) |
|
321 ].join("-"); |
|
322 }; |
|
323 |
|
324 |
|
325 /** @id MochiKit.DateTime.toISOTimeStamp */ |
|
326 toISOTimestamp = function (date, realISO/* = false*/) { |
|
327 if (typeof(date) == "undefined" || date === null) { |
|
328 return null; |
|
329 } |
|
330 var sep = realISO ? "T" : " "; |
|
331 var foot = realISO ? "Z" : ""; |
|
332 if (realISO) { |
|
333 date = new Date(date.getTime() + (date.getTimezoneOffset() * 60000)); |
|
334 } |
|
335 return toISODate(date) + sep + toISOTime(date, realISO) + foot; |
|
336 }; |
|
337 |
|
338 |
|
339 function loadJSON(url, data, type, dataType) { |
|
340 d = new Deferred(); |
|
341 jQuery.ajax({ |
|
342 url: url, |
|
343 type: type, |
|
344 data: data, |
|
345 dataType: dataType, |
|
346 |
|
347 beforeSend: function(xhr) { |
|
348 d.req = xhr; |
|
349 }, |
|
350 |
|
351 success: function(data, status) { |
|
352 d.success(data); |
|
353 }, |
|
354 |
|
355 error: function(xhr, status, error) { |
|
356 error = evalJSON(xhr.responseText); |
|
357 d.error(xhr, status, error['reason']); |
|
358 } |
|
359 }); |
|
360 return d; |
|
361 } |
|
362 |
|
363 /* depth-first implementation of the nodeWalk function found |
|
364 * in MochiKit.Base |
|
365 * cf. http://mochikit.com/doc/html/MochiKit/Base.html#fn-nodewalk |
|
366 */ |
|
367 function nodeWalkDepthFirst(node, visitor) { |
|
368 var children = visitor(node); |
|
369 if (children) { |
|
370 for(var i=0; i<children.length; i++) { |
|
371 nodeWalkDepthFirst(children[i], visitor); |
|
372 } |
|
373 } |
|
374 } |
|
375 |
|
376 |
|
377 /* Returns true if all the given Array-like or string arguments are not empty (obj.length > 0) */ |
|
378 function isNotEmpty(obj) { |
|
379 for (var i = 0; i < arguments.length; i++) { |
|
380 var o = arguments[i]; |
|
381 if (!(o && o.length)) { |
|
382 return false; |
|
383 } |
|
384 } |
|
385 return true; |
|
386 } |
|
387 |
|
388 /** this implementation comes from MochiKit */ |
|
389 function formContents(elem/* = document.body */) { |
|
390 var names = []; |
|
391 var values = []; |
|
392 if (typeof(elem) == "undefined" || elem === null) { |
|
393 elem = document.body; |
|
394 } else { |
|
395 elem = getNode(elem); |
|
396 } |
|
397 nodeWalkDepthFirst(elem, function (elem) { |
|
398 var name = elem.name; |
|
399 if (isNotEmpty(name)) { |
|
400 var tagName = elem.tagName.toUpperCase(); |
|
401 if (tagName === "INPUT" |
|
402 && (elem.type == "radio" || elem.type == "checkbox") |
|
403 && !elem.checked |
|
404 ) { |
|
405 return null; |
|
406 } |
|
407 if (tagName === "SELECT") { |
|
408 if (elem.type == "select-one") { |
|
409 if (elem.selectedIndex >= 0) { |
|
410 var opt = elem.options[elem.selectedIndex]; |
|
411 var v = opt.value; |
|
412 if (!v) { |
|
413 var h = opt.outerHTML; |
|
414 // internet explorer sure does suck. |
|
415 if (h && !h.match(/^[^>]+\svalue\s*=/i)) { |
|
416 v = opt.text; |
|
417 } |
|
418 } |
|
419 names.push(name); |
|
420 values.push(v); |
|
421 return null; |
|
422 } |
|
423 // no form elements? |
|
424 names.push(name); |
|
425 values.push(""); |
|
426 return null; |
|
427 } else { |
|
428 var opts = elem.options; |
|
429 if (!opts.length) { |
|
430 names.push(name); |
|
431 values.push(""); |
|
432 return null; |
|
433 } |
|
434 for (var i = 0; i < opts.length; i++) { |
|
435 var opt = opts[i]; |
|
436 if (!opt.selected) { |
|
437 continue; |
|
438 } |
|
439 var v = opt.value; |
|
440 if (!v) { |
|
441 var h = opt.outerHTML; |
|
442 // internet explorer sure does suck. |
|
443 if (h && !h.match(/^[^>]+\svalue\s*=/i)) { |
|
444 v = opt.text; |
|
445 } |
|
446 } |
|
447 names.push(name); |
|
448 values.push(v); |
|
449 } |
|
450 return null; |
|
451 } |
|
452 } |
|
453 if (tagName === "FORM" || tagName === "P" || tagName === "SPAN" |
|
454 || tagName === "DIV" |
|
455 ) { |
|
456 return elem.childNodes; |
|
457 } |
|
458 names.push(name); |
|
459 values.push(elem.value || ''); |
|
460 return null; |
|
461 } |
|
462 return elem.childNodes; |
|
463 }); |
|
464 return [names, values]; |
|
465 } |
|
466 |
|
467 function merge(array1, array2) { |
|
468 var result = []; |
|
469 for (var i=0,length=arguments.length; i<length; i++) { |
|
470 var array = arguments[i]; |
|
471 for (var j=0,alength=array.length; j<alength; j++) { |
|
472 result.push(array[j]); |
|
473 } |
|
474 } |
|
475 return result; |
|
476 } |
|
477 |
|
478 var KEYS = { |
|
479 KEY_ESC: 27, |
|
480 KEY_ENTER: 13 |
|
481 } |
|
482 |
|
483 // XHR = null; |
|
484 // function test() { |
|
485 // var d = loadJSON('http://crater:9876/json?mode=remote&fname=i18n&pageid=xxx&arg=' + jQuery.toJSON(['modify'])); |
|
486 // d = d.addCallback(function (result, xhr) { |
|
487 // XHR = xhr; |
|
488 // log('got ajax result 1' + result + xhr); |
|
489 // log('got ajax result 1' + xhr); |
|
490 // log('got ajax result 1' + xhr + 'arguments =', arguments.length); |
|
491 // }); |
|
492 // d.addCallback(function (x, req, y, z) { |
|
493 // log('callback 2 x =' + x, ' req=', req, 'y =', y, 'z=',z); |
|
494 // }, 12, 13) |
|
495 // d.addErrback(function (error, xhr) { |
|
496 // XHR = xhr; |
|
497 // log('got err', error, ' code =', xhr.status, 'arguments length=', arguments.length); |
|
498 // }) |
|
499 // } |
|
500 |