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