src/cm/media/js/lib/yui/yui_3.10.3/build/node-base/node-base.js
changeset 525 89ef5ed3c48b
equal deleted inserted replaced
524:322d0feea350 525:89ef5ed3c48b
       
     1 /*
       
     2 YUI 3.10.3 (build 2fb5187)
       
     3 Copyright 2013 Yahoo! Inc. All rights reserved.
       
     4 Licensed under the BSD License.
       
     5 http://yuilibrary.com/license/
       
     6 */
       
     7 
       
     8 YUI.add('node-base', function (Y, NAME) {
       
     9 
       
    10 /**
       
    11  * @module node
       
    12  * @submodule node-base
       
    13  */
       
    14 
       
    15 var methods = [
       
    16 /**
       
    17  * Determines whether each node has the given className.
       
    18  * @method hasClass
       
    19  * @for Node
       
    20  * @param {String} className the class name to search for
       
    21  * @return {Boolean} Whether or not the element has the specified class
       
    22  */
       
    23  'hasClass',
       
    24 
       
    25 /**
       
    26  * Adds a class name to each node.
       
    27  * @method addClass
       
    28  * @param {String} className the class name to add to the node's class attribute
       
    29  * @chainable
       
    30  */
       
    31  'addClass',
       
    32 
       
    33 /**
       
    34  * Removes a class name from each node.
       
    35  * @method removeClass
       
    36  * @param {String} className the class name to remove from the node's class attribute
       
    37  * @chainable
       
    38  */
       
    39  'removeClass',
       
    40 
       
    41 /**
       
    42  * Replace a class with another class for each node.
       
    43  * If no oldClassName is present, the newClassName is simply added.
       
    44  * @method replaceClass
       
    45  * @param {String} oldClassName the class name to be replaced
       
    46  * @param {String} newClassName the class name that will be replacing the old class name
       
    47  * @chainable
       
    48  */
       
    49  'replaceClass',
       
    50 
       
    51 /**
       
    52  * If the className exists on the node it is removed, if it doesn't exist it is added.
       
    53  * @method toggleClass
       
    54  * @param {String} className the class name to be toggled
       
    55  * @param {Boolean} force Option to force adding or removing the class.
       
    56  * @chainable
       
    57  */
       
    58  'toggleClass'
       
    59 ];
       
    60 
       
    61 Y.Node.importMethod(Y.DOM, methods);
       
    62 /**
       
    63  * Determines whether each node has the given className.
       
    64  * @method hasClass
       
    65  * @see Node.hasClass
       
    66  * @for NodeList
       
    67  * @param {String} className the class name to search for
       
    68  * @return {Array} An array of booleans for each node bound to the NodeList.
       
    69  */
       
    70 
       
    71 /**
       
    72  * Adds a class name to each node.
       
    73  * @method addClass
       
    74  * @see Node.addClass
       
    75  * @param {String} className the class name to add to the node's class attribute
       
    76  * @chainable
       
    77  */
       
    78 
       
    79 /**
       
    80  * Removes a class name from each node.
       
    81  * @method removeClass
       
    82  * @see Node.removeClass
       
    83  * @param {String} className the class name to remove from the node's class attribute
       
    84  * @chainable
       
    85  */
       
    86 
       
    87 /**
       
    88  * Replace a class with another class for each node.
       
    89  * If no oldClassName is present, the newClassName is simply added.
       
    90  * @method replaceClass
       
    91  * @see Node.replaceClass
       
    92  * @param {String} oldClassName the class name to be replaced
       
    93  * @param {String} newClassName the class name that will be replacing the old class name
       
    94  * @chainable
       
    95  */
       
    96 
       
    97 /**
       
    98  * If the className exists on the node it is removed, if it doesn't exist it is added.
       
    99  * @method toggleClass
       
   100  * @see Node.toggleClass
       
   101  * @param {String} className the class name to be toggled
       
   102  * @chainable
       
   103  */
       
   104 Y.NodeList.importMethod(Y.Node.prototype, methods);
       
   105 /**
       
   106  * @module node
       
   107  * @submodule node-base
       
   108  */
       
   109 
       
   110 var Y_Node = Y.Node,
       
   111     Y_DOM = Y.DOM;
       
   112 
       
   113 /**
       
   114  * Returns a new dom node using the provided markup string.
       
   115  * @method create
       
   116  * @static
       
   117  * @param {String} html The markup used to create the element
       
   118  * Use <a href="../classes/Escape.html#method_html">`Y.Escape.html()`</a>
       
   119  * to escape html content.
       
   120  * @param {HTMLDocument} doc An optional document context
       
   121  * @return {Node} A Node instance bound to a DOM node or fragment
       
   122  * @for Node
       
   123  */
       
   124 Y_Node.create = function(html, doc) {
       
   125     if (doc && doc._node) {
       
   126         doc = doc._node;
       
   127     }
       
   128     return Y.one(Y_DOM.create(html, doc));
       
   129 };
       
   130 
       
   131 Y.mix(Y_Node.prototype, {
       
   132     /**
       
   133      * Creates a new Node using the provided markup string.
       
   134      * @method create
       
   135      * @param {String} html The markup used to create the element.
       
   136      * Use <a href="../classes/Escape.html#method_html">`Y.Escape.html()`</a>
       
   137      * to escape html content.
       
   138      * @param {HTMLDocument} doc An optional document context
       
   139      * @return {Node} A Node instance bound to a DOM node or fragment
       
   140      */
       
   141     create: Y_Node.create,
       
   142 
       
   143     /**
       
   144      * Inserts the content before the reference node.
       
   145      * @method insert
       
   146      * @param {String | Node | HTMLElement | NodeList | HTMLCollection} content The content to insert
       
   147      * Use <a href="../classes/Escape.html#method_html">`Y.Escape.html()`</a>
       
   148      * to escape html content.
       
   149      * @param {Int | Node | HTMLElement | String} where The position to insert at.
       
   150      * Possible "where" arguments
       
   151      * <dl>
       
   152      * <dt>Y.Node</dt>
       
   153      * <dd>The Node to insert before</dd>
       
   154      * <dt>HTMLElement</dt>
       
   155      * <dd>The element to insert before</dd>
       
   156      * <dt>Int</dt>
       
   157      * <dd>The index of the child element to insert before</dd>
       
   158      * <dt>"replace"</dt>
       
   159      * <dd>Replaces the existing HTML</dd>
       
   160      * <dt>"before"</dt>
       
   161      * <dd>Inserts before the existing HTML</dd>
       
   162      * <dt>"before"</dt>
       
   163      * <dd>Inserts content before the node</dd>
       
   164      * <dt>"after"</dt>
       
   165      * <dd>Inserts content after the node</dd>
       
   166      * </dl>
       
   167      * @chainable
       
   168      */
       
   169     insert: function(content, where) {
       
   170         this._insert(content, where);
       
   171         return this;
       
   172     },
       
   173 
       
   174     _insert: function(content, where) {
       
   175         var node = this._node,
       
   176             ret = null;
       
   177 
       
   178         if (typeof where == 'number') { // allow index
       
   179             where = this._node.childNodes[where];
       
   180         } else if (where && where._node) { // Node
       
   181             where = where._node;
       
   182         }
       
   183 
       
   184         if (content && typeof content != 'string') { // allow Node or NodeList/Array instances
       
   185             content = content._node || content._nodes || content;
       
   186         }
       
   187         ret = Y_DOM.addHTML(node, content, where);
       
   188 
       
   189         return ret;
       
   190     },
       
   191 
       
   192     /**
       
   193      * Inserts the content as the firstChild of the node.
       
   194      * @method prepend
       
   195      * @param {String | Node | HTMLElement} content The content to insert
       
   196      * Use <a href="../classes/Escape.html#method_html">`Y.Escape.html()`</a>
       
   197      * to escape html content.
       
   198      * @chainable
       
   199      */
       
   200     prepend: function(content) {
       
   201         return this.insert(content, 0);
       
   202     },
       
   203 
       
   204     /**
       
   205      * Inserts the content as the lastChild of the node.
       
   206      * @method append
       
   207      * @param {String | Node | HTMLElement} content The content to insert
       
   208      * Use <a href="../classes/Escape.html#method_html">`Y.Escape.html()`</a>
       
   209      * to escape html content.
       
   210      * @chainable
       
   211      */
       
   212     append: function(content) {
       
   213         return this.insert(content, null);
       
   214     },
       
   215 
       
   216     /**
       
   217      * @method appendChild
       
   218      * @param {String | HTMLElement | Node} node Node to be appended
       
   219      * Use <a href="../classes/Escape.html#method_html">`Y.Escape.html()`</a>
       
   220      * to escape html content.
       
   221      * @return {Node} The appended node
       
   222      */
       
   223     appendChild: function(node) {
       
   224         return Y_Node.scrubVal(this._insert(node));
       
   225     },
       
   226 
       
   227     /**
       
   228      * @method insertBefore
       
   229      * @param {String | HTMLElement | Node} newNode Node to be appended
       
   230      * @param {HTMLElement | Node} refNode Node to be inserted before
       
   231      * Use <a href="../classes/Escape.html#method_html">`Y.Escape.html()`</a>
       
   232      * to escape html content.
       
   233      * @return {Node} The inserted node
       
   234      */
       
   235     insertBefore: function(newNode, refNode) {
       
   236         return Y.Node.scrubVal(this._insert(newNode, refNode));
       
   237     },
       
   238 
       
   239     /**
       
   240      * Appends the node to the given node.
       
   241      * @method appendTo
       
   242      * @param {Node | HTMLElement} node The node to append to
       
   243      * @chainable
       
   244      */
       
   245     appendTo: function(node) {
       
   246         Y.one(node).append(this);
       
   247         return this;
       
   248     },
       
   249 
       
   250     /**
       
   251      * Replaces the node's current content with the content.
       
   252      * Note that this passes to innerHTML and is not escaped.
       
   253      * Use <a href="../classes/Escape.html#method_html">`Y.Escape.html()`</a>
       
   254      * to escape html content or `set('text')` to add as text.
       
   255      * @method setContent
       
   256      * @deprecated Use setHTML
       
   257      * @param {String | Node | HTMLElement | NodeList | HTMLCollection} content The content to insert
       
   258      * @chainable
       
   259      */
       
   260     setContent: function(content) {
       
   261         this._insert(content, 'replace');
       
   262         return this;
       
   263     },
       
   264 
       
   265     /**
       
   266      * Returns the node's current content (e.g. innerHTML)
       
   267      * @method getContent
       
   268      * @deprecated Use getHTML
       
   269      * @return {String} The current content
       
   270      */
       
   271     getContent: function(content) {
       
   272         return this.get('innerHTML');
       
   273     }
       
   274 });
       
   275 
       
   276 /**
       
   277  * Replaces the node's current html content with the content provided.
       
   278  * Note that this passes to innerHTML and is not escaped.
       
   279  * Use `Y.Escape.html()` to escape HTML, or `set('text')` to add as text.
       
   280  * @method setHTML
       
   281  * @param {String | HTML | Node | HTMLElement | NodeList | HTMLCollection} content The content to insert
       
   282  * @chainable
       
   283  */
       
   284 Y.Node.prototype.setHTML = Y.Node.prototype.setContent;
       
   285 
       
   286 /**
       
   287  * Returns the node's current html content (e.g. innerHTML)
       
   288  * @method getHTML
       
   289  * @return {String} The html content
       
   290  */
       
   291 Y.Node.prototype.getHTML = Y.Node.prototype.getContent;
       
   292 
       
   293 Y.NodeList.importMethod(Y.Node.prototype, [
       
   294     /**
       
   295      * Called on each Node instance
       
   296      * @for NodeList
       
   297      * @method append
       
   298      * @see Node.append
       
   299      */
       
   300     'append',
       
   301 
       
   302     /**
       
   303      * Called on each Node instance
       
   304      * @for NodeList
       
   305      * @method insert
       
   306      * @see Node.insert
       
   307      */
       
   308     'insert',
       
   309 
       
   310     /**
       
   311      * Called on each Node instance
       
   312      * @for NodeList
       
   313      * @method appendChild
       
   314      * @see Node.appendChild
       
   315      */
       
   316     'appendChild',
       
   317 
       
   318     /**
       
   319      * Called on each Node instance
       
   320      * @for NodeList
       
   321      * @method insertBefore
       
   322      * @see Node.insertBefore
       
   323      */
       
   324     'insertBefore',
       
   325 
       
   326     /**
       
   327      * Called on each Node instance
       
   328      * @for NodeList
       
   329      * @method prepend
       
   330      * @see Node.prepend
       
   331      */
       
   332     'prepend',
       
   333 
       
   334     /**
       
   335      * Called on each Node instance
       
   336      * Note that this passes to innerHTML and is not escaped.
       
   337      * Use `Y.Escape.html()` to escape HTML, or `set('text')` to add as text.
       
   338      * @for NodeList
       
   339      * @method setContent
       
   340      * @deprecated Use setHTML
       
   341      */
       
   342     'setContent',
       
   343 
       
   344     /**
       
   345      * Called on each Node instance
       
   346      * @for NodeList
       
   347      * @method getContent
       
   348      * @deprecated Use getHTML
       
   349      */
       
   350     'getContent',
       
   351 
       
   352     /**
       
   353      * Called on each Node instance
       
   354      * Note that this passes to innerHTML and is not escaped.
       
   355      * Use `Y.Escape.html()` to escape HTML, or `set('text')` to add as text.
       
   356      * @for NodeList
       
   357      * @method setHTML
       
   358      * @see Node.setHTML
       
   359      */
       
   360     'setHTML',
       
   361 
       
   362     /**
       
   363      * Called on each Node instance
       
   364      * @for NodeList
       
   365      * @method getHTML
       
   366      * @see Node.getHTML
       
   367      */
       
   368     'getHTML'
       
   369 ]);
       
   370 /**
       
   371  * @module node
       
   372  * @submodule node-base
       
   373  */
       
   374 
       
   375 var Y_Node = Y.Node,
       
   376     Y_DOM = Y.DOM;
       
   377 
       
   378 /**
       
   379  * Static collection of configuration attributes for special handling
       
   380  * @property ATTRS
       
   381  * @static
       
   382  * @type object
       
   383  */
       
   384 Y_Node.ATTRS = {
       
   385     /**
       
   386      * Allows for getting and setting the text of an element.
       
   387      * Formatting is preserved and special characters are treated literally.
       
   388      * @config text
       
   389      * @type String
       
   390      */
       
   391     text: {
       
   392         getter: function() {
       
   393             return Y_DOM.getText(this._node);
       
   394         },
       
   395 
       
   396         setter: function(content) {
       
   397             Y_DOM.setText(this._node, content);
       
   398             return content;
       
   399         }
       
   400     },
       
   401 
       
   402     /**
       
   403      * Allows for getting and setting the text of an element.
       
   404      * Formatting is preserved and special characters are treated literally.
       
   405      * @config for
       
   406      * @type String
       
   407      */
       
   408     'for': {
       
   409         getter: function() {
       
   410             return Y_DOM.getAttribute(this._node, 'for');
       
   411         },
       
   412 
       
   413         setter: function(val) {
       
   414             Y_DOM.setAttribute(this._node, 'for', val);
       
   415             return val;
       
   416         }
       
   417     },
       
   418 
       
   419     'options': {
       
   420         getter: function() {
       
   421             return this._node.getElementsByTagName('option');
       
   422         }
       
   423     },
       
   424 
       
   425     /**
       
   426      * Returns a NodeList instance of all HTMLElement children.
       
   427      * @readOnly
       
   428      * @config children
       
   429      * @type NodeList
       
   430      */
       
   431     'children': {
       
   432         getter: function() {
       
   433             var node = this._node,
       
   434                 children = node.children,
       
   435                 childNodes, i, len;
       
   436 
       
   437             if (!children) {
       
   438                 childNodes = node.childNodes;
       
   439                 children = [];
       
   440 
       
   441                 for (i = 0, len = childNodes.length; i < len; ++i) {
       
   442                     if (childNodes[i].tagName) {
       
   443                         children[children.length] = childNodes[i];
       
   444                     }
       
   445                 }
       
   446             }
       
   447             return Y.all(children);
       
   448         }
       
   449     },
       
   450 
       
   451     value: {
       
   452         getter: function() {
       
   453             return Y_DOM.getValue(this._node);
       
   454         },
       
   455 
       
   456         setter: function(val) {
       
   457             Y_DOM.setValue(this._node, val);
       
   458             return val;
       
   459         }
       
   460     }
       
   461 };
       
   462 
       
   463 Y.Node.importMethod(Y.DOM, [
       
   464     /**
       
   465      * Allows setting attributes on DOM nodes, normalizing in some cases.
       
   466      * This passes through to the DOM node, allowing for custom attributes.
       
   467      * @method setAttribute
       
   468      * @for Node
       
   469      * @for NodeList
       
   470      * @chainable
       
   471      * @param {string} name The attribute name
       
   472      * @param {string} value The value to set
       
   473      */
       
   474     'setAttribute',
       
   475     /**
       
   476      * Allows getting attributes on DOM nodes, normalizing in some cases.
       
   477      * This passes through to the DOM node, allowing for custom attributes.
       
   478      * @method getAttribute
       
   479      * @for Node
       
   480      * @for NodeList
       
   481      * @param {string} name The attribute name
       
   482      * @return {string} The attribute value
       
   483      */
       
   484     'getAttribute'
       
   485 
       
   486 ]);
       
   487 /**
       
   488  * @module node
       
   489  * @submodule node-base
       
   490  */
       
   491 
       
   492 var Y_Node = Y.Node;
       
   493 var Y_NodeList = Y.NodeList;
       
   494 /**
       
   495  * List of events that route to DOM events
       
   496  * @static
       
   497  * @property DOM_EVENTS
       
   498  * @for Node
       
   499  */
       
   500 
       
   501 Y_Node.DOM_EVENTS = {
       
   502     abort: 1,
       
   503     beforeunload: 1,
       
   504     blur: 1,
       
   505     change: 1,
       
   506     click: 1,
       
   507     close: 1,
       
   508     command: 1,
       
   509     contextmenu: 1,
       
   510     dblclick: 1,
       
   511     DOMMouseScroll: 1,
       
   512     drag: 1,
       
   513     dragstart: 1,
       
   514     dragenter: 1,
       
   515     dragover: 1,
       
   516     dragleave: 1,
       
   517     dragend: 1,
       
   518     drop: 1,
       
   519     error: 1,
       
   520     focus: 1,
       
   521     key: 1,
       
   522     keydown: 1,
       
   523     keypress: 1,
       
   524     keyup: 1,
       
   525     load: 1,
       
   526     message: 1,
       
   527     mousedown: 1,
       
   528     mouseenter: 1,
       
   529     mouseleave: 1,
       
   530     mousemove: 1,
       
   531     mousemultiwheel: 1,
       
   532     mouseout: 1,
       
   533     mouseover: 1,
       
   534     mouseup: 1,
       
   535     mousewheel: 1,
       
   536     orientationchange: 1,
       
   537     reset: 1,
       
   538     resize: 1,
       
   539     select: 1,
       
   540     selectstart: 1,
       
   541     submit: 1,
       
   542     scroll: 1,
       
   543     textInput: 1,
       
   544     unload: 1
       
   545 };
       
   546 
       
   547 // Add custom event adaptors to this list.  This will make it so
       
   548 // that delegate, key, available, contentready, etc all will
       
   549 // be available through Node.on
       
   550 Y.mix(Y_Node.DOM_EVENTS, Y.Env.evt.plugins);
       
   551 
       
   552 Y.augment(Y_Node, Y.EventTarget);
       
   553 
       
   554 Y.mix(Y_Node.prototype, {
       
   555     /**
       
   556      * Removes event listeners from the node and (optionally) its subtree
       
   557      * @method purge
       
   558      * @param {Boolean} recurse (optional) Whether or not to remove listeners from the
       
   559      * node's subtree
       
   560      * @param {String} type (optional) Only remove listeners of the specified type
       
   561      * @chainable
       
   562      *
       
   563      */
       
   564     purge: function(recurse, type) {
       
   565         Y.Event.purgeElement(this._node, recurse, type);
       
   566         return this;
       
   567     }
       
   568 
       
   569 });
       
   570 
       
   571 Y.mix(Y.NodeList.prototype, {
       
   572     _prepEvtArgs: function(type, fn, context) {
       
   573         // map to Y.on/after signature (type, fn, nodes, context, arg1, arg2, etc)
       
   574         var args = Y.Array(arguments, 0, true);
       
   575 
       
   576         if (args.length < 2) { // type only (event hash) just add nodes
       
   577             args[2] = this._nodes;
       
   578         } else {
       
   579             args.splice(2, 0, this._nodes);
       
   580         }
       
   581 
       
   582         args[3] = context || this; // default to NodeList instance as context
       
   583 
       
   584         return args;
       
   585     },
       
   586 
       
   587     /**
       
   588     Subscribe a callback function for each `Node` in the collection to execute
       
   589     in response to a DOM event.
       
   590 
       
   591     NOTE: Generally, the `on()` method should be avoided on `NodeLists`, in
       
   592     favor of using event delegation from a parent Node.  See the Event user
       
   593     guide for details.
       
   594 
       
   595     Most DOM events are associated with a preventable default behavior, such as
       
   596     link clicks navigating to a new page.  Callbacks are passed a
       
   597     `DOMEventFacade` object as their first argument (usually called `e`) that
       
   598     can be used to prevent this default behavior with `e.preventDefault()`. See
       
   599     the `DOMEventFacade` API for all available properties and methods on the
       
   600     object.
       
   601 
       
   602     By default, the `this` object will be the `NodeList` that the subscription
       
   603     came from, <em>not the `Node` that received the event</em>.  Use
       
   604     `e.currentTarget` to refer to the `Node`.
       
   605 
       
   606     Returning `false` from a callback is supported as an alternative to calling
       
   607     `e.preventDefault(); e.stopPropagation();`.  However, it is recommended to
       
   608     use the event methods.
       
   609 
       
   610     @example
       
   611 
       
   612         Y.all(".sku").on("keydown", function (e) {
       
   613             if (e.keyCode === 13) {
       
   614                 e.preventDefault();
       
   615 
       
   616                 // Use e.currentTarget to refer to the individual Node
       
   617                 var item = Y.MyApp.searchInventory( e.currentTarget.get('value') );
       
   618                 // etc ...
       
   619             }
       
   620         });
       
   621 
       
   622     @method on
       
   623     @param {String} type The name of the event
       
   624     @param {Function} fn The callback to execute in response to the event
       
   625     @param {Object} [context] Override `this` object in callback
       
   626     @param {Any} [arg*] 0..n additional arguments to supply to the subscriber
       
   627     @return {EventHandle} A subscription handle capable of detaching that
       
   628                           subscription
       
   629     @for NodeList
       
   630     **/
       
   631     on: function(type, fn, context) {
       
   632         return Y.on.apply(Y, this._prepEvtArgs.apply(this, arguments));
       
   633     },
       
   634 
       
   635     /**
       
   636      * Applies an one-time event listener to each Node bound to the NodeList.
       
   637      * @method once
       
   638      * @param {String} type The event being listened for
       
   639      * @param {Function} fn The handler to call when the event fires
       
   640      * @param {Object} context The context to call the handler with.
       
   641      * Default is the NodeList instance.
       
   642      * @return {EventHandle} A subscription handle capable of detaching that
       
   643      *                    subscription
       
   644      * @for NodeList
       
   645      */
       
   646     once: function(type, fn, context) {
       
   647         return Y.once.apply(Y, this._prepEvtArgs.apply(this, arguments));
       
   648     },
       
   649 
       
   650     /**
       
   651      * Applies an event listener to each Node bound to the NodeList.
       
   652      * The handler is called only after all on() handlers are called
       
   653      * and the event is not prevented.
       
   654      * @method after
       
   655      * @param {String} type The event being listened for
       
   656      * @param {Function} fn The handler to call when the event fires
       
   657      * @param {Object} context The context to call the handler with.
       
   658      * Default is the NodeList instance.
       
   659      * @return {EventHandle} A subscription handle capable of detaching that
       
   660      *                    subscription
       
   661      * @for NodeList
       
   662      */
       
   663     after: function(type, fn, context) {
       
   664         return Y.after.apply(Y, this._prepEvtArgs.apply(this, arguments));
       
   665     },
       
   666 
       
   667     /**
       
   668      * Applies an one-time event listener to each Node bound to the NodeList
       
   669      * that will be called only after all on() handlers are called and the
       
   670      * event is not prevented.
       
   671      *
       
   672      * @method onceAfter
       
   673      * @param {String} type The event being listened for
       
   674      * @param {Function} fn The handler to call when the event fires
       
   675      * @param {Object} context The context to call the handler with.
       
   676      * Default is the NodeList instance.
       
   677      * @return {EventHandle} A subscription handle capable of detaching that
       
   678      *                    subscription
       
   679      * @for NodeList
       
   680      */
       
   681     onceAfter: function(type, fn, context) {
       
   682         return Y.onceAfter.apply(Y, this._prepEvtArgs.apply(this, arguments));
       
   683     }
       
   684 });
       
   685 
       
   686 Y_NodeList.importMethod(Y.Node.prototype, [
       
   687     /**
       
   688       * Called on each Node instance
       
   689       * @method detach
       
   690       * @see Node.detach
       
   691       * @for NodeList
       
   692       */
       
   693     'detach',
       
   694 
       
   695     /** Called on each Node instance
       
   696       * @method detachAll
       
   697       * @see Node.detachAll
       
   698       * @for NodeList
       
   699       */
       
   700     'detachAll'
       
   701 ]);
       
   702 
       
   703 /**
       
   704 Subscribe a callback function to execute in response to a DOM event or custom
       
   705 event.
       
   706 
       
   707 Most DOM events are associated with a preventable default behavior such as
       
   708 link clicks navigating to a new page.  Callbacks are passed a `DOMEventFacade`
       
   709 object as their first argument (usually called `e`) that can be used to
       
   710 prevent this default behavior with `e.preventDefault()`. See the
       
   711 `DOMEventFacade` API for all available properties and methods on the object.
       
   712 
       
   713 If the event name passed as the first parameter is not a whitelisted DOM event,
       
   714 it will be treated as a custom event subscriptions, allowing
       
   715 `node.fire('customEventName')` later in the code.  Refer to the Event user guide
       
   716 for the full DOM event whitelist.
       
   717 
       
   718 By default, the `this` object in the callback will refer to the subscribed
       
   719 `Node`.
       
   720 
       
   721 Returning `false` from a callback is supported as an alternative to calling
       
   722 `e.preventDefault(); e.stopPropagation();`.  However, it is recommended to use
       
   723 the event methods.
       
   724 
       
   725 @example
       
   726 
       
   727     Y.one("#my-form").on("submit", function (e) {
       
   728         e.preventDefault();
       
   729 
       
   730         // proceed with ajax form submission instead...
       
   731     });
       
   732 
       
   733 @method on
       
   734 @param {String} type The name of the event
       
   735 @param {Function} fn The callback to execute in response to the event
       
   736 @param {Object} [context] Override `this` object in callback
       
   737 @param {Any} [arg*] 0..n additional arguments to supply to the subscriber
       
   738 @return {EventHandle} A subscription handle capable of detaching that
       
   739                       subscription
       
   740 @for Node
       
   741 **/
       
   742 
       
   743 Y.mix(Y.Node.ATTRS, {
       
   744     offsetHeight: {
       
   745         setter: function(h) {
       
   746             Y.DOM.setHeight(this._node, h);
       
   747             return h;
       
   748         },
       
   749 
       
   750         getter: function() {
       
   751             return this._node.offsetHeight;
       
   752         }
       
   753     },
       
   754 
       
   755     offsetWidth: {
       
   756         setter: function(w) {
       
   757             Y.DOM.setWidth(this._node, w);
       
   758             return w;
       
   759         },
       
   760 
       
   761         getter: function() {
       
   762             return this._node.offsetWidth;
       
   763         }
       
   764     }
       
   765 });
       
   766 
       
   767 Y.mix(Y.Node.prototype, {
       
   768     sizeTo: function(w, h) {
       
   769         var node;
       
   770         if (arguments.length < 2) {
       
   771             node = Y.one(w);
       
   772             w = node.get('offsetWidth');
       
   773             h = node.get('offsetHeight');
       
   774         }
       
   775 
       
   776         this.setAttrs({
       
   777             offsetWidth: w,
       
   778             offsetHeight: h
       
   779         });
       
   780     }
       
   781 });
       
   782 /**
       
   783  * @module node
       
   784  * @submodule node-base
       
   785  */
       
   786 
       
   787 var Y_Node = Y.Node;
       
   788 
       
   789 Y.mix(Y_Node.prototype, {
       
   790     /**
       
   791      * Makes the node visible.
       
   792      * If the "transition" module is loaded, show optionally
       
   793      * animates the showing of the node using either the default
       
   794      * transition effect ('fadeIn'), or the given named effect.
       
   795      * @method show
       
   796      * @for Node
       
   797      * @param {String} name A named Transition effect to use as the show effect.
       
   798      * @param {Object} config Options to use with the transition.
       
   799      * @param {Function} callback An optional function to run after the transition completes.
       
   800      * @chainable
       
   801      */
       
   802     show: function(callback) {
       
   803         callback = arguments[arguments.length - 1];
       
   804         this.toggleView(true, callback);
       
   805         return this;
       
   806     },
       
   807 
       
   808     /**
       
   809      * The implementation for showing nodes.
       
   810      * Default is to remove the hidden attribute and reset the CSS style.display property.
       
   811      * @method _show
       
   812      * @protected
       
   813      * @chainable
       
   814      */
       
   815     _show: function() {
       
   816         this.removeAttribute('hidden');
       
   817 
       
   818         // For back-compat we need to leave this in for browsers that
       
   819         // do not visually hide a node via the hidden attribute
       
   820         // and for users that check visibility based on style display.
       
   821         this.setStyle('display', '');
       
   822 
       
   823     },
       
   824 
       
   825     _isHidden: function() {
       
   826         return Y.DOM.getAttribute(this._node, 'hidden') === 'true';
       
   827     },
       
   828 
       
   829     /**
       
   830      * Displays or hides the node.
       
   831      * If the "transition" module is loaded, toggleView optionally
       
   832      * animates the toggling of the node using given named effect.
       
   833      * @method toggleView
       
   834      * @for Node
       
   835      * @param {String} [name] An optional string value to use as transition effect.
       
   836      * @param {Boolean} [on] An optional boolean value to force the node to be shown or hidden
       
   837      * @param {Function} [callback] An optional function to run after the transition completes.
       
   838      * @chainable
       
   839      */
       
   840     toggleView: function(on, callback) {
       
   841         this._toggleView.apply(this, arguments);
       
   842         return this;
       
   843     },
       
   844 
       
   845     _toggleView: function(on, callback) {
       
   846         callback = arguments[arguments.length - 1];
       
   847 
       
   848         // base on current state if not forcing
       
   849         if (typeof on != 'boolean') {
       
   850             on = (this._isHidden()) ? 1 : 0;
       
   851         }
       
   852 
       
   853         if (on) {
       
   854             this._show();
       
   855         }  else {
       
   856             this._hide();
       
   857         }
       
   858 
       
   859         if (typeof callback == 'function') {
       
   860             callback.call(this);
       
   861         }
       
   862 
       
   863         return this;
       
   864     },
       
   865 
       
   866     /**
       
   867      * Hides the node.
       
   868      * If the "transition" module is loaded, hide optionally
       
   869      * animates the hiding of the node using either the default
       
   870      * transition effect ('fadeOut'), or the given named effect.
       
   871      * @method hide
       
   872      * @param {String} name A named Transition effect to use as the show effect.
       
   873      * @param {Object} config Options to use with the transition.
       
   874      * @param {Function} callback An optional function to run after the transition completes.
       
   875      * @chainable
       
   876      */
       
   877     hide: function(callback) {
       
   878         callback = arguments[arguments.length - 1];
       
   879         this.toggleView(false, callback);
       
   880         return this;
       
   881     },
       
   882 
       
   883     /**
       
   884      * The implementation for hiding nodes.
       
   885      * Default is to set the hidden attribute to true and set the CSS style.display to 'none'.
       
   886      * @method _hide
       
   887      * @protected
       
   888      * @chainable
       
   889      */
       
   890     _hide: function() {
       
   891         this.setAttribute('hidden', true);
       
   892 
       
   893         // For back-compat we need to leave this in for browsers that
       
   894         // do not visually hide a node via the hidden attribute
       
   895         // and for users that check visibility based on style display.
       
   896         this.setStyle('display', 'none');
       
   897     }
       
   898 });
       
   899 
       
   900 Y.NodeList.importMethod(Y.Node.prototype, [
       
   901     /**
       
   902      * Makes each node visible.
       
   903      * If the "transition" module is loaded, show optionally
       
   904      * animates the showing of the node using either the default
       
   905      * transition effect ('fadeIn'), or the given named effect.
       
   906      * @method show
       
   907      * @param {String} name A named Transition effect to use as the show effect.
       
   908      * @param {Object} config Options to use with the transition.
       
   909      * @param {Function} callback An optional function to run after the transition completes.
       
   910      * @for NodeList
       
   911      * @chainable
       
   912      */
       
   913     'show',
       
   914 
       
   915     /**
       
   916      * Hides each node.
       
   917      * If the "transition" module is loaded, hide optionally
       
   918      * animates the hiding of the node using either the default
       
   919      * transition effect ('fadeOut'), or the given named effect.
       
   920      * @method hide
       
   921      * @param {String} name A named Transition effect to use as the show effect.
       
   922      * @param {Object} config Options to use with the transition.
       
   923      * @param {Function} callback An optional function to run after the transition completes.
       
   924      * @chainable
       
   925      */
       
   926     'hide',
       
   927 
       
   928     /**
       
   929      * Displays or hides each node.
       
   930      * If the "transition" module is loaded, toggleView optionally
       
   931      * animates the toggling of the nodes using given named effect.
       
   932      * @method toggleView
       
   933      * @param {String} [name] An optional string value to use as transition effect.
       
   934      * @param {Boolean} [on] An optional boolean value to force the nodes to be shown or hidden
       
   935      * @param {Function} [callback] An optional function to run after the transition completes.
       
   936      * @chainable
       
   937      */
       
   938     'toggleView'
       
   939 ]);
       
   940 
       
   941 if (!Y.config.doc.documentElement.hasAttribute) { // IE < 8
       
   942     Y.Node.prototype.hasAttribute = function(attr) {
       
   943         if (attr === 'value') {
       
   944             if (this.get('value') !== "") { // IE < 8 fails to populate specified when set in HTML
       
   945                 return true;
       
   946             }
       
   947         }
       
   948         return !!(this._node.attributes[attr] &&
       
   949                 this._node.attributes[attr].specified);
       
   950     };
       
   951 }
       
   952 
       
   953 // IE throws an error when calling focus() on an element that's invisible, not
       
   954 // displayed, or disabled.
       
   955 Y.Node.prototype.focus = function () {
       
   956     try {
       
   957         this._node.focus();
       
   958     } catch (e) {
       
   959     }
       
   960 
       
   961     return this;
       
   962 };
       
   963 
       
   964 // IE throws error when setting input.type = 'hidden',
       
   965 // input.setAttribute('type', 'hidden') and input.attributes.type.value = 'hidden'
       
   966 Y.Node.ATTRS.type = {
       
   967     setter: function(val) {
       
   968         if (val === 'hidden') {
       
   969             try {
       
   970                 this._node.type = 'hidden';
       
   971             } catch(e) {
       
   972                 this.setStyle('display', 'none');
       
   973                 this._inputType = 'hidden';
       
   974             }
       
   975         } else {
       
   976             try { // IE errors when changing the type from "hidden'
       
   977                 this._node.type = val;
       
   978             } catch (e) {
       
   979             }
       
   980         }
       
   981         return val;
       
   982     },
       
   983 
       
   984     getter: function() {
       
   985         return this._inputType || this._node.type;
       
   986     },
       
   987 
       
   988     _bypassProxy: true // don't update DOM when using with Attribute
       
   989 };
       
   990 
       
   991 if (Y.config.doc.createElement('form').elements.nodeType) {
       
   992     // IE: elements collection is also FORM node which trips up scrubVal.
       
   993     Y.Node.ATTRS.elements = {
       
   994             getter: function() {
       
   995                 return this.all('input, textarea, button, select');
       
   996             }
       
   997     };
       
   998 }
       
   999 
       
  1000 /**
       
  1001  * Provides methods for managing custom Node data.
       
  1002  * 
       
  1003  * @module node
       
  1004  * @main node
       
  1005  * @submodule node-data
       
  1006  */
       
  1007 
       
  1008 Y.mix(Y.Node.prototype, {
       
  1009     _initData: function() {
       
  1010         if (! ('_data' in this)) {
       
  1011             this._data = {};
       
  1012         }
       
  1013     },
       
  1014 
       
  1015     /**
       
  1016     * @method getData
       
  1017     * @for Node
       
  1018     * @description Retrieves arbitrary data stored on a Node instance.
       
  1019     * If no data is associated with the Node, it will attempt to retrieve
       
  1020     * a value from the corresponding HTML data attribute. (e.g. node.getData('foo')
       
  1021     * will check node.getAttribute('data-foo')).
       
  1022     * @param {string} name Optional name of the data field to retrieve.
       
  1023     * If no name is given, all data is returned.
       
  1024     * @return {any | Object} Whatever is stored at the given field,
       
  1025     * or an object hash of all fields.
       
  1026     */
       
  1027     getData: function(name) {
       
  1028         this._initData();
       
  1029         var data = this._data,
       
  1030             ret = data;
       
  1031 
       
  1032         if (arguments.length) { // single field
       
  1033             if (name in data) {
       
  1034                 ret = data[name];
       
  1035             } else { // initialize from HTML attribute
       
  1036                 ret = this._getDataAttribute(name);
       
  1037             }
       
  1038         } else if (typeof data == 'object' && data !== null) { // all fields
       
  1039             ret = {};
       
  1040             Y.Object.each(data, function(v, n) {
       
  1041                 ret[n] = v;
       
  1042             });
       
  1043 
       
  1044             ret = this._getDataAttributes(ret);
       
  1045         }
       
  1046 
       
  1047         return ret;
       
  1048 
       
  1049     },
       
  1050 
       
  1051     _getDataAttributes: function(ret) {
       
  1052         ret = ret || {};
       
  1053         var i = 0,
       
  1054             attrs = this._node.attributes,
       
  1055             len = attrs.length,
       
  1056             prefix = this.DATA_PREFIX,
       
  1057             prefixLength = prefix.length,
       
  1058             name;
       
  1059 
       
  1060         while (i < len) {
       
  1061             name = attrs[i].name;
       
  1062             if (name.indexOf(prefix) === 0) {
       
  1063                 name = name.substr(prefixLength);
       
  1064                 if (!(name in ret)) { // only merge if not already stored
       
  1065                     ret[name] = this._getDataAttribute(name);
       
  1066                 }
       
  1067             }
       
  1068 
       
  1069             i += 1;
       
  1070         }
       
  1071 
       
  1072         return ret;
       
  1073     },
       
  1074 
       
  1075     _getDataAttribute: function(name) {
       
  1076         name = this.DATA_PREFIX + name;
       
  1077 
       
  1078         var node = this._node,
       
  1079             attrs = node.attributes,
       
  1080             data = attrs && attrs[name] && attrs[name].value;
       
  1081 
       
  1082         return data;
       
  1083     },
       
  1084 
       
  1085     /**
       
  1086     * @method setData
       
  1087     * @for Node
       
  1088     * @description Stores arbitrary data on a Node instance.
       
  1089     * This is not stored with the DOM node.
       
  1090     * @param {string} name The name of the field to set. If no val
       
  1091     * is given, name is treated as the data and overrides any existing data.
       
  1092     * @param {any} val The value to be assigned to the field.
       
  1093     * @chainable
       
  1094     */
       
  1095     setData: function(name, val) {
       
  1096         this._initData();
       
  1097         if (arguments.length > 1) {
       
  1098             this._data[name] = val;
       
  1099         } else {
       
  1100             this._data = name;
       
  1101         }
       
  1102 
       
  1103        return this;
       
  1104     },
       
  1105 
       
  1106     /**
       
  1107     * @method clearData
       
  1108     * @for Node
       
  1109     * @description Clears internally stored data.
       
  1110     * @param {string} name The name of the field to clear. If no name
       
  1111     * is given, all data is cleared.
       
  1112     * @chainable
       
  1113     */
       
  1114     clearData: function(name) {
       
  1115         if ('_data' in this) {
       
  1116             if (typeof name != 'undefined') {
       
  1117                 delete this._data[name];
       
  1118             } else {
       
  1119                 delete this._data;
       
  1120             }
       
  1121         }
       
  1122 
       
  1123         return this;
       
  1124     }
       
  1125 });
       
  1126 
       
  1127 Y.mix(Y.NodeList.prototype, {
       
  1128     /**
       
  1129     * @method getData
       
  1130     * @for NodeList
       
  1131     * @description Retrieves arbitrary data stored on each Node instance
       
  1132     * bound to the NodeList.
       
  1133     * @see Node
       
  1134     * @param {string} name Optional name of the data field to retrieve.
       
  1135     * If no name is given, all data is returned.
       
  1136     * @return {Array} An array containing all of the data for each Node instance. 
       
  1137     * or an object hash of all fields.
       
  1138     */
       
  1139     getData: function(name) {
       
  1140         var args = (arguments.length) ? [name] : [];
       
  1141         return this._invoke('getData', args, true);
       
  1142     },
       
  1143 
       
  1144     /**
       
  1145     * @method setData
       
  1146     * @for NodeList
       
  1147     * @description Stores arbitrary data on each Node instance bound to the
       
  1148     *  NodeList. This is not stored with the DOM node.
       
  1149     * @param {string} name The name of the field to set. If no name
       
  1150     * is given, name is treated as the data and overrides any existing data.
       
  1151     * @param {any} val The value to be assigned to the field.
       
  1152     * @chainable
       
  1153     */
       
  1154     setData: function(name, val) {
       
  1155         var args = (arguments.length > 1) ? [name, val] : [name];
       
  1156         return this._invoke('setData', args);
       
  1157     },
       
  1158 
       
  1159     /**
       
  1160     * @method clearData
       
  1161     * @for NodeList
       
  1162     * @description Clears data on all Node instances bound to the NodeList.
       
  1163     * @param {string} name The name of the field to clear. If no name
       
  1164     * is given, all data is cleared.
       
  1165     * @chainable
       
  1166     */
       
  1167     clearData: function(name) {
       
  1168         var args = (arguments.length) ? [name] : [];
       
  1169         return this._invoke('clearData', [name]);
       
  1170     }
       
  1171 });
       
  1172 
       
  1173 
       
  1174 }, '3.10.3', {"requires": ["event-base", "node-core", "dom-base"]});