src/cm/media/js/lib/yui/yui3.0.0/build/node/node-debug.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         Y.log('unable to add method: ' + name, 'warn', 'Node');
       
   184     }
       
   185 };
       
   186 
       
   187 Node.importMethod = function(host, name, altName) {
       
   188     if (typeof name === 'string') {
       
   189         altName = altName || name;
       
   190         Node.addMethod(altName, host[name], host);
       
   191     } else {
       
   192         Y.each(name, function(n) {
       
   193             Node.importMethod(host, n);
       
   194         });
       
   195     }
       
   196 };
       
   197 
       
   198 /**
       
   199  * Returns a single Node instance bound to the node or the
       
   200  * first element matching the given selector.
       
   201  * @method Y.one
       
   202  * @static
       
   203  * @param {String | HTMLElement} node a node or Selector 
       
   204  * @param {Y.Node || HTMLElement} doc an optional document to scan. Defaults to Y.config.doc. 
       
   205  */
       
   206 Node.one = function(node) {
       
   207     var instance = null,
       
   208         cachedNode,
       
   209         uid;
       
   210 
       
   211     if (node) {
       
   212         if (typeof node === 'string') {
       
   213             if (node.indexOf('doc') === 0) { // doc OR document
       
   214                 node = Y.config.doc;
       
   215             } else if (node.indexOf('win') === 0) { // win OR window
       
   216                 node = Y.config.win;
       
   217             } else {
       
   218                 node = Y.Selector.query(node, null, true);
       
   219             }
       
   220             if (!node) {
       
   221                 return null;
       
   222             }
       
   223         } else if (node instanceof Node) {
       
   224             return node; // NOTE: return
       
   225         }
       
   226 
       
   227         uid = node._yuid;
       
   228         instance = Node._instances[uid]; // reuse exising instances
       
   229         cachedNode = instance ? instance._node : null;
       
   230         if (!instance || (cachedNode && node !== cachedNode)) { // new Node when nodes don't match
       
   231             instance = new Node(node);
       
   232         }
       
   233     }
       
   234     return instance;
       
   235 };
       
   236 
       
   237 /**
       
   238  * Returns a single Node instance bound to the node or the
       
   239  * first element matching the given selector.
       
   240  * @method Y.get
       
   241  * @deprecated Use Y.one
       
   242  * @static
       
   243  * @param {String | HTMLElement} node a node or Selector 
       
   244  * @param {Y.Node || HTMLElement} doc an optional document to scan. Defaults to Y.config.doc. 
       
   245  */
       
   246 Node.get = function() {
       
   247     Y.log('Y.get is deprecated, use Y.one', 'warn', 'deprecated');
       
   248     return Node.one.apply(Node, arguments);
       
   249 };
       
   250 
       
   251 /**
       
   252  * Creates a new dom node using the provided markup string. 
       
   253  * @method create
       
   254  * @static
       
   255  * @param {String} html The markup used to create the element
       
   256  * @param {HTMLDocument} doc An optional document context 
       
   257  * @return {Node} A Node instance bound to a DOM node or fragment 
       
   258  */
       
   259 Node.create = function() {
       
   260     return Node.get(Y.DOM.create.apply(Y.DOM, arguments));
       
   261 };
       
   262 
       
   263 Node.ATTRS = {
       
   264     /**
       
   265      * Allows for getting and setting the text of an element.
       
   266      * Formatting is preserved and special characters are treated literally.
       
   267      * @config text
       
   268      * @type String
       
   269      */
       
   270     text: {
       
   271         getter: function() {
       
   272             return Y.DOM.getText(this._node);
       
   273         },
       
   274 
       
   275         setter: function(content) {
       
   276             Y.DOM.setText(this._node, content);
       
   277             return content;
       
   278         }
       
   279     },
       
   280 
       
   281     'options': {
       
   282         getter: function() {
       
   283             return this._node.getElementsByTagName('option');
       
   284         }
       
   285     },
       
   286 
       
   287      // IE: elements collection is also FORM node which trips up scrubVal.
       
   288      // preconverting to NodeList
       
   289      // TODO: break out for IE only
       
   290     'elements': {
       
   291         getter: function() {
       
   292             return Y.all(this._node.elements);
       
   293         }
       
   294     },
       
   295 
       
   296     /**
       
   297      * Returns a NodeList instance of all HTMLElement children.
       
   298      * @readOnly
       
   299      * @config children
       
   300      * @type NodeList
       
   301      */
       
   302     'children': {
       
   303         getter: function() {
       
   304             var node = this._node,
       
   305                 children = node.children,
       
   306                 childNodes, i, len;
       
   307 
       
   308             if (!children) {
       
   309                 childNodes = node.childNodes;
       
   310                 children = [];
       
   311 
       
   312                 for (i = 0, len = childNodes.length; i < len; ++i) {
       
   313                     if (childNodes[i][TAG_NAME]) {
       
   314                         children[children.length] = childNodes[i];
       
   315                     }
       
   316                 }
       
   317             }
       
   318             return Y.all(children);
       
   319         }
       
   320     },
       
   321 
       
   322     value: {
       
   323         getter: function() {
       
   324             return Y.DOM.getValue(this._node);
       
   325         },
       
   326 
       
   327         setter: function(val) {
       
   328             Y.DOM.setValue(this._node, val);
       
   329             return val;
       
   330         }
       
   331     },
       
   332 
       
   333     data: {
       
   334         getter: function() {
       
   335             return this._data;
       
   336         },
       
   337 
       
   338         setter: function(val) {
       
   339             this._data = val;
       
   340             return val;
       
   341         }
       
   342     }
       
   343 };
       
   344 
       
   345 // call with instance context
       
   346 Node.DEFAULT_SETTER = function(name, val) {
       
   347     var node = this._stateProxy,
       
   348         strPath;
       
   349 
       
   350     if (name.indexOf(DOT) > -1) {
       
   351         strPath = name;
       
   352         name = name.split(DOT);
       
   353         // only allow when defined on node
       
   354         Y.Object.setValue(node, name, val);
       
   355     } else if (node[name] !== undefined) { // pass thru DOM properties 
       
   356         node[name] = val;
       
   357     }
       
   358 
       
   359     return val;
       
   360 };
       
   361 
       
   362 // call with instance context
       
   363 Node.DEFAULT_GETTER = function(name) {
       
   364     var node = this._stateProxy,
       
   365         val;
       
   366 
       
   367     if (name.indexOf && name.indexOf(DOT) > -1) {
       
   368         val = Y.Object.getValue(node, name.split(DOT));
       
   369     } else if (node[name] !== undefined) { // pass thru from DOM
       
   370         val = node[name];
       
   371     }
       
   372 
       
   373     return val;
       
   374 };
       
   375 
       
   376 Y.augment(Node, Y.Event.Target);
       
   377 
       
   378 Y.mix(Node.prototype, {
       
   379     toString: function() {
       
   380         var str = '',
       
   381             errorMsg = this[UID] + ': not bound to a node',
       
   382             node = this._node;
       
   383 
       
   384         if (node) {
       
   385             str += node[NODE_NAME];
       
   386             if (node.id) {
       
   387                 str += '#' + node.id; 
       
   388             }
       
   389 
       
   390             if (node.className) {
       
   391                 str += '.' + node.className.replace(' ', '.'); 
       
   392             }
       
   393 
       
   394             // TODO: add yuid?
       
   395             str += ' ' + this[UID];
       
   396         }
       
   397         return str || errorMsg;
       
   398     },
       
   399 
       
   400     /**
       
   401      * Returns an attribute value on the Node instance
       
   402      * @method get
       
   403      * @param {String} attr The attribute to be set
       
   404      * @return {any} The current value of the attribute
       
   405      */
       
   406     get: function(attr) {
       
   407         var val;
       
   408 
       
   409         if (this._getAttr) { // use Attribute imple
       
   410             val = this._getAttr(attr);
       
   411         } else {
       
   412             val = this._get(attr);
       
   413         }
       
   414 
       
   415         if (val) {
       
   416             val = Y.Node.scrubVal(val, this);
       
   417         }
       
   418         return val;
       
   419     },
       
   420 
       
   421     _get: function(attr) {
       
   422         var attrConfig = Node.ATTRS[attr],
       
   423             val;
       
   424 
       
   425         if (attrConfig && attrConfig.getter) {
       
   426             val = attrConfig.getter.call(this);
       
   427         } else if (Node.re_aria.test(attr)) {
       
   428             val = this._node.getAttribute(attr, 2); 
       
   429         } else {
       
   430             val = Node.DEFAULT_GETTER.apply(this, arguments);
       
   431         }
       
   432 
       
   433         return val;
       
   434     },
       
   435 
       
   436     /**
       
   437      * Sets an attribute on the Node instance.
       
   438      * @method set
       
   439      * @param {String} attr The attribute to be set.  
       
   440      * @param {any} val The value to set the attribute to.  
       
   441      * @chainable
       
   442      */
       
   443     set: function(attr, val) {
       
   444         var attrConfig = Node.ATTRS[attr];
       
   445 
       
   446         if (this._setAttr) { // use Attribute imple
       
   447             this._setAttr.apply(this, arguments);
       
   448         } else { // use setters inline
       
   449             if (attrConfig && attrConfig.setter) {
       
   450                 attrConfig.setter.call(this, val);
       
   451             } else if (Node.re_aria.test(attr)) { // special case Aria
       
   452                 this._node.setAttribute(attr, val);
       
   453             } else {
       
   454                 Node.DEFAULT_SETTER.apply(this, arguments);
       
   455             }
       
   456         }
       
   457 
       
   458         return this;
       
   459     },
       
   460 
       
   461     /**
       
   462      * Sets multiple attributes. 
       
   463      * @method setAttrs
       
   464      * @param {Object} attrMap an object of name/value pairs to set  
       
   465      * @chainable
       
   466      */
       
   467     setAttrs: function(attrMap) {
       
   468         if (this._setAttrs) { // use Attribute imple
       
   469             this._setAttrs(attrMap);
       
   470         } else { // use setters inline
       
   471             Y.Object.each(attrMap, function(v, n) {
       
   472                 this.set(n, v); 
       
   473             }, this);
       
   474         }
       
   475 
       
   476         return this;
       
   477     },
       
   478 
       
   479     /**
       
   480      * Returns an object containing the values for the requested attributes. 
       
   481      * @method getAttrs
       
   482      * @param {Array} attrs an array of attributes to get values  
       
   483      * @return {Object} An object with attribute name/value pairs.
       
   484      */
       
   485     getAttrs: function(attrs) {
       
   486         var ret = {};
       
   487         if (this._getAttrs) { // use Attribute imple
       
   488             this._getAttrs(attrs);
       
   489         } else { // use setters inline
       
   490             Y.Array.each(attrs, function(v, n) {
       
   491                 ret[v] = this.get(v); 
       
   492             }, this);
       
   493         }
       
   494 
       
   495         return ret;
       
   496     },
       
   497 
       
   498     /**
       
   499      * Creates a new Node using the provided markup string. 
       
   500      * @method create
       
   501      * @param {String} html The markup used to create the element
       
   502      * @param {HTMLDocument} doc An optional document context 
       
   503      * @return {Node} A Node instance bound to a DOM node or fragment 
       
   504      */
       
   505     create: Node.create,
       
   506 
       
   507     /**
       
   508      * Compares nodes to determine if they match.
       
   509      * Node instances can be compared to each other and/or HTMLElements.
       
   510      * @method compareTo
       
   511      * @param {HTMLElement | Node} refNode The reference node to compare to the node.
       
   512      * @return {Boolean} True if the nodes match, false if they do not. 
       
   513      */
       
   514     compareTo: function(refNode) {
       
   515         var node = this._node;
       
   516         if (refNode instanceof Y.Node) { 
       
   517             refNode = refNode._node;
       
   518         }
       
   519         return node === refNode;
       
   520     },
       
   521 
       
   522     /**
       
   523      * Determines whether the node is appended to the document.
       
   524      * @method inDoc
       
   525      * @param {Node|HTMLElement} doc optional An optional document to check against.
       
   526      * Defaults to current document. 
       
   527      * @return {Boolean} Whether or not this node is appended to the document. 
       
   528      */
       
   529     inDoc: function(doc) {
       
   530         var node = this._node;
       
   531         doc = (doc) ? doc._node || doc : node[OWNER_DOCUMENT];
       
   532         if (doc.documentElement) {
       
   533             return Y.DOM.contains(doc.documentElement, node);
       
   534         }
       
   535     },
       
   536 
       
   537     getById: function(id) {
       
   538         var node = this._node,
       
   539             ret = Y.DOM.byId(id, node[OWNER_DOCUMENT]);
       
   540         if (ret && Y.DOM.contains(node, ret)) {
       
   541             ret = Y.one(ret);
       
   542         } else {
       
   543             ret = null;
       
   544         }
       
   545         return ret;
       
   546     },
       
   547 
       
   548    /**
       
   549      * Returns the nearest ancestor that passes the test applied by supplied boolean method.
       
   550      * @method ancestor
       
   551      * @param {String | Function} fn A selector string or boolean method for testing elements.
       
   552      * If a function is used, it receives the current node being tested as the only argument.
       
   553      * @return {Node} The matching Node instance or null if not found
       
   554      */
       
   555     ancestor: function(fn) {
       
   556         return Node.get(Y.DOM.elementByAxis(this._node, 'parentNode', _wrapFn(fn)));
       
   557     },
       
   558 
       
   559     /**
       
   560      * Returns the previous matching sibling. 
       
   561      * Returns the nearest element node sibling if no method provided.
       
   562      * @method previous
       
   563      * @param {String | Function} fn A selector or boolean method for testing elements.
       
   564      * If a function is used, it receives the current node being tested as the only argument.
       
   565      * @return {Node} Node instance or null if not found
       
   566      */
       
   567     previous: function(fn, all) {
       
   568         return Node.get(Y.DOM.elementByAxis(this._node, 'previousSibling', _wrapFn(fn), all));
       
   569     }, 
       
   570 
       
   571     /**
       
   572      * Returns the next matching sibling. 
       
   573      * Returns the nearest element node sibling if no method provided.
       
   574      * @method next
       
   575      * @param {String | Function} fn A selector or boolean method for testing elements.
       
   576      * If a function is used, it receives the current node being tested as the only argument.
       
   577      * @return {Node} Node instance or null if not found
       
   578      */
       
   579     next: function(node, fn, all) {
       
   580         return Node.get(Y.DOM.elementByAxis(this._node, 'nextSibling', _wrapFn(fn), all));
       
   581     },
       
   582         
       
   583     /**
       
   584      * Retrieves a Node instance of nodes based on the given CSS selector. 
       
   585      * @method one
       
   586      *
       
   587      * @param {string} selector The CSS selector to test against.
       
   588      * @return {Node} A Node instance for the matching HTMLElement.
       
   589      */
       
   590     one: function(selector) {
       
   591         return Y.one(Y.Selector.query(selector, this._node, true));
       
   592     },
       
   593 
       
   594     /**
       
   595      * Retrieves a Node instance of nodes based on the given CSS selector. 
       
   596      * @method query
       
   597      * @deprecated Use one()
       
   598      * @param {string} selector The CSS selector to test against.
       
   599      * @return {Node} A Node instance for the matching HTMLElement.
       
   600      */
       
   601     query: function(selector) {
       
   602         Y.log('query() is deprecated, use one()', 'warn', 'deprecated');
       
   603         return this.one(selector);
       
   604     },
       
   605 
       
   606     /**
       
   607      * Retrieves a nodeList based on the given CSS selector. 
       
   608      * @method all
       
   609      *
       
   610      * @param {string} selector The CSS selector to test against.
       
   611      * @return {NodeList} A NodeList instance for the matching HTMLCollection/Array.
       
   612      */
       
   613     all: function(selector) {
       
   614         var nodelist = Y.all(Y.Selector.query(selector, this._node));
       
   615         nodelist._query = selector;
       
   616         return nodelist;
       
   617     },
       
   618 
       
   619     /**
       
   620      * Retrieves a nodeList based on the given CSS selector. 
       
   621      * @method queryAll
       
   622      * @deprecated Use all()
       
   623      * @param {string} selector The CSS selector to test against.
       
   624      * @return {NodeList} A NodeList instance for the matching HTMLCollection/Array.
       
   625      */
       
   626     queryAll: function(selector) {
       
   627         Y.log('queryAll() is deprecated, use all()', 'warn', 'deprecated');
       
   628         return this.all(selector);
       
   629     },
       
   630 
       
   631     // TODO: allow fn test
       
   632     /**
       
   633      * Test if the supplied node matches the supplied selector.
       
   634      * @method test
       
   635      *
       
   636      * @param {string} selector The CSS selector to test against.
       
   637      * @return {boolean} Whether or not the node matches the selector.
       
   638      */
       
   639     test: function(selector) {
       
   640         return Y.Selector.test(this._node, selector);
       
   641     },
       
   642 
       
   643     /**
       
   644      * Removes the node from its parent.
       
   645      * Shortcut for myNode.get('parentNode').removeChild(myNode);
       
   646      * @method remove
       
   647      * @chainable
       
   648      *
       
   649      */
       
   650     remove: function(destroy) {
       
   651         var node = this._node;
       
   652         node.parentNode.removeChild(node);
       
   653         if (destroy) {
       
   654             this.destroy(true);
       
   655         }
       
   656         return this;
       
   657     },
       
   658 
       
   659     /**
       
   660      * Replace the node with the other node. This is a DOM update only
       
   661      * and does not change the node bound to the Node instance.
       
   662      * Shortcut for myNode.get('parentNode').replaceChild(newNode, myNode);
       
   663      * @method replace
       
   664      * @chainable
       
   665      *
       
   666      */
       
   667     replace: function(newNode) {
       
   668         var node = this._node;
       
   669         node.parentNode.replaceChild(newNode, node);
       
   670         return this;
       
   671     },
       
   672 
       
   673     purge: function(recurse, type) {
       
   674         Y.Event.purgeElement(this._node, recurse, type);
       
   675     },
       
   676 
       
   677     destroy: function(purge) {
       
   678         delete Node._instances[this[UID]];
       
   679         if (purge) {
       
   680             this.purge(true);
       
   681         }
       
   682 
       
   683         if (this.unplug) {
       
   684             this.unplug();
       
   685         }
       
   686 
       
   687         this._node._yuid = null;
       
   688         this._node = null;
       
   689         this._stateProxy = null;
       
   690     },
       
   691 
       
   692     /**
       
   693      * Invokes a method on the Node instance 
       
   694      * @method invoke
       
   695      * @param {String} method The name of the method to invoke
       
   696      * @param {Any}  a, b, c, etc. Arguments to invoke the method with. 
       
   697      * @return Whatever the underly method returns. 
       
   698      * DOM Nodes and Collections return values
       
   699      * are converted to Node/NodeList instances.
       
   700      *
       
   701      */
       
   702     invoke: function(method, a, b, c, d, e) {
       
   703         var node = this._node,
       
   704             ret;
       
   705 
       
   706         if (a && a instanceof Y.Node) {
       
   707             a = a._node;
       
   708         }
       
   709 
       
   710         if (b && b instanceof Y.Node) {
       
   711             b = b._node;
       
   712         }
       
   713 
       
   714         ret = node[method](a, b, c, d, e);    
       
   715         return Y.Node.scrubVal(ret, this);
       
   716     },
       
   717 
       
   718     /**
       
   719      * Applies the given function to each Node in the NodeList.
       
   720      * @method each
       
   721      * @deprecated Use NodeList
       
   722      * @param {Function} fn The function to apply 
       
   723      * @param {Object} context optional An optional context to apply the function with
       
   724      * Default context is the NodeList instance
       
   725      * @chainable
       
   726      */
       
   727     each: function(fn, context) {
       
   728         context = context || this;
       
   729         Y.log('each is deprecated on Node', 'warn', 'deprecated');
       
   730         return fn.call(context, this);
       
   731     },
       
   732 
       
   733     /**
       
   734      * Retrieves the Node instance at the given index. 
       
   735      * @method item
       
   736      * @deprecated Use NodeList
       
   737      *
       
   738      * @param {Number} index The index of the target Node.
       
   739      * @return {Node} The Node instance at the given index.
       
   740      */
       
   741     item: function(index) {
       
   742         Y.log('item is deprecated on Node', 'warn', 'deprecated');
       
   743         return this;
       
   744     },
       
   745 
       
   746     /**
       
   747      * Returns the current number of items in the Node.
       
   748      * @method size
       
   749      * @deprecated Use NodeList
       
   750      * @return {Int} The number of items in the Node. 
       
   751      */
       
   752     size: function() {
       
   753         Y.log('size is deprecated on Node', 'warn', 'deprecated');
       
   754         return this._node ? 1 : 0;
       
   755     },
       
   756 
       
   757     /**
       
   758      * Inserts the content before the reference node. 
       
   759      * @method insert
       
   760      * @param {String | Y.Node | HTMLElement} content The content to insert 
       
   761      * @param {Int | Y.Node | HTMLElement | String} where The position to insert at.
       
   762      * @chainable
       
   763      */
       
   764     insert: function(content, where) {
       
   765         var node = this._node;
       
   766 
       
   767         if (content) {
       
   768             if (typeof where === 'number') { // allow index
       
   769                 where = this._node.childNodes[where];
       
   770             }
       
   771 
       
   772             if (typeof content !== 'string') { // allow Node or NodeList/Array instances
       
   773                 if (content._node) { // Node
       
   774                     content = content._node;
       
   775                 } else if (content._nodes || (!content.nodeType && content.length)) { // NodeList or Array
       
   776                     Y.each(content._nodes, function(n) {
       
   777                         Y.DOM.addHTML(node, n, where);
       
   778                     });
       
   779 
       
   780                     return this; // NOTE: early return
       
   781                 }
       
   782             }
       
   783             Y.DOM.addHTML(node, content, where);
       
   784         }
       
   785         return this;
       
   786     },
       
   787 
       
   788     /**
       
   789      * Inserts the content as the firstChild of the node. 
       
   790      * @method prepend
       
   791      * @param {String | Y.Node | HTMLElement} content The content to insert 
       
   792      * @chainable
       
   793      */
       
   794     prepend: function(content) {
       
   795         return this.insert(content, 0);
       
   796     },
       
   797 
       
   798     /**
       
   799      * Inserts the content as the lastChild of the node. 
       
   800      * @method append
       
   801      * @param {String | Y.Node | HTMLElement} content The content to insert 
       
   802      * @chainable
       
   803      */
       
   804     append: function(content) {
       
   805         return this.insert(content, null);
       
   806     },
       
   807 
       
   808     /**
       
   809      * Replaces the node's current content with the content.
       
   810      * @method setContent
       
   811      * @param {String | Y.Node | HTMLElement} content The content to insert 
       
   812      * @chainable
       
   813      */
       
   814     setContent: function(content) {
       
   815         Y.DOM.addHTML(this._node, content, 'replace');
       
   816         return this;
       
   817     },
       
   818 
       
   819     // TODO: need this?
       
   820     hasMethod: function(method) {
       
   821         var node = this._node;
       
   822         return (node && (typeof node === 'function'));
       
   823     }
       
   824 }, true);
       
   825 
       
   826 Y.Node = Node;
       
   827 Y.get = Y.Node.get;
       
   828 Y.one = Y.Node.one;
       
   829 /**
       
   830  * The NodeList module provides support for managing collections of Nodes.
       
   831  * @module node
       
   832  * @submodule nodelist
       
   833  */    
       
   834 
       
   835 /**
       
   836  * The NodeList class provides a wrapper for manipulating DOM NodeLists.
       
   837  * NodeList properties can be accessed via the set/get methods.
       
   838  * Use Y.all() to retrieve NodeList instances.
       
   839  *
       
   840  * @class NodeList
       
   841  * @constructor
       
   842  */
       
   843 
       
   844 var NodeList = function(nodes) {
       
   845     if (typeof nodes === 'string') {
       
   846         this._query = nodes;
       
   847         nodes = Y.Selector.query(nodes);
       
   848     } else {
       
   849         nodes = Y.Array(nodes, 0, true);
       
   850     }
       
   851 
       
   852     NodeList._instances[Y.stamp(this)] = this;
       
   853     this._nodes = nodes;
       
   854 };
       
   855 // end "globals"
       
   856 
       
   857 NodeList.NAME = 'NodeList';
       
   858 
       
   859 /**
       
   860  * Retrieves the DOM nodes bound to a NodeList instance
       
   861  * @method NodeList.getDOMNodes
       
   862  * @static
       
   863  *
       
   864  * @param {Y.NodeList} node The NodeList instance
       
   865  * @return {Array} The array of DOM nodes bound to the NodeList
       
   866  */
       
   867 NodeList.getDOMNodes = function(nodeList) {
       
   868     return nodeList._nodes;
       
   869 };
       
   870 
       
   871 NodeList._instances = [];
       
   872 
       
   873 NodeList.each = function(instance, fn, context) {
       
   874     var nodes = instance._nodes;
       
   875     if (nodes && nodes.length) {
       
   876         Y.Array.each(nodes, fn, context || instance);
       
   877     } else {
       
   878         Y.log('no nodes bound to ' + this, 'warn', 'NodeList');
       
   879     }
       
   880 };
       
   881 
       
   882 NodeList.addMethod = function(name, fn, context) {
       
   883     if (name && fn) {
       
   884         NodeList.prototype[name] = function() {
       
   885             var ret = [],
       
   886                 args = arguments;
       
   887 
       
   888             Y.Array.each(this._nodes, function(node) {
       
   889                 var UID = '_yuid',
       
   890                     instance = Y.Node._instances[node[UID]],
       
   891                     ctx,
       
   892                     result;
       
   893 
       
   894                 if (!instance) {
       
   895                     instance = NodeList._getTempNode(node);
       
   896                 }
       
   897                 ctx = context || instance;
       
   898                 result = fn.apply(ctx, args);
       
   899                 if (result !== undefined && result !== instance) {
       
   900                     ret[ret.length] = result;
       
   901                 }
       
   902             });
       
   903 
       
   904             // TODO: remove tmp pointer
       
   905             return ret.length ? ret : this;
       
   906         };
       
   907     } else {
       
   908         Y.log('unable to add method: ' + name, 'warn', 'Node');
       
   909     }
       
   910 };
       
   911 
       
   912 NodeList.importMethod = function(host, name, altName) {
       
   913     if (typeof name === 'string') {
       
   914         altName = altName || name;
       
   915         NodeList.addMethod(name, host[name]);
       
   916     } else {
       
   917         Y.each(name, function(n) {
       
   918             NodeList.importMethod(host, n);
       
   919         });
       
   920     }
       
   921 };
       
   922 
       
   923 NodeList._getTempNode = function(node) {
       
   924     var tmp = NodeList._tempNode;
       
   925     if (!tmp) {
       
   926         tmp = Y.Node.create('<div></div>');
       
   927         NodeList._tempNode = tmp;
       
   928     }
       
   929 
       
   930     tmp._node = node;
       
   931     tmp._stateProxy = node;
       
   932     return tmp;
       
   933 };
       
   934 
       
   935 Y.mix(NodeList.prototype, {
       
   936     /**
       
   937      * Retrieves the Node instance at the given index. 
       
   938      * @method item
       
   939      *
       
   940      * @param {Number} index The index of the target Node.
       
   941      * @return {Node} The Node instance at the given index.
       
   942      */
       
   943     item: function(index) {
       
   944         return Y.one((this._nodes || [])[index]);
       
   945     },
       
   946 
       
   947     /**
       
   948      * Applies the given function to each Node in the NodeList.
       
   949      * @method each
       
   950      * @param {Function} fn The function to apply. It receives 3 arguments:
       
   951      * the current node instance, the node's index, and the NodeList instance
       
   952      * @param {Object} context optional An optional context to apply the function with
       
   953      * Default context is the current Node instance
       
   954      * @chainable
       
   955      */
       
   956     each: function(fn, context) {
       
   957         var instance = this;
       
   958         Y.Array.each(this._nodes, function(node, index) {
       
   959             node = Y.one(node);
       
   960             return fn.call(context || node, node, index, instance);
       
   961         });
       
   962         return instance;
       
   963     },
       
   964 
       
   965     batch: function(fn, context) {
       
   966         var nodelist = this;
       
   967 
       
   968         Y.Array.each(this._nodes, function(node, index) {
       
   969             var instance = Y.Node._instances[node[UID]];
       
   970             if (!instance) {
       
   971                 instance = NodeList._getTempNode(node);
       
   972             }
       
   973 
       
   974             return fn.call(context || instance, instance, index, nodelist);
       
   975         });
       
   976         return nodelist;
       
   977     },
       
   978 
       
   979     /**
       
   980      * Executes the function once for each node until a true value is returned.
       
   981      * @method some
       
   982      * @param {Function} fn The function to apply. It receives 3 arguments:
       
   983      * the current node instance, the node's index, and the NodeList instance
       
   984      * @param {Object} context optional An optional context to execute the function from.
       
   985      * Default context is the current Node instance
       
   986      * @return {Boolean} Whether or not the function returned true for any node.
       
   987      */
       
   988     some: function(fn, context) {
       
   989         var instance = this;
       
   990         return Y.Array.some(this._nodes, function(node, index) {
       
   991             node = Y.one(node);
       
   992             context = context || node;
       
   993             return fn.call(context, node, index, instance);
       
   994         });
       
   995     },
       
   996 
       
   997     /**
       
   998      * Creates a documenFragment from the nodes bound to the NodeList instance 
       
   999      * @method toDocFrag
       
  1000      * @return Node a Node instance bound to the documentFragment
       
  1001      */
       
  1002     toFrag: function() {
       
  1003         return Y.one(Y.DOM._nl2frag(this._nodes));
       
  1004     },
       
  1005 
       
  1006     /**
       
  1007      * Returns the index of the node in the NodeList instance
       
  1008      * or -1 if the node isn't found.
       
  1009      * @method indexOf
       
  1010      * @param {Y.Node || DOMNode} node the node to search for
       
  1011      * @return {Int} the index of the node value or -1 if not found
       
  1012      */
       
  1013     indexOf: function(node) {
       
  1014         return Y.Array.indexOf(this._nodes, Y.Node.getDOMNode(node));
       
  1015     },
       
  1016 
       
  1017     /**
       
  1018      * Filters the NodeList instance down to only nodes matching the given selector.
       
  1019      * @method filter
       
  1020      * @param {String} selector The selector to filter against
       
  1021      * @return {NodeList} NodeList containing the updated collection 
       
  1022      * @see Selector
       
  1023      */
       
  1024     filter: function(selector) {
       
  1025         return Y.all(Y.Selector.filter(this._nodes, selector));
       
  1026     },
       
  1027 
       
  1028 
       
  1029     /**
       
  1030      * Creates a new NodeList containing all nodes at every n indices, where 
       
  1031      * remainder n % index equals r.
       
  1032      * (zero-based index).
       
  1033      * @method modulus
       
  1034      * @param {Int} n The offset to use (return every nth node)
       
  1035      * @param {Int} r An optional remainder to use with the modulus operation (defaults to zero) 
       
  1036      * @return {NodeList} NodeList containing the updated collection 
       
  1037      */
       
  1038     modulus: function(n, r) {
       
  1039         r = r || 0;
       
  1040         var nodes = [];
       
  1041         NodeList.each(this, function(node, i) {
       
  1042             if (i % n === r) {
       
  1043                 nodes.push(node);
       
  1044             }
       
  1045         });
       
  1046 
       
  1047         return Y.all(nodes);
       
  1048     },
       
  1049 
       
  1050     /**
       
  1051      * Creates a new NodeList containing all nodes at odd indices
       
  1052      * (zero-based index).
       
  1053      * @method odd
       
  1054      * @return {NodeList} NodeList containing the updated collection 
       
  1055      */
       
  1056     odd: function() {
       
  1057         return this.modulus(2, 1);
       
  1058     },
       
  1059 
       
  1060     /**
       
  1061      * Creates a new NodeList containing all nodes at even indices
       
  1062      * (zero-based index), including zero. 
       
  1063      * @method even
       
  1064      * @return {NodeList} NodeList containing the updated collection 
       
  1065      */
       
  1066     even: function() {
       
  1067         return this.modulus(2);
       
  1068     },
       
  1069 
       
  1070     destructor: function() {
       
  1071         delete NodeList._instances[this[UID]];
       
  1072     },
       
  1073 
       
  1074     /**
       
  1075      * Reruns the initial query, when created using a selector query 
       
  1076      * @method refresh
       
  1077      * @chainable
       
  1078      */
       
  1079     refresh: function() {
       
  1080         var doc,
       
  1081             nodes = this._nodes;
       
  1082         if (this._query) {
       
  1083             if (nodes && nodes[0] && nodes[0].ownerDocument) {
       
  1084                 doc = nodes[0].ownerDocument;
       
  1085             }
       
  1086 
       
  1087             this._nodes = Y.Selector.query(this._query, doc || Y.config.doc);        
       
  1088         }
       
  1089 
       
  1090         return this;
       
  1091     },
       
  1092 
       
  1093     /**
       
  1094      * Applies an event listener to each Node bound to the NodeList. 
       
  1095      * @method on
       
  1096      * @param {String} type The event being listened for
       
  1097      * @param {Function} fn The handler to call when the event fires
       
  1098      * @param {Object} context The context to call the handler with.
       
  1099      * Default is the NodeList instance. 
       
  1100      * @return {Object} Returns an event handle that can later be use to detach(). 
       
  1101      * @see Event.on
       
  1102      */
       
  1103     on: function(type, fn, context) {
       
  1104         var args = Y.Array(arguments, 0, true);
       
  1105         args.splice(2, 0, this._nodes);
       
  1106         args[3] = context || this;
       
  1107         return Y.on.apply(Y, args);
       
  1108     },
       
  1109 
       
  1110     /**
       
  1111      * Applies an event listener to each Node bound to the NodeList. 
       
  1112      * The handler is called only after all on() handlers are called
       
  1113      * and the event is not prevented.
       
  1114      * @method after
       
  1115      * @param {String} type The event being listened for
       
  1116      * @param {Function} fn The handler to call when the event fires
       
  1117      * @param {Object} context The context to call the handler with.
       
  1118      * Default is the NodeList instance. 
       
  1119      * @return {Object} Returns an event handle that can later be use to detach(). 
       
  1120      * @see Event.on
       
  1121      */
       
  1122     after: function(type, fn, context) {
       
  1123         var args = Y.Array(arguments, 0, true);
       
  1124         args.splice(2, 0, this._nodes);
       
  1125         args[3] = context || this;
       
  1126         return Y.after.apply(Y, args);
       
  1127     },
       
  1128 
       
  1129     /**
       
  1130      * Returns the current number of items in the NodeList.
       
  1131      * @method size
       
  1132      * @return {Int} The number of items in the NodeList. 
       
  1133      */
       
  1134     size: function() {
       
  1135         return this._nodes.length;
       
  1136     },
       
  1137 
       
  1138     toString: function() {
       
  1139         var str = '',
       
  1140             errorMsg = this[UID] + ': not bound to any nodes',
       
  1141             nodes = this._nodes,
       
  1142             node;
       
  1143 
       
  1144         if (nodes && nodes[0]) {
       
  1145             node = nodes[0];
       
  1146             str += node[NODE_NAME];
       
  1147             if (node.id) {
       
  1148                 str += '#' + node.id; 
       
  1149             }
       
  1150 
       
  1151             if (node.className) {
       
  1152                 str += '.' + node.className.replace(' ', '.'); 
       
  1153             }
       
  1154 
       
  1155             if (nodes.length > 1) {
       
  1156                 str += '...[' + nodes.length + ' items]';
       
  1157             }
       
  1158         }
       
  1159         return str || errorMsg;
       
  1160     }
       
  1161 
       
  1162 }, true);
       
  1163 
       
  1164 NodeList.importMethod(Y.Node.prototype, [
       
  1165     /**
       
  1166      * Called on each Node instance
       
  1167      * @for NodeList
       
  1168      * @method append
       
  1169      * @see Node.append
       
  1170      */
       
  1171     'append',
       
  1172 
       
  1173     /**
       
  1174       * Called on each Node instance
       
  1175       * @method detach
       
  1176       * @see Node.detach
       
  1177       */
       
  1178     'detach',
       
  1179     
       
  1180     /** Called on each Node instance
       
  1181       * @method detachAll
       
  1182       * @see Node.detachAll
       
  1183       */
       
  1184     'detachAll',
       
  1185 
       
  1186     /** Called on each Node instance
       
  1187       * @method insert
       
  1188       * @see NodeInsert
       
  1189       */
       
  1190     'insert',
       
  1191 
       
  1192     /** Called on each Node instance
       
  1193       * @method prepend
       
  1194       * @see Node.prepend
       
  1195       */
       
  1196     'prepend',
       
  1197 
       
  1198     /** Called on each Node instance
       
  1199       * @method remove
       
  1200       * @see Node.remove
       
  1201       */
       
  1202     'remove',
       
  1203 
       
  1204     /** Called on each Node instance
       
  1205       * @method set
       
  1206       * @see Node.set
       
  1207       */
       
  1208     'set',
       
  1209 
       
  1210     /** Called on each Node instance
       
  1211       * @method setContent
       
  1212       * @see Node.setContent
       
  1213       */
       
  1214     'setContent'
       
  1215 ]);
       
  1216 
       
  1217 // one-off implementation to convert array of Nodes to NodeList
       
  1218 // e.g. Y.all('input').get('parentNode');
       
  1219 
       
  1220 /** Called on each Node instance
       
  1221   * @method get
       
  1222   * @see Node
       
  1223   */
       
  1224 NodeList.prototype.get = function(attr) {
       
  1225     var ret = [],
       
  1226         nodes = this._nodes,
       
  1227         isNodeList = false,
       
  1228         getTemp = NodeList._getTempNode,
       
  1229         instance,
       
  1230         val;
       
  1231 
       
  1232     if (nodes[0]) {
       
  1233         instance = Y.Node._instances[nodes[0]._yuid] || getTemp(nodes[0]);
       
  1234         val = instance._get(attr);
       
  1235         if (val && val.nodeType) {
       
  1236             isNodeList = true;
       
  1237         }
       
  1238     }
       
  1239 
       
  1240     Y.Array.each(nodes, function(node) {
       
  1241         instance = Y.Node._instances[node._yuid];
       
  1242 
       
  1243         if (!instance) {
       
  1244             instance = getTemp(node);
       
  1245         }
       
  1246 
       
  1247         val = instance._get(attr);
       
  1248         if (!isNodeList) { // convert array of Nodes to NodeList
       
  1249             val = Y.Node.scrubVal(val, instance);
       
  1250         }
       
  1251 
       
  1252         ret.push(val);
       
  1253     });
       
  1254 
       
  1255     return (isNodeList) ? Y.all(ret) : ret;
       
  1256 };
       
  1257 
       
  1258 Y.NodeList = NodeList;
       
  1259 
       
  1260 Y.all = function(nodes) {
       
  1261     return new NodeList(nodes);
       
  1262 };
       
  1263 
       
  1264 Y.Node.all = Y.all;
       
  1265 Y.Array.each([
       
  1266     /**
       
  1267      * Passes through to DOM method.
       
  1268      * @method replaceChild
       
  1269      * @for Node
       
  1270      * @param {HTMLElement | Node} node Node to be inserted 
       
  1271      * @param {HTMLElement | Node} refNode Node to be replaced 
       
  1272      * @return {Node} The replaced node 
       
  1273      */
       
  1274     'replaceChild',
       
  1275 
       
  1276     /**
       
  1277      * Passes through to DOM method.
       
  1278      * @method appendChild
       
  1279      * @param {HTMLElement | Node} node Node to be appended 
       
  1280      * @return {Node} The appended node 
       
  1281      */
       
  1282     'appendChild',
       
  1283 
       
  1284     /**
       
  1285      * Passes through to DOM method.
       
  1286      * @method insertBefore
       
  1287      * @param {HTMLElement | Node} newNode Node to be appended 
       
  1288      * @param {HTMLElement | Node} refNode Node to be inserted before 
       
  1289      * @return {Node} The inserted node 
       
  1290      */
       
  1291     'insertBefore',
       
  1292 
       
  1293     /**
       
  1294      * Passes through to DOM method.
       
  1295      * @method removeChild
       
  1296      * @param {HTMLElement | Node} node Node to be removed 
       
  1297      * @return {Node} The removed node 
       
  1298      */
       
  1299     'removeChild',
       
  1300 
       
  1301     /**
       
  1302      * Passes through to DOM method.
       
  1303      * @method hasChildNodes
       
  1304      * @return {Boolean} Whether or not the node has any childNodes 
       
  1305      */
       
  1306     'hasChildNodes',
       
  1307 
       
  1308     /**
       
  1309      * Passes through to DOM method.
       
  1310      * @method cloneNode
       
  1311      * @param {Boolean} deep Whether or not to perform a deep clone, which includes
       
  1312      * subtree and attributes
       
  1313      * @return {Node} The clone 
       
  1314      */
       
  1315     'cloneNode',
       
  1316 
       
  1317     /**
       
  1318      * Passes through to DOM method.
       
  1319      * @method hasAttribute
       
  1320      * @param {String} attribute The attribute to test for 
       
  1321      * @return {Boolean} Whether or not the attribute is present 
       
  1322      */
       
  1323     'hasAttribute',
       
  1324 
       
  1325     /**
       
  1326      * Passes through to DOM method.
       
  1327      * @method removeAttribute
       
  1328      * @param {String} attribute The attribute to be removed 
       
  1329      * @chainable
       
  1330      */
       
  1331     'removeAttribute',
       
  1332 
       
  1333     /**
       
  1334      * Passes through to DOM method.
       
  1335      * @method scrollIntoView
       
  1336      * @chainable
       
  1337      */
       
  1338     'scrollIntoView',
       
  1339 
       
  1340     /**
       
  1341      * Passes through to DOM method.
       
  1342      * @method getElementsByTagName
       
  1343      * @param {String} tagName The tagName to collect 
       
  1344      * @return {NodeList} A NodeList representing the HTMLCollection
       
  1345      */
       
  1346     'getElementsByTagName',
       
  1347 
       
  1348     /**
       
  1349      * Passes through to DOM method.
       
  1350      * @method focus
       
  1351      * @chainable
       
  1352      */
       
  1353     'focus',
       
  1354 
       
  1355     /**
       
  1356      * Passes through to DOM method.
       
  1357      * @method blur
       
  1358      * @chainable
       
  1359      */
       
  1360     'blur',
       
  1361 
       
  1362     /**
       
  1363      * Passes through to DOM method.
       
  1364      * Only valid on FORM elements
       
  1365      * @method submit
       
  1366      * @chainable
       
  1367      */
       
  1368     'submit',
       
  1369 
       
  1370     /**
       
  1371      * Passes through to DOM method.
       
  1372      * Only valid on FORM elements
       
  1373      * @method reset
       
  1374      * @chainable
       
  1375      */
       
  1376     'reset',
       
  1377 
       
  1378     /**
       
  1379      * Passes through to DOM method.
       
  1380      * @method select
       
  1381      * @chainable
       
  1382      */
       
  1383      'select'
       
  1384 ], function(method) {
       
  1385     Y.Node.prototype[method] = function(arg1, arg2, arg3) {
       
  1386         var ret = this.invoke(method, arg1, arg2, arg3);
       
  1387         return ret;
       
  1388     };
       
  1389 });
       
  1390 
       
  1391 Node.importMethod(Y.DOM, [
       
  1392     /**
       
  1393      * Determines whether the ndoe is an ancestor of another HTML element in the DOM hierarchy.
       
  1394      * @method contains
       
  1395      * @param {Node | HTMLElement} needle The possible node or descendent
       
  1396      * @return {Boolean} Whether or not this node is the needle its ancestor
       
  1397      */
       
  1398     'contains',
       
  1399     /**
       
  1400      * Allows setting attributes on DOM nodes, normalizing in some cases.
       
  1401      * This passes through to the DOM node, allowing for custom attributes.
       
  1402      * @method setAttribute
       
  1403      * @for Node
       
  1404      * @for NodeList
       
  1405      * @chainable
       
  1406      * @param {string} name The attribute name 
       
  1407      * @param {string} value The value to set
       
  1408      */
       
  1409     'setAttribute',
       
  1410     /**
       
  1411      * Allows getting attributes on DOM nodes, normalizing in some cases.
       
  1412      * This passes through to the DOM node, allowing for custom attributes.
       
  1413      * @method getAttribute
       
  1414      * @for Node
       
  1415      * @for NodeList
       
  1416      * @param {string} name The attribute name 
       
  1417      * @return {string} The attribute value 
       
  1418      */
       
  1419     'getAttribute'
       
  1420 ]);
       
  1421 
       
  1422 /**
       
  1423  * Allows setting attributes on DOM nodes, normalizing in some cases.
       
  1424  * This passes through to the DOM node, allowing for custom attributes.
       
  1425  * @method setAttribute
       
  1426  * @see Node
       
  1427  * @for NodeList
       
  1428  * @chainable
       
  1429  * @param {string} name The attribute name 
       
  1430  * @param {string} value The value to set
       
  1431  */
       
  1432 
       
  1433 /**
       
  1434  * Allows getting attributes on DOM nodes, normalizing in some cases.
       
  1435  * This passes through to the DOM node, allowing for custom attributes.
       
  1436  * @method getAttribute
       
  1437  * @see Node
       
  1438  * @for NodeList
       
  1439  * @param {string} name The attribute name 
       
  1440  * @return {string} The attribute value 
       
  1441  */
       
  1442 Y.NodeList.importMethod(Y.Node.prototype, ['getAttribute', 'setAttribute']);
       
  1443 (function(Y) {
       
  1444     var methods = [
       
  1445     /**
       
  1446      * Determines whether each node has the given className.
       
  1447      * @method hasClass
       
  1448      * @for Node
       
  1449      * @param {String} className the class name to search for
       
  1450      * @return {Array} An array of booleans for each node bound to the NodeList. 
       
  1451      */
       
  1452      'hasClass',
       
  1453 
       
  1454     /**
       
  1455      * Adds a class name to each node.
       
  1456      * @method addClass         
       
  1457      * @param {String} className the class name to add to the node's class attribute
       
  1458      * @chainable
       
  1459      */
       
  1460      'addClass',
       
  1461 
       
  1462     /**
       
  1463      * Removes a class name from each node.
       
  1464      * @method removeClass         
       
  1465      * @param {String} className the class name to remove from the node's class attribute
       
  1466      * @chainable
       
  1467      */
       
  1468      'removeClass',
       
  1469 
       
  1470     /**
       
  1471      * Replace a class with another class for each node.
       
  1472      * If no oldClassName is present, the newClassName is simply added.
       
  1473      * @method replaceClass  
       
  1474      * @param {String} oldClassName the class name to be replaced
       
  1475      * @param {String} newClassName the class name that will be replacing the old class name
       
  1476      * @chainable
       
  1477      */
       
  1478      'replaceClass',
       
  1479 
       
  1480     /**
       
  1481      * If the className exists on the node it is removed, if it doesn't exist it is added.
       
  1482      * @method toggleClass  
       
  1483      * @param {String} className the class name to be toggled
       
  1484      * @chainable
       
  1485      */
       
  1486      'toggleClass'
       
  1487     ];
       
  1488 
       
  1489     Y.Node.importMethod(Y.DOM, methods);
       
  1490     /**
       
  1491      * Determines whether each node has the given className.
       
  1492      * @method hasClass
       
  1493      * @see Node.hasClass
       
  1494      * @for NodeList
       
  1495      * @param {String} className the class name to search for
       
  1496      * @return {Array} An array of booleans for each node bound to the NodeList. 
       
  1497      */
       
  1498 
       
  1499     /**
       
  1500      * Adds a class name to each node.
       
  1501      * @method addClass         
       
  1502      * @see Node.addClass
       
  1503      * @param {String} className the class name to add to the node's class attribute
       
  1504      * @chainable
       
  1505      */
       
  1506 
       
  1507     /**
       
  1508      * Removes a class name from each node.
       
  1509      * @method removeClass         
       
  1510      * @see Node.removeClass
       
  1511      * @param {String} className the class name to remove from the node's class attribute
       
  1512      * @chainable
       
  1513      */
       
  1514 
       
  1515     /**
       
  1516      * Replace a class with another class for each node.
       
  1517      * If no oldClassName is present, the newClassName is simply added.
       
  1518      * @method replaceClass  
       
  1519      * @see Node.replaceClass
       
  1520      * @param {String} oldClassName the class name to be replaced
       
  1521      * @param {String} newClassName the class name that will be replacing the old class name
       
  1522      * @chainable
       
  1523      */
       
  1524 
       
  1525     /**
       
  1526      * If the className exists on the node it is removed, if it doesn't exist it is added.
       
  1527      * @method toggleClass  
       
  1528      * @see Node.toggleClass
       
  1529      * @param {String} className the class name to be toggled
       
  1530      * @chainable
       
  1531      */
       
  1532     Y.NodeList.importMethod(Y.Node.prototype, methods);
       
  1533 })(Y);
       
  1534 
       
  1535 if (!document.documentElement.hasAttribute) { // IE < 8
       
  1536     Y.Node.prototype.hasAttribute = function(attr) {
       
  1537         return Y.DOM.getAttribute(this._node, attr) !== '';
       
  1538     };
       
  1539 }
       
  1540 
       
  1541 // IE throws error when setting input.type = 'hidden',
       
  1542 // input.setAttribute('type', 'hidden') and input.attributes.type.value = 'hidden'
       
  1543 Y.Node.ATTRS.type = {
       
  1544     setter: function(val) {
       
  1545         if (val === 'hidden') {
       
  1546             try {
       
  1547                 this._node.type = 'hidden';
       
  1548             } catch(e) {
       
  1549                 this.setStyle('display', 'none');
       
  1550                 this._inputType = 'hidden';
       
  1551             }
       
  1552         } else {
       
  1553             try { // IE errors when changing the type from "hidden'
       
  1554                 this._node.type = val;
       
  1555             } catch (e) {
       
  1556                 Y.log('error setting type: ' + val, 'info', 'node');
       
  1557             }
       
  1558         }
       
  1559         return val;
       
  1560     },
       
  1561 
       
  1562     getter: function() {
       
  1563         return this._inputType || this._node.type;
       
  1564     },
       
  1565 
       
  1566     _bypassProxy: true // don't update DOM when using with Attribute
       
  1567 };
       
  1568 
       
  1569 
       
  1570 }, '3.0.0' ,{requires:['dom-base', 'selector-css2', 'event-base']});
       
  1571 YUI.add('node-style', function(Y) {
       
  1572 
       
  1573 (function(Y) {
       
  1574 /**
       
  1575  * Extended Node interface for managing node styles.
       
  1576  * @module node
       
  1577  * @submodule node-style
       
  1578  */
       
  1579 
       
  1580 var methods = [
       
  1581     /**
       
  1582      * Returns the style's current value.
       
  1583      * @method getStyle
       
  1584      * @for Node
       
  1585      * @param {String} attr The style attribute to retrieve. 
       
  1586      * @return {String} The current value of the style property for the element.
       
  1587      */
       
  1588     'getStyle',
       
  1589 
       
  1590     /**
       
  1591      * Returns the computed value for the given style property.
       
  1592      * @method getComputedStyle
       
  1593      * @param {String} attr The style attribute to retrieve. 
       
  1594      * @return {String} The computed value of the style property for the element.
       
  1595      */
       
  1596     'getComputedStyle',
       
  1597 
       
  1598     /**
       
  1599      * Sets a style property of the node.
       
  1600      * @method setStyle
       
  1601      * @param {String} attr The style attribute to set. 
       
  1602      * @param {String|Number} val The value. 
       
  1603      * @chainable
       
  1604      */
       
  1605     'setStyle',
       
  1606 
       
  1607     /**
       
  1608      * Sets multiple style properties on the node.
       
  1609      * @method setStyles
       
  1610      * @param {Object} hash An object literal of property:value pairs. 
       
  1611      * @chainable
       
  1612      */
       
  1613     'setStyles'
       
  1614 ];
       
  1615 Y.Node.importMethod(Y.DOM, methods);
       
  1616 /**
       
  1617  * Returns an array of values for each node.
       
  1618  * @method getStyle
       
  1619  * @for NodeList
       
  1620  * @see Node.getStyle
       
  1621  * @param {String} attr The style attribute to retrieve. 
       
  1622  * @return {Array} The current values of the style property for the element.
       
  1623  */
       
  1624 
       
  1625 /**
       
  1626  * Returns an array of the computed value for each node.
       
  1627  * @method getComputedStyle
       
  1628  * @see Node.getComputedStyle
       
  1629  * @param {String} attr The style attribute to retrieve. 
       
  1630  * @return {Array} The computed values for each node.
       
  1631  */
       
  1632 
       
  1633 /**
       
  1634  * Sets a style property on each node.
       
  1635  * @method setStyle
       
  1636  * @see Node.setStyle
       
  1637  * @param {String} attr The style attribute to set. 
       
  1638  * @param {String|Number} val The value. 
       
  1639  * @chainable
       
  1640  */
       
  1641 
       
  1642 /**
       
  1643  * Sets multiple style properties on each node.
       
  1644  * @method setStyles
       
  1645  * @see Node.setStyles
       
  1646  * @param {Object} hash An object literal of property:value pairs. 
       
  1647  * @chainable
       
  1648  */
       
  1649 Y.NodeList.importMethod(Y.Node.prototype, methods);
       
  1650 })(Y);
       
  1651 
       
  1652 
       
  1653 }, '3.0.0' ,{requires:['dom-style', 'node-base']});
       
  1654 YUI.add('node-screen', function(Y) {
       
  1655 
       
  1656 /**
       
  1657  * Extended Node interface for managing regions and screen positioning.
       
  1658  * Adds support for positioning elements and normalizes window size and scroll detection. 
       
  1659  * @module node
       
  1660  * @submodule node-screen
       
  1661  */
       
  1662 
       
  1663 // these are all "safe" returns, no wrapping required
       
  1664 Y.each([
       
  1665     /**
       
  1666      * Returns the inner width of the viewport (exludes scrollbar). 
       
  1667      * @config winWidth
       
  1668      * @for Node
       
  1669      * @type {Int}
       
  1670      */
       
  1671     'winWidth',
       
  1672 
       
  1673     /**
       
  1674      * Returns the inner height of the viewport (exludes scrollbar). 
       
  1675      * @config winHeight
       
  1676      * @type {Int}
       
  1677      */
       
  1678     'winHeight',
       
  1679 
       
  1680     /**
       
  1681      * Document width 
       
  1682      * @config winHeight
       
  1683      * @type {Int}
       
  1684      */
       
  1685     'docWidth',
       
  1686 
       
  1687     /**
       
  1688      * Document height 
       
  1689      * @config docHeight
       
  1690      * @type {Int}
       
  1691      */
       
  1692     'docHeight',
       
  1693 
       
  1694     /**
       
  1695      * Amount page has been scroll vertically 
       
  1696      * @config docScrollX
       
  1697      * @type {Int}
       
  1698      */
       
  1699     'docScrollX',
       
  1700 
       
  1701     /**
       
  1702      * Amount page has been scroll horizontally 
       
  1703      * @config docScrollY
       
  1704      * @type {Int}
       
  1705      */
       
  1706     'docScrollY'
       
  1707     ],
       
  1708     function(name) {
       
  1709         Y.Node.ATTRS[name] = {
       
  1710             getter: function() {
       
  1711                 var args = Array.prototype.slice.call(arguments);
       
  1712                 args.unshift(Y.Node.getDOMNode(this));
       
  1713 
       
  1714                 return Y.DOM[name].apply(this, args);
       
  1715             }
       
  1716         };
       
  1717     }
       
  1718 );
       
  1719 
       
  1720 Y.Node.ATTRS.scrollLeft = {
       
  1721     getter: function() {
       
  1722         var node = Y.Node.getDOMNode(this);
       
  1723         return ('scrollLeft' in node) ? node.scrollLeft : Y.DOM.docScrollX(node);
       
  1724     },
       
  1725 
       
  1726     setter: function(val) {
       
  1727         var node = Y.Node.getDOMNode(this);
       
  1728         if (node) {
       
  1729             if ('scrollLeft' in node) {
       
  1730                 node.scrollLeft = val;
       
  1731             } else if (node.document || node.nodeType === 9) {
       
  1732                 Y.DOM._getWin(node).scrollTo(val, Y.DOM.docScrollY(node)); // scroll window if win or doc
       
  1733             }
       
  1734         } else {
       
  1735             Y.log('unable to set scrollLeft for ' + node, 'error', 'Node');
       
  1736         }
       
  1737     }
       
  1738 };
       
  1739 
       
  1740 Y.Node.ATTRS.scrollTop = {
       
  1741     getter: function() {
       
  1742         var node = Y.Node.getDOMNode(this);
       
  1743         return ('scrollTop' in node) ? node.scrollTop : Y.DOM.docScrollY(node);
       
  1744     },
       
  1745 
       
  1746     setter: function(val) {
       
  1747         var node = Y.Node.getDOMNode(this);
       
  1748         if (node) {
       
  1749             if ('scrollTop' in node) {
       
  1750                 node.scrollTop = val;
       
  1751             } else if (node.document || node.nodeType === 9) {
       
  1752                 Y.DOM._getWin(node).scrollTo(Y.DOM.docScrollX(node), val); // scroll window if win or doc
       
  1753             }
       
  1754         } else {
       
  1755             Y.log('unable to set scrollTop for ' + node, 'error', 'Node');
       
  1756         }
       
  1757     }
       
  1758 };
       
  1759 
       
  1760 Y.Node.importMethod(Y.DOM, [
       
  1761 /**
       
  1762  * Gets the current position of the node in page coordinates. 
       
  1763  * @method getXY
       
  1764  * @for Node
       
  1765  * @return {Array} The XY position of the node
       
  1766 */
       
  1767     'getXY',
       
  1768 
       
  1769 /**
       
  1770  * Set the position of the node in page coordinates, regardless of how the node is positioned.
       
  1771  * @method setXY
       
  1772  * @param {Array} xy Contains X & Y values for new position (coordinates are page-based)
       
  1773  * @chainable
       
  1774  */
       
  1775     'setXY',
       
  1776 
       
  1777 /**
       
  1778  * Gets the current position of the node in page coordinates. 
       
  1779  * @method getX
       
  1780  * @return {Int} The X position of the node
       
  1781 */
       
  1782     'getX',
       
  1783 
       
  1784 /**
       
  1785  * Set the position of the node in page coordinates, regardless of how the node is positioned.
       
  1786  * @method setX
       
  1787  * @param {Int} x X value for new position (coordinates are page-based)
       
  1788  * @chainable
       
  1789  */
       
  1790     'setX',
       
  1791 
       
  1792 /**
       
  1793  * Gets the current position of the node in page coordinates. 
       
  1794  * @method getY
       
  1795  * @return {Int} The Y position of the node
       
  1796 */
       
  1797     'getY',
       
  1798 
       
  1799 /**
       
  1800  * Set the position of the node in page coordinates, regardless of how the node is positioned.
       
  1801  * @method setY
       
  1802  * @param {Int} y Y value for new position (coordinates are page-based)
       
  1803  * @chainable
       
  1804  */
       
  1805     'setY'
       
  1806 ]);
       
  1807 
       
  1808 /**
       
  1809  * Returns a region object for the node 
       
  1810  * @config region
       
  1811  * @for Node
       
  1812  * @type Node
       
  1813  */
       
  1814 Y.Node.ATTRS.region = {
       
  1815     getter: function() {
       
  1816         var node = Y.Node.getDOMNode(this);
       
  1817         if (node && !node.tagName) {
       
  1818             if (node.nodeType === 9) { // document
       
  1819                 node = node.documentElement;
       
  1820             } else if (node.alert) { // window
       
  1821                 node = node.document.documentElement;
       
  1822             }
       
  1823         }
       
  1824         return Y.DOM.region(node);
       
  1825     }
       
  1826 };
       
  1827     
       
  1828 /**
       
  1829  * Returns a region object for the node's viewport 
       
  1830  * @config viewportRegion
       
  1831  * @type Node
       
  1832  */
       
  1833 Y.Node.ATTRS.viewportRegion = {
       
  1834     getter: function() {
       
  1835         return Y.DOM.viewportRegion(Y.Node.getDOMNode(this));
       
  1836     }
       
  1837 };
       
  1838 
       
  1839 Y.Node.importMethod(Y.DOM, 'inViewportRegion');
       
  1840 
       
  1841 // these need special treatment to extract 2nd node arg
       
  1842 /**
       
  1843  * Compares the intersection of the node with another node or region 
       
  1844  * @method intersect         
       
  1845  * @for Node
       
  1846  * @param {Node|Object} node2 The node or region to compare with.
       
  1847  * @param {Object} altRegion An alternate region to use (rather than this node's). 
       
  1848  * @return {Object} An object representing the intersection of the regions. 
       
  1849  */
       
  1850 Y.Node.prototype.intersect = function(node2, altRegion) {
       
  1851     var node1 = Y.Node.getDOMNode(this);
       
  1852     if (node2 instanceof Y.Node) { // might be a region object
       
  1853         node2 = Y.Node.getDOMNode(node2);
       
  1854     }
       
  1855     return Y.DOM.intersect(node1, node2, altRegion); 
       
  1856 };
       
  1857 
       
  1858 /**
       
  1859  * Determines whether or not the node is within the giving region.
       
  1860  * @method inRegion         
       
  1861  * @param {Node|Object} node2 The node or region to compare with.
       
  1862  * @param {Boolean} all Whether or not all of the node must be in the region. 
       
  1863  * @param {Object} altRegion An alternate region to use (rather than this node's). 
       
  1864  * @return {Object} An object representing the intersection of the regions. 
       
  1865  */
       
  1866 Y.Node.prototype.inRegion = function(node2, all, altRegion) {
       
  1867     var node1 = Y.Node.getDOMNode(this);
       
  1868     if (node2 instanceof Y.Node) { // might be a region object
       
  1869         node2 = Y.Node.getDOMNode(node2);
       
  1870     }
       
  1871     return Y.DOM.inRegion(node1, node2, all, altRegion); 
       
  1872 };
       
  1873 
       
  1874 
       
  1875 }, '3.0.0' ,{requires:['dom-screen']});
       
  1876 YUI.add('node-pluginhost', function(Y) {
       
  1877 
       
  1878 /**
       
  1879  * Registers plugins to be instantiated at the class level (plugins 
       
  1880  * which should be plugged into every instance of Node by default).
       
  1881  *
       
  1882  * @method Node.plug
       
  1883  * @static
       
  1884  *
       
  1885  * @param {Function | Array} plugin Either the plugin class, an array of plugin classes or an array of objects (with fn and cfg properties defined)
       
  1886  * @param {Object} config (Optional) If plugin is the plugin class, the configuration for the plugin
       
  1887  */
       
  1888 Y.Node.plug = function() {
       
  1889     var args = Y.Array(arguments);
       
  1890     args.unshift(Y.Node);
       
  1891     Y.Plugin.Host.plug.apply(Y.Base, args);
       
  1892     return Y.Node;
       
  1893 };
       
  1894 
       
  1895 /**
       
  1896  * Unregisters any class level plugins which have been registered by the Node
       
  1897  *
       
  1898  * @method Node.unplug
       
  1899  * @static
       
  1900  *
       
  1901  * @param {Function | Array} plugin The plugin class, or an array of plugin classes
       
  1902  */
       
  1903 Y.Node.unplug = function() {
       
  1904     var args = Y.Array(arguments);
       
  1905     args.unshift(Y.Node);
       
  1906     Y.Plugin.Host.unplug.apply(Y.Base, args);
       
  1907     return Y.Node;
       
  1908 };
       
  1909 
       
  1910 Y.mix(Y.Node, Y.Plugin.Host, false, null, 1);
       
  1911 
       
  1912 // allow batching of plug/unplug via NodeList
       
  1913 // doesn't use NodeList.importMethod because we need real Nodes (not tmpNode)
       
  1914 Y.NodeList.prototype.plug = function() {
       
  1915     var args = arguments;
       
  1916     Y.NodeList.each(this, function(node) {
       
  1917         Y.Node.prototype.plug.apply(Y.one(node), args);
       
  1918     });
       
  1919 };
       
  1920 
       
  1921 Y.NodeList.prototype.unplug = function() {
       
  1922     var args = arguments;
       
  1923     Y.NodeList.each(this, function(node) {
       
  1924         Y.Node.prototype.unplug.apply(Y.one(node), args);
       
  1925     });
       
  1926 };
       
  1927 
       
  1928 
       
  1929 }, '3.0.0' ,{requires:['node-base', 'pluginhost']});
       
  1930 YUI.add('node-event-delegate', function(Y) {
       
  1931 
       
  1932 /**
       
  1933  * Functionality to make the node a delegated event container
       
  1934  * @module node
       
  1935  * @submodule node-event-delegate
       
  1936  */
       
  1937 
       
  1938 /**
       
  1939  * Functionality to make the node a delegated event container
       
  1940  * @method delegate
       
  1941  * @param type {String} the event type to delegate
       
  1942  * @param fn {Function} the function to execute
       
  1943  * @param selector {String} a selector that must match the target of the event.
       
  1944  * @return {Event.Handle} the detach handle
       
  1945  * @for Node
       
  1946  */
       
  1947 Y.Node.prototype.delegate = function(type, fn, selector) {
       
  1948 
       
  1949     var args = Array.prototype.slice.call(arguments, 3),
       
  1950         a = [type, fn, Y.Node.getDOMNode(this), selector];
       
  1951     a = a.concat(args);
       
  1952 
       
  1953     return Y.delegate.apply(Y, a);
       
  1954 };
       
  1955 
       
  1956 
       
  1957 }, '3.0.0' ,{requires:['node-base', 'event-delegate', 'pluginhost']});
       
  1958 
       
  1959 
       
  1960 YUI.add('node', function(Y){}, '3.0.0' ,{skinnable:false, use:['node-base', 'node-style', 'node-screen', 'node-pluginhost', 'node-event-delegate'], requires:['dom', 'event-base', 'event-delegate', 'pluginhost']});
       
  1961