src/cm/media/js/lib/yui/yui_3.0.0b1/build/dom/dom-debug.js
changeset 0 40c8f766c9b8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cm/media/js/lib/yui/yui_3.0.0b1/build/dom/dom-debug.js	Mon Nov 23 15:14:29 2009 +0100
@@ -0,0 +1,2720 @@
+/*
+Copyright (c) 2009, Yahoo! Inc. All rights reserved.
+Code licensed under the BSD License:
+http://developer.yahoo.net/yui/license.txt
+version: 3.0.0b1
+build: 1163
+*/
+YUI.add('dom-base', function(Y) {
+
+(function(Y) {
+/** 
+ * The DOM utility provides a cross-browser abtraction layer
+ * normalizing DOM tasks, and adds extra helper functionality
+ * for other common tasks. 
+ * @module dom
+ * @submodule dom-base
+ *
+ */
+
+/**
+ * Provides DOM helper methods.
+ * @class DOM
+ *
+ */
+var NODE_TYPE = 'nodeType',
+    OWNER_DOCUMENT = 'ownerDocument',
+    DOCUMENT_ELEMENT = 'documentElement',
+    DEFAULT_VIEW = 'defaultView',
+    PARENT_WINDOW = 'parentWindow',
+    TAG_NAME = 'tagName',
+    PARENT_NODE = 'parentNode',
+    FIRST_CHILD = 'firstChild',
+    LAST_CHILD = 'lastChild',
+    PREVIOUS_SIBLING = 'previousSibling',
+    NEXT_SIBLING = 'nextSibling',
+    CONTAINS = 'contains',
+    COMPARE_DOCUMENT_POSITION = 'compareDocumentPosition',
+
+    re_tag = /<([a-z]+)/i;
+
+Y.DOM = {
+    /**
+     * Returns the HTMLElement with the given ID (Wrapper for document.getElementById).
+     * @method byId         
+     * @param {String} id the id attribute 
+     * @param {Object} doc optional The document to search. Defaults to current document 
+     * @return {HTMLElement | null} The HTMLElement with the id, or null if none found. 
+     */
+    byId: function(id, doc) {
+        doc = doc || Y.config.doc;
+        // TODO: IE Name
+        return doc.getElementById(id);
+    },
+
+    /**
+     * Returns the text content of the HTMLElement. 
+     * @method getText         
+     * @param {HTMLElement} element The html element. 
+     * @return {String} The text content of the element (includes text of any descending elements).
+     */
+    getText: (document.documentElement.textContent !== undefined) ?
+        function(element) {
+            var ret = '';
+            if (element) {
+                ret = element.textContent;
+            }
+            return ret || '';
+        } : function(element) {
+            var ret = '';
+            if (element) {
+                ret = element.innerText;
+            }
+            return ret || '';
+        },
+
+    /**
+     * Sets the text content of the HTMLElement. 
+     * @method setText         
+     * @param {HTMLElement} element The html element. 
+     * @param {String} content The content to add. 
+     */
+    setText: (document.documentElement.textContent !== undefined) ?
+        function(element, content) {
+            if (element) {
+                element.textContent = content;
+            }
+        } : function(element, content) {
+            if (element) {
+                element.innerText = content;
+            }
+        },
+
+// TODO: pull out sugar (rely on _childBy, byAxis, etc)?
+    /*
+     * Finds the firstChild of the given HTMLElement. 
+     * @method firstChild
+     * @deprecated Use _childBy
+     * @param {HTMLElement} element The html element. 
+     * @param {Function} fn optional An optional boolean test to apply.
+     * The optional function is passed the current HTMLElement being tested as its only argument.
+     * If no function is given, the first found is returned.
+     * @return {HTMLElement | null} The first matching child html element.
+     */
+    firstChild: function(element, fn) {
+        return Y.DOM._childBy(element, null, fn);
+    },
+
+    // @deprecated Use _childBy
+    firstChildByTag: function(element, tag, fn) {
+        return Y.DOM._childBy(element, tag, fn);
+    },
+
+    /*
+     * Finds the lastChild of the given HTMLElement.
+     * @method lastChild
+     * @deprecated Use _childBy
+     * @param {HTMLElement} element The html element.
+     * @param {String} tag The tag to search for.
+     * @param {Function} fn optional An optional boolean test to apply.
+     * The optional function is passed the current HTMLElement being tested as its only argument.
+     * If no function is given, the first found is returned.
+     * @return {HTMLElement | null} The first matching child html element.
+     */
+    lastChild: function(element, fn) {
+        return Y.DOM._childBy(element, null, fn, true);
+    },
+
+    // @deprecated Use _childBy
+    lastChildByTag: function(element, tag, fn) {
+        return Y.DOM._childBy(element, tag, fn, true);
+    },
+
+    /*
+     * Finds all HTMLElement childNodes matching the given tag.
+     * @method childrenByTag
+     * @deprecated Use Selector
+     * @param {HTMLElement} element The html element.
+     * @param {String} tag The tag to search for.
+     * @param {Function} fn optional An optional boolean test to apply.
+     * The optional function is passed the current HTMLElement being tested as its only argument.
+     * If no function is given, all children with the given tag are collected.
+     * @return {Array} The collection of child elements.
+     * TODO: Webkit children.tags() returns grandchildren
+     */
+    _childrenByTag: function() {
+        if (document[DOCUMENT_ELEMENT].children) {
+            return function(element, tag, fn, toArray) { // TODO: keep toArray option?
+                tag = (tag && tag !== '*') ? tag.toUpperCase() : null;
+                var elements = [],
+                    wrapFn = fn;
+                if (element) {
+                    if (tag && !Y.UA.webkit) { // children.tags() broken in safari
+                        elements = element.children.tags(tag);
+                    } else {
+                        elements = element.children;
+                        if (tag) {
+                            wrapFn = function(el) {
+                                return el[TAG_NAME].toUpperCase() === tag && (!fn || fn(el));
+                            };
+                        }
+                    }
+
+                    elements = Y.DOM.filterElementsBy(elements, wrapFn);
+                }
+
+                return elements;
+            };
+        } else {
+            return function(element, tag, fn) {
+                tag = (tag && tag !== '*') ? tag.toUpperCase() : null;
+                var elements = [],
+                    wrapFn = fn;
+
+                if (element) {
+                    elements = element.childNodes; 
+                    if (tag) { // wrap fn and add tag test TODO: allow tag in filterElementsBy?
+                        wrapFn = function(el) {
+                            return el[TAG_NAME].toUpperCase() === tag && (!fn || fn(el));
+                        };
+                    }
+
+                    elements = Y.DOM.filterElementsBy(elements, wrapFn);
+                }
+                return elements;
+            };
+        }
+    }(),
+
+    /*
+     * Finds all HTMLElement childNodes.
+     * @method children
+     * @deprecated Use Selector
+     * @param {HTMLElement} element The html element.
+     * @param {Function} fn optional An optional boolean test to apply.
+     * The optional function is passed the current HTMLElement being tested as its only argument.
+     * If no function is given, all children are collected.
+     * @return {Array} The collection of child elements.
+     */
+    children: function(element, fn) {
+        return Y.DOM._childrenByTag(element, null, fn);
+    },
+
+    /*
+     * Finds the previous sibling of the element.
+     * @method previous
+     * @deprecated Use elementByAxis
+     * @param {HTMLElement} element The html element.
+     * @param {Function} fn optional An optional boolean test to apply.
+     * The optional function is passed the current DOM node being tested as its only argument.
+     * If no function is given, the first sibling is returned.
+     * @param {Boolean} all optional Whether all node types should be scanned, or just element nodes.
+     * @return {HTMLElement | null} The matching DOM node or null if none found. 
+     */
+    previous: function(element, fn, all) {
+        return Y.DOM.elementByAxis(element, PREVIOUS_SIBLING, fn, all);
+    },
+
+    /*
+     * Finds the next sibling of the element.
+     * @method next
+     * @deprecated Use elementByAxis
+     * @param {HTMLElement} element The html element.
+     * @param {Function} fn optional An optional boolean test to apply.
+     * The optional function is passed the current DOM node being tested as its only argument.
+     * If no function is given, the first sibling is returned.
+     * @param {Boolean} all optional Whether all node types should be scanned, or just element nodes.
+     * @return {HTMLElement | null} The matching DOM node or null if none found. 
+     */
+    next: function(element, fn, all) {
+        return Y.DOM.elementByAxis(element, NEXT_SIBLING, fn, all);
+    },
+
+    /*
+     * Finds the ancestor of the element.
+     * @method ancestor
+     * @deprecated Use elementByAxis
+     * @param {HTMLElement} element The html element.
+     * @param {Function} fn optional An optional boolean test to apply.
+     * The optional function is passed the current DOM node being tested as its only argument.
+     * If no function is given, the parentNode is returned.
+     * @param {Boolean} all optional Whether all node types should be scanned, or just element nodes.
+     * @return {HTMLElement | null} The matching DOM node or null if none found. 
+     */
+     // TODO: optional stopAt node?
+    ancestor: function(element, fn, all) {
+        return Y.DOM.elementByAxis(element, PARENT_NODE, fn, all);
+    },
+
+    /**
+     * Searches the element by the given axis for the first matching element.
+     * @method elementByAxis
+     * @param {HTMLElement} element The html element.
+     * @param {String} axis The axis to search (parentNode, nextSibling, previousSibling).
+     * @param {Function} fn optional An optional boolean test to apply.
+     * @param {Boolean} all optional Whether all node types should be returned, or just element nodes.
+     * The optional function is passed the current HTMLElement being tested as its only argument.
+     * If no function is given, the first element is returned.
+     * @return {HTMLElement | null} The matching element or null if none found.
+     */
+    elementByAxis: function(element, axis, fn, all) {
+        while (element && (element = element[axis])) { // NOTE: assignment
+                if ( (all || element[TAG_NAME]) && (!fn || fn(element)) ) {
+                    return element;
+                }
+        }
+        return null;
+    },
+
+    /*
+     * Finds all elements with the given tag.
+     * @method byTag
+     * @deprecated Use Selector
+     * @param {String} tag The tag being search for. 
+     * @param {HTMLElement} root optional An optional root element to start from.
+     * @param {Function} fn optional An optional boolean test to apply.
+     * The optional function is passed the current HTMLElement being tested as its only argument.
+     * If no function is given, all elements with the given tag are returned.
+     * @return {Array} The collection of matching elements.
+     */
+    byTag: function(tag, root, fn) {
+        root = root || Y.config.doc;
+
+        var elements = root.getElementsByTagName(tag),
+            retNodes = [],
+            i, len;
+
+        for (i = 0, len = elements.length; i < len; ++i) {
+            if ( !fn || fn(elements[i]) ) {
+                retNodes[retNodes.length] = elements[i];
+            }
+        }
+        return retNodes;
+    },
+
+    /*
+     * Finds the first element with the given tag.
+     * @method firstByTag
+     * @deprecated Use Selector
+     * @param {String} tag The tag being search for. 
+     * @param {HTMLElement} root optional An optional root element to start from.
+     * @param {Function} fn optional An optional boolean test to apply.
+     * The optional function is passed the current HTMLElement being tested as its only argument.
+     * If no function is given, the first match is returned. 
+     * @return {HTMLElement} The matching element.
+     */
+    firstByTag: function(tag, root, fn) {
+        root = root || Y.config.doc;
+
+        var elements = root.getElementsByTagName(tag),
+            ret = null,
+            i, len;
+
+        for (i = 0, len = elements.length; i < len; ++i) {
+            if ( !fn || fn(elements[i]) ) {
+                ret = elements[i];
+                break;
+            }
+        }
+        return ret;
+    },
+
+    /*
+     * Filters a collection of HTMLElements by the given attributes.
+     * @method filterElementsBy
+     * @param {Array} elements The collection of HTMLElements to filter.
+     * @param {Function} fn A boolean test to apply.
+     * The function is passed the current HTMLElement being tested as its only argument.
+     * If no function is given, all HTMLElements are kept.
+     * @return {Array} The filtered collection of HTMLElements.
+     */
+    filterElementsBy: function(elements, fn, firstOnly) {
+        var ret = (firstOnly) ? null : [],
+            i, len;
+        for (i = 0, len = elements.length; i < len; ++i) {
+            if (elements[i][TAG_NAME] && (!fn || fn(elements[i]))) {
+                if (firstOnly) {
+                    ret = elements[i];
+                    break;
+                } else {
+                    ret[ret.length] = elements[i];
+                }
+            }
+        }
+
+        return ret;
+    },
+
+    /**
+     * Determines whether or not one HTMLElement is or contains another HTMLElement.
+     * @method contains
+     * @param {HTMLElement} element The containing html element.
+     * @param {HTMLElement} needle The html element that may be contained.
+     * @return {Boolean} Whether or not the element is or contains the needle.
+     */
+    contains: function(element, needle) {
+        var ret = false;
+
+        if ( !needle || !element || !needle[NODE_TYPE] || !element[NODE_TYPE]) {
+            ret = false;
+        } else if (element[CONTAINS])  {
+            if (Y.UA.opera || needle[NODE_TYPE] === 1) { // IE & SAF contains fail if needle not an ELEMENT_NODE
+                ret = element[CONTAINS](needle);
+            } else {
+                ret = Y.DOM._bruteContains(element, needle); 
+            }
+        } else if (element[COMPARE_DOCUMENT_POSITION]) { // gecko
+            if (element === needle || !!(element[COMPARE_DOCUMENT_POSITION](needle) & 16)) { 
+                ret = true;
+            }
+        }
+
+        return ret;
+    },
+
+    /**
+     * Determines whether or not the HTMLElement is part of the document.
+     * @method inDoc
+     * @param {HTMLElement} element The containing html element.
+     * @param {HTMLElement} doc optional The document to check.
+     * @return {Boolean} Whether or not the element is attached to the document. 
+     */
+    inDoc: function(element, doc) {
+        doc = doc || element[OWNER_DOCUMENT];
+        var id = element.id;
+        if (!id) { // TODO: remove when done?
+            id = element.id = Y.guid();
+        }
+
+        return !! (doc.getElementById(id));
+    },
+
+    /**
+     * Inserts the new node as the previous sibling of the reference node 
+     * @method insertBefore
+     * @param {String | HTMLElement} newNode The node to be inserted
+     * @param {String | HTMLElement} referenceNode The node to insert the new node before 
+     * @return {HTMLElement} The node that was inserted (or null if insert fails) 
+     */
+    insertBefore: function(newNode, referenceNode) {
+        var ret = null,
+            parent;
+        if (newNode && referenceNode && (parent = referenceNode.parentNode)) { // NOTE: assignment
+            if (typeof newNode === 'string') {
+                newNode = Y.DOM.create(newNode);
+            }
+            ret = parent.insertBefore(newNode, referenceNode);
+        } else {
+            Y.log('insertBefore failed: missing or invalid arg(s)', 'error', 'dom');
+        }
+        return ret;
+    },
+
+    /**
+     * Inserts the new node as the next sibling of the reference node 
+     * @method insertAfter
+     * @param {String | HTMLElement} newNode The node to be inserted
+     * @param {String | HTMLElement} referenceNode The node to insert the new node after 
+     * @return {HTMLElement} The node that was inserted (or null if insert fails) 
+     */
+    insertAfter: function(newNode, referenceNode) {
+        if (!newNode || !referenceNode || !referenceNode[PARENT_NODE]) {
+            Y.log('insertAfter failed: missing or invalid arg(s)', 'error', 'DOM');
+            return null;
+        }       
+
+        if (typeof newNode === 'string') {
+            newNode = Y.DOM.create(newNode);
+        }
+
+        if (referenceNode[NEXT_SIBLING]) {
+            return referenceNode[PARENT_NODE].insertBefore(newNode, referenceNode[NEXT_SIBLING]); 
+        } else {
+            return referenceNode[PARENT_NODE].appendChild(newNode);
+        }
+    },
+
+    /**
+     * Creates a new dom node using the provided markup string. 
+     * @method create
+     * @param {String} html The markup used to create the element
+     * @param {HTMLDocument} doc An optional document context 
+     */
+    create: function(html, doc) {
+        html = Y.Lang.trim(html); // match IE which trims whitespace from innerHTML
+        if (!doc && Y.DOM._cloneCache[html]) {
+            return Y.DOM._cloneCache[html].cloneNode(true); // NOTE: return
+        }
+
+        doc = doc || Y.config.doc;
+        var m = re_tag.exec(html),
+            create = Y.DOM._create,
+            custom = Y.DOM.creators,
+            ret = null,
+            tag, nodes;
+
+        if (m && custom[m[1]]) {
+            if (typeof custom[m[1]] === 'function') {
+                create = custom[m[1]];
+            } else {
+                tag = custom[m[1]];
+            }
+        }
+
+        nodes = create(html, doc, tag).childNodes;
+
+        if (nodes.length === 1) { // return single node, breaking parentNode ref from "fragment"
+            ret = nodes[0].parentNode.removeChild(nodes[0]);
+        } else { // return multiple nodes as a fragment
+            ret = doc.createDocumentFragment();
+            while (nodes.length) {
+                ret.appendChild(nodes[0]); 
+            }
+        }
+
+        Y.DOM._cloneCache[html] = ret.cloneNode(true);
+        return ret;
+    },
+
+    CUSTOM_ATTRIBUTES: (!document.documentElement.hasAttribute) ? { // IE < 8
+        'for': 'htmlFor',
+        'class': 'className'
+    } : { // w3c
+        'htmlFor': 'for',
+        'className': 'class'
+    },
+
+    /**
+     * Provides a normalized attribute interface. 
+     * @method setAttibute
+     * @param {String | HTMLElement} el The target element for the attribute.
+     * @param {String} attr The attribute to set.
+     * @param {String} val The value of the attribute.
+     */
+    setAttribute: function(el, attr, val) {
+        if (el && el.setAttribute) {
+            attr = Y.DOM.CUSTOM_ATTRIBUTES[attr] || attr;
+            el.setAttribute(attr, val);
+        }
+    },
+
+
+    /**
+     * Provides a normalized attribute interface. 
+     * @method getAttibute
+     * @param {String | HTMLElement} el The target element for the attribute.
+     * @param {String} attr The attribute to get.
+     * @return {String} The current value of the attribute. 
+     */
+    getAttribute: function(el, attr) {
+        var ret = '';
+        if (el && el.getAttribute) {
+            attr = Y.DOM.CUSTOM_ATTRIBUTES[attr] || attr;
+            ret = el.getAttribute(attr, 2);
+
+            if (ret === null) {
+                ret = ''; // per DOM spec
+            }
+        }
+        return ret;
+    },
+
+    // @deprecated
+    srcIndex: (document.documentElement.sourceIndex) ?
+        function(node) {
+            return (node && node.sourceIndex) ? node.sourceIndex : null;
+        } :
+        function(node) {
+            return (node && node[OWNER_DOCUMENT]) ? 
+                    [].indexOf.call(node[OWNER_DOCUMENT].
+                            getElementsByTagName('*'), node) : null;
+        },
+
+    isWindow: function(obj) {
+        return obj.alert && obj.document;
+    },
+
+    _fragClones: {
+        div: document.createElement('div')
+    },
+
+    _create: function(html, doc, tag) {
+        tag = tag || 'div';
+
+        var frag = Y.DOM._fragClones[tag];
+        if (frag) {
+            frag = frag.cloneNode(false);
+        } else {
+            frag = Y.DOM._fragClones[tag] = doc.createElement(tag);
+        }
+        frag.innerHTML = html;
+        return frag;
+    },
+
+    _removeChildNodes: function(node) {
+        while (node.firstChild) {
+            node.removeChild(node.firstChild);
+        }
+    },
+
+    _cloneCache: {},
+
+    /**
+     * Inserts content in a node at the given location 
+     * @method addHTML
+     * @param {HTMLElement} node The node to insert into
+     * @param {String} content The content to be inserted 
+     * @param {String} where Where to insert the content; default is after lastChild 
+     */
+    addHTML: function(node, content, where) {
+        if (typeof content === 'string') {
+            content = Y.Lang.trim(content); // match IE which trims whitespace from innerHTML
+        }
+
+        var newNode = Y.DOM._cloneCache[content];
+            
+        if (newNode) {
+            newNode = newNode.cloneNode(true);
+        } else {
+            if (content.nodeType) { // domNode
+                newNode = content;
+            } else { // create from string and cache
+                newNode = Y.DOM.create(content);
+            }
+        }
+
+        if (where) {
+            if (where.nodeType) { // insert regardless of relationship to node
+                // TODO: check if node.contains(where)?
+                where.parentNode.insertBefore(newNode, where);
+            } else {
+                switch (where) {
+                    case 'replace':
+                        while (node.firstChild) {
+                            node.removeChild(node.firstChild);
+                        }
+                        node.appendChild(newNode);
+                        break;
+                    case 'before':
+                        node.parentNode.insertBefore(newNode, node);
+                        break;
+                    case 'after':
+                        if (node.nextSibling) { // IE errors if refNode is null
+                            node.parentNode.insertBefore(newNode, node.nextSibling);
+                        } else {
+                            node.parentNode.appendChild(newNode);
+                        }
+                        break;
+                    default:
+                        node.appendChild(newNode);
+                }
+            }
+        } else {
+            node.appendChild(newNode);
+        }
+
+        return newNode;
+    },
+
+    VALUE_SETTERS: {},
+
+    VALUE_GETTERS: {},
+
+    getValue: function(node) {
+        var ret = '', // TODO: return null?
+            getter;
+
+        if (node && node[TAG_NAME]) {
+            getter = Y.DOM.VALUE_GETTERS[node[TAG_NAME].toLowerCase()];
+
+            if (getter) {
+                ret = getter(node);
+            } else {
+                ret = node.value;
+            }
+        }
+
+        return (typeof ret === 'string') ? ret : '';
+    },
+
+    setValue: function(node, val) {
+        var setter;
+
+        if (node && node[TAG_NAME]) {
+            setter = Y.DOM.VALUE_SETTERS[node[TAG_NAME].toLowerCase()];
+
+            if (setter) {
+                setter(node, val);
+            } else {
+                node.value = val;
+            }
+        }
+    },
+
+    _stripScripts: function(node) {
+        var scripts = node.getElementsByTagName('script'),
+            i, script;
+
+        for (i = 0, script; script = scripts[i++];) {
+            script.parentNode.removeChild(script);
+        }
+    },
+
+    _execScripts: function(scripts, startIndex) {
+        var newScript,
+            i, script;
+
+        startIndex = startIndex || 0;
+
+        for (i = startIndex, script; script = scripts[i++];) {
+            newScript = script.ownerDocument.createElement('script');
+            script.parentNode.replaceChild(newScript, script);
+            if (script.text) {
+                newScript.text = script.text;
+            } else if (script.src) {
+                newScript.src = script.src;
+
+                 // "pause" while loading to ensure exec order 
+                // FF reports typeof onload as "undefined", so try IE first
+                if (typeof newScript.onreadystatechange !== 'undefined') {
+                    newScript.onreadystatechange = function() {
+                        if (/loaded|complete/.test(script.readyState)) {
+                            event.srcElement.onreadystatechange = null; 
+                            // timer to help ensure exec order
+                            setTimeout(function() {
+                                Y.DOM._execScripts(scripts, i++);
+                            }, 0);
+                        }
+                    };
+                } else {
+                    newScript.onload = function(e) {
+                        e.target.onload = null; 
+                        Y.DOM._execScripts(scripts, i++);
+                    };
+                }
+                return; // NOTE: early return to chain async loading
+            }
+        }
+    },
+
+    /**
+     * Brute force version of contains.
+     * Used for browsers without contains support for non-HTMLElement Nodes (textNodes, etc).
+     * @method _bruteContains
+     * @private
+     * @param {HTMLElement} element The containing html element.
+     * @param {HTMLElement} needle The html element that may be contained.
+     * @return {Boolean} Whether or not the element is or contains the needle.
+     */
+    _bruteContains: function(element, needle) {
+        while (needle) {
+            if (element === needle) {
+                return true;
+            }
+            needle = needle.parentNode;
+        }
+        return false;
+    },
+
+// TODO: move to Lang?
+    /**
+     * Memoizes dynamic regular expressions to boost runtime performance. 
+     * @method _getRegExp
+     * @private
+     * @param {String} str The string to convert to a regular expression.
+     * @param {String} flags optional An optinal string of flags.
+     * @return {RegExp} An instance of RegExp
+     */
+    _getRegExp: function(str, flags) {
+        flags = flags || '';
+        Y.DOM._regexCache = Y.DOM._regexCache || {};
+        if (!Y.DOM._regexCache[str + flags]) {
+            Y.DOM._regexCache[str + flags] = new RegExp(str, flags);
+        }
+        return Y.DOM._regexCache[str + flags];
+    },
+
+// TODO: make getDoc/Win true privates?
+    /**
+     * returns the appropriate document.
+     * @method _getDoc
+     * @private
+     * @param {HTMLElement} element optional Target element.
+     * @return {Object} The document for the given element or the default document. 
+     */
+    _getDoc: function(element) {
+        element = element || {};
+
+        return (element[NODE_TYPE] === 9) ? element : // element === document
+                element[OWNER_DOCUMENT] || // element === DOM node
+                element.document || // element === window
+                Y.config.doc; // default
+    },
+
+    /**
+     * returns the appropriate window.
+     * @method _getWin
+     * @private
+     * @param {HTMLElement} element optional Target element.
+     * @return {Object} The window for the given element or the default window. 
+     */
+    _getWin: function(element) {
+        var doc = Y.DOM._getDoc(element);
+        return doc[DEFAULT_VIEW] || doc[PARENT_WINDOW] || Y.config.win;
+    },
+
+    // @deprecated, use Selector 
+    _childBy: function(element, tag, fn, rev) {
+        var ret = null,
+            root, axis;
+
+        if (element) {
+            if (rev) {
+                root = element[LAST_CHILD];
+                axis = PREVIOUS_SIBLING;
+            } else {
+                root = element[FIRST_CHILD];
+                axis = NEXT_SIBLING;
+            }
+
+            if (Y.DOM._testElement(root, tag, fn)) { // is the matching element
+                ret = root;
+            } else { // need to scan nextSibling axis of firstChild to find matching element
+                ret = Y.DOM.elementByAxis(root, axis, fn);
+            }
+        }
+        return ret;
+
+    },
+
+    _batch: function(nodes, fn, arg1, arg2, arg3, etc) {
+        fn = (typeof name === 'string') ? Y.DOM[fn] : fn;
+        var result,
+            ret = [];
+
+        if (fn && nodes) {
+            Y.each(nodes, function(node) {
+                if ((result = fn.call(Y.DOM, node, arg1, arg2, arg3, etc)) !== undefined) {
+                    ret[ret.length] = result;
+                }
+            });
+        }
+
+        return ret.length ? ret : nodes;
+    },
+
+    _testElement: function(element, tag, fn) {
+        tag = (tag && tag !== '*') ? tag.toUpperCase() : null;
+        return (element && element[TAG_NAME] &&
+                (!tag || element[TAG_NAME].toUpperCase() === tag) &&
+                (!fn || fn(element)));
+    },
+
+    creators: {},
+
+    _IESimpleCreate: function(html, doc) {
+        doc = doc || Y.config.doc;
+        return doc.createElement(html);
+    }
+};
+
+
+(function(Y) {
+    var creators = Y.DOM.creators,
+        create = Y.DOM.create,
+        re_tbody = /(?:\/(?:thead|tfoot|tbody|caption|col|colgroup)>)+\s*<tbody/,
+
+        TABLE_OPEN = '<table>',
+        TABLE_CLOSE = '</table>';
+
+    if (Y.UA.gecko || Y.UA.ie) { // require custom creation code for certain element types
+        Y.mix(creators, {
+            option: function(html, doc) {
+                return create('<select>' + html + '</select>', doc);
+            },
+
+            tr: function(html, doc) {
+                return create('<tbody>' + html + '</tbody>', doc);
+            },
+
+            td: function(html, doc) {
+                return create('<tr>' + html + '</tr>', doc);
+            }, 
+
+            tbody: function(html, doc) {
+                return create(TABLE_OPEN + html + TABLE_CLOSE, doc);
+            },
+
+            legend: 'fieldset'
+        });
+
+        creators.col = creators.tbody; // IE wraps in colgroup
+    }
+
+    if (Y.UA.ie) {
+        Y.mix(creators, {
+        // TODO: thead/tfoot with nested tbody
+            // IE adds TBODY when creating TABLE elements (which may share this impl)
+            tbody: function(html, doc) {
+                var frag = create(TABLE_OPEN + html + TABLE_CLOSE, doc),
+                    tb = frag.children.tags('tbody')[0];
+
+                if (frag.children.length > 1 && tb && !re_tbody.test(html)) {
+                    tb[PARENT_NODE].removeChild(tb); // strip extraneous tbody
+                }
+                return frag;
+            },
+
+            script: function(html, doc) {
+                var frag = doc.createElement('div');
+
+                frag.innerHTML = '-' + html;
+                frag.removeChild(frag[FIRST_CHILD]);
+                return frag;
+            }
+
+        }, true);
+
+        Y.mix(Y.DOM.VALUE_GETTERS, {
+            button: function(node) {
+                return (node.attributes && node.attributes.value) ? node.attributes.value.value : '';
+            }
+        });
+
+        Y.mix(Y.DOM.VALUE_SETTERS, {
+            // IE: node.value changes the button text, which should be handled via innerHTML
+            button: function(node, val) {
+                var attr = node.attributes.value;
+                if (!attr) {
+                    attr = node[OWNER_DOCUMENT].createAttribute('value');
+                    node.setAttributeNode(attr);
+                }
+
+                attr.value = val;
+            }
+        });
+    }
+
+    if (Y.UA.gecko || Y.UA.ie) {
+        Y.mix(creators, {
+                th: creators.td,
+                thead: creators.tbody,
+                tfoot: creators.tbody,
+                caption: creators.tbody,
+                colgroup: creators.tbody,
+                col: creators.tbody,
+                optgroup: creators.option
+        });
+    }
+
+    Y.mix(Y.DOM.VALUE_GETTERS, {
+        option: function(node) {
+            var attrs = node.attributes;
+            return (attrs.value && attrs.value.specified) ? node.value : node.text;
+        },
+
+        select: function(node) {
+            var val = node.value,
+                options = node.options;
+
+            if (options && val === '') {
+                if (node.multiple) {
+                    Y.log('multiple select normalization not implemented', 'warn', 'DOM');
+                } else {
+                    val = Y.DOM.getValue(options[node.selectedIndex], 'value');
+                }
+            }
+
+            return val;
+        }
+    });
+})(Y);
+
+})(Y);
+Y.mix(Y.DOM, {
+    /**
+     * Determines whether a DOM element has the given className.
+     * @method hasClass
+     * @param {HTMLElement} element The DOM element. 
+     * @param {String} className the class name to search for
+     * @return {Boolean} Whether or not the element has the given class. 
+     */
+    hasClass: function(node, className) {
+        var re = Y.DOM._getRegExp('(?:^|\\s+)' + className + '(?:\\s+|$)');
+        return re.test(node.className);
+    },
+
+    /**
+     * Adds a class name to a given DOM element.
+     * @method addClass         
+     * @param {HTMLElement} element The DOM element. 
+     * @param {String} className the class name to add to the class attribute
+     */
+    addClass: function(node, className) {
+        if (!Y.DOM.hasClass(node, className)) { // skip if already present 
+            node.className = Y.Lang.trim([node.className, className].join(' '));
+        }
+    },
+
+    /**
+     * Removes a class name from a given element.
+     * @method removeClass         
+     * @param {HTMLElement} element The DOM element. 
+     * @param {String} className the class name to remove from the class attribute
+     */
+    removeClass: function(node, className) {
+        if (className && Y.DOM.hasClass(node, className)) {
+            node.className = Y.Lang.trim(node.className.replace(Y.DOM._getRegExp('(?:^|\\s+)' +
+                            className + '(?:\\s+|$)'), ' '));
+
+            if ( Y.DOM.hasClass(node, className) ) { // in case of multiple adjacent
+                Y.DOM.removeClass(node, className);
+            }
+        }                 
+    },
+
+    /**
+     * Replace a class with another class for a given element.
+     * If no oldClassName is present, the newClassName is simply added.
+     * @method replaceClass  
+     * @param {HTMLElement} element The DOM element. 
+     * @param {String} oldClassName the class name to be replaced
+     * @param {String} newClassName the class name that will be replacing the old class name
+     */
+    replaceClass: function(node, oldC, newC) {
+        //Y.log('replaceClass replacing ' + oldC + ' with ' + newC, 'info', 'Node');
+        Y.DOM.addClass(node, newC);
+        Y.DOM.removeClass(node, oldC);
+    },
+
+    /**
+     * If the className exists on the node it is removed, if it doesn't exist it is added.
+     * @method toggleClass  
+     * @param {HTMLElement} element The DOM element. 
+     * @param {String} className the class name to be toggled
+     */
+    toggleClass: function(node, className) {
+        if (Y.DOM.hasClass(node, className)) {
+            Y.DOM.removeClass(node, className);
+        } else {
+            Y.DOM.addClass(node, className);
+        }
+    }
+});
+
+
+
+}, '3.0.0b1' ,{requires:['event'], skinnable:false});
+YUI.add('dom-style', function(Y) {
+
+(function(Y) {
+/** 
+ * Add style management functionality to DOM.
+ * @module dom
+ * @submodule dom-style
+ * @for DOM
+ */
+
+var DOCUMENT_ELEMENT = 'documentElement',
+    DEFAULT_VIEW = 'defaultView',
+    OWNER_DOCUMENT = 'ownerDocument',
+    STYLE = 'style',
+    FLOAT = 'float',
+    CSS_FLOAT = 'cssFloat',
+    STYLE_FLOAT = 'styleFloat',
+    TRANSPARENT = 'transparent',
+    GET_COMPUTED_STYLE = 'getComputedStyle',
+
+    DOCUMENT = Y.config.doc,
+    UNDEFINED = undefined,
+
+    re_color = /color$/i;
+
+
+Y.mix(Y.DOM, {
+    CUSTOM_STYLES: {
+    },
+
+
+    /**
+     * Sets a style property for a given element.
+     * @method setStyle
+     * @param {HTMLElement} An HTMLElement to apply the style to.
+     * @param {String} att The style property to set. 
+     * @param {String|Number} val The value. 
+     */
+    setStyle: function(node, att, val, style) {
+        style = style || node.style;
+        var CUSTOM_STYLES = Y.DOM.CUSTOM_STYLES;
+
+        if (style) {
+            if (val === null) {
+                val = ''; // normalize for unsetting
+            }
+            if (att in CUSTOM_STYLES) {
+                if (CUSTOM_STYLES[att].set) {
+                    CUSTOM_STYLES[att].set(node, val, style);
+                    return; // NOTE: return
+                } else if (typeof CUSTOM_STYLES[att] === 'string') {
+                    att = CUSTOM_STYLES[att];
+                }
+            }
+            style[att] = val; 
+        }
+    },
+
+    /**
+     * Returns the current style value for the given property.
+     * @method getStyle
+     * @param {HTMLElement} An HTMLElement to get the style from.
+     * @param {String} att The style property to get. 
+     */
+    getStyle: function(node, att) {
+        var style = node[STYLE],
+            CUSTOM_STYLES = Y.DOM.CUSTOM_STYLES,
+            val = '';
+
+        if (style) {
+            if (att in CUSTOM_STYLES) {
+                if (CUSTOM_STYLES[att].get) {
+                    return CUSTOM_STYLES[att].get(node, att, style); // NOTE: return
+                } else if (typeof CUSTOM_STYLES[att] === 'string') {
+                    att = CUSTOM_STYLES[att];
+                }
+            }
+            val = style[att];
+            if (val === '') { // TODO: is empty string sufficient?
+                val = Y.DOM[GET_COMPUTED_STYLE](node, att);
+            }
+        }
+
+        return val;
+    },
+
+    /**
+     * Sets multiple style properties.
+     * @method setStyles
+     * @param {HTMLElement} node An HTMLElement to apply the styles to. 
+     * @param {Object} hash An object literal of property:value pairs. 
+     */
+    setStyles: function(node, hash) {
+        var style = node.style;
+        Y.each(hash, function(v, n) {
+            Y.DOM.setStyle(node, n, v, style);
+        }, Y.DOM);
+    },
+
+    /**
+     * Returns the computed style for the given node.
+     * @method getComputedStyle
+     * @param {HTMLElement} An HTMLElement to get the style from.
+     * @param {String} att The style property to get. 
+     * @return {String} The computed value of the style property. 
+     */
+    getComputedStyle: function(node, att) {
+        var val = '',
+            doc = node[OWNER_DOCUMENT];
+
+        if (node[STYLE]) {
+            val = doc[DEFAULT_VIEW][GET_COMPUTED_STYLE](node, null)[att];
+        }
+        return val;
+    }
+});
+
+// normalize reserved word float alternatives ("cssFloat" or "styleFloat")
+if (DOCUMENT[DOCUMENT_ELEMENT][STYLE][CSS_FLOAT] !== UNDEFINED) {
+    Y.DOM.CUSTOM_STYLES[FLOAT] = CSS_FLOAT;
+} else if (DOCUMENT[DOCUMENT_ELEMENT][STYLE][STYLE_FLOAT] !== UNDEFINED) {
+    Y.DOM.CUSTOM_STYLES[FLOAT] = STYLE_FLOAT;
+}
+
+// fix opera computedStyle default color unit (convert to rgb)
+if (Y.UA.opera) {
+    Y.DOM[GET_COMPUTED_STYLE] = function(node, att) {
+        var view = node[OWNER_DOCUMENT][DEFAULT_VIEW],
+            val = view[GET_COMPUTED_STYLE](node, '')[att];
+
+        if (re_color.test(att)) {
+            val = Y.Color.toRGB(val);
+        }
+
+        return val;
+    };
+
+}
+
+// safari converts transparent to rgba(), others use "transparent"
+if (Y.UA.webkit) {
+    Y.DOM[GET_COMPUTED_STYLE] = function(node, att) {
+        var view = node[OWNER_DOCUMENT][DEFAULT_VIEW],
+            val = view[GET_COMPUTED_STYLE](node, '')[att];
+
+        if (val === 'rgba(0, 0, 0, 0)') {
+            val = TRANSPARENT; 
+        }
+
+        return val;
+    };
+
+}
+})(Y);
+(function(Y) {
+var TO_STRING = 'toString',
+    PARSE_INT = parseInt,
+    RE = RegExp;
+
+Y.Color = {
+    KEYWORDS: {
+        black: '000',
+        silver: 'c0c0c0',
+        gray: '808080',
+        white: 'fff',
+        maroon: '800000',
+        red: 'f00',
+        purple: '800080',
+        fuchsia: 'f0f',
+        green: '008000',
+        lime: '0f0',
+        olive: '808000',
+        yellow: 'ff0',
+        navy: '000080',
+        blue: '00f',
+        teal: '008080',
+        aqua: '0ff'
+    },
+
+    re_RGB: /^rgb\(([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\)$/i,
+    re_hex: /^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i,
+    re_hex3: /([0-9A-F])/gi,
+
+    toRGB: function(val) {
+        if (!Y.Color.re_RGB.test(val)) {
+            val = Y.Color.toHex(val);
+        }
+
+        if(Y.Color.re_hex.exec(val)) {
+            val = 'rgb(' + [
+                PARSE_INT(RE.$1, 16),
+                PARSE_INT(RE.$2, 16),
+                PARSE_INT(RE.$3, 16)
+            ].join(', ') + ')';
+        }
+        return val;
+    },
+
+    toHex: function(val) {
+        val = Y.Color.KEYWORDS[val] || val;
+        if (Y.Color.re_RGB.exec(val)) {
+            var r = (RE.$1.length === 1) ? '0' + RE.$1 : Number(RE.$1),
+                g = (RE.$2.length === 1) ? '0' + RE.$2 : Number(RE.$2),
+                b = (RE.$3.length === 1) ? '0' + RE.$3 : Number(RE.$3);
+
+            val = [
+                r[TO_STRING](16),
+                g[TO_STRING](16),
+                b[TO_STRING](16)
+            ].join('');
+        }
+
+        if (val.length < 6) {
+            val = val.replace(Y.Color.re_hex3, '$1$1');
+        }
+
+        if (val !== 'transparent' && val.indexOf('#') < 0) {
+            val = '#' + val;
+        }
+
+        return val.toLowerCase();
+    }
+};
+})(Y);
+
+(function(Y) {
+var CLIENT_TOP = 'clientTop',
+    CLIENT_LEFT = 'clientLeft',
+    HAS_LAYOUT = 'hasLayout',
+    PX = 'px',
+    FILTER = 'filter',
+    FILTERS = 'filters',
+    OPACITY = 'opacity',
+    AUTO = 'auto',
+    BORDER_TOP_WIDTH = 'borderTopWidth',
+    BORDER_RIGHT_WIDTH = 'borderRightWidth',
+    BORDER_BOTTOM_WIDTH = 'borderBottomWidth',
+    BORDER_LEFT_WIDTH = 'borderLeftWidth',
+    WIDTH = 'width',
+    HEIGHT = 'height',
+    TRANSPARENT = 'transparent',
+    VISIBLE = 'visible',
+    GET_COMPUTED_STYLE = 'getComputedStyle',
+    UNDEFINED = undefined,
+    documentElement = document.documentElement,
+
+    // TODO: unit-less lineHeight (e.g. 1.22)
+    re_size = /^width|height$/,
+    re_unit = /^(\d[.\d]*)+(em|ex|px|gd|rem|vw|vh|vm|ch|mm|cm|in|pt|pc|deg|rad|ms|s|hz|khz|%){1}?/i,
+
+    _getStyleObj = function(node) {
+        return node.currentStyle || node.style;
+    },
+
+    ComputedStyle = {
+        CUSTOM_STYLES: {},
+
+        get: function(el, property) {
+            var value = '',
+                current;
+
+            if (el) {
+                    current = _getStyleObj(el)[property];
+
+                if (property === OPACITY) {
+                    value = Y.DOM.CUSTOM_STYLES[OPACITY].get(el);        
+                } else if (!current || (current.indexOf && current.indexOf(PX) > -1)) { // no need to convert
+                    value = current;
+                } else if (Y.DOM.IE.COMPUTED[property]) { // use compute function
+                    value = Y.DOM.IE.COMPUTED[property](el, property);
+                } else if (re_unit.test(current)) { // convert to pixel
+                    value = ComputedStyle.getPixel(el, property) + PX;
+                } else {
+                    value = current;
+                }
+            }
+
+            return value;
+        },
+
+        getOffset: function(el, prop) {
+            var current = _getStyleObj(el)[prop],                     // value of "width", "top", etc.
+                capped = prop.charAt(0).toUpperCase() + prop.substr(1), // "Width", "Top", etc.
+                offset = 'offset' + capped,                             // "offsetWidth", "offsetTop", etc.
+                pixel = 'pixel' + capped,                               // "pixelWidth", "pixelTop", etc.
+                actual,
+                value = '';
+
+            if (current === AUTO) {
+                actual = el[offset]; // offsetHeight/Top etc.
+                if (actual === UNDEFINED) { // likely "right" or "bottom"
+                    value = 0;
+                }
+
+                value = actual;
+                if (re_size.test(prop)) { // account for box model diff 
+                    el.style[prop] = actual;
+                    if (el[offset] > actual) {
+                        // the difference is padding + border (works in Standards & Quirks modes)
+                        value = actual - (el[offset] - actual);
+                    }
+                    el.style[prop] = AUTO; // revert to auto
+                }
+            } else { // convert units to px
+                if (current.indexOf('%') > -1) { // IE pixelWidth incorrect for percent; manually compute 
+                    current = el.clientWidth - // offsetWidth - borderWidth
+                            ComputedStyle.getPixel(el, 'paddingRight') -
+                            ComputedStyle.getPixel(el, 'paddingLeft');
+                }
+                if (!el.style[pixel] && !el.style[prop]) { // need to map style.width to currentStyle (no currentStyle.pixelWidth)
+                    el.style[prop] = current;              // no style.pixelWidth if no style.width
+                }
+                value = el.style[pixel];
+            }
+            return value + PX;
+        },
+
+        getBorderWidth: function(el, property) {
+            // clientHeight/Width = paddingBox (e.g. offsetWidth - borderWidth)
+            // clientTop/Left = borderWidth
+            var value = null;
+            if (!el.currentStyle || !el.currentStyle[HAS_LAYOUT]) { // TODO: unset layout?
+                el.style.zoom = 1; // need layout to measure client
+            }
+
+            switch(property) {
+                case BORDER_TOP_WIDTH:
+                    value = el[CLIENT_TOP];
+                    break;
+                case BORDER_BOTTOM_WIDTH:
+                    value = el.offsetHeight - el.clientHeight - el[CLIENT_TOP];
+                    break;
+                case BORDER_LEFT_WIDTH:
+                    value = el[CLIENT_LEFT];
+                    break;
+                case BORDER_RIGHT_WIDTH:
+                    value = el.offsetWidth - el.clientWidth - el[CLIENT_LEFT];
+                    break;
+            }
+            return value + PX;
+        },
+
+        getPixel: function(node, att) {
+            // use pixelRight to convert to px
+            var val = null,
+                style = _getStyleObj(node),
+                styleRight = style.right,
+                current = style[att];
+
+            node.style.right = current;
+            val = node.style.pixelRight;
+            node.style.right = styleRight; // revert
+
+            return val;
+        },
+
+        getMargin: function(node, att) {
+            var val,
+                style = _getStyleObj(node);
+
+            if (style[att] == AUTO) {
+                val = 0;
+            } else {
+                val = ComputedStyle.getPixel(node, att);
+            }
+            return val + PX;
+        },
+
+        getVisibility: function(node, att) {
+            var current;
+            while ( (current = node.currentStyle) && current[att] == 'inherit') { // NOTE: assignment in test
+                node = node.parentNode;
+            }
+            return (current) ? current[att] : VISIBLE;
+        },
+
+        getColor: function(node, att) {
+            var current = _getStyleObj(node)[att];
+
+            if (!current || current === TRANSPARENT) {
+                Y.DOM.elementByAxis(node, 'parentNode', null, function(parent) {
+                    current = _getStyleObj(parent)[att];
+                    if (current && current !== TRANSPARENT) {
+                        node = parent;
+                        return true;
+                    }
+                });
+            }
+
+            return Y.Color.toRGB(current);
+        },
+
+        getBorderColor: function(node, att) {
+            var current = _getStyleObj(node),
+                val = current[att] || current.color;
+            return Y.Color.toRGB(Y.Color.toHex(val));
+        }
+    },
+
+    //fontSize: getPixelFont,
+    IEComputed = {};
+
+// use alpha filter for IE opacity
+if (documentElement.style[OPACITY] === UNDEFINED &&
+        documentElement[FILTERS]) {
+    Y.DOM.CUSTOM_STYLES[OPACITY] = {
+        get: function(node) {
+            var val = 100;
+            try { // will error if no DXImageTransform
+                val = node[FILTERS]['DXImageTransform.Microsoft.Alpha'][OPACITY];
+
+            } catch(e) {
+                try { // make sure its in the document
+                    val = node[FILTERS]('alpha')[OPACITY];
+                } catch(err) {
+                    Y.log('getStyle: IE opacity filter not found; returning 1', 'warn', 'dom-style');
+                }
+            }
+            return val / 100;
+        },
+
+        set: function(node, val, style) {
+            var current,
+                styleObj;
+
+            if (val === '') { // normalize inline style behavior
+                styleObj = _getStyleObj(node);
+                current = (OPACITY in styleObj) ? styleObj[OPACITY] : 1; // revert to original opacity
+                val = current;
+            }
+
+            if (typeof style[FILTER] == 'string') { // in case not appended
+                style[FILTER] = 'alpha(' + OPACITY + '=' + val * 100 + ')';
+                
+                if (!node.currentStyle || !node.currentStyle[HAS_LAYOUT]) {
+                    style.zoom = 1; // needs layout 
+                }
+            }
+        }
+    };
+}
+
+try {
+    document.createElement('div').style.height = '-1px';
+} catch(e) { // IE throws error on invalid style set; trap common cases
+    Y.DOM.CUSTOM_STYLES.height = {
+        set: function(node, val, style) {
+            if (parseInt(val, 10) >= 0) {
+                style.height = val;
+            } else {
+                Y.log('invalid style value for height: ' + val, 'warn', 'dom-style');
+            }
+        }
+    };
+
+    Y.DOM.CUSTOM_STYLES.width = {
+        set: function(node, val, style) {
+            if (parseInt(val, 10) >= 0) {
+                style.width = val;
+            } else {
+                Y.log('invalid style value for width: ' + val, 'warn', 'dom-style');
+            }
+        }
+    };
+}
+
+// TODO: top, right, bottom, left
+IEComputed[WIDTH] = IEComputed[HEIGHT] = ComputedStyle.getOffset;
+
+IEComputed.color = IEComputed.backgroundColor = ComputedStyle.getColor;
+
+IEComputed[BORDER_TOP_WIDTH] = IEComputed[BORDER_RIGHT_WIDTH] =
+        IEComputed[BORDER_BOTTOM_WIDTH] = IEComputed[BORDER_LEFT_WIDTH] =
+        ComputedStyle.getBorderWidth;
+
+IEComputed.marginTop = IEComputed.marginRight = IEComputed.marginBottom =
+        IEComputed.marginLeft = ComputedStyle.getMargin;
+
+IEComputed.visibility = ComputedStyle.getVisibility;
+IEComputed.borderColor = IEComputed.borderTopColor =
+        IEComputed.borderRightColor = IEComputed.borderBottomColor =
+        IEComputed.borderLeftColor = ComputedStyle.getBorderColor;
+
+if (!Y.config.win[GET_COMPUTED_STYLE]) {
+    Y.DOM[GET_COMPUTED_STYLE] = ComputedStyle.get; 
+}
+
+Y.namespace('DOM.IE');
+Y.DOM.IE.COMPUTED = IEComputed;
+Y.DOM.IE.ComputedStyle = ComputedStyle;
+
+})(Y);
+
+
+}, '3.0.0b1' ,{skinnable:false, requires:['dom-base']});
+YUI.add('dom-screen', function(Y) {
+
+(function(Y) {
+
+/**
+ * Adds position and region management functionality to DOM.
+ * @module dom
+ * @submodule dom-screen
+ * @for DOM
+ */
+
+var DOCUMENT_ELEMENT = 'documentElement',
+    COMPAT_MODE = 'compatMode',
+    POSITION = 'position',
+    FIXED = 'fixed',
+    RELATIVE = 'relative',
+    LEFT = 'left',
+    TOP = 'top',
+    _BACK_COMPAT = 'BackCompat',
+    MEDIUM = 'medium',
+    BORDER_LEFT_WIDTH = 'borderLeftWidth',
+    BORDER_TOP_WIDTH = 'borderTopWidth',
+    GET_BOUNDING_CLIENT_RECT = 'getBoundingClientRect',
+    GET_COMPUTED_STYLE = 'getComputedStyle',
+
+    // TODO: how about thead/tbody/tfoot/tr?
+    // TODO: does caption matter?
+    RE_TABLE = /^t(?:able|d|h)$/i;
+
+Y.mix(Y.DOM, {
+    /**
+     * Returns the inner height of the viewport (exludes scrollbar). 
+     * @method winHeight
+     * @return {Number} The current height of the viewport.
+     */
+    winHeight: function(node) {
+        var h = Y.DOM._getWinSize(node).height;
+        Y.log('winHeight returning ' + h, 'info', 'dom-screen');
+        return h;
+    },
+
+    /**
+     * Returns the inner width of the viewport (exludes scrollbar). 
+     * @method winWidth
+     * @return {Number} The current width of the viewport.
+     */
+    winWidth: function(node) {
+        var w = Y.DOM._getWinSize(node).width;
+        Y.log('winWidth returning ' + w, 'info', 'dom-screen');
+        return w;
+    },
+
+    /**
+     * Document height 
+     * @method docHeight
+     * @return {Number} The current height of the document.
+     */
+    docHeight:  function(node) {
+        var h = Y.DOM._getDocSize(node).height;
+        Y.log('docHeight returning ' + h, 'info', 'dom-screen');
+        return Math.max(h, Y.DOM._getWinSize(node).height);
+    },
+
+    /**
+     * Document width 
+     * @method docWidth
+     * @return {Number} The current width of the document.
+     */
+    docWidth:  function(node) {
+        var w = Y.DOM._getDocSize(node).width;
+        Y.log('docWidth returning ' + w, 'info', 'dom-screen');
+        return Math.max(w, Y.DOM._getWinSize(node).width);
+    },
+
+    /**
+     * Amount page has been scroll horizontally 
+     * @method docScrollX
+     * @return {Number} The current amount the screen is scrolled horizontally.
+     */
+    docScrollX: function(node) {
+        var doc = Y.DOM._getDoc(node);
+        return Math.max(doc[DOCUMENT_ELEMENT].scrollLeft, doc.body.scrollLeft);
+    },
+
+    /**
+     * Amount page has been scroll vertically 
+     * @method docScrollY
+     * @return {Number} The current amount the screen is scrolled vertically.
+     */
+    docScrollY:  function(node) {
+        var doc = Y.DOM._getDoc(node);
+        return Math.max(doc[DOCUMENT_ELEMENT].scrollTop, doc.body.scrollTop);
+    },
+
+    /**
+     * Gets the current position of an element based on page coordinates. 
+     * Element must be part of the DOM tree to have page coordinates
+     * (display:none or elements not appended return false).
+     * @method getXY
+     * @param element The target element
+     * @return {Array} The XY position of the element
+
+     TODO: test inDocument/display?
+     */
+    getXY: function() {
+        if (document[DOCUMENT_ELEMENT][GET_BOUNDING_CLIENT_RECT]) {
+            return function(node) {
+                var xy = null,
+                    scrollLeft,
+                    scrollTop,
+                    box,
+                    off1, off2,
+                    bLeft, bTop,
+                    mode,
+                    doc;
+
+                if (node) {
+                    if (Y.DOM.inDoc(node)) {
+                        scrollLeft = Y.DOM.docScrollX(node);
+                        scrollTop = Y.DOM.docScrollY(node);
+                        box = node[GET_BOUNDING_CLIENT_RECT]();
+                        doc = Y.DOM._getDoc(node);
+                        xy = [box.left, box.top];
+
+                            if (Y.UA.ie) {
+                                off1 = 2;
+                                off2 = 2;
+                                mode = doc[COMPAT_MODE];
+                                bLeft = Y.DOM[GET_COMPUTED_STYLE](doc[DOCUMENT_ELEMENT], BORDER_LEFT_WIDTH);
+                                bTop = Y.DOM[GET_COMPUTED_STYLE](doc[DOCUMENT_ELEMENT], BORDER_TOP_WIDTH);
+
+                                if (Y.UA.ie === 6) {
+                                    if (mode !== _BACK_COMPAT) {
+                                        off1 = 0;
+                                        off2 = 0;
+                                    }
+                                }
+                                
+                                if ((mode == _BACK_COMPAT)) {
+                                    if (bLeft !== MEDIUM) {
+                                        off1 = parseInt(bLeft, 10);
+                                    }
+                                    if (bTop !== MEDIUM) {
+                                        off2 = parseInt(bTop, 10);
+                                    }
+                                }
+                                
+                                xy[0] -= off1;
+                                xy[1] -= off2;
+
+                            }
+
+                        if ((scrollTop || scrollLeft)) {
+                            xy[0] += scrollLeft;
+                            xy[1] += scrollTop;
+                        }
+                    } else { // default to current offsets
+                        xy = Y.DOM._getOffset(node);
+                    }
+                }
+                return xy;                   
+            };
+        } else {
+            return function(node) { // manually calculate by crawling up offsetParents
+                //Calculate the Top and Left border sizes (assumes pixels)
+                var xy = null,
+                    parentNode,
+                    bCheck,
+                    scrollTop,
+                    scrollLeft;
+
+                if (node) {
+                    if (Y.DOM.inDoc(node)) {
+                        xy = [node.offsetLeft, node.offsetTop];
+                        parentNode = node;
+                        // TODO: refactor with !! or just falsey
+                        bCheck = ((Y.UA.gecko || Y.UA.webkit > 519) ? true : false);
+
+                        // TODO: worth refactoring for TOP/LEFT only?
+                        while ((parentNode = parentNode.offsetParent)) {
+                            xy[0] += parentNode.offsetLeft;
+                            xy[1] += parentNode.offsetTop;
+                            if (bCheck) {
+                                xy = Y.DOM._calcBorders(parentNode, xy);
+                            }
+                        }
+
+                        // account for any scrolled ancestors
+                        if (Y.DOM.getStyle(node, POSITION) != FIXED) {
+                            parentNode = node;
+
+                            while ((parentNode = parentNode.parentNode)) {
+                                scrollTop = parentNode.scrollTop;
+                                scrollLeft = parentNode.scrollLeft;
+
+                                //Firefox does something funky with borders when overflow is not visible.
+                                if (Y.UA.gecko && (Y.DOM.getStyle(parentNode, 'overflow') !== 'visible')) {
+                                        xy = Y.DOM._calcBorders(parentNode, xy);
+                                }
+                                
+
+                                if (scrollTop || scrollLeft) {
+                                    xy[0] -= scrollLeft;
+                                    xy[1] -= scrollTop;
+                                }
+                            }
+                            xy[0] += Y.DOM.docScrollX(node);
+                            xy[1] += Y.DOM.docScrollY(node);
+
+                        } else {
+                            //Fix FIXED position -- add scrollbars
+                            xy[0] += Y.DOM.docScrollX(node);
+                            xy[1] += Y.DOM.docScrollY(node);
+                        }
+                    } else {
+                        xy = Y.DOM._getOffset(node);
+                    }
+                }
+
+                return xy;                
+            };
+        }
+    }(),// NOTE: Executing for loadtime branching
+
+    _getOffset: function(node) {
+        var pos,
+            xy = null;
+
+        if (node) {
+            pos = Y.DOM.getStyle(node, POSITION);
+            xy = [
+                parseInt(Y.DOM[GET_COMPUTED_STYLE](node, LEFT), 10),
+                parseInt(Y.DOM[GET_COMPUTED_STYLE](node, TOP), 10)
+            ];
+
+            if ( isNaN(xy[0]) ) { // in case of 'auto'
+                xy[0] = parseInt(Y.DOM.getStyle(node, LEFT), 10); // try inline
+                if ( isNaN(xy[0]) ) { // default to offset value
+                    xy[0] = (pos === RELATIVE) ? 0 : node.offsetLeft || 0;
+                }
+            } 
+
+            if ( isNaN(xy[1]) ) { // in case of 'auto'
+                xy[1] = parseInt(Y.DOM.getStyle(node, TOP), 10); // try inline
+                if ( isNaN(xy[1]) ) { // default to offset value
+                    xy[1] = (pos === RELATIVE) ? 0 : node.offsetTop || 0;
+                }
+            } 
+        }
+
+        return xy;
+
+    },
+
+    /**
+     * Gets the current X position of an element based on page coordinates. 
+     * Element must be part of the DOM tree to have page coordinates
+     * (display:none or elements not appended return false).
+     * @method getX
+     * @param element The target element
+     * @return {Int} The X position of the element
+     */
+
+    getX: function(node) {
+        return Y.DOM.getXY(node)[0];
+    },
+
+    /**
+     * Gets the current Y position of an element based on page coordinates. 
+     * Element must be part of the DOM tree to have page coordinates
+     * (display:none or elements not appended return false).
+     * @method getY
+     * @param element The target element
+     * @return {Int} The Y position of the element
+     */
+
+    getY: function(node) {
+        return Y.DOM.getXY(node)[1];
+    },
+
+    /**
+     * Set the position of an html element in page coordinates.
+     * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
+     * @method setXY
+     * @param element The target element
+     * @param {Array} xy Contains X & Y values for new position (coordinates are page-based)
+     * @param {Boolean} noRetry By default we try and set the position a second time if the first fails
+     */
+    setXY: function(node, xy, noRetry) {
+        var setStyle = Y.DOM.setStyle,
+            pos,
+            delta,
+            newXY,
+            currentXY;
+
+        if (node && xy) {
+            pos = Y.DOM.getStyle(node, POSITION);
+
+            delta = Y.DOM._getOffset(node);       
+
+            if (pos == 'static') { // default to relative
+                pos = RELATIVE;
+                setStyle(node, POSITION, pos);
+            }
+
+            currentXY = Y.DOM.getXY(node);
+
+            if (xy[0] !== null) {
+                setStyle(node, LEFT, xy[0] - currentXY[0] + delta[0] + 'px');
+            }
+
+            if (xy[1] !== null) {
+                setStyle(node, TOP, xy[1] - currentXY[1] + delta[1] + 'px');
+            }
+
+            if (!noRetry) {
+                newXY = Y.DOM.getXY(node);
+                if (newXY[0] !== xy[0] || newXY[1] !== xy[1]) {
+                    Y.DOM.setXY(node, xy, true); 
+                }
+            }
+          
+            Y.log('setXY setting position to ' + xy, 'info', 'dom-screen');
+        } else {
+            Y.log('setXY failed to set ' + node + ' to ' + xy, 'info', 'dom-screen');
+        }
+    },
+
+    /**
+     * Set the X position of an html element in page coordinates, regardless of how the element is positioned.
+     * The element(s) must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
+     * @method setX
+     * @param element The target element
+     * @param {Int} x The X values for new position (coordinates are page-based)
+     */
+    setX: function(node, x) {
+        return Y.DOM.setXY(node, [x, null]);
+    },
+
+    /**
+     * Set the Y position of an html element in page coordinates, regardless of how the element is positioned.
+     * The element(s) must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
+     * @method setY
+     * @param element The target element
+     * @param {Int} y The Y values for new position (coordinates are page-based)
+     */
+    setY: function(node, y) {
+        return Y.DOM.setXY(node, [null, y]);
+    },
+
+    _calcBorders: function(node, xy2) {
+        var t = parseInt(Y.DOM[GET_COMPUTED_STYLE](node, BORDER_TOP_WIDTH), 10) || 0,
+            l = parseInt(Y.DOM[GET_COMPUTED_STYLE](node, BORDER_LEFT_WIDTH), 10) || 0;
+        if (Y.UA.gecko) {
+            if (RE_TABLE.test(node.tagName)) {
+                t = 0;
+                l = 0;
+            }
+        }
+        xy2[0] += l;
+        xy2[1] += t;
+        return xy2;
+    },
+
+    _getWinSize: function(node) {
+        var doc = Y.DOM._getDoc(),
+            win = doc.defaultView || doc.parentWindow,
+            mode = doc[COMPAT_MODE],
+            h = win.innerHeight,
+            w = win.innerWidth,
+            root = doc[DOCUMENT_ELEMENT];
+
+        if ( mode && !Y.UA.opera ) { // IE, Gecko
+            if (mode != 'CSS1Compat') { // Quirks
+                root = doc.body; 
+            }
+            h = root.clientHeight;
+            w = root.clientWidth;
+        }
+        return { height: h, width: w }; 
+    },
+
+    _getDocSize: function(node) {
+        var doc = Y.DOM._getDoc(),
+            root = doc[DOCUMENT_ELEMENT];
+
+        if (doc[COMPAT_MODE] != 'CSS1Compat') {
+            root = doc.body;
+        }
+
+        return { height: root.scrollHeight, width: root.scrollWidth };
+    }
+});
+})(Y);
+(function(Y) {
+var TOP = 'top',
+    RIGHT = 'right',
+    BOTTOM = 'bottom',
+    LEFT = 'left',
+
+    getOffsets = function(r1, r2) {
+        var t = Math.max(r1[TOP], r2[TOP]),
+            r = Math.min(r1[RIGHT], r2[RIGHT]),
+            b = Math.min(r1[BOTTOM], r2[BOTTOM]),
+            l = Math.max(r1[LEFT], r2[LEFT]),
+            ret = {};
+        
+        ret[TOP] = t;
+        ret[RIGHT] = r;
+        ret[BOTTOM] = b;
+        ret[LEFT] = l;
+        return ret;
+    },
+
+    DOM = Y.DOM;
+
+Y.mix(DOM, {
+    /**
+     * Returns an Object literal containing the following about this element: (top, right, bottom, left)
+     * @method region
+     * @param {HTMLElement} element The DOM element. 
+     @return {Object} Object literal containing the following about this element: (top, right, bottom, left)
+     */
+    region: function(node) {
+        var xy = DOM.getXY(node),
+            ret = false;
+        
+        if (node && xy) {
+            ret = DOM._getRegion(
+                xy[1], // top
+                xy[0] + node.offsetWidth, // right
+                xy[1] + node.offsetHeight, // bottom
+                xy[0] // left
+            );
+        }
+
+        return ret;
+    },
+
+    /**
+     * Find the intersect information for the passes nodes.
+     * @method intersect
+     * @param {HTMLElement} element The first element 
+     * @param {HTMLElement | Object} element2 The element or region to check the interect with
+     * @param {Object} altRegion An object literal containing the region for the first element if we already have the data (for performance i.e. DragDrop)
+     @return {Object} Object literal containing the following intersection data: (top, right, bottom, left, area, yoff, xoff, inRegion)
+     */
+    intersect: function(node, node2, altRegion) {
+        var r = altRegion || DOM.region(node), region = {},
+            n = node2,
+            off;
+
+        if (n.tagName) {
+            region = DOM.region(n);
+        } else if (Y.Lang.isObject(node2)) {
+            region = node2;
+        } else {
+            return false;
+        }
+        
+        off = getOffsets(region, r);
+        return {
+            top: off[TOP],
+            right: off[RIGHT],
+            bottom: off[BOTTOM],
+            left: off[LEFT],
+            area: ((off[BOTTOM] - off[TOP]) * (off[RIGHT] - off[LEFT])),
+            yoff: ((off[BOTTOM] - off[TOP])),
+            xoff: (off[RIGHT] - off[LEFT]),
+            inRegion: DOM.inRegion(node, node2, false, altRegion)
+        };
+        
+    },
+    /**
+     * Check if any part of this node is in the passed region
+     * @method inRegion
+     * @param {Object} node2 The node to get the region from or an Object literal of the region
+     * $param {Boolean} all Should all of the node be inside the region
+     * @param {Object} altRegion An object literal containing the region for this node if we already have the data (for performance i.e. DragDrop)
+     * @return {Boolean} True if in region, false if not.
+     */
+    inRegion: function(node, node2, all, altRegion) {
+        var region = {},
+            r = altRegion || DOM.region(node),
+            n = node2,
+            off;
+
+        if (n.tagName) {
+            region = DOM.region(n);
+        } else if (Y.Lang.isObject(node2)) {
+            region = node2;
+        } else {
+            return false;
+        }
+            
+        if (all) {
+            return (
+                r[LEFT]   >= region[LEFT]   &&
+                r[RIGHT]  <= region[RIGHT]  && 
+                r[TOP]    >= region[TOP]    && 
+                r[BOTTOM] <= region[BOTTOM]  );
+        } else {
+            off = getOffsets(region, r);
+            if (off[BOTTOM] >= off[TOP] && off[RIGHT] >= off[LEFT]) {
+                return true;
+            } else {
+                return false;
+            }
+            
+        }
+    },
+
+    /**
+     * Check if any part of this element is in the viewport
+     * @method inViewportRegion
+     * @param {HTMLElement} element The DOM element. 
+     * @param {Boolean} all Should all of the node be inside the region
+     * @param {Object} altRegion An object literal containing the region for this node if we already have the data (for performance i.e. DragDrop)
+     * @return {Boolean} True if in region, false if not.
+     */
+    inViewportRegion: function(node, all, altRegion) {
+        return DOM.inRegion(node, DOM.viewportRegion(node), all, altRegion);
+            
+    },
+
+    _getRegion: function(t, r, b, l) {
+        var region = {};
+
+        region[TOP] = region[1] = t;
+        region[LEFT] = region[0] = l;
+        region[BOTTOM] = b;
+        region[RIGHT] = r;
+        region.width = region[RIGHT] - region[LEFT];
+        region.height = region[BOTTOM] - region[TOP];
+
+        return region;
+    },
+
+    /**
+     * Returns an Object literal containing the following about the visible region of viewport: (top, right, bottom, left)
+     * @method viewportRegion
+     @return {Object} Object literal containing the following about the visible region of the viewport: (top, right, bottom, left)
+     */
+    viewportRegion: function(node) {
+        node = node || Y.config.doc.documentElement;
+        var ret = false,
+            scrollX,
+            scrollY;
+
+        if (node) {
+            scrollX = DOM.docScrollX(node);
+            scrollY = DOM.docScrollY(node);
+
+            ret = DOM._getRegion(scrollY, // top
+                DOM.winWidth(node) + scrollX, // right
+                scrollY + DOM.winHeight(node), // bottom
+                scrollX); // left
+        }
+
+        return ret;
+    }
+});
+})(Y);
+
+
+}, '3.0.0b1' ,{requires:['dom-base', 'dom-style'], skinnable:false});
+YUI.add('selector-native', function(Y) {
+
+(function(Y) {
+/**
+ * The selector-native module provides support for native querySelector
+ * @module dom
+ * @submodule selector-native
+ * @for Selector
+ */
+
+/**
+ * Provides support for using CSS selectors to query the DOM 
+ * @class Selector 
+ * @static
+ * @for Selector
+ */
+
+Y.namespace('Selector'); // allow native module to standalone
+
+var NativeSelector = {
+    _reLead: /^\s*([>+~]|:self)/,
+    _reUnSupported: /!./,
+
+    _foundCache: [],
+
+    _supportsNative: function() {
+        // whitelist and feature detection to manage
+        // future implementations manually
+        return ( (Y.UA.ie >= 8 || Y.UA.webkit > 525) &&
+            document.querySelectorAll);
+    },
+
+    _toArray: function(nodes) { // TODO: move to Y.Array
+        var ret = nodes,
+            i, len;
+
+        if (!nodes.slice) {
+            try {
+                ret = Array.prototype.slice.call(nodes);
+            } catch(e) { // IE: requires manual copy
+                ret = [];
+                for (i = 0, len = nodes.length; i < len; ++i) {
+                    ret[i] = nodes[i];
+                }
+            }
+        }
+        return ret;
+    },
+
+    _clearFoundCache: function() {
+        var foundCache = NativeSelector._foundCache,
+            i, len;
+
+        for (i = 0, len = foundCache.length; i < len; ++i) {
+            try { // IE no like delete
+                delete foundCache[i]._found;
+            } catch(e) {
+                foundCache[i].removeAttribute('_found');
+            }
+        }
+        foundCache = [];
+    },
+
+    _sort: function(nodes) {
+        if (nodes) {
+            nodes = NativeSelector._toArray(nodes);
+            if (nodes.sort) {
+                nodes.sort(function(a, b) {
+                    return Y.DOM.srcIndex(a) - Y.DOM.srcIndex(b);
+                });
+            }
+        }
+
+        return nodes;
+    },
+
+    _deDupe: function(nodes) {
+        var ret = [],
+            cache = NativeSelector._foundCache,
+            i, node;
+
+        for (i = 0, node; node = nodes[i++];) {
+            if (!node._found) {
+                ret[ret.length] = cache[cache.length] = node;
+                node._found = true;
+            }
+        }
+        NativeSelector._clearFoundCache();
+        return ret;
+    },
+
+    // allows element scoped queries to begin with combinator
+    // e.g. query('> p', document.body) === query('body > p')
+    _prepQuery: function(root, selector) {
+        var groups = selector.split(','),
+            queries = [],
+            isDocRoot = (root && root.nodeType === 9),
+            i, len;
+
+        if (root) {
+            if (!isDocRoot) {
+                root.id = root.id || Y.guid();
+                // break into separate queries for element scoping
+                for (i = 0, len = groups.length; i < len; ++i) {
+                    selector = '#' + root.id + ' ' + groups[i]; // prepend with root ID
+                    queries.push({root: root.ownerDocument, selector: selector});
+                }
+            } else {
+                queries.push({root: root, selector: selector});
+            }
+        }
+
+        return queries;
+    },
+
+    _query: function(selector, root, firstOnly) {
+        if (NativeSelector._reUnSupported.test(selector)) {
+            return Y.Selector._brute.query(selector, root, firstOnly);
+        }
+
+        var ret = firstOnly ? null : [],
+            queryName = firstOnly ? 'querySelector' : 'querySelectorAll',
+            result,
+            queries,
+            i, query;
+
+        root = root || Y.config.doc;
+
+        if (selector) {
+            queries = NativeSelector._prepQuery(root, selector);
+            ret = [];
+
+            for (i = 0, query; query = queries[i++];) {
+                try {
+                    result = query.root[queryName](query.selector);
+                    if (queryName === 'querySelectorAll') { // convert NodeList to Array
+                        result = NativeSelector._toArray(result);
+                    }
+                    ret = ret.concat(result);
+                } catch(e) {
+                    Y.log('native selector error: ' + e, 'error', 'Selector');
+                }
+            }
+
+            if (queries.length > 1) { // remove dupes and sort by doc order 
+                ret = NativeSelector._sort(NativeSelector._deDupe(ret));
+            }
+            ret = (!firstOnly) ? ret : ret[0] || null;
+        }
+        return ret;
+    },
+
+    _filter: function(nodes, selector) {
+        var ret = [],
+            i, node;
+
+        if (nodes && selector) {
+            for (i = 0, node; (node = nodes[i++]);) {
+                if (Y.Selector._test(node, selector)) {
+                    ret[ret.length] = node;
+                }
+            }
+        } else {
+            Y.log('invalid filter input (nodes: ' + nodes +
+                    ', selector: ' + selector + ')', 'warn', 'Selector');
+        }
+
+        return ret;
+    },
+
+    _test: function(node, selector) {
+        var ret = false,
+            groups = selector.split(','),
+            item,
+            i, group;
+
+        if (node && node.tagName) { // only test HTMLElements
+            node.id = node.id || Y.guid();
+            for (i = 0, group; group = groups[i++];) {
+                group += '#' + node.id; // add ID for uniqueness
+                item = Y.Selector.query(group, null, true);
+                ret = (item === node);
+                if (ret) {
+                    break;
+                }
+            }
+        }
+
+        return ret;
+    }
+};
+
+if (Y.UA.ie && Y.UA.ie <= 8) {
+    NativeSelector._reUnSupported = /:(?:nth|not|root|only|checked|first|last|empty)/;
+}
+
+
+
+Y.mix(Y.Selector, NativeSelector, true);
+
+// allow standalone selector-native module
+if (NativeSelector._supportsNative()) {
+    Y.Selector.query = NativeSelector._query;
+    //Y.Selector.filter = NativeSelector._filter;
+    //Y.Selector.test = NativeSelector._test;
+}
+Y.Selector.test = NativeSelector._test;
+Y.Selector.filter = NativeSelector._filter;
+
+})(Y);
+
+
+}, '3.0.0b1' ,{requires:['dom-base'], skinnable:false});
+YUI.add('selector-css2', function(Y) {
+
+/**
+ * The selector module provides helper methods allowing CSS2 Selectors to be used with DOM elements.
+ * @module dom
+ * @submodule selector-css2
+ * @for Selector
+ */
+
+/**
+ * Provides helper methods for collecting and filtering DOM elements.
+ */
+
+var PARENT_NODE = 'parentNode',
+    TAG_NAME = 'tagName',
+    ATTRIBUTES = 'attributes',
+    COMBINATOR = 'combinator',
+    PSEUDOS = 'pseudos',
+    PREVIOUS = 'previous',
+    PREVIOUS_SIBLING = 'previousSibling',
+
+    _childCache = [], // cache to cleanup expando node.children
+
+    Selector = Y.Selector,
+
+    SelectorCSS2 = {
+        SORT_RESULTS: true,
+        _children: function(node) {
+            var ret = node.children,
+                i, n;
+
+            if (!ret && node[TAG_NAME]) { // only HTMLElements have children
+                ret = [];
+                for (i = 0, n; n = node.childNodes[i++];) {
+                    if (n.tagName) {
+                        ret[ret.length] = n;
+                    }
+                }
+                _childCache[_childCache.length] = node;
+                node.children = ret;
+            }
+
+            return ret || [];
+        },
+
+        _regexCache: {},
+
+        _re: {
+            attr: /(\[.*\])/g,
+            urls: /^(?:href|src)/
+        },
+
+        /**
+         * Mapping of shorthand tokens to corresponding attribute selector 
+         * @property shorthand
+         * @type object
+         */
+        shorthand: {
+            '\\#(-?[_a-z]+[-\\w]*)': '[id=$1]',
+            '\\.(-?[_a-z]+[-\\w]*)': '[className~=$1]'
+        },
+
+        /**
+         * List of operators and corresponding boolean functions. 
+         * These functions are passed the attribute and the current node's value of the attribute.
+         * @property operators
+         * @type object
+         */
+        operators: {
+            '': function(node, m) { return Y.DOM.getAttribute(node, m[0]) !== ''; }, // Just test for existence of attribute
+            //'': '.+',
+            '=': '^{val}$', // equality
+            '~=': '(?:^|\\s+){val}(?:\\s+|$)', // space-delimited
+            '|=': '^{val}-?' // optional hyphen-delimited
+        },
+
+        pseudos: {
+           'first-child': function(node) { 
+                return Y.Selector._children(node[PARENT_NODE])[0] === node; 
+            } 
+        },
+
+        _brute: {
+            /**
+             * Retrieves a set of nodes based on a given CSS selector. 
+             * @method query
+             *
+             * @param {string} selector The CSS Selector to test the node against.
+             * @param {HTMLElement} root optional An HTMLElement to start the query from. Defaults to Y.config.doc
+             * @param {Boolean} firstOnly optional Whether or not to return only the first match.
+             * @return {Array} An array of nodes that match the given selector.
+             * @static
+             */
+            query: function(selector, root, firstOnly) {
+                var ret = [];
+                if (selector) {
+                    ret = Selector._query(selector, root, firstOnly);
+                }
+
+                Y.log('query: ' + selector + ' returning: ' + ret.length, 'info', 'Selector');
+                Selector._cleanup();
+                return (firstOnly) ? (ret[0] || null) : ret;
+            }
+
+        },
+
+        // TODO: make extensible? events?
+        _cleanup: function() {
+            for (var i = 0, node; node = _childCache[i++];) {
+                delete node.children;
+            }
+
+            _childCache = [];
+        },
+
+        _query: function(selector, root, firstOnly, deDupe) {
+            var ret = [],
+                groups = selector.split(','), // TODO: handle comma in attribute/pseudo
+                nodes = [],
+                tokens,
+                token,
+                i, len;
+
+            if (groups.length > 1) {
+                for (i = 0, len = groups.length; i < len; ++i) {
+                    ret = ret.concat(arguments.callee(groups[i],
+                            root, firstOnly, true)); 
+                }
+
+                ret = Selector.SORT_RESULTS ? Selector._sort(ret) : ret;
+                Selector._clearFoundCache();
+            } else {
+                root = root || Y.config.doc;
+
+                if (root.nodeType !== 9) { // enforce element scope
+                    if (!root.id) {
+                        root.id = Y.guid();
+                    }
+                    // fast-path ID when possible
+                    if (root.ownerDocument.getElementById(root.id)) {
+                        selector = '#' + root.id + ' ' + selector;
+                        root = root.ownerDocument;
+
+                    }
+                }
+
+                tokens = Selector._tokenize(selector, root);
+                token = tokens.pop();
+
+                if (token) {
+                    if (deDupe) {
+                        token.deDupe = true; // TODO: better approach?
+                    }
+                    if (tokens[0] && tokens[0].id && root.nodeType === 9 && root.getElementById(tokens[0].id)) {
+                        root = root.getElementById(tokens[0].id);
+                    }
+
+                    // TODO: no prefilter for off-dom id
+                    if (root && !nodes.length && token.prefilter) {
+                        nodes = token.prefilter(root, token);
+                    }
+
+                    if (nodes.length) {
+                        if (firstOnly) {
+                            Y.Array.some(nodes, Selector._testToken, token);
+                        } else {
+                            Y.Array.each(nodes, Selector._testToken, token);
+                        }
+                    }
+                    ret = token.result;
+                }
+            }
+
+            return ret;
+        },
+
+        _testToken: function(node, index, nodes, token) {
+            token = token || this;
+            var tag = token.tag,
+                previous = token[PREVIOUS],
+                result = token.result,
+                i = 0,
+                nextTest = previous && previous[COMBINATOR] ?
+                        Selector.combinators[previous[COMBINATOR]] :
+                        null,
+                test,
+                attr;
+
+            if (//node[TAG_NAME] && // tagName limits to HTMLElements
+                    (tag === '*' || tag === node[TAG_NAME]) &&
+                    !(token.last && node._found) ) {
+                while ((attr = token.tests[i])) {
+                    i++;
+                    test = attr.test;
+                    if (test.test) {
+                        if (!test.test(Y.DOM.getAttribute(node, attr.name))) {
+                            return false;
+                        }
+                    } else if (!test(node, attr.match)) {
+                        return false;
+                    }
+                }
+
+                if (nextTest && !nextTest(node, token)) {
+                    return false;
+                }
+
+                if (token.root && token.root.nodeType !== 9 && !Y.DOM.contains(token.root, node)) {
+                    return false;
+                }
+
+                result[result.length] = node;
+                if (token.deDupe && token.last) {
+                    node._found = true;
+                    Selector._foundCache.push(node);
+                }
+                return true;
+            }
+            return false;
+        },
+
+
+        _getRegExp: function(str, flags) {
+            var regexCache = Selector._regexCache;
+            flags = flags || '';
+            if (!regexCache[str + flags]) {
+                regexCache[str + flags] = new RegExp(str, flags);
+            }
+            return regexCache[str + flags];
+        },
+
+        combinators: {
+            ' ': function(node, token) {
+                var test = Selector._testToken,
+                    previous = token[PREVIOUS];
+                while ( (node = node[PARENT_NODE]) ) {
+                    if (test(node, null, null, previous)) {
+                        return true;
+                    }
+                }  
+                return false;
+            },
+
+            '>': function(node, token) {
+                return Selector._testToken(node[PARENT_NODE], null, null, token[PREVIOUS]);
+            },
+
+
+            '+': function(node, token) {
+                var sib = node[PREVIOUS_SIBLING];
+                while (sib && sib.nodeType !== 1) {
+                    sib = sib[PREVIOUS_SIBLING];
+                }
+
+                if (sib && Y.Selector._testToken(sib, null, null, token[PREVIOUS])) {
+                    return true; 
+                }
+                return false;
+            }
+
+        },
+
+        _parsers: [
+            {
+                name: TAG_NAME,
+                re: /^((?:-?[_a-z]+[\w-]*)|\*)/i,
+                fn: function(token, match) {
+                    token.tag = match[1].toUpperCase();
+                    token.prefilter = function(root) {
+                        return root.getElementsByTagName(token.tag);
+                    };
+                    return true;
+                }
+            },
+            {
+                name: ATTRIBUTES,
+                re: /^\[([a-z]+\w*)+([~\|\^\$\*!=]=?)?['"]?([^\]]*?)['"]?\]/i,
+                fn: function(token, match) {
+                    var val = match[3],
+                        operator = !(match[2] && val) ? '' : match[2],
+                        test = Selector.operators[operator];
+
+                    // might be a function
+                    if (typeof test === 'string') {
+                        test = Selector._getRegExp(test.replace('{val}', val));
+                    }
+                    
+                    if (match[1] === 'id' && val) { // store ID for fast-path match
+                        token.id = val;
+                        token.prefilter = function(root) {
+                            var doc = root.nodeType === 9 ? root : root.ownerDocument,
+                                node = doc.getElementById(val);
+                            
+                            return node ? [node] : [];
+                        };
+                    } else if (document.documentElement.getElementsByClassName && 
+                            match[1].indexOf('class') === 0) {
+                        if (!token.prefilter) {
+                            token.prefilter = function(root) {
+                                return root.getElementsByClassName(val);
+                            };
+                            test = true; // skip class test 
+                        }
+                    }
+                    return test;
+
+                }
+
+            },
+            {
+                name: COMBINATOR,
+                re: /^\s*([>+~]|\s)\s*/,
+                fn: function(token, match) {
+                    token[COMBINATOR] = match[1];
+                    return !! Selector.combinators[token[COMBINATOR]];
+                }
+            },
+            {
+                name: PSEUDOS,
+                re: /^:([\-\w]+)(?:\(['"]?(.+)['"]?\))*/i,
+                fn: function(token, match) {
+                    return Selector[PSEUDOS][match[1]];
+
+                }
+            }
+            ],
+
+        _getToken: function(token) {
+            return {
+                previous: token,
+                combinator: ' ',
+                tag: '*',
+                prefilter: function(root) {
+                    return root.getElementsByTagName('*');
+                },
+                tests: [],
+                result: []
+            };
+        },
+
+        /**
+            Break selector into token units per simple selector.
+            Combinator is attached to the previous token.
+         */
+        _tokenize: function(selector, root) {
+            selector = selector || '';
+            selector = Selector._replaceShorthand(Y.Lang.trim(selector)); 
+            var token = Selector._getToken(),     // one token per simple selector (left selector holds combinator)
+                query = selector, // original query for debug report
+                tokens = [],    // array of tokens
+                found = false,  // whether or not any matches were found this pass
+                test,
+                match,         // the regex match
+                i, parser;
+
+            /*
+                Search for selector patterns, store, and strip them from the selector string
+                until no patterns match (invalid selector) or we run out of chars.
+
+                Multiple attributes and pseudos are allowed, in any order.
+                for example:
+                    'form:first-child[type=button]:not(button)[lang|=en]'
+            */
+            outer:
+            do {
+                found = false; // reset after full pass
+                for (i = 0, parser; parser = Selector._parsers[i++];) {
+                    if ( (match = parser.re.exec(selector)) ) { // note assignment
+                        test = parser.fn(token, match);
+                        if (test) {
+                            if (test !== true) { // auto-pass
+                                token.tests.push({
+                                    name: match[1],
+                                    test: test,
+                                    match: match.slice(1)
+                                });
+                            }
+
+                            found = true;
+                            selector = selector.replace(match[0], ''); // strip current match from selector
+                            if (!selector.length || parser.name === COMBINATOR) {
+                                token.root = root;
+                                tokens.push(token);
+                                token = Selector._getToken(token);
+                            }
+                        } else {
+                            found = false;
+                            break outer;
+                        }
+                    }
+                }
+            } while (found && selector.length);
+
+            if (!found || selector.length) { // not fully parsed
+                Y.log('query: ' + query + ' contains unsupported token in: ' + selector, 'warn', 'Selector');
+                tokens = [];
+            } else if (tokens.length) {
+                tokens[tokens.length - 1].last = true;
+            }
+            return tokens;
+        },
+
+        _replaceShorthand: function(selector) {
+            var shorthand = Selector.shorthand,
+                attrs = selector.match(Selector._re.attr), // pull attributes to avoid false pos on "." and "#"
+                re, i, len;
+
+            if (attrs) {
+                selector = selector.replace(Selector._re.attr, 'REPLACED_ATTRIBUTE');
+            }
+
+            for (re in shorthand) {
+                if (shorthand.hasOwnProperty(re)) {
+                    selector = selector.replace(Selector._getRegExp(re, 'gi'), shorthand[re]);
+                }
+            }
+
+            if (attrs) {
+                for (i = 0, len = attrs.length; i < len; ++i) {
+                    selector = selector.replace('REPLACED_ATTRIBUTE', attrs[i]);
+                }
+            }
+            return selector;
+        }
+    };
+
+Y.mix(Y.Selector, SelectorCSS2, true);
+
+// only override native when not supported
+if (!Y.Selector._supportsNative()) {
+    Y.Selector.query = Selector._brute.query;
+}
+
+
+}, '3.0.0b1' ,{requires:['dom-base', 'selector-native'], skinnable:false});
+
+
+YUI.add('dom', function(Y){}, '3.0.0b1' ,{skinnable:false, use:['dom-base', 'dom-style', 'dom-screen', 'selector-native', 'selector-css2']});
+