~bac/juju-gui/trunkcopy

« back to all changes in this revision

Viewing changes to lib/yui/build/node-core/node-core.js

  • Committer: kapil.foss at gmail
  • Date: 2012-07-13 18:45:59 UTC
  • Revision ID: kapil.foss@gmail.com-20120713184559-2xl7be17egsrz0c9
reshape

Show diffs side-by-side

added added

removed removed

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