fmsystem-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Fmsystem-commits] [7287] add missing


From: Sigurd Nes
Subject: [Fmsystem-commits] [7287] add missing
Date: Mon, 23 May 2011 07:42:55 +0000

Revision: 7287
          http://svn.sv.gnu.org/viewvc/?view=rev&root=fmsystem&revision=7287
Author:   sigurdne
Date:     2011-05-23 07:42:55 +0000 (Mon, 23 May 2011)
Log Message:
-----------
add missing

Added Paths:
-----------
    trunk/phpgwapi/js/yui3/dom/
    trunk/phpgwapi/js/yui3/dom/dom-base-debug.js
    trunk/phpgwapi/js/yui3/dom/dom-base-min.js
    trunk/phpgwapi/js/yui3/dom/dom-base.js
    trunk/phpgwapi/js/yui3/dom/dom-debug.js
    trunk/phpgwapi/js/yui3/dom/dom-deprecated-debug.js
    trunk/phpgwapi/js/yui3/dom/dom-deprecated-min.js
    trunk/phpgwapi/js/yui3/dom/dom-deprecated.js
    trunk/phpgwapi/js/yui3/dom/dom-min.js
    trunk/phpgwapi/js/yui3/dom/dom-screen-debug.js
    trunk/phpgwapi/js/yui3/dom/dom-screen-min.js
    trunk/phpgwapi/js/yui3/dom/dom-screen.js
    trunk/phpgwapi/js/yui3/dom/dom-style-debug.js
    trunk/phpgwapi/js/yui3/dom/dom-style-ie-debug.js
    trunk/phpgwapi/js/yui3/dom/dom-style-ie-min.js
    trunk/phpgwapi/js/yui3/dom/dom-style-ie.js
    trunk/phpgwapi/js/yui3/dom/dom-style-min.js
    trunk/phpgwapi/js/yui3/dom/dom-style.js
    trunk/phpgwapi/js/yui3/dom/dom.js
    trunk/phpgwapi/js/yui3/dom/selector-css2-debug.js
    trunk/phpgwapi/js/yui3/dom/selector-css2-min.js
    trunk/phpgwapi/js/yui3/dom/selector-css2.js
    trunk/phpgwapi/js/yui3/dom/selector-css3-debug.js
    trunk/phpgwapi/js/yui3/dom/selector-css3-min.js
    trunk/phpgwapi/js/yui3/dom/selector-css3.js
    trunk/phpgwapi/js/yui3/dom/selector-debug.js
    trunk/phpgwapi/js/yui3/dom/selector-min.js
    trunk/phpgwapi/js/yui3/dom/selector-native-debug.js
    trunk/phpgwapi/js/yui3/dom/selector-native-min.js
    trunk/phpgwapi/js/yui3/dom/selector-native.js
    trunk/phpgwapi/js/yui3/dom/selector.js

