ext-foundation-debug.js
上传用户:dawnssy
上传日期:2022-08-06
资源大小:9345k
文件大小:532k
源码类别:

JavaScript

开发平台:

JavaScript

  1. /*!  * Ext JS Library 3.1.0  * Copyright(c) 2006-2009 Ext JS, LLC  * licensing@extjs.com  * http://www.extjs.com/license  */ /**
  2.  * @class Ext.DomHelper
  3.  * <p>The DomHelper class provides a layer of abstraction from DOM and transparently supports creating
  4.  * elements via DOM or using HTML fragments. It also has the ability to create HTML fragment templates
  5.  * from your DOM building code.</p>
  6.  *
  7.  * <p><b><u>DomHelper element specification object</u></b></p>
  8.  * <p>A specification object is used when creating elements. Attributes of this object
  9.  * are assumed to be element attributes, except for 4 special attributes:
  10.  * <div class="mdetail-params"><ul>
  11.  * <li><b><tt>tag</tt></b> : <div class="sub-desc">The tag name of the element</div></li>
  12.  * <li><b><tt>children</tt></b> : or <tt>cn</tt><div class="sub-desc">An array of the
  13.  * same kind of element definition objects to be created and appended. These can be nested
  14.  * as deep as you want.</div></li>
  15.  * <li><b><tt>cls</tt></b> : <div class="sub-desc">The class attribute of the element.
  16.  * This will end up being either the "class" attribute on a HTML fragment or className
  17.  * for a DOM node, depending on whether DomHelper is using fragments or DOM.</div></li>
  18.  * <li><b><tt>html</tt></b> : <div class="sub-desc">The innerHTML for the element</div></li>
  19.  * </ul></div></p>
  20.  *
  21.  * <p><b><u>Insertion methods</u></b></p>
  22.  * <p>Commonly used insertion methods:
  23.  * <div class="mdetail-params"><ul>
  24.  * <li><b><tt>{@link #append}</tt></b> : <div class="sub-desc"></div></li>
  25.  * <li><b><tt>{@link #insertBefore}</tt></b> : <div class="sub-desc"></div></li>
  26.  * <li><b><tt>{@link #insertAfter}</tt></b> : <div class="sub-desc"></div></li>
  27.  * <li><b><tt>{@link #overwrite}</tt></b> : <div class="sub-desc"></div></li>
  28.  * <li><b><tt>{@link #createTemplate}</tt></b> : <div class="sub-desc"></div></li>
  29.  * <li><b><tt>{@link #insertHtml}</tt></b> : <div class="sub-desc"></div></li>
  30.  * </ul></div></p>
  31.  *
  32.  * <p><b><u>Example</u></b></p>
  33.  * <p>This is an example, where an unordered list with 3 children items is appended to an existing
  34.  * element with id <tt>'my-div'</tt>:<br>
  35.  <pre><code>
  36. var dh = Ext.DomHelper; // create shorthand alias
  37. // specification object
  38. var spec = {
  39.     id: 'my-ul',
  40.     tag: 'ul',
  41.     cls: 'my-list',
  42.     // append children after creating
  43.     children: [     // may also specify 'cn' instead of 'children'
  44.         {tag: 'li', id: 'item0', html: 'List Item 0'},
  45.         {tag: 'li', id: 'item1', html: 'List Item 1'},
  46.         {tag: 'li', id: 'item2', html: 'List Item 2'}
  47.     ]
  48. };
  49. var list = dh.append(
  50.     'my-div', // the context element 'my-div' can either be the id or the actual node
  51.     spec      // the specification object
  52. );
  53.  </code></pre></p>
  54.  * <p>Element creation specification parameters in this class may also be passed as an Array of
  55.  * specification objects. This can be used to insert multiple sibling nodes into an existing
  56.  * container very efficiently. For example, to add more list items to the example above:<pre><code>
  57. dh.append('my-ul', [
  58.     {tag: 'li', id: 'item3', html: 'List Item 3'},
  59.     {tag: 'li', id: 'item4', html: 'List Item 4'}
  60. ]);
  61.  * </code></pre></p>
  62.  *
  63.  * <p><b><u>Templating</u></b></p>
  64.  * <p>The real power is in the built-in templating. Instead of creating or appending any elements,
  65.  * <tt>{@link #createTemplate}</tt> returns a Template object which can be used over and over to
  66.  * insert new elements. Revisiting the example above, we could utilize templating this time:
  67.  * <pre><code>
  68. // create the node
  69. var list = dh.append('my-div', {tag: 'ul', cls: 'my-list'});
  70. // get template
  71. var tpl = dh.createTemplate({tag: 'li', id: 'item{0}', html: 'List Item {0}'});
  72. for(var i = 0; i < 5, i++){
  73.     tpl.append(list, [i]); // use template to append to the actual node
  74. }
  75.  * </code></pre></p>
  76.  * <p>An example using a template:<pre><code>
  77. var html = '<a id="{0}" href="{1}" class="nav">{2}</a>';
  78. var tpl = new Ext.DomHelper.createTemplate(html);
  79. tpl.append('blog-roll', ['link1', 'http://www.jackslocum.com/', "Jack&#39;s Site"]);
  80. tpl.append('blog-roll', ['link2', 'http://www.dustindiaz.com/', "Dustin&#39;s Site"]);
  81.  * </code></pre></p>
  82.  *
  83.  * <p>The same example using named parameters:<pre><code>
  84. var html = '<a id="{id}" href="{url}" class="nav">{text}</a>';
  85. var tpl = new Ext.DomHelper.createTemplate(html);
  86. tpl.append('blog-roll', {
  87.     id: 'link1',
  88.     url: 'http://www.jackslocum.com/',
  89.     text: "Jack&#39;s Site"
  90. });
  91. tpl.append('blog-roll', {
  92.     id: 'link2',
  93.     url: 'http://www.dustindiaz.com/',
  94.     text: "Dustin&#39;s Site"
  95. });
  96.  * </code></pre></p>
  97.  *
  98.  * <p><b><u>Compiling Templates</u></b></p>
  99.  * <p>Templates are applied using regular expressions. The performance is great, but if
  100.  * you are adding a bunch of DOM elements using the same template, you can increase
  101.  * performance even further by {@link Ext.Template#compile "compiling"} the template.
  102.  * The way "{@link Ext.Template#compile compile()}" works is the template is parsed and
  103.  * broken up at the different variable points and a dynamic function is created and eval'ed.
  104.  * The generated function performs string concatenation of these parts and the passed
  105.  * variables instead of using regular expressions.
  106.  * <pre><code>
  107. var html = '<a id="{id}" href="{url}" class="nav">{text}</a>';
  108. var tpl = new Ext.DomHelper.createTemplate(html);
  109. tpl.compile();
  110. //... use template like normal
  111.  * </code></pre></p>
  112.  *
  113.  * <p><b><u>Performance Boost</u></b></p>
  114.  * <p>DomHelper will transparently create HTML fragments when it can. Using HTML fragments instead
  115.  * of DOM can significantly boost performance.</p>
  116.  * <p>Element creation specification parameters may also be strings. If {@link #useDom} is <tt>false</tt>,
  117.  * then the string is used as innerHTML. If {@link #useDom} is <tt>true</tt>, a string specification
  118.  * results in the creation of a text node. Usage:</p>
  119.  * <pre><code>
  120. Ext.DomHelper.useDom = true; // force it to use DOM; reduces performance
  121.  * </code></pre>
  122.  * @singleton
  123.  */
  124. Ext.DomHelper = function(){
  125.     var tempTableEl = null,
  126.         emptyTags = /^(?:br|frame|hr|img|input|link|meta|range|spacer|wbr|area|param|col)$/i,
  127.         tableRe = /^table|tbody|tr|td$/i,
  128.         pub,
  129.         // kill repeat to save bytes
  130.         afterbegin = 'afterbegin',
  131.         afterend = 'afterend',
  132.         beforebegin = 'beforebegin',
  133.         beforeend = 'beforeend',
  134.         ts = '<table>',
  135.         te = '</table>',
  136.         tbs = ts+'<tbody>',
  137.         tbe = '</tbody>'+te,
  138.         trs = tbs + '<tr>',
  139.         tre = '</tr>'+tbe;
  140.     // private
  141.     function doInsert(el, o, returnElement, pos, sibling, append){
  142.         var newNode = pub.insertHtml(pos, Ext.getDom(el), createHtml(o));
  143.         return returnElement ? Ext.get(newNode, true) : newNode;
  144.     }
  145.     // build as innerHTML where available
  146.     function createHtml(o){
  147.         var b = '',
  148.             attr,
  149.             val,
  150.             key,
  151.             keyVal,
  152.             cn;
  153.         if(Ext.isString(o)){
  154.             b = o;
  155.         } else if (Ext.isArray(o)) {
  156.             for (var i=0; i < o.length; i++) {
  157.                 if(o[i]) {
  158.                     b += createHtml(o[i]);
  159.                 }
  160.             };
  161.         } else {
  162.             b += '<' + (o.tag = o.tag || 'div');
  163.             Ext.iterate(o, function(attr, val){
  164.                 if(!/tag|children|cn|html$/i.test(attr)){
  165.                     if (Ext.isObject(val)) {
  166.                         b += ' ' + attr + '="';
  167.                         Ext.iterate(val, function(key, keyVal){
  168.                             b += key + ':' + keyVal + ';';
  169.                         });
  170.                         b += '"';
  171.                     }else{
  172.                         b += ' ' + ({cls : 'class', htmlFor : 'for'}[attr] || attr) + '="' + val + '"';
  173.                     }
  174.                 }
  175.             });
  176.             // Now either just close the tag or try to add children and close the tag.
  177.             if (emptyTags.test(o.tag)) {
  178.                 b += '/>';
  179.             } else {
  180.                 b += '>';
  181.                 if ((cn = o.children || o.cn)) {
  182.                     b += createHtml(cn);
  183.                 } else if(o.html){
  184.                     b += o.html;
  185.                 }
  186.                 b += '</' + o.tag + '>';
  187.             }
  188.         }
  189.         return b;
  190.     }
  191.     function ieTable(depth, s, h, e){
  192.         tempTableEl.innerHTML = [s, h, e].join('');
  193.         var i = -1,
  194.             el = tempTableEl,
  195.             ns;
  196.         while(++i < depth){
  197.             el = el.firstChild;
  198.         }
  199. //      If the result is multiple siblings, then encapsulate them into one fragment.
  200.         if(ns = el.nextSibling){
  201.             var df = document.createDocumentFragment();
  202.             while(el){
  203.                 ns = el.nextSibling;
  204.                 df.appendChild(el);
  205.                 el = ns;
  206.             }
  207.             el = df;
  208.         }
  209.         return el;
  210.     }
  211.     /**
  212.      * @ignore
  213.      * Nasty code for IE's broken table implementation
  214.      */
  215.     function insertIntoTable(tag, where, el, html) {
  216.         var node,
  217.             before;
  218.         tempTableEl = tempTableEl || document.createElement('div');
  219.         if(tag == 'td' && (where == afterbegin || where == beforeend) ||
  220.            !/td|tr|tbody/i.test(tag) && (where == beforebegin || where == afterend)) {
  221.             return;
  222.         }
  223.         before = where == beforebegin ? el :
  224.                  where == afterend ? el.nextSibling :
  225.                  where == afterbegin ? el.firstChild : null;
  226.         if (where == beforebegin || where == afterend) {
  227.             el = el.parentNode;
  228.         }
  229.         if (tag == 'td' || (tag == 'tr' && (where == beforeend || where == afterbegin))) {
  230.             node = ieTable(4, trs, html, tre);
  231.         } else if ((tag == 'tbody' && (where == beforeend || where == afterbegin)) ||
  232.                    (tag == 'tr' && (where == beforebegin || where == afterend))) {
  233.             node = ieTable(3, tbs, html, tbe);
  234.         } else {
  235.             node = ieTable(2, ts, html, te);
  236.         }
  237.         el.insertBefore(node, before);
  238.         return node;
  239.     }
  240.     pub = {
  241.         /**
  242.          * Returns the markup for the passed Element(s) config.
  243.          * @param {Object} o The DOM object spec (and children)
  244.          * @return {String}
  245.          */
  246.         markup : function(o){
  247.             return createHtml(o);
  248.         },
  249.         
  250.         /**
  251.          * Applies a style specification to an element.
  252.          * @param {String/HTMLElement} el The element to apply styles to
  253.          * @param {String/Object/Function} styles A style specification string e.g. 'width:100px', or object in the form {width:'100px'}, or
  254.          * a function which returns such a specification.
  255.          */
  256.         applyStyles : function(el, styles){
  257.             if(styles){
  258.                 var i = 0,
  259.                     len,
  260.                     style;
  261.                 el = Ext.fly(el);
  262.                 if(Ext.isFunction(styles)){
  263.                     styles = styles.call();
  264.                 }
  265.                 if(Ext.isString(styles)){
  266.                     styles = styles.trim().split(/s*(?::|;)s*/);
  267.                     for(len = styles.length; i < len;){
  268.                         el.setStyle(styles[i++], styles[i++]);
  269.                     }
  270.                 }else if (Ext.isObject(styles)){
  271.                     el.setStyle(styles);
  272.                 }
  273.             }
  274.         },
  275.         /**
  276.          * Inserts an HTML fragment into the DOM.
  277.          * @param {String} where Where to insert the html in relation to el - beforeBegin, afterBegin, beforeEnd, afterEnd.
  278.          * @param {HTMLElement} el The context element
  279.          * @param {String} html The HTML fragment
  280.          * @return {HTMLElement} The new node
  281.          */
  282.         insertHtml : function(where, el, html){
  283.             var hash = {},
  284.                 hashVal,
  285.                 setStart,
  286.                 range,
  287.                 frag,
  288.                 rangeEl,
  289.                 rs;
  290.             where = where.toLowerCase();
  291.             // add these here because they are used in both branches of the condition.
  292.             hash[beforebegin] = ['BeforeBegin', 'previousSibling'];
  293.             hash[afterend] = ['AfterEnd', 'nextSibling'];
  294.             if (el.insertAdjacentHTML) {
  295.                 if(tableRe.test(el.tagName) && (rs = insertIntoTable(el.tagName.toLowerCase(), where, el, html))){
  296.                     return rs;
  297.                 }
  298.                 // add these two to the hash.
  299.                 hash[afterbegin] = ['AfterBegin', 'firstChild'];
  300.                 hash[beforeend] = ['BeforeEnd', 'lastChild'];
  301.                 if ((hashVal = hash[where])) {
  302.                     el.insertAdjacentHTML(hashVal[0], html);
  303.                     return el[hashVal[1]];
  304.                 }
  305.             } else {
  306.                 range = el.ownerDocument.createRange();
  307.                 setStart = 'setStart' + (/end/i.test(where) ? 'After' : 'Before');
  308.                 if (hash[where]) {
  309.                     range[setStart](el);
  310.                     frag = range.createContextualFragment(html);
  311.                     el.parentNode.insertBefore(frag, where == beforebegin ? el : el.nextSibling);
  312.                     return el[(where == beforebegin ? 'previous' : 'next') + 'Sibling'];
  313.                 } else {
  314.                     rangeEl = (where == afterbegin ? 'first' : 'last') + 'Child';
  315.                     if (el.firstChild) {
  316.                         range[setStart](el[rangeEl]);
  317.                         frag = range.createContextualFragment(html);
  318.                         if(where == afterbegin){
  319.                             el.insertBefore(frag, el.firstChild);
  320.                         }else{
  321.                             el.appendChild(frag);
  322.                         }
  323.                     } else {
  324.                         el.innerHTML = html;
  325.                     }
  326.                     return el[rangeEl];
  327.                 }
  328.             }
  329.             throw 'Illegal insertion point -> "' + where + '"';
  330.         },
  331.         /**
  332.          * Creates new DOM element(s) and inserts them before el.
  333.          * @param {Mixed} el The context element
  334.          * @param {Object/String} o The DOM object spec (and children) or raw HTML blob
  335.          * @param {Boolean} returnElement (optional) true to return a Ext.Element
  336.          * @return {HTMLElement/Ext.Element} The new node
  337.          */
  338.         insertBefore : function(el, o, returnElement){
  339.             return doInsert(el, o, returnElement, beforebegin);
  340.         },
  341.         /**
  342.          * Creates new DOM element(s) and inserts them after el.
  343.          * @param {Mixed} el The context element
  344.          * @param {Object} o The DOM object spec (and children)
  345.          * @param {Boolean} returnElement (optional) true to return a Ext.Element
  346.          * @return {HTMLElement/Ext.Element} The new node
  347.          */
  348.         insertAfter : function(el, o, returnElement){
  349.             return doInsert(el, o, returnElement, afterend, 'nextSibling');
  350.         },
  351.         /**
  352.          * Creates new DOM element(s) and inserts them as the first child of el.
  353.          * @param {Mixed} el The context element
  354.          * @param {Object/String} o The DOM object spec (and children) or raw HTML blob
  355.          * @param {Boolean} returnElement (optional) true to return a Ext.Element
  356.          * @return {HTMLElement/Ext.Element} The new node
  357.          */
  358.         insertFirst : function(el, o, returnElement){
  359.             return doInsert(el, o, returnElement, afterbegin, 'firstChild');
  360.         },
  361.         /**
  362.          * Creates new DOM element(s) and appends them to el.
  363.          * @param {Mixed} el The context element
  364.          * @param {Object/String} o The DOM object spec (and children) or raw HTML blob
  365.          * @param {Boolean} returnElement (optional) true to return a Ext.Element
  366.          * @return {HTMLElement/Ext.Element} The new node
  367.          */
  368.         append : function(el, o, returnElement){
  369.             return doInsert(el, o, returnElement, beforeend, '', true);
  370.         },
  371.         /**
  372.          * Creates new DOM element(s) and overwrites the contents of el with them.
  373.          * @param {Mixed} el The context element
  374.          * @param {Object/String} o The DOM object spec (and children) or raw HTML blob
  375.          * @param {Boolean} returnElement (optional) true to return a Ext.Element
  376.          * @return {HTMLElement/Ext.Element} The new node
  377.          */
  378.         overwrite : function(el, o, returnElement){
  379.             el = Ext.getDom(el);
  380.             el.innerHTML = createHtml(o);
  381.             return returnElement ? Ext.get(el.firstChild) : el.firstChild;
  382.         },
  383.         createHtml : createHtml
  384.     };
  385.     return pub;
  386. }();/**
  387.  * @class Ext.DomHelper
  388.  */
  389. Ext.apply(Ext.DomHelper,
  390. function(){
  391. var pub,
  392. afterbegin = 'afterbegin',
  393.      afterend = 'afterend',
  394.      beforebegin = 'beforebegin',
  395.      beforeend = 'beforeend';
  396. // private
  397.     function doInsert(el, o, returnElement, pos, sibling, append){
  398.         el = Ext.getDom(el);
  399.         var newNode;
  400.         if (pub.useDom) {
  401.             newNode = createDom(o, null);
  402.             if (append) {
  403.             el.appendChild(newNode);
  404.             } else {
  405.          (sibling == 'firstChild' ? el : el.parentNode).insertBefore(newNode, el[sibling] || el);
  406.             }
  407.         } else {
  408.             newNode = Ext.DomHelper.insertHtml(pos, el, Ext.DomHelper.createHtml(o));
  409.         }
  410.         return returnElement ? Ext.get(newNode, true) : newNode;
  411.     }
  412. // build as dom
  413.     /** @ignore */
  414.     function createDom(o, parentNode){
  415.         var el,
  416.          doc = document,
  417.          useSet,
  418.          attr,
  419.          val,
  420.          cn;
  421.         if (Ext.isArray(o)) {                       // Allow Arrays of siblings to be inserted
  422.             el = doc.createDocumentFragment(); // in one shot using a DocumentFragment
  423.         Ext.each(o, function(v) {
  424.                 createDom(v, el);
  425.             });
  426.         } else if (Ext.isString(o)) {         // Allow a string as a child spec.
  427.             el = doc.createTextNode(o);
  428.         } else {
  429.             el = doc.createElement( o.tag || 'div' );
  430.             useSet = !!el.setAttribute; // In IE some elements don't have setAttribute
  431.             Ext.iterate(o, function(attr, val){
  432.                 if(!/tag|children|cn|html|style/.test(attr)){
  433.                 if(attr == 'cls'){
  434.                     el.className = val;
  435.                 }else{
  436.                         if(useSet){
  437.                             el.setAttribute(attr, val);
  438.                         }else{
  439.                             el[attr] = val;
  440.                         }
  441.                 }
  442.                 }
  443.             });
  444.             Ext.DomHelper.applyStyles(el, o.style);
  445.             if ((cn = o.children || o.cn)) {
  446.                 createDom(cn, el);
  447.             } else if (o.html) {
  448.                 el.innerHTML = o.html;
  449.             }
  450.         }
  451.         if(parentNode){
  452.            parentNode.appendChild(el);
  453.         }
  454.         return el;
  455.     }
  456. pub = {
  457. /**
  458.      * Creates a new Ext.Template from the DOM object spec.
  459.      * @param {Object} o The DOM object spec (and children)
  460.      * @return {Ext.Template} The new template
  461.      */
  462.     createTemplate : function(o){
  463.         var html = Ext.DomHelper.createHtml(o);
  464.         return new Ext.Template(html);
  465.     },
  466. /** True to force the use of DOM instead of html fragments @type Boolean */
  467.     useDom : false,
  468.     /**
  469.      * Creates new DOM element(s) and inserts them before el.
  470.      * @param {Mixed} el The context element
  471.      * @param {Object/String} o The DOM object spec (and children) or raw HTML blob
  472.      * @param {Boolean} returnElement (optional) true to return a Ext.Element
  473.      * @return {HTMLElement/Ext.Element} The new node
  474.          * @hide (repeat)
  475.      */
  476.     insertBefore : function(el, o, returnElement){
  477.         return doInsert(el, o, returnElement, beforebegin);
  478.     },
  479.     /**
  480.      * Creates new DOM element(s) and inserts them after el.
  481.      * @param {Mixed} el The context element
  482.      * @param {Object} o The DOM object spec (and children)
  483.      * @param {Boolean} returnElement (optional) true to return a Ext.Element
  484.      * @return {HTMLElement/Ext.Element} The new node
  485.          * @hide (repeat)
  486.      */
  487.     insertAfter : function(el, o, returnElement){
  488.         return doInsert(el, o, returnElement, afterend, 'nextSibling');
  489.     },
  490.     /**
  491.      * Creates new DOM element(s) and inserts them as the first child of el.
  492.      * @param {Mixed} el The context element
  493.      * @param {Object/String} o The DOM object spec (and children) or raw HTML blob
  494.      * @param {Boolean} returnElement (optional) true to return a Ext.Element
  495.      * @return {HTMLElement/Ext.Element} The new node
  496.          * @hide (repeat)
  497.      */
  498.     insertFirst : function(el, o, returnElement){
  499.         return doInsert(el, o, returnElement, afterbegin, 'firstChild');
  500.     },
  501.     /**
  502.      * Creates new DOM element(s) and appends them to el.
  503.      * @param {Mixed} el The context element
  504.      * @param {Object/String} o The DOM object spec (and children) or raw HTML blob
  505.      * @param {Boolean} returnElement (optional) true to return a Ext.Element
  506.      * @return {HTMLElement/Ext.Element} The new node
  507.          * @hide (repeat)
  508.      */
  509.     append: function(el, o, returnElement){
  510.             return doInsert(el, o, returnElement, beforeend, '', true);
  511.         },
  512.     /**
  513.      * Creates new DOM element(s) without inserting them to the document.
  514.      * @param {Object/String} o The DOM object spec (and children) or raw HTML blob
  515.      * @return {HTMLElement} The new uninserted node
  516.      */
  517.         createDom: createDom
  518. };
  519. return pub;
  520. }());/**  * @class Ext.Template  * <p>Represents an HTML fragment template. Templates may be {@link #compile precompiled}  * for greater performance.</p>  * <p>For example usage {@link #Template see the constructor}.</p>  *   * @constructor  * An instance of this class may be created by passing to the constructor either  * a single argument, or multiple arguments:  * <div class="mdetail-params"><ul>  * <li><b>single argument</b> : String/Array  * <div class="sub-desc">  * The single argument may be either a String or an Array:<ul>  * <li><tt>String</tt> : </li><pre><code> var t = new Ext.Template("&lt;div>Hello {0}.&lt;/div>"); t.{@link #append}('some-element', ['foo']);  * </code></pre>  * <li><tt>Array</tt> : </li>  * An Array will be combined with <code>join('')</code>. <pre><code> var t = new Ext.Template([     '&lt;div name="{id}"&gt;',         '&lt;span class="{cls}"&gt;{name:trim} {value:ellipsis(10)}&lt;/span&gt;',     '&lt;/div&gt;', ]); t.{@link #compile}(); t.{@link #append}('some-element', {id: 'myid', cls: 'myclass', name: 'foo', value: 'bar'}); </code></pre>  * </ul></div></li>  * <li><b>multiple arguments</b> : String, Object, Array, ...  * <div class="sub-desc">  * Multiple arguments will be combined with <code>join('')</code>.  * <pre><code> var t = new Ext.Template(     '&lt;div name="{id}"&gt;',         '&lt;span class="{cls}"&gt;{name} {value}&lt;/span&gt;',     '&lt;/div&gt;',     // a configuration object:     {         compiled: true,      // {@link #compile} immediately         disableFormats: true // See Notes below.     }  );  * </code></pre>  * <p><b>Notes</b>:</p>  * <div class="mdetail-params"><ul>  * <li>Formatting and <code>disableFormats</code> are not applicable for Ext Core.</li>  * <li>For a list of available format functions, see {@link Ext.util.Format}.</li>  * <li><code>disableFormats</code> reduces <code>{@link #apply}</code> time  * when no formatting is required.</li>  * </ul></div>  * </div></li>  * </ul></div>  * @param {Mixed} config  */ Ext.Template = function(html){     var me = this,      a = arguments,      buf = [];     if (Ext.isArray(html)) {         html = html.join("");     } else if (a.length > 1) {     Ext.each(a, function(v) {             if (Ext.isObject(v)) {                 Ext.apply(me, v);             } else {                 buf.push(v);             }         });         html = buf.join('');     }     /**@private*/     me.html = html;     /**      * @cfg {Boolean} compiled Specify <tt>true</tt> to compile the template      * immediately (see <code>{@link #compile}</code>).      * Defaults to <tt>false</tt>.      */     if (me.compiled) {         me.compile();     } }; Ext.Template.prototype = {     /**      * @cfg {RegExp} re The regular expression used to match template variables.      * Defaults to:<pre><code>      * re : /{([w-]+)}/g                                     // for Ext Core      * re : /{([w-]+)(?::([w.]*)(?:((.*?)?))?)?}/g      // for Ext JS      * </code></pre>      */     re : /{([w-]+)}/g,     /**      * See <code>{@link #re}</code>.      * @type RegExp      * @property re      */     /**      * Returns an HTML fragment of this template with the specified <code>values</code> applied.      * @param {Object/Array} values      * The template values. Can be an array if the params are numeric (i.e. <code>{0}</code>)      * or an object (i.e. <code>{foo: 'bar'}</code>).      * @return {String} The HTML fragment      */     applyTemplate : function(values){ var me = this;         return me.compiled ?          me.compiled(values) : me.html.replace(me.re, function(m, name){          return values[name] !== undefined ? values[name] : "";         }); },     /**      * Sets the HTML used as the template and optionally compiles it.      * @param {String} html      * @param {Boolean} compile (optional) True to compile the template (defaults to undefined)      * @return {Ext.Template} this      */     set : function(html, compile){     var me = this;         me.html = html;         me.compiled = null;         return compile ? me.compile() : me;     },     /**      * Compiles the template into an internal function, eliminating the RegEx overhead.      * @return {Ext.Template} this      */     compile : function(){         var me = this,          sep = Ext.isGecko ? "+" : ",";         function fn(m, name){                                 name = "values['" + name + "']";         return "'"+ sep + '(' + name + " == undefined ? '' : " + name + ')' + sep + "'";         }                          eval("this.compiled = function(values){ return " + (Ext.isGecko ? "'" : "['") +              me.html.replace(/\/g, '\\').replace(/(rn|n)/g, '\n').replace(/'/g, "\'").replace(this.re, fn) +              (Ext.isGecko ?  "';};" : "'].join('');};"));         return me;     },     /**      * Applies the supplied values to the template and inserts the new node(s) as the first child of el.      * @param {Mixed} el The context element      * @param {Object/Array} values The template values. Can be an array if your params are numeric (i.e. {0}) or an object (i.e. {foo: 'bar'})      * @param {Boolean} returnElement (optional) true to return a Ext.Element (defaults to undefined)      * @return {HTMLElement/Ext.Element} The new node or Element      */     insertFirst: function(el, values, returnElement){         return this.doInsert('afterBegin', el, values, returnElement);     },     /**      * Applies the supplied values to the template and inserts the new node(s) before el.      * @param {Mixed} el The context element      * @param {Object/Array} values The template values. Can be an array if your params are numeric (i.e. {0}) or an object (i.e. {foo: 'bar'})      * @param {Boolean} returnElement (optional) true to return a Ext.Element (defaults to undefined)      * @return {HTMLElement/Ext.Element} The new node or Element      */     insertBefore: function(el, values, returnElement){         return this.doInsert('beforeBegin', el, values, returnElement);     },     /**      * Applies the supplied values to the template and inserts the new node(s) after el.      * @param {Mixed} el The context element      * @param {Object/Array} values The template values. Can be an array if your params are numeric (i.e. {0}) or an object (i.e. {foo: 'bar'})      * @param {Boolean} returnElement (optional) true to return a Ext.Element (defaults to undefined)      * @return {HTMLElement/Ext.Element} The new node or Element      */     insertAfter : function(el, values, returnElement){         return this.doInsert('afterEnd', el, values, returnElement);     },     /**      * Applies the supplied <code>values</code> to the template and appends      * the new node(s) to the specified <code>el</code>.      * <p>For example usage {@link #Template see the constructor}.</p>      * @param {Mixed} el The context element      * @param {Object/Array} values      * The template values. Can be an array if the params are numeric (i.e. <code>{0}</code>)      * or an object (i.e. <code>{foo: 'bar'}</code>).      * @param {Boolean} returnElement (optional) true to return an Ext.Element (defaults to undefined)      * @return {HTMLElement/Ext.Element} The new node or Element      */     append : function(el, values, returnElement){         return this.doInsert('beforeEnd', el, values, returnElement);     },     doInsert : function(where, el, values, returnEl){         el = Ext.getDom(el);         var newNode = Ext.DomHelper.insertHtml(where, el, this.applyTemplate(values));         return returnEl ? Ext.get(newNode, true) : newNode;     },     /**      * Applies the supplied values to the template and overwrites the content of el with the new node(s).      * @param {Mixed} el The context element      * @param {Object/Array} values The template values. Can be an array if your params are numeric (i.e. {0}) or an object (i.e. {foo: 'bar'})      * @param {Boolean} returnElement (optional) true to return a Ext.Element (defaults to undefined)      * @return {HTMLElement/Ext.Element} The new node or Element      */     overwrite : function(el, values, returnElement){         el = Ext.getDom(el);         el.innerHTML = this.applyTemplate(values);         return returnElement ? Ext.get(el.firstChild, true) : el.firstChild;     } }; /**  * Alias for {@link #applyTemplate}  * Returns an HTML fragment of this template with the specified <code>values</code> applied.  * @param {Object/Array} values  * The template values. Can be an array if the params are numeric (i.e. <code>{0}</code>)  * or an object (i.e. <code>{foo: 'bar'}</code>).  * @return {String} The HTML fragment  * @member Ext.Template  * @method apply  */ Ext.Template.prototype.apply = Ext.Template.prototype.applyTemplate; /**  * Creates a template from the passed element's value (<i>display:none</i> textarea, preferred) or innerHTML.  * @param {String/HTMLElement} el A DOM element or its id  * @param {Object} config A configuration object  * @return {Ext.Template} The created template  * @static  */ Ext.Template.from = function(el, config){     el = Ext.getDom(el);     return new Ext.Template(el.value || el.innerHTML, config || ''); };/**
  521.  * @class Ext.Template
  522.  */
  523. Ext.apply(Ext.Template.prototype, {
  524.     /**
  525.      * @cfg {Boolean} disableFormats Specify <tt>true</tt> to disable format
  526.      * functions in the template. If the template does not contain
  527.      * {@link Ext.util.Format format functions}, setting <code>disableFormats</code>
  528.      * to true will reduce <code>{@link #apply}</code> time. Defaults to <tt>false</tt>.
  529.      * <pre><code>
  530. var t = new Ext.Template(
  531.     '&lt;div name="{id}"&gt;',
  532.         '&lt;span class="{cls}"&gt;{name} {value}&lt;/span&gt;',
  533.     '&lt;/div&gt;',
  534.     {
  535.         compiled: true,      // {@link #compile} immediately
  536.         disableFormats: true // reduce <code>{@link #apply}</code> time since no formatting
  537.     }    
  538. );
  539.      * </code></pre>
  540.      * For a list of available format functions, see {@link Ext.util.Format}.
  541.      */
  542.     disableFormats : false,
  543.     /**
  544.      * See <code>{@link #disableFormats}</code>.
  545.      * @type Boolean
  546.      * @property disableFormats
  547.      */
  548.     /**
  549.      * The regular expression used to match template variables
  550.      * @type RegExp
  551.      * @property
  552.      * @hide repeat doc
  553.      */
  554.     re : /{([w-]+)(?::([w.]*)(?:((.*?)?))?)?}/g,
  555.     /**
  556.      * Returns an HTML fragment of this template with the specified values applied.
  557.      * @param {Object/Array} values The template values. Can be an array if your params are numeric (i.e. {0}) or an object (i.e. {foo: 'bar'})
  558.      * @return {String} The HTML fragment
  559.      * @hide repeat doc
  560.      */
  561.     applyTemplate : function(values){
  562. var me = this,
  563. useF = me.disableFormats !== true,
  564.          fm = Ext.util.Format, 
  565.          tpl = me;     
  566.     
  567.         if(me.compiled){
  568.             return me.compiled(values);
  569.         }
  570.         function fn(m, name, format, args){
  571.             if (format && useF) {
  572.                 if (format.substr(0, 5) == "this.") {
  573.                     return tpl.call(format.substr(5), values[name], values);
  574.                 } else {
  575.                     if (args) {
  576.                         // quoted values are required for strings in compiled templates,
  577.                         // but for non compiled we need to strip them
  578.                         // quoted reversed for jsmin
  579.                         var re = /^s*['"](.*)["']s*$/;
  580.                         args = args.split(',');
  581.                         for(var i = 0, len = args.length; i < len; i++){
  582.                             args[i] = args[i].replace(re, "$1");
  583.                         }
  584.                         args = [values[name]].concat(args);
  585.                     } else {
  586.                         args = [values[name]];
  587.                     }
  588.                     return fm[format].apply(fm, args);
  589.                 }
  590.             } else {
  591.                 return values[name] !== undefined ? values[name] : "";
  592.             }
  593.         }
  594.         return me.html.replace(me.re, fn);
  595.     },
  596.     /**
  597.      * Compiles the template into an internal function, eliminating the RegEx overhead.
  598.      * @return {Ext.Template} this
  599.      * @hide repeat doc
  600.      */
  601.     compile : function(){
  602.         var me = this,
  603.          fm = Ext.util.Format,
  604.          useF = me.disableFormats !== true,
  605.          sep = Ext.isGecko ? "+" : ",",
  606.          body;
  607.         
  608.         function fn(m, name, format, args){
  609.             if(format && useF){
  610.                 args = args ? ',' + args : "";
  611.                 if(format.substr(0, 5) != "this."){
  612.                     format = "fm." + format + '(';
  613.                 }else{
  614.                     format = 'this.call("'+ format.substr(5) + '", ';
  615.                     args = ", values";
  616.                 }
  617.             }else{
  618.                 args= ''; format = "(values['" + name + "'] == undefined ? '' : ";
  619.             }
  620.             return "'"+ sep + format + "values['" + name + "']" + args + ")"+sep+"'";
  621.         }
  622.         
  623.         // branched to use + in gecko and [].join() in others
  624.         if(Ext.isGecko){
  625.             body = "this.compiled = function(values){ return '" +
  626.                    me.html.replace(/\/g, '\\').replace(/(rn|n)/g, '\n').replace(/'/g, "\'").replace(this.re, fn) +
  627.                     "';};";
  628.         }else{
  629.             body = ["this.compiled = function(values){ return ['"];
  630.             body.push(me.html.replace(/\/g, '\\').replace(/(rn|n)/g, '\n').replace(/'/g, "\'").replace(this.re, fn));
  631.             body.push("'].join('');};");
  632.             body = body.join('');
  633.         }
  634.         eval(body);
  635.         return me;
  636.     },
  637.     
  638.     // private function used to call members
  639.     call : function(fnName, value, allValues){
  640.         return this[fnName](value, allValues);
  641.     }
  642. });
  643. Ext.Template.prototype.apply = Ext.Template.prototype.applyTemplate; /*
  644.  * This is code is also distributed under MIT license for use
  645.  * with jQuery and prototype JavaScript libraries.
  646.  */
  647. /**
  648.  * @class Ext.DomQuery
  649. Provides high performance selector/xpath processing by compiling queries into reusable functions. New pseudo classes and matchers can be plugged. It works on HTML and XML documents (if a content node is passed in).
  650. <p>
  651. DomQuery supports most of the <a href="http://www.w3.org/TR/2005/WD-css3-selectors-20051215/#selectors">CSS3 selectors spec</a>, along with some custom selectors and basic XPath.</p>
  652. <p>
  653. All selectors, attribute filters and pseudos below can be combined infinitely in any order. For example "div.foo:nth-child(odd)[@foo=bar].bar:first" would be a perfectly valid selector. Node filters are processed in the order in which they appear, which allows you to optimize your queries for your document structure.
  654. </p>
  655. <h4>Element Selectors:</h4>
  656. <ul class="list">
  657.     <li> <b>*</b> any element</li>
  658.     <li> <b>E</b> an element with the tag E</li>
  659.     <li> <b>E F</b> All descendent elements of E that have the tag F</li>
  660.     <li> <b>E > F</b> or <b>E/F</b> all direct children elements of E that have the tag F</li>
  661.     <li> <b>E + F</b> all elements with the tag F that are immediately preceded by an element with the tag E</li>
  662.     <li> <b>E ~ F</b> all elements with the tag F that are preceded by a sibling element with the tag E</li>
  663. </ul>
  664. <h4>Attribute Selectors:</h4>
  665. <p>The use of &#64; and quotes are optional. For example, div[&#64;foo='bar'] is also a valid attribute selector.</p>
  666. <ul class="list">
  667.     <li> <b>E[foo]</b> has an attribute "foo"</li>
  668.     <li> <b>E[foo=bar]</b> has an attribute "foo" that equals "bar"</li>
  669.     <li> <b>E[foo^=bar]</b> has an attribute "foo" that starts with "bar"</li>
  670.     <li> <b>E[foo$=bar]</b> has an attribute "foo" that ends with "bar"</li>
  671.     <li> <b>E[foo*=bar]</b> has an attribute "foo" that contains the substring "bar"</li>
  672.     <li> <b>E[foo%=2]</b> has an attribute "foo" that is evenly divisible by 2</li>
  673.     <li> <b>E[foo!=bar]</b> has an attribute "foo" that does not equal "bar"</li>
  674. </ul>
  675. <h4>Pseudo Classes:</h4>
  676. <ul class="list">
  677.     <li> <b>E:first-child</b> E is the first child of its parent</li>
  678.     <li> <b>E:last-child</b> E is the last child of its parent</li>
  679.     <li> <b>E:nth-child(<i>n</i>)</b> E is the <i>n</i>th child of its parent (1 based as per the spec)</li>
  680.     <li> <b>E:nth-child(odd)</b> E is an odd child of its parent</li>
  681.     <li> <b>E:nth-child(even)</b> E is an even child of its parent</li>
  682.     <li> <b>E:only-child</b> E is the only child of its parent</li>
  683.     <li> <b>E:checked</b> E is an element that is has a checked attribute that is true (e.g. a radio or checkbox) </li>
  684.     <li> <b>E:first</b> the first E in the resultset</li>
  685.     <li> <b>E:last</b> the last E in the resultset</li>
  686.     <li> <b>E:nth(<i>n</i>)</b> the <i>n</i>th E in the resultset (1 based)</li>
  687.     <li> <b>E:odd</b> shortcut for :nth-child(odd)</li>
  688.     <li> <b>E:even</b> shortcut for :nth-child(even)</li>
  689.     <li> <b>E:contains(foo)</b> E's innerHTML contains the substring "foo"</li>
  690.     <li> <b>E:nodeValue(foo)</b> E contains a textNode with a nodeValue that equals "foo"</li>
  691.     <li> <b>E:not(S)</b> an E element that does not match simple selector S</li>
  692.     <li> <b>E:has(S)</b> an E element that has a descendent that matches simple selector S</li>
  693.     <li> <b>E:next(S)</b> an E element whose next sibling matches simple selector S</li>
  694.     <li> <b>E:prev(S)</b> an E element whose previous sibling matches simple selector S</li>
  695. </ul>
  696. <h4>CSS Value Selectors:</h4>
  697. <ul class="list">
  698.     <li> <b>E{display=none}</b> css value "display" that equals "none"</li>
  699.     <li> <b>E{display^=none}</b> css value "display" that starts with "none"</li>
  700.     <li> <b>E{display$=none}</b> css value "display" that ends with "none"</li>
  701.     <li> <b>E{display*=none}</b> css value "display" that contains the substring "none"</li>
  702.     <li> <b>E{display%=2}</b> css value "display" that is evenly divisible by 2</li>
  703.     <li> <b>E{display!=none}</b> css value "display" that does not equal "none"</li>
  704. </ul>
  705.  * @singleton
  706.  */
  707. Ext.DomQuery = function(){
  708.     var cache = {}, 
  709.      simpleCache = {}, 
  710.      valueCache = {},
  711.      nonSpace = /S/,
  712.      trimRe = /^s+|s+$/g,
  713.      tplRe = /{(d+)}/g,
  714.      modeRe = /^(s?[/>+~]s?|s|$)/,
  715.      tagTokenRe = /^(#)?([w-*]+)/,
  716.      nthRe = /(d*)n+?(d*)/, 
  717.      nthRe2 = /D/,
  718.      // This is for IE MSXML which does not support expandos.
  719.     // IE runs the same speed using setAttribute, however FF slows way down
  720.     // and Safari completely fails so they need to continue to use expandos.
  721.     isIE = window.ActiveXObject ? true : false,
  722.     key = 30803;
  723.     
  724.     // this eval is stop the compressor from
  725. // renaming the variable to something shorter
  726. eval("var batch = 30803;");    
  727.     function child(p, index){
  728.         var i = 0,
  729.          n = p.firstChild;
  730.         while(n){
  731.             if(n.nodeType == 1){
  732.                if(++i == index){
  733.                    return n;
  734.                }
  735.             }
  736.             n = n.nextSibling;
  737.         }
  738.         return null;
  739.     };
  740.     function next(n){
  741.         while((n = n.nextSibling) && n.nodeType != 1);
  742.         return n;
  743.     };
  744.     function prev(n){
  745.         while((n = n.previousSibling) && n.nodeType != 1);
  746.         return n;
  747.     };
  748.     function children(d){
  749.         var n = d.firstChild, ni = -1,
  750.          nx;
  751.       while(n){
  752.           nx = n.nextSibling;
  753.           if(n.nodeType == 3 && !nonSpace.test(n.nodeValue)){
  754.               d.removeChild(n);
  755.           }else{
  756.               n.nodeIndex = ++ni;
  757.           }
  758.           n = nx;
  759.       }
  760.       return this;
  761.   };
  762.     function byClassName(c, a, v){
  763.         if(!v){
  764.             return c;
  765.         }
  766.         var r = [], ri = -1, cn;
  767.         for(var i = 0, ci; ci = c[i]; i++){
  768.             if((' '+ci.className+' ').indexOf(v) != -1){
  769.                 r[++ri] = ci;
  770.             }
  771.         }
  772.         return r;
  773.     };
  774.     function attrValue(n, attr){
  775.         if(!n.tagName && typeof n.length != "undefined"){
  776.             n = n[0];
  777.         }
  778.         if(!n){
  779.             return null;
  780.         }
  781.         if(attr == "for"){
  782.             return n.htmlFor;
  783.         }
  784.         if(attr == "class" || attr == "className"){
  785.             return n.className;
  786.         }
  787.         return n.getAttribute(attr) || n[attr];
  788.     };
  789.     function getNodes(ns, mode, tagName){
  790.         var result = [], ri = -1, cs;
  791.         if(!ns){
  792.             return result;
  793.         }
  794.         tagName = tagName || "*";
  795.         if(typeof ns.getElementsByTagName != "undefined"){
  796.             ns = [ns];
  797.         }
  798.         if(!mode){
  799.             for(var i = 0, ni; ni = ns[i]; i++){
  800.                 cs = ni.getElementsByTagName(tagName);
  801.                 for(var j = 0, ci; ci = cs[j]; j++){
  802.                     result[++ri] = ci;
  803.                 }
  804.             }
  805.         }else if(mode == "/" || mode == ">"){
  806.             var utag = tagName.toUpperCase();
  807.             for(var i = 0, ni, cn; ni = ns[i]; i++){
  808.                 cn = ni.childNodes;
  809.                 for(var j = 0, cj; cj = cn[j]; j++){
  810.                     if(cj.nodeName == utag || cj.nodeName == tagName  || tagName == '*'){
  811.                         result[++ri] = cj;
  812.                     }
  813.                 }
  814.             }
  815.         }else if(mode == "+"){
  816.             var utag = tagName.toUpperCase();
  817.             for(var i = 0, n; n = ns[i]; i++){
  818.                 while((n = n.nextSibling) && n.nodeType != 1);
  819.                 if(n && (n.nodeName == utag || n.nodeName == tagName || tagName == '*')){
  820.                     result[++ri] = n;
  821.                 }
  822.             }
  823.         }else if(mode == "~"){
  824.             var utag = tagName.toUpperCase();
  825.             for(var i = 0, n; n = ns[i]; i++){
  826.                 while((n = n.nextSibling)){
  827.                     if (n.nodeName == utag || n.nodeName == tagName || tagName == '*'){
  828.                         result[++ri] = n;
  829.                     }
  830.                 }
  831.             }
  832.         }
  833.         return result;
  834.     };
  835.     function concat(a, b){
  836.         if(b.slice){
  837.             return a.concat(b);
  838.         }
  839.         for(var i = 0, l = b.length; i < l; i++){
  840.             a[a.length] = b[i];
  841.         }
  842.         return a;
  843.     }
  844.     function byTag(cs, tagName){
  845.         if(cs.tagName || cs == document){
  846.             cs = [cs];
  847.         }
  848.         if(!tagName){
  849.             return cs;
  850.         }
  851.         var r = [], ri = -1;
  852.         tagName = tagName.toLowerCase();
  853.         for(var i = 0, ci; ci = cs[i]; i++){
  854.             if(ci.nodeType == 1 && ci.tagName.toLowerCase()==tagName){
  855.                 r[++ri] = ci;
  856.             }
  857.         }
  858.         return r;
  859.     };
  860.     function byId(cs, attr, id){
  861.         if(cs.tagName || cs == document){
  862.             cs = [cs];
  863.         }
  864.         if(!id){
  865.             return cs;
  866.         }
  867.         var r = [], ri = -1;
  868.         for(var i = 0,ci; ci = cs[i]; i++){
  869.             if(ci && ci.id == id){
  870.                 r[++ri] = ci;
  871.                 return r;
  872.             }
  873.         }
  874.         return r;
  875.     };
  876.     function byAttribute(cs, attr, value, op, custom){
  877.         var r = [], 
  878.          ri = -1, 
  879.          st = custom=="{",
  880.          f = Ext.DomQuery.operators[op];
  881.         for(var i = 0, ci; ci = cs[i]; i++){
  882.             if(ci.nodeType != 1){
  883.                 continue;
  884.             }
  885.             var a;
  886.             if(st){
  887.                 a = Ext.DomQuery.getStyle(ci, attr);
  888.             }
  889.             else if(attr == "class" || attr == "className"){
  890.                 a = ci.className;
  891.             }else if(attr == "for"){
  892.                 a = ci.htmlFor;
  893.             }else if(attr == "href"){
  894.                 a = ci.getAttribute("href", 2);
  895.             }else{
  896.                 a = ci.getAttribute(attr);
  897.             }
  898.             if((f && f(a, value)) || (!f && a)){
  899.                 r[++ri] = ci;
  900.             }
  901.         }
  902.         return r;
  903.     };
  904.     function byPseudo(cs, name, value){
  905.         return Ext.DomQuery.pseudos[name](cs, value);
  906.     };
  907.     function nodupIEXml(cs){
  908.         var d = ++key, 
  909.          r;
  910.         cs[0].setAttribute("_nodup", d);
  911.         r = [cs[0]];
  912.         for(var i = 1, len = cs.length; i < len; i++){
  913.             var c = cs[i];
  914.             if(!c.getAttribute("_nodup") != d){
  915.                 c.setAttribute("_nodup", d);
  916.                 r[r.length] = c;
  917.             }
  918.         }
  919.         for(var i = 0, len = cs.length; i < len; i++){
  920.             cs[i].removeAttribute("_nodup");
  921.         }
  922.         return r;
  923.     }
  924.     function nodup(cs){
  925.         if(!cs){
  926.             return [];
  927.         }
  928.         var len = cs.length, c, i, r = cs, cj, ri = -1;
  929.         if(!len || typeof cs.nodeType != "undefined" || len == 1){
  930.             return cs;
  931.         }
  932.         if(isIE && typeof cs[0].selectSingleNode != "undefined"){
  933.             return nodupIEXml(cs);
  934.         }
  935.         var d = ++key;
  936.         cs[0]._nodup = d;
  937.         for(i = 1; c = cs[i]; i++){
  938.             if(c._nodup != d){
  939.                 c._nodup = d;
  940.             }else{
  941.                 r = [];
  942.                 for(var j = 0; j < i; j++){
  943.                     r[++ri] = cs[j];
  944.                 }
  945.                 for(j = i+1; cj = cs[j]; j++){
  946.                     if(cj._nodup != d){
  947.                         cj._nodup = d;
  948.                         r[++ri] = cj;
  949.                     }
  950.                 }
  951.                 return r;
  952.             }
  953.         }
  954.         return r;
  955.     }
  956.     function quickDiffIEXml(c1, c2){
  957.         var d = ++key,
  958.          r = [];
  959.         for(var i = 0, len = c1.length; i < len; i++){
  960.             c1[i].setAttribute("_qdiff", d);
  961.         }        
  962.         for(var i = 0, len = c2.length; i < len; i++){
  963.             if(c2[i].getAttribute("_qdiff") != d){
  964.                 r[r.length] = c2[i];
  965.             }
  966.         }
  967.         for(var i = 0, len = c1.length; i < len; i++){
  968.            c1[i].removeAttribute("_qdiff");
  969.         }
  970.         return r;
  971.     }
  972.     function quickDiff(c1, c2){
  973.         var len1 = c1.length,
  974.          d = ++key,
  975.          r = [];
  976.         if(!len1){
  977.             return c2;
  978.         }
  979.         if(isIE && typeof c1[0].selectSingleNode != "undefined"){
  980.             return quickDiffIEXml(c1, c2);
  981.         }        
  982.         for(var i = 0; i < len1; i++){
  983.             c1[i]._qdiff = d;
  984.         }        
  985.         for(var i = 0, len = c2.length; i < len; i++){
  986.             if(c2[i]._qdiff != d){
  987.                 r[r.length] = c2[i];
  988.             }
  989.         }
  990.         return r;
  991.     }
  992.     function quickId(ns, mode, root, id){
  993.         if(ns == root){
  994.            var d = root.ownerDocument || root;
  995.            return d.getElementById(id);
  996.         }
  997.         ns = getNodes(ns, mode, "*");
  998.         return byId(ns, null, id);
  999.     }
  1000.     return {
  1001.         getStyle : function(el, name){
  1002.             return Ext.fly(el).getStyle(name);
  1003.         },
  1004.         /**
  1005.          * Compiles a selector/xpath query into a reusable function. The returned function
  1006.          * takes one parameter "root" (optional), which is the context node from where the query should start.
  1007.          * @param {String} selector The selector/xpath query
  1008.          * @param {String} type (optional) Either "select" (the default) or "simple" for a simple selector match
  1009.          * @return {Function}
  1010.          */
  1011.         compile : function(path, type){
  1012.             type = type || "select";
  1013.             var fn = ["var f = function(root){n var mode; ++batch; var n = root || document;n"],
  1014.              q = path, mode, lq,
  1015.              tk = Ext.DomQuery.matchers,
  1016.              tklen = tk.length,
  1017.              mm,
  1018.              // accept leading mode switch
  1019.              lmode = q.match(modeRe);
  1020.             
  1021.             if(lmode && lmode[1]){
  1022.                 fn[fn.length] = 'mode="'+lmode[1].replace(trimRe, "")+'";';
  1023.                 q = q.replace(lmode[1], "");
  1024.             }
  1025.             // strip leading slashes
  1026.             while(path.substr(0, 1)=="/"){
  1027.                 path = path.substr(1);
  1028.             }
  1029.             while(q && lq != q){
  1030.                 lq = q;
  1031.                 var tm = q.match(tagTokenRe);
  1032.                 if(type == "select"){
  1033.                     if(tm){
  1034.                         if(tm[1] == "#"){
  1035.                             fn[fn.length] = 'n = quickId(n, mode, root, "'+tm[2]+'");';
  1036.                         }else{
  1037.                             fn[fn.length] = 'n = getNodes(n, mode, "'+tm[2]+'");';
  1038.                         }
  1039.                         q = q.replace(tm[0], "");
  1040.                     }else if(q.substr(0, 1) != '@'){
  1041.                         fn[fn.length] = 'n = getNodes(n, mode, "*");';
  1042.                     }
  1043.                 }else{
  1044.                     if(tm){
  1045.                         if(tm[1] == "#"){
  1046.                             fn[fn.length] = 'n = byId(n, null, "'+tm[2]+'");';
  1047.                         }else{
  1048.                             fn[fn.length] = 'n = byTag(n, "'+tm[2]+'");';
  1049.                         }
  1050.                         q = q.replace(tm[0], "");
  1051.                     }
  1052.                 }
  1053.                 while(!(mm = q.match(modeRe))){
  1054.                     var matched = false;
  1055.                     for(var j = 0; j < tklen; j++){
  1056.                         var t = tk[j];
  1057.                         var m = q.match(t.re);
  1058.                         if(m){
  1059.                             fn[fn.length] = t.select.replace(tplRe, function(x, i){
  1060.                                                     return m[i];
  1061.                                                 });
  1062.                             q = q.replace(m[0], "");
  1063.                             matched = true;
  1064.                             break;
  1065.                         }
  1066.                     }
  1067.                     // prevent infinite loop on bad selector
  1068.                     if(!matched){
  1069.                         throw 'Error parsing selector, parsing failed at "' + q + '"';
  1070.                     }
  1071.                 }
  1072.                 if(mm[1]){
  1073.                     fn[fn.length] = 'mode="'+mm[1].replace(trimRe, "")+'";';
  1074.                     q = q.replace(mm[1], "");
  1075.                 }
  1076.             }
  1077.             fn[fn.length] = "return nodup(n);n}";
  1078.             eval(fn.join(""));
  1079.             return f;
  1080.         },
  1081.         /**
  1082.          * Selects a group of elements.
  1083.          * @param {String} selector The selector/xpath query (can be a comma separated list of selectors)
  1084.          * @param {Node} root (optional) The start of the query (defaults to document).
  1085.          * @return {Array} An Array of DOM elements which match the selector. If there are
  1086.          * no matches, and empty Array is returned.
  1087.          */
  1088.         select : function(path, root, type){
  1089.             if(!root || root == document){
  1090.                 root = document;
  1091.             }
  1092.             if(typeof root == "string"){
  1093.                 root = document.getElementById(root);
  1094.             }
  1095.             var paths = path.split(","),
  1096.              results = [];
  1097.             for(var i = 0, len = paths.length; i < len; i++){
  1098.                 var p = paths[i].replace(trimRe, "");
  1099.                 if(!cache[p]){
  1100.                     cache[p] = Ext.DomQuery.compile(p);
  1101.                     if(!cache[p]){
  1102.                         throw p + " is not a valid selector";
  1103.                     }
  1104.                 }
  1105.                 var result = cache[p](root);
  1106.                 if(result && result != document){
  1107.                     results = results.concat(result);
  1108.                 }
  1109.             }
  1110.             if(paths.length > 1){
  1111.                 return nodup(results);
  1112.             }
  1113.             return results;
  1114.         },
  1115.         /**
  1116.          * Selects a single element.
  1117.          * @param {String} selector The selector/xpath query
  1118.          * @param {Node} root (optional) The start of the query (defaults to document).
  1119.          * @return {Element} The DOM element which matched the selector.
  1120.          */
  1121.         selectNode : function(path, root){
  1122.             return Ext.DomQuery.select(path, root)[0];
  1123.         },
  1124.         /**
  1125.          * Selects the value of a node, optionally replacing null with the defaultValue.
  1126.          * @param {String} selector The selector/xpath query
  1127.          * @param {Node} root (optional) The start of the query (defaults to document).
  1128.          * @param {String} defaultValue
  1129.          * @return {String}
  1130.          */
  1131.         selectValue : function(path, root, defaultValue){
  1132.             path = path.replace(trimRe, "");
  1133.             if(!valueCache[path]){
  1134.                 valueCache[path] = Ext.DomQuery.compile(path, "select");
  1135.             }
  1136.             var n = valueCache[path](root), v;
  1137.             n = n[0] ? n[0] : n;
  1138.             
  1139.             if (typeof n.normalize == 'function') n.normalize();
  1140.             
  1141.             v = (n && n.firstChild ? n.firstChild.nodeValue : null);
  1142.             return ((v === null||v === undefined||v==='') ? defaultValue : v);
  1143.         },
  1144.         /**
  1145.          * Selects the value of a node, parsing integers and floats. Returns the defaultValue, or 0 if none is specified.
  1146.          * @param {String} selector The selector/xpath query
  1147.          * @param {Node} root (optional) The start of the query (defaults to document).
  1148.          * @param {Number} defaultValue
  1149.          * @return {Number}
  1150.          */
  1151.         selectNumber : function(path, root, defaultValue){
  1152.             var v = Ext.DomQuery.selectValue(path, root, defaultValue || 0);
  1153.             return parseFloat(v);
  1154.         },
  1155.         /**
  1156.          * Returns true if the passed element(s) match the passed simple selector (e.g. div.some-class or span:first-child)
  1157.          * @param {String/HTMLElement/Array} el An element id, element or array of elements
  1158.          * @param {String} selector The simple selector to test
  1159.          * @return {Boolean}
  1160.          */
  1161.         is : function(el, ss){
  1162.             if(typeof el == "string"){
  1163.                 el = document.getElementById(el);
  1164.             }
  1165.             var isArray = Ext.isArray(el),
  1166.              result = Ext.DomQuery.filter(isArray ? el : [el], ss);
  1167.             return isArray ? (result.length == el.length) : (result.length > 0);
  1168.         },
  1169.         /**
  1170.          * Filters an array of elements to only include matches of a simple selector (e.g. div.some-class or span:first-child)
  1171.          * @param {Array} el An array of elements to filter
  1172.          * @param {String} selector The simple selector to test
  1173.          * @param {Boolean} nonMatches If true, it returns the elements that DON'T match
  1174.          * the selector instead of the ones that match
  1175.          * @return {Array} An Array of DOM elements which match the selector. If there are
  1176.          * no matches, and empty Array is returned.
  1177.          */
  1178.         filter : function(els, ss, nonMatches){
  1179.             ss = ss.replace(trimRe, "");
  1180.             if(!simpleCache[ss]){
  1181.                 simpleCache[ss] = Ext.DomQuery.compile(ss, "simple");
  1182.             }
  1183.             var result = simpleCache[ss](els);
  1184.             return nonMatches ? quickDiff(result, els) : result;
  1185.         },
  1186.         /**
  1187.          * Collection of matching regular expressions and code snippets.
  1188.          */
  1189.         matchers : [{
  1190.                 re: /^.([w-]+)/,
  1191.                 select: 'n = byClassName(n, null, " {1} ");'
  1192.             }, {
  1193.                 re: /^:([w-]+)(?:(((?:[^s>/]*|.*?))))?/,
  1194.                 select: 'n = byPseudo(n, "{1}", "{2}");'
  1195.             },{
  1196.                 re: /^(?:([[{])(?:@)?([w-]+)s?(?:(=|.=)s?['"]?(.*?)["']?)?[]}])/,
  1197.                 select: 'n = byAttribute(n, "{2}", "{4}", "{3}", "{1}");'
  1198.             }, {
  1199.                 re: /^#([w-]+)/,
  1200.                 select: 'n = byId(n, null, "{1}");'
  1201.             },{
  1202.                 re: /^@([w-]+)/,
  1203.                 select: 'return {firstChild:{nodeValue:attrValue(n, "{1}")}};'
  1204.             }
  1205.         ],
  1206.         /**
  1207.          * Collection of operator comparison functions. The default operators are =, !=, ^=, $=, *=, %=, |= and ~=.
  1208.          * New operators can be added as long as the match the format <i>c</i>= where <i>c</i> is any character other than space, &gt; &lt;.
  1209.          */
  1210.         operators : {
  1211.             "=" : function(a, v){
  1212.                 return a == v;
  1213.             },
  1214.             "!=" : function(a, v){
  1215.                 return a != v;
  1216.             },
  1217.             "^=" : function(a, v){
  1218.                 return a && a.substr(0, v.length) == v;
  1219.             },
  1220.             "$=" : function(a, v){
  1221.                 return a && a.substr(a.length-v.length) == v;
  1222.             },
  1223.             "*=" : function(a, v){
  1224.                 return a && a.indexOf(v) !== -1;
  1225.             },
  1226.             "%=" : function(a, v){
  1227.                 return (a % v) == 0;
  1228.             },
  1229.             "|=" : function(a, v){
  1230.                 return a && (a == v || a.substr(0, v.length+1) == v+'-');
  1231.             },
  1232.             "~=" : function(a, v){
  1233.                 return a && (' '+a+' ').indexOf(' '+v+' ') != -1;
  1234.             }
  1235.         },
  1236.         /**
  1237.          * <p>Object hash of "pseudo class" filter functions which are used when filtering selections. Each function is passed
  1238.          * two parameters:</p><div class="mdetail-params"><ul>
  1239.          * <li><b>c</b> : Array<div class="sub-desc">An Array of DOM elements to filter.</div></li>
  1240.          * <li><b>v</b> : String<div class="sub-desc">The argument (if any) supplied in the selector.</div></li>
  1241.          * </ul></div>
  1242.          * <p>A filter function returns an Array of DOM elements which conform to the pseudo class.</p>
  1243.          * <p>In addition to the provided pseudo classes listed above such as <code>first-child</code> and <code>nth-child</code>,
  1244.          * developers may add additional, custom psuedo class filters to select elements according to application-specific requirements.</p>
  1245.          * <p>For example, to filter <code>&lt;a></code> elements to only return links to <i>external</i> resources:</p>
  1246.          * <code><pre>
  1247. Ext.DomQuery.pseudos.external = function(c, v){
  1248.     var r = [], ri = -1;
  1249.     for(var i = 0, ci; ci = c[i]; i++){
  1250. //      Include in result set only if it's a link to an external resource
  1251.         if(ci.hostname != location.hostname){
  1252.             r[++ri] = ci;
  1253.         }
  1254.     }
  1255.     return r;
  1256. };</pre></code>
  1257.          * Then external links could be gathered with the following statement:<code><pre>
  1258. var externalLinks = Ext.select("a:external");
  1259. </code></pre>
  1260.          */
  1261.         pseudos : {
  1262.             "first-child" : function(c){
  1263.                 var r = [], ri = -1, n;
  1264.                 for(var i = 0, ci; ci = n = c[i]; i++){
  1265.                     while((n = n.previousSibling) && n.nodeType != 1);
  1266.                     if(!n){
  1267.                         r[++ri] = ci;
  1268.                     }
  1269.                 }
  1270.                 return r;
  1271.             },
  1272.             "last-child" : function(c){
  1273.                 var r = [], ri = -1, n;
  1274.                 for(var i = 0, ci; ci = n = c[i]; i++){
  1275.                     while((n = n.nextSibling) && n.nodeType != 1);
  1276.                     if(!n){
  1277.                         r[++ri] = ci;
  1278.                     }
  1279.                 }
  1280.                 return r;
  1281.             },
  1282.             "nth-child" : function(c, a) {
  1283.                 var r = [], ri = -1,
  1284.                  m = nthRe.exec(a == "even" && "2n" || a == "odd" && "2n+1" || !nthRe2.test(a) && "n+" + a || a),
  1285.                  f = (m[1] || 1) - 0, l = m[2] - 0;
  1286.                 for(var i = 0, n; n = c[i]; i++){
  1287.                     var pn = n.parentNode;
  1288.                     if (batch != pn._batch) {
  1289.                         var j = 0;
  1290.                         for(var cn = pn.firstChild; cn; cn = cn.nextSibling){
  1291.                             if(cn.nodeType == 1){
  1292.                                cn.nodeIndex = ++j;
  1293.                             }
  1294.                         }
  1295.                         pn._batch = batch;
  1296.                     }
  1297.                     if (f == 1) {
  1298.                         if (l == 0 || n.nodeIndex == l){
  1299.                             r[++ri] = n;
  1300.                         }
  1301.                     } else if ((n.nodeIndex + l) % f == 0){
  1302.                         r[++ri] = n;
  1303.                     }
  1304.                 }
  1305.                 return r;
  1306.             },
  1307.             "only-child" : function(c){
  1308.                 var r = [], ri = -1;;
  1309.                 for(var i = 0, ci; ci = c[i]; i++){
  1310.                     if(!prev(ci) && !next(ci)){
  1311.                         r[++ri] = ci;
  1312.                     }
  1313.                 }
  1314.                 return r;
  1315.             },
  1316.             "empty" : function(c){
  1317.                 var r = [], ri = -1;
  1318.                 for(var i = 0, ci; ci = c[i]; i++){
  1319.                     var cns = ci.childNodes, j = 0, cn, empty = true;
  1320.                     while(cn = cns[j]){
  1321.                         ++j;
  1322.                         if(cn.nodeType == 1 || cn.nodeType == 3){
  1323.                             empty = false;
  1324.                             break;
  1325.                         }
  1326.                     }
  1327.                     if(empty){
  1328.                         r[++ri] = ci;
  1329.                     }
  1330.                 }
  1331.                 return r;
  1332.             },
  1333.             "contains" : function(c, v){
  1334.                 var r = [], ri = -1;
  1335.                 for(var i = 0, ci; ci = c[i]; i++){
  1336.                     if((ci.textContent||ci.innerText||'').indexOf(v) != -1){
  1337.                         r[++ri] = ci;
  1338.                     }
  1339.                 }
  1340.                 return r;
  1341.             },
  1342.             "nodeValue" : function(c, v){
  1343.                 var r = [], ri = -1;
  1344.                 for(var i = 0, ci; ci = c[i]; i++){
  1345.                     if(ci.firstChild && ci.firstChild.nodeValue == v){
  1346.                         r[++ri] = ci;
  1347.                     }
  1348.                 }
  1349.                 return r;
  1350.             },
  1351.             "checked" : function(c){
  1352.                 var r = [], ri = -1;
  1353.                 for(var i = 0, ci; ci = c[i]; i++){
  1354.                     if(ci.checked == true){
  1355.                         r[++ri] = ci;
  1356.                     }
  1357.                 }
  1358.                 return r;
  1359.             },
  1360.             "not" : function(c, ss){
  1361.                 return Ext.DomQuery.filter(c, ss, true);
  1362.             },
  1363.             "any" : function(c, selectors){
  1364.                 var ss = selectors.split('|'),
  1365.                  r = [], ri = -1, s;
  1366.                 for(var i = 0, ci; ci = c[i]; i++){
  1367.                     for(var j = 0; s = ss[j]; j++){
  1368.                         if(Ext.DomQuery.is(ci, s)){
  1369.                             r[++ri] = ci;
  1370.                             break;
  1371.                         }
  1372.                     }
  1373.                 }
  1374.                 return r;
  1375.             },
  1376.             "odd" : function(c){
  1377.                 return this["nth-child"](c, "odd");
  1378.             },
  1379.             "even" : function(c){
  1380.                 return this["nth-child"](c, "even");
  1381.             },