summaryrefslogtreecommitdiff
path: root/frontend/beta/js/MochiKit/DOM.js
Unidiff
Diffstat (limited to 'frontend/beta/js/MochiKit/DOM.js') (more/less context) (ignore whitespace changes)
-rw-r--r--frontend/beta/js/MochiKit/DOM.js1267
1 files changed, 1267 insertions, 0 deletions
diff --git a/frontend/beta/js/MochiKit/DOM.js b/frontend/beta/js/MochiKit/DOM.js
new file mode 100644
index 0000000..591c597
--- a/dev/null
+++ b/frontend/beta/js/MochiKit/DOM.js
@@ -0,0 +1,1267 @@
1/***
2
3MochiKit.DOM 1.4
4
5See <http://mochikit.com/> for documentation, downloads, license, etc.
6
7(c) 2005 Bob Ippolito. All rights Reserved.
8
9***/
10
11if (typeof(dojo) != 'undefined') {
12 dojo.provide("MochiKit.DOM");
13 dojo.require("MochiKit.Base");
14}
15if (typeof(JSAN) != 'undefined') {
16 JSAN.use("MochiKit.Base", []);
17}
18
19try {
20 if (typeof(MochiKit.Base) == 'undefined') {
21 throw "";
22 }
23} catch (e) {
24 throw "MochiKit.DOM depends on MochiKit.Base!";
25}
26
27if (typeof(MochiKit.DOM) == 'undefined') {
28 MochiKit.DOM = {};
29}
30
31MochiKit.DOM.NAME = "MochiKit.DOM";
32MochiKit.DOM.VERSION = "1.4";
33MochiKit.DOM.__repr__ = function () {
34 return "[" + this.NAME + " " + this.VERSION + "]";
35};
36MochiKit.DOM.toString = function () {
37 return this.__repr__();
38};
39
40MochiKit.DOM.EXPORT = [
41 "removeEmptyTextNodes",
42 "formContents",
43 "currentWindow",
44 "currentDocument",
45 "withWindow",
46 "withDocument",
47 "registerDOMConverter",
48 "coerceToDOM",
49 "createDOM",
50 "createDOMFunc",
51 "isChildNode",
52 "getNodeAttribute",
53 "removeNodeAttribute",
54 "setNodeAttribute",
55 "updateNodeAttributes",
56 "appendChildNodes",
57 "insertSiblingNodesAfter",
58 "insertSiblingNodesBefore",
59 "replaceChildNodes",
60 "removeElement",
61 "swapDOM",
62 "BUTTON",
63 "TT",
64 "PRE",
65 "H1",
66 "H2",
67 "H3",
68 "BR",
69 "CANVAS",
70 "HR",
71 "LABEL",
72 "TEXTAREA",
73 "FORM",
74 "STRONG",
75 "SELECT",
76 "OPTION",
77 "OPTGROUP",
78 "LEGEND",
79 "FIELDSET",
80 "P",
81 "UL",
82 "OL",
83 "LI",
84 "TD",
85 "TR",
86 "THEAD",
87 "TBODY",
88 "TFOOT",
89 "TABLE",
90 "TH",
91 "INPUT",
92 "SPAN",
93 "A",
94 "DIV",
95 "IMG",
96 "getElement",
97 "$",
98 "getElementsByTagAndClassName",
99 "addToCallStack",
100 "addLoadEvent",
101 "focusOnLoad",
102 "setElementClass",
103 "toggleElementClass",
104 "addElementClass",
105 "removeElementClass",
106 "swapElementClass",
107 "hasElementClass",
108 "escapeHTML",
109 "toHTML",
110 "emitHTML",
111 "scrapeText",
112 "isParent",
113 "getFirstParentByTagAndClassName",
114 "makeClipping",
115 "undoClipping",
116 "makePositioned",
117 "undoPositioned",
118 "getFirstElementByTagAndClassName"
119];
120
121MochiKit.DOM.EXPORT_OK = [
122 "domConverters"
123];
124
125MochiKit.DOM.DEPRECATED = [
126 ['computedStyle', 'MochiKit.Style.getStyle', '1.4'],
127 /** @id MochiKit.DOM.elementDimensions */
128 ['elementDimensions', 'MochiKit.Style.getElementDimensions', '1.4'],
129 /** @id MochiKit.DOM.elementPosition */
130 ['elementPosition', 'MochiKit.Style.getElementPosition', '1.4'],
131 ['hideElement', 'MochiKit.Style.hideElement', '1.4'],
132 /** @id MochiKit.DOM.setElementDimensions */
133 ['setElementDimensions', 'MochiKit.Style.setElementDimensions', '1.4'],
134 /** @id MochiKit.DOM.setElementPosition */
135 ['setElementPosition', 'MochiKit.Style.setElementPosition', '1.4'],
136 ['setDisplayForElement', 'MochiKit.Style.setDisplayForElement', '1.4'],
137 /** @id MochiKit.DOM.setOpacity */
138 ['setOpacity', 'MochiKit.Style.setOpacity', '1.4'],
139 ['showElement', 'MochiKit.Style.showElement', '1.4'],
140 /** @id MochiKit.DOM.Coordinates */
141 ['Coordinates', 'MochiKit.Style.Coordinates', '1.4'], // FIXME: broken
142 /** @id MochiKit.DOM.Dimensions */
143 ['Dimensions', 'MochiKit.Style.Dimensions', '1.4'] // FIXME: broken
144];
145
146/** @id MochiKit.DOM.getViewportDimensions */
147MochiKit.DOM.getViewportDimensions = new Function('' +
148 'if (!MochiKit["Style"]) {' +
149 ' throw new Error("This function has been deprecated and depends on MochiKit.Style.");' +
150 '}' +
151 'return MochiKit.Style.getViewportDimensions.apply(this, arguments);');
152
153MochiKit.Base.update(MochiKit.DOM, {
154
155 /** @id MochiKit.DOM.currentWindow */
156 currentWindow: function () {
157 return MochiKit.DOM._window;
158 },
159
160 /** @id MochiKit.DOM.currentDocument */
161 currentDocument: function () {
162 return MochiKit.DOM._document;
163 },
164
165 /** @id MochiKit.DOM.withWindow */
166 withWindow: function (win, func) {
167 var self = MochiKit.DOM;
168 var oldDoc = self._document;
169 var oldWin = self._window;
170 var rval;
171 try {
172 self._window = win;
173 self._document = win.document;
174 rval = func();
175 } catch (e) {
176 self._window = oldWin;
177 self._document = oldDoc;
178 throw e;
179 }
180 self._window = oldWin;
181 self._document = oldDoc;
182 return rval;
183 },
184
185 /** @id MochiKit.DOM.formContents */
186 formContents: function (elem/* = document.body */) {
187 var names = [];
188 var values = [];
189 var m = MochiKit.Base;
190 var self = MochiKit.DOM;
191 if (typeof(elem) == "undefined" || elem === null) {
192 elem = self._document.body;
193 } else {
194 elem = self.getElement(elem);
195 }
196 m.nodeWalk(elem, function (elem) {
197 var name = elem.name;
198 if (m.isNotEmpty(name)) {
199 var tagName = elem.tagName.toUpperCase();
200 if (tagName === "INPUT"
201 && (elem.type == "radio" || elem.type == "checkbox")
202 && !elem.checked
203 ) {
204 return null;
205 }
206 if (tagName === "SELECT") {
207 if (elem.type == "select-one") {
208 if (elem.selectedIndex >= 0) {
209 var opt = elem.options[elem.selectedIndex];
210 var v = opt.value;
211 if (!v) {
212 var h = opt.outerHTML;
213 // internet explorer sure does suck.
214 if (h && !h.match(/^[^>]+\svalue\s*=/i)) {
215 v = opt.text;
216 }
217 }
218 names.push(name);
219 values.push(v);
220 return null;
221 }
222 // no form elements?
223 names.push(name);
224 values.push("");
225 return null;
226 } else {
227 var opts = elem.options;
228 if (!opts.length) {
229 names.push(name);
230 values.push("");
231 return null;
232 }
233 for (var i = 0; i < opts.length; i++) {
234 var opt = opts[i];
235 if (!opt.selected) {
236 continue;
237 }
238 var v = opt.value;
239 if (!v) {
240 var h = opt.outerHTML;
241 // internet explorer sure does suck.
242 if (h && !h.match(/^[^>]+\svalue\s*=/i)) {
243 v = opt.text;
244 }
245 }
246 names.push(name);
247 values.push(v);
248 }
249 return null;
250 }
251 }
252 if (tagName === "FORM" || tagName === "P" || tagName === "SPAN"
253 || tagName === "DIV"
254 ) {
255 return elem.childNodes;
256 }
257 names.push(name);
258 values.push(elem.value || '');
259 return null;
260 }
261 return elem.childNodes;
262 });
263 return [names, values];
264 },
265
266 /** @id MochiKit.DOM.withDocument */
267 withDocument: function (doc, func) {
268 var self = MochiKit.DOM;
269 var oldDoc = self._document;
270 var rval;
271 try {
272 self._document = doc;
273 rval = func();
274 } catch (e) {
275 self._document = oldDoc;
276 throw e;
277 }
278 self._document = oldDoc;
279 return rval;
280 },
281
282 /** @id MochiKit.DOM.registerDOMConverter */
283 registerDOMConverter: function (name, check, wrap, /* optional */override) {
284 MochiKit.DOM.domConverters.register(name, check, wrap, override);
285 },
286
287 /** @id MochiKit.DOM.coerceToDOM */
288 coerceToDOM: function (node, ctx) {
289 var m = MochiKit.Base;
290 var im = MochiKit.Iter;
291 var self = MochiKit.DOM;
292 if (im) {
293 var iter = im.iter;
294 var repeat = im.repeat;
295 var map = m.map;
296 }
297 var domConverters = self.domConverters;
298 var coerceToDOM = arguments.callee;
299 var NotFound = m.NotFound;
300 while (true) {
301 if (typeof(node) == 'undefined' || node === null) {
302 return null;
303 }
304 if (typeof(node.nodeType) != 'undefined' && node.nodeType > 0) {
305 return node;
306 }
307 if (typeof(node) == 'number' || typeof(node) == 'boolean') {
308 node = node.toString();
309 // FALL THROUGH
310 }
311 if (typeof(node) == 'string') {
312 return self._document.createTextNode(node);
313 }
314 if (typeof(node.__dom__) == 'function') {
315 node = node.__dom__(ctx);
316 continue;
317 }
318 if (typeof(node.dom) == 'function') {
319 node = node.dom(ctx);
320 continue;
321 }
322 if (typeof(node) == 'function') {
323 node = node.apply(ctx, [ctx]);
324 continue;
325 }
326
327 if (im) {
328 // iterable
329 var iterNodes = null;
330 try {
331 iterNodes = iter(node);
332 } catch (e) {
333 // pass
334 }
335 if (iterNodes) {
336 return map(coerceToDOM, iterNodes, repeat(ctx));
337 }
338 }
339
340 // adapter
341 try {
342 node = domConverters.match(node, ctx);
343 continue;
344 } catch (e) {
345 if (e != NotFound) {
346 throw e;
347 }
348 }
349
350 // fallback
351 return self._document.createTextNode(node.toString());
352 }
353 // mozilla warnings aren't too bright
354 return undefined;
355 },
356
357 /** @id MochiKit.DOM.isChildNode */
358 isChildNode: function (node, maybeparent) {
359 var self = MochiKit.DOM;
360 if (typeof(node) == "string") {
361 node = self.getElement(node);
362 }
363 if (typeof(maybeparent) == "string") {
364 maybeparent = self.getElement(maybeparent);
365 }
366 if (node === maybeparent) {
367 return true;
368 }
369 while (node && node.tagName.toUpperCase() != "BODY") {
370 node = node.parentNode;
371 if (node === maybeparent) {
372 return true;
373 }
374 }
375 return false;
376 },
377
378 /** @id MochiKit.DOM.setNodeAttribute */
379 setNodeAttribute: function (node, attr, value) {
380 var o = {};
381 o[attr] = value;
382 try {
383 return MochiKit.DOM.updateNodeAttributes(node, o);
384 } catch (e) {
385 // pass
386 }
387 return null;
388 },
389
390 /** @id MochiKit.DOM.getNodeAttribute */
391 getNodeAttribute: function (node, attr) {
392 var self = MochiKit.DOM;
393 var rename = self.attributeArray.renames[attr];
394 node = self.getElement(node);
395 try {
396 if (rename) {
397 return node[rename];
398 }
399 return node.getAttribute(attr);
400 } catch (e) {
401 // pass
402 }
403 return null;
404 },
405
406 /** @id MochiKit.DOM.removeNodeAttribute */
407 removeNodeAttribute: function (node, attr) {
408 var self = MochiKit.DOM;
409 var rename = self.attributeArray.renames[attr];
410 node = self.getElement(node);
411 try {
412 if (rename) {
413 return node[rename];
414 }
415 return node.removeAttribute(attr);
416 } catch (e) {
417 // pass
418 }
419 return null;
420 },
421
422 /** @id MochiKit.DOM.updateNodeAttributes */
423 updateNodeAttributes: function (node, attrs) {
424 var elem = node;
425 var self = MochiKit.DOM;
426 if (typeof(node) == 'string') {
427 elem = self.getElement(node);
428 }
429 if (attrs) {
430 var updatetree = MochiKit.Base.updatetree;
431 if (self.attributeArray.compliant) {
432 // not IE, good.
433 for (var k in attrs) {
434 var v = attrs[k];
435 if (typeof(v) == 'object' && typeof(elem[k]) == 'object') {
436 if (k == "style" && MochiKit.Style) {
437 MochiKit.Style.setStyle(elem, v);
438 } else {
439 updatetree(elem[k], v);
440 }
441 } else if (k.substring(0, 2) == "on") {
442 if (typeof(v) == "string") {
443 v = new Function(v);
444 }
445 elem[k] = v;
446 } else {
447 elem.setAttribute(k, v);
448 }
449 }
450 } else {
451 // IE is insane in the membrane
452 var renames = self.attributeArray.renames;
453 for (k in attrs) {
454 v = attrs[k];
455 var renamed = renames[k];
456 if (k == "style" && typeof(v) == "string") {
457 elem.style.cssText = v;
458 } else if (typeof(renamed) == "string") {
459 elem[renamed] = v;
460 } else if (typeof(elem[k]) == 'object'
461 && typeof(v) == 'object') {
462 if (k == "style" && MochiKit.Style) {
463 MochiKit.Style.setStyle(elem, v);
464 } else {
465 updatetree(elem[k], v);
466 }
467 } else if (k.substring(0, 2) == "on") {
468 if (typeof(v) == "string") {
469 v = new Function(v);
470 }
471 elem[k] = v;
472 } else {
473 elem.setAttribute(k, v);
474 }
475 }
476 }
477 }
478 return elem;
479 },
480
481 /** @id MochiKit.DOM.appendChildNodes */
482 appendChildNodes: function (node/*, nodes...*/) {
483 var elem = node;
484 var self = MochiKit.DOM;
485 if (typeof(node) == 'string') {
486 elem = self.getElement(node);
487 }
488 var nodeStack = [
489 self.coerceToDOM(
490 MochiKit.Base.extend(null, arguments, 1),
491 elem
492 )
493 ];
494 var concat = MochiKit.Base.concat;
495 while (nodeStack.length) {
496 var n = nodeStack.shift();
497 if (typeof(n) == 'undefined' || n === null) {
498 // pass
499 } else if (typeof(n.nodeType) == 'number') {
500 elem.appendChild(n);
501 } else {
502 nodeStack = concat(n, nodeStack);
503 }
504 }
505 return elem;
506 },
507
508
509 /** @id MochiKit.DOM.insertSiblingNodesBefore */
510 insertSiblingNodesBefore: function (node/*, nodes...*/) {
511 var elem = node;
512 var self = MochiKit.DOM;
513 if (typeof(node) == 'string') {
514 elem = self.getElement(node);
515 }
516 var nodeStack = [
517 self.coerceToDOM(
518 MochiKit.Base.extend(null, arguments, 1),
519 elem
520 )
521 ];
522 var parentnode = elem.parentNode;
523 var concat = MochiKit.Base.concat;
524 while (nodeStack.length) {
525 var n = nodeStack.shift();
526 if (typeof(n) == 'undefined' || n === null) {
527 // pass
528 } else if (typeof(n.nodeType) == 'number') {
529 parentnode.insertBefore(n, elem);
530 } else {
531 nodeStack = concat(n, nodeStack);
532 }
533 }
534 return parentnode;
535 },
536
537 /** @id MochiKit.DOM.insertSiblingNodesAfter */
538 insertSiblingNodesAfter: function (node/*, nodes...*/) {
539 var elem = node;
540 var self = MochiKit.DOM;
541
542 if (typeof(node) == 'string') {
543 elem = self.getElement(node);
544 }
545 var nodeStack = [
546 self.coerceToDOM(
547 MochiKit.Base.extend(null, arguments, 1),
548 elem
549 )
550 ];
551
552 if (elem.nextSibling) {
553 return self.insertSiblingNodesBefore(elem.nextSibling, nodeStack);
554 }
555 else {
556 return self.appendChildNodes(elem.parentNode, nodeStack);
557 }
558 },
559
560 /** @id MochiKit.DOM.replaceChildNodes */
561 replaceChildNodes: function (node/*, nodes...*/) {
562 var elem = node;
563 var self = MochiKit.DOM;
564 if (typeof(node) == 'string') {
565 elem = self.getElement(node);
566 arguments[0] = elem;
567 }
568 var child;
569 while ((child = elem.firstChild)) {
570 elem.removeChild(child);
571 }
572 if (arguments.length < 2) {
573 return elem;
574 } else {
575 return self.appendChildNodes.apply(this, arguments);
576 }
577 },
578
579 /** @id MochiKit.DOM.createDOM */
580 createDOM: function (name, attrs/*, nodes... */) {
581 var elem;
582 var self = MochiKit.DOM;
583 var m = MochiKit.Base;
584 if (typeof(attrs) == "string" || typeof(attrs) == "number") {
585 var args = m.extend([name, null], arguments, 1);
586 return arguments.callee.apply(this, args);
587 }
588 if (typeof(name) == 'string') {
589 // Internet Explorer is dumb
590 var xhtml = self._xhtml;
591 if (attrs && !self.attributeArray.compliant) {
592 // http://msdn.microsoft.com/workshop/author/dhtml/reference/properties/name_2.asp
593 var contents = "";
594 if ('name' in attrs) {
595 contents += ' name="' + self.escapeHTML(attrs.name) + '"';
596 }
597 if (name == 'input' && 'type' in attrs) {
598 contents += ' type="' + self.escapeHTML(attrs.type) + '"';
599 }
600 if (contents) {
601 name = "<" + name + contents + ">";
602 xhtml = false;
603 }
604 }
605 var d = self._document;
606 if (xhtml && d === document) {
607 elem = d.createElementNS("http://www.w3.org/1999/xhtml", name);
608 } else {
609 elem = d.createElement(name);
610 }
611 } else {
612 elem = name;
613 }
614 if (attrs) {
615 self.updateNodeAttributes(elem, attrs);
616 }
617 if (arguments.length <= 2) {
618 return elem;
619 } else {
620 var args = m.extend([elem], arguments, 2);
621 return self.appendChildNodes.apply(this, args);
622 }
623 },
624
625 /** @id MochiKit.DOM.createDOMFunc */
626 createDOMFunc: function (/* tag, attrs, *nodes */) {
627 var m = MochiKit.Base;
628 return m.partial.apply(
629 this,
630 m.extend([MochiKit.DOM.createDOM], arguments)
631 );
632 },
633
634 /** @id MochiKit.DOM.removeElement */
635 removeElement: function (elem) {
636 var e = MochiKit.DOM.getElement(elem);
637 e.parentNode.removeChild(e);
638 return e;
639 },
640
641 /** @id MochiKit.DOM.swapDOM */
642 swapDOM: function (dest, src) {
643 var self = MochiKit.DOM;
644 dest = self.getElement(dest);
645 var parent = dest.parentNode;
646 if (src) {
647 src = self.getElement(src);
648 parent.replaceChild(src, dest);
649 } else {
650 parent.removeChild(dest);
651 }
652 return src;
653 },
654
655 /** @id MochiKit.DOM.getElement */
656 getElement: function (id) {
657 var self = MochiKit.DOM;
658 if (arguments.length == 1) {
659 return ((typeof(id) == "string") ?
660 self._document.getElementById(id) : id);
661 } else {
662 return MochiKit.Base.map(self.getElement, arguments);
663 }
664 },
665
666 /** @id MochiKit.DOM.getElementsByTagAndClassName */
667 getElementsByTagAndClassName: function (tagName, className,
668 /* optional */parent) {
669 var self = MochiKit.DOM;
670 if (typeof(tagName) == 'undefined' || tagName === null) {
671 tagName = '*';
672 }
673 if (typeof(parent) == 'undefined' || parent === null) {
674 parent = self._document;
675 }
676 parent = self.getElement(parent);
677 var children = (parent.getElementsByTagName(tagName)
678 || self._document.all);
679 if (typeof(className) == 'undefined' || className === null) {
680 return MochiKit.Base.extend(null, children);
681 }
682
683 var elements = [];
684 for (var i = 0; i < children.length; i++) {
685 var child = children[i];
686 var cls = child.className;
687 if (!cls) {
688 continue;
689 }
690 var classNames = cls.split(' ');
691 for (var j = 0; j < classNames.length; j++) {
692 if (classNames[j] == className) {
693 elements.push(child);
694 break;
695 }
696 }
697 }
698
699 return elements;
700 },
701
702 _newCallStack: function (path, once) {
703 var rval = function () {
704 var callStack = arguments.callee.callStack;
705 for (var i = 0; i < callStack.length; i++) {
706 if (callStack[i].apply(this, arguments) === false) {
707 break;
708 }
709 }
710 if (once) {
711 try {
712 this[path] = null;
713 } catch (e) {
714 // pass
715 }
716 }
717 };
718 rval.callStack = [];
719 return rval;
720 },
721
722 /** @id MochiKit.DOM.addToCallStack */
723 addToCallStack: function (target, path, func, once) {
724 var self = MochiKit.DOM;
725 var existing = target[path];
726 var regfunc = existing;
727 if (!(typeof(existing) == 'function'
728 && typeof(existing.callStack) == "object"
729 && existing.callStack !== null)) {
730 regfunc = self._newCallStack(path, once);
731 if (typeof(existing) == 'function') {
732 regfunc.callStack.push(existing);
733 }
734 target[path] = regfunc;
735 }
736 regfunc.callStack.push(func);
737 },
738
739 /** @id MochiKit.DOM.addLoadEvent */
740 addLoadEvent: function (func) {
741 var self = MochiKit.DOM;
742 self.addToCallStack(self._window, "onload", func, true);
743
744 },
745
746 /** @id MochiKit.DOM.focusOnLoad */
747 focusOnLoad: function (element) {
748 var self = MochiKit.DOM;
749 self.addLoadEvent(function () {
750 element = self.getElement(element);
751 if (element) {
752 element.focus();
753 }
754 });
755 },
756
757 /** @id MochiKit.DOM.setElementClass */
758 setElementClass: function (element, className) {
759 var self = MochiKit.DOM;
760 var obj = self.getElement(element);
761 if (self.attributeArray.compliant) {
762 obj.setAttribute("class", className);
763 } else {
764 obj.setAttribute("className", className);
765 }
766 },
767
768 /** @id MochiKit.DOM.toggleElementClass */
769 toggleElementClass: function (className/*, element... */) {
770 var self = MochiKit.DOM;
771 for (var i = 1; i < arguments.length; i++) {
772 var obj = self.getElement(arguments[i]);
773 if (!self.addElementClass(obj, className)) {
774 self.removeElementClass(obj, className);
775 }
776 }
777 },
778
779 /** @id MochiKit.DOM.addElementClass */
780 addElementClass: function (element, className) {
781 var self = MochiKit.DOM;
782 var obj = self.getElement(element);
783 var cls = obj.className;
784 // trivial case, no className yet
785 if (cls == undefined || cls.length === 0) {
786 self.setElementClass(obj, className);
787 return true;
788 }
789 // the other trivial case, already set as the only class
790 if (cls == className) {
791 return false;
792 }
793 var classes = cls.split(" ");
794 for (var i = 0; i < classes.length; i++) {
795 // already present
796 if (classes[i] == className) {
797 return false;
798 }
799 }
800 // append class
801 self.setElementClass(obj, cls + " " + className);
802 return true;
803 },
804
805 /** @id MochiKit.DOM.removeElementClass */
806 removeElementClass: function (element, className) {
807 var self = MochiKit.DOM;
808 var obj = self.getElement(element);
809 var cls = obj.className;
810 // trivial case, no className yet
811 if (cls == undefined || cls.length === 0) {
812 return false;
813 }
814 // other trivial case, set only to className
815 if (cls == className) {
816 self.setElementClass(obj, "");
817 return true;
818 }
819 var classes = cls.split(" ");
820 for (var i = 0; i < classes.length; i++) {
821 // already present
822 if (classes[i] == className) {
823 // only check sane case where the class is used once
824 classes.splice(i, 1);
825 self.setElementClass(obj, classes.join(" "));
826 return true;
827 }
828 }
829 // not found
830 return false;
831 },
832
833 /** @id MochiKit.DOM.swapElementClass */
834 swapElementClass: function (element, fromClass, toClass) {
835 var obj = MochiKit.DOM.getElement(element);
836 var res = MochiKit.DOM.removeElementClass(obj, fromClass);
837 if (res) {
838 MochiKit.DOM.addElementClass(obj, toClass);
839 }
840 return res;
841 },
842
843 /** @id MochiKit.DOM.hasElementClass */
844 hasElementClass: function (element, className/*...*/) {
845 var obj = MochiKit.DOM.getElement(element);
846 var cls = obj.className;
847 if (!cls) {
848 return false;
849 }
850 var classes = cls.split(" ");
851 for (var i = 1; i < arguments.length; i++) {
852 var good = false;
853 for (var j = 0; j < classes.length; j++) {
854 if (classes[j] == arguments[i]) {
855 good = true;
856 break;
857 }
858 }
859 if (!good) {
860 return false;
861 }
862 }
863 return true;
864 },
865
866 /** @id MochiKit.DOM.escapeHTML */
867 escapeHTML: function (s) {
868 return s.replace(/&/g, "&amp;"
869 ).replace(/"/g, "&quot;"
870 ).replace(/</g, "&lt;"
871 ).replace(/>/g, "&gt;");
872 },
873
874 /** @id MochiKit.DOM.toHTML */
875 toHTML: function (dom) {
876 return MochiKit.DOM.emitHTML(dom).join("");
877 },
878
879 /** @id MochiKit.DOM.emitHTML */
880 emitHTML: function (dom, /* optional */lst) {
881 if (typeof(lst) == 'undefined' || lst === null) {
882 lst = [];
883 }
884 // queue is the call stack, we're doing this non-recursively
885 var queue = [dom];
886 var self = MochiKit.DOM;
887 var escapeHTML = self.escapeHTML;
888 var attributeArray = self.attributeArray;
889 while (queue.length) {
890 dom = queue.pop();
891 if (typeof(dom) == 'string') {
892 lst.push(dom);
893 } else if (dom.nodeType == 1) {
894 // we're not using higher order stuff here
895 // because safari has heisenbugs.. argh.
896 //
897 // I think it might have something to do with
898 // garbage collection and function calls.
899 lst.push('<' + dom.tagName.toLowerCase());
900 var attributes = [];
901 var domAttr = attributeArray(dom);
902 for (var i = 0; i < domAttr.length; i++) {
903 var a = domAttr[i];
904 attributes.push([
905 " ",
906 a.name,
907 '="',
908 escapeHTML(a.value),
909 '"'
910 ]);
911 }
912 attributes.sort();
913 for (i = 0; i < attributes.length; i++) {
914 var attrs = attributes[i];
915 for (var j = 0; j < attrs.length; j++) {
916 lst.push(attrs[j]);
917 }
918 }
919 if (dom.hasChildNodes()) {
920 lst.push(">");
921 // queue is the FILO call stack, so we put the close tag
922 // on first
923 queue.push("</" + dom.tagName.toLowerCase() + ">");
924 var cnodes = dom.childNodes;
925 for (i = cnodes.length - 1; i >= 0; i--) {
926 queue.push(cnodes[i]);
927 }
928 } else {
929 lst.push('/>');
930 }
931 } else if (dom.nodeType == 3) {
932 lst.push(escapeHTML(dom.nodeValue));
933 }
934 }
935 return lst;
936 },
937
938 /** @id MochiKit.DOM.scrapeText */
939 scrapeText: function (node, /* optional */asArray) {
940 var rval = [];
941 (function (node) {
942 var cn = node.childNodes;
943 if (cn) {
944 for (var i = 0; i < cn.length; i++) {
945 arguments.callee.call(this, cn[i]);
946 }
947 }
948 var nodeValue = node.nodeValue;
949 if (typeof(nodeValue) == 'string') {
950 rval.push(nodeValue);
951 }
952 })(MochiKit.DOM.getElement(node));
953 if (asArray) {
954 return rval;
955 } else {
956 return rval.join("");
957 }
958 },
959
960 /** @id MochiKit.DOM.removeEmptyTextNodes */
961 removeEmptyTextNodes: function (element) {
962 element = MochiKit.DOM.getElement(element);
963 for (var i = 0; i < element.childNodes.length; i++) {
964 var node = element.childNodes[i];
965 if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) {
966 node.parentNode.removeChild(node);
967 }
968 }
969 },
970
971 /** @id MochiKit.DOM.makeClipping */
972 makeClipping: function (element) {
973 element = MochiKit.DOM.getElement(element);
974 var oldOverflow = element.style.overflow;
975 if ((MochiKit.Style.getStyle(element, 'overflow') || 'visible') != 'hidden') {
976 element.style.overflow = 'hidden';
977 }
978 return oldOverflow;
979 },
980
981 /** @id MochiKit.DOM.undoClipping */
982 undoClipping: function (element, overflow) {
983 element = MochiKit.DOM.getElement(element);
984 if (!overflow) {
985 return;
986 }
987 element.style.overflow = overflow;
988 },
989
990 /** @id MochiKit.DOM.makePositioned */
991 makePositioned: function (element) {
992 element = MochiKit.DOM.getElement(element);
993 var pos = MochiKit.Style.getStyle(element, 'position');
994 if (pos == 'static' || !pos) {
995 element.style.position = 'relative';
996 // Opera returns the offset relative to the positioning context,
997 // when an element is position relative but top and left have
998 // not been defined
999 if (/Opera/.test(navigator.userAgent)) {
1000 element.style.top = 0;
1001 element.style.left = 0;
1002 }
1003 }
1004 },
1005
1006 /** @id MochiKit.DOM.undoPositioned */
1007 undoPositioned: function (element) {
1008 element = MochiKit.DOM.getElement(element);
1009 if (element.style.position == 'relative') {
1010 element.style.position = element.style.top = element.style.left = element.style.bottom = element.style.right = '';
1011 }
1012 },
1013
1014 /** @id MochiKit.DOM.getFirstElementByTagAndClassName */
1015 getFirstElementByTagAndClassName: function (tagName, className,
1016 /* optional */parent) {
1017 var self = MochiKit.DOM;
1018 if (typeof(tagName) == 'undefined' || tagName === null) {
1019 tagName = '*';
1020 }
1021 if (typeof(parent) == 'undefined' || parent === null) {
1022 parent = self._document;
1023 }
1024 parent = self.getElement(parent);
1025 var children = (parent.getElementsByTagName(tagName)
1026 || self._document.all);
1027 if (typeof(className) == 'undefined' || className === null) {
1028 return children[0];
1029 }
1030
1031 for (var i = 0; i < children.length; i++) {
1032 var child = children[i];
1033 var classNames = child.className.split(' ');
1034 for (var j = 0; j < classNames.length; j++) {
1035 if (classNames[j] == className) {
1036 return child;
1037 }
1038 }
1039 }
1040 },
1041
1042 /** @id MochiKit.DOM.getFirstParentByTagAndClassName */
1043 getFirstParentByTagAndClassName: function (elem, tagName, className) {
1044 var self = MochiKit.DOM;
1045 elem = self.getElement(elem);
1046 if (typeof(tagName) == 'undefined' || tagName === null) {
1047 tagName = '*';
1048 } else {
1049 tagName = tagName.toUpperCase();
1050 }
1051 if (typeof(className) == 'undefined' || className === null) {
1052 className = null;
1053 }
1054
1055 var classList = '';
1056 var curTagName = '';
1057 while (elem && elem.tagName) {
1058 elem = elem.parentNode;
1059 if (tagName == '*' && className === null) {
1060 return elem;
1061 }
1062 classList = elem.className.split(' ');
1063 curTagName = elem.tagName.toUpperCase();
1064 if (className === null && tagName == curTagName) {
1065 return elem;
1066 } else if (className !== null) {
1067 for (var i = 0; i < classList.length; i++) {
1068 if (tagName == '*' && classList[i] == className) {
1069 return elem;
1070 } else if (tagName == curTagName && classList[i] == className) {
1071 return elem;
1072 }
1073 }
1074 }
1075 }
1076 return elem;
1077 },
1078
1079 /** @id MochiKit.DOM.isParent */
1080 isParent: function (child, element) {
1081 if (!child.parentNode || child == element) {
1082 return false;
1083 }
1084
1085 if (child.parentNode == element) {
1086 return true;
1087 }
1088
1089 return MochiKit.DOM.isParent(child.parentNode, element);
1090 },
1091
1092 __new__: function (win) {
1093
1094 var m = MochiKit.Base;
1095 if (typeof(document) != "undefined") {
1096 this._document = document;
1097 var kXULNSURI = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
1098 this._xhtml = (document.documentElement &&
1099 document.createElementNS &&
1100 document.documentElement.namespaceURI === kXULNSURI);
1101 } else if (MochiKit.MockDOM) {
1102 this._document = MochiKit.MockDOM.document;
1103 }
1104 this._window = win;
1105
1106 this.domConverters = new m.AdapterRegistry();
1107
1108 var __tmpElement = this._document.createElement("span");
1109 var attributeArray;
1110 if (__tmpElement && __tmpElement.attributes &&
1111 __tmpElement.attributes.length > 0) {
1112 // for braindead browsers (IE) that insert extra junk
1113 var filter = m.filter;
1114 attributeArray = function (node) {
1115 return filter(attributeArray.ignoreAttrFilter, node.attributes);
1116 };
1117 attributeArray.ignoreAttr = {};
1118 var attrs = __tmpElement.attributes;
1119 var ignoreAttr = attributeArray.ignoreAttr;
1120 for (var i = 0; i < attrs.length; i++) {
1121 var a = attrs[i];
1122 ignoreAttr[a.name] = a.value;
1123 }
1124 attributeArray.ignoreAttrFilter = function (a) {
1125 return (attributeArray.ignoreAttr[a.name] != a.value);
1126 };
1127 attributeArray.compliant = false;
1128 attributeArray.renames = {
1129 "class": "className",
1130 "checked": "defaultChecked",
1131 "usemap": "useMap",
1132 "for": "htmlFor",
1133 "readonly": "readOnly",
1134 "colspan": "colSpan",
1135 "bgcolor": "bgColor"
1136 };
1137 } else {
1138 attributeArray = function (node) {
1139 /***
1140
1141 Return an array of attributes for a given node,
1142 filtering out attributes that don't belong for
1143 that are inserted by "Certain Browsers".
1144
1145 ***/
1146 return node.attributes;
1147 };
1148 attributeArray.compliant = true;
1149 attributeArray.renames = {};
1150 }
1151 this.attributeArray = attributeArray;
1152
1153 // FIXME: this really belongs in Base, and could probably be cleaner
1154 var _deprecated = function(fromModule, arr) {
1155 var modules = arr[1].split('.');
1156 var str = '';
1157 var obj = {};
1158
1159 str += 'if (!MochiKit.' + modules[1] + ') { throw new Error("';
1160 str += 'This function has been deprecated and depends on MochiKit.';
1161 str += modules[1] + '.");}';
1162 str += 'return MochiKit.' + modules[1] + '.' + arr[0];
1163 str += '.apply(this, arguments);';
1164
1165 obj[modules[2]] = new Function(str);
1166 MochiKit.Base.update(MochiKit[fromModule], obj);
1167 }
1168 for (var i; i < MochiKit.DOM.DEPRECATED.length; i++) {
1169 _deprecated('DOM', MochiKit.DOM.DEPRECATED[i]);
1170 }
1171
1172 // shorthand for createDOM syntax
1173 var createDOMFunc = this.createDOMFunc;
1174 /** @id MochiKit.DOM.UL */
1175 this.UL = createDOMFunc("ul");
1176 /** @id MochiKit.DOM.OL */
1177 this.OL = createDOMFunc("ol");
1178 /** @id MochiKit.DOM.LI */
1179 this.LI = createDOMFunc("li");
1180 /** @id MochiKit.DOM.TD */
1181 this.TD = createDOMFunc("td");
1182 /** @id MochiKit.DOM.TR */
1183 this.TR = createDOMFunc("tr");
1184 /** @id MochiKit.DOM.TBODY */
1185 this.TBODY = createDOMFunc("tbody");
1186 /** @id MochiKit.DOM.THEAD */
1187 this.THEAD = createDOMFunc("thead");
1188 /** @id MochiKit.DOM.TFOOT */
1189 this.TFOOT = createDOMFunc("tfoot");
1190 /** @id MochiKit.DOM.TABLE */
1191 this.TABLE = createDOMFunc("table");
1192 /** @id MochiKit.DOM.TH */
1193 this.TH = createDOMFunc("th");
1194 /** @id MochiKit.DOM.INPUT */
1195 this.INPUT = createDOMFunc("input");
1196 /** @id MochiKit.DOM.SPAN */
1197 this.SPAN = createDOMFunc("span");
1198 /** @id MochiKit.DOM.A */
1199 this.A = createDOMFunc("a");
1200 /** @id MochiKit.DOM.DIV */
1201 this.DIV = createDOMFunc("div");
1202 /** @id MochiKit.DOM.IMG */
1203 this.IMG = createDOMFunc("img");
1204 /** @id MochiKit.DOM.BUTTON */
1205 this.BUTTON = createDOMFunc("button");
1206 /** @id MochiKit.DOM.TT */
1207 this.TT = createDOMFunc("tt");
1208 /** @id MochiKit.DOM.PRE */
1209 this.PRE = createDOMFunc("pre");
1210 /** @id MochiKit.DOM.H1 */
1211 this.H1 = createDOMFunc("h1");
1212 /** @id MochiKit.DOM.H2 */
1213 this.H2 = createDOMFunc("h2");
1214 /** @id MochiKit.DOM.H3 */
1215 this.H3 = createDOMFunc("h3");
1216 /** @id MochiKit.DOM.BR */
1217 this.BR = createDOMFunc("br");
1218 /** @id MochiKit.DOM.HR */
1219 this.HR = createDOMFunc("hr");
1220 /** @id MochiKit.DOM.LABEL */
1221 this.LABEL = createDOMFunc("label");
1222 /** @id MochiKit.DOM.TEXTAREA */
1223 this.TEXTAREA = createDOMFunc("textarea");
1224 /** @id MochiKit.DOM.FORM */
1225 this.FORM = createDOMFunc("form");
1226 /** @id MochiKit.DOM.P */
1227 this.P = createDOMFunc("p");
1228 /** @id MochiKit.DOM.SELECT */
1229 this.SELECT = createDOMFunc("select");
1230 /** @id MochiKit.DOM.OPTION */
1231 this.OPTION = createDOMFunc("option");
1232 /** @id MochiKit.DOM.OPTGROUP */
1233 this.OPTGROUP = createDOMFunc("optgroup");
1234 /** @id MochiKit.DOM.LEGEND */
1235 this.LEGEND = createDOMFunc("legend");
1236 /** @id MochiKit.DOM.FIELDSET */
1237 this.FIELDSET = createDOMFunc("fieldset");
1238 /** @id MochiKit.DOM.STRONG */
1239 this.STRONG = createDOMFunc("strong");
1240 /** @id MochiKit.DOM.CANVAS */
1241 this.CANVAS = createDOMFunc("canvas");
1242
1243 /** @id MochiKit.DOM.$ */
1244 this.$ = this.getElement;
1245
1246 this.EXPORT_TAGS = {
1247 ":common": this.EXPORT,
1248 ":all": m.concat(this.EXPORT, this.EXPORT_OK)
1249 };
1250
1251 m.nameFunctions(this);
1252
1253 }
1254});
1255
1256
1257MochiKit.DOM.__new__(((typeof(window) == "undefined") ? this : window));
1258
1259//
1260// XXX: Internet Explorer blows
1261//
1262if (MochiKit.__export__) {
1263 withWindow = MochiKit.DOM.withWindow;
1264 withDocument = MochiKit.DOM.withDocument;
1265}
1266
1267MochiKit.Base._exportSymbols(this, MochiKit.DOM);