Added: trunk/phpgwapi/js/yui3/dom/dom-base-debug.js
===================================================================
--- trunk/phpgwapi/js/yui3/dom/dom-base-debug.js                                
(rev 0)
+++ trunk/phpgwapi/js/yui3/dom/dom-base-debug.js        2011-05-23 07:42:55 UTC 
(rev 7287)
@@ -0,0 +1,986 @@
+/*
+Copyright (c) 2010, Yahoo! Inc. All rights reserved.
+Code licensed under the BSD License:
+http://developer.yahoo.com/yui/license.html
+version: 3.3.0
+build: 3167
+*/
+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
+ * @for DOM
+ *
+ */
+
+/**
+ * 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',
+    PREVIOUS_SIBLING = 'previousSibling',
+    NEXT_SIBLING = 'nextSibling',
+    CONTAINS = 'contains',
+    COMPARE_DOCUMENT_POSITION = 'compareDocumentPosition',
+    EMPTY_STRING = '',
+    EMPTY_ARRAY = [],
+
+    documentElement = Y.config.doc.documentElement,
+
+    re_tag = /<([a-z]+)/i,
+
+    createFromDIV = function(html, tag) {
+        var div = Y.config.doc.createElement('div'),
+            ret = true;
+
+        div.innerHTML = html;
+        if (!div.firstChild || div.firstChild.tagName !== tag.toUpperCase()) {
+            ret = false;
+        }
+
+        return ret;
+    },
+
+    addFeature = Y.Features.add,
+    testFeature = Y.Features.test,
+    
+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) {
+        // handle dupe IDs and IE name collision
+        return Y_DOM.allById(id, doc)[0] || null;
+    },
+
+    /**
+     * 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: (documentElement.textContent !== undefined) ?
+        function(element) {
+            var ret = '';
+            if (element) {
+                ret = element.textContent;
+            }
+            return ret || '';
+        } : function(element) {
+            var ret = '';
+            if (element) {
+                ret = element.innerText || element.nodeValue; // might be a 
textNode
+            }
+            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: (documentElement.textContent !== undefined) ?
+        function(element, content) {
+            if (element) {
+                element.textContent = content;
+            }
+        } : function(element, content) {
+            if ('innerText' in element) {
+                element.innerText = content;
+            } else if ('nodeValue' in element) {
+                element.nodeValue = content;
+            }
+
+        },
+
+    /*
+     * Finds the ancestor of the element.
+     * @method ancestor
+     * @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} testSelf optional Whether or not to include the 
element in the scan 
+     * @return {HTMLElement | null} The matching DOM node or null if none 
found. 
+     */
+    ancestor: function(element, fn, testSelf) {
+        var ret = null;
+        if (testSelf) {
+            ret = (!fn || fn(element)) ? element : null;
+
+        }
+        return ret || Y_DOM.elementByAxis(element, PARENT_NODE, fn, null);
+    },
+
+    /*
+     * Finds the ancestors of the element.
+     * @method ancestors
+     * @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, all ancestors are returned.
+     * @param {Boolean} testSelf optional Whether or not to include the 
element in the scan 
+     * @return {Array} An array containing all matching DOM nodes.
+     */
+    ancestors: function(element, fn, testSelf) {
+        var ancestor = Y_DOM.ancestor.apply(Y_DOM, arguments),
+            ret = (ancestor) ? [ancestor] : [];
+
+        while ((ancestor = Y_DOM.ancestor(ancestor, fn))) {
+            if (ancestor) {
+                ret.unshift(ancestor);
+            }
+        }
+
+        return ret;
+    },
+
+    /**
+     * 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;
+    },
+
+    /**
+     * 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) {
+        var ret = false,
+            rootNode;
+
+        if (element && element.nodeType) {
+            (doc) || (doc = element[OWNER_DOCUMENT]);
+
+            rootNode = doc[DOCUMENT_ELEMENT];
+
+            // contains only works with HTML_ELEMENT
+            if (rootNode && rootNode.contains && element.tagName) {
+                ret = rootNode.contains(element);
+            } else {
+                ret = Y_DOM.contains(rootNode, element);
+            }
+        }
+
+        return ret;
+
+    },
+
+   allById: function(id, root) {
+        root = root || Y.config.doc;
+        var nodes = [],
+            ret = [],
+            i,
+            node;
+
+        if (root.querySelectorAll) {
+            ret = root.querySelectorAll('[id="' + id + '"]');
+        } else if (root.all) {
+            nodes = root.all(id);
+
+            if (nodes) {
+                // root.all may return HTMLElement or HTMLCollection.
+                // some elements are also HTMLCollection (FORM, SELECT).
+                if (nodes.nodeName) {
+                    if (nodes.id === id) { // avoid false positive on name
+                        ret.push(nodes);
+                        nodes = EMPTY_ARRAY; // done, no need to filter
+                    } else { //  prep for filtering
+                        nodes = [nodes];
+                    }
+                }
+
+                if (nodes.length) {
+                    // filter out matches on node.name
+                    // and element.id as reference to element with id === 'id'
+                    for (i = 0; node = nodes[i++];) {
+                        if (node.id === id  || 
+                                (node.attributes && node.attributes.id &&
+                                node.attributes.id.value === id)) { 
+                            ret.push(node);
+                        }
+                    }
+                }
+            }
+        } else {
+            ret = [Y_DOM._getDoc(root).getElementById(id)];
+        }
+    
+        return ret;
+   },
+
+    /**
+     * 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 
+     * @return {HTMLElement|DocumentFragment} returns a single HTMLElement 
+     * when creating one node, and a documentFragment when creating
+     * multiple nodes.
+     */
+    create: function(html, doc) {
+        if (typeof html === 'string') {
+            html = Y.Lang.trim(html); // match IE which trims whitespace from 
innerHTML
+
+        }
+
+        doc = doc || Y.config.doc;
+        var m = re_tag.exec(html),
+            create = Y_DOM._create,
+            custom = Y_DOM.creators,
+            ret = null,
+            creator,
+            tag, nodes;
+
+        if (html != undefined) { // not undefined or null
+            if (m && m[1]) {
+                creator = custom[m[1].toLowerCase()];
+                if (typeof creator === 'function') {
+                    create = creator; 
+                } else {
+                    tag = creator;
+                }
+            }
+
+            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 if (nodes[0] && nodes[0].className === 'yui3-big-dummy') { 
// using dummy node to preserve some attributes (e.g. OPTION not selected)
+                if (nodes.length === 2) {
+                    ret = nodes[0].nextSibling;
+                } else {
+                    nodes[0].parentNode.removeChild(nodes[0]); 
+                     ret = Y_DOM._nl2frag(nodes, doc);
+                }
+            } else { // return multiple nodes as a fragment
+                 ret = Y_DOM._nl2frag(nodes, doc);
+            }
+        }
+
+        return ret;
+    },
+
+    _nl2frag: function(nodes, doc) {
+        var ret = null,
+            i, len;
+
+        if (nodes && (nodes.push || nodes.item) && nodes[0]) {
+            doc = doc || nodes[0].ownerDocument; 
+            ret = doc.createDocumentFragment();
+
+            if (nodes.item) { // convert live list to static array
+                nodes = Y.Array(nodes, 0, true);
+            }
+
+            for (i = 0, len = nodes.length; i < len; i++) {
+                ret.appendChild(nodes[i]); 
+            }
+        } // else inline with log for minification
+        else { Y.log('unable to convert ' + nodes + ' to fragment', 'warn', 
'dom'); }
+        return ret;
+    },
+
+
+    CUSTOM_ATTRIBUTES: (!documentElement.hasAttribute) ? { // IE < 8
+        'for': 'htmlFor',
+        'class': 'className'
+    } : { // w3c
+        'htmlFor': 'for',
+        'className': 'class'
+    },
+
+    /**
+     * Provides a normalized attribute interface. 
+     * @method setAttibute
+     * @param {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, ieAttr) {
+        if (el && attr && el.setAttribute) {
+            attr = Y_DOM.CUSTOM_ATTRIBUTES[attr] || attr;
+            el.setAttribute(attr, val, ieAttr);
+        }
+        else { Y.log('bad input to setAttribute', 'warn', 'dom'); }
+    },
+
+
+    /**
+     * Provides a normalized attribute interface. 
+     * @method getAttibute
+     * @param {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, ieAttr) {
+        ieAttr = (ieAttr !== undefined) ? ieAttr : 2;
+        var ret = '';
+        if (el && attr && el.getAttribute) {
+            attr = Y_DOM.CUSTOM_ATTRIBUTES[attr] || attr;
+            ret = el.getAttribute(attr, ieAttr);
+
+            if (ret === null) {
+                ret = ''; // per DOM spec
+            }
+        }
+        else { Y.log('bad input to getAttribute', 'warn', 'dom'); }
+        return ret;
+    },
+
+    isWindow: function(obj) {
+        return !!(obj && obj.alert && obj.document);
+    },
+
+    _fragClones: {},
+
+    _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);
+        }
+    },
+
+    /**
+     * Inserts content in a node at the given location 
+     * @method addHTML
+     * @param {HTMLElement} node The node to insert into
+     * @param {HTMLElement | Array | HTMLCollection} content The content to be 
inserted 
+     * @param {HTMLElement} where Where to insert the content
+     * If no "where" is given, content is appended to the node
+     * Possible values for "where"
+     * <dl>
+     * <dt>HTMLElement</dt>
+     * <dd>The element to insert before</dd>
+     * <dt>"replace"</dt>
+     * <dd>Replaces the existing HTML</dd>
+     * <dt>"before"</dt>
+     * <dd>Inserts before the existing HTML</dd>
+     * <dt>"before"</dt>
+     * <dd>Inserts content before the node</dd>
+     * <dt>"after"</dt>
+     * <dd>Inserts content after the node</dd>
+     * </dl>
+     */
+    addHTML: function(node, content, where) {
+        var nodeParent = node.parentNode,
+            i = 0,
+            item,
+            ret = content,
+            newNode;
+            
+
+        if (content != undefined) { // not null or undefined (maybe 0)
+            if (content.nodeType) { // DOM node, just add it
+                newNode = content;
+            } else if (typeof content == 'string' || typeof content == 
'number') {
+                ret = newNode = Y_DOM.create(content);
+            } else if (content[0] && content[0].nodeType) { // array or 
collection 
+                newNode = Y.config.doc.createDocumentFragment();
+                while ((item = content[i++])) {
+                    newNode.appendChild(item); // append to fragment for 
insertion
+                }
+            }
+        }
+
+        if (where) {
+            if (where.nodeType) { // insert regardless of relationship to node
+                where.parentNode.insertBefore(newNode, where);
+            } else {
+                switch (where) {
+                    case 'replace':
+                        while (node.firstChild) {
+                            node.removeChild(node.firstChild);
+                        }
+                        if (newNode) { // allow empty content to clear node
+                            node.appendChild(newNode);
+                        }
+                        break;
+                    case 'before':
+                        nodeParent.insertBefore(newNode, node);
+                        break;
+                    case 'after':
+                        if (node.nextSibling) { // IE errors if refNode is null
+                            nodeParent.insertBefore(newNode, node.nextSibling);
+                        } else {
+                            nodeParent.appendChild(newNode);
+                        }
+                        break;
+                    default:
+                        node.appendChild(newNode);
+                }
+            }
+        } else if (newNode) {
+            node.appendChild(newNode);
+        }
+
+        return ret;
+    },
+
+    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;
+            }
+        }
+
+        // workaround for IE8 JSON stringify bug
+        // which converts empty string values to null
+        if (ret === EMPTY_STRING) {
+            ret = EMPTY_STRING; // for real
+        }
+
+        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;
+            }
+        }
+    },
+
+    siblings: function(node, fn) {
+        var nodes = [],
+            sibling = node;
+
+        while ((sibling = sibling[PREVIOUS_SIBLING])) {
+            if (sibling[TAG_NAME] && (!fn || fn(sibling))) {
+                nodes.unshift(sibling);
+            }
+        }
+
+        sibling = node;
+        while ((sibling = sibling[NEXT_SIBLING])) {
+            if (sibling[TAG_NAME] && (!fn || fn(sibling))) {
+                nodes.push(sibling);
+            }
+        }
+
+        return nodes;
+    },
+
+    /**
+     * 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) {
+        var doc = Y.config.doc;
+        if (element) {
+            doc = (element[NODE_TYPE] === 9) ? element : // element === 
document
+                element[OWNER_DOCUMENT] || // element === DOM node
+                element.document || // element === window
+                Y.config.doc; // default
+        }
+
+        return doc;
+    },
+
+    /**
+     * 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;
+    },
+
+    _batch: function(nodes, fn, arg1, arg2, arg3, etc) {
+        fn = (typeof fn === 'string') ? Y_DOM[fn] : fn;
+        var result,
+            args = Array.prototype.slice.call(arguments, 2),
+            i = 0,
+            node,
+            ret;
+
+        if (fn && nodes) {
+            while ((node = nodes[i++])) {
+                result = result = fn.call(Y_DOM, node, arg1, arg2, arg3, etc);
+                if (typeof result !== 'undefined') {
+                    (ret) || (ret = []);
+                    ret.push(result);
+                }
+            }
+        }
+
+        return (typeof ret !== 'undefined') ? ret : nodes;
+    },
+
+    wrap: function(node, html) {
+        var parent = Y.DOM.create(html),
+            nodes = parent.getElementsByTagName('*');
+
+        if (nodes.length) {
+            parent = nodes[nodes.length - 1];
+        }
+
+        if (node.parentNode) { 
+            node.parentNode.replaceChild(parent, node);
+        }
+        parent.appendChild(node);
+    },
+
+    unwrap: function(node) {
+        var parent = node.parentNode,
+            lastChild = parent.lastChild,
+            node = parent.firstChild,
+            next = node,
+            grandparent;
+
+        if (parent) {
+            grandparent = parent.parentNode;
+            if (grandparent) {
+                while (node !== lastChild) {
+                    next = node.nextSibling;
+                    grandparent.insertBefore(node, parent);
+                    node = next;
+                }
+                grandparent.replaceChild(lastChild, parent);
+            } else {
+                parent.removeChild(node);
+            }
+        }
+    },
+
+    generateID: function(el) {
+        var id = el.id;
+
+        if (!id) {
+            id = Y.stamp(el);
+            el.id = id; 
+        }   
+
+        return id; 
+    },
+
+    creators: {}
+};
+
+addFeature('innerhtml', 'table', {
+    test: function() {
+        var node = Y.config.doc.createElement('table');
+        try {
+            node.innerHTML = '<tbody></tbody>';
+        } catch(e) {
+            return false;
+        }
+        return (node.firstChild && node.firstChild.nodeName === 'TBODY');
+    }
+});
+
+addFeature('innerhtml-div', 'tr', {
+    test: function() {
+        return createFromDIV('<tr></tr>', 'tr');
+    }
+});
+
+addFeature('innerhtml-div', 'script', {
+    test: function() {
+        return createFromDIV('<script></script>', 'script');
+    }
+});
+
+addFeature('value-set', 'select', {
+    test: function() {
+        var node = Y.config.doc.createElement('select');
+        node.innerHTML = '<option>1</option><option>2</option>';
+        node.value = '2';
+        return (node.value && node.value === '2');
+    }
+});
+
+(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 (!testFeature('innerhtml', 'table')) {
+        // TODO: thead/tfoot with nested tbody
+            // IE adds TBODY when creating TABLE elements (which may share 
this impl)
+        creators.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;
+        };
+    }
+
+    if (!testFeature('innerhtml-div', 'script')) {
+        creators.script = function(html, doc) {
+            var frag = doc.createElement('div');
+
+            frag.innerHTML = '-' + html;
+            frag.removeChild(frag[FIRST_CHILD]);
+            return frag;
+        }
+
+        Y_DOM.creators.link = Y_DOM.creators.style = Y_DOM.creators.script;
+    }
+
+    
+    if (!testFeature('value-set', 'select')) {
+        Y_DOM.VALUE_SETTERS.select = function(node, val) {
+            for (var i = 0, options = node.getElementsByTagName('option'), 
option;
+                    option = options[i++];) {
+                if (Y_DOM.getValue(option) === val) {
+                    option.selected = true;
+                    //Y_DOM.setAttribute(option, 'selected', 'selected');
+                    break;
+                }
+            }
+        }
+    }
+
+    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 (!testFeature('innerhtml-div', 'tr')) {
+        Y.mix(creators, {
+            option: function(html, doc) {
+                return create('<select><option class="yui3-big-dummy" 
selected></option>' + html + '</select>', doc);
+            },
+
+            tr: function(html, doc) {
+                return create('<tbody>' + html + '</tbody>', doc);
+            },
+
+            td: function(html, doc) {
+                return create('<tr>' + html + '</tr>', doc);
+            }, 
+
+            col: function(html, doc) {
+                return create('<colgroup>' + html + '</colgroup>', doc);
+            }, 
+
+            tbody: 'table'
+        });
+
+        Y.mix(creators, {
+            legend: 'fieldset',
+            th: creators.td,
+            thead: creators.tbody,
+            tfoot: creators.tbody,
+            caption: creators.tbody,
+            colgroup: 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 && options.length) {
+                // TODO: implement multipe select
+                if (node.multiple) {
+                    Y.log('multiple select normalization not implemented', 
'warn', 'DOM');
+                } else {
+                    val = Y_DOM.getValue(options[node.selectedIndex]);
+                }
+            }
+
+            return val;
+        }
+    });
+})(Y);
+
+Y.DOM = Y_DOM;
+})(Y);
+var addClass, hasClass, removeClass;
+
+Y.mix(Y.DOM, {
+    /**
+     * Determines whether a DOM element has the given className.
+     * @method hasClass
+     * @for DOM
+     * @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         
+     * @for DOM
+     * @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         
+     * @for DOM
+     * @param {HTMLElement} element The DOM element. 
+     * @param {String} className the class name to remove from the class 
attribute
+     */
+    removeClass: function(node, className) {
+        if (className && hasClass(node, className)) {
+            node.className = 
Y.Lang.trim(node.className.replace(Y.DOM._getRegExp('(?:^|\\s+)' +
+                            className + '(?:\\s+|$)'), ' '));
+
+            if ( hasClass(node, className) ) { // in case of multiple adjacent
+                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  
+     * @for DOM
+     * @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');
+        removeClass(node, oldC); // remove first in case oldC === newC
+        addClass(node, newC);
+    },
+
+    /**
+     * If the className exists on the node it is removed, if it doesn't exist 
it is added.
+     * @method toggleClass  
+     * @for DOM
+     * @param {HTMLElement} element The DOM element
+     * @param {String} className the class name to be toggled
+     * @param {Boolean} addClass optional boolean to indicate whether class
+     * should be added or removed regardless of current state
+     */
+    toggleClass: function(node, className, force) {
+        var add = (force !== undefined) ? force :
+                !(hasClass(node, className));
+
+        if (add) {
+            addClass(node, className);
+        } else {
+            removeClass(node, className);
+        }
+    }
+});
+
+hasClass = Y.DOM.hasClass;
+removeClass = Y.DOM.removeClass;
+addClass = Y.DOM.addClass;
+
+Y.mix(Y.DOM, {
+    /**
+     * Sets the width of the element to the given size, regardless
+     * of box model, border, padding, etc.
+     * @method setWidth
+     * @param {HTMLElement} element The DOM element. 
+     * @param {String|Int} size The pixel height to size to
+     */
+
+    setWidth: function(node, size) {
+        Y.DOM._setSize(node, 'width', size);
+    },
+
+    /**
+     * Sets the height of the element to the given size, regardless
+     * of box model, border, padding, etc.
+     * @method setHeight
+     * @param {HTMLElement} element The DOM element. 
+     * @param {String|Int} size The pixel height to size to
+     */
+
+    setHeight: function(node, size) {
+        Y.DOM._setSize(node, 'height', size);
+    },
+
+    _setSize: function(node, prop, val) {
+        val = (val > 0) ? val : 0;
+        var size = 0;
+
+        node.style[prop] = val + 'px';
+        size = (prop === 'height') ? node.offsetHeight : node.offsetWidth;
+
+        if (size > val) {
+            val = val - (size - val);
+
+            if (val < 0) {
+                val = 0;
+            }
+
+            node.style[prop] = val + 'px';
+        }
+    }
+});
+
+
+}, '3.3.0' ,{requires:['oop']});

