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