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