Added: trunk/phpgwapi/js/yui3/dom/dom-base-min.js
===================================================================
--- trunk/phpgwapi/js/yui3/dom/dom-base-min.js                          (rev 0)
+++ trunk/phpgwapi/js/yui3/dom/dom-base-min.js  2011-05-23 07:42:55 UTC (rev 
7287)
@@ -0,0 +1,9 @@
+/*
+Copyright (c) 2010, Yahoo! Inc. All rights reserved.
+Code licensed under the BSD License:
+http://developer.yahoo.com/yui/license.html
+version: 3.3.0
+build: 3167
+*/
+YUI.add("dom-base",function(d){(function(h){var 
o="nodeType",u="ownerDocument",v="documentElement",g="defaultView",m="parentWindow",s="tagName",k="parentNode",e="firstChild",t="previousSibling",w="nextSibling",l="contains",r="compareDocumentPosition",f="",i=[],y=h.config.doc.documentElement,n=/<([a-z]+)/i,j=function(B,z){var
 
C=h.config.doc.createElement("div"),A=true;C.innerHTML=B;if(!C.firstChild||C.firstChild.tagName!==z.toUpperCase()){A=false;}return
 A;},p=h.Features.add,q=h.Features.test,x={byId:function(A,z){return 
x.allById(A,z)[0]||null;},getText:(y.textContent!==undefined)?function(A){var 
z="";if(A){z=A.textContent;}return z||"";}:function(A){var 
z="";if(A){z=A.innerText||A.nodeValue;}return 
z||"";},setText:(y.textContent!==undefined)?function(z,A){if(z){z.textContent=A;}}:function(z,A){if("innerText"
 in z){z.innerText=A;}else{if("nodeValue" in 
z){z.nodeValue=A;}}},ancestor:function(A,B,C){var 
z=null;if(C){z=(!B||B(A))?A:null;}return 
z||x.elementByAxis(A,k,B,null);},ancestors:function(B,C,D){var 
A=x.ancestor.apply(x,arguments),z=(A)?[A]:[];while((A=x.ancestor(A,C))){if(A){z.unshift(A);}}return
 
z;},elementByAxis:function(z,C,B,A){while(z&&(z=z[C])){if((A||z[s])&&(!B||B(z))){return
 z;}}return null;},contains:function(A,B){var 
z=false;if(!B||!A||!B[o]||!A[o]){z=false;}else{if(A[l]){if(h.UA.opera||B[o]===1){z=A[l](B);}else{z=x._bruteContains(A,B);}}else{if(A[r]){if(A===B||!!(A[r](B)&16)){z=true;}}}}return
 z;},inDoc:function(B,C){var 
A=false,z;if(B&&B.nodeType){(C)||(C=B[u]);z=C[v];if(z&&z.contains&&B.tagName){A=z.contains(B);}else{A=x.contains(z,B);}}return
 A;},allById:function(E,z){z=z||h.config.doc;var 
A=[],B=[],C,D;if(z.querySelectorAll){B=z.querySelectorAll('[id="'+E+'"]');}else{if(z.all){A=z.all(E);if(A){if(A.nodeName){if(A.id===E){B.push(A);A=i;}else{A=[A];}}if(A.length){for(C=0;D=A[C++];){if(D.id===E||(D.attributes&&D.attributes.id&&D.attributes.id.value===E)){B.push(D);}}}}}else{B=[x._getDoc(z).getElementById(E)];}}return
 B;},create:function(D,G){if(typeof 
D==="string"){D=h.Lang.trim(D);}G=G||h.config.doc;var 
C=n.exec(D),E=x._create,A=x.creators,F=null,B,H,z;if(D!=undefined){if(C&&C[1]){B=A[C[1].toLowerCase()];if(typeof
 
B==="function"){E=B;}else{H=B;}}z=E(D,G,H).childNodes;if(z.length===1){F=z[0].parentNode.removeChild(z[0]);}else{if(z[0]&&z[0].className==="yui3-big-dummy"){if(z.length===2){F=z[0].nextSibling;}else{z[0].parentNode.removeChild(z[0]);F=x._nl2frag(z,G);}}else{F=x._nl2frag(z,G);}}}return
 F;},_nl2frag:function(A,D){var 
B=null,C,z;if(A&&(A.push||A.item)&&A[0]){D=D||A[0].ownerDocument;B=D.createDocumentFragment();if(A.item){A=h.Array(A,0,true);}for(C=0,z=A.length;C<z;C++){B.appendChild(A[C]);}}return
 
B;},CUSTOM_ATTRIBUTES:(!y.hasAttribute)?{"for":"htmlFor","class":"className"}:{"htmlFor":"for","className":"class"},setAttribute:function(B,z,C,A){if(B&&z&&B.setAttribute){z=x.CUSTOM_ATTRIBUTES[z]||z;B.setAttribute(z,C,A);}},getAttribute:function(C,z,B){B=(B!==undefined)?B:2;var
 
A="";if(C&&z&&C.getAttribute){z=x.CUSTOM_ATTRIBUTES[z]||z;A=C.getAttribute(z,B);if(A===null){A="";}}return
 A;},isWindow:function(z){return 
!!(z&&z.alert&&z.document);},_fragClones:{},_create:function(A,B,z){z=z||"div";var
 
C=x._fragClones[z];if(C){C=C.cloneNode(false);}else{C=x._fragClones[z]=B.createElement(z);}C.innerHTML=A;return
 
C;},_removeChildNodes:function(z){while(z.firstChild){z.removeChild(z.firstChild);}},addHTML:function(G,F,B){var
 z=G.parentNode,D=0,E,A=F,C;if(F!=undefined){if(F.nodeType){C=F;}else{if(typeof 
F=="string"||typeof 
F=="number"){A=C=x.create(F);}else{if(F[0]&&F[0].nodeType){C=h.config.doc.createDocumentFragment();while((E=F[D++])){C.appendChild(E);}}}}}if(B){if(B.nodeType){B.parentNode.insertBefore(C,B);}else{switch(B){case"replace":while(G.firstChild){G.removeChild(G.firstChild);}if(C){G.appendChild(C);}break;case"before":z.insertBefore(C,G);break;case"after":if(G.nextSibling){z.insertBefore(C,G.nextSibling);}else{z.appendChild(C);}break;default:G.appendChild(C);}}}else{if(C){G.appendChild(C);}}return
 A;},VALUE_SETTERS:{},VALUE_GETTERS:{},getValue:function(B){var 
A="",z;if(B&&B[s]){z=x.VALUE_GETTERS[B[s].toLowerCase()];if(z){A=z(B);}else{A=B.value;}}if(A===f){A=f;}return(typeof
 A==="string")?A:"";},setValue:function(z,A){var 
B;if(z&&z[s]){B=x.VALUE_SETTERS[z[s].toLowerCase()];if(B){B(z,A);}else{z.value=A;}}},siblings:function(C,B){var
 
z=[],A=C;while((A=A[t])){if(A[s]&&(!B||B(A))){z.unshift(A);}}A=C;while((A=A[w])){if(A[s]&&(!B||B(A))){z.push(A);}}return
 z;},_bruteContains:function(z,A){while(A){if(z===A){return 
true;}A=A.parentNode;}return 
false;},_getRegExp:function(A,z){z=z||"";x._regexCache=x._regexCache||{};if(!x._regexCache[A+z]){x._regexCache[A+z]=new
 RegExp(A,z);}return x._regexCache[A+z];},_getDoc:function(z){var 
A=h.config.doc;if(z){A=(z[o]===9)?z:z[u]||z.document||h.config.doc;}return 
A;},_getWin:function(z){var A=x._getDoc(z);return 
A[g]||A[m]||h.config.win;},_batch:function(z,I,F,E,D,B){I=(typeof 
I==="string")?x[I]:I;var 
J,H=Array.prototype.slice.call(arguments,2),C=0,A,G;if(I&&z){while((A=z[C++])){J=J=I.call(x,A,F,E,D,B);if(typeof
 J!=="undefined"){(G)||(G=[]);G.push(J);}}}return(typeof 
G!=="undefined")?G:z;},wrap:function(C,A){var 
B=h.DOM.create(A),z=B.getElementsByTagName("*");if(z.length){B=z[z.length-1];}if(C.parentNode){C.parentNode.replaceChild(B,C);}B.appendChild(C);},unwrap:function(C){var
 
A=C.parentNode,B=A.lastChild,C=A.firstChild,z=C,D;if(A){D=A.parentNode;if(D){while(C!==B){z=C.nextSibling;D.insertBefore(C,A);C=z;}D.replaceChild(B,A);}else{A.removeChild(C);}}},generateID:function(z){var
 A=z.id;if(!A){A=h.stamp(z);z.id=A;}return 
A;},creators:{}};p("innerhtml","table",{test:function(){var 
z=h.config.doc.createElement("table");try{z.innerHTML="<tbody></tbody>";}catch(A){return
 
false;}return(z.firstChild&&z.firstChild.nodeName==="TBODY");}});p("innerhtml-div","tr",{test:function(){return
 j("<tr></tr>","tr");}});p("innerhtml-div","script",{test:function(){return 
j("<script><\/script>","script");}});p("value-set","select",{test:function(){var
 z=h.config.doc.createElement("select");
+z.innerHTML="<option>1</option><option>2</option>";z.value="2";return(z.value&&z.value==="2");}});(function(D){var
 
E=x.creators,z=x.create,C=/(?:\/(?:thead|tfoot|tbody|caption|col|colgroup)>)+\s*<tbody/,B="<table>",A="</table>";if(!q("innerhtml","table")){E.tbody=function(G,H){var
 
I=z(B+G+A,H),F=I.children.tags("tbody")[0];if(I.children.length>1&&F&&!C.test(G)){F[k].removeChild(F);}return
 I;};}if(!q("innerhtml-div","script")){E.script=function(F,G){var 
H=G.createElement("div");H.innerHTML="-"+F;H.removeChild(H[e]);return 
H;};x.creators.link=x.creators.style=x.creators.script;}if(!q("value-set","select")){x.VALUE_SETTERS.select=function(I,J){for(var
 
G=0,F=I.getElementsByTagName("option"),H;H=F[G++];){if(x.getValue(H)===J){H.selected=true;break;}}};}D.mix(x.VALUE_GETTERS,{button:function(F){return(F.attributes&&F.attributes.value)?F.attributes.value.value:"";}});D.mix(x.VALUE_SETTERS,{button:function(G,H){var
 
F=G.attributes.value;if(!F){F=G[u].createAttribute("value");G.setAttributeNode(F);}F.value=H;}});if(!q("innerhtml-div","tr")){D.mix(E,{option:function(F,G){return
 z('<select><option class="yui3-big-dummy" 
selected></option>'+F+"</select>",G);},tr:function(F,G){return 
z("<tbody>"+F+"</tbody>",G);},td:function(F,G){return 
z("<tr>"+F+"</tr>",G);},col:function(F,G){return 
z("<colgroup>"+F+"</colgroup>",G);},tbody:"table"});D.mix(E,{legend:"fieldset",th:E.td,thead:E.tbody,tfoot:E.tbody,caption:E.tbody,colgroup:E.tbody,optgroup:E.option});}D.mix(x.VALUE_GETTERS,{option:function(G){var
 
F=G.attributes;return(F.value&&F.value.specified)?G.value:G.text;},select:function(G){var
 
H=G.value,F=G.options;if(F&&F.length){if(G.multiple){}else{H=x.getValue(F[G.selectedIndex]);}}return
 H;}});})(h);h.DOM=x;})(d);var b,a,c;d.mix(d.DOM,{hasClass:function(g,f){var 
e=d.DOM._getRegExp("(?:^|\\s+)"+f+"(?:\\s+|$)");return 
e.test(g.className);},addClass:function(f,e){if(!d.DOM.hasClass(f,e)){f.className=d.Lang.trim([f.className,e].join("
 
"));}},removeClass:function(f,e){if(e&&a(f,e)){f.className=d.Lang.trim(f.className.replace(d.DOM._getRegExp("(?:^|\\s+)"+e+"(?:\\s+|$)"),"
 
"));if(a(f,e)){c(f,e);}}},replaceClass:function(f,e,g){c(f,e);b(f,g);},toggleClass:function(f,e,g){var
 
h=(g!==undefined)?g:!(a(f,e));if(h){b(f,e);}else{c(f,e);}}});a=d.DOM.hasClass;c=d.DOM.removeClass;b=d.DOM.addClass;d.mix(d.DOM,{setWidth:function(f,e){d.DOM._setSize(f,"width",e);},setHeight:function(f,e){d.DOM._setSize(f,"height",e);},_setSize:function(f,h,g){g=(g>0)?g:0;var
 
e=0;f.style[h]=g+"px";e=(h==="height")?f.offsetHeight:f.offsetWidth;if(e>g){g=g-(e-g);if(g<0){g=0;}f.style[h]=g+"px";}}});},"3.3.0",{requires:["oop"]});
\ No newline at end of file

Added: trunk/phpgwapi/js/yui3/dom/dom-base.js
===================================================================
--- trunk/phpgwapi/js/yui3/dom/dom-base.js                              (rev 0)
+++ trunk/phpgwapi/js/yui3/dom/dom-base.js      2011-05-23 07:42:55 UTC (rev 
7287)
@@ -0,0 +1,981 @@
+/*
+Copyright (c) 2010, Yahoo! Inc. All rights reserved.
+Code licensed under the BSD License:
+http://developer.yahoo.com/yui/license.html
+version: 3.3.0
+build: 3167
+*/
+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
+ * @for DOM
+ *
+ */
+
+/**
+ * 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',
+    PREVIOUS_SIBLING = 'previousSibling',
+    NEXT_SIBLING = 'nextSibling',
+    CONTAINS = 'contains',
+    COMPARE_DOCUMENT_POSITION = 'compareDocumentPosition',
+    EMPTY_STRING = '',
+    EMPTY_ARRAY = [],
+
+    documentElement = Y.config.doc.documentElement,
+
+    re_tag = /<([a-z]+)/i,
+
+    createFromDIV = function(html, tag) {
+        var div = Y.config.doc.createElement('div'),
+            ret = true;
+
+        div.innerHTML = html;
+        if (!div.firstChild || div.firstChild.tagName !== tag.toUpperCase()) {
+            ret = false;
+        }
+
+        return ret;
+    },
+
+    addFeature = Y.Features.add,
+    testFeature = Y.Features.test,
+    
+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) {
+        // handle dupe IDs and IE name collision
+        return Y_DOM.allById(id, doc)[0] || null;
+    },
+
+    /**
+     * 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: (documentElement.textContent !== undefined) ?
+        function(element) {
+            var ret = '';
+            if (element) {
+                ret = element.textContent;
+            }
+            return ret || '';
+        } : function(element) {
+            var ret = '';
+            if (element) {
+                ret = element.innerText || element.nodeValue; // might be a 
textNode
+            }
+            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: (documentElement.textContent !== undefined) ?
+        function(element, content) {
+            if (element) {
+                element.textContent = content;
+            }
+        } : function(element, content) {
+            if ('innerText' in element) {
+                element.innerText = content;
+            } else if ('nodeValue' in element) {
+                element.nodeValue = content;
+            }
+
+        },
+
+    /*
+     * Finds the ancestor of the element.
+     * @method ancestor
+     * @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} testSelf optional Whether or not to include the 
element in the scan 
+     * @return {HTMLElement | null} The matching DOM node or null if none 
found. 
+     */
+    ancestor: function(element, fn, testSelf) {
+        var ret = null;
+        if (testSelf) {
+            ret = (!fn || fn(element)) ? element : null;
+
+        }
+        return ret || Y_DOM.elementByAxis(element, PARENT_NODE, fn, null);
+    },
+
+    /*
+     * Finds the ancestors of the element.
+     * @method ancestors
+     * @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, all ancestors are returned.
+     * @param {Boolean} testSelf optional Whether or not to include the 
element in the scan 
+     * @return {Array} An array containing all matching DOM nodes.
+     */
+    ancestors: function(element, fn, testSelf) {
+        var ancestor = Y_DOM.ancestor.apply(Y_DOM, arguments),
+            ret = (ancestor) ? [ancestor] : [];
+
+        while ((ancestor = Y_DOM.ancestor(ancestor, fn))) {
+            if (ancestor) {
+                ret.unshift(ancestor);
+            }
+        }
+
+        return ret;
+    },
+
+    /**
+     * 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;
+    },
+
+    /**
+     * 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) {
+        var ret = false,
+            rootNode;
+
+        if (element && element.nodeType) {
+            (doc) || (doc = element[OWNER_DOCUMENT]);
+
+            rootNode = doc[DOCUMENT_ELEMENT];
+
+            // contains only works with HTML_ELEMENT
+            if (rootNode && rootNode.contains && element.tagName) {
+                ret = rootNode.contains(element);
+            } else {
+                ret = Y_DOM.contains(rootNode, element);
+            }
+        }
+
+        return ret;
+
+    },
+
+   allById: function(id, root) {
+        root = root || Y.config.doc;
+        var nodes = [],
+            ret = [],
+            i,
+            node;
+
+        if (root.querySelectorAll) {
+            ret = root.querySelectorAll('[id="' + id + '"]');
+        } else if (root.all) {
+            nodes = root.all(id);
+
+            if (nodes) {
+                // root.all may return HTMLElement or HTMLCollection.
+                // some elements are also HTMLCollection (FORM, SELECT).
+                if (nodes.nodeName) {
+                    if (nodes.id === id) { // avoid false positive on name
+                        ret.push(nodes);
+                        nodes = EMPTY_ARRAY; // done, no need to filter
+                    } else { //  prep for filtering
+                        nodes = [nodes];
+                    }
+                }
+
+                if (nodes.length) {
+                    // filter out matches on node.name
+                    // and element.id as reference to element with id === 'id'
+                    for (i = 0; node = nodes[i++];) {
+                        if (node.id === id  || 
+                                (node.attributes && node.attributes.id &&
+                                node.attributes.id.value === id)) { 
+                            ret.push(node);
+                        }
+                    }
+                }
+            }
+        } else {
+            ret = [Y_DOM._getDoc(root).getElementById(id)];
+        }
+    
+        return ret;
+   },
+
+    /**
+     * 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 
+     * @return {HTMLElement|DocumentFragment} returns a single HTMLElement 
+     * when creating one node, and a documentFragment when creating
+     * multiple nodes.
+     */
+    create: function(html, doc) {
+        if (typeof html === 'string') {
+            html = Y.Lang.trim(html); // match IE which trims whitespace from 
innerHTML
+
+        }
+
+        doc = doc || Y.config.doc;
+        var m = re_tag.exec(html),
+            create = Y_DOM._create,
+            custom = Y_DOM.creators,
+            ret = null,
+            creator,
+            tag, nodes;
+
+        if (html != undefined) { // not undefined or null
+            if (m && m[1]) {
+                creator = custom[m[1].toLowerCase()];
+                if (typeof creator === 'function') {
+                    create = creator; 
+                } else {
+                    tag = creator;
+                }
+            }
+
+            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 if (nodes[0] && nodes[0].className === 'yui3-big-dummy') { 
// using dummy node to preserve some attributes (e.g. OPTION not selected)
+                if (nodes.length === 2) {
+                    ret = nodes[0].nextSibling;
+                } else {
+                    nodes[0].parentNode.removeChild(nodes[0]); 
+                     ret = Y_DOM._nl2frag(nodes, doc);
+                }
+            } else { // return multiple nodes as a fragment
+                 ret = Y_DOM._nl2frag(nodes, doc);
+            }
+        }
+
+        return ret;
+    },
+
+    _nl2frag: function(nodes, doc) {
+        var ret = null,
+            i, len;
+
+        if (nodes && (nodes.push || nodes.item) && nodes[0]) {
+            doc = doc || nodes[0].ownerDocument; 
+            ret = doc.createDocumentFragment();
+
+            if (nodes.item) { // convert live list to static array
+                nodes = Y.Array(nodes, 0, true);
+            }
+
+            for (i = 0, len = nodes.length; i < len; i++) {
+                ret.appendChild(nodes[i]); 
+            }
+        } // else inline with log for minification
+        return ret;
+    },
+
+
+    CUSTOM_ATTRIBUTES: (!documentElement.hasAttribute) ? { // IE < 8
+        'for': 'htmlFor',
+        'class': 'className'
+    } : { // w3c
+        'htmlFor': 'for',
+        'className': 'class'
+    },
+
+    /**
+     * Provides a normalized attribute interface. 
+     * @method setAttibute
+     * @param {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, ieAttr) {
+        if (el && attr && el.setAttribute) {
+            attr = Y_DOM.CUSTOM_ATTRIBUTES[attr] || attr;
+            el.setAttribute(attr, val, ieAttr);
+        }
+    },
+
+
+    /**
+     * Provides a normalized attribute interface. 
+     * @method getAttibute
+     * @param {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, ieAttr) {
+        ieAttr = (ieAttr !== undefined) ? ieAttr : 2;
+        var ret = '';
+        if (el && attr && el.getAttribute) {
+            attr = Y_DOM.CUSTOM_ATTRIBUTES[attr] || attr;
+            ret = el.getAttribute(attr, ieAttr);
+
+            if (ret === null) {
+                ret = ''; // per DOM spec
+            }
+        }
+        return ret;
+    },
+
+    isWindow: function(obj) {
+        return !!(obj && obj.alert && obj.document);
+    },
+
+    _fragClones: {},
+
+    _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);
+        }
+    },
+
+    /**
+     * Inserts content in a node at the given location 
+     * @method addHTML
+     * @param {HTMLElement} node The node to insert into
+     * @param {HTMLElement | Array | HTMLCollection} content The content to be 
inserted 
+     * @param {HTMLElement} where Where to insert the content
+     * If no "where" is given, content is appended to the node
+     * Possible values for "where"
+     * <dl>
+     * <dt>HTMLElement</dt>
+     * <dd>The element to insert before</dd>
+     * <dt>"replace"</dt>
+     * <dd>Replaces the existing HTML</dd>
+     * <dt>"before"</dt>
+     * <dd>Inserts before the existing HTML</dd>
+     * <dt>"before"</dt>
+     * <dd>Inserts content before the node</dd>
+     * <dt>"after"</dt>
+     * <dd>Inserts content after the node</dd>
+     * </dl>
+     */
+    addHTML: function(node, content, where) {
+        var nodeParent = node.parentNode,
+            i = 0,
+            item,
+            ret = content,
+            newNode;
+            
+
+        if (content != undefined) { // not null or undefined (maybe 0)
+            if (content.nodeType) { // DOM node, just add it
+                newNode = content;
+            } else if (typeof content == 'string' || typeof content == 
'number') {
+                ret = newNode = Y_DOM.create(content);
+            } else if (content[0] && content[0].nodeType) { // array or 
collection 
+                newNode = Y.config.doc.createDocumentFragment();
+                while ((item = content[i++])) {
+                    newNode.appendChild(item); // append to fragment for 
insertion
+                }
+            }
+        }
+
+        if (where) {
+            if (where.nodeType) { // insert regardless of relationship to node
+                where.parentNode.insertBefore(newNode, where);
+            } else {
+                switch (where) {
+                    case 'replace':
+                        while (node.firstChild) {
+                            node.removeChild(node.firstChild);
+                        }
+                        if (newNode) { // allow empty content to clear node
+                            node.appendChild(newNode);
+                        }
+                        break;
+                    case 'before':
+                        nodeParent.insertBefore(newNode, node);
+                        break;
+                    case 'after':
+                        if (node.nextSibling) { // IE errors if refNode is null
+                            nodeParent.insertBefore(newNode, node.nextSibling);
+                        } else {
+                            nodeParent.appendChild(newNode);
+                        }
+                        break;
+                    default:
+                        node.appendChild(newNode);
+                }
+            }
+        } else if (newNode) {
+            node.appendChild(newNode);
+        }
+
+        return ret;
+    },
+
+    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;
+            }
+        }
+
+        // workaround for IE8 JSON stringify bug
+        // which converts empty string values to null
+        if (ret === EMPTY_STRING) {
+            ret = EMPTY_STRING; // for real
+        }
+
+        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;
+            }
+        }
+    },
+
+    siblings: function(node, fn) {
+        var nodes = [],
+            sibling = node;
+
+        while ((sibling = sibling[PREVIOUS_SIBLING])) {
+            if (sibling[TAG_NAME] && (!fn || fn(sibling))) {
+                nodes.unshift(sibling);
+            }
+        }
+
+        sibling = node;
+        while ((sibling = sibling[NEXT_SIBLING])) {
+            if (sibling[TAG_NAME] && (!fn || fn(sibling))) {
+                nodes.push(sibling);
+            }
+        }
+
+        return nodes;
+    },
+
+    /**
+     * 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) {
+        var doc = Y.config.doc;
+        if (element) {
+            doc = (element[NODE_TYPE] === 9) ? element : // element === 
document
+                element[OWNER_DOCUMENT] || // element === DOM node
+                element.document || // element === window
+                Y.config.doc; // default
+        }
+
+        return doc;
+    },
+
+    /**
+     * 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;
+    },
+
+    _batch: function(nodes, fn, arg1, arg2, arg3, etc) {
+        fn = (typeof fn === 'string') ? Y_DOM[fn] : fn;
+        var result,
+            args = Array.prototype.slice.call(arguments, 2),
+            i = 0,
+            node,
+            ret;
+
+        if (fn && nodes) {
+            while ((node = nodes[i++])) {
+                result = result = fn.call(Y_DOM, node, arg1, arg2, arg3, etc);
+                if (typeof result !== 'undefined') {
+                    (ret) || (ret = []);
+                    ret.push(result);
+                }
+            }
+        }
+
+        return (typeof ret !== 'undefined') ? ret : nodes;
+    },
+
+    wrap: function(node, html) {
+        var parent = Y.DOM.create(html),
+            nodes = parent.getElementsByTagName('*');
+
+        if (nodes.length) {
+            parent = nodes[nodes.length - 1];
+        }
+
+        if (node.parentNode) { 
+            node.parentNode.replaceChild(parent, node);
+        }
+        parent.appendChild(node);
+    },
+
+    unwrap: function(node) {
+        var parent = node.parentNode,
+            lastChild = parent.lastChild,
+            node = parent.firstChild,
+            next = node,
+            grandparent;
+
+        if (parent) {
+            grandparent = parent.parentNode;
+            if (grandparent) {
+                while (node !== lastChild) {
+                    next = node.nextSibling;
+                    grandparent.insertBefore(node, parent);
+                    node = next;
+                }
+                grandparent.replaceChild(lastChild, parent);
+            } else {
+                parent.removeChild(node);
+            }
+        }
+    },
+
+    generateID: function(el) {
+        var id = el.id;
+
+        if (!id) {
+            id = Y.stamp(el);
+            el.id = id; 
+        }   
+
+        return id; 
+    },
+
+    creators: {}
+};
+
+addFeature('innerhtml', 'table', {
+    test: function() {
+        var node = Y.config.doc.createElement('table');
+        try {
+            node.innerHTML = '<tbody></tbody>';
+        } catch(e) {
+            return false;
+        }
+        return (node.firstChild && node.firstChild.nodeName === 'TBODY');
+    }
+});
+
+addFeature('innerhtml-div', 'tr', {
+    test: function() {
+        return createFromDIV('<tr></tr>', 'tr');
+    }
+});
+
+addFeature('innerhtml-div', 'script', {
+    test: function() {
+        return createFromDIV('<script></script>', 'script');
+    }
+});
+
+addFeature('value-set', 'select', {
+    test: function() {
+        var node = Y.config.doc.createElement('select');
+        node.innerHTML = '<option>1</option><option>2</option>';
+        node.value = '2';
+        return (node.value && node.value === '2');
+    }
+});
+
+(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 (!testFeature('innerhtml', 'table')) {
+        // TODO: thead/tfoot with nested tbody
+            // IE adds TBODY when creating TABLE elements (which may share 
this impl)
+        creators.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;
+        };
+    }
+
+    if (!testFeature('innerhtml-div', 'script')) {
+        creators.script = function(html, doc) {
+            var frag = doc.createElement('div');
+
+            frag.innerHTML = '-' + html;
+            frag.removeChild(frag[FIRST_CHILD]);
+            return frag;
+        }
+
+        Y_DOM.creators.link = Y_DOM.creators.style = Y_DOM.creators.script;
+    }
+
+    
+    if (!testFeature('value-set', 'select')) {
+        Y_DOM.VALUE_SETTERS.select = function(node, val) {
+            for (var i = 0, options = node.getElementsByTagName('option'), 
option;
+                    option = options[i++];) {
+                if (Y_DOM.getValue(option) === val) {
+                    option.selected = true;
+                    //Y_DOM.setAttribute(option, 'selected', 'selected');
+                    break;
+                }
+            }
+        }
+    }
+
+    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 (!testFeature('innerhtml-div', 'tr')) {
+        Y.mix(creators, {
+            option: function(html, doc) {
+                return create('<select><option class="yui3-big-dummy" 
selected></option>' + html + '</select>', doc);
+            },
+
+            tr: function(html, doc) {
+                return create('<tbody>' + html + '</tbody>', doc);
+            },
+
+            td: function(html, doc) {
+                return create('<tr>' + html + '</tr>', doc);
+            }, 
+
+            col: function(html, doc) {
+                return create('<colgroup>' + html + '</colgroup>', doc);
+            }, 
+
+            tbody: 'table'
+        });
+
+        Y.mix(creators, {
+            legend: 'fieldset',
+            th: creators.td,
+            thead: creators.tbody,
+            tfoot: creators.tbody,
+            caption: creators.tbody,
+            colgroup: 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 && options.length) {
+                // TODO: implement multipe select
+                if (node.multiple) {
+                } else {
+                    val = Y_DOM.getValue(options[node.selectedIndex]);
+                }
+            }
+
+            return val;
+        }
+    });
+})(Y);
+
+Y.DOM = Y_DOM;
+})(Y);
+var addClass, hasClass, removeClass;
+
+Y.mix(Y.DOM, {
+    /**
+     * Determines whether a DOM element has the given className.
+     * @method hasClass
+     * @for DOM
+     * @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         
+     * @for DOM
+     * @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         
+     * @for DOM
+     * @param {HTMLElement} element The DOM element. 
+     * @param {String} className the class name to remove from the class 
attribute
+     */
+    removeClass: function(node, className) {
+        if (className && hasClass(node, className)) {
+            node.className = 
Y.Lang.trim(node.className.replace(Y.DOM._getRegExp('(?:^|\\s+)' +
+                            className + '(?:\\s+|$)'), ' '));
+
+            if ( hasClass(node, className) ) { // in case of multiple adjacent
+                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  
+     * @for DOM
+     * @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) {
+        removeClass(node, oldC); // remove first in case oldC === newC
+        addClass(node, newC);
+    },
+
+    /**
+     * If the className exists on the node it is removed, if it doesn't exist 
it is added.
+     * @method toggleClass  
+     * @for DOM
+     * @param {HTMLElement} element The DOM element
+     * @param {String} className the class name to be toggled
+     * @param {Boolean} addClass optional boolean to indicate whether class
+     * should be added or removed regardless of current state
+     */
+    toggleClass: function(node, className, force) {
+        var add = (force !== undefined) ? force :
+                !(hasClass(node, className));
+
+        if (add) {
+            addClass(node, className);
+        } else {
+            removeClass(node, className);
+        }
+    }
+});
+
+hasClass = Y.DOM.hasClass;
+removeClass = Y.DOM.removeClass;
+addClass = Y.DOM.addClass;
+
+Y.mix(Y.DOM, {
+    /**
+     * Sets the width of the element to the given size, regardless
+     * of box model, border, padding, etc.
+     * @method setWidth
+     * @param {HTMLElement} element The DOM element. 
+     * @param {String|Int} size The pixel height to size to
+     */
+
+    setWidth: function(node, size) {
+        Y.DOM._setSize(node, 'width', size);
+    },
+
+    /**
+     * Sets the height of the element to the given size, regardless
+     * of box model, border, padding, etc.
+     * @method setHeight
+     * @param {HTMLElement} element The DOM element. 
+     * @param {String|Int} size The pixel height to size to
+     */
+
+    setHeight: function(node, size) {
+        Y.DOM._setSize(node, 'height', size);
+    },
+
+    _setSize: function(node, prop, val) {
+        val = (val > 0) ? val : 0;
+        var size = 0;
+
+        node.style[prop] = val + 'px';
+        size = (prop === 'height') ? node.offsetHeight : node.offsetWidth;
+
+        if (size > val) {
+            val = val - (size - val);
+
+            if (val < 0) {
+                val = 0;
+            }
+
+            node.style[prop] = val + 'px';
+        }
+    }
+});
+
+
+}, '3.3.0' ,{requires:['oop']});

