text: /**
   * This class encapsulates a *collection* of DOM elements, providing methods to filter members, or to perform collective
   * actions upon the whole set.
   *
   * Although they are not listed, this class supports all of the methods of {@link Ext.dom.Element} and
   * {@link Ext.Anim}. The methods from these classes will be performed on all the elements in this collection.
   *
   * Example:
   *
   *     var els = Ext.select("#some-el div.some-class");
   *     // or select directly from an existing element
   *     var el = Ext.get('some-el');
   *     el.select('div.some-class');
   *
   *     els.setWidth(100); // all elements become 100 width
   *     els.hide(true); // all elements fade out and hide
   *     // or
   *     els.setWidth(100).hide(true);
   */
  Ext.define('Ext.dom.CompositeElementLite', {
      alternateClassName: ['Ext.CompositeElementLite', 'Ext.CompositeElement'],
  
      requires: ['Ext.dom.Element'],
  
      statics: {
          /**
           * @private
           * @static
           * Copies all of the functions from Ext.dom.Element's prototype onto CompositeElementLite's prototype.
           */
          importElementMethods: function() {
  
          }
      },
  
      constructor: function(elements, root) {
          /**
           * @property {HTMLElement[]} elements
           * The Array of DOM elements which this CompositeElement encapsulates. Read-only.
           *
           * This will not *usually* be accessed in developers' code, but developers wishing to augment the capabilities
           * of the CompositeElementLite class may use it when adding methods to the class.
           *
           * For example to add the `nextAll` method to the class to **add** all following siblings of selected elements,
           * the code would be
           *
           *     Ext.override(Ext.dom.CompositeElementLite, {
           *         nextAll: function() {
           *             var elements = this.elements, i, l = elements.length, n, r = [], ri = -1;
           *
           *             // Loop through all elements in this Composite, accumulating
           *             // an Array of all siblings.
           *             for (i = 0; i < l; i++) {
           *                 for (n = elements[i].nextSibling; n; n = n.nextSibling) {
           *                     r[++ri] = n;
           *                 }
           *             }
           *
           *             // Add all found siblings to this Composite
           *             return this.add(r);
           *         }
           *     });
           *
           */
          this.elements = [];
          this.add(elements, root);
          this.el = new Ext.dom.Element.Fly();
      },
  
      isComposite: true,
  
      // private
      getElement: function(el) {
          // Set the shared flyweight dom property to the current element
          return this.el.attach(el).synchronize();
      },
  
      // private
      transformElement: function(el) {
          return Ext.getDom(el);
      },
  
      /**
       * Returns the number of elements in this Composite.
       * @return {Number}
       */
      getCount: function() {
          return this.elements.length;
      },
  
      /**
       * Adds elements to this Composite object.
       * @param {HTMLElement[]/Ext.dom.CompositeElementLite} els Either an Array of DOM elements to add, or another Composite
       * object who's elements should be added.
       * @return {Ext.dom.CompositeElementLite} This Composite object.
       */
      add: function(els, root) {
          var elements = this.elements,
              i, ln;
  
          if (!els) {
              return this;
          }
  
          if (typeof els == "string") {
              els = Ext.dom.Element.selectorFunction(els, root);
          }
          else if (els.isComposite) {
              els = els.elements;
          }
          else if (!Ext.isIterable(els)) {
              els = [els];
          }
  
          for (i = 0, ln = els.length; i < ln; ++i) {
              elements.push(this.transformElement(els[i]));
          }
  
          return this;
      },
  
      invoke: function(fn, args) {
          var elements = this.elements,
              ln = elements.length,
              element,
              i;
  
          for (i = 0; i < ln; i++) {
              element = elements[i];
  
              if (element) {
                  Ext.dom.Element.prototype[fn].apply(this.getElement(element), args);
              }
          }
          return this;
      },
  
      /**
       * Returns a flyweight Element of the dom element object at the specified index
       * @param {Number} index
       * @return {Ext.dom.Element}
       */
      item: function(index) {
          var el = this.elements[index],
              out = null;
  
          if (el) {
              out = this.getElement(el);
          }
  
          return out;
      },
  
      // fixes scope with flyweight
      addListener: function(eventName, handler, scope, opt) {
          var els = this.elements,
                  len = els.length,
                  i, e;
  
          for (i = 0; i < len; i++) {
              e = els[i];
              if (e) {
                  Ext.EventManager.on(e, eventName, handler, scope || e, opt);
              }
          }
          return this;
      },
      /**
       * Calls the passed function for each element in this composite.
       * @param {Function} fn The function to call.
       * @param {Ext.dom.Element} fn.el The current Element in the iteration. **This is the flyweight
       * (shared) Ext.dom.Element instance, so if you require a a reference to the dom node, use el.dom.**
       * @param {Ext.dom.CompositeElementLite} fn.c This Composite object.
       * @param {Number} fn.index The zero-based index in the iteration.
       * @param {Object} [scope] The scope (this reference) in which the function is executed.
       * Defaults to the Element.
       * @return {Ext.dom.CompositeElementLite} this
       */
      each: function(fn, scope) {
          var me = this,
                  els = me.elements,
                  len = els.length,
                  i, e;
  
          for (i = 0; i < len; i++) {
              e = els[i];
              if (e) {
                  e = this.getElement(e);
                  if (fn.call(scope || e, e, me, i) === false) {
                      break;
                  }
              }
          }
          return me;
      },
  
      /**
       * Clears this Composite and adds the elements passed.
       * @param {HTMLElement[]/Ext.dom.CompositeElementLite} els Either an array of DOM elements, or another Composite from which
       * to fill this Composite.
       * @return {Ext.dom.CompositeElementLite} this
       */
      fill: function(els) {
          var me = this;
          me.elements = [];
          me.add(els);
          return me;
      },
  
      /**
       * Filters this composite to only elements that match the passed selector.
       * @param {String/Function} selector A string CSS selector or a comparison function. The comparison function will be
       * called with the following arguments:
       * @param {Ext.dom.Element} selector.el The current DOM element.
       * @param {Number} selector.index The current index within the collection.
       * @return {Ext.dom.CompositeElementLite} this
       */
      filter: function(selector) {
          var els = [],
                  me = this,
                  fn = Ext.isFunction(selector) ? selector
                          : function(el) {
                      return el.is(selector);
                  };
  
          me.each(function(el, self, i) {
              if (fn(el, i) !== false) {
                  els[els.length] = me.transformElement(el);
              }
          });
  
          me.elements = els;
          return me;
      },
  
      /**
       * Find the index of the passed element within the composite collection.
       * @param {String/HTMLElement/Ext.Element/Number} el The id of an element, or an Ext.dom.Element, or an HtmlElement
       * to find within the composite collection.
       * @return {Number} The index of the passed Ext.dom.Element in the composite collection, or -1 if not found.
       */
      indexOf: function(el) {
          return Ext.Array.indexOf(this.elements, this.transformElement(el));
      },
  
      /**
       * Replaces the specified element with the passed element.
       * @param {String/HTMLElement/Ext.Element/Number} el The id of an element, the Element itself, the index of the
       * element in this composite to replace.
       * @param {String/Ext.Element} replacement The id of an element or the Element itself.
       * @param {Boolean} [domReplace] True to remove and replace the element in the document too.
       * @return {Ext.dom.CompositeElementLite} this
       */
      replaceElement: function(el, replacement, domReplace) {
          var index = !isNaN(el) ? el : this.indexOf(el),
                  d;
          if (index > -1) {
              replacement = Ext.getDom(replacement);
              if (domReplace) {
                  d = this.elements[index];
                  d.parentNode.insertBefore(replacement, d);
                  Ext.removeNode(d);
              }
              Ext.Array.splice(this.elements, index, 1, replacement);
          }
          return this;
      },
  
      /**
       * Removes all elements.
       */
      clear: function() {
          this.elements = [];
      },
  
      addElements: function(els, root) {
          if (!els) {
              return this;
          }
  
          if (typeof els == "string") {
              els = Ext.dom.Element.selectorFunction(els, root);
          }
  
          var yels = this.elements;
  
          Ext.each(els, function(e) {
              yels.push(Ext.get(e));
          });
  
          return this;
      },
  
      /**
       * Returns the first Element
       * @return {Ext.dom.Element}
       */
      first: function() {
          return this.item(0);
      },
  
      /**
       * Returns the last Element
       * @return {Ext.dom.Element}
       */
      last: function() {
          return this.item(this.getCount() - 1);
      },
  
      /**
       * Returns true if this composite contains the passed element
       * @param {String/HTMLElement/Ext.Element/Number} el The id of an element, or an Ext.Element, or an HtmlElement to
       * find within the composite collection.
       * @return {Boolean}
       */
      contains: function(el) {
          return this.indexOf(el) != -1;
      },
  
      /**
       * Removes the specified element(s).
       * @param {String/HTMLElement/Ext.Element/Number} el The id of an element, the Element itself, the index of the
       * element in this composite or an array of any of those.
       * @param {Boolean} [removeDom] True to also remove the element from the document
       * @return {Ext.dom.CompositeElementLite} this
       */
      removeElement: function(keys, removeDom) {
          var me = this,
                  elements = this.elements,
                  el;
  
          Ext.each(keys, function(val) {
              if ((el = (elements[val] || elements[val = me.indexOf(val)]))) {
                  if (removeDom) {
                      if (el.dom) {
                          el.remove();
                      }
                      else {
                          Ext.removeNode(el);
                      }
                  }
                  Ext.Array.erase(elements, val, 1);
              }
          });
  
          return this;
      }
  
  }, function() {
      var Element = Ext.dom.Element,
          elementPrototype = Element.prototype,
          prototype = this.prototype,
          name;
  
      for (name in elementPrototype) {
          if (typeof elementPrototype[name] == 'function'){
              (function(key) {
                  prototype[key] = prototype[key] || function() {
                      return this.invoke(key, arguments);
                  };
              }).call(prototype, name);
          }
      }
  
      prototype.on = prototype.addListener;
  
      if (Ext.DomQuery){
          Element.selectorFunction = Ext.DomQuery.select;
      }
  
      /**
       * Selects elements based on the passed CSS selector to enable {@link Ext.Element Element} methods
       * to be applied to many related elements in one statement through the returned
       * {@link Ext.dom.CompositeElementLite CompositeElementLite} object.
       * @param {String/HTMLElement[]} selector The CSS selector or an array of elements
       * @param {HTMLElement/String} [root] The root element of the query or id of the root
       * @return {Ext.dom.CompositeElementLite}
       * @member Ext.dom.Element
       * @method select
       */
     Element.select = function(selector, root) {
          var elements;
  
          if (typeof selector == "string") {
              elements = Element.selectorFunction(selector, root);
          }
          else if (selector.length !== undefined) {
              elements = selector;
          }
          else {
              //<debug>
              throw new Error("[Ext.select] Invalid selector specified: " + selector);
              //</debug>
          }
  
          return new Ext.CompositeElementLite(elements);
      };
  
      /**
       * @member Ext
       * @method select
       * @alias Ext.dom.Element#select
       */
      Ext.select = function() {
          return Element.select.apply(Element, arguments);
      };
  });
  