[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/lib/yuilib/3.17.2/node-base/ -> node-base-debug.js (source)

   1  /*
   2  YUI 3.17.2 (build 9c3c78e)
   3  Copyright 2014 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 the 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 node has the specified class
  22   */
  23   'hasClass',
  24  
  25  /**
  26   * Adds a class name to the 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 the 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 on the 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 each 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 each 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   * For each node, 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       * @example
 242       *      // appendTo returns the node that has been created beforehand
 243       *      Y.Node.create('<p></p>').appendTo('body').set('text', 'hello world!');
 244       * @method appendTo
 245       * @param {Node | HTMLElement | String} node The node to append to.
 246       *  If `node` is a string it will be considered as a css selector and only the first matching node will be used.
 247       * @chainable
 248       */
 249      appendTo: function(node) {
 250          Y.one(node).append(this);
 251          return this;
 252      },
 253      
 254      // This method is deprecated, and is intentionally left undocumented.
 255      // Use `setHTML` instead.
 256      setContent: function(content) {
 257          this._insert(content, 'replace');
 258          return this;
 259      },
 260      
 261      // This method is deprecated, and is intentionally left undocumented.
 262      // Use `getHTML` instead.
 263      getContent: function() {
 264          var node = this;
 265  
 266          if (node._node.nodeType === 11) { // 11 === Node.DOCUMENT_FRAGMENT_NODE
 267              // "this", when it is a document fragment, must be cloned because
 268              // the nodes contained in the fragment actually disappear once
 269              // the fragment is appended anywhere
 270              node = node.create("<div/>").append(node.cloneNode(true));
 271          }
 272  
 273          return node.get("innerHTML");
 274      }
 275  });
 276  
 277  /**
 278   * Replaces the node's current html content with the content provided.
 279   * Note that this passes to innerHTML and is not escaped.
 280   * Use <a href="../classes/Escape.html#method_html">`Y.Escape.html()`</a>
 281   * to escape html content or `set('text')` to add as text.
 282   * @method setHTML
 283   * @param {String | Node | HTMLElement | NodeList | HTMLCollection} content The content to insert
 284   * @chainable
 285   */
 286  Y.Node.prototype.setHTML = Y.Node.prototype.setContent;
 287  
 288  /**
 289   * Returns the node's current html content (e.g. innerHTML)
 290   * @method getHTML
 291   * @return {String} The html content
 292   */
 293  Y.Node.prototype.getHTML = Y.Node.prototype.getContent;
 294  
 295  Y.NodeList.importMethod(Y.Node.prototype, [
 296      /**
 297       * Called on each Node instance
 298       * @for NodeList
 299       * @method append
 300       * @see Node.append
 301       */
 302      'append',
 303  
 304      /**
 305       * Called on each Node instance
 306       * @for NodeList
 307       * @method insert
 308       * @see Node.insert
 309       */
 310      'insert',
 311  
 312      /**
 313       * Called on each Node instance
 314       * @for NodeList
 315       * @method appendChild
 316       * @see Node.appendChild
 317       */
 318      'appendChild',
 319  
 320      /**
 321       * Called on each Node instance
 322       * @for NodeList
 323       * @method insertBefore
 324       * @see Node.insertBefore
 325       */
 326      'insertBefore',
 327  
 328      /**
 329       * Called on each Node instance
 330       * @for NodeList
 331       * @method prepend
 332       * @see Node.prepend
 333       */
 334      'prepend',
 335  
 336      'setContent',
 337  
 338      'getContent',
 339  
 340      /**
 341       * Called on each Node instance
 342       * Note that this passes to innerHTML and is not escaped.
 343       * Use <a href="../classes/Escape.html#method_html">`Y.Escape.html()`</a>
 344       * to escape html content or `set('text')` to add as text.
 345       * @for NodeList
 346       * @method setHTML
 347       * @see Node.setHTML
 348       */
 349      'setHTML',
 350  
 351      /**
 352       * Called on each Node instance
 353       * @for NodeList
 354       * @method getHTML
 355       * @see Node.getHTML
 356       */
 357      'getHTML'
 358  ]);
 359  /**
 360   * @module node
 361   * @submodule node-base
 362   */
 363  
 364  var Y_Node = Y.Node,
 365      Y_DOM = Y.DOM;
 366  
 367  /**
 368   * Static collection of configuration attributes for special handling
 369   * @property ATTRS
 370   * @static
 371   * @type object
 372   */
 373  Y_Node.ATTRS = {
 374      /**
 375       * Allows for getting and setting the text of an element.
 376       * Formatting is preserved and special characters are treated literally.
 377       * @config text
 378       * @type String
 379       */
 380      text: {
 381          getter: function() {
 382              return Y_DOM.getText(this._node);
 383          },
 384  
 385          setter: function(content) {
 386              Y_DOM.setText(this._node, content);
 387              return content;
 388          }
 389      },
 390  
 391      /**
 392       * Allows for getting and setting the text of an element.
 393       * Formatting is preserved and special characters are treated literally.
 394       * @config for
 395       * @type String
 396       */
 397      'for': {
 398          getter: function() {
 399              return Y_DOM.getAttribute(this._node, 'for');
 400          },
 401  
 402          setter: function(val) {
 403              Y_DOM.setAttribute(this._node, 'for', val);
 404              return val;
 405          }
 406      },
 407  
 408      'options': {
 409          getter: function() {
 410              return this._node.getElementsByTagName('option');
 411          }
 412      },
 413  
 414      /**
 415       * Returns a NodeList instance of all HTMLElement children.
 416       * @readOnly
 417       * @config children
 418       * @type NodeList
 419       */
 420      'children': {
 421          getter: function() {
 422              var node = this._node,
 423                  children = node.children,
 424                  childNodes, i, len;
 425  
 426              if (!children) {
 427                  childNodes = node.childNodes;
 428                  children = [];
 429  
 430                  for (i = 0, len = childNodes.length; i < len; ++i) {
 431                      if (childNodes[i].tagName) {
 432                          children[children.length] = childNodes[i];
 433                      }
 434                  }
 435              }
 436              return Y.all(children);
 437          }
 438      },
 439  
 440      value: {
 441          getter: function() {
 442              return Y_DOM.getValue(this._node);
 443          },
 444  
 445          setter: function(val) {
 446              Y_DOM.setValue(this._node, val);
 447              return val;
 448          }
 449      }
 450  };
 451  
 452  Y.Node.importMethod(Y.DOM, [
 453      /**
 454       * Allows setting attributes on DOM nodes, normalizing in some cases.
 455       * This passes through to the DOM node, allowing for custom attributes.
 456       * @method setAttribute
 457       * @for Node
 458       * @for NodeList
 459       * @chainable
 460       * @param {string} name The attribute name
 461       * @param {string} value The value to set
 462       */
 463      'setAttribute',
 464      /**
 465       * Allows getting attributes on DOM nodes, normalizing in some cases.
 466       * This passes through to the DOM node, allowing for custom attributes.
 467       * @method getAttribute
 468       * @for Node
 469       * @for NodeList
 470       * @param {string} name The attribute name
 471       * @return {string} The attribute value
 472       */
 473      'getAttribute'
 474  
 475  ]);
 476  /**
 477   * @module node
 478   * @submodule node-base
 479   */
 480  
 481  var Y_Node = Y.Node;
 482  var Y_NodeList = Y.NodeList;
 483  /**
 484   * List of events that route to DOM events
 485   * @static
 486   * @property DOM_EVENTS
 487   * @for Node
 488   */
 489  
 490  Y_Node.DOM_EVENTS = {
 491      abort: 1,
 492      beforeunload: 1,
 493      blur: 1,
 494      change: 1,
 495      click: 1,
 496      close: 1,
 497      command: 1,
 498      contextmenu: 1,
 499      copy: 1,
 500      cut: 1,
 501      dblclick: 1,
 502      DOMMouseScroll: 1,
 503      drag: 1,
 504      dragstart: 1,
 505      dragenter: 1,
 506      dragover: 1,
 507      dragleave: 1,
 508      dragend: 1,
 509      drop: 1,
 510      error: 1,
 511      focus: 1,
 512      key: 1,
 513      keydown: 1,
 514      keypress: 1,
 515      keyup: 1,
 516      load: 1,
 517      message: 1,
 518      mousedown: 1,
 519      mouseenter: 1,
 520      mouseleave: 1,
 521      mousemove: 1,
 522      mousemultiwheel: 1,
 523      mouseout: 1,
 524      mouseover: 1,
 525      mouseup: 1,
 526      mousewheel: 1,
 527      orientationchange: 1,
 528      paste: 1,
 529      reset: 1,
 530      resize: 1,
 531      select: 1,
 532      selectstart: 1,
 533      submit: 1,
 534      scroll: 1,
 535      textInput: 1,
 536      unload: 1,
 537      invalid: 1
 538  };
 539  
 540  // Add custom event adaptors to this list.  This will make it so
 541  // that delegate, key, available, contentready, etc all will
 542  // be available through Node.on
 543  Y.mix(Y_Node.DOM_EVENTS, Y.Env.evt.plugins);
 544  
 545  Y.augment(Y_Node, Y.EventTarget);
 546  
 547  Y.mix(Y_Node.prototype, {
 548      /**
 549       * Removes event listeners from the node and (optionally) its subtree
 550       * @method purge
 551       * @param {Boolean} recurse (optional) Whether or not to remove listeners from the
 552       * node's subtree
 553       * @param {String} type (optional) Only remove listeners of the specified type
 554       * @chainable
 555       *
 556       */
 557      purge: function(recurse, type) {
 558          Y.Event.purgeElement(this._node, recurse, type);
 559          return this;
 560      }
 561  
 562  });
 563  
 564  Y.mix(Y.NodeList.prototype, {
 565      _prepEvtArgs: function(type, fn, context) {
 566          // map to Y.on/after signature (type, fn, nodes, context, arg1, arg2, etc)
 567          var args = Y.Array(arguments, 0, true);
 568  
 569          if (args.length < 2) { // type only (event hash) just add nodes
 570              args[2] = this._nodes;
 571          } else {
 572              args.splice(2, 0, this._nodes);
 573          }
 574  
 575          args[3] = context || this; // default to NodeList instance as context
 576  
 577          return args;
 578      },
 579  
 580      /**
 581      Subscribe a callback function for each `Node` in the collection to execute
 582      in response to a DOM event.
 583  
 584      NOTE: Generally, the `on()` method should be avoided on `NodeLists`, in
 585      favor of using event delegation from a parent Node.  See the Event user
 586      guide for details.
 587  
 588      Most DOM events are associated with a preventable default behavior, such as
 589      link clicks navigating to a new page.  Callbacks are passed a
 590      `DOMEventFacade` object as their first argument (usually called `e`) that
 591      can be used to prevent this default behavior with `e.preventDefault()`. See
 592      the `DOMEventFacade` API for all available properties and methods on the
 593      object.
 594  
 595      By default, the `this` object will be the `NodeList` that the subscription
 596      came from, <em>not the `Node` that received the event</em>.  Use
 597      `e.currentTarget` to refer to the `Node`.
 598  
 599      Returning `false` from a callback is supported as an alternative to calling
 600      `e.preventDefault(); e.stopPropagation();`.  However, it is recommended to
 601      use the event methods.
 602  
 603      @example
 604  
 605          Y.all(".sku").on("keydown", function (e) {
 606              if (e.keyCode === 13) {
 607                  e.preventDefault();
 608  
 609                  // Use e.currentTarget to refer to the individual Node
 610                  var item = Y.MyApp.searchInventory( e.currentTarget.get('value') );
 611                  // etc ...
 612              }
 613          });
 614  
 615      @method on
 616      @param {String} type The name of the event
 617      @param {Function} fn The callback to execute in response to the event
 618      @param {Object} [context] Override `this` object in callback
 619      @param {Any} [arg*] 0..n additional arguments to supply to the subscriber
 620      @return {EventHandle} A subscription handle capable of detaching that
 621                            subscription
 622      @for NodeList
 623      **/
 624      on: function(type, fn, context) {
 625          return Y.on.apply(Y, this._prepEvtArgs.apply(this, arguments));
 626      },
 627  
 628      /**
 629       * Applies an one-time event listener to each Node bound to the NodeList.
 630       * @method once
 631       * @param {String} type The event being listened for
 632       * @param {Function} fn The handler to call when the event fires
 633       * @param {Object} context The context to call the handler with.
 634       * Default is the NodeList instance.
 635       * @return {EventHandle} A subscription handle capable of detaching that
 636       *                    subscription
 637       * @for NodeList
 638       */
 639      once: function(type, fn, context) {
 640          return Y.once.apply(Y, this._prepEvtArgs.apply(this, arguments));
 641      },
 642  
 643      /**
 644       * Applies an event listener to each Node bound to the NodeList.
 645       * The handler is called only after all on() handlers are called
 646       * and the event is not prevented.
 647       * @method after
 648       * @param {String} type The event being listened for
 649       * @param {Function} fn The handler to call when the event fires
 650       * @param {Object} context The context to call the handler with.
 651       * Default is the NodeList instance.
 652       * @return {EventHandle} A subscription handle capable of detaching that
 653       *                    subscription
 654       * @for NodeList
 655       */
 656      after: function(type, fn, context) {
 657          return Y.after.apply(Y, this._prepEvtArgs.apply(this, arguments));
 658      },
 659  
 660      /**
 661       * Applies an one-time event listener to each Node bound to the NodeList
 662       * that will be called only after all on() handlers are called and the
 663       * event is not prevented.
 664       *
 665       * @method onceAfter
 666       * @param {String} type The event being listened for
 667       * @param {Function} fn The handler to call when the event fires
 668       * @param {Object} context The context to call the handler with.
 669       * Default is the NodeList instance.
 670       * @return {EventHandle} A subscription handle capable of detaching that
 671       *                    subscription
 672       * @for NodeList
 673       */
 674      onceAfter: function(type, fn, context) {
 675          return Y.onceAfter.apply(Y, this._prepEvtArgs.apply(this, arguments));
 676      }
 677  });
 678  
 679  Y_NodeList.importMethod(Y.Node.prototype, [
 680      /**
 681        * Called on each Node instance
 682        * @method detach
 683        * @see Node.detach
 684        * @for NodeList
 685        */
 686      'detach',
 687  
 688      /** Called on each Node instance
 689        * @method detachAll
 690        * @see Node.detachAll
 691        * @for NodeList
 692        */
 693      'detachAll'
 694  ]);
 695  
 696  /**
 697  Subscribe a callback function to execute in response to a DOM event or custom
 698  event.
 699  
 700  Most DOM events are associated with a preventable default behavior such as
 701  link clicks navigating to a new page.  Callbacks are passed a `DOMEventFacade`
 702  object as their first argument (usually called `e`) that can be used to
 703  prevent this default behavior with `e.preventDefault()`. See the
 704  `DOMEventFacade` API for all available properties and methods on the object.
 705  
 706  If the event name passed as the first parameter is not a whitelisted DOM event,
 707  it will be treated as a custom event subscriptions, allowing
 708  `node.fire('customEventName')` later in the code.  Refer to the Event user guide
 709  for the full DOM event whitelist.
 710  
 711  By default, the `this` object in the callback will refer to the subscribed
 712  `Node`.
 713  
 714  Returning `false` from a callback is supported as an alternative to calling
 715  `e.preventDefault(); e.stopPropagation();`.  However, it is recommended to use
 716  the event methods.
 717  
 718  @example
 719  
 720      Y.one("#my-form").on("submit", function (e) {
 721          e.preventDefault();
 722  
 723          // proceed with ajax form submission instead...
 724      });
 725  
 726  @method on
 727  @param {String} type The name of the event
 728  @param {Function} fn The callback to execute in response to the event
 729  @param {Object} [context] Override `this` object in callback
 730  @param {Any} [arg*] 0..n additional arguments to supply to the subscriber
 731  @return {EventHandle} A subscription handle capable of detaching that
 732                        subscription
 733  @for Node
 734  **/
 735  
 736  Y.mix(Y.Node.ATTRS, {
 737      offsetHeight: {
 738          setter: function(h) {
 739              Y.DOM.setHeight(this._node, h);
 740              return h;
 741          },
 742  
 743          getter: function() {
 744              return this._node.offsetHeight;
 745          }
 746      },
 747  
 748      offsetWidth: {
 749          setter: function(w) {
 750              Y.DOM.setWidth(this._node, w);
 751              return w;
 752          },
 753  
 754          getter: function() {
 755              return this._node.offsetWidth;
 756          }
 757      }
 758  });
 759  
 760  Y.mix(Y.Node.prototype, {
 761      sizeTo: function(w, h) {
 762          var node;
 763          if (arguments.length < 2) {
 764              node = Y.one(w);
 765              w = node.get('offsetWidth');
 766              h = node.get('offsetHeight');
 767          }
 768  
 769          this.setAttrs({
 770              offsetWidth: w,
 771              offsetHeight: h
 772          });
 773      }
 774  });
 775  
 776  if (!Y.config.doc.documentElement.hasAttribute) { // IE < 8
 777      Y.Node.prototype.hasAttribute = function(attr) {
 778          if (attr === 'value') {
 779              if (this.get('value') !== "") { // IE < 8 fails to populate specified when set in HTML
 780                  return true;
 781              }
 782          }
 783          return !!(this._node.attributes[attr] &&
 784                  this._node.attributes[attr].specified);
 785      };
 786  }
 787  
 788  // IE throws an error when calling focus() on an element that's invisible, not
 789  // displayed, or disabled.
 790  Y.Node.prototype.focus = function () {
 791      try {
 792          this._node.focus();
 793      } catch (e) {
 794          Y.log('error focusing node: ' + e.toString(), 'error', 'node');
 795      }
 796  
 797      return this;
 798  };
 799  
 800  // IE throws error when setting input.type = 'hidden',
 801  // input.setAttribute('type', 'hidden') and input.attributes.type.value = 'hidden'
 802  Y.Node.ATTRS.type = {
 803      setter: function(val) {
 804          if (val === 'hidden') {
 805              try {
 806                  this._node.type = 'hidden';
 807              } catch(e) {
 808                  this._node.style.display = 'none';
 809                  this._inputType = 'hidden';
 810              }
 811          } else {
 812              try { // IE errors when changing the type from "hidden'
 813                  this._node.type = val;
 814              } catch (e) {
 815                  Y.log('error setting type: ' + val, 'info', 'node');
 816              }
 817          }
 818          return val;
 819      },
 820  
 821      getter: function() {
 822          return this._inputType || this._node.type;
 823      },
 824  
 825      _bypassProxy: true // don't update DOM when using with Attribute
 826  };
 827  
 828  if (Y.config.doc.createElement('form').elements.nodeType) {
 829      // IE: elements collection is also FORM node which trips up scrubVal.
 830      Y.Node.ATTRS.elements = {
 831              getter: function() {
 832                  return this.all('input, textarea, button, select');
 833              }
 834      };
 835  }
 836  /**
 837   * Provides methods for managing custom Node data.
 838   *
 839   * @module node
 840   * @main node
 841   * @submodule node-data
 842   */
 843  
 844  Y.mix(Y.Node.prototype, {
 845      _initData: function() {
 846          if (! ('_data' in this)) {
 847              this._data = {};
 848          }
 849      },
 850  
 851      /**
 852      * @method getData
 853      * @for Node
 854      * @description Retrieves arbitrary data stored on a Node instance.
 855      * If no data is associated with the Node, it will attempt to retrieve
 856      * a value from the corresponding HTML data attribute. (e.g. node.getData('foo')
 857      * will check node.getAttribute('data-foo')).
 858      * @param {string} name Optional name of the data field to retrieve.
 859      * If no name is given, all data is returned.
 860      * @return {any | Object} Whatever is stored at the given field,
 861      * or an object hash of all fields.
 862      */
 863      getData: function(name) {
 864          this._initData();
 865          var data = this._data,
 866              ret = data;
 867  
 868          if (arguments.length) { // single field
 869              if (name in data) {
 870                  ret = data[name];
 871              } else { // initialize from HTML attribute
 872                  ret = this._getDataAttribute(name);
 873              }
 874          } else if (typeof data == 'object' && data !== null) { // all fields
 875              ret = {};
 876              Y.Object.each(data, function(v, n) {
 877                  ret[n] = v;
 878              });
 879  
 880              ret = this._getDataAttributes(ret);
 881          }
 882  
 883          return ret;
 884  
 885      },
 886  
 887      _getDataAttributes: function(ret) {
 888          ret = ret || {};
 889          var i = 0,
 890              attrs = this._node.attributes,
 891              len = attrs.length,
 892              prefix = this.DATA_PREFIX,
 893              prefixLength = prefix.length,
 894              name;
 895  
 896          while (i < len) {
 897              name = attrs[i].name;
 898              if (name.indexOf(prefix) === 0) {
 899                  name = name.substr(prefixLength);
 900                  if (!(name in ret)) { // only merge if not already stored
 901                      ret[name] = this._getDataAttribute(name);
 902                  }
 903              }
 904  
 905              i += 1;
 906          }
 907  
 908          return ret;
 909      },
 910  
 911      _getDataAttribute: function(name) {
 912          name = this.DATA_PREFIX + name;
 913  
 914          var node = this._node,
 915              attrs = node.attributes,
 916              data = attrs && attrs[name] && attrs[name].value;
 917  
 918          return data;
 919      },
 920  
 921      /**
 922      * @method setData
 923      * @for Node
 924      * @description Stores arbitrary data on a Node instance.
 925      * This is not stored with the DOM node.
 926      * @param {string} name The name of the field to set. If no val
 927      * is given, name is treated as the data and overrides any existing data.
 928      * @param {any} val The value to be assigned to the field.
 929      * @chainable
 930      */
 931      setData: function(name, val) {
 932          this._initData();
 933          if (arguments.length > 1) {
 934              this._data[name] = val;
 935          } else {
 936              this._data = name;
 937          }
 938  
 939         return this;
 940      },
 941  
 942      /**
 943      * @method clearData
 944      * @for Node
 945      * @description Clears internally stored data.
 946      * @param {string} name The name of the field to clear. If no name
 947      * is given, all data is cleared.
 948      * @chainable
 949      */
 950      clearData: function(name) {
 951          if ('_data' in this) {
 952              if (typeof name != 'undefined') {
 953                  delete this._data[name];
 954              } else {
 955                  delete this._data;
 956              }
 957          }
 958  
 959          return this;
 960      }
 961  });
 962  
 963  Y.mix(Y.NodeList.prototype, {
 964      /**
 965      * @method getData
 966      * @for NodeList
 967      * @description Retrieves arbitrary data stored on each Node instance
 968      * bound to the NodeList.
 969      * @see Node
 970      * @param {string} name Optional name of the data field to retrieve.
 971      * If no name is given, all data is returned.
 972      * @return {Array} An array containing all of the data for each Node instance.
 973      * or an object hash of all fields.
 974      */
 975      getData: function(name) {
 976          var args = (arguments.length) ? [name] : [];
 977          return this._invoke('getData', args, true);
 978      },
 979  
 980      /**
 981      * @method setData
 982      * @for NodeList
 983      * @description Stores arbitrary data on each Node instance bound to the
 984      *  NodeList. This is not stored with the DOM node.
 985      * @param {string} name The name of the field to set. If no name
 986      * is given, name is treated as the data and overrides any existing data.
 987      * @param {any} val The value to be assigned to the field.
 988      * @chainable
 989      */
 990      setData: function(name, val) {
 991          var args = (arguments.length > 1) ? [name, val] : [name];
 992          return this._invoke('setData', args);
 993      },
 994  
 995      /**
 996      * @method clearData
 997      * @for NodeList
 998      * @description Clears data on all Node instances bound to the NodeList.
 999      * @param {string} name The name of the field to clear. If no name
1000      * is given, all data is cleared.
1001      * @chainable
1002      */
1003      clearData: function(name) {
1004          var args = (arguments.length) ? [name] : [];
1005          return this._invoke('clearData', [name]);
1006      }
1007  });
1008  
1009  
1010  }, '3.17.2', {"requires": ["event-base", "node-core", "dom-base", "dom-style"]});


Generated: Thu Aug 11 10:00:09 2016 Cross-referenced by PHPXref 0.7.1