Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
YUI.add('node-core', function (Y, NAME) {
2
 
3
/**
4
 * The Node Utility provides a DOM-like interface for interacting with DOM nodes.
5
 * @module node
6
 * @main node
7
 * @submodule node-core
8
 */
9
 
10
/**
11
 * The Node class provides a wrapper for manipulating DOM Nodes.
12
 * Node properties can be accessed via the set/get methods.
13
 * Use `Y.one()` to retrieve Node instances.
14
 *
15
 * <strong>NOTE:</strong> Node properties are accessed using
16
 * the <code>set</code> and <code>get</code> methods.
17
 *
18
 * @class Node
19
 * @constructor
20
 * @param {HTMLElement} node the DOM node to be mapped to the Node instance.
21
 * @uses EventTarget
22
 */
23
 
24
// "globals"
25
var DOT = '.',
26
    NODE_NAME = 'nodeName',
27
    NODE_TYPE = 'nodeType',
28
    OWNER_DOCUMENT = 'ownerDocument',
29
    TAG_NAME = 'tagName',
30
    UID = '_yuid',
31
    EMPTY_OBJ = {},
32
 
33
    _slice = Array.prototype.slice,
34
 
35
    Y_DOM = Y.DOM,
36
 
37
    Y_Node = function(node) {
38
        if (!this.getDOMNode) { // support optional "new"
39
            return new Y_Node(node);
40
        }
41
 
42
        if (typeof node == 'string') {
43
            node = Y_Node._fromString(node);
44
            if (!node) {
45
                return null; // NOTE: return
46
            }
47
        }
48
 
49
        var uid = (node.nodeType !== 9) ? node.uniqueID : node[UID];
50
 
51
        if (uid && Y_Node._instances[uid] && Y_Node._instances[uid]._node !== node) {
52
            node[UID] = null; // unset existing uid to prevent collision (via clone or hack)
53
        }
54
 
55
        uid = uid || Y.stamp(node);
56
        if (!uid) { // stamp failed; likely IE non-HTMLElement
57
            uid = Y.guid();
58
        }
59
 
60
        this[UID] = uid;
61
 
62
        /**
63
         * The underlying DOM node bound to the Y.Node instance
64
         * @property _node
65
         * @type HTMLElement
66
         * @private
67
         */
68
        this._node = node;
69
 
70
        this._stateProxy = node; // when augmented with Attribute
71
 
72
        if (this._initPlugins) { // when augmented with Plugin.Host
73
            this._initPlugins();
74
        }
75
    },
76
 
77
    // used with previous/next/ancestor tests
78
    _wrapFn = function(fn) {
79
        var ret = null;
80
        if (fn) {
81
            ret = (typeof fn == 'string') ?
82
            function(n) {
83
                return Y.Selector.test(n, fn);
84
            } :
85
            function(n) {
86
                return fn(Y.one(n));
87
            };
88
        }
89
 
90
        return ret;
91
    };
92
// end "globals"
93
 
94
Y_Node.ATTRS = {};
95
Y_Node.DOM_EVENTS = {};
96
 
97
Y_Node._fromString = function(node) {
98
    if (node) {
99
        if (node.indexOf('doc') === 0) { // doc OR document
100
            node = Y.config.doc;
101
        } else if (node.indexOf('win') === 0) { // win OR window
102
            node = Y.config.win;
103
        } else {
104
            node = Y.Selector.query(node, null, true);
105
        }
106
    }
107
 
108
    return node || null;
109
};
110
 
111
/**
112
 * The name of the component
113
 * @static
114
 * @type String
115
 * @property NAME
116
 */
117
Y_Node.NAME = 'node';
118
 
119
/*
120
 * The pattern used to identify ARIA attributes
121
 */
122
Y_Node.re_aria = /^(?:role$|aria-)/;
123
 
124
Y_Node.SHOW_TRANSITION = 'fadeIn';
125
Y_Node.HIDE_TRANSITION = 'fadeOut';
126
 
127
/**
128
 * A list of Node instances that have been created
129
 * @private
130
 * @type Object
131
 * @property _instances
132
 * @static
133
 *
134
 */
135
Y_Node._instances = {};
136
 
137
/**
138
 * Retrieves the DOM node bound to a Node instance
139
 * @method getDOMNode
140
 * @static
141
 *
142
 * @param {Node|HTMLElement} node The Node instance or an HTMLElement
143
 * @return {HTMLElement} The DOM node bound to the Node instance.  If a DOM node is passed
144
 * as the node argument, it is simply returned.
145
 */
146
Y_Node.getDOMNode = function(node) {
147
    if (node) {
148
        return (node.nodeType) ? node : node._node || null;
149
    }
150
    return null;
151
};
152
 
153
/**
154
 * Checks Node return values and wraps DOM Nodes as Y.Node instances
155
 * and DOM Collections / Arrays as Y.NodeList instances.
156
 * Other return values just pass thru.  If undefined is returned (e.g. no return)
157
 * then the Node instance is returned for chainability.
158
 * @method scrubVal
159
 * @static
160
 *
161
 * @param {HTMLElement|HTMLElement[]|Node} node The Node instance or an HTMLElement
162
 * @return {Node | NodeList | Any} Depends on what is returned from the DOM node.
163
 */
164
Y_Node.scrubVal = function(val, node) {
165
    if (val) { // only truthy values are risky
166
         if (typeof val == 'object' || typeof val == 'function') { // safari nodeList === function
167
            if (NODE_TYPE in val || Y_DOM.isWindow(val)) {// node || window
168
                val = Y.one(val);
169
            } else if ((val.item && !val._nodes) || // dom collection or Node instance
170
                    (val[0] && val[0][NODE_TYPE])) { // array of DOM Nodes
171
                val = Y.all(val);
172
            }
173
        }
174
    } else if (typeof val === 'undefined') {
175
        val = node; // for chaining
176
    } else if (val === null) {
177
        val = null; // IE: DOM null not the same as null
178
    }
179
 
180
    return val;
181
};
182
 
183
/**
184
 * Adds methods to the Y.Node prototype, routing through scrubVal.
185
 * @method addMethod
186
 * @static
187
 *
188
 * @param {String} name The name of the method to add
189
 * @param {Function} fn The function that becomes the method
190
 * @param {Object} context An optional context to call the method with
191
 * (defaults to the Node instance)
192
 * @return {any} Depends on what is returned from the DOM node.
193
 */
194
Y_Node.addMethod = function(name, fn, context) {
195
    if (name && fn && typeof fn == 'function') {
196
        Y_Node.prototype[name] = function() {
197
            var args = _slice.call(arguments),
198
                node = this,
199
                ret;
200
 
201
            if (args[0] && args[0]._node) {
202
                args[0] = args[0]._node;
203
            }
204
 
205
            if (args[1] && args[1]._node) {
206
                args[1] = args[1]._node;
207
            }
208
            args.unshift(node._node);
209
 
210
            ret = fn.apply(context || node, args);
211
 
212
            if (ret) { // scrub truthy
213
                ret = Y_Node.scrubVal(ret, node);
214
            }
215
 
216
            (typeof ret != 'undefined') || (ret = node);
217
            return ret;
218
        };
219
    } else {
220
    }
221
};
222
 
223
/**
224
 * Imports utility methods to be added as Y.Node methods.
225
 * @method importMethod
226
 * @static
227
 *
228
 * @param {Object} host The object that contains the method to import.
229
 * @param {String} name The name of the method to import
230
 * @param {String} altName An optional name to use in place of the host name
231
 * @param {Object} context An optional context to call the method with
232
 */
233
Y_Node.importMethod = function(host, name, altName) {
234
    if (typeof name == 'string') {
235
        altName = altName || name;
236
        Y_Node.addMethod(altName, host[name], host);
237
    } else {
238
        Y.Array.each(name, function(n) {
239
            Y_Node.importMethod(host, n);
240
        });
241
    }
242
};
243
 
244
/**
245
 * Retrieves a NodeList based on the given CSS selector.
246
 * @method all
247
 *
248
 * @param {string} selector The CSS selector to test against.
249
 * @return {NodeList} A NodeList instance for the matching HTMLCollection/Array.
250
 * @for YUI
251
 */
252
 
253
/**
254
 * Returns a single Node instance bound to the node or the
255
 * first element matching the given selector. Returns null if no match found.
256
 * <strong>Note:</strong> For chaining purposes you may want to
257
 * use <code>Y.all</code>, which returns a NodeList when no match is found.
258
 * @method one
259
 * @param {String | HTMLElement} node a node or Selector
260
 * @return {Node | null} a Node instance or null if no match found.
261
 * @for YUI
262
 */
263
 
264
/**
265
 * Returns a single Node instance bound to the node or the
266
 * first element matching the given selector. Returns null if no match found.
267
 * <strong>Note:</strong> For chaining purposes you may want to
268
 * use <code>Y.all</code>, which returns a NodeList when no match is found.
269
 * @method one
270
 * @static
271
 * @param {String | HTMLElement} node a node or Selector
272
 * @return {Node | null} a Node instance or null if no match found.
273
 * @for Node
274
 */
275
Y_Node.one = function(node) {
276
    var instance = null,
277
        cachedNode,
278
        uid;
279
 
280
    if (node) {
281
        if (typeof node == 'string') {
282
            node = Y_Node._fromString(node);
283
            if (!node) {
284
                return null; // NOTE: return
285
            }
286
        } else if (node.getDOMNode) {
287
            return node; // NOTE: return
288
        }
289
 
290
        if (node.nodeType || Y.DOM.isWindow(node)) { // avoid bad input (numbers, boolean, etc)
291
            uid = (node.uniqueID && node.nodeType !== 9) ? node.uniqueID : node._yuid;
292
            instance = Y_Node._instances[uid]; // reuse exising instances
293
            cachedNode = instance ? instance._node : null;
294
            if (!instance || (cachedNode && node !== cachedNode)) { // new Node when nodes don't match
295
                instance = new Y_Node(node);
296
                if (node.nodeType != 11) { // dont cache document fragment
297
                    Y_Node._instances[instance[UID]] = instance; // cache node
298
                }
299
            }
300
        }
301
    }
302
 
303
    return instance;
304
};
305
 
306
/**
307
 * The default setter for DOM properties
308
 * Called with instance context (this === the Node instance)
309
 * @method DEFAULT_SETTER
310
 * @static
311
 * @param {String} name The attribute/property being set
312
 * @param {any} val The value to be set
313
 * @return {any} The value
314
 */
315
Y_Node.DEFAULT_SETTER = function(name, val) {
316
    var node = this._stateProxy,
317
        strPath;
318
 
319
    if (name.indexOf(DOT) > -1) {
320
        strPath = name;
321
        name = name.split(DOT);
322
        // only allow when defined on node
323
        Y.Object.setValue(node, name, val);
324
    } else if (typeof node[name] != 'undefined') { // pass thru DOM properties
325
        node[name] = val;
326
    }
327
 
328
    return val;
329
};
330
 
331
/**
332
 * The default getter for DOM properties
333
 * Called with instance context (this === the Node instance)
334
 * @method DEFAULT_GETTER
335
 * @static
336
 * @param {String} name The attribute/property to look up
337
 * @return {any} The current value
338
 */
339
Y_Node.DEFAULT_GETTER = function(name) {
340
    var node = this._stateProxy,
341
        val;
342
 
343
    if (name.indexOf && name.indexOf(DOT) > -1) {
344
        val = Y.Object.getValue(node, name.split(DOT));
345
    } else if (typeof node[name] != 'undefined') { // pass thru from DOM
346
        val = node[name];
347
    }
348
 
349
    return val;
350
};
351
 
352
Y.mix(Y_Node.prototype, {
353
    DATA_PREFIX: 'data-',
354
 
355
    /**
356
     * The method called when outputting Node instances as strings
357
     * @method toString
358
     * @return {String} A string representation of the Node instance
359
     */
360
    toString: function() {
361
        var str = this[UID] + ': not bound to a node',
362
            node = this._node,
363
            attrs, id, className;
364
 
365
        if (node) {
366
            attrs = node.attributes;
367
            id = (attrs && attrs.id) ? node.getAttribute('id') : null;
368
            className = (attrs && attrs.className) ? node.getAttribute('className') : null;
369
            str = node[NODE_NAME];
370
 
371
            if (id) {
372
                str += '#' + id;
373
            }
374
 
375
            if (className) {
376
                str += '.' + className.replace(' ', '.');
377
            }
378
 
379
            // TODO: add yuid?
380
            str += ' ' + this[UID];
381
        }
382
        return str;
383
    },
384
 
385
    /**
386
     * Returns an attribute value on the Node instance.
387
     * Unless pre-configured (via `Node.ATTRS`), get hands
388
     * off to the underlying DOM node.  Only valid
389
     * attributes/properties for the node will be queried.
390
     * @method get
391
     * @param {String} attr The attribute
392
     * @return {any} The current value of the attribute
393
     */
394
    get: function(attr) {
395
        var val;
396
 
397
        if (this._getAttr) { // use Attribute imple
398
            val = this._getAttr(attr);
399
        } else {
400
            val = this._get(attr);
401
        }
402
 
403
        if (val) {
404
            val = Y_Node.scrubVal(val, this);
405
        } else if (val === null) {
406
            val = null; // IE: DOM null is not true null (even though they ===)
407
        }
408
        return val;
409
    },
410
 
411
    /**
412
     * Helper method for get.
413
     * @method _get
414
     * @private
415
     * @param {String} attr The attribute
416
     * @return {any} The current value of the attribute
417
     */
418
    _get: function(attr) {
419
        var attrConfig = Y_Node.ATTRS[attr],
420
            val;
421
 
422
        if (attrConfig && attrConfig.getter) {
423
            val = attrConfig.getter.call(this);
424
        } else if (Y_Node.re_aria.test(attr)) {
425
            val = this._node.getAttribute(attr, 2);
426
        } else {
427
            val = Y_Node.DEFAULT_GETTER.apply(this, arguments);
428
        }
429
 
430
        return val;
431
    },
432
 
433
    /**
434
     * Sets an attribute on the Node instance.
435
     * Unless pre-configured (via Node.ATTRS), set hands
436
     * off to the underlying DOM node.  Only valid
437
     * attributes/properties for the node will be set.
438
     * To set custom attributes use setAttribute.
439
     * @method set
440
     * @param {String} attr The attribute to be set.
441
     * @param {any} val The value to set the attribute to.
442
     * @chainable
443
     */
444
    set: function(attr, val) {
445
        var attrConfig = Y_Node.ATTRS[attr];
446
 
447
        if (this._setAttr) { // use Attribute imple
448
            this._setAttr.apply(this, arguments);
449
        } else { // use setters inline
450
            if (attrConfig && attrConfig.setter) {
451
                attrConfig.setter.call(this, val, attr);
452
            } else if (Y_Node.re_aria.test(attr)) { // special case Aria
453
                this._node.setAttribute(attr, val);
454
            } else {
455
                Y_Node.DEFAULT_SETTER.apply(this, arguments);
456
            }
457
        }
458
 
459
        return this;
460
    },
461
 
462
    /**
463
     * Sets multiple attributes.
464
     * @method setAttrs
465
     * @param {Object} attrMap an object of name/value pairs to set
466
     * @chainable
467
     */
468
    setAttrs: function(attrMap) {
469
        if (this._setAttrs) { // use Attribute imple
470
            this._setAttrs(attrMap);
471
        } else { // use setters inline
472
            Y.Object.each(attrMap, function(v, n) {
473
                this.set(n, v);
474
            }, this);
475
        }
476
 
477
        return this;
478
    },
479
 
480
    /**
481
     * Returns an object containing the values for the requested attributes.
482
     * @method getAttrs
483
     * @param {Array} attrs an array of attributes to get values
484
     * @return {Object} An object with attribute name/value pairs.
485
     */
486
    getAttrs: function(attrs) {
487
        var ret = {};
488
        if (this._getAttrs) { // use Attribute imple
489
            this._getAttrs(attrs);
490
        } else { // use setters inline
491
            Y.Array.each(attrs, function(v, n) {
492
                ret[v] = this.get(v);
493
            }, this);
494
        }
495
 
496
        return ret;
497
    },
498
 
499
    /**
500
     * Compares nodes to determine if they match.
501
     * Node instances can be compared to each other and/or HTMLElements.
502
     * @method compareTo
503
     * @param {HTMLElement | Node} refNode The reference node to compare to the node.
504
     * @return {Boolean} True if the nodes match, false if they do not.
505
     */
506
    compareTo: function(refNode) {
507
        var node = this._node;
508
 
509
        if (refNode && refNode._node) {
510
            refNode = refNode._node;
511
        }
512
        return node === refNode;
513
    },
514
 
515
    /**
516
     * Determines whether the node is appended to the document.
517
     * @method inDoc
518
     * @param {Node|HTMLElement} doc optional An optional document to check against.
519
     * Defaults to current document.
520
     * @return {Boolean} Whether or not this node is appended to the document.
521
     */
522
    inDoc: function(doc) {
523
        var node = this._node;
524
 
525
        if (node) {
526
            doc = (doc) ? doc._node || doc : node[OWNER_DOCUMENT];
527
            if (doc.documentElement) {
528
                return Y_DOM.contains(doc.documentElement, node);
529
            }
530
        }
531
 
532
        return false;
533
    },
534
 
535
    getById: function(id) {
536
        var node = this._node,
537
            ret = Y_DOM.byId(id, node[OWNER_DOCUMENT]);
538
        if (ret && Y_DOM.contains(node, ret)) {
539
            ret = Y.one(ret);
540
        } else {
541
            ret = null;
542
        }
543
        return ret;
544
    },
545
 
546
   /**
547
     * Returns the nearest ancestor that passes the test applied by supplied boolean method.
548
     * @method ancestor
549
     * @param {String | Function} fn A selector string or boolean method for testing elements.
550
     * If a function is used, it receives the current node being tested as the only argument.
551
     * If fn is not passed as an argument, the parent node will be returned.
552
     * @param {Boolean} testSelf optional Whether or not to include the element in the scan
553
     * @param {String | Function} stopFn optional A selector string or boolean
554
     * method to indicate when the search should stop. The search bails when the function
555
     * returns true or the selector matches.
556
     * If a function is used, it receives the current node being tested as the only argument.
557
     * @return {Node} The matching Node instance or null if not found
558
     */
559
    ancestor: function(fn, testSelf, stopFn) {
560
        // testSelf is optional, check for stopFn as 2nd arg
561
        if (arguments.length === 2 &&
562
                (typeof testSelf == 'string' || typeof testSelf == 'function')) {
563
            stopFn = testSelf;
564
        }
565
 
566
        return Y.one(Y_DOM.ancestor(this._node, _wrapFn(fn), testSelf, _wrapFn(stopFn)));
567
    },
568
 
569
   /**
570
     * Returns the ancestors that pass the test applied by supplied boolean method.
571
     * @method ancestors
572
     * @param {String | Function} fn A selector string or boolean method for testing elements.
573
     * @param {Boolean} testSelf optional Whether or not to include the element in the scan
574
     * If a function is used, it receives the current node being tested as the only argument.
575
     * @return {NodeList} A NodeList instance containing the matching elements
576
     */
577
    ancestors: function(fn, testSelf, stopFn) {
578
        if (arguments.length === 2 &&
579
                (typeof testSelf == 'string' || typeof testSelf == 'function')) {
580
            stopFn = testSelf;
581
        }
582
        return Y.all(Y_DOM.ancestors(this._node, _wrapFn(fn), testSelf, _wrapFn(stopFn)));
583
    },
584
 
585
    /**
586
     * Returns the previous matching sibling.
587
     * Returns the nearest element node sibling if no method provided.
588
     * @method previous
589
     * @param {String | Function} fn A selector or boolean method for testing elements.
590
     * If a function is used, it receives the current node being tested as the only argument.
591
     * @param {Boolean} [all] Whether text nodes as well as element nodes should be returned, or
592
     * just element nodes will be returned(default)
593
     * @return {Node} Node instance or null if not found
594
     */
595
    previous: function(fn, all) {
596
        return Y.one(Y_DOM.elementByAxis(this._node, 'previousSibling', _wrapFn(fn), all));
597
    },
598
 
599
    /**
600
     * Returns the next matching sibling.
601
     * Returns the nearest element node sibling if no method provided.
602
     * @method next
603
     * @param {String | Function} fn A selector or boolean method for testing elements.
604
     * If a function is used, it receives the current node being tested as the only argument.
605
     * @param {Boolean} [all] Whether text nodes as well as element nodes should be returned, or
606
     * just element nodes will be returned(default)
607
     * @return {Node} Node instance or null if not found
608
     */
609
    next: function(fn, all) {
610
        return Y.one(Y_DOM.elementByAxis(this._node, 'nextSibling', _wrapFn(fn), all));
611
    },
612
 
613
    /**
614
     * Returns all matching siblings.
615
     * Returns all siblings if no method provided.
616
     * @method siblings
617
     * @param {String | Function} fn A selector or boolean method for testing elements.
618
     * If a function is used, it receives the current node being tested as the only argument.
619
     * @return {NodeList} NodeList instance bound to found siblings
620
     */
621
    siblings: function(fn) {
622
        return Y.all(Y_DOM.siblings(this._node, _wrapFn(fn)));
623
    },
624
 
625
    /**
626
     * Retrieves a single Node instance, the first element matching the given
627
     * CSS selector.
628
     * Returns null if no match found.
629
     * @method one
630
     *
631
     * @param {string} selector The CSS selector to test against.
632
     * @return {Node | null} A Node instance for the matching HTMLElement or null
633
     * if no match found.
634
     */
635
    one: function(selector) {
636
        return Y.one(Y.Selector.query(selector, this._node, true));
637
    },
638
 
639
    /**
640
     * Retrieves a NodeList based on the given CSS selector.
641
     * @method all
642
     *
643
     * @param {string} selector The CSS selector to test against.
644
     * @return {NodeList} A NodeList instance for the matching HTMLCollection/Array.
645
     */
646
    all: function(selector) {
647
        var nodelist;
648
 
649
        if (this._node) {
650
            nodelist = Y.all(Y.Selector.query(selector, this._node));
651
            nodelist._query = selector;
652
            nodelist._queryRoot = this._node;
653
        }
654
 
655
        return nodelist || Y.all([]);
656
    },
657
 
658
    // TODO: allow fn test
659
    /**
660
     * Test if the supplied node matches the supplied selector.
661
     * @method test
662
     *
663
     * @param {string} selector The CSS selector to test against.
664
     * @return {boolean} Whether or not the node matches the selector.
665
     */
666
    test: function(selector) {
667
        return Y.Selector.test(this._node, selector);
668
    },
669
 
670
    /**
671
     * Removes the node from its parent.
672
     * Shortcut for myNode.get('parentNode').removeChild(myNode);
673
     * @method remove
674
     * @param {Boolean} destroy whether or not to call destroy() on the node
675
     * after removal.
676
     * @chainable
677
     *
678
     */
679
    remove: function(destroy) {
680
        var node = this._node;
681
 
682
        if (node && node.parentNode) {
683
            node.parentNode.removeChild(node);
684
        }
685
 
686
        if (destroy) {
687
            this.destroy();
688
        }
689
 
690
        return this;
691
    },
692
 
693
    /**
694
     * Replace the node with the other node. This is a DOM update only
695
     * and does not change the node bound to the Node instance.
696
     * Shortcut for myNode.get('parentNode').replaceChild(newNode, myNode);
697
     * @method replace
698
     * @param {Node | HTMLElement} newNode Node to be inserted
699
     * @chainable
700
     *
701
     */
702
    replace: function(newNode) {
703
        var node = this._node;
704
        if (typeof newNode == 'string') {
705
            newNode = Y_Node.create(newNode);
706
        }
707
        node.parentNode.replaceChild(Y_Node.getDOMNode(newNode), node);
708
        return this;
709
    },
710
 
711
    /**
712
     * @method replaceChild
713
     * @for Node
714
     * @param {String | HTMLElement | Node} node Node to be inserted
715
     * @param {HTMLElement | Node} refNode Node to be replaced
716
     * @return {Node} The replaced node
717
     */
718
    replaceChild: function(node, refNode) {
719
        if (typeof node == 'string') {
720
            node = Y_DOM.create(node);
721
        }
722
 
723
        return Y.one(this._node.replaceChild(Y_Node.getDOMNode(node), Y_Node.getDOMNode(refNode)));
724
    },
725
 
726
    /**
727
     * Nulls internal node references, removes any plugins and event listeners.
728
     * Note that destroy() will not remove the node from its parent or from the DOM. For that
729
     * functionality, call remove(true).
730
     * @method destroy
731
     * @param {Boolean} recursivePurge (optional) Whether or not to remove listeners from the
732
     * node's subtree (default is false)
733
     *
734
     */
735
    destroy: function(recursive) {
736
        var UID = Y.config.doc.uniqueID ? 'uniqueID' : '_yuid',
737
            instance;
738
 
739
        this.purge(); // TODO: only remove events add via this Node
740
 
741
        if (this.unplug) { // may not be a PluginHost
742
            this.unplug();
743
        }
744
 
745
        this.clearData();
746
 
747
        if (recursive) {
748
            Y.NodeList.each(this.all('*'), function(node) {
749
                instance = Y_Node._instances[node[UID]];
750
                if (instance) {
751
                   instance.destroy();
752
                } else { // purge in case added by other means
753
                    Y.Event.purgeElement(node);
754
                }
755
            });
756
        }
757
 
758
        this._node = null;
759
        this._stateProxy = null;
760
 
761
        delete Y_Node._instances[this._yuid];
762
    },
763
 
764
    /**
765
     * Invokes a method on the Node instance
766
     * @method invoke
767
     * @param {String} method The name of the method to invoke
768
     * @param {any} [args*] Arguments to invoke the method with.
769
     * @return {any} Whatever the underly method returns.
770
     * DOM Nodes and Collections return values
771
     * are converted to Node/NodeList instances.
772
     *
773
     */
774
    invoke: function(method, a, b, c, d, e) {
775
        var node = this._node,
776
            ret;
777
 
778
        if (a && a._node) {
779
            a = a._node;
780
        }
781
 
782
        if (b && b._node) {
783
            b = b._node;
784
        }
785
 
786
        ret = node[method](a, b, c, d, e);
787
        return Y_Node.scrubVal(ret, this);
788
    },
789
 
790
    /**
791
    * @method swap
792
    * @description Swap DOM locations with the given node.
793
    * This does not change which DOM node each Node instance refers to.
794
    * @param {Node} otherNode The node to swap with
795
     * @chainable
796
    */
797
    swap: Y.config.doc.documentElement.swapNode ?
798
        function(otherNode) {
799
            this._node.swapNode(Y_Node.getDOMNode(otherNode));
800
        } :
801
        function(otherNode) {
802
            otherNode = Y_Node.getDOMNode(otherNode);
803
            var node = this._node,
804
                parent = otherNode.parentNode,
805
                nextSibling = otherNode.nextSibling;
806
 
807
            if (nextSibling === node) {
808
                parent.insertBefore(node, otherNode);
809
            } else if (otherNode === node.nextSibling) {
810
                parent.insertBefore(otherNode, node);
811
            } else {
812
                node.parentNode.replaceChild(otherNode, node);
813
                Y_DOM.addHTML(parent, node, nextSibling);
814
            }
815
            return this;
816
        },
817
 
818
 
819
    hasMethod: function(method) {
820
        var node = this._node;
821
        return !!(node && method in node &&
822
                typeof node[method] != 'unknown' &&
823
            (typeof node[method] == 'function' ||
824
                String(node[method]).indexOf('function') === 1)); // IE reports as object, prepends space
825
    },
826
 
827
    isFragment: function() {
828
        return (this.get('nodeType') === 11);
829
    },
830
 
831
    /**
832
     * Removes and destroys all of the nodes within the node.
833
     * @method empty
834
     * @chainable
835
     */
836
    empty: function() {
837
        this.get('childNodes').remove().destroy(true);
838
        return this;
839
    },
840
 
841
    /**
842
     * Returns the DOM node bound to the Node instance
843
     * @method getDOMNode
844
     * @return {HTMLElement}
845
     */
846
    getDOMNode: function() {
847
        return this._node;
848
    }
849
}, true);
850
 
851
Y.Node = Y_Node;
852
Y.one = Y_Node.one;
853
/**
854
 * The NodeList module provides support for managing collections of Nodes.
855
 * @module node
856
 * @submodule node-core
857
 */
858
 
859
/**
860
 * The NodeList class provides a wrapper for manipulating DOM NodeLists.
861
 * NodeList properties can be accessed via the set/get methods.
862
 * Use Y.all() to retrieve NodeList instances.
863
 *
864
 * @class NodeList
865
 * @constructor
866
 * @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.
867
 */
868
 
869
var NodeList = function(nodes) {
870
    var tmp = [];
871
 
872
    if (nodes) {
873
        if (typeof nodes === 'string') { // selector query
874
            this._query = nodes;
875
            nodes = Y.Selector.query(nodes);
876
        } else if (nodes.nodeType || Y_DOM.isWindow(nodes)) { // domNode || window
877
            nodes = [nodes];
878
        } else if (nodes._node) { // Y.Node
879
            nodes = [nodes._node];
880
        } else if (nodes[0] && nodes[0]._node) { // allow array of Y.Nodes
881
            Y.Array.each(nodes, function(node) {
882
                if (node._node) {
883
                    tmp.push(node._node);
884
                }
885
            });
886
            nodes = tmp;
887
        } else { // array of domNodes or domNodeList (no mixed array of Y.Node/domNodes)
888
            nodes = Y.Array(nodes, 0, true);
889
        }
890
    }
891
 
892
    /**
893
     * The underlying array of DOM nodes bound to the Y.NodeList instance
894
     * @property _nodes
895
     * @private
896
     */
897
    this._nodes = nodes || [];
898
};
899
 
900
NodeList.NAME = 'NodeList';
901
 
902
/**
903
 * Retrieves the DOM nodes bound to a NodeList instance
904
 * @method getDOMNodes
905
 * @static
906
 *
907
 * @param {NodeList} nodelist The NodeList instance
908
 * @return {Array} The array of DOM nodes bound to the NodeList
909
 */
910
NodeList.getDOMNodes = function(nodelist) {
911
    return (nodelist && nodelist._nodes) ? nodelist._nodes : nodelist;
912
};
913
 
914
NodeList.each = function(instance, fn, context) {
915
    var nodes = instance._nodes;
916
    if (nodes && nodes.length) {
917
        Y.Array.each(nodes, fn, context || instance);
918
    } else {
919
    }
920
};
921
 
922
NodeList.addMethod = function(name, fn, context) {
923
    if (name && fn) {
924
        NodeList.prototype[name] = function() {
925
            var ret = [],
926
                args = arguments;
927
 
928
            Y.Array.each(this._nodes, function(node) {
929
                var UID = (node.uniqueID && node.nodeType !== 9 ) ? 'uniqueID' : '_yuid',
930
                    instance = Y.Node._instances[node[UID]],
931
                    ctx,
932
                    result;
933
 
934
                if (!instance) {
935
                    instance = NodeList._getTempNode(node);
936
                }
937
                ctx = context || instance;
938
                result = fn.apply(ctx, args);
939
                if (result !== undefined && result !== instance) {
940
                    ret[ret.length] = result;
941
                }
942
            });
943
 
944
            // TODO: remove tmp pointer
945
            return ret.length ? ret : this;
946
        };
947
    } else {
948
    }
949
};
950
 
951
/**
952
 * Import the named method, or methods from the host onto NodeList.
953
 *
954
 * @method importMethod
955
 * @static
956
 * @param {Object} host The object containing the methods to copy. Typically a prototype.
957
 * @param {String|String[]} name The name, or an Array of names of the methods to import onto NodeList.
958
 * @param {String} [altName] An alternative name to use for the method added to NodeList, which may differ from the name
959
 * of the original host object. Has no effect if <em>name</em> is an array of method names.
960
 */
961
NodeList.importMethod = function(host, name, altName) {
962
    if (typeof name === 'string') {
963
        altName = altName || name;
964
        NodeList.addMethod(altName, 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.Node.prototype[method] = function(arg1, arg2, arg3) {
1493
        var ret = this.invoke(method, arg1, arg2, arg3);
1494
        return ret;
1495
    };
1496
});
1497
 
1498
/**
1499
 * Passes through to DOM method.
1500
 * @method removeAttribute
1501
 * @param {String} attribute The attribute to be removed
1502
 * @chainable
1503
 */
1504
 // one-off implementation due to IE returning boolean, breaking chaining
1505
Y.Node.prototype.removeAttribute = function(attr) {
1506
    var node = this._node;
1507
    if (node) {
1508
        node.removeAttribute(attr, 0); // comma zero for IE < 8 to force case-insensitive
1509
    }
1510
 
1511
    return this;
1512
};
1513
 
1514
Y.Node.importMethod(Y.DOM, [
1515
    /**
1516
     * Determines whether the node is an ancestor of another HTML element in the DOM hierarchy.
1517
     * @method contains
1518
     * @param {Node | HTMLElement} needle The possible node or descendent
1519
     * @return {Boolean} Whether or not this node is the needle its ancestor
1520
     */
1521
    'contains',
1522
    /**
1523
     * Allows setting attributes on DOM nodes, normalizing in some cases.
1524
     * This passes through to the DOM node, allowing for custom attributes.
1525
     * @method setAttribute
1526
     * @for Node
1527
     * @chainable
1528
     * @param {string} name The attribute name
1529
     * @param {string} value The value to set
1530
     */
1531
    'setAttribute',
1532
    /**
1533
     * Allows getting attributes on DOM nodes, normalizing in some cases.
1534
     * This passes through to the DOM node, allowing for custom attributes.
1535
     * @method getAttribute
1536
     * @for Node
1537
     * @param {string} name The attribute name
1538
     * @return {string} The attribute value
1539
     */
1540
    'getAttribute',
1541
 
1542
    /**
1543
     * Wraps the given HTML around the node.
1544
     * @method wrap
1545
     * @param {String} html The markup to wrap around the node.
1546
     * @chainable
1547
     * @for Node
1548
     */
1549
    'wrap',
1550
 
1551
    /**
1552
     * Removes the node's parent node.
1553
     * @method unwrap
1554
     * @chainable
1555
     */
1556
    'unwrap',
1557
 
1558
    /**
1559
     * Applies a unique ID to the node if none exists
1560
     * @method generateID
1561
     * @return {String} The existing or generated ID
1562
     */
1563
    'generateID'
1564
]);
1565
 
1566
Y.NodeList.importMethod(Y.Node.prototype, [
1567
/**
1568
 * Allows getting attributes on DOM nodes, normalizing in some cases.
1569
 * This passes through to the DOM node, allowing for custom attributes.
1570
 * @method getAttribute
1571
 * @see Node
1572
 * @for NodeList
1573
 * @param {string} name The attribute name
1574
 * @return {string} The attribute value
1575
 */
1576
 
1577
    'getAttribute',
1578
/**
1579
 * Allows setting attributes on DOM nodes, normalizing in some cases.
1580
 * This passes through to the DOM node, allowing for custom attributes.
1581
 * @method setAttribute
1582
 * @see Node
1583
 * @for NodeList
1584
 * @chainable
1585
 * @param {string} name The attribute name
1586
 * @param {string} value The value to set
1587
 */
1588
    'setAttribute',
1589
 
1590
/**
1591
 * Allows for removing attributes on DOM nodes.
1592
 * This passes through to the DOM node, allowing for custom attributes.
1593
 * @method removeAttribute
1594
 * @see Node
1595
 * @for NodeList
1596
 * @param {string} name The attribute to remove
1597
 */
1598
    'removeAttribute',
1599
/**
1600
 * Removes the parent node from node in the list.
1601
 * @method unwrap
1602
 * @chainable
1603
 */
1604
    'unwrap',
1605
/**
1606
 * Wraps the given HTML around each node.
1607
 * @method wrap
1608
 * @param {String} html The markup to wrap around the node.
1609
 * @chainable
1610
 */
1611
    'wrap',
1612
 
1613
/**
1614
 * Applies a unique ID to each node if none exists
1615
 * @method generateID
1616
 * @return {String} The existing or generated ID
1617
 */
1618
    'generateID'
1619
]);
1620
 
1621
 
1622
}, '3.18.1', {"requires": ["dom-core", "selector"]});