~bcsaller/juju-gui/update-reductions

« back to all changes in this revision

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