summaryrefslogtreecommitdiff
path: root/frontend/gamma/js/Clipperz/YUI/DomQuery.js
Unidiff
Diffstat (limited to 'frontend/gamma/js/Clipperz/YUI/DomQuery.js') (more/less context) (ignore whitespace changes)
-rw-r--r--frontend/gamma/js/Clipperz/YUI/DomQuery.js714
1 files changed, 714 insertions, 0 deletions
diff --git a/frontend/gamma/js/Clipperz/YUI/DomQuery.js b/frontend/gamma/js/Clipperz/YUI/DomQuery.js
new file mode 100644
index 0000000..4a143ab
--- a/dev/null
+++ b/frontend/gamma/js/Clipperz/YUI/DomQuery.js
@@ -0,0 +1,714 @@
1/*
2
3Copyright 2008-2011 Clipperz Srl
4
5This file is part of Clipperz's Javascript Crypto Library.
6Javascript Crypto Library provides web developers with an extensive
7and efficient set of cryptographic functions. The library aims to
8obtain maximum execution speed while preserving modularity and
9reusability.
10For further information about its features and functionalities please
11refer to http://www.clipperz.com
12
13* Javascript Crypto Library is free software: you can redistribute
14 it and/or modify it under the terms of the GNU Affero General Public
15 License as published by the Free Software Foundation, either version
16 3 of the License, or (at your option) any later version.
17
18* Javascript Crypto Library is distributed in the hope that it will
19 be useful, but WITHOUT ANY WARRANTY; without even the implied
20 warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
21 See the GNU Affero General Public License for more details.
22
23* You should have received a copy of the GNU Affero General Public
24 License along with Javascript Crypto Library. If not, see
25 <http://www.gnu.org/licenses/>.
26
27*/
28
29if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
30if (typeof(Clipperz.YUI) == 'undefined') { Clipperz.YUI = {}; }
31
32
33/*
34 * yui-ext 0.40
35 * Copyright(c) 2006, Jack Slocum.
36 */
37
38/**
39 * @class Clipperz.YUI.DomQuery
40 * Provides high performance selector/xpath processing by compiling queries into reusable functions.
41 * New pseudo classes and matchers can be plugged. It works on HTML and XML documents (if a content node is passed in).
42 * @singleton
43 */
44Clipperz.YUI.DomQuery = function(){
45 var cache = {}, simpleCache = {}, valueCache = {};
46 var nonSpace = /\S/;
47 var trimRe = /^\s*(.*?)\s*$/;
48 var tplRe = /\{(\d+)\}/g;
49 var modeRe = /^(\s?[\/>]\s?|\s|$)/;
50 var clsRes = {};
51
52 function child(p, index){
53 var i = 0;
54 var n = p.firstChild;
55 while(n){
56 if(n.nodeType == 1){
57 i++;
58 if(i == index){
59 return n;
60 }
61 }
62 n = n.nextSibling;
63 }
64 return null;
65 };
66
67 function next(d){
68 var n = d.nextSibling;
69 while(n && n.nodeType != 1){
70 n = n.nextSibling;
71 }
72 return n;
73 };
74
75 function prev(d){
76 var n = d.previousSibling;
77 while(n && n.nodeType != 1){
78 n = n.previousSibling;
79 }
80 return n;
81 };
82
83 function clean(d){
84 var n = d.firstChild, ni = -1;
85 while(n){
86 var nx = n.nextSibling;
87 if(n.nodeType == 3 && !nonSpace.test(n.nodeValue)){
88 d.removeChild(n);
89 }else{
90 n.nodeIndex = ++ni;
91 }
92 n = nx;
93 }
94 return this;
95 };
96
97 function byClassName(c, a, v){
98 if(!v){
99 return c;
100 }
101 var re = clsRes[v];
102 if(!re){
103 re = new RegExp('(?:^|\\s)(?:' + v + ')(?:\\s|$)');
104 clsRes[v] = re;
105 }
106 var r = [];
107 for(var i = 0, ci; ci = c[i]; i++){
108 if(re.test(ci.className)){
109 r[r.length] = ci;
110 }
111 }
112 return r;
113 };
114
115 function convert(c){
116 if(c.slice){
117 return c;
118 }
119 var r = [];
120 for(var i = 0, l = c.length; i < l; i++){
121 r[r.length] = c[i];
122 }
123 return r;
124 };
125
126 function attrValue(n, attr){
127 if(!n.tagName && typeof n.length != 'undefined'){
128 n = n[0];
129 }
130 if(!n){
131 return null;
132 }
133 if(attr == 'for'){
134 return n.htmlFor;
135 }
136 if(attr == 'class' || attr == 'className'){
137 return n.className;
138 }
139 return n.getAttribute(attr) || n[attr];
140
141 };
142
143 function getNodes(ns, mode, tagName){
144 var result = [], cs;
145 if(!ns){
146 return result;
147 }
148 mode = mode ? mode.replace(trimRe, '$1') : '';
149 tagName = tagName || '*';
150 if(ns.tagName || ns == document){
151 ns = [ns];
152 }
153 if(mode != '/' && mode != '>'){
154 for(var i = 0, ni; ni = ns[i]; i++){
155 cs = ni.getElementsByTagName(tagName);
156 result = concat(result, cs);
157 }
158 }else{
159 for(var i = 0, ni; ni = ns[i]; i++){
160 var cn = ni.getElementsByTagName(tagName);
161 for(var j = 0, cj; cj = cn[j]; j++){
162 if(cj.parentNode == ni){
163 result[result.length] = cj;
164 }
165 }
166 }
167
168 }
169 return result;
170 };
171
172 function concat(a, b){
173 if(b.slice){
174 return a.concat(b);
175 }
176 for(var i = 0, l = b.length; i < l; i++){
177 a[a.length] = b[i];
178 }
179 return a;
180 }
181
182 function byTag(cs, tagName){
183 if(cs.tagName || cs == document){
184 cs = [cs];
185 }
186 if(!tagName){
187 return cs;
188 }
189 var r = []; tagName = tagName.toLowerCase();
190 for(var i = 0, ci; ci = cs[i]; i++){
191 if(ci.nodeType == 1 && ci.tagName.toLowerCase()==tagName){
192 r[r.length] = ci;
193 }
194 }
195 return r;
196 };
197
198 function byId(cs, attr, id){
199 if(cs.tagName || cs == document){
200 cs = [cs];
201 }
202 if(!id){
203 return cs;
204 }
205 var r = [];
206 for(var i = 0, l = cs.length; i < l; i++){
207 var ci = cs[i];
208 if(ci && ci.id == id){
209 r[r.length] = ci;
210 }
211 }
212 return r;
213 };
214
215 function byAttribute(cs, attr, value, op, custom){
216 var r = [], st = custom=='{';
217 var f = Clipperz.YUI.DomQuery.operators[op];
218 for(var i = 0, l = cs.length; i < l; i++){
219 var a;
220 if(st){
221 a = Clipperz.YUI.DomQuery.getStyle(cs[i], attr);
222 }
223 else if(attr == 'class' || attr == 'className'){
224 a = cs[i].className;
225 }else if(attr == 'for'){
226 a = cs[i].htmlFor;
227 }else{
228 a = cs[i].getAttribute(attr);
229 }
230 if((f && f(a, value)) || (!f && a)){
231 r[r.length] = cs[i];
232 }
233 }
234 return r;
235 };
236
237 function byPseudo(cs, name, value){
238 return Clipperz.YUI.DomQuery.pseudos[name](cs, value);
239 };
240
241 // This is for IE MSXML which does not support expandos.
242 // IE runs the same speed using setAttribute, however FF slows way down
243 // and Safari completely fails so they need to continue to use expandos.
244 // Branched at load time for faster execution.
245 var isIE = window.ActiveXObject;
246 var addAttr = isIE ?
247 function(n, a, v){
248 n.setAttribute(a, v);
249 } :
250 function(n, a, v){
251 n[a] = v;
252 };
253 var getAttr = isIE ?
254 function(n, a){
255 return n.getAttribute(a);
256 } :
257 function(n, a){
258 return n[a];
259 };
260 var clearAttr = isIE ?
261 function(n, a){
262 n.removeAttribute(a);
263 } :
264 function(n, a, v){
265 delete n[a];
266 };
267
268 function nodup(cs){
269 if(!cs.length){
270 return cs;
271 }
272 addAttr(cs[0], '_nodup', true);
273 var r = [cs[0]];
274 for(var i = 1, len = cs.length; i < len; i++){
275 var c = cs[i];
276 if(!getAttr(c, '_nodup')){
277 addAttr(c, '_nodup', true);
278 r[r.length] = c;
279 }
280 }
281 for(var i = 0, len = cs.length; i < len; i++){
282 clearAttr(cs[i], '_nodup');
283 }
284 return r;
285 }
286
287 function quickDiff(c1, c2){
288 if(!c1.length){
289 return c2;
290 }
291 for(var i = 0, len = c1.length; i < len; i++){
292 addAttr(c1[i], '_qdiff', true);
293 }
294 var r = [];
295 for(var i = 0, len = c2.length; i < len; i++){
296 if(!getAttr(c2[i], '_qdiff')){
297 r[r.length] = c2[i];
298 }
299 }
300 for(var i = 0, len = c1.length; i < len; i++){
301 clearAttr(c1[i], '_qdiff');
302 }
303 return r;
304 }
305
306 function quickId(ns, mode, root, id){
307 if(ns == root){
308 var d = root.ownerDocument || root;
309 return d.getElementById(id);
310 }
311 ns = getNodes(ns, mode, '*');
312 return byId(ns, null, id);
313 }
314
315 return {
316 getStyle : function(el, name){
317 return YAHOO.util.Dom.getStyle(el, name);
318 },
319 /**
320 * Compiles a selector/xpath query into a reusable function. The returned function
321 * takes one parameter "root" (optional), which is the context node from where the query should start.
322 * @param {String} selector The selector/xpath query
323 * @param {String} type (optional) Either 'select' (the default) or 'simple' for a simple selector match
324 * @return {Function}
325 */
326 compile : function(path, type){
327 // strip leading slashes
328 while(path.substr(0, 1)=='/'){
329 path = path.substr(1);
330 }
331 type = type || 'select';
332
333 var fn = ['var f = function(root){\n var mode; var n = root || document;\n'];
334 var q = path, mode, lq;
335 var tk = Clipperz.YUI.DomQuery.matchers;
336 var tklen = tk.length;
337 var mm;
338 while(q && lq != q){
339 lq = q;
340 var tm = q.match(/^(#)?([\w-\*]+)/);
341 if(type == 'select'){
342 if(tm){
343 if(tm[1] == '#'){
344 fn[fn.length] = 'n = quickId(n, mode, root, "'+tm[2]+'");';
345 }else{
346 fn[fn.length] = 'n = getNodes(n, mode, "'+tm[2]+'");';
347 }
348 q = q.replace(tm[0], '');
349 }else{
350 fn[fn.length] = 'n = getNodes(n, mode, "*");';
351 }
352 }else{
353 if(tm){
354 if(tm[1] == '#'){
355 fn[fn.length] = 'n = byId(n, null, "'+tm[2]+'");';
356 }else{
357 fn[fn.length] = 'n = byTag(n, "'+tm[2]+'");';
358 }
359 q = q.replace(tm[0], '');
360 }
361 }
362 while(!(mm = q.match(modeRe))){
363 var matched = false;
364 for(var j = 0; j < tklen; j++){
365 var t = tk[j];
366 var m = q.match(t.re);
367 if(m){
368 fn[fn.length] = t.select.replace(tplRe, function(x, i){
369 return m[i];
370 });
371 q = q.replace(m[0], '');
372 matched = true;
373 break;
374 }
375 }
376 // prevent infinite loop on bad selector
377 if(!matched){
378 throw 'Error parsing selector, parsing failed at "' + q + '"';
379 }
380 }
381 if(mm[1]){
382 fn[fn.length] = 'mode="'+mm[1]+'";';
383 q = q.replace(mm[1], '');
384 }
385 }
386 fn[fn.length] = 'return nodup(n);\n}';
387 eval(fn.join(''));
388 return f;
389 },
390
391 /**
392 * Selects a group of elements.
393 * @param {String} selector The selector/xpath query
394 * @param {Node} root (optional) The start of the query (defaults to document).
395 * @return {Array}
396 */
397 select : function(path, root, type){
398 if(!root || root == document){
399 root = document;
400 }
401 if(typeof root == 'string'){
402 root = document.getElementById(root);
403 }
404 var paths = path.split(',');
405 var results = [];
406 for(var i = 0, len = paths.length; i < len; i++){
407 var p = paths[i].replace(trimRe, '$1');
408 if(!cache[p]){
409 cache[p] = Clipperz.YUI.DomQuery.compile(p);
410 if(!cache[p]){
411 throw p + ' is not a valid selector';
412 }
413 }
414 var result = cache[p](root);
415 if(result && result != document){
416 results = results.concat(result);
417 }
418 }
419 return results;
420 },
421
422 /**
423 * Selects a single element.
424 * @param {String} selector The selector/xpath query
425 * @param {Node} root (optional) The start of the query (defaults to document).
426 * @return {Element}
427 */
428 selectNode : function(path, root){
429 return Clipperz.YUI.DomQuery.select(path, root)[0];
430 },
431
432 /**
433 * Selects the value of a node, optionally replacing null with the defaultValue.
434 * @param {String} selector The selector/xpath query
435 * @param {Node} root (optional) The start of the query (defaults to document).
436 * @param {String} defaultValue
437 */
438 selectValue : function(path, root, defaultValue){
439 path = path.replace(trimRe, '$1');
440 if(!valueCache[path]){
441 valueCache[path] = Clipperz.YUI.DomQuery.compile(path, 'simple');
442 }
443 var n = valueCache[path](root);
444 n = n[0] ? n[0] : n;
445 var v = (n && n.firstChild ? n.firstChild.nodeValue : null);
446 return (v === null ? defaultValue : v);
447 },
448
449 /**
450 * Selects the value of a node, parsing integers and floats.
451 * @param {String} selector The selector/xpath query
452 * @param {Node} root (optional) The start of the query (defaults to document).
453 * @param {Number} defaultValue
454 * @return {Number}
455 */
456 selectNumber : function(path, root, defaultValue){
457 var v = Clipperz.YUI.DomQuery.selectValue(path, root, defaultValue || 0);
458 return parseFloat(v);
459 },
460
461 /**
462 * Returns true if the passed element(s) match the passed simple selector (e.g. div.some-class or span:first-child)
463 * @param {String/HTMLElement/Array} el An element id, element or array of elements
464 * @param {String} selector The simple selector to test
465 * @return {Boolean}
466 */
467 is : function(el, ss){
468 if(typeof el == 'string'){
469 el = document.getElementById(el);
470 }
471 var isArray = (el instanceof Array);
472 var result = Clipperz.YUI.DomQuery.filter(isArray ? el : [el], ss);
473 return isArray ? (result.length == el.length) : (result.length > 0);
474 },
475
476 /**
477 * Filters an array of elements to only include matches of a simple selector (e.g. div.some-class or span:first-child)
478 * @param {Array} el An array of elements to filter
479 * @param {String} selector The simple selector to test
480 * @param {Boolean} nonMatches If true, it returns the elements that DON'T match
481 * the selector instead of the ones that match
482 * @return {Array}
483 */
484 filter : function(els, ss, nonMatches){
485 ss = ss.replace(trimRe, '$1');
486 if(!simpleCache[ss]){
487 simpleCache[ss] = Clipperz.YUI.DomQuery.compile(ss, 'simple');
488 }
489 var result = simpleCache[ss](els);
490 return nonMatches ? quickDiff(result, els) : result;
491 },
492
493 /**
494 * Collection of matching regular expressions and code snippets.
495 */
496 matchers : [{
497 re: /^\.([\w-]+)/,
498 select: 'n = byClassName(n, null, "{1}");'
499 }, {
500 re: /^\:([\w-]+)(?:\(((?:[^\s>\/]*|.*?))\))?/,
501 select: 'n = byPseudo(n, "{1}", "{2}");'
502 },{
503 re: /^(?:([\[\{])(?:@)?([\w-]+)\s?(?:(=|.=)\s?['"]?(.*?)["']?)?[\]\}])/,
504 select: 'n = byAttribute(n, "{2}", "{4}", "{3}", "{1}");'
505 }, {
506 re: /^#([\w-]+)/,
507 select: 'n = byId(n, null, "{1}");'
508 },{
509 re: /^@([\w-]+)/,
510 select: 'return {firstChild:{nodeValue:attrValue(n, "{1}")}};'
511 }
512 ],
513
514 /**
515 * Collection of operator comparison functions. The default operators are =, !=, ^=, $=, *= and %=.
516 * New operators can be added as long as the match the format <i>c</i>= where <i>c<i> is any character other than space, &gt; &lt;.
517 */
518 operators : {
519 '=' : function(a, v){
520 return a == v;
521 },
522 '!=' : function(a, v){
523 return a != v;
524 },
525 '^=' : function(a, v){
526 return a && a.substr(0, v.length) == v;
527 },
528 '$=' : function(a, v){
529 return a && a.substr(a.length-v.length) == v;
530 },
531 '*=' : function(a, v){
532 return a && a.indexOf(v) !== -1;
533 },
534 '%=' : function(a, v){
535 return (a % v) == 0;
536 }
537 },
538
539 /**
540 * Collection of "pseudo class" processors. Each processor is passed the current nodeset (array)
541 * and the argument (if any) supplied in the selector.
542 */
543 pseudos : {
544 'first-child' : function(c){
545 var r = [];
546 for(var i = 0, l = c.length; i < l; i++){
547 var ci = c[i];
548 if(!prev(ci)){
549 r[r.length] = ci;
550 }
551 }
552 return r;
553 },
554
555 'last-child' : function(c){
556 var r = [];
557 for(var i = 0, l = c.length; i < l; i++){
558 var ci = c[i];
559 if(!next(ci)){
560 r[r.length] = ci;
561 }
562 }
563 return r;
564 },
565
566 'nth-child' : function(c, a){
567 var r = [];
568 if(a != 'odd' && a != 'even'){
569 for(var i = 0, ci; ci = c[i]; i++){
570 var m = child(ci.parentNode, a);
571 if(m == ci){
572 r[r.length] = m;
573 }
574 }
575 return r;
576 }
577 var p;
578 // first let's clean up the parent nodes
579 for(var i = 0, l = c.length; i < l; i++){
580 var cp = c[i].parentNode;
581 if(cp != p){
582 clean(cp);
583 p = cp;
584 }
585 }
586 // then lets see if we match
587 for(var i = 0, l = c.length; i < l; i++){
588 var ci = c[i], m = false;
589 if(a == 'odd'){
590 m = ((ci.nodeIndex+1) % 2 == 1);
591 }else if(a == 'even'){
592 m = ((ci.nodeIndex+1) % 2 == 0);
593 }
594 if(m){
595 r[r.length] = ci;
596 }
597 }
598 return r;
599 },
600
601 'only-child' : function(c){
602 var r = [];
603 for(var i = 0, l = c.length; i < l; i++){
604 var ci = c[i];
605 if(!prev(ci) && !next(ci)){
606 r[r.length] = ci;
607 }
608 }
609 return r;
610 },
611
612 'empty' : function(c){
613 var r = [];
614 for(var i = 0, l = c.length; i < l; i++){
615 var ci = c[i];
616 if(!ci.firstChild){
617 r[r.length] = ci;
618 }
619 }
620 return r;
621 },
622
623 'contains' : function(c, v){
624 var r = [];
625 for(var i = 0, l = c.length; i < l; i++){
626 var ci = c[i];
627 if(ci.innerHTML.indexOf(v) !== -1){
628 r[r.length] = ci;
629 }
630 }
631 return r;
632 },
633
634 'checked' : function(c){
635 var r = [];
636 for(var i = 0, l = c.length; i < l; i++){
637 if(c[i].checked == 'checked'){
638 r[r.length] = c[i];
639 }
640 }
641 return r;
642 },
643
644 'not' : function(c, ss){
645 return Clipperz.YUI.DomQuery.filter(c, ss, true);
646 },
647
648 'odd' : function(c){
649 return this['nth-child'](c, 'odd');
650 },
651
652 'even' : function(c){
653 return this['nth-child'](c, 'even');
654 },
655
656 'nth' : function(c, a){
657 return c[a-1];
658 },
659
660 'first' : function(c){
661 return c[0];
662 },
663
664 'last' : function(c){
665 return c[c.length-1];
666 },
667
668 'has' : function(c, ss){
669 var s = Clipperz.YUI.DomQuery.select;
670 var r = [];
671 for(var i = 0, ci; ci = c[i]; i++){
672 if(s(ss, ci).length > 0){
673 r[r.length] = ci;
674 }
675 }
676 return r;
677 },
678
679 'next' : function(c, ss){
680 var is = Clipperz.YUI.DomQuery.is;
681 var r = [];
682 for(var i = 0, ci; ci = c[i]; i++){
683 var n = next(ci);
684 if(n && is(n, ss)){
685 r[r.length] = ci;
686 }
687 }
688 return r;
689 },
690
691 'prev' : function(c, ss){
692 var is = Clipperz.YUI.DomQuery.is;
693 var r = [];
694 for(var i = 0, ci; ci = c[i]; i++){
695 var n = prev(ci);
696 if(n && is(n, ss)){
697 r[r.length] = ci;
698 }
699 }
700 return r;
701 }
702 }
703 };
704}();
705
706/**
707 * Selects an array of DOM nodes by CSS/XPath selector. Shorthand of {@link Clipperz.YUI.DomQuery#select}
708 * @param {String} path The selector/xpath query
709 * @param {Node} root (optional) The start of the query (defaults to document).
710 * @return {Array}
711 * @member Ext
712 * @method query
713 */
714Clipperz.YUI.query = Clipperz.YUI.DomQuery.select;