Added: trunk/phpgwapi/js/yui3/dom/dom-debug.js
===================================================================
--- trunk/phpgwapi/js/yui3/dom/dom-debug.js                             (rev 0)
+++ trunk/phpgwapi/js/yui3/dom/dom-debug.js     2011-05-23 07:42:55 UTC (rev 
7287)
@@ -0,0 +1,2621 @@
+/*
+Copyright (c) 2010, Yahoo! Inc. All rights reserved.
+Code licensed under the BSD License:
+http://developer.yahoo.com/yui/license.html
+version: 3.3.0
+build: 3167
+*/
+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
+ * @for DOM
+ *
+ */
+
+/**
+ * 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',
+    PREVIOUS_SIBLING = 'previousSibling',
+    NEXT_SIBLING = 'nextSibling',
+    CONTAINS = 'contains',
+    COMPARE_DOCUMENT_POSITION = 'compareDocumentPosition',
+    EMPTY_STRING = '',
+    EMPTY_ARRAY = [],
+
+    documentElement = Y.config.doc.documentElement,
+
+    re_tag = /<([a-z]+)/i,
+
+    createFromDIV = function(html, tag) {
+        var div = Y.config.doc.createElement('div'),
+            ret = true;
+
+        div.innerHTML = html;
+        if (!div.firstChild || div.firstChild.tagName !== tag.toUpperCase()) {
+            ret = false;
+        }
+
+        return ret;
+    },
+
+    addFeature = Y.Features.add,
+    testFeature = Y.Features.test,
+    
+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) {
+        // handle dupe IDs and IE name collision
+        return Y_DOM.allById(id, doc)[0] || null;
+    },
+
+    /**
+     * 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: (documentElement.textContent !== undefined) ?
+        function(element) {
+            var ret = '';
+            if (element) {
+                ret = element.textContent;
+            }
+            return ret || '';
+        } : function(element) {
+            var ret = '';
+            if (element) {
+                ret = element.innerText || element.nodeValue; // might be a 
textNode
+            }
+            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: (documentElement.textContent !== undefined) ?
+        function(element, content) {
+            if (element) {
+                element.textContent = content;
+            }
+        } : function(element, content) {
+            if ('innerText' in element) {
+                element.innerText = content;
+            } else if ('nodeValue' in element) {
+                element.nodeValue = content;
+            }
+
+        },
+
+    /*
+     * Finds the ancestor of the element.
+     * @method ancestor
+     * @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} testSelf optional Whether or not to include the 
element in the scan 
+     * @return {HTMLElement | null} The matching DOM node or null if none 
found. 
+     */
+    ancestor: function(element, fn, testSelf) {
+        var ret = null;
+        if (testSelf) {
+            ret = (!fn || fn(element)) ? element : null;
+
+        }
+        return ret || Y_DOM.elementByAxis(element, PARENT_NODE, fn, null);
+    },
+
+    /*
+     * Finds the ancestors of the element.
+     * @method ancestors
+     * @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, all ancestors are returned.
+     * @param {Boolean} testSelf optional Whether or not to include the 
element in the scan 
+     * @return {Array} An array containing all matching DOM nodes.
+     */
+    ancestors: function(element, fn, testSelf) {
+        var ancestor = Y_DOM.ancestor.apply(Y_DOM, arguments),
+            ret = (ancestor) ? [ancestor] : [];
+
+        while ((ancestor = Y_DOM.ancestor(ancestor, fn))) {
+            if (ancestor) {
+                ret.unshift(ancestor);
+            }
+        }
+
+        return ret;
+    },
+
+    /**
+     * 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;
+    },
+
+    /**
+     * 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) {
+        var ret = false,
+            rootNode;
+
+        if (element && element.nodeType) {
+            (doc) || (doc = element[OWNER_DOCUMENT]);
+
+            rootNode = doc[DOCUMENT_ELEMENT];
+
+            // contains only works with HTML_ELEMENT
+            if (rootNode && rootNode.contains && element.tagName) {
+                ret = rootNode.contains(element);
+            } else {
+                ret = Y_DOM.contains(rootNode, element);
+            }
+        }
+
+        return ret;
+
+    },
+
+   allById: function(id, root) {
+        root = root || Y.config.doc;
+        var nodes = [],
+            ret = [],
+            i,
+            node;
+
+        if (root.querySelectorAll) {
+            ret = root.querySelectorAll('[id="' + id + '"]');
+        } else if (root.all) {
+            nodes = root.all(id);
+
+            if (nodes) {
+                // root.all may return HTMLElement or HTMLCollection.
+                // some elements are also HTMLCollection (FORM, SELECT).
+                if (nodes.nodeName) {
+                    if (nodes.id === id) { // avoid false positive on name
+                        ret.push(nodes);
+                        nodes = EMPTY_ARRAY; // done, no need to filter
+                    } else { //  prep for filtering
+                        nodes = [nodes];
+                    }
+                }
+
+                if (nodes.length) {
+                    // filter out matches on node.name
+                    // and element.id as reference to element with id === 'id'
+                    for (i = 0; node = nodes[i++];) {
+                        if (node.id === id  || 
+                                (node.attributes && node.attributes.id &&
+                                node.attributes.id.value === id)) { 
+                            ret.push(node);
+                        }
+                    }
+                }
+            }
+        } else {
+            ret = [Y_DOM._getDoc(root).getElementById(id)];
+        }
+    
+        return ret;
+   },
+
+    /**
+     * 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 
+     * @return {HTMLElement|DocumentFragment} returns a single HTMLElement 
+     * when creating one node, and a documentFragment when creating
+     * multiple nodes.
+     */
+    create: function(html, doc) {
+        if (typeof html === 'string') {
+            html = Y.Lang.trim(html); // match IE which trims whitespace from 
innerHTML
+
+        }
+
+        doc = doc || Y.config.doc;
+        var m = re_tag.exec(html),
+            create = Y_DOM._create,
+            custom = Y_DOM.creators,
+            ret = null,
+            creator,
+            tag, nodes;
+
+        if (html != undefined) { // not undefined or null
+            if (m && m[1]) {
+                creator = custom[m[1].toLowerCase()];
+                if (typeof creator === 'function') {
+                    create = creator; 
+                } else {
+                    tag = creator;
+                }
+            }
+
+            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 if (nodes[0] && nodes[0].className === 'yui3-big-dummy') { 
// using dummy node to preserve some attributes (e.g. OPTION not selected)
+                if (nodes.length === 2) {
+                    ret = nodes[0].nextSibling;
+                } else {
+                    nodes[0].parentNode.removeChild(nodes[0]); 
+                     ret = Y_DOM._nl2frag(nodes, doc);
+                }
+            } else { // return multiple nodes as a fragment
+                 ret = Y_DOM._nl2frag(nodes, doc);
+            }
+        }
+
+        return ret;
+    },
+
+    _nl2frag: function(nodes, doc) {
+        var ret = null,
+            i, len;
+
+        if (nodes && (nodes.push || nodes.item) && nodes[0]) {
+            doc = doc || nodes[0].ownerDocument; 
+            ret = doc.createDocumentFragment();
+
+            if (nodes.item) { // convert live list to static array
+                nodes = Y.Array(nodes, 0, true);
+            }
+
+            for (i = 0, len = nodes.length; i < len; i++) {
+                ret.appendChild(nodes[i]); 
+            }
+        } // else inline with log for minification
+        else { Y.log('unable to convert ' + nodes + ' to fragment', 'warn', 
'dom'); }
+        return ret;
+    },
+
+
+    CUSTOM_ATTRIBUTES: (!documentElement.hasAttribute) ? { // IE < 8
+        'for': 'htmlFor',
+        'class': 'className'
+    } : { // w3c
+        'htmlFor': 'for',
+        'className': 'class'
+    },
+
+    /**
+     * Provides a normalized attribute interface. 
+     * @method setAttibute
+     * @param {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, ieAttr) {
+        if (el && attr && el.setAttribute) {
+            attr = Y_DOM.CUSTOM_ATTRIBUTES[attr] || attr;
+            el.setAttribute(attr, val, ieAttr);
+        }
+        else { Y.log('bad input to setAttribute', 'warn', 'dom'); }
+    },
+
+
+    /**
+     * Provides a normalized attribute interface. 
+     * @method getAttibute
+     * @param {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, ieAttr) {
+        ieAttr = (ieAttr !== undefined) ? ieAttr : 2;
+        var ret = '';
+        if (el && attr && el.getAttribute) {
+            attr = Y_DOM.CUSTOM_ATTRIBUTES[attr] || attr;
+            ret = el.getAttribute(attr, ieAttr);
+
+            if (ret === null) {
+                ret = ''; // per DOM spec
+            }
+        }
+        else { Y.log('bad input to getAttribute', 'warn', 'dom'); }
+        return ret;
+    },
+
+    isWindow: function(obj) {
+        return !!(obj && obj.alert && obj.document);
+    },
+
+    _fragClones: {},
+
+    _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);
+        }
+    },
+
+    /**
+     * Inserts content in a node at the given location 
+     * @method addHTML
+     * @param {HTMLElement} node The node to insert into
+     * @param {HTMLElement | Array | HTMLCollection} content The content to be 
inserted 
+     * @param {HTMLElement} where Where to insert the content
+     * If no "where" is given, content is appended to the node
+     * Possible values for "where"
+     * <dl>
+     * <dt>HTMLElement</dt>
+     * <dd>The element to insert before</dd>
+     * <dt>"replace"</dt>
+     * <dd>Replaces the existing HTML</dd>
+     * <dt>"before"</dt>
+     * <dd>Inserts before the existing HTML</dd>
+     * <dt>"before"</dt>
+     * <dd>Inserts content before the node</dd>
+     * <dt>"after"</dt>
+     * <dd>Inserts content after the node</dd>
+     * </dl>
+     */
+    addHTML: function(node, content, where) {
+        var nodeParent = node.parentNode,
+            i = 0,
+            item,
+            ret = content,
+            newNode;
+            
+
+        if (content != undefined) { // not null or undefined (maybe 0)
+            if (content.nodeType) { // DOM node, just add it
+                newNode = content;
+            } else if (typeof content == 'string' || typeof content == 
'number') {
+                ret = newNode = Y_DOM.create(content);
+            } else if (content[0] && content[0].nodeType) { // array or 
collection 
+                newNode = Y.config.doc.createDocumentFragment();
+                while ((item = content[i++])) {
+                    newNode.appendChild(item); // append to fragment for 
insertion
+                }
+            }
+        }
+
+        if (where) {
+            if (where.nodeType) { // insert regardless of relationship to node
+                where.parentNode.insertBefore(newNode, where);
+            } else {
+                switch (where) {
+                    case 'replace':
+                        while (node.firstChild) {
+                            node.removeChild(node.firstChild);
+                        }
+                        if (newNode) { // allow empty content to clear node
+                            node.appendChild(newNode);
+                        }
+                        break;
+                    case 'before':
+                        nodeParent.insertBefore(newNode, node);
+                        break;
+                    case 'after':
+                        if (node.nextSibling) { // IE errors if refNode is null
+                            nodeParent.insertBefore(newNode, node.nextSibling);
+                        } else {
+                            nodeParent.appendChild(newNode);
+                        }
+                        break;
+                    default:
+                        node.appendChild(newNode);
+                }
+            }
+        } else if (newNode) {
+            node.appendChild(newNode);
+        }
+
+        return ret;
+    },
+
+    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;
+            }
+        }
+
+        // workaround for IE8 JSON stringify bug
+        // which converts empty string values to null
+        if (ret === EMPTY_STRING) {
+            ret = EMPTY_STRING; // for real
+        }
+
+        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;
+            }
+        }
+    },
+
+    siblings: function(node, fn) {
+        var nodes = [],
+            sibling = node;
+
+        while ((sibling = sibling[PREVIOUS_SIBLING])) {
+            if (sibling[TAG_NAME] && (!fn || fn(sibling))) {
+                nodes.unshift(sibling);
+            }
+        }
+
+        sibling = node;
+        while ((sibling = sibling[NEXT_SIBLING])) {
+            if (sibling[TAG_NAME] && (!fn || fn(sibling))) {
+                nodes.push(sibling);
+            }
+        }
+
+        return nodes;
+    },
+
+    /**
+     * 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) {
+        var doc = Y.config.doc;
+        if (element) {
+            doc = (element[NODE_TYPE] === 9) ? element : // element === 
document
+                element[OWNER_DOCUMENT] || // element === DOM node
+                element.document || // element === window
+                Y.config.doc; // default
+        }
+
+        return doc;
+    },
+
+    /**
+     * 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;
+    },
+
+    _batch: function(nodes, fn, arg1, arg2, arg3, etc) {
+        fn = (typeof fn === 'string') ? Y_DOM[fn] : fn;
+        var result,
+            args = Array.prototype.slice.call(arguments, 2),
+            i = 0,
+            node,
+            ret;
+
+        if (fn && nodes) {
+            while ((node = nodes[i++])) {
+                result = result = fn.call(Y_DOM, node, arg1, arg2, arg3, etc);
+                if (typeof result !== 'undefined') {
+                    (ret) || (ret = []);
+                    ret.push(result);
+                }
+            }
+        }
+
+        return (typeof ret !== 'undefined') ? ret : nodes;
+    },
+
+    wrap: function(node, html) {
+        var parent = Y.DOM.create(html),
+            nodes = parent.getElementsByTagName('*');
+
+        if (nodes.length) {
+            parent = nodes[nodes.length - 1];
+        }
+
+        if (node.parentNode) { 
+            node.parentNode.replaceChild(parent, node);
+        }
+        parent.appendChild(node);
+    },
+
+    unwrap: function(node) {
+        var parent = node.parentNode,
+            lastChild = parent.lastChild,
+            node = parent.firstChild,
+            next = node,
+            grandparent;
+
+        if (parent) {
+            grandparent = parent.parentNode;
+            if (grandparent) {
+                while (node !== lastChild) {
+                    next = node.nextSibling;
+                    grandparent.insertBefore(node, parent);
+                    node = next;
+                }
+                grandparent.replaceChild(lastChild, parent);
+            } else {
+                parent.removeChild(node);
+            }
+        }
+    },
+
+    generateID: function(el) {
+        var id = el.id;
+
+        if (!id) {
+            id = Y.stamp(el);
+            el.id = id; 
+        }   
+
+        return id; 
+    },
+
+    creators: {}
+};
+
+addFeature('innerhtml', 'table', {
+    test: function() {
+        var node = Y.config.doc.createElement('table');
+        try {
+            node.innerHTML = '<tbody></tbody>';
+        } catch(e) {
+            return false;
+        }
+        return (node.firstChild && node.firstChild.nodeName === 'TBODY');
+    }
+});
+
+addFeature('innerhtml-div', 'tr', {
+    test: function() {
+        return createFromDIV('<tr></tr>', 'tr');
+    }
+});
+
+addFeature('innerhtml-div', 'script', {
+    test: function() {
+        return createFromDIV('<script></script>', 'script');
+    }
+});
+
+addFeature('value-set', 'select', {
+    test: function() {
+        var node = Y.config.doc.createElement('select');
+        node.innerHTML = '<option>1</option><option>2</option>';
+        node.value = '2';
+        return (node.value && node.value === '2');
+    }
+});
+
+(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 (!testFeature('innerhtml', 'table')) {
+        // TODO: thead/tfoot with nested tbody
+            // IE adds TBODY when creating TABLE elements (which may share 
this impl)
+        creators.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;
+        };
+    }
+
+    if (!testFeature('innerhtml-div', 'script')) {
+        creators.script = function(html, doc) {
+            var frag = doc.createElement('div');
+
+            frag.innerHTML = '-' + html;
+            frag.removeChild(frag[FIRST_CHILD]);
+            return frag;
+        }
+
+        Y_DOM.creators.link = Y_DOM.creators.style = Y_DOM.creators.script;
+    }
+
+    
+    if (!testFeature('value-set', 'select')) {
+        Y_DOM.VALUE_SETTERS.select = function(node, val) {
+            for (var i = 0, options = node.getElementsByTagName('option'), 
option;
+                    option = options[i++];) {
+                if (Y_DOM.getValue(option) === val) {
+                    option.selected = true;
+                    //Y_DOM.setAttribute(option, 'selected', 'selected');
+                    break;
+                }
+            }
+        }
+    }
+
+    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 (!testFeature('innerhtml-div', 'tr')) {
+        Y.mix(creators, {
+            option: function(html, doc) {
+                return create('<select><option class="yui3-big-dummy" 
selected></option>' + html + '</select>', doc);
+            },
+
+            tr: function(html, doc) {
+                return create('<tbody>' + html + '</tbody>', doc);
+            },
+
+            td: function(html, doc) {
+                return create('<tr>' + html + '</tr>', doc);
+            }, 
+
+            col: function(html, doc) {
+                return create('<colgroup>' + html + '</colgroup>', doc);
+            }, 
+
+            tbody: 'table'
+        });
+
+        Y.mix(creators, {
+            legend: 'fieldset',
+            th: creators.td,
+            thead: creators.tbody,
+            tfoot: creators.tbody,
+            caption: creators.tbody,
+            colgroup: 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 && options.length) {
+                // TODO: implement multipe select
+                if (node.multiple) {
+                    Y.log('multiple select normalization not implemented', 
'warn', 'DOM');
+                } else {
+                    val = Y_DOM.getValue(options[node.selectedIndex]);
+                }
+            }
+
+            return val;
+        }
+    });
+})(Y);
+
+Y.DOM = Y_DOM;
+})(Y);
+var addClass, hasClass, removeClass;
+
+Y.mix(Y.DOM, {
+    /**
+     * Determines whether a DOM element has the given className.
+     * @method hasClass
+     * @for DOM
+     * @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         
+     * @for DOM
+     * @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         
+     * @for DOM
+     * @param {HTMLElement} element The DOM element. 
+     * @param {String} className the class name to remove from the class 
attribute
+     */
+    removeClass: function(node, className) {
+        if (className && hasClass(node, className)) {
+            node.className = 
Y.Lang.trim(node.className.replace(Y.DOM._getRegExp('(?:^|\\s+)' +
+                            className + '(?:\\s+|$)'), ' '));
+
+            if ( hasClass(node, className) ) { // in case of multiple adjacent
+                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  
+     * @for DOM
+     * @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');
+        removeClass(node, oldC); // remove first in case oldC === newC
+        addClass(node, newC);
+    },
+
+    /**
+     * If the className exists on the node it is removed, if it doesn't exist 
it is added.
+     * @method toggleClass  
+     * @for DOM
+     * @param {HTMLElement} element The DOM element
+     * @param {String} className the class name to be toggled
+     * @param {Boolean} addClass optional boolean to indicate whether class
+     * should be added or removed regardless of current state
+     */
+    toggleClass: function(node, className, force) {
+        var add = (force !== undefined) ? force :
+                !(hasClass(node, className));
+
+        if (add) {
+            addClass(node, className);
+        } else {
+            removeClass(node, className);
+        }
+    }
+});
+
+hasClass = Y.DOM.hasClass;
+removeClass = Y.DOM.removeClass;
+addClass = Y.DOM.addClass;
+
+Y.mix(Y.DOM, {
+    /**
+     * Sets the width of the element to the given size, regardless
+     * of box model, border, padding, etc.
+     * @method setWidth
+     * @param {HTMLElement} element The DOM element. 
+     * @param {String|Int} size The pixel height to size to
+     */
+
+    setWidth: function(node, size) {
+        Y.DOM._setSize(node, 'width', size);
+    },
+
+    /**
+     * Sets the height of the element to the given size, regardless
+     * of box model, border, padding, etc.
+     * @method setHeight
+     * @param {HTMLElement} element The DOM element. 
+     * @param {String|Int} size The pixel height to size to
+     */
+
+    setHeight: function(node, size) {
+        Y.DOM._setSize(node, 'height', size);
+    },
+
+    _setSize: function(node, prop, val) {
+        val = (val > 0) ? val : 0;
+        var size = 0;
+
+        node.style[prop] = val + 'px';
+        size = (prop === 'height') ? node.offsetHeight : node.offsetWidth;
+
+        if (size > val) {
+            val = val - (size - val);
+
+            if (val < 0) {
+                val = 0;
+            }
+
+            node.style[prop] = val + 'px';
+        }
+    }
+});
+
+
+}, '3.3.0' ,{requires:['oop']});
+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',
+    GET_BOUNDING_CLIENT_RECT = 'getBoundingClientRect',
+
+    WINDOW = Y.config.win,
+    DOCUMENT = Y.config.doc,
+    UNDEFINED = undefined,
+
+    Y_DOM = Y.DOM,
+
+    TRANSFORM = 'transform',
+    VENDOR_TRANSFORM = [
+        'WebkitTransform',
+        'MozTransform',
+        'OTransform'
+    ],
+
+    re_color = /color$/i,
+    re_unit = /width|height|top|left|right|bottom|margin|padding/i;
+
+Y.Array.each(VENDOR_TRANSFORM, function(val) {
+    if (val in DOCUMENT[DOCUMENT_ELEMENT].style) {
+        TRANSFORM = val;
+    }
+});
+
+Y.mix(Y_DOM, {
+    DEFAULT_UNIT: 'px',
+
+    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 unsetting
+                val = '';
+            } else if (!isNaN(new Number(val)) && re_unit.test(att)) { // 
number values may need a unit
+                val += Y_DOM.DEFAULT_UNIT;
+            }
+
+            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];
+                }
+            } else if (att === '') { // unset inline styles
+                att = 'cssText';
+                val = '';
+            }
+            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, style) {
+        style = style || node.style;
+        var 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] && doc[DEFAULT_VIEW] && 
doc[DEFAULT_VIEW][GET_COMPUTED_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.DOM._getAttrOffset = function(node, attr) {
+    var val = Y.DOM[GET_COMPUTED_STYLE](node, attr),
+        offsetParent = node.offsetParent,
+        position,
+        parentOffset,
+        offset;
+
+    if (val === 'auto') {
+        position = Y.DOM.getStyle(node, 'position');
+        if (position === 'static' || position === 'relative') {
+            val = 0;    
+        } else if (offsetParent && offsetParent[GET_BOUNDING_CLIENT_RECT]) {
+            parentOffset = offsetParent[GET_BOUNDING_CLIENT_RECT]()[attr];
+            offset = node[GET_BOUNDING_CLIENT_RECT]()[attr];
+            if (attr === 'left' || attr === 'top') {
+                val = offset - parentOffset;
+            } else {
+                val = parentOffset - node[GET_BOUNDING_CLIENT_RECT]()[attr];
+            }
+        }
+    }
+
+    return val;
+};
+
+Y.DOM._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;
+
+};
+
+Y_DOM.CUSTOM_STYLES.transform = {
+    set: function(node, val, style) {
+        style[TRANSFORM] = val;
+    },
+
+    get: function(node, style) {
+        return Y_DOM[GET_COMPUTED_STYLE](node, TRANSFORM);
+    }
+};
+
+
+})(Y);
+(function(Y) {
+var 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)) {
+            val = [
+                Number(RE.$1).toString(16),
+                Number(RE.$2).toString(16),
+                Number(RE.$3).toString(16)
+            ];
+
+            for (var i = 0; i < val.length; i++) {
+                if (val[i].length < 2) {
+                    val[i] = '0' + val[i];
+                }
+            }
+
+            val = val.join('');
+        }
+
+        if (val.length < 6) {
+            val = val.replace(Y.Color.re_hex3, '$1$1');
+        }
+
+        if (val !== 'transparent' && val.indexOf('#') < 0) {
+            val = '#' + val;
+        }
+
+        return val.toUpperCase();
+    }
+};
+})(Y);
+
+
+
+}, '3.3.0' ,{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',
+
+    Y_DOM = Y.DOM,
+
+    // TODO: how about thead/tbody/tfoot/tr?
+    // TODO: does caption matter?
+    RE_TABLE = /^t(?:able|d|h)$/i,
+
+    SCROLL_NODE;
+
+if (Y.UA.ie) {
+    if (Y.config.doc[COMPAT_MODE] !== 'quirks') {
+        SCROLL_NODE = DOCUMENT_ELEMENT; 
+    } else {
+        SCROLL_NODE = 'body';
+    }
+}
+
+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, doc) {
+        doc = doc || (node) ? Y_DOM._getDoc(node) : Y.config.doc; // perf 
optimization
+        var dv = doc.defaultView,
+            pageOffset = (dv) ? dv.pageXOffset : 0;
+        return Math.max(doc[DOCUMENT_ELEMENT].scrollLeft, doc.body.scrollLeft, 
pageOffset);
+    },
+
+    /**
+     * Amount page has been scroll vertically 
+     * @method docScrollY
+     * @return {Number} The current amount the screen is scrolled vertically.
+     */
+    docScrollY:  function(node, doc) {
+        doc = doc || (node) ? Y_DOM._getDoc(node) : Y.config.doc; // perf 
optimization
+        var dv = doc.defaultView,
+            pageOffset = (dv) ? dv.pageYOffset : 0;
+        return Math.max(doc[DOCUMENT_ELEMENT].scrollTop, doc.body.scrollTop, 
pageOffset);
+    },
+
+    /**
+     * 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 (Y.config.doc[DOCUMENT_ELEMENT][GET_BOUNDING_CLIENT_RECT]) {
+            return function(node) {
+                var xy = null,
+                    scrollLeft,
+                    scrollTop,
+                    box,
+                    off1, off2,
+                    bLeft, bTop,
+                    mode,
+                    doc,
+                    inDoc,
+                    rootNode;
+
+                if (node && node.tagName) {
+                    doc = node.ownerDocument;
+                    rootNode = doc[DOCUMENT_ELEMENT];
+
+                    // inline inDoc check for perf
+                    if (rootNode.contains) {
+                        inDoc = rootNode.contains(node); 
+                    } else {
+                        inDoc = Y.DOM.contains(rootNode, node);
+                    }
+
+                    if (inDoc) {
+                        scrollLeft = (SCROLL_NODE) ? 
doc[SCROLL_NODE].scrollLeft : Y_DOM.docScrollX(node, doc);
+                        scrollTop = (SCROLL_NODE) ? doc[SCROLL_NODE].scrollTop 
: Y_DOM.docScrollY(node, doc);
+                        box = node[GET_BOUNDING_CLIENT_RECT]();
+                        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)) {
+                            if (!Y.UA.ios || (Y.UA.ios >= 4.2)) {
+                                xy[0] += scrollLeft;
+                                xy[1] += scrollTop;
+                            }
+                            
+                        }
+                    } else {
+                        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,
+                    doc,
+                    parentNode,
+                    bCheck,
+                    scrollTop,
+                    scrollLeft;
+
+                if (node) {
+                    if (Y_DOM.inDoc(node)) {
+                        xy = [node.offsetLeft, node.offsetTop];
+                        doc = node.ownerDocument;
+                        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, doc);
+                            xy[1] += Y_DOM.docScrollY(node, doc);
+
+                        } else {
+                            //Fix FIXED position -- add scrollbars
+                            xy[0] += Y_DOM.docScrollX(node, doc);
+                            xy[1] += Y_DOM.docScrollY(node, doc);
+                        }
+                    } else {
+                        xy = Y_DOM._getOffset(node);
+                    }
+                }
+
+                return xy;                
+            };
+        }
+    }(),// NOTE: Executing for loadtime branching
+
+    /**
+     * 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]);
+    },
+
+    /**
+     * @method swapXY
+     * @description Swap the xy position with another node
+     * @param {Node} node The node to swap with
+     * @param {Node} otherNode The other node to swap with
+     * @return {Node}
+     */
+    swapXY: function(node, otherNode) {
+        var xy = Y_DOM.getXY(node);
+        Y_DOM.setXY(node, Y_DOM.getXY(otherNode));
+        Y_DOM.setXY(otherNode, xy);
+    },
+
+    _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, doc) {
+        doc  = doc || (node) ? Y_DOM._getDoc(node) : Y.config.doc;
+        var 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 = (node) ? Y_DOM._getDoc(node) : Y.config.doc,
+            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)
+     * @for DOM
+     * @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
+     * @for DOM
+     * @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
+     * @for DOM
+     * @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
+     * @for DOM
+     * @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
+     * @for DOM
+     * @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.3.0' ,{requires:['dom-base', 'dom-style', 'event-base']});
+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 COMPARE_DOCUMENT_POSITION = 'compareDocumentPosition',
+    OWNER_DOCUMENT = 'ownerDocument';
+
+var Selector = {
+    _foundCache: [],
+
+    useNative: true,
+
+    _compare: ('sourceIndex' in Y.config.doc.documentElement) ?
+        function(nodeA, nodeB) {
+            var a = nodeA.sourceIndex,
+                b = nodeB.sourceIndex;
+
+            if (a === b) {
+                return 0;
+            } else if (a > b) {
+                return 1;
+            }
+
+            return -1;
+
+        } : (Y.config.doc.documentElement[COMPARE_DOCUMENT_POSITION] ?
+        function(nodeA, nodeB) {
+            if (nodeA[COMPARE_DOCUMENT_POSITION](nodeB) & 4) {
+                return -1;
+            } else {
+                return 1;
+            }
+        } :
+        function(nodeA, nodeB) {
+            var rangeA, rangeB, compare;
+            if (nodeA && nodeB) {
+                rangeA = nodeA[OWNER_DOCUMENT].createRange();
+                rangeA.setStart(nodeA, 0);
+                rangeB = nodeB[OWNER_DOCUMENT].createRange();
+                rangeB.setStart(nodeB, 0);
+                compare = rangeA.compareBoundaryPoints(1, rangeB); // 1 === 
Range.START_TO_END
+            }
+
+            return compare;
+        
+    }),
+
+    _sort: function(nodes) {
+        if (nodes) {
+            nodes = Y.Array(nodes, 0, true);
+            if (nodes.sort) {
+                nodes.sort(Selector._compare);
+            }
+        }
+
+        return nodes;
+    },
+
+    _deDupe: function(nodes) {
+        var ret = [],
+            i, node;
+
+        for (i = 0; (node = nodes[i++]);) {
+            if (!node._found) {
+                ret[ret.length] = node;
+                node._found = true;
+            }
+        }
+
+        for (i = 0; (node = ret[i++]);) {
+            node._found = null;
+            node.removeAttribute('_found');
+        }
+
+        return ret;
+    },
+
+    /**
+     * 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, skipNative) {
+        root = root || Y.config.doc;
+        var ret = [],
+            useNative = (Y.Selector.useNative && Y.config.doc.querySelector && 
!skipNative),
+            queries = [[selector, root]],
+            query,
+            result,
+            i,
+            fn = (useNative) ? Y.Selector._nativeQuery : 
Y.Selector._bruteQuery;
+
+        if (selector && fn) {
+            // split group into seperate queries
+            if (!skipNative && // already done if skipping
+                    (!useNative || root.tagName)) { // split native when 
element scoping is needed
+                queries = Selector._splitQueries(selector, root);
+            }
+
+            for (i = 0; (query = queries[i++]);) {
+                result = fn(query[0], query[1], firstOnly);
+                if (!firstOnly) { // coerce DOM Collection to Array
+                    result = Y.Array(result, 0, true);
+                }
+                if (result) {
+                    ret = ret.concat(result);
+                }
+            }
+
+            if (queries.length > 1) { // remove dupes and sort by doc order 
+                ret = Selector._sort(Selector._deDupe(ret));
+            }
+        }
+
+        Y.log('query: ' + selector + ' returning: ' + ret.length, 'info', 
'Selector');
+        return (firstOnly) ? (ret[0] || null) : ret;
+
+    },
+
+    // allows element scoped queries to begin with combinator
+    // e.g. query('> p', document.body) === query('body > p')
+    _splitQueries: function(selector, node) {
+        var groups = selector.split(','),
+            queries = [],
+            prefix = '',
+            i, len;
+
+        if (node) {
+            // enforce for element scoping
+            if (node.tagName) {
+                node.id = node.id || Y.guid();
+                prefix = '[id="' + node.id + '"] ';
+            }
+
+            for (i = 0, len = groups.length; i < len; ++i) {
+                selector =  prefix + groups[i];
+                queries.push([selector, node]);
+            }
+        }
+
+        return queries;
+    },
+
+    _nativeQuery: function(selector, root, one) {
+        if (Y.UA.webkit && selector.indexOf(':checked') > -1 &&
+                (Y.Selector.pseudos && Y.Selector.pseudos.checked)) { // 
webkit (chrome, safari) fails to find "selected"
+            return Y.Selector.query(selector, root, one, true); // redo with 
skipNative true to try brute query
+        }
+        try {
+            //Y.log('trying native query with: ' + selector, 'info', 
'selector-native');
+            return root['querySelector' + (one ? '' : 'All')](selector);
+        } catch(e) { // fallback to brute if available
+            //Y.log('native query error; reverting to brute query with: ' + 
selector, 'info', 'selector-native');
+            return Y.Selector.query(selector, root, one, true); // redo with 
skipNative true
+        }
+    },
+
+    filter: function(nodes, selector) {
+        var ret = [],
+            i, node;
+
+        if (nodes && selector) {
+            for (i = 0; (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, root) {
+        var ret = false,
+            groups = selector.split(','),
+            useFrag = false,
+            parent,
+            item,
+            items,
+            frag,
+            i, j, group;
+
+        if (node && node.tagName) { // only test HTMLElements
+
+            // we need a root if off-doc
+            if (!root && !Y.DOM.inDoc(node)) {
+                parent = node.parentNode;
+                if (parent) { 
+                    root = parent;
+                } else { // only use frag when no parent to query
+                    frag = node[OWNER_DOCUMENT].createDocumentFragment();
+                    frag.appendChild(node);
+                    root = frag;
+                    useFrag = true;
+                }
+            }
+            root = root || node[OWNER_DOCUMENT];
+
+            if (!node.id) {
+                node.id = Y.guid();
+            }
+            for (i = 0; (group = groups[i++]);) { // TODO: off-dom test
+                group += '[id="' + node.id + '"]';
+                items = Y.Selector.query(group, root);
+
+                for (j = 0; item = items[j++];) {
+                    if (item === node) {
+                        ret = true;
+                        break;
+                    }
+                }
+                if (ret) {
+                    break;
+                }
+            }
+
+            if (useFrag) { // cleanup
+                frag.removeChild(node);
+            }
+        }
+
+        return ret;
+    },
+
+    /**
+     * A convenience function to emulate Y.Node's aNode.ancestor(selector).
+     * @param {HTMLElement} element An HTMLElement to start the query from.
+     * @param {String} selector The CSS selector to test the node against.
+     * @return {HTMLElement} The ancestor node matching the selector, or null.
+     * @param {Boolean} testSelf optional Whether or not to include the 
element in the scan 
+     * @static
+     * @method ancestor
+     */
+    ancestor: function (element, selector, testSelf) {
+        return Y.DOM.ancestor(element, function(n) {
+            return Y.Selector.test(n, selector);
+        }, testSelf);
+    }
+};
+
+Y.mix(Y.Selector, Selector, true);
+
+})(Y);
+
+
+}, '3.3.0' ,{requires:['dom-base']});
+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',
+
+    Selector = Y.Selector,
+
+    SelectorCSS2 = {
+        _reRegExpTokens: /([\^\$\?\[\]\*\+\-\.\(\)\|\\])/, // TODO: move?
+        SORT_RESULTS: true,
+        _children: function(node, tag) {
+            var ret = node.children,
+                i,
+                children = [],
+                childNodes,
+                child;
+
+            if (node.children && tag && node.children.tags) {
+                children = node.children.tags(tag);
+            } else if ((!ret && node[TAG_NAME]) || (ret && tag)) { // only 
HTMLElements have children
+                childNodes = ret || node.childNodes;
+                ret = [];
+                for (i = 0; (child = childNodes[i++]);) {
+                    if (child.tagName) {
+                        if (!tag || tag === child.tagName) {
+                            ret.push(child);
+                        }
+                    }
+                }
+            }
+
+            return ret || [];
+        },
+
+        _re: {
+            //attr: /(\[.*\])/g,
+            attr: /(\[[^\]]*\])/g,
+            pseudos: /:([\-\w]+(?:\(?:['"]?(.+)['"]?\)))*/i
+        },
+
+        /**
+         * 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, attr) { return Y.DOM.getAttribute(node, attr) 
!== ''; }, // 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; 
+            } 
+        },
+
+        _bruteQuery: function(selector, root, firstOnly) {
+            var ret = [],
+                nodes = [],
+                tokens = Selector._tokenize(selector),
+                token = tokens[tokens.length - 1],
+                rootDoc = Y.DOM._getDoc(root),
+                child,
+                id,
+                className,
+                tagName;
+
+
+            // if we have an initial ID, set to root when in document
+            /*
+            if (tokens[0] && rootDoc === root &&  
+                    (id = tokens[0].id) &&
+                    rootDoc.getElementById(id)) {
+                root = rootDoc.getElementById(id);
+            }
+            */
+
+            if (token) {
+                // prefilter nodes
+                id = token.id;
+                className = token.className;
+                tagName = token.tagName || '*';
+
+                if (root.getElementsByTagName) { // non-IE lacks DOM api on 
doc frags
+                    // try ID first, unless no root.all && root not in document
+                    // (root.all works off document, but not getElementById)
+                    // TODO: move to allById?
+                    if (id && (root.all || (root.nodeType === 9 || 
Y.DOM.inDoc(root)))) {
+                        nodes = Y.DOM.allById(id, root);
+                    // try className
+                    } else if (className) {
+                        nodes = root.getElementsByClassName(className);
+                    } else { // default to tagName
+                        nodes = root.getElementsByTagName(tagName);
+                    }
+
+                } else { // brute getElementsByTagName('*')
+                    child = root.firstChild;
+                    while (child) {
+                        if (child.tagName) { // only collect HTMLElements
+                            nodes.push(child);
+                        }
+                        child = child.nextSilbing || child.firstChild;
+                    }
+                }
+                if (nodes.length) {
+                    ret = Selector._filterNodes(nodes, tokens, firstOnly);
+                }
+            }
+
+            return ret;
+        },
+        
+        _filterNodes: function(nodes, tokens, firstOnly) {
+            var i = 0,
+                j,
+                len = tokens.length,
+                n = len - 1,
+                result = [],
+                node = nodes[0],
+                tmpNode = node,
+                getters = Y.Selector.getters,
+                operator,
+                combinator,
+                token,
+                path,
+                pass,
+                //FUNCTION = 'function',
+                value,
+                tests,
+                test;
+
+            //do {
+            for (i = 0; (tmpNode = node = nodes[i++]);) {
+                n = len - 1;
+                path = null;
+                
+                testLoop:
+                while (tmpNode && tmpNode.tagName) {
+                    token = tokens[n];
+                    tests = token.tests;
+                    j = tests.length;
+                    if (j && !pass) {
+                        while ((test = tests[--j])) {
+                            operator = test[1];
+                            if (getters[test[0]]) {
+                                value = getters[test[0]](tmpNode, test[0]);
+                            } else {
+                                value = tmpNode[test[0]];
+                                // use getAttribute for non-standard attributes
+                                if (value === undefined && 
tmpNode.getAttribute) {
+                                    value = tmpNode.getAttribute(test[0]);
+                                }
+                            }
+
+                            if ((operator === '=' && value !== test[2]) ||  // 
fast path for equality
+                                (typeof operator !== 'string' && // protect 
against String.test monkey-patch (Moo)
+                                operator.test && !operator.test(value)) ||  // 
regex test
+                                (!operator.test && // protect against RegExp 
as function (webkit)
+                                        typeof operator === 'function' && 
!operator(tmpNode, test[0]))) { // function test
+
+                                // skip non element nodes or non-matching tags
+                                if ((tmpNode = tmpNode[path])) {
+                                    while (tmpNode &&
+                                        (!tmpNode.tagName ||
+                                            (token.tagName && token.tagName 
!== tmpNode.tagName))
+                                    ) {
+                                        tmpNode = tmpNode[path]; 
+                                    }
+                                }
+                                continue testLoop;
+                            }
+                        }
+                    }
+
+                    n--; // move to next token
+                    // now that we've passed the test, move up the tree by 
combinator
+                    if (!pass && (combinator = token.combinator)) {
+                        path = combinator.axis;
+                        tmpNode = tmpNode[path];
+
+                        // skip non element nodes
+                        while (tmpNode && !tmpNode.tagName) {
+                            tmpNode = tmpNode[path]; 
+                        }
+
+                        if (combinator.direct) { // one pass only
+                            path = null; 
+                        }
+
+                    } else { // success if we made it this far
+                        result.push(node);
+                        if (firstOnly) {
+                            return result;
+                        }
+                        break;
+                    }
+                }
+            }// while (tmpNode = node = nodes[++i]);
+            node = tmpNode = null;
+            return result;
+        },
+
+        combinators: {
+            ' ': {
+                axis: 'parentNode'
+            },
+
+            '>': {
+                axis: 'parentNode',
+                direct: true
+            },
+
+
+            '+': {
+                axis: 'previousSibling',
+                direct: true
+            }
+        },
+
+        _parsers: [
+            {
+                name: ATTRIBUTES,
+                re: 
/^\[(-?[a-z]+[\w\-]*)+([~\|\^\$\*!=]=?)?['"]?([^\]]*?)['"]?\]/i,
+                fn: function(match, token) {
+                    var operator = match[2] || '',
+                        operators = Y.Selector.operators,
+                        test;
+
+                    // add prefiltering for ID and CLASS
+                    if ((match[1] === 'id' && operator === '=') ||
+                            (match[1] === 'className' &&
+                            
Y.config.doc.documentElement.getElementsByClassName &&
+                            (operator === '~=' || operator === '='))) {
+                        token.prefilter = match[1];
+                        token[match[1]] = match[3];
+                    }
+
+                    // add tests
+                    if (operator in operators) {
+                        test = operators[operator];
+                        if (typeof test === 'string') {
+                            match[3] = 
match[3].replace(Y.Selector._reRegExpTokens, '\\$1');
+                            test = Y.DOM._getRegExp(test.replace('{val}', 
match[3]));
+                        }
+                        match[2] = test;
+                    }
+                    if (!token.last || token.prefilter !== match[1]) {
+                        return match.slice(1);
+                    }
+                }
+
+            },
+            {
+                name: TAG_NAME,
+                re: /^((?:-?[_a-z]+[\w-]*)|\*)/i,
+                fn: function(match, token) {
+                    var tag = match[1].toUpperCase();
+                    token.tagName = tag;
+
+                    if (tag !== '*' && (!token.last || token.prefilter)) {
+                        return [TAG_NAME, '=', tag];
+                    }
+                    if (!token.prefilter) {
+                        token.prefilter = 'tagName';
+                    }
+                }
+            },
+            {
+                name: COMBINATOR,
+                re: /^\s*([>+~]|\s)\s*/,
+                fn: function(match, token) {
+                }
+            },
+            {
+                name: PSEUDOS,
+                re: /^:([\-\w]+)(?:\(['"]?(.+)['"]?\))*/i,
+                fn: function(match, token) {
+                    var test = Selector[PSEUDOS][match[1]];
+                    if (test) { // reorder match array
+                        return [match[2], test];
+                    } else { // selector token not supported (possibly missing 
CSS3 module)
+                        return false;
+                    }
+                }
+            }
+            ],
+
+        _getToken: function(token) {
+            return {
+                tagName: null,
+                id: null,
+                className: null,
+                attributes: {},
+                combinator: null,
+                tests: []
+            };
+        },
+
+        /**
+            Break selector into token units per simple selector.
+            Combinator is attached to the previous token.
+         */

@@ Diff output truncated at 153600 characters. @@



reply via email to

[Prev in Thread] Current Thread [Next in Thread]