src/cm/media/js/lib/yui/yui3.0.0/build/node/node-base.js
changeset 0 40c8f766c9b8
equal deleted inserted replaced
-1:000000000000 0:40c8f766c9b8
       
     1 /*
       
     2 Copyright (c) 2009, Yahoo! Inc. All rights reserved.
       
     3 Code licensed under the BSD License:
       
     4 http://developer.yahoo.net/yui/license.txt
       
     5 version: 3.0.0
       
     6 build: 1549
       
     7 */
       
     8 YUI.add('node-base', function(Y) {
       
     9 
       
    10 /**
       
    11  * The Node Utility provides a DOM-like interface for interacting with DOM nodes.
       
    12  * @module node
       
    13  * @submodule node-base
       
    14  */    
       
    15 
       
    16 /**
       
    17  * The Node class provides a wrapper for manipulating DOM Nodes.
       
    18  * Node properties can be accessed via the set/get methods.
       
    19  * Use Y.get() to retrieve Node instances.
       
    20  *
       
    21  * <strong>NOTE:</strong> Node properties are accessed using
       
    22  * the <code>set</code> and <code>get</code> methods.
       
    23  *
       
    24  * @class Node
       
    25  * @constructor
       
    26  * @for Node
       
    27  */
       
    28 
       
    29 // "globals"
       
    30 var DOT = '.',
       
    31     NODE_NAME = 'nodeName',
       
    32     NODE_TYPE = 'nodeType',
       
    33     OWNER_DOCUMENT = 'ownerDocument',
       
    34     TAG_NAME = 'tagName',
       
    35     UID = '_yuid',
       
    36 
       
    37     Node = function(node) {
       
    38         var uid = node[UID];
       
    39 
       
    40         if (uid && Node._instances[uid] && Node._instances[uid]._node !== node) {
       
    41             node[UID] = null; // unset existing uid to prevent collision (via clone or hack)
       
    42         }
       
    43 
       
    44         uid = Y.stamp(node);
       
    45         if (!uid) { // stamp failed; likely IE non-HTMLElement
       
    46             uid = Y.guid();
       
    47         }
       
    48 
       
    49         this[UID] = uid;
       
    50 
       
    51         this._node = node;
       
    52         Node._instances[uid] = this;
       
    53 
       
    54         this._stateProxy = node; // when augmented with Attribute
       
    55 
       
    56         if (this._initPlugins) { // when augmented with Plugin.Host
       
    57             this._initPlugins();
       
    58         }
       
    59     },
       
    60 
       
    61     // used with previous/next/ancestor tests
       
    62     _wrapFn = function(fn) {
       
    63         var ret = null;
       
    64         if (fn) {
       
    65             ret = (typeof fn === 'string') ?
       
    66             function(n) {
       
    67                 return Y.Selector.test(n, fn);
       
    68             } : 
       
    69             function(n) {
       
    70                 return fn(Node.get(n));
       
    71             };
       
    72         }
       
    73 
       
    74         return ret;
       
    75     };
       
    76 // end "globals"
       
    77 
       
    78 Node.NAME = 'Node';
       
    79 
       
    80 Node.re_aria = /^(?:role$|aria-)/;
       
    81 
       
    82 Node.DOM_EVENTS = {
       
    83     abort: true,
       
    84     beforeunload: true,
       
    85     blur: true,
       
    86     change: true,
       
    87     click: true,
       
    88     close: true,
       
    89     command: true,
       
    90     contextmenu: true,
       
    91     drag: true,
       
    92     dragstart: true,
       
    93     dragenter: true,
       
    94     dragover: true,
       
    95     dragleave: true,
       
    96     dragend: true,
       
    97     drop: true,
       
    98     dblclick: true,
       
    99     error: true,
       
   100     focus: true,
       
   101     keydown: true,
       
   102     keypress: true,
       
   103     keyup: true,
       
   104     load: true,
       
   105     message: true,
       
   106     mousedown: true,
       
   107     mousemove: true,
       
   108     mouseout: true, 
       
   109     mouseover: true, 
       
   110     mouseup: true,
       
   111     mousemultiwheel: true,
       
   112     mousewheel: true,
       
   113     submit: true,
       
   114     mouseenter: true,
       
   115     mouseleave: true,
       
   116     scroll: true,
       
   117     reset: true,
       
   118     resize: true,
       
   119     select: true,
       
   120     textInput: true,
       
   121     unload: true
       
   122 };
       
   123 
       
   124 // Add custom event adaptors to this list.  This will make it so
       
   125 // that delegate, key, available, contentready, etc all will
       
   126 // be available through Node.on
       
   127 Y.mix(Node.DOM_EVENTS, Y.Env.evt.plugins);
       
   128 
       
   129 Node._instances = {};
       
   130 
       
   131 /**
       
   132  * Retrieves the DOM node bound to a Node instance
       
   133  * @method Node.getDOMNode
       
   134  * @static
       
   135  *
       
   136  * @param {Y.Node || HTMLNode} node The Node instance or an HTMLNode
       
   137  * @return {HTMLNode} The DOM node bound to the Node instance.  If a DOM node is passed
       
   138  * as the node argument, it is simply returned.
       
   139  */
       
   140 Node.getDOMNode = function(node) {
       
   141     if (node) {
       
   142         return (node.nodeType) ? node : node._node || null;
       
   143     }
       
   144     return null;
       
   145 };
       
   146  
       
   147 Node.scrubVal = function(val, node) {
       
   148     if (node && val) { // only truthy values are risky
       
   149         if (typeof val === 'object' || typeof val === 'function') { // safari nodeList === function
       
   150             if (NODE_TYPE in val || Y.DOM.isWindow(val)) {// node || window
       
   151                 val = Node.get(val);
       
   152             } else if ((val.item && !val._nodes) || // dom collection or Node instance
       
   153                     (val[0] && val[0][NODE_TYPE])) { // array of DOM Nodes
       
   154                 val = Y.all(val);
       
   155             }
       
   156         }
       
   157     } else if (val === undefined) {
       
   158         val = node; // for chaining
       
   159     }
       
   160 
       
   161     return val;
       
   162 };
       
   163 
       
   164 Node.addMethod = function(name, fn, context) {
       
   165     if (name && fn && typeof fn === 'function') {
       
   166         Node.prototype[name] = function() {
       
   167             context = context || this;
       
   168             var args = Y.Array(arguments),
       
   169                 ret;
       
   170 
       
   171             if (args[0] && args[0] instanceof Node) {
       
   172                 args[0] = args[0]._node;
       
   173             }
       
   174 
       
   175             if (args[1] && args[1] instanceof Node) {
       
   176                 args[1] = args[1]._node;
       
   177             }
       
   178             args.unshift(this._node);
       
   179             ret = Node.scrubVal(fn.apply(context, args), this);
       
   180             return ret;
       
   181         };
       
   182     } else {
       
   183     }
       
   184 };
       
   185 
       
   186 Node.importMethod = function(host, name, altName) {
       
   187     if (typeof name === 'string') {
       
   188         altName = altName || name;
       
   189         Node.addMethod(altName, host[name], host);
       
   190     } else {
       
   191         Y.each(name, function(n) {
       
   192             Node.importMethod(host, n);
       
   193         });
       
   194     }
       
   195 };
       
   196 
       
   197 /**
       
   198  * Returns a single Node instance bound to the node or the
       
   199  * first element matching the given selector.
       
   200  * @method Y.one
       
   201  * @static
       
   202  * @param {String | HTMLElement} node a node or Selector 
       
   203  * @param {Y.Node || HTMLElement} doc an optional document to scan. Defaults to Y.config.doc. 
       
   204  */
       
   205 Node.one = function(node) {
       
   206     var instance = null,
       
   207         cachedNode,
       
   208         uid;
       
   209 
       
   210     if (node) {
       
   211         if (typeof node === 'string') {
       
   212             if (node.indexOf('doc') === 0) { // doc OR document
       
   213                 node = Y.config.doc;
       
   214             } else if (node.indexOf('win') === 0) { // win OR window
       
   215                 node = Y.config.win;
       
   216             } else {
       
   217                 node = Y.Selector.query(node, null, true);
       
   218             }
       
   219             if (!node) {
       
   220                 return null;
       
   221             }
       
   222         } else if (node instanceof Node) {
       
   223             return node; // NOTE: return
       
   224         }
       
   225 
       
   226         uid = node._yuid;
       
   227         instance = Node._instances[uid]; // reuse exising instances
       
   228         cachedNode = instance ? instance._node : null;
       
   229         if (!instance || (cachedNode && node !== cachedNode)) { // new Node when nodes don't match
       
   230             instance = new Node(node);
       
   231         }
       
   232     }
       
   233     return instance;
       
   234 };
       
   235 
       
   236 /**
       
   237  * Returns a single Node instance bound to the node or the
       
   238  * first element matching the given selector.
       
   239  * @method Y.get
       
   240  * @deprecated Use Y.one
       
   241  * @static
       
   242  * @param {String | HTMLElement} node a node or Selector 
       
   243  * @param {Y.Node || HTMLElement} doc an optional document to scan. Defaults to Y.config.doc. 
       
   244  */
       
   245 Node.get = function() {
       
   246     return Node.one.apply(Node, arguments);
       
   247 };
       
   248 
       
   249 /**
       
   250  * Creates a new dom node using the provided markup string. 
       
   251  * @method create
       
   252  * @static
       
   253  * @param {String} html The markup used to create the element
       
   254  * @param {HTMLDocument} doc An optional document context 
       
   255  * @return {Node} A Node instance bound to a DOM node or fragment 
       
   256  */
       
   257 Node.create = function() {
       
   258     return Node.get(Y.DOM.create.apply(Y.DOM, arguments));
       
   259 };
       
   260 
       
   261 Node.ATTRS = {
       
   262     /**
       
   263      * Allows for getting and setting the text of an element.
       
   264      * Formatting is preserved and special characters are treated literally.
       
   265      * @config text
       
   266      * @type String
       
   267      */
       
   268     text: {
       
   269         getter: function() {
       
   270             return Y.DOM.getText(this._node);
       
   271         },
       
   272 
       
   273         setter: function(content) {
       
   274             Y.DOM.setText(this._node, content);
       
   275             return content;
       
   276         }
       
   277     },
       
   278 
       
   279     'options': {
       
   280         getter: function() {
       
   281             return this._node.getElementsByTagName('option');
       
   282         }
       
   283     },
       
   284 
       
   285      // IE: elements collection is also FORM node which trips up scrubVal.
       
   286      // preconverting to NodeList
       
   287      // TODO: break out for IE only
       
   288     'elements': {
       
   289         getter: function() {
       
   290             return Y.all(this._node.elements);
       
   291         }
       
   292     },
       
   293 
       
   294     /**
       
   295      * Returns a NodeList instance of all HTMLElement children.
       
   296      * @readOnly
       
   297      * @config children
       
   298      * @type NodeList
       
   299      */
       
   300     'children': {
       
   301         getter: function() {
       
   302             var node = this._node,
       
   303                 children = node.children,
       
   304                 childNodes, i, len;
       
   305 
       
   306             if (!children) {
       
   307                 childNodes = node.childNodes;
       
   308                 children = [];
       
   309 
       
   310                 for (i = 0, len = childNodes.length; i < len; ++i) {
       
   311                     if (childNodes[i][TAG_NAME]) {
       
   312                         children[children.length] = childNodes[i];
       
   313                     }
       
   314                 }
       
   315             }
       
   316             return Y.all(children);
       
   317         }
       
   318     },
       
   319 
       
   320     value: {
       
   321         getter: function() {
       
   322             return Y.DOM.getValue(this._node);
       
   323         },
       
   324 
       
   325         setter: function(val) {
       
   326             Y.DOM.setValue(this._node, val);
       
   327             return val;
       
   328         }
       
   329     },
       
   330 
       
   331     data: {
       
   332         getter: function() {
       
   333             return this._data;
       
   334         },
       
   335 
       
   336         setter: function(val) {
       
   337             this._data = val;
       
   338             return val;
       
   339         }
       
   340     }
       
   341 };
       
   342 
       
   343 // call with instance context
       
   344 Node.DEFAULT_SETTER = function(name, val) {
       
   345     var node = this._stateProxy,
       
   346         strPath;
       
   347 
       
   348     if (name.indexOf(DOT) > -1) {
       
   349         strPath = name;
       
   350         name = name.split(DOT);
       
   351         // only allow when defined on node
       
   352         Y.Object.setValue(node, name, val);
       
   353     } else if (node[name] !== undefined) { // pass thru DOM properties 
       
   354         node[name] = val;
       
   355     }
       
   356 
       
   357     return val;
       
   358 };
       
   359 
       
   360 // call with instance context
       
   361 Node.DEFAULT_GETTER = function(name) {
       
   362     var node = this._stateProxy,
       
   363         val;
       
   364 
       
   365     if (name.indexOf && name.indexOf(DOT) > -1) {
       
   366         val = Y.Object.getValue(node, name.split(DOT));
       
   367     } else if (node[name] !== undefined) { // pass thru from DOM
       
   368         val = node[name];
       
   369     }
       
   370 
       
   371     return val;
       
   372 };
       
   373 
       
   374 Y.augment(Node, Y.Event.Target);
       
   375 
       
   376 Y.mix(Node.prototype, {
       
   377     toString: function() {
       
   378         var str = '',
       
   379             errorMsg = this[UID] + ': not bound to a node',
       
   380             node = this._node;
       
   381 
       
   382         if (node) {
       
   383             str += node[NODE_NAME];
       
   384             if (node.id) {
       
   385                 str += '#' + node.id; 
       
   386             }
       
   387 
       
   388             if (node.className) {
       
   389                 str += '.' + node.className.replace(' ', '.'); 
       
   390             }
       
   391 
       
   392             // TODO: add yuid?
       
   393             str += ' ' + this[UID];
       
   394         }
       
   395         return str || errorMsg;
       
   396     },
       
   397 
       
   398     /**
       
   399      * Returns an attribute value on the Node instance
       
   400      * @method get
       
   401      * @param {String} attr The attribute to be set
       
   402      * @return {any} The current value of the attribute
       
   403      */
       
   404     get: function(attr) {
       
   405         var val;
       
   406 
       
   407         if (this._getAttr) { // use Attribute imple
       
   408             val = this._getAttr(attr);
       
   409         } else {
       
   410             val = this._get(attr);
       
   411         }
       
   412 
       
   413         if (val) {
       
   414             val = Y.Node.scrubVal(val, this);
       
   415         }
       
   416         return val;
       
   417     },
       
   418 
       
   419     _get: function(attr) {
       
   420         var attrConfig = Node.ATTRS[attr],
       
   421             val;
       
   422 
       
   423         if (attrConfig && attrConfig.getter) {
       
   424             val = attrConfig.getter.call(this);
       
   425         } else if (Node.re_aria.test(attr)) {
       
   426             val = this._node.getAttribute(attr, 2); 
       
   427         } else {
       
   428             val = Node.DEFAULT_GETTER.apply(this, arguments);
       
   429         }
       
   430 
       
   431         return val;
       
   432     },
       
   433 
       
   434     /**
       
   435      * Sets an attribute on the Node instance.
       
   436      * @method set
       
   437      * @param {String} attr The attribute to be set.  
       
   438      * @param {any} val The value to set the attribute to.  
       
   439      * @chainable
       
   440      */
       
   441     set: function(attr, val) {
       
   442         var attrConfig = Node.ATTRS[attr];
       
   443 
       
   444         if (this._setAttr) { // use Attribute imple
       
   445             this._setAttr.apply(this, arguments);
       
   446         } else { // use setters inline
       
   447             if (attrConfig && attrConfig.setter) {
       
   448                 attrConfig.setter.call(this, val);
       
   449             } else if (Node.re_aria.test(attr)) { // special case Aria
       
   450                 this._node.setAttribute(attr, val);
       
   451             } else {
       
   452                 Node.DEFAULT_SETTER.apply(this, arguments);
       
   453             }
       
   454         }
       
   455 
       
   456         return this;
       
   457     },
       
   458 
       
   459     /**
       
   460      * Sets multiple attributes. 
       
   461      * @method setAttrs
       
   462      * @param {Object} attrMap an object of name/value pairs to set  
       
   463      * @chainable
       
   464      */
       
   465     setAttrs: function(attrMap) {
       
   466         if (this._setAttrs) { // use Attribute imple
       
   467             this._setAttrs(attrMap);
       
   468         } else { // use setters inline
       
   469             Y.Object.each(attrMap, function(v, n) {
       
   470                 this.set(n, v); 
       
   471             }, this);
       
   472         }
       
   473 
       
   474         return this;
       
   475     },
       
   476 
       
   477     /**
       
   478      * Returns an object containing the values for the requested attributes. 
       
   479      * @method getAttrs
       
   480      * @param {Array} attrs an array of attributes to get values  
       
   481      * @return {Object} An object with attribute name/value pairs.
       
   482      */
       
   483     getAttrs: function(attrs) {
       
   484         var ret = {};
       
   485         if (this._getAttrs) { // use Attribute imple
       
   486             this._getAttrs(attrs);
       
   487         } else { // use setters inline
       
   488             Y.Array.each(attrs, function(v, n) {
       
   489                 ret[v] = this.get(v); 
       
   490             }, this);
       
   491         }
       
   492 
       
   493         return ret;
       
   494     },
       
   495 
       
   496     /**
       
   497      * Creates a new Node using the provided markup string. 
       
   498      * @method create
       
   499      * @param {String} html The markup used to create the element
       
   500      * @param {HTMLDocument} doc An optional document context 
       
   501      * @return {Node} A Node instance bound to a DOM node or fragment 
       
   502      */
       
   503     create: Node.create,
       
   504 
       
   505     /**
       
   506      * Compares nodes to determine if they match.
       
   507      * Node instances can be compared to each other and/or HTMLElements.
       
   508      * @method compareTo
       
   509      * @param {HTMLElement | Node} refNode The reference node to compare to the node.
       
   510      * @return {Boolean} True if the nodes match, false if they do not. 
       
   511      */
       
   512     compareTo: function(refNode) {
       
   513         var node = this._node;
       
   514         if (refNode instanceof Y.Node) { 
       
   515             refNode = refNode._node;
       
   516         }
       
   517         return node === refNode;
       
   518     },
       
   519 
       
   520     /**
       
   521      * Determines whether the node is appended to the document.
       
   522      * @method inDoc
       
   523      * @param {Node|HTMLElement} doc optional An optional document to check against.
       
   524      * Defaults to current document. 
       
   525      * @return {Boolean} Whether or not this node is appended to the document. 
       
   526      */
       
   527     inDoc: function(doc) {
       
   528         var node = this._node;
       
   529         doc = (doc) ? doc._node || doc : node[OWNER_DOCUMENT];
       
   530         if (doc.documentElement) {
       
   531             return Y.DOM.contains(doc.documentElement, node);
       
   532         }
       
   533     },
       
   534 
       
   535     getById: function(id) {
       
   536         var node = this._node,
       
   537             ret = Y.DOM.byId(id, node[OWNER_DOCUMENT]);
       
   538         if (ret && Y.DOM.contains(node, ret)) {
       
   539             ret = Y.one(ret);
       
   540         } else {
       
   541             ret = null;
       
   542         }
       
   543         return ret;
       
   544     },
       
   545 
       
   546    /**
       
   547      * Returns the nearest ancestor that passes the test applied by supplied boolean method.
       
   548      * @method ancestor
       
   549      * @param {String | Function} fn A selector string or boolean method for testing elements.
       
   550      * If a function is used, it receives the current node being tested as the only argument.
       
   551      * @return {Node} The matching Node instance or null if not found
       
   552      */
       
   553     ancestor: function(fn) {
       
   554         return Node.get(Y.DOM.elementByAxis(this._node, 'parentNode', _wrapFn(fn)));
       
   555     },
       
   556 
       
   557     /**
       
   558      * Returns the previous matching sibling. 
       
   559      * Returns the nearest element node sibling if no method provided.
       
   560      * @method previous
       
   561      * @param {String | Function} fn A selector or boolean method for testing elements.
       
   562      * If a function is used, it receives the current node being tested as the only argument.
       
   563      * @return {Node} Node instance or null if not found
       
   564      */
       
   565     previous: function(fn, all) {
       
   566         return Node.get(Y.DOM.elementByAxis(this._node, 'previousSibling', _wrapFn(fn), all));
       
   567     }, 
       
   568 
       
   569     /**
       
   570      * Returns the next matching sibling. 
       
   571      * Returns the nearest element node sibling if no method provided.
       
   572      * @method next
       
   573      * @param {String | Function} fn A selector or boolean method for testing elements.
       
   574      * If a function is used, it receives the current node being tested as the only argument.
       
   575      * @return {Node} Node instance or null if not found
       
   576      */
       
   577     next: function(node, fn, all) {
       
   578         return Node.get(Y.DOM.elementByAxis(this._node, 'nextSibling', _wrapFn(fn), all));
       
   579     },
       
   580         
       
   581     /**
       
   582      * Retrieves a Node instance of nodes based on the given CSS selector. 
       
   583      * @method one
       
   584      *
       
   585      * @param {string} selector The CSS selector to test against.
       
   586      * @return {Node} A Node instance for the matching HTMLElement.
       
   587      */
       
   588     one: function(selector) {
       
   589         return Y.one(Y.Selector.query(selector, this._node, true));
       
   590     },
       
   591 
       
   592     /**
       
   593      * Retrieves a Node instance of nodes based on the given CSS selector. 
       
   594      * @method query
       
   595      * @deprecated Use one()
       
   596      * @param {string} selector The CSS selector to test against.
       
   597      * @return {Node} A Node instance for the matching HTMLElement.
       
   598      */
       
   599     query: function(selector) {
       
   600         return this.one(selector);
       
   601     },
       
   602 
       
   603     /**
       
   604      * Retrieves a nodeList based on the given CSS selector. 
       
   605      * @method all
       
   606      *
       
   607      * @param {string} selector The CSS selector to test against.
       
   608      * @return {NodeList} A NodeList instance for the matching HTMLCollection/Array.
       
   609      */
       
   610     all: function(selector) {
       
   611         var nodelist = Y.all(Y.Selector.query(selector, this._node));
       
   612         nodelist._query = selector;
       
   613         return nodelist;
       
   614     },
       
   615 
       
   616     /**
       
   617      * Retrieves a nodeList based on the given CSS selector. 
       
   618      * @method queryAll
       
   619      * @deprecated Use all()
       
   620      * @param {string} selector The CSS selector to test against.
       
   621      * @return {NodeList} A NodeList instance for the matching HTMLCollection/Array.
       
   622      */
       
   623     queryAll: function(selector) {
       
   624         return this.all(selector);
       
   625     },
       
   626 
       
   627     // TODO: allow fn test
       
   628     /**
       
   629      * Test if the supplied node matches the supplied selector.
       
   630      * @method test
       
   631      *
       
   632      * @param {string} selector The CSS selector to test against.
       
   633      * @return {boolean} Whether or not the node matches the selector.
       
   634      */
       
   635     test: function(selector) {
       
   636         return Y.Selector.test(this._node, selector);
       
   637     },
       
   638 
       
   639     /**
       
   640      * Removes the node from its parent.
       
   641      * Shortcut for myNode.get('parentNode').removeChild(myNode);
       
   642      * @method remove
       
   643      * @chainable
       
   644      *
       
   645      */
       
   646     remove: function(destroy) {
       
   647         var node = this._node;
       
   648         node.parentNode.removeChild(node);
       
   649         if (destroy) {
       
   650             this.destroy(true);
       
   651         }
       
   652         return this;
       
   653     },
       
   654 
       
   655     /**
       
   656      * Replace the node with the other node. This is a DOM update only
       
   657      * and does not change the node bound to the Node instance.
       
   658      * Shortcut for myNode.get('parentNode').replaceChild(newNode, myNode);
       
   659      * @method replace
       
   660      * @chainable
       
   661      *
       
   662      */
       
   663     replace: function(newNode) {
       
   664         var node = this._node;
       
   665         node.parentNode.replaceChild(newNode, node);
       
   666         return this;
       
   667     },
       
   668 
       
   669     purge: function(recurse, type) {
       
   670         Y.Event.purgeElement(this._node, recurse, type);
       
   671     },
       
   672 
       
   673     destroy: function(purge) {
       
   674         delete Node._instances[this[UID]];
       
   675         if (purge) {
       
   676             this.purge(true);
       
   677         }
       
   678 
       
   679         if (this.unplug) {
       
   680             this.unplug();
       
   681         }
       
   682 
       
   683         this._node._yuid = null;
       
   684         this._node = null;
       
   685         this._stateProxy = null;
       
   686     },
       
   687 
       
   688     /**
       
   689      * Invokes a method on the Node instance 
       
   690      * @method invoke
       
   691      * @param {String} method The name of the method to invoke
       
   692      * @param {Any}  a, b, c, etc. Arguments to invoke the method with. 
       
   693      * @return Whatever the underly method returns. 
       
   694      * DOM Nodes and Collections return values
       
   695      * are converted to Node/NodeList instances.
       
   696      *
       
   697      */
       
   698     invoke: function(method, a, b, c, d, e) {
       
   699         var node = this._node,
       
   700             ret;
       
   701 
       
   702         if (a && a instanceof Y.Node) {
       
   703             a = a._node;
       
   704         }
       
   705 
       
   706         if (b && b instanceof Y.Node) {
       
   707             b = b._node;
       
   708         }
       
   709 
       
   710         ret = node[method](a, b, c, d, e);    
       
   711         return Y.Node.scrubVal(ret, this);
       
   712     },
       
   713 
       
   714     /**
       
   715      * Applies the given function to each Node in the NodeList.
       
   716      * @method each
       
   717      * @deprecated Use NodeList
       
   718      * @param {Function} fn The function to apply 
       
   719      * @param {Object} context optional An optional context to apply the function with
       
   720      * Default context is the NodeList instance
       
   721      * @chainable
       
   722      */
       
   723     each: function(fn, context) {
       
   724         context = context || this;
       
   725         return fn.call(context, this);
       
   726     },
       
   727 
       
   728     /**
       
   729      * Retrieves the Node instance at the given index. 
       
   730      * @method item
       
   731      * @deprecated Use NodeList
       
   732      *
       
   733      * @param {Number} index The index of the target Node.
       
   734      * @return {Node} The Node instance at the given index.
       
   735      */
       
   736     item: function(index) {
       
   737         return this;
       
   738     },
       
   739 
       
   740     /**
       
   741      * Returns the current number of items in the Node.
       
   742      * @method size
       
   743      * @deprecated Use NodeList
       
   744      * @return {Int} The number of items in the Node. 
       
   745      */
       
   746     size: function() {
       
   747         return this._node ? 1 : 0;
       
   748     },
       
   749 
       
   750     /**
       
   751      * Inserts the content before the reference node. 
       
   752      * @method insert
       
   753      * @param {String | Y.Node | HTMLElement} content The content to insert 
       
   754      * @param {Int | Y.Node | HTMLElement | String} where The position to insert at.
       
   755      * @chainable
       
   756      */
       
   757     insert: function(content, where) {
       
   758         var node = this._node;
       
   759 
       
   760         if (content) {
       
   761             if (typeof where === 'number') { // allow index
       
   762                 where = this._node.childNodes[where];
       
   763             }
       
   764 
       
   765             if (typeof content !== 'string') { // allow Node or NodeList/Array instances
       
   766                 if (content._node) { // Node
       
   767                     content = content._node;
       
   768                 } else if (content._nodes || (!content.nodeType && content.length)) { // NodeList or Array
       
   769                     Y.each(content._nodes, function(n) {
       
   770                         Y.DOM.addHTML(node, n, where);
       
   771                     });
       
   772 
       
   773                     return this; // NOTE: early return
       
   774                 }
       
   775             }
       
   776             Y.DOM.addHTML(node, content, where);
       
   777         }
       
   778         return this;
       
   779     },
       
   780 
       
   781     /**
       
   782      * Inserts the content as the firstChild of the node. 
       
   783      * @method prepend
       
   784      * @param {String | Y.Node | HTMLElement} content The content to insert 
       
   785      * @chainable
       
   786      */
       
   787     prepend: function(content) {
       
   788         return this.insert(content, 0);
       
   789     },
       
   790 
       
   791     /**
       
   792      * Inserts the content as the lastChild of the node. 
       
   793      * @method append
       
   794      * @param {String | Y.Node | HTMLElement} content The content to insert 
       
   795      * @chainable
       
   796      */
       
   797     append: function(content) {
       
   798         return this.insert(content, null);
       
   799     },
       
   800 
       
   801     /**
       
   802      * Replaces the node's current content with the content.
       
   803      * @method setContent
       
   804      * @param {String | Y.Node | HTMLElement} content The content to insert 
       
   805      * @chainable
       
   806      */
       
   807     setContent: function(content) {
       
   808         Y.DOM.addHTML(this._node, content, 'replace');
       
   809         return this;
       
   810     },
       
   811 
       
   812     // TODO: need this?
       
   813     hasMethod: function(method) {
       
   814         var node = this._node;
       
   815         return (node && (typeof node === 'function'));
       
   816     }
       
   817 }, true);
       
   818 
       
   819 Y.Node = Node;
       
   820 Y.get = Y.Node.get;
       
   821 Y.one = Y.Node.one;
       
   822 /**
       
   823  * The NodeList module provides support for managing collections of Nodes.
       
   824  * @module node
       
   825  * @submodule nodelist
       
   826  */    
       
   827 
       
   828 /**
       
   829  * The NodeList class provides a wrapper for manipulating DOM NodeLists.
       
   830  * NodeList properties can be accessed via the set/get methods.
       
   831  * Use Y.all() to retrieve NodeList instances.
       
   832  *
       
   833  * @class NodeList
       
   834  * @constructor
       
   835  */
       
   836 
       
   837 var NodeList = function(nodes) {
       
   838     if (typeof nodes === 'string') {
       
   839         this._query = nodes;
       
   840         nodes = Y.Selector.query(nodes);
       
   841     } else {
       
   842         nodes = Y.Array(nodes, 0, true);
       
   843     }
       
   844 
       
   845     NodeList._instances[Y.stamp(this)] = this;
       
   846     this._nodes = nodes;
       
   847 };
       
   848 // end "globals"
       
   849 
       
   850 NodeList.NAME = 'NodeList';
       
   851 
       
   852 /**
       
   853  * Retrieves the DOM nodes bound to a NodeList instance
       
   854  * @method NodeList.getDOMNodes
       
   855  * @static
       
   856  *
       
   857  * @param {Y.NodeList} node The NodeList instance
       
   858  * @return {Array} The array of DOM nodes bound to the NodeList
       
   859  */
       
   860 NodeList.getDOMNodes = function(nodeList) {
       
   861     return nodeList._nodes;
       
   862 };
       
   863 
       
   864 NodeList._instances = [];
       
   865 
       
   866 NodeList.each = function(instance, fn, context) {
       
   867     var nodes = instance._nodes;
       
   868     if (nodes && nodes.length) {
       
   869         Y.Array.each(nodes, fn, context || instance);
       
   870     } else {
       
   871     }
       
   872 };
       
   873 
       
   874 NodeList.addMethod = function(name, fn, context) {
       
   875     if (name && fn) {
       
   876         NodeList.prototype[name] = function() {
       
   877             var ret = [],
       
   878                 args = arguments;
       
   879 
       
   880             Y.Array.each(this._nodes, function(node) {
       
   881                 var UID = '_yuid',
       
   882                     instance = Y.Node._instances[node[UID]],
       
   883                     ctx,
       
   884                     result;
       
   885 
       
   886                 if (!instance) {
       
   887                     instance = NodeList._getTempNode(node);
       
   888                 }
       
   889                 ctx = context || instance;
       
   890                 result = fn.apply(ctx, args);
       
   891                 if (result !== undefined && result !== instance) {
       
   892                     ret[ret.length] = result;
       
   893                 }
       
   894             });
       
   895 
       
   896             // TODO: remove tmp pointer
       
   897             return ret.length ? ret : this;
       
   898         };
       
   899     } else {
       
   900     }
       
   901 };
       
   902 
       
   903 NodeList.importMethod = function(host, name, altName) {
       
   904     if (typeof name === 'string') {
       
   905         altName = altName || name;
       
   906         NodeList.addMethod(name, host[name]);
       
   907     } else {
       
   908         Y.each(name, function(n) {
       
   909             NodeList.importMethod(host, n);
       
   910         });
       
   911     }
       
   912 };
       
   913 
       
   914 NodeList._getTempNode = function(node) {
       
   915     var tmp = NodeList._tempNode;
       
   916     if (!tmp) {
       
   917         tmp = Y.Node.create('<div></div>');
       
   918         NodeList._tempNode = tmp;
       
   919     }
       
   920 
       
   921     tmp._node = node;
       
   922     tmp._stateProxy = node;
       
   923     return tmp;
       
   924 };
       
   925 
       
   926 Y.mix(NodeList.prototype, {
       
   927     /**
       
   928      * Retrieves the Node instance at the given index. 
       
   929      * @method item
       
   930      *
       
   931      * @param {Number} index The index of the target Node.
       
   932      * @return {Node} The Node instance at the given index.
       
   933      */
       
   934     item: function(index) {
       
   935         return Y.one((this._nodes || [])[index]);
       
   936     },
       
   937 
       
   938     /**
       
   939      * Applies the given function to each Node in the NodeList.
       
   940      * @method each
       
   941      * @param {Function} fn The function to apply. It receives 3 arguments:
       
   942      * the current node instance, the node's index, and the NodeList instance
       
   943      * @param {Object} context optional An optional context to apply the function with
       
   944      * Default context is the current Node instance
       
   945      * @chainable
       
   946      */
       
   947     each: function(fn, context) {
       
   948         var instance = this;
       
   949         Y.Array.each(this._nodes, function(node, index) {
       
   950             node = Y.one(node);
       
   951             return fn.call(context || node, node, index, instance);
       
   952         });
       
   953         return instance;
       
   954     },
       
   955 
       
   956     batch: function(fn, context) {
       
   957         var nodelist = this;
       
   958 
       
   959         Y.Array.each(this._nodes, function(node, index) {
       
   960             var instance = Y.Node._instances[node[UID]];
       
   961             if (!instance) {
       
   962                 instance = NodeList._getTempNode(node);
       
   963             }
       
   964 
       
   965             return fn.call(context || instance, instance, index, nodelist);
       
   966         });
       
   967         return nodelist;
       
   968     },
       
   969 
       
   970     /**
       
   971      * Executes the function once for each node until a true value is returned.
       
   972      * @method some
       
   973      * @param {Function} fn The function to apply. It receives 3 arguments:
       
   974      * the current node instance, the node's index, and the NodeList instance
       
   975      * @param {Object} context optional An optional context to execute the function from.
       
   976      * Default context is the current Node instance
       
   977      * @return {Boolean} Whether or not the function returned true for any node.
       
   978      */
       
   979     some: function(fn, context) {
       
   980         var instance = this;
       
   981         return Y.Array.some(this._nodes, function(node, index) {
       
   982             node = Y.one(node);
       
   983             context = context || node;
       
   984             return fn.call(context, node, index, instance);
       
   985         });
       
   986     },
       
   987 
       
   988     /**
       
   989      * Creates a documenFragment from the nodes bound to the NodeList instance 
       
   990      * @method toDocFrag
       
   991      * @return Node a Node instance bound to the documentFragment
       
   992      */
       
   993     toFrag: function() {
       
   994         return Y.one(Y.DOM._nl2frag(this._nodes));
       
   995     },
       
   996 
       
   997     /**
       
   998      * Returns the index of the node in the NodeList instance
       
   999      * or -1 if the node isn't found.
       
  1000      * @method indexOf
       
  1001      * @param {Y.Node || DOMNode} node the node to search for
       
  1002      * @return {Int} the index of the node value or -1 if not found
       
  1003      */
       
  1004     indexOf: function(node) {
       
  1005         return Y.Array.indexOf(this._nodes, Y.Node.getDOMNode(node));
       
  1006     },
       
  1007 
       
  1008     /**
       
  1009      * Filters the NodeList instance down to only nodes matching the given selector.
       
  1010      * @method filter
       
  1011      * @param {String} selector The selector to filter against
       
  1012      * @return {NodeList} NodeList containing the updated collection 
       
  1013      * @see Selector
       
  1014      */
       
  1015     filter: function(selector) {
       
  1016         return Y.all(Y.Selector.filter(this._nodes, selector));
       
  1017     },
       
  1018 
       
  1019 
       
  1020     /**
       
  1021      * Creates a new NodeList containing all nodes at every n indices, where 
       
  1022      * remainder n % index equals r.
       
  1023      * (zero-based index).
       
  1024      * @method modulus
       
  1025      * @param {Int} n The offset to use (return every nth node)
       
  1026      * @param {Int} r An optional remainder to use with the modulus operation (defaults to zero) 
       
  1027      * @return {NodeList} NodeList containing the updated collection 
       
  1028      */
       
  1029     modulus: function(n, r) {
       
  1030         r = r || 0;
       
  1031         var nodes = [];
       
  1032         NodeList.each(this, function(node, i) {
       
  1033             if (i % n === r) {
       
  1034                 nodes.push(node);
       
  1035             }
       
  1036         });
       
  1037 
       
  1038         return Y.all(nodes);
       
  1039     },
       
  1040 
       
  1041     /**
       
  1042      * Creates a new NodeList containing all nodes at odd indices
       
  1043      * (zero-based index).
       
  1044      * @method odd
       
  1045      * @return {NodeList} NodeList containing the updated collection 
       
  1046      */
       
  1047     odd: function() {
       
  1048         return this.modulus(2, 1);
       
  1049     },
       
  1050 
       
  1051     /**
       
  1052      * Creates a new NodeList containing all nodes at even indices
       
  1053      * (zero-based index), including zero. 
       
  1054      * @method even
       
  1055      * @return {NodeList} NodeList containing the updated collection 
       
  1056      */
       
  1057     even: function() {
       
  1058         return this.modulus(2);
       
  1059     },
       
  1060 
       
  1061     destructor: function() {
       
  1062         delete NodeList._instances[this[UID]];
       
  1063     },
       
  1064 
       
  1065     /**
       
  1066      * Reruns the initial query, when created using a selector query 
       
  1067      * @method refresh
       
  1068      * @chainable
       
  1069      */
       
  1070     refresh: function() {
       
  1071         var doc,
       
  1072             nodes = this._nodes;
       
  1073         if (this._query) {
       
  1074             if (nodes && nodes[0] && nodes[0].ownerDocument) {
       
  1075                 doc = nodes[0].ownerDocument;
       
  1076             }
       
  1077 
       
  1078             this._nodes = Y.Selector.query(this._query, doc || Y.config.doc);        
       
  1079         }
       
  1080 
       
  1081         return this;
       
  1082     },
       
  1083 
       
  1084     /**
       
  1085      * Applies an event listener to each Node bound to the NodeList. 
       
  1086      * @method on
       
  1087      * @param {String} type The event being listened for
       
  1088      * @param {Function} fn The handler to call when the event fires
       
  1089      * @param {Object} context The context to call the handler with.
       
  1090      * Default is the NodeList instance. 
       
  1091      * @return {Object} Returns an event handle that can later be use to detach(). 
       
  1092      * @see Event.on
       
  1093      */
       
  1094     on: function(type, fn, context) {
       
  1095         var args = Y.Array(arguments, 0, true);
       
  1096         args.splice(2, 0, this._nodes);
       
  1097         args[3] = context || this;
       
  1098         return Y.on.apply(Y, args);
       
  1099     },
       
  1100 
       
  1101     /**
       
  1102      * Applies an event listener to each Node bound to the NodeList. 
       
  1103      * The handler is called only after all on() handlers are called
       
  1104      * and the event is not prevented.
       
  1105      * @method after
       
  1106      * @param {String} type The event being listened for
       
  1107      * @param {Function} fn The handler to call when the event fires
       
  1108      * @param {Object} context The context to call the handler with.
       
  1109      * Default is the NodeList instance. 
       
  1110      * @return {Object} Returns an event handle that can later be use to detach(). 
       
  1111      * @see Event.on
       
  1112      */
       
  1113     after: function(type, fn, context) {
       
  1114         var args = Y.Array(arguments, 0, true);
       
  1115         args.splice(2, 0, this._nodes);
       
  1116         args[3] = context || this;
       
  1117         return Y.after.apply(Y, args);
       
  1118     },
       
  1119 
       
  1120     /**
       
  1121      * Returns the current number of items in the NodeList.
       
  1122      * @method size
       
  1123      * @return {Int} The number of items in the NodeList. 
       
  1124      */
       
  1125     size: function() {
       
  1126         return this._nodes.length;
       
  1127     },
       
  1128 
       
  1129     toString: function() {
       
  1130         var str = '',
       
  1131             errorMsg = this[UID] + ': not bound to any nodes',
       
  1132             nodes = this._nodes,
       
  1133             node;
       
  1134 
       
  1135         if (nodes && nodes[0]) {
       
  1136             node = nodes[0];
       
  1137             str += node[NODE_NAME];
       
  1138             if (node.id) {
       
  1139                 str += '#' + node.id; 
       
  1140             }
       
  1141 
       
  1142             if (node.className) {
       
  1143                 str += '.' + node.className.replace(' ', '.'); 
       
  1144             }
       
  1145 
       
  1146             if (nodes.length > 1) {
       
  1147                 str += '...[' + nodes.length + ' items]';
       
  1148             }
       
  1149         }
       
  1150         return str || errorMsg;
       
  1151     }
       
  1152 
       
  1153 }, true);
       
  1154 
       
  1155 NodeList.importMethod(Y.Node.prototype, [
       
  1156     /**
       
  1157      * Called on each Node instance
       
  1158      * @for NodeList
       
  1159      * @method append
       
  1160      * @see Node.append
       
  1161      */
       
  1162     'append',
       
  1163 
       
  1164     /**
       
  1165       * Called on each Node instance
       
  1166       * @method detach
       
  1167       * @see Node.detach
       
  1168       */
       
  1169     'detach',
       
  1170     
       
  1171     /** Called on each Node instance
       
  1172       * @method detachAll
       
  1173       * @see Node.detachAll
       
  1174       */
       
  1175     'detachAll',
       
  1176 
       
  1177     /** Called on each Node instance
       
  1178       * @method insert
       
  1179       * @see NodeInsert
       
  1180       */
       
  1181     'insert',
       
  1182 
       
  1183     /** Called on each Node instance
       
  1184       * @method prepend
       
  1185       * @see Node.prepend
       
  1186       */
       
  1187     'prepend',
       
  1188 
       
  1189     /** Called on each Node instance
       
  1190       * @method remove
       
  1191       * @see Node.remove
       
  1192       */
       
  1193     'remove',
       
  1194 
       
  1195     /** Called on each Node instance
       
  1196       * @method set
       
  1197       * @see Node.set
       
  1198       */
       
  1199     'set',
       
  1200 
       
  1201     /** Called on each Node instance
       
  1202       * @method setContent
       
  1203       * @see Node.setContent
       
  1204       */
       
  1205     'setContent'
       
  1206 ]);
       
  1207 
       
  1208 // one-off implementation to convert array of Nodes to NodeList
       
  1209 // e.g. Y.all('input').get('parentNode');
       
  1210 
       
  1211 /** Called on each Node instance
       
  1212   * @method get
       
  1213   * @see Node
       
  1214   */
       
  1215 NodeList.prototype.get = function(attr) {
       
  1216     var ret = [],
       
  1217         nodes = this._nodes,
       
  1218         isNodeList = false,
       
  1219         getTemp = NodeList._getTempNode,
       
  1220         instance,
       
  1221         val;
       
  1222 
       
  1223     if (nodes[0]) {
       
  1224         instance = Y.Node._instances[nodes[0]._yuid] || getTemp(nodes[0]);
       
  1225         val = instance._get(attr);
       
  1226         if (val && val.nodeType) {
       
  1227             isNodeList = true;
       
  1228         }
       
  1229     }
       
  1230 
       
  1231     Y.Array.each(nodes, function(node) {
       
  1232         instance = Y.Node._instances[node._yuid];
       
  1233 
       
  1234         if (!instance) {
       
  1235             instance = getTemp(node);
       
  1236         }
       
  1237 
       
  1238         val = instance._get(attr);
       
  1239         if (!isNodeList) { // convert array of Nodes to NodeList
       
  1240             val = Y.Node.scrubVal(val, instance);
       
  1241         }
       
  1242 
       
  1243         ret.push(val);
       
  1244     });
       
  1245 
       
  1246     return (isNodeList) ? Y.all(ret) : ret;
       
  1247 };
       
  1248 
       
  1249 Y.NodeList = NodeList;
       
  1250 
       
  1251 Y.all = function(nodes) {
       
  1252     return new NodeList(nodes);
       
  1253 };
       
  1254 
       
  1255 Y.Node.all = Y.all;
       
  1256 Y.Array.each([
       
  1257     /**
       
  1258      * Passes through to DOM method.
       
  1259      * @method replaceChild
       
  1260      * @for Node
       
  1261      * @param {HTMLElement | Node} node Node to be inserted 
       
  1262      * @param {HTMLElement | Node} refNode Node to be replaced 
       
  1263      * @return {Node} The replaced node 
       
  1264      */
       
  1265     'replaceChild',
       
  1266 
       
  1267     /**
       
  1268      * Passes through to DOM method.
       
  1269      * @method appendChild
       
  1270      * @param {HTMLElement | Node} node Node to be appended 
       
  1271      * @return {Node} The appended node 
       
  1272      */
       
  1273     'appendChild',
       
  1274 
       
  1275     /**
       
  1276      * Passes through to DOM method.
       
  1277      * @method insertBefore
       
  1278      * @param {HTMLElement | Node} newNode Node to be appended 
       
  1279      * @param {HTMLElement | Node} refNode Node to be inserted before 
       
  1280      * @return {Node} The inserted node 
       
  1281      */
       
  1282     'insertBefore',
       
  1283 
       
  1284     /**
       
  1285      * Passes through to DOM method.
       
  1286      * @method removeChild
       
  1287      * @param {HTMLElement | Node} node Node to be removed 
       
  1288      * @return {Node} The removed node 
       
  1289      */
       
  1290     'removeChild',
       
  1291 
       
  1292     /**
       
  1293      * Passes through to DOM method.
       
  1294      * @method hasChildNodes
       
  1295      * @return {Boolean} Whether or not the node has any childNodes 
       
  1296      */
       
  1297     'hasChildNodes',
       
  1298 
       
  1299     /**
       
  1300      * Passes through to DOM method.
       
  1301      * @method cloneNode
       
  1302      * @param {Boolean} deep Whether or not to perform a deep clone, which includes
       
  1303      * subtree and attributes
       
  1304      * @return {Node} The clone 
       
  1305      */
       
  1306     'cloneNode',
       
  1307 
       
  1308     /**
       
  1309      * Passes through to DOM method.
       
  1310      * @method hasAttribute
       
  1311      * @param {String} attribute The attribute to test for 
       
  1312      * @return {Boolean} Whether or not the attribute is present 
       
  1313      */
       
  1314     'hasAttribute',
       
  1315 
       
  1316     /**
       
  1317      * Passes through to DOM method.
       
  1318      * @method removeAttribute
       
  1319      * @param {String} attribute The attribute to be removed 
       
  1320      * @chainable
       
  1321      */
       
  1322     'removeAttribute',
       
  1323 
       
  1324     /**
       
  1325      * Passes through to DOM method.
       
  1326      * @method scrollIntoView
       
  1327      * @chainable
       
  1328      */
       
  1329     'scrollIntoView',
       
  1330 
       
  1331     /**
       
  1332      * Passes through to DOM method.
       
  1333      * @method getElementsByTagName
       
  1334      * @param {String} tagName The tagName to collect 
       
  1335      * @return {NodeList} A NodeList representing the HTMLCollection
       
  1336      */
       
  1337     'getElementsByTagName',
       
  1338 
       
  1339     /**
       
  1340      * Passes through to DOM method.
       
  1341      * @method focus
       
  1342      * @chainable
       
  1343      */
       
  1344     'focus',
       
  1345 
       
  1346     /**
       
  1347      * Passes through to DOM method.
       
  1348      * @method blur
       
  1349      * @chainable
       
  1350      */
       
  1351     'blur',
       
  1352 
       
  1353     /**
       
  1354      * Passes through to DOM method.
       
  1355      * Only valid on FORM elements
       
  1356      * @method submit
       
  1357      * @chainable
       
  1358      */
       
  1359     'submit',
       
  1360 
       
  1361     /**
       
  1362      * Passes through to DOM method.
       
  1363      * Only valid on FORM elements
       
  1364      * @method reset
       
  1365      * @chainable
       
  1366      */
       
  1367     'reset',
       
  1368 
       
  1369     /**
       
  1370      * Passes through to DOM method.
       
  1371      * @method select
       
  1372      * @chainable
       
  1373      */
       
  1374      'select'
       
  1375 ], function(method) {
       
  1376     Y.Node.prototype[method] = function(arg1, arg2, arg3) {
       
  1377         var ret = this.invoke(method, arg1, arg2, arg3);
       
  1378         return ret;
       
  1379     };
       
  1380 });
       
  1381 
       
  1382 Node.importMethod(Y.DOM, [
       
  1383     /**
       
  1384      * Determines whether the ndoe is an ancestor of another HTML element in the DOM hierarchy.
       
  1385      * @method contains
       
  1386      * @param {Node | HTMLElement} needle The possible node or descendent
       
  1387      * @return {Boolean} Whether or not this node is the needle its ancestor
       
  1388      */
       
  1389     'contains',
       
  1390     /**
       
  1391      * Allows setting attributes on DOM nodes, normalizing in some cases.
       
  1392      * This passes through to the DOM node, allowing for custom attributes.
       
  1393      * @method setAttribute
       
  1394      * @for Node
       
  1395      * @for NodeList
       
  1396      * @chainable
       
  1397      * @param {string} name The attribute name 
       
  1398      * @param {string} value The value to set
       
  1399      */
       
  1400     'setAttribute',
       
  1401     /**
       
  1402      * Allows getting attributes on DOM nodes, normalizing in some cases.
       
  1403      * This passes through to the DOM node, allowing for custom attributes.
       
  1404      * @method getAttribute
       
  1405      * @for Node
       
  1406      * @for NodeList
       
  1407      * @param {string} name The attribute name 
       
  1408      * @return {string} The attribute value 
       
  1409      */
       
  1410     'getAttribute'
       
  1411 ]);
       
  1412 
       
  1413 /**
       
  1414  * Allows setting attributes on DOM nodes, normalizing in some cases.
       
  1415  * This passes through to the DOM node, allowing for custom attributes.
       
  1416  * @method setAttribute
       
  1417  * @see Node
       
  1418  * @for NodeList
       
  1419  * @chainable
       
  1420  * @param {string} name The attribute name 
       
  1421  * @param {string} value The value to set
       
  1422  */
       
  1423 
       
  1424 /**
       
  1425  * Allows getting attributes on DOM nodes, normalizing in some cases.
       
  1426  * This passes through to the DOM node, allowing for custom attributes.
       
  1427  * @method getAttribute
       
  1428  * @see Node
       
  1429  * @for NodeList
       
  1430  * @param {string} name The attribute name 
       
  1431  * @return {string} The attribute value 
       
  1432  */
       
  1433 Y.NodeList.importMethod(Y.Node.prototype, ['getAttribute', 'setAttribute']);
       
  1434 (function(Y) {
       
  1435     var methods = [
       
  1436     /**
       
  1437      * Determines whether each node has the given className.
       
  1438      * @method hasClass
       
  1439      * @for Node
       
  1440      * @param {String} className the class name to search for
       
  1441      * @return {Array} An array of booleans for each node bound to the NodeList. 
       
  1442      */
       
  1443      'hasClass',
       
  1444 
       
  1445     /**
       
  1446      * Adds a class name to each node.
       
  1447      * @method addClass         
       
  1448      * @param {String} className the class name to add to the node's class attribute
       
  1449      * @chainable
       
  1450      */
       
  1451      'addClass',
       
  1452 
       
  1453     /**
       
  1454      * Removes a class name from each node.
       
  1455      * @method removeClass         
       
  1456      * @param {String} className the class name to remove from the node's class attribute
       
  1457      * @chainable
       
  1458      */
       
  1459      'removeClass',
       
  1460 
       
  1461     /**
       
  1462      * Replace a class with another class for each node.
       
  1463      * If no oldClassName is present, the newClassName is simply added.
       
  1464      * @method replaceClass  
       
  1465      * @param {String} oldClassName the class name to be replaced
       
  1466      * @param {String} newClassName the class name that will be replacing the old class name
       
  1467      * @chainable
       
  1468      */
       
  1469      'replaceClass',
       
  1470 
       
  1471     /**
       
  1472      * If the className exists on the node it is removed, if it doesn't exist it is added.
       
  1473      * @method toggleClass  
       
  1474      * @param {String} className the class name to be toggled
       
  1475      * @chainable
       
  1476      */
       
  1477      'toggleClass'
       
  1478     ];
       
  1479 
       
  1480     Y.Node.importMethod(Y.DOM, methods);
       
  1481     /**
       
  1482      * Determines whether each node has the given className.
       
  1483      * @method hasClass
       
  1484      * @see Node.hasClass
       
  1485      * @for NodeList
       
  1486      * @param {String} className the class name to search for
       
  1487      * @return {Array} An array of booleans for each node bound to the NodeList. 
       
  1488      */
       
  1489 
       
  1490     /**
       
  1491      * Adds a class name to each node.
       
  1492      * @method addClass         
       
  1493      * @see Node.addClass
       
  1494      * @param {String} className the class name to add to the node's class attribute
       
  1495      * @chainable
       
  1496      */
       
  1497 
       
  1498     /**
       
  1499      * Removes a class name from each node.
       
  1500      * @method removeClass         
       
  1501      * @see Node.removeClass
       
  1502      * @param {String} className the class name to remove from the node's class attribute
       
  1503      * @chainable
       
  1504      */
       
  1505 
       
  1506     /**
       
  1507      * Replace a class with another class for each node.
       
  1508      * If no oldClassName is present, the newClassName is simply added.
       
  1509      * @method replaceClass  
       
  1510      * @see Node.replaceClass
       
  1511      * @param {String} oldClassName the class name to be replaced
       
  1512      * @param {String} newClassName the class name that will be replacing the old class name
       
  1513      * @chainable
       
  1514      */
       
  1515 
       
  1516     /**
       
  1517      * If the className exists on the node it is removed, if it doesn't exist it is added.
       
  1518      * @method toggleClass  
       
  1519      * @see Node.toggleClass
       
  1520      * @param {String} className the class name to be toggled
       
  1521      * @chainable
       
  1522      */
       
  1523     Y.NodeList.importMethod(Y.Node.prototype, methods);
       
  1524 })(Y);
       
  1525 
       
  1526 if (!document.documentElement.hasAttribute) { // IE < 8
       
  1527     Y.Node.prototype.hasAttribute = function(attr) {
       
  1528         return Y.DOM.getAttribute(this._node, attr) !== '';
       
  1529     };
       
  1530 }
       
  1531 
       
  1532 // IE throws error when setting input.type = 'hidden',
       
  1533 // input.setAttribute('type', 'hidden') and input.attributes.type.value = 'hidden'
       
  1534 Y.Node.ATTRS.type = {
       
  1535     setter: function(val) {
       
  1536         if (val === 'hidden') {
       
  1537             try {
       
  1538                 this._node.type = 'hidden';
       
  1539             } catch(e) {
       
  1540                 this.setStyle('display', 'none');
       
  1541                 this._inputType = 'hidden';
       
  1542             }
       
  1543         } else {
       
  1544             try { // IE errors when changing the type from "hidden'
       
  1545                 this._node.type = val;
       
  1546             } catch (e) {
       
  1547             }
       
  1548         }
       
  1549         return val;
       
  1550     },
       
  1551 
       
  1552     getter: function() {
       
  1553         return this._inputType || this._node.type;
       
  1554     },
       
  1555 
       
  1556     _bypassProxy: true // don't update DOM when using with Attribute
       
  1557 };
       
  1558 
       
  1559 
       
  1560 }, '3.0.0' ,{requires:['dom-base', 'selector-css2', 'event-base']});