testing/mochitest/tests/MochiKit-1.4.2/MochiKit/DOM.js

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial