5 See <http://mochikit.com/> for documentation, downloads, license, etc.
7 (c) 2005 Bob Ippolito. All rights Reserved.
11 if (typeof(dojo
) != 'undefined') {
12 dojo
.provide("MochiKit.DOM");
13 dojo
.require("MochiKit.Base");
15 if (typeof(JSAN
) != 'undefined') {
16 JSAN
.use("MochiKit.Base", []);
20 if (typeof(MochiKit
.Base
) == 'undefined') {
24 throw "MochiKit.DOM depends on MochiKit.Base!";
27 if (typeof(MochiKit
.DOM
) == 'undefined') {
31 MochiKit
.DOM
.NAME
= "MochiKit.DOM";
32 MochiKit
.DOM
.VERSION
= "1.4";
33 MochiKit
.DOM
.__repr__
= function () {
34 return "[" + this.NAME
+ " " + this.VERSION
+ "]";
36 MochiKit
.DOM
.toString
= function () {
37 return this.__repr__();
40 MochiKit
.DOM
.EXPORT
= [
41 "removeEmptyTextNodes",
47 "registerDOMConverter",
53 "removeNodeAttribute",
55 "updateNodeAttributes",
57 "insertSiblingNodesAfter",
58 "insertSiblingNodesBefore",
98 "getElementsByTagAndClassName",
103 "toggleElementClass",
105 "removeElementClass",
113 "getFirstParentByTagAndClassName",
118 "getFirstElementByTagAndClassName"
121 MochiKit
.DOM
.EXPORT_OK
= [
125 MochiKit
.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
146 /** @id MochiKit.DOM.getViewportDimensions */
147 MochiKit
.DOM
.getViewportDimensions
= new Function('' +
148 'if (!MochiKit["Style"]) {' +
149 ' throw new Error("This function has been deprecated and depends on MochiKit.Style.");' +
151 'return MochiKit.Style.getViewportDimensions.apply(this, arguments);');
153 MochiKit
.Base
.update(MochiKit
.DOM
, {
155 /** @id MochiKit.DOM.currentWindow */
156 currentWindow
: function () {
157 return MochiKit
.DOM
._window
;
160 /** @id MochiKit.DOM.currentDocument */
161 currentDocument
: function () {
162 return MochiKit
.DOM
._document
;
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
;
173 self
._document
= win
.document
;
176 self
._window
= oldWin
;
177 self
._document
= oldDoc
;
180 self
._window
= oldWin
;
181 self
._document
= oldDoc
;
185 /** @id MochiKit.DOM.formContents */
186 formContents
: function (elem
/* = document.body */) {
189 var m
= MochiKit
.Base
;
190 var self
= MochiKit
.DOM
;
191 if (typeof(elem
) == "undefined" || elem
=== null) {
192 elem
= self
._document
.body
;
194 elem
= self
.getElement(elem
);
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")
206 if (tagName
=== "SELECT") {
207 if (elem
.type
== "select-one") {
208 if (elem
.selectedIndex
>= 0) {
209 var opt
= elem
.options
[elem
.selectedIndex
];
212 var h
= opt
.outerHTML
;
213 // internet explorer sure does suck.
214 if (h
&& !h
.match(/^[^>]+\svalue\s*=/i)) {
227 var opts
= elem
.options
;
233 for (var i
= 0; i
< opts
.length
; i
++) {
240 var h
= opt
.outerHTML
;
241 // internet explorer sure does suck.
242 if (h
&& !h
.match(/^[^>]+\svalue\s*=/i)) {
252 if (tagName
=== "FORM" || tagName
=== "P" || tagName
=== "SPAN"
255 return elem
.childNodes
;
258 values
.push(elem
.value
|| '');
261 return elem
.childNodes
;
263 return [names
, values
];
266 /** @id MochiKit.DOM.withDocument */
267 withDocument
: function (doc
, func
) {
268 var self
= MochiKit
.DOM
;
269 var oldDoc
= self
._document
;
272 self
._document
= doc
;
275 self
._document
= oldDoc
;
278 self
._document
= oldDoc
;
282 /** @id MochiKit.DOM.registerDOMConverter */
283 registerDOMConverter
: function (name
, check
, wrap
, /* optional */override
) {
284 MochiKit
.DOM
.domConverters
.register(name
, check
, wrap
, override
);
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
;
294 var repeat
= im
.repeat
;
297 var domConverters
= self
.domConverters
;
298 var coerceToDOM
= arguments
.callee
;
299 var NotFound
= m
.NotFound
;
301 if (typeof(node
) == 'undefined' || node
=== null) {
304 // this is a safari childNodes object, avoiding crashes w/ attr
306 if (typeof(node
) == "function" &&
307 typeof(node
.length
) == "number" &&
308 !(node
instanceof Function
)) {
309 node
= im
.list(node
);
311 if (typeof(node
.nodeType
) != 'undefined' && node
.nodeType
> 0) {
314 if (typeof(node
) == 'number' || typeof(node
) == 'boolean') {
315 node
= node
.toString();
318 if (typeof(node
) == 'string') {
319 return self
._document
.createTextNode(node
);
321 if (typeof(node
.__dom__
) == 'function') {
322 node
= node
.__dom__(ctx
);
325 if (typeof(node
.dom
) == 'function') {
326 node
= node
.dom(ctx
);
329 if (typeof(node
) == 'function') {
330 node
= node
.apply(ctx
, [ctx
]);
336 var iterNodes
= null;
338 iterNodes
= iter(node
);
343 return map(coerceToDOM
, iterNodes
, repeat(ctx
));
349 node
= domConverters
.match(node
, ctx
);
358 return self
._document
.createTextNode(node
.toString());
360 // mozilla warnings aren't too bright
364 /** @id MochiKit.DOM.isChildNode */
365 isChildNode
: function (node
, maybeparent
) {
366 var self
= MochiKit
.DOM
;
367 if (typeof(node
) == "string") {
368 node
= self
.getElement(node
);
370 if (typeof(maybeparent
) == "string") {
371 maybeparent
= self
.getElement(maybeparent
);
373 if (node
=== maybeparent
) {
376 while (node
&& node
.tagName
.toUpperCase() != "BODY") {
377 node
= node
.parentNode
;
378 if (node
=== maybeparent
) {
385 /** @id MochiKit.DOM.setNodeAttribute */
386 setNodeAttribute
: function (node
, attr
, value
) {
390 return MochiKit
.DOM
.updateNodeAttributes(node
, o
);
397 /** @id MochiKit.DOM.getNodeAttribute */
398 getNodeAttribute
: function (node
, attr
) {
399 var self
= MochiKit
.DOM
;
400 var rename
= self
.attributeArray
.renames
[attr
];
401 node
= self
.getElement(node
);
406 return node
.getAttribute(attr
);
413 /** @id MochiKit.DOM.removeNodeAttribute */
414 removeNodeAttribute
: function (node
, attr
) {
415 var self
= MochiKit
.DOM
;
416 var rename
= self
.attributeArray
.renames
[attr
];
417 node
= self
.getElement(node
);
422 return node
.removeAttribute(attr
);
429 /** @id MochiKit.DOM.updateNodeAttributes */
430 updateNodeAttributes
: function (node
, attrs
) {
432 var self
= MochiKit
.DOM
;
433 if (typeof(node
) == 'string') {
434 elem
= self
.getElement(node
);
437 var updatetree
= MochiKit
.Base
.updatetree
;
438 if (self
.attributeArray
.compliant
) {
440 for (var k
in attrs
) {
442 if (typeof(v
) == 'object' && typeof(elem
[k
]) == 'object') {
443 if (k
== "style" && MochiKit
.Style
) {
444 MochiKit
.Style
.setStyle(elem
, v
);
446 updatetree(elem
[k
], v
);
448 } else if (k
.substring(0, 2) == "on") {
449 if (typeof(v
) == "string") {
454 elem
.setAttribute(k
, v
);
458 // IE is insane in the membrane
459 var renames
= self
.attributeArray
.renames
;
460 for (var k
in attrs
) {
462 var renamed
= renames
[k
];
463 if (k
== "style" && typeof(v
) == "string") {
464 elem
.style
.cssText
= v
;
465 } else if (typeof(renamed
) == "string") {
467 } else if (typeof(elem
[k
]) == 'object'
468 && typeof(v
) == 'object') {
469 if (k
== "style" && MochiKit
.Style
) {
470 MochiKit
.Style
.setStyle(elem
, v
);
472 updatetree(elem
[k
], v
);
474 } else if (k
.substring(0, 2) == "on") {
475 if (typeof(v
) == "string") {
480 elem
.setAttribute(k
, v
);
488 /** @id MochiKit.DOM.appendChildNodes */
489 appendChildNodes
: function (node
/*, nodes...*/) {
491 var self
= MochiKit
.DOM
;
492 if (typeof(node
) == 'string') {
493 elem
= self
.getElement(node
);
497 MochiKit
.Base
.extend(null, arguments
, 1),
501 var concat
= MochiKit
.Base
.concat
;
502 while (nodeStack
.length
) {
503 var n
= nodeStack
.shift();
504 if (typeof(n
) == 'undefined' || n
=== null) {
506 } else if (typeof(n
.nodeType
) == 'number') {
509 nodeStack
= concat(n
, nodeStack
);
516 /** @id MochiKit.DOM.insertSiblingNodesBefore */
517 insertSiblingNodesBefore
: function (node
/*, nodes...*/) {
519 var self
= MochiKit
.DOM
;
520 if (typeof(node
) == 'string') {
521 elem
= self
.getElement(node
);
525 MochiKit
.Base
.extend(null, arguments
, 1),
529 var parentnode
= elem
.parentNode
;
530 var concat
= MochiKit
.Base
.concat
;
531 while (nodeStack
.length
) {
532 var n
= nodeStack
.shift();
533 if (typeof(n
) == 'undefined' || n
=== null) {
535 } else if (typeof(n
.nodeType
) == 'number') {
536 parentnode
.insertBefore(n
, elem
);
538 nodeStack
= concat(n
, nodeStack
);
544 /** @id MochiKit.DOM.insertSiblingNodesAfter */
545 insertSiblingNodesAfter
: function (node
/*, nodes...*/) {
547 var self
= MochiKit
.DOM
;
549 if (typeof(node
) == 'string') {
550 elem
= self
.getElement(node
);
554 MochiKit
.Base
.extend(null, arguments
, 1),
559 if (elem
.nextSibling
) {
560 return self
.insertSiblingNodesBefore(elem
.nextSibling
, nodeStack
);
563 return self
.appendChildNodes(elem
.parentNode
, nodeStack
);
567 /** @id MochiKit.DOM.replaceChildNodes */
568 replaceChildNodes
: function (node
/*, nodes...*/) {
570 var self
= MochiKit
.DOM
;
571 if (typeof(node
) == 'string') {
572 elem
= self
.getElement(node
);
576 while ((child
= elem
.firstChild
)) {
577 elem
.removeChild(child
);
579 if (arguments
.length
< 2) {
582 return self
.appendChildNodes
.apply(this, arguments
);
586 /** @id MochiKit.DOM.createDOM */
587 createDOM
: function (name
, attrs
/*, nodes... */) {
589 var self
= MochiKit
.DOM
;
590 var m
= MochiKit
.Base
;
591 if (typeof(attrs
) == "string" || typeof(attrs
) == "number") {
592 var args
= m
.extend([name
, null], arguments
, 1);
593 return arguments
.callee
.apply(this, args
);
595 if (typeof(name
) == 'string') {
596 // Internet Explorer is dumb
597 var xhtml
= self
._xhtml
;
598 if (attrs
&& !self
.attributeArray
.compliant
) {
599 // http://msdn.microsoft.com/workshop
/author/dhtml/reference/properties/name_2
.asp
601 if ('name' in attrs
) {
602 contents
+= ' name="' + self
.escapeHTML(attrs
.name
) + '"';
604 if (name
== 'input' && 'type' in attrs
) {
605 contents
+= ' type="' + self
.escapeHTML(attrs
.type
) + '"';
608 name
= "<" + name
+ contents
+ ">";
612 var d
= self
._document
;
613 if (xhtml
&& d
=== document
) {
614 elem
= d
.createElementNS("http://www.w3.org/1999/xhtml", name
);
616 elem
= d
.createElement(name
);
622 self
.updateNodeAttributes(elem
, attrs
);
624 if (arguments
.length
<= 2) {
627 var args
= m
.extend([elem
], arguments
, 2);
628 return self
.appendChildNodes
.apply(this, args
);
632 /** @id MochiKit.DOM.createDOMFunc */
633 createDOMFunc
: function (/* tag, attrs, *nodes */) {
634 var m
= MochiKit
.Base
;
635 return m
.partial
.apply(
637 m
.extend([MochiKit
.DOM
.createDOM
], arguments
)
641 /** @id MochiKit.DOM.removeElement */
642 removeElement
: function (elem
) {
643 var e
= MochiKit
.DOM
.getElement(elem
);
644 e
.parentNode
.removeChild(e
);
648 /** @id MochiKit.DOM.swapDOM */
649 swapDOM
: function (dest
, src
) {
650 var self
= MochiKit
.DOM
;
651 dest
= self
.getElement(dest
);
652 var parent
= dest
.parentNode
;
654 src
= self
.getElement(src
);
655 parent
.replaceChild(src
, dest
);
657 parent
.removeChild(dest
);
662 /** @id MochiKit.DOM.getElement */
663 getElement
: function (id
) {
664 var self
= MochiKit
.DOM
;
665 if (arguments
.length
== 1) {
666 return ((typeof(id
) == "string") ?
667 self
._document
.getElementById(id
) : id
);
669 return MochiKit
.Base
.map(self
.getElement
, arguments
);
673 /** @id MochiKit.DOM.getElementsByTagAndClassName */
674 getElementsByTagAndClassName
: function (tagName
, className
,
675 /* optional */parent
) {
676 var self
= MochiKit
.DOM
;
677 if (typeof(tagName
) == 'undefined' || tagName
=== null) {
680 if (typeof(parent
) == 'undefined' || parent
=== null) {
681 parent
= self
._document
;
683 parent
= self
.getElement(parent
);
684 var children
= (parent
.getElementsByTagName(tagName
)
685 || self
._document
.all
);
686 if (typeof(className
) == 'undefined' || className
=== null) {
687 return MochiKit
.Base
.extend(null, children
);
691 for (var i
= 0; i
< children
.length
; i
++) {
692 var child
= children
[i
];
693 var cls
= child
.className
;
697 var classNames
= cls
.split(' ');
698 for (var j
= 0; j
< classNames
.length
; j
++) {
699 if (classNames
[j
] == className
) {
700 elements
.push(child
);
709 _newCallStack
: function (path
, once
) {
710 var rval
= function () {
711 var callStack
= arguments
.callee
.callStack
;
712 for (var i
= 0; i
< callStack
.length
; i
++) {
713 if (callStack
[i
].apply(this, arguments
) === false) {
729 /** @id MochiKit.DOM.addToCallStack */
730 addToCallStack
: function (target
, path
, func
, once
) {
731 var self
= MochiKit
.DOM
;
732 var existing
= target
[path
];
733 var regfunc
= existing
;
734 if (!(typeof(existing
) == 'function'
735 && typeof(existing
.callStack
) == "object"
736 && existing
.callStack
!== null)) {
737 regfunc
= self
._newCallStack(path
, once
);
738 if (typeof(existing
) == 'function') {
739 regfunc
.callStack
.push(existing
);
741 target
[path
] = regfunc
;
743 regfunc
.callStack
.push(func
);
746 /** @id MochiKit.DOM.addLoadEvent */
747 addLoadEvent
: function (func
) {
748 var self
= MochiKit
.DOM
;
749 self
.addToCallStack(self
._window
, "onload", func
, true);
753 /** @id MochiKit.DOM.focusOnLoad */
754 focusOnLoad
: function (element
) {
755 var self
= MochiKit
.DOM
;
756 self
.addLoadEvent(function () {
757 element
= self
.getElement(element
);
764 /** @id MochiKit.DOM.setElementClass */
765 setElementClass
: function (element
, className
) {
766 var self
= MochiKit
.DOM
;
767 var obj
= self
.getElement(element
);
768 if (self
.attributeArray
.compliant
) {
769 obj
.setAttribute("class", className
);
771 obj
.setAttribute("className", className
);
775 /** @id MochiKit.DOM.toggleElementClass */
776 toggleElementClass
: function (className
/*, element... */) {
777 var self
= MochiKit
.DOM
;
778 for (var i
= 1; i
< arguments
.length
; i
++) {
779 var obj
= self
.getElement(arguments
[i
]);
780 if (!self
.addElementClass(obj
, className
)) {
781 self
.removeElementClass(obj
, className
);
786 /** @id MochiKit.DOM.addElementClass */
787 addElementClass
: function (element
, className
) {
788 var self
= MochiKit
.DOM
;
789 var obj
= self
.getElement(element
);
790 var cls
= obj
.className
;
791 // trivial case, no className yet
792 if (cls
== undefined
|| cls
.length
=== 0) {
793 self
.setElementClass(obj
, className
);
796 // the other trivial case, already set as the only class
797 if (cls
== className
) {
800 var classes
= cls
.split(" ");
801 for (var i
= 0; i
< classes
.length
; i
++) {
803 if (classes
[i
] == className
) {
808 self
.setElementClass(obj
, cls
+ " " + className
);
812 /** @id MochiKit.DOM.removeElementClass */
813 removeElementClass
: function (element
, className
) {
814 var self
= MochiKit
.DOM
;
815 var obj
= self
.getElement(element
);
816 var cls
= obj
.className
;
817 // trivial case, no className yet
818 if (cls
== undefined
|| cls
.length
=== 0) {
821 // other trivial case, set only to className
822 if (cls
== className
) {
823 self
.setElementClass(obj
, "");
826 var classes
= cls
.split(" ");
827 for (var i
= 0; i
< classes
.length
; i
++) {
829 if (classes
[i
] == className
) {
830 // only check sane case where the class is used once
831 classes
.splice(i
, 1);
832 self
.setElementClass(obj
, classes
.join(" "));
840 /** @id MochiKit.DOM.swapElementClass */
841 swapElementClass
: function (element
, fromClass
, toClass
) {
842 var obj
= MochiKit
.DOM
.getElement(element
);
843 var res
= MochiKit
.DOM
.removeElementClass(obj
, fromClass
);
845 MochiKit
.DOM
.addElementClass(obj
, toClass
);
850 /** @id MochiKit.DOM.hasElementClass */
851 hasElementClass
: function (element
, className
/*...*/) {
852 var obj
= MochiKit
.DOM
.getElement(element
);
853 var cls
= obj
.className
;
857 var classes
= cls
.split(" ");
858 for (var i
= 1; i
< arguments
.length
; i
++) {
860 for (var j
= 0; j
< classes
.length
; j
++) {
861 if (classes
[j
] == arguments
[i
]) {
873 /** @id MochiKit.DOM.escapeHTML */
874 escapeHTML
: function (s
) {
875 return s
.replace(/&/g, "&"
876 ).replace(/"/g, """
877 ).replace(/</g, "<"
878 ).replace(/>/g, ">");
881 /** @id MochiKit.DOM.toHTML */
882 toHTML
: function (dom
) {
883 return MochiKit
.DOM
.emitHTML(dom
).join("");
886 /** @id MochiKit.DOM.emitHTML */
887 emitHTML
: function (dom
, /* optional */lst
) {
888 if (typeof(lst
) == 'undefined' || lst
=== null) {
891 // queue is the call stack, we're doing this non-recursively
893 var self
= MochiKit
.DOM
;
894 var escapeHTML
= self
.escapeHTML
;
895 var attributeArray
= self
.attributeArray
;
896 while (queue
.length
) {
898 if (typeof(dom
) == 'string') {
900 } else if (dom
.nodeType
== 1) {
901 // we're not using higher order stuff here
902 // because safari has heisenbugs.. argh.
904 // I think it might have something to do with
905 // garbage collection and function calls.
906 lst
.push('<' + dom
.tagName
.toLowerCase());
908 var domAttr
= attributeArray(dom
);
909 for (var i
= 0; i
< domAttr
.length
; i
++) {
920 for (i
= 0; i
< attributes
.length
; i
++) {
921 var attrs
= attributes
[i
];
922 for (var j
= 0; j
< attrs
.length
; j
++) {
926 if (dom
.hasChildNodes()) {
928 // queue is the FILO call stack, so we put the close tag
930 queue
.push("</" + dom
.tagName
.toLowerCase() + ">");
931 var cnodes
= dom
.childNodes
;
932 for (i
= cnodes
.length
- 1; i
>= 0; i
--) {
933 queue
.push(cnodes
[i
]);
938 } else if (dom
.nodeType
== 3) {
939 lst
.push(escapeHTML(dom
.nodeValue
));
945 /** @id MochiKit.DOM.scrapeText */
946 scrapeText
: function (node
, /* optional */asArray
) {
949 var cn
= node
.childNodes
;
951 for (var i
= 0; i
< cn
.length
; i
++) {
952 arguments
.callee
.call(this, cn
[i
]);
955 var nodeValue
= node
.nodeValue
;
956 if (typeof(nodeValue
) == 'string') {
957 rval
.push(nodeValue
);
959 })(MochiKit
.DOM
.getElement(node
));
963 return rval
.join("");
967 /** @id MochiKit.DOM.removeEmptyTextNodes */
968 removeEmptyTextNodes
: function (element
) {
969 element
= MochiKit
.DOM
.getElement(element
);
970 for (var i
= 0; i
< element
.childNodes
.length
; i
++) {
971 var node
= element
.childNodes
[i
];
972 if (node
.nodeType
== 3 && !/\S/.test(node
.nodeValue
)) {
973 node
.parentNode
.removeChild(node
);
978 /** @id MochiKit.DOM.makeClipping */
979 makeClipping
: function (element
) {
980 element
= MochiKit
.DOM
.getElement(element
);
981 var oldOverflow
= element
.style
.overflow
;
982 if ((MochiKit
.Style
.getStyle(element
, 'overflow') || 'visible') != 'hidden') {
983 element
.style
.overflow
= 'hidden';
988 /** @id MochiKit.DOM.undoClipping */
989 undoClipping
: function (element
, overflow
) {
990 element
= MochiKit
.DOM
.getElement(element
);
994 element
.style
.overflow
= overflow
;
997 /** @id MochiKit.DOM.makePositioned */
998 makePositioned
: function (element
) {
999 element
= MochiKit
.DOM
.getElement(element
);
1000 var pos
= MochiKit
.Style
.getStyle(element
, 'position');
1001 if (pos
== 'static' || !pos
) {
1002 element
.style
.position
= 'relative';
1003 // Opera returns the offset relative to the positioning context,
1004 // when an element is position relative but top and left have
1006 if (/Opera/.test(navigator
.userAgent
)) {
1007 element
.style
.top
= 0;
1008 element
.style
.left
= 0;
1013 /** @id MochiKit.DOM.undoPositioned */
1014 undoPositioned
: function (element
) {
1015 element
= MochiKit
.DOM
.getElement(element
);
1016 if (element
.style
.position
== 'relative') {
1017 element
.style
.position
= element
.style
.top
= element
.style
.left
= element
.style
.bottom
= element
.style
.right
= '';
1021 /** @id MochiKit.DOM.getFirstElementByTagAndClassName */
1022 getFirstElementByTagAndClassName
: function (tagName
, className
,
1023 /* optional */parent
) {
1024 var self
= MochiKit
.DOM
;
1025 if (typeof(tagName
) == 'undefined' || tagName
=== null) {
1028 if (typeof(parent
) == 'undefined' || parent
=== null) {
1029 parent
= self
._document
;
1031 parent
= self
.getElement(parent
);
1032 var children
= (parent
.getElementsByTagName(tagName
)
1033 || self
._document
.all
);
1034 if (typeof(className
) == 'undefined' || className
=== null) {
1038 for (var i
= 0; i
< children
.length
; i
++) {
1039 var child
= children
[i
];
1040 var classNames
= child
.className
.split(' ');
1041 for (var j
= 0; j
< classNames
.length
; j
++) {
1042 if (classNames
[j
] == className
) {
1049 /** @id MochiKit.DOM.getFirstParentByTagAndClassName */
1050 getFirstParentByTagAndClassName
: function (elem
, tagName
, className
) {
1051 var self
= MochiKit
.DOM
;
1052 elem
= self
.getElement(elem
);
1053 if (typeof(tagName
) == 'undefined' || tagName
=== null) {
1056 tagName
= tagName
.toUpperCase();
1058 if (typeof(className
) == 'undefined' || className
=== null) {
1063 var curTagName
= '';
1064 while (elem
&& elem
.tagName
) {
1065 elem
= elem
.parentNode
;
1066 if (tagName
== '*' && className
=== null) {
1069 classList
= elem
.className
.split(' ');
1070 curTagName
= elem
.tagName
.toUpperCase();
1071 if (className
=== null && tagName
== curTagName
) {
1073 } else if (className
!== null) {
1074 for (var i
= 0; i
< classList
.length
; i
++) {
1075 if (tagName
== '*' && classList
[i
] == className
) {
1077 } else if (tagName
== curTagName
&& classList
[i
] == className
) {
1086 /** @id MochiKit.DOM.isParent */
1087 isParent
: function (child
, element
) {
1088 if (!child
.parentNode
|| child
== element
) {
1092 if (child
.parentNode
== element
) {
1096 return MochiKit
.DOM
.isParent(child
.parentNode
, element
);
1099 __new__
: function (win
) {
1101 var m
= MochiKit
.Base
;
1102 if (typeof(document
) != "undefined") {
1103 this._document
= document
;
1104 var kXULNSURI
= "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
1105 this._xhtml
= (document
.documentElement
&&
1106 document
.createElementNS
&&
1107 document
.documentElement
.namespaceURI
=== kXULNSURI
);
1108 } else if (MochiKit
.MockDOM
) {
1109 this._document
= MochiKit
.MockDOM
.document
;
1113 this.domConverters
= new m
.AdapterRegistry();
1115 var __tmpElement
= this._document
.createElement("span");
1117 if (__tmpElement
&& __tmpElement
.attributes
&&
1118 __tmpElement
.attributes
.length
> 0) {
1119 // for braindead browsers (IE) that insert extra junk
1120 var filter
= m
.filter
;
1121 attributeArray
= function (node
) {
1122 return filter(attributeArray
.ignoreAttrFilter
, node
.attributes
);
1124 attributeArray
.ignoreAttr
= {};
1125 var attrs
= __tmpElement
.attributes
;
1126 var ignoreAttr
= attributeArray
.ignoreAttr
;
1127 for (var i
= 0; i
< attrs
.length
; i
++) {
1129 ignoreAttr
[a
.name
] = a
.value
;
1131 attributeArray
.ignoreAttrFilter
= function (a
) {
1132 return (attributeArray
.ignoreAttr
[a
.name
] != a
.value
);
1134 attributeArray
.compliant
= false;
1135 attributeArray
.renames
= {
1136 "class": "className",
1137 "checked": "defaultChecked",
1140 "readonly": "readOnly",
1141 "colspan": "colSpan",
1142 "bgcolor": "bgColor",
1143 "cellspacing": "cellSpacing",
1144 "cellpadding": "cellPadding"
1147 attributeArray
= function (node
) {
1150 Return an array of attributes for a given node,
1151 filtering out attributes that don't belong for
1152 that are inserted by "Certain Browsers".
1155 return node
.attributes
;
1157 attributeArray
.compliant
= true;
1158 attributeArray
.renames
= {};
1160 this.attributeArray
= attributeArray
;
1162 // FIXME: this really belongs in Base, and could probably be cleaner
1163 var _deprecated
= function(fromModule
, arr
) {
1164 var modules
= arr
[1].split('.');
1168 str
+= 'if (!MochiKit.' + modules
[1] + ') { throw new Error("';
1169 str
+= 'This function has been deprecated and depends on MochiKit.';
1170 str
+= modules
[1] + '.");}';
1171 str
+= 'return MochiKit.' + modules
[1] + '.' + arr
[0];
1172 str
+= '.apply(this, arguments);';
1174 obj
[modules
[2]] = new Function(str
);
1175 MochiKit
.Base
.update(MochiKit
[fromModule
], obj
);
1177 for (var i
; i
< MochiKit
.DOM
.DEPRECATED
.length
; i
++) {
1178 _deprecated('DOM', MochiKit
.DOM
.DEPRECATED
[i
]);
1181 // shorthand for createDOM syntax
1182 var createDOMFunc
= this.createDOMFunc
;
1183 /** @id MochiKit.DOM.UL */
1184 this.UL
= createDOMFunc("ul");
1185 /** @id MochiKit.DOM.OL */
1186 this.OL
= createDOMFunc("ol");
1187 /** @id MochiKit.DOM.LI */
1188 this.LI
= createDOMFunc("li");
1189 /** @id MochiKit.DOM.TD */
1190 this.TD
= createDOMFunc("td");
1191 /** @id MochiKit.DOM.TR */
1192 this.TR
= createDOMFunc("tr");
1193 /** @id MochiKit.DOM.TBODY */
1194 this.TBODY
= createDOMFunc("tbody");
1195 /** @id MochiKit.DOM.THEAD */
1196 this.THEAD
= createDOMFunc("thead");
1197 /** @id MochiKit.DOM.TFOOT */
1198 this.TFOOT
= createDOMFunc("tfoot");
1199 /** @id MochiKit.DOM.TABLE */
1200 this.TABLE
= createDOMFunc("table");
1201 /** @id MochiKit.DOM.TH */
1202 this.TH
= createDOMFunc("th");
1203 /** @id MochiKit.DOM.INPUT */
1204 this.INPUT
= createDOMFunc("input");
1205 /** @id MochiKit.DOM.SPAN */
1206 this.SPAN
= createDOMFunc("span");
1207 /** @id MochiKit.DOM.A */
1208 this.A
= createDOMFunc("a");
1209 /** @id MochiKit.DOM.DIV */
1210 this.DIV
= createDOMFunc("div");
1211 /** @id MochiKit.DOM.IMG */
1212 this.IMG
= createDOMFunc("img");
1213 /** @id MochiKit.DOM.BUTTON */
1214 this.BUTTON
= createDOMFunc("button");
1215 /** @id MochiKit.DOM.TT */
1216 this.TT
= createDOMFunc("tt");
1217 /** @id MochiKit.DOM.PRE */
1218 this.PRE
= createDOMFunc("pre");
1219 /** @id MochiKit.DOM.H1 */
1220 this.H1
= createDOMFunc("h1");
1221 /** @id MochiKit.DOM.H2 */
1222 this.H2
= createDOMFunc("h2");
1223 /** @id MochiKit.DOM.H3 */
1224 this.H3
= createDOMFunc("h3");
1225 /** @id MochiKit.DOM.BR */
1226 this.BR
= createDOMFunc("br");
1227 /** @id MochiKit.DOM.HR */
1228 this.HR
= createDOMFunc("hr");
1229 /** @id MochiKit.DOM.LABEL */
1230 this.LABEL
= createDOMFunc("label");
1231 /** @id MochiKit.DOM.TEXTAREA */
1232 this.TEXTAREA
= createDOMFunc("textarea");
1233 /** @id MochiKit.DOM.FORM */
1234 this.FORM
= createDOMFunc("form");
1235 /** @id MochiKit.DOM.P */
1236 this.P
= createDOMFunc("p");
1237 /** @id MochiKit.DOM.SELECT */
1238 this.SELECT
= createDOMFunc("select");
1239 /** @id MochiKit.DOM.OPTION */
1240 this.OPTION
= createDOMFunc("option");
1241 /** @id MochiKit.DOM.OPTGROUP */
1242 this.OPTGROUP
= createDOMFunc("optgroup");
1243 /** @id MochiKit.DOM.LEGEND */
1244 this.LEGEND
= createDOMFunc("legend");
1245 /** @id MochiKit.DOM.FIELDSET */
1246 this.FIELDSET
= createDOMFunc("fieldset");
1247 /** @id MochiKit.DOM.STRONG */
1248 this.STRONG
= createDOMFunc("strong");
1249 /** @id MochiKit.DOM.CANVAS */
1250 this.CANVAS
= createDOMFunc("canvas");
1252 /** @id MochiKit.DOM.$ */
1253 this.$ = this.getElement
;
1255 this.EXPORT_TAGS
= {
1256 ":common": this.EXPORT
,
1257 ":all": m
.concat(this.EXPORT
, this.EXPORT_OK
)
1260 m
.nameFunctions(this);
1266 MochiKit
.DOM
.__new__(((typeof(window
) == "undefined") ? this : window
));
1269 // XXX: Internet Explorer blows
1271 if (MochiKit
.__export__
) {
1272 withWindow
= MochiKit
.DOM
.withWindow
;
1273 withDocument
= MochiKit
.DOM
.withDocument
;
1276 MochiKit
.Base
._exportSymbols(this, MochiKit
.DOM
);