testing/mochitest/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
     5 See <http://mochikit.com/> for documentation, downloads, license, etc.
     7 (c) 2005 Bob Ippolito.  All rights Reserved.
     9 ***/
    11 if (typeof(dojo) != 'undefined') {
    12     dojo.provide("MochiKit.DOM");
    13     dojo.require("MochiKit.Base");
    14 }
    15 if (typeof(JSAN) != 'undefined') {
    16     JSAN.use("MochiKit.Base", []);
    17 }
    19 try {
    20     if (typeof(MochiKit.Base) == 'undefined') {
    21         throw "";
    22     }
    23 } catch (e) {
    24     throw "MochiKit.DOM depends on MochiKit.Base!";
    25 }
    27 if (typeof(MochiKit.DOM) == 'undefined') {
    28     MochiKit.DOM = {};
    29 }
    31 MochiKit.DOM.NAME = "MochiKit.DOM";
    32 MochiKit.DOM.VERSION = "1.4";
    33 MochiKit.DOM.__repr__ = function () {
    34     return "[" + this.NAME + " " + this.VERSION + "]";
    35 };
    36 MochiKit.DOM.toString = function () {
    37     return this.__repr__();
    38 };
    40 MochiKit.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     "setNodeAttribute",
    54     "updateNodeAttributes",
    55     "appendChildNodes",
    56     "replaceChildNodes",
    57     "removeElement",
    58     "swapDOM",
    59     "BUTTON",
    60     "TT",
    61     "PRE",
    62     "H1",
    63     "H2",
    64     "H3",
    65     "BR",
    66     "CANVAS",
    67     "HR",
    68     "LABEL",
    69     "TEXTAREA",
    70     "FORM",
    71     "STRONG",
    72     "SELECT",
    73     "OPTION",
    74     "OPTGROUP",
    75     "LEGEND",
    76     "FIELDSET",
    77     "P",
    78     "UL",
    79     "OL",
    80     "LI",
    81     "TD",
    82     "TR",
    83     "THEAD",
    84     "TBODY",
    85     "TFOOT",
    86     "TABLE",
    87     "TH",
    88     "INPUT",
    89     "SPAN",
    90     "A",
    91     "DIV",
    92     "IMG",
    93     "getElement",
    94     "$",
    95     "getElementsByTagAndClassName",
    96     "addToCallStack",
    97     "addLoadEvent",
    98     "focusOnLoad",
    99     "setElementClass",
   100     "toggleElementClass",
   101     "addElementClass",
   102     "removeElementClass",
   103     "swapElementClass",
   104     "hasElementClass",
   105     "escapeHTML",
   106     "toHTML",
   107     "emitHTML",
   108     "scrapeText"
   109 ];
   111 MochiKit.DOM.EXPORT_OK = [
   112     "domConverters"
   113 ];
   115 MochiKit.DOM.DEPRECATED = [
   116     ['computedStyle', 'MochiKit.Style.computedStyle', '1.4'],
   117     /** @id MochiKit.DOM.elementDimensions  */
   118     ['elementDimensions', 'MochiKit.Style.getElementDimensions', '1.4'],
   119     /** @id MochiKit.DOM.elementPosition  */
   120     ['elementPosition', 'MochiKit.Style.getElementPosition', '1.4'],
   121     ['hideElement', 'MochiKit.Style.hideElement', '1.4'],
   122     /** @id MochiKit.DOM.setElementDimensions */
   123     ['setElementDimensions', 'MochiKit.Style.setElementDimensions', '1.4'],
   124     /** @id MochiKit.DOM.setElementPosition */
   125     ['setElementPosition', 'MochiKit.Style.setElementPosition', '1.4'],
   126     ['setDisplayForElement', 'MochiKit.Style.setDisplayForElement', '1.4'],
   127     /** @id MochiKit.DOM.setOpacity */
   128     ['setOpacity', 'MochiKit.Style.setOpacity', '1.4'],
   129     ['showElement', 'MochiKit.Style.showElement', '1.4'],
   130     /** @id MochiKit.DOM.Coordinates */
   131     ['Coordinates', 'MochiKit.Style.Coordinates', '1.4'], // FIXME: broken
   132     /** @id MochiKit.DOM.Dimensions */
   133     ['Dimensions', 'MochiKit.Style.Dimensions', '1.4'] // FIXME: broken
   134 ];
   136 /** @id MochiKit.DOM.getViewportDimensions */
   137 MochiKit.DOM.getViewportDimensions = new Function('' + 
   138     'if (!MochiKit["Style"]) {' + 
   139     '    throw new Error("This function has been deprecated and depends on MochiKit.Style.");' + 
   140     '}' + 
   141     'return MochiKit.Style.getViewportDimensions.apply(this, arguments);');
   143 MochiKit.Base.update(MochiKit.DOM, {
   145     /** @id MochiKit.DOM.currentWindow */
   146     currentWindow: function () {
   147         return MochiKit.DOM._window;
   148     },
   150     /** @id MochiKit.DOM.currentDocument */
   151     currentDocument: function () {
   152         return MochiKit.DOM._document;
   153     },
   155     /** @id MochiKit.DOM.withWindow */
   156     withWindow: function (win, func) {
   157         var self = MochiKit.DOM;
   158         var oldDoc = self._document;
   159         var oldWin = self._win;
   160         var rval;
   161         try {
   162             self._window = win;
   163             self._document = win.document;
   164             rval = func();
   165         } catch (e) {
   166             self._window = oldWin;
   167             self._document = oldDoc;
   168             throw e;
   169         }
   170         self._window = oldWin;
   171         self._document = oldDoc;
   172         return rval;
   173     },
   175     /** @id MochiKit.DOM.formContents  */
   176     formContents: function (elem/* = document */) {
   177         var names = [];
   178         var values = [];
   179         var m = MochiKit.Base;
   180         var self = MochiKit.DOM;
   181         if (typeof(elem) == "undefined" || elem === null) {
   182             elem = self._document;
   183         } else {
   184             elem = self.getElement(elem);
   185         }
   186         m.nodeWalk(elem, function (elem) {
   187             var name = elem.name;
   188             if (m.isNotEmpty(name)) {
   189                 var tagName = elem.tagName.toUpperCase();
   190                 if (tagName === "INPUT"
   191                     && (elem.type == "radio" || elem.type == "checkbox")
   192                     && !elem.checked
   193                 ) {
   194                     return null;
   195                 }
   196                 if (tagName === "SELECT") {
   197                     if (elem.type == "select-one") {
   198                         if (elem.selectedIndex >= 0) {
   199                             var opt = elem.options[elem.selectedIndex];
   200                             names.push(name);
   201                             values.push(opt.value);
   202                             return null;
   203                         }
   204                         // no form elements?
   205                         names.push(name);
   206                         values.push("");
   207                         return null;
   208                     } else {
   209                         var opts = elem.options; 
   210                         if (!opts.length) {
   211                             names.push(name);
   212                             values.push("");
   213                             return null;
   214                         }
   215                         for (var i = 0; i < opts.length; i++) { 
   216                             var opt = opts[i];
   217                             if (!opt.selected) { 
   218                                 continue; 
   219                             } 
   220                             names.push(name); 
   221                             values.push(opt.value); 
   222                         }
   223                         return null;
   224                     }
   225                 }
   226                 if (tagName === "FORM" || tagName === "P" || tagName === "SPAN"
   227                     || tagName === "DIV"
   228                 ) {
   229                     return elem.childNodes;
   230                 }
   231                 names.push(name);
   232                 values.push(elem.value || '');
   233                 return null;
   234             }
   235             return elem.childNodes;
   236         });
   237         return [names, values];
   238     },
   240     /** @id MochiKit.DOM.withDocument */
   241     withDocument: function (doc, func) {
   242         var self = MochiKit.DOM;
   243         var oldDoc = self._document;
   244         var rval;
   245         try {
   246             self._document = doc;
   247             rval = func();
   248         } catch (e) {
   249             self._document = oldDoc;
   250             throw e;
   251         }
   252         self._document = oldDoc;
   253         return rval;
   254     },
   256     /** @id MochiKit.DOM.registerDOMConverter */
   257     registerDOMConverter: function (name, check, wrap, /* optional */override) {
   258         MochiKit.DOM.domConverters.register(name, check, wrap, override);
   259     },
   261     /** @id MochiKit.DOM.coerceToDOM */
   262     coerceToDOM: function (node, ctx) {
   263         var m = MochiKit.Base;
   264         var im = MochiKit.Iter;
   265         var self = MochiKit.DOM;
   266         if (im) {
   267             var iter = im.iter;
   268             var repeat = im.repeat;
   269             var map = m.map;
   270         }
   271         var domConverters = self.domConverters;
   272         var coerceToDOM = arguments.callee;
   273         var NotFound = m.NotFound;
   274         while (true) {
   275             if (typeof(node) == 'undefined' || node === null) {
   276                 return null;
   277             }
   278             if (typeof(node.nodeType) != 'undefined' && node.nodeType > 0) {
   279                 return node;
   280             }
   281             if (typeof(node) == 'number' || typeof(node) == 'boolean') {
   282                 node = node.toString();
   283                 // FALL THROUGH
   284             }
   285             if (typeof(node) == 'string') {
   286                 return self._document.createTextNode(node);
   287             }
   288             if (typeof(node.__dom__) == 'function') {
   289                 node = node.__dom__(ctx);
   290                 continue;
   291             }
   292             if (typeof(node.dom) == 'function') {
   293                 node = node.dom(ctx);
   294                 continue;
   295             }
   296             if (typeof(node) == 'function') {
   297                 node = node.apply(ctx, [ctx]);
   298                 continue;
   299             }
   301             if (im) {
   302                 // iterable
   303                 var iterNodes = null;
   304                 try {
   305                     iterNodes = iter(node);
   306                 } catch (e) {
   307                     // pass
   308                 }
   309                 if (iterNodes) {
   310                     return map(coerceToDOM, iterNodes, repeat(ctx));
   311                 }
   312             }
   314             // adapter
   315             try {
   316                 node = domConverters.match(node, ctx);
   317                 continue;
   318             } catch (e) {
   319                 if (e != NotFound) {
   320                     throw e;
   321                 }
   322             }
   324             // fallback
   325             return self._document.createTextNode(node.toString());
   326         }
   327         // mozilla warnings aren't too bright
   328         return undefined;
   329     },
   331     /** @id MochiKit.DOM.isChildNode */
   332     isChildNode: function (node, maybeparent) {
   333         var self = MochiKit.DOM;
   334         if (typeof(node) == "string") {
   335             node = self.getElement(node);
   336         }
   337         if (typeof(maybeparent) == "string") {
   338             maybeparent = self.getElement(maybeparent);
   339         }
   340         if (node === maybeparent) {
   341             return true;
   342         }
   343         while (node && node.tagName.toUpperCase() != "BODY") {
   344             node = node.parentNode;
   345             if (node === maybeparent) {
   346                 return true;
   347             }
   348         }
   349         return false;
   350     },
   352     /** @id MochiKit.DOM.setNodeAttribute */
   353     setNodeAttribute: function (node, attr, value) {
   354         var o = {};
   355         o[attr] = value;
   356         try {
   357             return MochiKit.DOM.updateNodeAttributes(node, o);
   358         } catch (e) {
   359             // pass
   360         }
   361         return null;
   362     },
   364     /** @id MochiKit.DOM.getNodeAttribute */
   365     getNodeAttribute: function (node, attr) {
   366         var self = MochiKit.DOM;
   367         var rename = self.attributeArray.renames[attr];
   368         node = self.getElement(node);
   369         try {
   370             if (rename) {
   371                 return node[rename];
   372             }
   373             return node.getAttribute(attr);
   374         } catch (e) {
   375             // pass
   376         }
   377         return null;
   378     },
   380     /** @id MochiKit.DOM.updateNodeAttributes */
   381     updateNodeAttributes: function (node, attrs) {
   382         var elem = node;
   383         var self = MochiKit.DOM;
   384         if (typeof(node) == 'string') {
   385             elem = self.getElement(node);
   386         }
   387         if (attrs) {
   388             var updatetree = MochiKit.Base.updatetree;
   389             if (self.attributeArray.compliant) {
   390                 // not IE, good.
   391                 for (var k in attrs) {
   392                     var v = attrs[k];
   393                     if (typeof(v) == 'object' && typeof(elem[k]) == 'object') {
   394                         updatetree(elem[k], v);
   395                     } else if (k.substring(0, 2) == "on") {
   396                         if (typeof(v) == "string") {
   397                             v = new Function(v);
   398                         }
   399                         elem[k] = v;
   400                     } else {
   401                         elem.setAttribute(k, v);
   402                     }
   403                 }
   404             } else {
   405                 // IE is insane in the membrane
   406                 var renames = self.attributeArray.renames;
   407                 for (k in attrs) {
   408                     v = attrs[k];
   409                     var renamed = renames[k];
   410                     if (k == "style" && typeof(v) == "string") {
   411                         elem.style.cssText = v;
   412                     } else if (typeof(renamed) == "string") {
   413                         elem[renamed] = v;
   414                     } else if (typeof(elem[k]) == 'object'
   415                             && typeof(v) == 'object') {
   416                         updatetree(elem[k], v);
   417                     } else if (k.substring(0, 2) == "on") {
   418                         if (typeof(v) == "string") {
   419                             v = new Function(v);
   420                         }
   421                         elem[k] = v;
   422                     } else {
   423                         elem.setAttribute(k, v);
   424                     }
   425                 }
   426             }
   427         }
   428         return elem;
   429     },
   431     /** @id MochiKit.DOM.appendChildNodes */
   432     appendChildNodes: function (node/*, nodes...*/) {
   433         var elem = node;
   434         var self = MochiKit.DOM;
   435         if (typeof(node) == 'string') {
   436             elem = self.getElement(node);
   437         }
   438         var nodeStack = [
   439             self.coerceToDOM(
   440                 MochiKit.Base.extend(null, arguments, 1),
   441                 elem
   442             )
   443         ];
   444         var concat = MochiKit.Base.concat;
   445         while (nodeStack.length) {
   446             var n = nodeStack.shift();
   447             if (typeof(n) == 'undefined' || n === null) {
   448                 // pass
   449             } else if (typeof(n.nodeType) == 'number') {
   450                 elem.appendChild(n);
   451             } else {
   452                 nodeStack = concat(n, nodeStack);
   453             }
   454         }
   455         return elem;
   456     },
   458     /** @id MochiKit.DOM.replaceChildNodes */
   459     replaceChildNodes: function (node/*, nodes...*/) {
   460         var elem = node;
   461         var self = MochiKit.DOM;
   462         if (typeof(node) == 'string') {
   463             elem = self.getElement(node);
   464             arguments[0] = elem;
   465         }
   466         var child;
   467         while ((child = elem.firstChild)) {
   468             elem.removeChild(child);
   469         }
   470         if (arguments.length < 2) {
   471             return elem;
   472         } else {
   473             return self.appendChildNodes.apply(this, arguments);
   474         }
   475     },
   477     /** @id MochiKit.DOM.createDOM */
   478     createDOM: function (name, attrs/*, nodes... */) {
   479         var elem;
   480         var self = MochiKit.DOM;
   481         var m = MochiKit.Base;
   482         if (typeof(attrs) == "string" || typeof(attrs) == "number") {
   483             var args = m.extend([name, null], arguments, 1);
   484             return arguments.callee.apply(this, args);
   485         }
   486         if (typeof(name) == 'string') {
   487             // Internet Explorer is dumb
   488             var xhtml = self._xhtml;
   489             if (attrs && !self.attributeArray.compliant) {
   490                 // http://msdn.microsoft.com/workshop/author/dhtml/reference/properties/name_2.asp
   491                 var contents = "";
   492                 if ('name' in attrs) {
   493                     contents += ' name="' + self.escapeHTML(attrs.name) + '"';
   494                 }
   495                 if (name == 'input' && 'type' in attrs) {
   496                     contents += ' type="' + self.escapeHTML(attrs.type) + '"';
   497                 }
   498                 if (contents) {
   499                     name = "<" + name + contents + ">";
   500                     xhtml = false;
   501                 }
   502             }
   503             var d = self._document;
   504             if (xhtml && d === document) {
   505                 elem = d.createElementNS("http://www.w3.org/1999/xhtml", name);
   506             } else {
   507                 elem = d.createElement(name);
   508             }
   509         } else {
   510             elem = name;
   511         }
   512         if (attrs) {
   513             self.updateNodeAttributes(elem, attrs);
   514         }
   515         if (arguments.length <= 2) {
   516             return elem;
   517         } else {
   518             var args = m.extend([elem], arguments, 2);
   519             return self.appendChildNodes.apply(this, args);
   520         }
   521     },
   523     /** @id MochiKit.DOM.createDOMFunc */
   524     createDOMFunc: function (/* tag, attrs, *nodes */) {
   525         var m = MochiKit.Base;
   526         return m.partial.apply(
   527             this,
   528             m.extend([MochiKit.DOM.createDOM], arguments)
   529         );
   530     },
   532     /** @id MochiKit.DOM.removeElement */
   533     removeElement: function (elem) {
   534         var e = MochiKit.DOM.getElement(elem);
   535         e.parentNode.removeChild(e);
   536         return e;
   537     },
   539     /** @id MochiKit.DOM.swapDOM */
   540     swapDOM: function (dest, src) {
   541         var self = MochiKit.DOM;
   542         dest = self.getElement(dest);
   543         var parent = dest.parentNode;
   544         if (src) {
   545             src = self.getElement(src);
   546             parent.replaceChild(src, dest);
   547         } else {
   548             parent.removeChild(dest);
   549         }
   550         return src;
   551     },
   553     /** @id MochiKit.DOM.getElement */
   554     getElement: function (id) {
   555         var self = MochiKit.DOM;
   556         if (arguments.length == 1) {
   557             return ((typeof(id) == "string") ?
   558                 self._document.getElementById(id) : id);
   559         } else {
   560             return MochiKit.Base.map(self.getElement, arguments);
   561         }
   562     },
   564     /** @id MochiKit.DOM.getElementsByTagAndClassName */
   565     getElementsByTagAndClassName: function (tagName, className,
   566             /* optional */parent) {
   567         var self = MochiKit.DOM;
   568         if (typeof(tagName) == 'undefined' || tagName === null) {
   569             tagName = '*';
   570         }
   571         if (typeof(parent) == 'undefined' || parent === null) {
   572             parent = self._document;
   573         }
   574         parent = self.getElement(parent);
   575         var children = (parent.getElementsByTagName(tagName)
   576             || self._document.all);
   577         if (typeof(className) == 'undefined' || className === null) {
   578             return MochiKit.Base.extend(null, children);
   579         }
   581         var elements = [];
   582         for (var i = 0; i < children.length; i++) {
   583             var child = children[i];
   584             var cls = child.className;
   585             if (!cls) {
   586                 continue;
   587             }
   588             var classNames = cls.split(' ');
   589             for (var j = 0; j < classNames.length; j++) {
   590                 if (classNames[j] == className) {
   591                     elements.push(child);
   592                     break;
   593                 }
   594             }
   595         }
   597         return elements;
   598     },
   600     _newCallStack: function (path, once) {
   601         var rval = function () {
   602             var callStack = arguments.callee.callStack;
   603             for (var i = 0; i < callStack.length; i++) {
   604                 if (callStack[i].apply(this, arguments) === false) {
   605                     break;
   606                 }
   607             }
   608             if (once) {
   609                 try {
   610                     this[path] = null;
   611                 } catch (e) {
   612                     // pass
   613                 }
   614             }
   615         };
   616         rval.callStack = [];
   617         return rval;
   618     },
   620     /** @id MochiKit.DOM.addToCallStack */
   621     addToCallStack: function (target, path, func, once) {
   622         var self = MochiKit.DOM;
   623         var existing = target[path];
   624         var regfunc = existing;
   625         if (!(typeof(existing) == 'function'
   626                 && typeof(existing.callStack) == "object"
   627                 && existing.callStack !== null)) {
   628             regfunc = self._newCallStack(path, once);
   629             if (typeof(existing) == 'function') {
   630                 regfunc.callStack.push(existing);
   631             }
   632             target[path] = regfunc;
   633         }
   634         regfunc.callStack.push(func);
   635     },
   637     /** @id MochiKit.DOM.addLoadEvent */
   638     addLoadEvent: function (func) {
   639         var self = MochiKit.DOM;
   640         self.addToCallStack(self._window, "onload", func, true);
   642     },
   644     /** @id MochiKit.DOM.focusOnLoad */
   645     focusOnLoad: function (element) {
   646         var self = MochiKit.DOM;
   647         self.addLoadEvent(function () {
   648             element = self.getElement(element);
   649             if (element) {
   650                 element.focus();
   651             }
   652         });
   653     },
   655     /** @id MochiKit.DOM.setElementClass */
   656     setElementClass: function (element, className) {
   657         var self = MochiKit.DOM;
   658         var obj = self.getElement(element);
   659         if (self.attributeArray.compliant) {
   660             obj.setAttribute("class", className);
   661         } else {
   662             obj.setAttribute("className", className);
   663         }
   664     },
   666     /** @id MochiKit.DOM.toggleElementClass */
   667     toggleElementClass: function (className/*, element... */) {
   668         var self = MochiKit.DOM;
   669         for (var i = 1; i < arguments.length; i++) {
   670             var obj = self.getElement(arguments[i]);
   671             if (!self.addElementClass(obj, className)) {
   672                 self.removeElementClass(obj, className);
   673             }
   674         }
   675     },
   677     /** @id MochiKit.DOM.addElementClass */
   678     addElementClass: function (element, className) {
   679         var self = MochiKit.DOM;
   680         var obj = self.getElement(element);
   681         var cls = obj.className;
   682         // trivial case, no className yet
   683         if (cls == undefined || cls.length === 0) {
   684             self.setElementClass(obj, className);
   685             return true;
   686         }
   687         // the other trivial case, already set as the only class
   688         if (cls == className) {
   689             return false;
   690         }
   691         var classes = cls.split(" ");
   692         for (var i = 0; i < classes.length; i++) {
   693             // already present
   694             if (classes[i] == className) {
   695                 return false;
   696             }
   697         }
   698         // append class
   699         self.setElementClass(obj, cls + " " + className);
   700         return true;
   701     },
   703     /** @id MochiKit.DOM.removeElementClass */
   704     removeElementClass: function (element, className) {
   705         var self = MochiKit.DOM;
   706         var obj = self.getElement(element);
   707         var cls = obj.className;
   708         // trivial case, no className yet
   709         if (cls == undefined || cls.length === 0) {
   710             return false;
   711         }
   712         // other trivial case, set only to className
   713         if (cls == className) {
   714             self.setElementClass(obj, "");
   715             return true;
   716         }
   717         var classes = cls.split(" ");
   718         for (var i = 0; i < classes.length; i++) {
   719             // already present
   720             if (classes[i] == className) {
   721                 // only check sane case where the class is used once
   722                 classes.splice(i, 1);
   723                 self.setElementClass(obj, classes.join(" "));
   724                 return true;
   725             }
   726         }
   727         // not found
   728         return false;
   729     },
   731     /** @id MochiKit.DOM.swapElementClass */
   732     swapElementClass: function (element, fromClass, toClass) {
   733         var obj = MochiKit.DOM.getElement(element);
   734         var res = MochiKit.DOM.removeElementClass(obj, fromClass);
   735         if (res) {
   736             MochiKit.DOM.addElementClass(obj, toClass);
   737         }
   738         return res;
   739     },
   741     /** @id MochiKit.DOM.hasElementClass */
   742     hasElementClass: function (element, className/*...*/) {
   743         var obj = MochiKit.DOM.getElement(element);
   744         var cls = obj.className;
   745         if (!cls) {
   746             return false;
   747         }
   748         var classes = cls.split(" ");
   749         for (var i = 1; i < arguments.length; i++) {
   750             var good = false;
   751             for (var j = 0; j < classes.length; j++) {
   752                 if (classes[j] == arguments[i]) {
   753                     good = true;
   754                     break;
   755                 }
   756             }
   757             if (!good) {
   758                 return false;
   759             }
   760         }
   761         return true;
   762     },
   764     /** @id MochiKit.DOM.escapeHTML */
   765     escapeHTML: function (s) {
   766         return s.replace(/&/g, "&amp;"
   767             ).replace(/"/g, "&quot;"
   768             ).replace(/</g, "&lt;"
   769             ).replace(/>/g, "&gt;");
   770     },
   772     /** @id MochiKit.DOM.toHTML */
   773     toHTML: function (dom) {
   774         return MochiKit.DOM.emitHTML(dom).join("");
   775     },
   777     /** @id MochiKit.DOM.emitHTML */
   778     emitHTML: function (dom, /* optional */lst) {
   779         if (typeof(lst) == 'undefined' || lst === null) {
   780             lst = [];
   781         }
   782         // queue is the call stack, we're doing this non-recursively
   783         var queue = [dom];
   784         var self = MochiKit.DOM;
   785         var escapeHTML = self.escapeHTML;
   786         var attributeArray = self.attributeArray;
   787         while (queue.length) {
   788             dom = queue.pop();
   789             if (typeof(dom) == 'string') {
   790                 lst.push(dom);
   791             } else if (dom.nodeType == 1) {
   792                 // we're not using higher order stuff here
   793                 // because safari has heisenbugs.. argh.
   794                 //
   795                 // I think it might have something to do with
   796                 // garbage collection and function calls.
   797                 lst.push('<' + dom.tagName.toLowerCase());
   798                 var attributes = [];
   799                 var domAttr = attributeArray(dom);
   800                 for (var i = 0; i < domAttr.length; i++) {
   801                     var a = domAttr[i];
   802                     attributes.push([
   803                         " ",
   804                         a.name,
   805                         '="',
   806                         escapeHTML(a.value),
   807                         '"'
   808                     ]);
   809                 }
   810                 attributes.sort();
   811                 for (i = 0; i < attributes.length; i++) {
   812                     var attrs = attributes[i];
   813                     for (var j = 0; j < attrs.length; j++) {
   814                         lst.push(attrs[j]);
   815                     }
   816                 }
   817                 if (dom.hasChildNodes()) {
   818                     lst.push(">");
   819                     // queue is the FILO call stack, so we put the close tag
   820                     // on first
   821                     queue.push("</" + dom.tagName.toLowerCase() + ">");
   822                     var cnodes = dom.childNodes;
   823                     for (i = cnodes.length - 1; i >= 0; i--) {
   824                         queue.push(cnodes[i]);
   825                     }
   826                 } else {
   827                     lst.push('/>');
   828                 }
   829             } else if (dom.nodeType == 3) {
   830                 lst.push(escapeHTML(dom.nodeValue));
   831             }
   832         }
   833         return lst;
   834     },
   836     /** @id MochiKit.DOM.scrapeText */
   837     scrapeText: function (node, /* optional */asArray) {
   838         var rval = [];
   839         (function (node) {
   840             var cn = node.childNodes;
   841             if (cn) {
   842                 for (var i = 0; i < cn.length; i++) {
   843                     arguments.callee.call(this, cn[i]);
   844                 }
   845             }
   846             var nodeValue = node.nodeValue;
   847             if (typeof(nodeValue) == 'string') {
   848                 rval.push(nodeValue);
   849             }
   850         })(MochiKit.DOM.getElement(node));
   851         if (asArray) {
   852             return rval;
   853         } else {
   854             return rval.join("");
   855         }
   856     },    
   858     /** @id MochiKit.DOM.removeEmptyTextNodes */
   859     removeEmptyTextNodes: function (element) {
   860         element = MochiKit.DOM.getElement(element);
   861         for (var i = 0; i < element.childNodes.length; i++) {
   862             var node = element.childNodes[i];
   863             if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) {
   864                 node.parentNode.removeChild(node);
   865             }
   866         }
   867     },
   869     __new__: function (win) {
   871         var m = MochiKit.Base;
   872         if (typeof(document) != "undefined") {
   873             this._document = document;
   874             this._xhtml =
   875 	        document.createElementNS &&
   876 		document.createElement("testname").localName == "testname";
   877         } else if (MochiKit.MockDOM) {
   878             this._document = MochiKit.MockDOM.document;
   879         }
   880         this._window = win;
   882         this.domConverters = new m.AdapterRegistry(); 
   884         var __tmpElement = this._document.createElement("span");
   885         var attributeArray;
   886         if (__tmpElement && __tmpElement.attributes &&
   887                 __tmpElement.attributes.length > 0) {
   888             // for braindead browsers (IE) that insert extra junk
   889             var filter = m.filter;
   890             attributeArray = function (node) {
   891                 return filter(attributeArray.ignoreAttrFilter, node.attributes);
   892             };
   893             attributeArray.ignoreAttr = {};
   894             var attrs = __tmpElement.attributes;
   895             var ignoreAttr = attributeArray.ignoreAttr;
   896             for (var i = 0; i < attrs.length; i++) {
   897                 var a = attrs[i];
   898                 ignoreAttr[a.name] = a.value;
   899             }
   900             attributeArray.ignoreAttrFilter = function (a) {
   901                 return (attributeArray.ignoreAttr[a.name] != a.value);
   902             };
   903             attributeArray.compliant = false;
   904             attributeArray.renames = {
   905                 "class": "className",
   906                 "checked": "defaultChecked",
   907                 "usemap": "useMap",
   908                 "for": "htmlFor",
   909                 "readonly": "readOnly",
   910                 "colspan": "colSpan",
   911                 "bgcolor": "bgColor"
   912             };
   913         } else {
   914             attributeArray = function (node) {
   915                 /***
   917                     Return an array of attributes for a given node,
   918                     filtering out attributes that don't belong for
   919                     that are inserted by "Certain Browsers".
   921                 ***/
   922                 return node.attributes;
   923             };
   924             attributeArray.compliant = true;
   925             attributeArray.renames = {};
   926         }
   927         this.attributeArray = attributeArray;
   929         // FIXME: this really belongs in Base, and could probably be cleaner
   930         var _deprecated = function(fromModule, arr) {
   931             var modules = arr[1].split('.');
   932             var str = '';
   933             var obj = {};
   935             str += 'if (!MochiKit.' + modules[1] + ') { throw new Error("';
   936             str += 'This function has been deprecated and depends on MochiKit.';
   937             str += modules[1] + '.");}';
   938             str += 'return MochiKit.' + modules[1] + '.' + arr[0];
   939             str += '.apply(this, arguments);';
   941             obj[modules[2]] = new Function(str);
   942             MochiKit.Base.update(MochiKit[fromModule], obj);
   943         }
   944         for (var i; i < MochiKit.DOM.DEPRECATED.length; i++) {
   945             _deprecated('DOM', MochiKit.DOM.DEPRECATED[i]);
   946         }
   948         // shorthand for createDOM syntax
   949         var createDOMFunc = this.createDOMFunc;
   950         /** @id MochiKit.DOM.UL */
   951         this.UL = createDOMFunc("ul");
   952         /** @id MochiKit.DOM.OL */
   953         this.OL = createDOMFunc("ol");
   954         /** @id MochiKit.DOM.LI */
   955         this.LI = createDOMFunc("li");
   956         /** @id MochiKit.DOM.TD */
   957         this.TD = createDOMFunc("td");
   958         /** @id MochiKit.DOM.TR */
   959         this.TR = createDOMFunc("tr");
   960         /** @id MochiKit.DOM.TBODY */
   961         this.TBODY = createDOMFunc("tbody");
   962         /** @id MochiKit.DOM.THEAD */
   963         this.THEAD = createDOMFunc("thead");
   964         /** @id MochiKit.DOM.TFOOT */
   965         this.TFOOT = createDOMFunc("tfoot");
   966         /** @id MochiKit.DOM.TABLE */
   967         this.TABLE = createDOMFunc("table");
   968         /** @id MochiKit.DOM.TH */
   969         this.TH = createDOMFunc("th");
   970         /** @id MochiKit.DOM.INPUT */
   971         this.INPUT = createDOMFunc("input");
   972         /** @id MochiKit.DOM.SPAN */
   973         this.SPAN = createDOMFunc("span");
   974         /** @id MochiKit.DOM.A */
   975         this.A = createDOMFunc("a");
   976         /** @id MochiKit.DOM.DIV */
   977         this.DIV = createDOMFunc("div");
   978         /** @id MochiKit.DOM.IMG */
   979         this.IMG = createDOMFunc("img");
   980         /** @id MochiKit.DOM.BUTTON */
   981         this.BUTTON = createDOMFunc("button");
   982         /** @id MochiKit.DOM.TT */
   983         this.TT = createDOMFunc("tt");
   984         /** @id MochiKit.DOM.PRE */
   985         this.PRE = createDOMFunc("pre");
   986         /** @id MochiKit.DOM.H1 */
   987         this.H1 = createDOMFunc("h1");
   988         /** @id MochiKit.DOM.H2 */
   989         this.H2 = createDOMFunc("h2");
   990         /** @id MochiKit.DOM.H3 */
   991         this.H3 = createDOMFunc("h3");
   992         /** @id MochiKit.DOM.BR */
   993         this.BR = createDOMFunc("br");
   994         /** @id MochiKit.DOM.HR */
   995         this.HR = createDOMFunc("hr");
   996         /** @id MochiKit.DOM.LABEL */
   997         this.LABEL = createDOMFunc("label");
   998         /** @id MochiKit.DOM.TEXTAREA */
   999         this.TEXTAREA = createDOMFunc("textarea");
  1000         /** @id MochiKit.DOM.FORM */
  1001         this.FORM = createDOMFunc("form");
  1002         /** @id MochiKit.DOM.P */
  1003         this.P = createDOMFunc("p");
  1004         /** @id MochiKit.DOM.SELECT */
  1005         this.SELECT = createDOMFunc("select");
  1006         /** @id MochiKit.DOM.OPTION */
  1007         this.OPTION = createDOMFunc("option");
  1008         /** @id MochiKit.DOM.OPTGROUP */
  1009         this.OPTGROUP = createDOMFunc("optgroup");
  1010         /** @id MochiKit.DOM.LEGEND */
  1011         this.LEGEND = createDOMFunc("legend");
  1012         /** @id MochiKit.DOM.FIELDSET */
  1013         this.FIELDSET = createDOMFunc("fieldset");
  1014         /** @id MochiKit.DOM.STRONG */
  1015         this.STRONG = createDOMFunc("strong");
  1016         /** @id MochiKit.DOM.CANVAS */
  1017         this.CANVAS = createDOMFunc("canvas");
  1019         /** @id MochiKit.DOM.$ */
  1020         this.$ = this.getElement;
  1022         this.EXPORT_TAGS = {
  1023             ":common": this.EXPORT,
  1024             ":all": m.concat(this.EXPORT, this.EXPORT_OK)
  1025         };
  1027         m.nameFunctions(this);
  1030 });
  1033 MochiKit.DOM.__new__(((typeof(window) == "undefined") ? this : window));
  1035 //
  1036 // XXX: Internet Explorer blows
  1037 //
  1038 if (MochiKit.__export__) {
  1039     withWindow = MochiKit.DOM.withWindow;
  1040     withDocument = MochiKit.DOM.withDocument;
  1043 MochiKit.Base._exportSymbols(this, MochiKit.DOM);

mercurial