~loggerhead-team/loggerhead/trunk-rich

« back to all changes in this revision

Viewing changes to loggerhead/static/javascript/yui/build/node/node-base-debug.js

  • Committer: Matt Nordhoff
  • Date: 2010-02-26 04:37:13 UTC
  • mfrom: (400 trunk)
  • mto: This revision was merged to the branch mainline in revision 401.
  • Revision ID: mnordhoff@mattnordhoff.com-20100226043713-7mw3r6dr9qowutmi
Merge trunk for NEWS

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
Copyright (c) 2008, Yahoo! Inc. All rights reserved.
 
3
Code licensed under the BSD License:
 
4
http://developer.yahoo.net/yui/license.txt
 
5
version: 3.0.0pr2
 
6
*/
 
7
YUI.add('node-base', function(Y) {
 
8
 
 
9
    /**
 
10
     * The Node Utility provides a DOM-like interface for interacting with DOM nodes.
 
11
     * @module node
 
12
     * @submodule node-base
 
13
     */    
 
14
 
 
15
    /**
 
16
     * The Node class provides a wrapper for manipulating DOM Nodes.
 
17
     * Node properties can be accessed via the set/get methods.
 
18
     * Use Y.get() to retrieve Node instances.
 
19
     *
 
20
     * <strong>NOTE:</strong> Node properties are accessed using
 
21
     * the <code>set</code> and <code>get</code> methods.
 
22
     *
 
23
     * @class Node
 
24
     * @constructor
 
25
     */
 
26
 
 
27
    var OWNER_DOCUMENT = 'ownerDocument',
 
28
        TAG_NAME = 'tagName',
 
29
        NODE_NAME = 'nodeName',
 
30
        NODE_TYPE = 'nodeType',
 
31
 
 
32
        Selector = Y.Selector,
 
33
        _instances = {},
 
34
        _restrict = {},
 
35
        _slice = [].slice;
 
36
 
 
37
    // used with previous/next/ancestor tests
 
38
    var _wrapFn = function(fn) {
 
39
        var ret = null;
 
40
        if (fn) {
 
41
            ret = (typeof fn === 'string') ?
 
42
            function(n) {
 
43
                return Y.Selector.test(n, fn);
 
44
            } : 
 
45
            function(n) {
 
46
                return fn(Y.get(n));
 
47
            };
 
48
        }
 
49
 
 
50
        return ret;
 
51
    };
 
52
 
 
53
    var _getDoc = function(node) {
 
54
        var doc = Y.config.doc;
 
55
 
 
56
        if (node) {
 
57
            if (node[NODE_TYPE]) {
 
58
                if (node[NODE_TYPE] === 9) { // already a document node
 
59
                    doc = node;
 
60
                } else {
 
61
                    doc = node[OWNER_DOCUMENT];
 
62
                }
 
63
            } else if (Node[node._yuid]) { // Node instance document
 
64
                doc = Node[node._yuid]()[0];
 
65
            }
 
66
        }
 
67
 
 
68
        return doc;
 
69
    };
 
70
 
 
71
    var _getDOMNode = function(node) {
 
72
        if (node && !node[NODE_TYPE] && node._yuid) {
 
73
            node = Node[node._yuid]()[0];
 
74
        }
 
75
 
 
76
        return  node || null;
 
77
    };
 
78
 
 
79
    var Node = function() {
 
80
        this.init.apply(this, arguments);
 
81
    };
 
82
 
 
83
    Node.PLUGINS = {};
 
84
 
 
85
    Node._deepGet = function (path, val) {
 
86
        var pl = path.length,
 
87
            i;
 
88
 
 
89
        if (pl > 0) {
 
90
            for (i = 0; val !== undefined && i < pl; ++i) {
 
91
                val = val[path[i]];
 
92
            }
 
93
        }
 
94
 
 
95
        return val;
 
96
    };
 
97
 
 
98
    Node._deepSet = function(path, val, subval) {
 
99
        var leafIdx = path.length-1,
 
100
            i,
 
101
            o;
 
102
 
 
103
        if (leafIdx >= 0) {
 
104
            o = val;
 
105
 
 
106
            for (i = 0; o !== undefined && i < leafIdx; ++i) {
 
107
                o = o[path[i]];
 
108
            }
 
109
 
 
110
            if (o !== undefined && o[path[i]] !== undefined) {
 
111
                o[path[i]] = subval;
 
112
            }
 
113
        }
 
114
    };
 
115
 
 
116
    Node.scrubVal = function(val, node, depth) {
 
117
        if (val !== undefined) {
 
118
            if (typeof val === 'object' || typeof val === 'function') { // safari nodeList === function
 
119
                if (val !== null && (
 
120
                        NODE_TYPE in val || // dom node
 
121
                        val.item || // dom collection or Node instance
 
122
                        (val[0] && val[0][NODE_TYPE]) || // assume array of nodes
 
123
                        val.document) // window TODO: restrict?
 
124
                    ) { 
 
125
                    if (node && _restrict && _restrict[node._yuid] && !node.contains(val)) {
 
126
                        val = null; // not allowed to go outside of root node
 
127
                    } else {
 
128
                        if (val[NODE_TYPE] || val.document) { // node or window
 
129
                            val = Node.get(val);
 
130
                        } else {
 
131
                            val = Node.all(val);
 
132
                        }
 
133
                    }
 
134
                } else {
 
135
                    depth = (depth === undefined) ? 4 : depth;
 
136
                    if (depth > 0) {
 
137
                        for (var i in val) {
 
138
                            if (val.hasOwnProperty && val.hasOwnProperty(i)) {
 
139
                                val[i] = Node.scrubVal(val[i], node, --depth);
 
140
                            }
 
141
                        }
 
142
                    }
 
143
                    
 
144
                }
 
145
            }
 
146
        } else {
 
147
            val = node; // for chaining
 
148
        }
 
149
 
 
150
        return val;
 
151
    };
 
152
 
 
153
    Node.setters = {};
 
154
    Node.getters = {
 
155
        /**
 
156
         * Normalizes nodeInnerText and textContent. 
 
157
         * @property text
 
158
         * @type String
 
159
         */
 
160
        'text': function(node) {
 
161
            return Y.DOM.getText(node);
 
162
        },
 
163
 
 
164
        'options': function(node) {
 
165
            return (node) ? node.getElementsByTagName('option') : [];
 
166
        },
 
167
 
 
168
        /**
 
169
         * Returns a NodeList instance. 
 
170
         * @property children
 
171
         * @type NodeList
 
172
         */
 
173
        'children': function(node) {
 
174
            var children = node.children;
 
175
 
 
176
            if (children === undefined) {
 
177
                var childNodes = node.childNodes;
 
178
                children = [];
 
179
 
 
180
                for (var i = 0, len = childNodes.length; i < len; ++i) {
 
181
                    if (childNodes[i][TAG_NAME]) {
 
182
                        children[children.length] = childNodes[i];
 
183
                    }
 
184
                }
 
185
            }
 
186
            return children;
 
187
        }
 
188
    };
 
189
 
 
190
    Node.methods = function(name, fn) {
 
191
        if (typeof name == 'string') {
 
192
            Node.prototype[name] = function() {
 
193
                var args = _slice.call(arguments, 0),
 
194
                    instance = this,
 
195
                    getAll =  (_instances[this._yuid]) ? false : true, // return array of vals for lists
 
196
                    ret = (getAll) ? [] : null,
 
197
                    val;
 
198
 
 
199
                var getValue = function(node) {
 
200
                    args[0] = node;
 
201
                    val = Node.scrubVal(fn.apply(instance, args), instance);
 
202
                    if (getAll) {
 
203
                        ret[ret.length] = val;
 
204
                    } else {
 
205
                        ret = val;
 
206
                    }
 
207
                };
 
208
 
 
209
                args.unshift('');
 
210
                Node[instance._yuid](getValue);
 
211
                return ret;
 
212
            };
 
213
        } else { // assume object
 
214
            Y.each(name, function(fn, name) {
 
215
                Node.methods(name, fn);
 
216
            });
 
217
        }
 
218
 
 
219
    };
 
220
 
 
221
    Node.getDOMNode = _getDOMNode;
 
222
    
 
223
    Node.wrapDOMMethod = function(name) {
 
224
        return function() {
 
225
            return Y.DOM[name].apply(Y.DOM, arguments);
 
226
        };
 
227
 
 
228
    };
 
229
 
 
230
    Node.addDOMMethods = function(methods) {
 
231
        var add = {}; 
 
232
        Y.each(methods, function(v, n) {
 
233
            add[v] = Y.Node.wrapDOMMethod(v);
 
234
        });
 
235
 
 
236
        Y.Node.methods(add);
 
237
    };
 
238
 
 
239
    Node.prototype = {
 
240
        init: function(nodes, doc, isRoot, getAll) {
 
241
            var uid;
 
242
 
 
243
            doc = _getDoc(doc);
 
244
 
 
245
            this.getId = function() {
 
246
                return uid;
 
247
            };
 
248
 
 
249
            var _all = function(fn, i) {
 
250
                if (fn) {
 
251
                    i = i || 0;
 
252
                    for (var node; node = nodes[i++];) {
 
253
                        fn(node);
 
254
                    }
 
255
                }
 
256
                return nodes;
 
257
            };
 
258
 
 
259
            // uid = selector || Y.guid(); // to cache queryAll results
 
260
            uid = Y.guid();
 
261
 
 
262
            if (nodes) { // zero length collection returns null
 
263
                if (nodes[NODE_TYPE] || nodes.document) { // node or window
 
264
                    nodes = [nodes];
 
265
                }
 
266
            } else {
 
267
                nodes = [];
 
268
            }
 
269
 
 
270
            if (!getAll && nodes.length) { // stamp the dom node
 
271
                try { // IE only allows ID on Element
 
272
                    if (nodes[0].uniqueID) {
 
273
                        uid = nodes[0].uniqueID;
 
274
                    }
 
275
                    nodes[0]._yuid = uid;
 
276
                } catch(e) { // not cacheable
 
277
                    Y.log(nodes[0] + ' is not cacheable', 'warn', 'Node'); 
 
278
                }
 
279
            }
 
280
 
 
281
            this._yuid = uid;
 
282
            Node[uid] = _all; // for applying/returning dom nodes
 
283
 
 
284
            if (!getAll) {
 
285
                _instances[uid] = this;
 
286
            }
 
287
 
 
288
            this.initPlugins();
 
289
        },
 
290
 
 
291
        initPlugins: function() {
 
292
            Y.each(Node.PLUGINS, function(config, fn) {
 
293
                this.plug(fn, config);
 
294
            });
 
295
        },
 
296
 
 
297
        /**
 
298
         * Filters the NodeList instance down to only nodes matching the given selector.
 
299
         * @method filter
 
300
         * @param {String} selector The selector to filter against
 
301
         * @return {NodeList} NodeList containing the updated collection 
 
302
         * @see Selector
 
303
         */
 
304
        filter: function(selector) {
 
305
            return Node.scrubVal(Selector.filter(Node[this._yuid](), selector), this);
 
306
        },
 
307
 
 
308
        /**
 
309
         * Applies the given function to each Node in the NodeList.
 
310
         * @method each
 
311
         * @param {Function} fn The function to apply 
 
312
         * @param {Object} context optional An optional context to apply the function with
 
313
         * Default context is the NodeList instance
 
314
         * @return {NodeList} NodeList containing the updated collection 
 
315
         * @chainable
 
316
         */
 
317
        each: function(fn, context) {
 
318
            context = context || this;
 
319
            Node[this._yuid](function(node) {
 
320
                fn.call(context, Node.get(node));
 
321
            });
 
322
        },
 
323
 
 
324
        /**
 
325
         * Returns the current number of items in the NodeList.
 
326
         * @method size
 
327
         * @return {Int} The number of items in the NodeList. 
 
328
         */
 
329
        size: function() {
 
330
            return Node[this._yuid]().length;
 
331
        },
 
332
 
 
333
        /**
 
334
         * Retrieves the Node instance at the given index. 
 
335
         * @method item
 
336
         *
 
337
         * @param {Number} index The index of the target Node.
 
338
         * @return {Node} The Node instance at the given index.
 
339
         */
 
340
        item: function(index) {
 
341
            var node = Node[this._yuid]()[index];
 
342
            return Node.get(node);
 
343
        },
 
344
 
 
345
       /**
 
346
         * Attaches a DOM event handler.
 
347
         * @method attach
 
348
         * @param {String} type The type of DOM Event to listen for 
 
349
         * @param {Function} fn The handler to call when the event fires 
 
350
         * @param {Object} arg An argument object to pass to the handler 
 
351
         */
 
352
 
 
353
        attach: function(type, fn, arg) {
 
354
            var args = _slice.call(arguments, 0);
 
355
            args.splice(2, 0, Node[this._yuid]());
 
356
            return Y.Event.attach.apply(Y.Event, args);
 
357
        },
 
358
 
 
359
       /**
 
360
         * Alias for attach.
 
361
         * @method on
 
362
         * @param {String} type The type of DOM Event to listen for 
 
363
         * @param {Function} fn The handler to call when the event fires 
 
364
         * @param {Object} arg An argument object to pass to the handler 
 
365
         * @see attach
 
366
         */
 
367
        on: function(type, fn, arg) {
 
368
            return this.attach.apply(this, arguments);
 
369
        },
 
370
 
 
371
       /**
 
372
         * Detaches a DOM event handler. 
 
373
         * @method detach
 
374
         * @param {String} type The type of DOM Event
 
375
         * @param {Function} fn The handler to call when the event fires 
 
376
         */
 
377
        detach: function(type, fn) {
 
378
            var args = _slice.call(arguments, 0);
 
379
            args.splice(2, 0, Node[this._yuid]());
 
380
            return Y.Event.detach.apply(Y.Event, args);
 
381
        },
 
382
 
 
383
       /**
 
384
         * Creates a Node instance from HTML string
 
385
         * @method create
 
386
         * @param {String|Array} html The string of html to create
 
387
         * @return {Node} A new Node instance 
 
388
         */
 
389
        create: function(html) {
 
390
            return Y.Node.create(html);
 
391
        },
 
392
 
 
393
        /**
 
394
         * Applies the supplied plugin to the node.
 
395
         * @method plug
 
396
         * @param {Function} The plugin Class to apply
 
397
         * @param {Object} config An optional config to pass to the constructor
 
398
         * @chainable
 
399
         */
 
400
        plug: function(PluginClass, config) {
 
401
            config = config || {};
 
402
            config.owner = this;
 
403
            if (PluginClass && PluginClass.NS) {
 
404
                this[PluginClass.NS] = new PluginClass(config);
 
405
            }
 
406
            return this;
 
407
        },
 
408
 
 
409
        //normalize: function() {},
 
410
        //isSupported: function(feature, version) {},
 
411
        toString: function() {
 
412
            var str = '', 
 
413
            node = Node[this._yuid]()[0] || {};
 
414
 
 
415
            if (node) {
 
416
                str += node[NODE_NAME];
 
417
                if (node.id) {
 
418
                    str += '#' + node.id; 
 
419
                }
 
420
 
 
421
                if (node.className) {
 
422
                    str += '.' + node.className.replace(' ', '.'); 
 
423
                }
 
424
            } else {
 
425
                'no nodes for ' + this._yuid;
 
426
            }
 
427
            return str;
 
428
        }
 
429
    };
 
430
 
 
431
    Node.methods({
 
432
        addEventListener: function() {
 
433
            return Y.Event.nativeAdd.apply(Y.Event, arguments);
 
434
        },
 
435
        
 
436
        removeEventListener: function() {
 
437
            return Y.Event.nativeRemove.apply(Y.Event, arguments);
 
438
        },
 
439
 
 
440
        /**
 
441
         * Set the value of the property/attribute on the HTMLElement bound to this Node.
 
442
         * Only strings/numbers/booleans are passed through unless a SETTER exists.
 
443
         * @method set
 
444
         * @param {String} prop Property to set 
 
445
         * @param {any} val Value to apply to the given property
 
446
         * @chainable
 
447
         */
 
448
        // TODO: document.location.href
 
449
        set: function(node, prop, val) {
 
450
            if (prop.indexOf('.') < 0) {
 
451
                if (prop in Node.setters) { // use custom setter
 
452
                    Node.setters[prop](this, prop, val);  // passing Node instance
 
453
                } else if (node[prop] !== undefined) { // no expandos 
 
454
                    node[prop] = val;
 
455
                } else {
 
456
                    Y.log(prop + ' not in ' + node, 'warn', 'Node');
 
457
                }
 
458
            } else {
 
459
                Node._deepSet(prop.split('.'), node, val);
 
460
            }
 
461
        },
 
462
 
 
463
        /**
 
464
         * Get the value of the property/attribute on the HTMLElement bound to this Node.
 
465
         * Only strings/numbers/booleans are passed through unless a GETTER exists.
 
466
         * @method get
 
467
         * @param {String} prop Property to get 
 
468
         * @return {any} Current value of the property
 
469
         */
 
470
        get: function(node, prop) {
 
471
            var val;
 
472
            if (prop.indexOf('.') < 0) {
 
473
                if (prop in Node.getters) { // use custom getter
 
474
                    val = Node.getters[prop].call(this, node, prop);
 
475
                } else {
 
476
                    val = node[prop];
 
477
                }
 
478
 
 
479
                // method wrapper uses undefined in chaining test
 
480
                if (val === undefined) {
 
481
                    val = null;
 
482
                }
 
483
            } else {
 
484
                val = Node._deepGet(prop.split('.'), node);
 
485
            }
 
486
 
 
487
            return val;
 
488
        },
 
489
 
 
490
        invoke: function(node, method, a, b, c, d, e) {
 
491
            var ret;
 
492
 
 
493
            if (a) { // first 2 may be Node instances
 
494
                a = (a[NODE_TYPE]) ? a : _getDOMNode(a);
 
495
                if (b) {
 
496
                    b = (b[NODE_TYPE]) ? b : _getDOMNode(b);
 
497
                }
 
498
            }
 
499
 
 
500
            ret = node[method](a, b, c, d, e);    
 
501
            return ret;
 
502
        },
 
503
 
 
504
        hasMethod: function(node, method) {
 
505
            return !! node[method];
 
506
        },
 
507
 
 
508
        /**
 
509
         * Retrieves a Node instance of nodes based on the given CSS selector. 
 
510
         * @method query
 
511
         *
 
512
         * @param {string} selector The CSS selector to test against.
 
513
         * @return {Node} A Node instance for the matching HTMLElement.
 
514
         */
 
515
        query: function(node, selector) {
 
516
            var ret = Selector.query(selector, node, true);
 
517
            if (!ret) {
 
518
                ret = null;
 
519
            }
 
520
 
 
521
            return ret;
 
522
        },
 
523
 
 
524
        /**
 
525
         * Retrieves a nodeList based on the given CSS selector. 
 
526
         * @method queryAll
 
527
         * @deprecated Use query() which returns all matches
 
528
         *
 
529
         * @param {string} selector The CSS selector to test against.
 
530
         * @return {NodeList} A NodeList instance for the matching HTMLCollection/Array.
 
531
         */
 
532
        queryAll: function(node, selector) {
 
533
            var ret = Selector.query(selector, node);
 
534
            if (!ret.length) {
 
535
                ret = null;
 
536
            }
 
537
 
 
538
            return ret;
 
539
        },
 
540
 
 
541
        /**
 
542
         * Test if the supplied node matches the supplied selector.
 
543
         * @method test
 
544
         *
 
545
         * @param {string} selector The CSS selector to test against.
 
546
         * @return {boolean} Whether or not the node matches the selector.
 
547
         */
 
548
        test: function(node, selector) {
 
549
            return Selector.test(node, selector);
 
550
        },
 
551
 
 
552
        /**
 
553
         * Compares nodes to determine if they match.
 
554
         * Node instances can be compared to each other and/or HTMLElements.
 
555
         * @method compareTo
 
556
         * @param {HTMLElement | Node} refNode The reference node to compare to the node.
 
557
         * @return {Boolean} True if the nodes match, false if they do not. 
 
558
         */
 
559
        compareTo: function(node, refNode) {
 
560
            refNode = _getDOMNode(refNode) || node;
 
561
            return node === refNode;
 
562
        },
 
563
 
 
564
       /**
 
565
         * Returns the nearest ancestor that passes the test applied by supplied boolean method.
 
566
         * @method ancestor
 
567
         * @param {String | Function} fn A selector or boolean method for testing elements.
 
568
         * If a function is used, it receives the current node being tested as the only argument.
 
569
         * @return {Node} The matching Node instance or null if not found
 
570
         */
 
571
        ancestor: function(node, fn) {
 
572
            return Y.DOM.elementByAxis(node, 'parentNode', _wrapFn(fn));
 
573
        },
 
574
 
 
575
        /**
 
576
         * Returns the previous matching sibling. 
 
577
         * Returns the nearest element node sibling if no method provided.
 
578
         * @method previous
 
579
         * @param {String | Function} fn A selector or boolean method for testing elements.
 
580
         * If a function is used, it receives the current node being tested as the only argument.
 
581
         * @param {Boolean} all optional Whether all node types should be returned, or just element nodes.
 
582
         * @return {Node} Node instance or null if not found
 
583
         */
 
584
        previous: function(node, fn, all) {
 
585
            return Y.DOM.elementByAxis(node, 'previousSibling', _wrapFn(fn), all);
 
586
        }, 
 
587
 
 
588
        /**
 
589
         * Returns the next matching sibling. 
 
590
         * Returns the nearest element node sibling if no method provided.
 
591
         * @method next
 
592
         * @param {String | Function} fn A selector or boolean method for testing elements.
 
593
         * If a function is used, it receives the current node being tested as the only argument.
 
594
         * @param {Boolean} all optional Whether all node types should be returned, or just element nodes.
 
595
         * @return {Node} Node instance or null if not found
 
596
         */
 
597
        next: function(node, fn, all) {
 
598
            return Y.DOM.elementByAxis(node, 'nextSibling', _wrapFn(fn), all);
 
599
        },
 
600
        
 
601
        /**
 
602
         * Determines whether the ndoe is an ancestor of another HTML element in the DOM hierarchy.
 
603
         * @method contains
 
604
         * @param {Node | HTMLElement} needle The possible node or descendent
 
605
         * @return {Boolean} Whether or not this node is the needle its ancestor
 
606
         */
 
607
        contains: function(node, needle) {
 
608
            return Y.DOM.contains(node, _getDOMNode(needle));
 
609
        },
 
610
 
 
611
        /**
 
612
         * Determines whether the node is appended to the document.
 
613
         * @method inDoc
 
614
         * @param {Node|HTMLElement} doc optional An optional document to check against.
 
615
         * Defaults to current document. 
 
616
         * @return {Boolean} Whether or not this node is appended to the document. 
 
617
         */
 
618
        inDoc: function(node, doc) {
 
619
            doc = (doc) ? _getDoc(doc) : node.ownerDocument;
 
620
            if (doc.documentElement) {
 
621
                return Y.DOM.contains(doc.documentElement, node);
 
622
            }
 
623
        },
 
624
 
 
625
        byId: function(node, id) {
 
626
            var ret = node[OWNER_DOCUMENT].getElementById(id);
 
627
            if (!ret || !Y.DOM.contains(node, ret)) {
 
628
                ret = null;
 
629
            }
 
630
            return ret;
 
631
        }
 
632
 
 
633
    });
 
634
 
 
635
    /** 
 
636
     * Creates a Node instance from an HTML string
 
637
     * @method create
 
638
     * @param {String} html HTML string
 
639
     */
 
640
    Node.create = function(html) {
 
641
        return Node.get(Y.DOM.create(html));
 
642
    };
 
643
 
 
644
    Node.getById = function(id, doc) {
 
645
        doc = (doc && doc[NODE_TYPE]) ? doc : Y.config.doc;
 
646
        return Node.get(doc.getElementById(id));
 
647
    };
 
648
 
 
649
    /**
 
650
     * Retrieves a Node instance for the given query or nodes. 
 
651
     * Note: Use 'document' string to retrieve document Node instance from string
 
652
     * @method Y.get
 
653
     * @static
 
654
     * @param {document|HTMLElement|HTMLCollection|Array|String} node The object to wrap.
 
655
     * @param {document|Node} doc optional The document containing the node. Defaults to current document.
 
656
     * @param {boolean} isRoot optional Whether or not this node should be treated as a root node. Root nodes
 
657
     * aren't allowed to traverse outside their DOM tree.
 
658
     * @return {Node} A Node instance bound to the supplied node(s).
 
659
     */
 
660
    Node.get = function(node, doc, isRoot, getAll) {
 
661
        var instance;
 
662
 
 
663
        if (node) {
 
664
            if (typeof node === 'string') {
 
665
                if (node === 'document') { // TODO: allow 'doc'? 'window'?
 
666
                    node = [Y.config.doc];
 
667
                } else {
 
668
                    node = Selector.query(node, doc, !getAll); // Selector arg is getFirst
 
669
                }
 
670
            }
 
671
 
 
672
            if (node) {
 
673
                if (!getAll) { // reuse single element node instances
 
674
                    if (node._yuid) {
 
675
                        // verify IE's uniqueID in case the node was cloned
 
676
                        if (!node.uniqueID || (node.uniqueID === node._yuid)) {
 
677
                            instance = _instances[node._yuid];
 
678
                        }
 
679
                    }
 
680
                }
 
681
 
 
682
                if (!instance) {
 
683
                    instance = new Node(node, doc, isRoot, getAll);
 
684
                }
 
685
 
 
686
                if (instance && isRoot && !getAll) {
 
687
                    _restrict[instance._yuid] = true;
 
688
                }
 
689
            }
 
690
        }
 
691
 
 
692
        // zero length collection returns null
 
693
        return (instance && instance.size()) ? instance : null;
 
694
    };
 
695
 
 
696
    /**
 
697
     * Retrieves a NodeList instance for the given object/string. 
 
698
     * @method Y.all
 
699
     * @static
 
700
     * @param {HTMLCollection|Array|String} node The object to wrap.
 
701
     * @param {document|Node} doc optional The document containing the node. Defaults to current document.
 
702
     * @param {boolean} isRoot optional Whether or not this node should be treated as a root node. Root nodes
 
703
     * @return {NodeList} A NodeList instance for the supplied nodes.
 
704
     */
 
705
    Node.all = function(node, doc, isRoot) {
 
706
        return Node.get.call(Node, node, doc, isRoot, true);
 
707
    };
 
708
 
 
709
    Y.Array.each([
 
710
        /**
 
711
         * Passes through to DOM method.
 
712
         * @method replaceChild
 
713
         * @param {HTMLElement | Node} node Node to be inserted 
 
714
         * @param {HTMLElement | Node} refNode Node to be replaced 
 
715
         * @return {Node} The replaced node 
 
716
         */
 
717
        'replaceChild',
 
718
 
 
719
        /**
 
720
         * Passes through to DOM method.
 
721
         * @method appendChild
 
722
         * @param {HTMLElement | Node} node Node to be appended 
 
723
         * @return {Node} The appended node 
 
724
         */
 
725
        'appendChild',
 
726
 
 
727
        /**
 
728
         * Passes through to DOM method.
 
729
         * @method insertBefore
 
730
         * @param {HTMLElement | Node} newNode Node to be appended 
 
731
         * @param {HTMLElement | Node} refNode Node to be inserted before 
 
732
         * @return {Node} The inserted node 
 
733
         */
 
734
        'insertBefore',
 
735
 
 
736
        /**
 
737
         * Passes through to DOM method.
 
738
         * @method removeChild
 
739
         * @param {HTMLElement | Node} node Node to be removed 
 
740
         * @return {Node} The removed node 
 
741
         */
 
742
        'removeChild',
 
743
 
 
744
        /**
 
745
         * Passes through to DOM method.
 
746
         * @method hasChildNodes
 
747
         * @return {Boolean} Whether or not the node has any childNodes 
 
748
         */
 
749
        'hasChildNodes',
 
750
 
 
751
        /**
 
752
         * Passes through to DOM method.
 
753
         * @method cloneNode
 
754
         * @param {HTMLElement | Node} node Node to be cloned 
 
755
         * @return {Node} The clone 
 
756
         */
 
757
        'cloneNode',
 
758
 
 
759
        /**
 
760
         * Passes through to DOM method.
 
761
         * @method getAttribute
 
762
         * @param {String} attribute The attribute to retrieve 
 
763
         * @return {String} The current value of the attribute 
 
764
         */
 
765
        'getAttribute',
 
766
 
 
767
        /**
 
768
         * Passes through to DOM method.
 
769
         * @method setAttribute
 
770
         * @param {String} attribute The attribute to set 
 
771
         * @param {String} The value to apply to the attribute 
 
772
         * @chainable
 
773
         */
 
774
        'setAttribute',
 
775
 
 
776
        /**
 
777
         * Passes through to DOM method.
 
778
         * @method hasAttribute
 
779
         * @param {String} attribute The attribute to test for 
 
780
         * @return {Boolean} Whether or not the attribute is present 
 
781
         */
 
782
        'hasAttribute',
 
783
 
 
784
        /**
 
785
         * Passes through to DOM method.
 
786
         * @method removeAttribute
 
787
         * @param {String} attribute The attribute to be removed 
 
788
         * @chainable
 
789
         */
 
790
        'removeAttribute',
 
791
 
 
792
        /**
 
793
         * Passes through to DOM method.
 
794
         * @method scrollIntoView
 
795
         * @chainable
 
796
         */
 
797
        'scrollIntoView',
 
798
 
 
799
        /**
 
800
         * Passes through to DOM method.
 
801
         * @method getElementsByTagName
 
802
         * @param {String} tagName The tagName to collect 
 
803
         * @return {NodeList} A NodeList representing the HTMLCollection
 
804
         */
 
805
        'getElementsByTagName',
 
806
 
 
807
        /**
 
808
         * Passes through to DOM method.
 
809
         * @method focus
 
810
         * @chainable
 
811
         */
 
812
        'focus',
 
813
 
 
814
        /**
 
815
         * Passes through to DOM method.
 
816
         * @method blur
 
817
         * @chainable
 
818
         */
 
819
        'blur',
 
820
 
 
821
        /**
 
822
         * Passes through to DOM method.
 
823
         * Only valid on FORM elements
 
824
         * @method submit
 
825
         * @chainable
 
826
         */
 
827
        'submit',
 
828
 
 
829
        /**
 
830
         * Passes through to DOM method.
 
831
         * Only valid on FORM elements
 
832
         * @method reset
 
833
         * @chainable
 
834
         */
 
835
        'reset',
 
836
 
 
837
        /**
 
838
         * Passes through to DOM method.
 
839
         * @method select
 
840
         * @chainable
 
841
         */
 
842
         'select'
 
843
    ], function(method) {
 
844
        Node.prototype[method] = function(arg1, arg2, arg3) {
 
845
            var ret = this.invoke(method, arg1, arg2, arg3);
 
846
            return ret;
 
847
        };
 
848
    });
 
849
 
 
850
    if (!document.documentElement.hasAttribute) {
 
851
        Node.methods({
 
852
            'hasAttribute': function(node, att) {
 
853
                return !! node.getAttribute(att);
 
854
            }
 
855
        });
 
856
    }
 
857
 
 
858
    // used to call Node methods against NodeList nodes
 
859
    Y.Node = Node;
 
860
    Y.all = Y.Node.all;
 
861
    Y.get = Y.Node.get;
 
862
/**
 
863
 * Extended Node interface for managing classNames.
 
864
 * @module node
 
865
 * @submodule node
 
866
 * @for Node
 
867
 */
 
868
 
 
869
    Y.Node.addDOMMethods([
 
870
        /**
 
871
         * Determines whether the node has the given className.
 
872
         * @method hasClass
 
873
         * @param {String} className the class name to search for
 
874
         * @return {Boolean} Whether or not the node has the given class. 
 
875
         */
 
876
        'hasClass',
 
877
 
 
878
        /**
 
879
         * Adds a class name to the node.
 
880
         * @method addClass         
 
881
         * @param {String} className the class name to add to the node's class attribute
 
882
         * @chainable
 
883
         */
 
884
        'addClass',
 
885
 
 
886
        /**
 
887
         * Removes a class name from the node.
 
888
         * @method removeClass         
 
889
         * @param {String} className the class name to remove from the node's class attribute
 
890
         * @chainable
 
891
         */
 
892
        'removeClass',
 
893
 
 
894
        /**
 
895
         * Replace a class with another class.
 
896
         * If no oldClassName is present, the newClassName is simply added.
 
897
         * @method replaceClass  
 
898
         * @param {String} oldClassName the class name to be replaced
 
899
         * @param {String} newClassName the class name that will be replacing the old class name
 
900
         * @chainable
 
901
         */
 
902
        'replaceClass',
 
903
 
 
904
        /**
 
905
         * If the className exists on the node it is removed, if it doesn't exist it is added.
 
906
         * @method toggleClass  
 
907
         * @param {String} className the class name to be toggled
 
908
         * @chainable
 
909
         */
 
910
        'toggleClass'
 
911
    ]);
 
912
 
 
913
 
 
914
}, '3.0.0pr2' ,{requires:['dom-base', 'selector']});