]> ToastFreeware Gitweb - philipp/winterrodeln/wradmin.git/blobdiff - wradmin/static/yui/selector/selector.js
Rename public directory to static.
[philipp/winterrodeln/wradmin.git] / wradmin / static / yui / selector / selector.js
diff --git a/wradmin/static/yui/selector/selector.js b/wradmin/static/yui/selector/selector.js
new file mode 100644 (file)
index 0000000..a1d6ecb
--- /dev/null
@@ -0,0 +1,648 @@
+/*
+Copyright (c) 2009, Yahoo! Inc. All rights reserved.
+Code licensed under the BSD License:
+http://developer.yahoo.net/yui/license.txt
+version: 2.7.0
+*/
+/**
+ * The selector module provides helper methods allowing CSS3 Selectors to be used with DOM elements.
+ * @module selector
+ * @title Selector Utility
+ * @namespace YAHOO.util
+ * @requires yahoo, dom
+ */
+
+(function() {
+var Y = YAHOO.util;
+
+/**
+ * Provides helper methods for collecting and filtering DOM elements.
+ * @namespace YAHOO.util
+ * @class Selector
+ * @static
+ */
+
+Y.Selector = {
+    _foundCache: [],
+    _regexCache: {},
+
+    _re: {
+        nth: /^(?:([-]?\d*)(n){1}|(odd|even)$)*([-+]?\d*)$/,
+        attr: /(\[.*\])/g,
+        urls: /^(?:href|src)/
+    },
+
+    /**
+     * Default document for use queries 
+     * @property document
+     * @type object
+     * @default window.document
+     */
+    document: window.document,
+    /**
+     * Mapping of attributes to aliases, normally to work around HTMLAttributes
+     * that conflict with JS reserved words.
+     * @property attrAliases
+     * @type object
+     */
+    attrAliases: {
+    },
+
+    /**
+     * Mapping of shorthand tokens to corresponding attribute selector 
+     * @property shorthand
+     * @type object
+     */
+    shorthand: {
+        //'(?:(?:[^\\)\\]\\s*>+~,]+)(?:-?[_a-z]+[-\\w]))+#(-?[_a-z]+[-\\w]*)': '[id=$1]',
+        '\\#(-?[_a-z]+[-\\w]*)': '[id=$1]',
+        '\\.(-?[_a-z]+[-\\w]*)': '[class~=$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(attr, val) { return attr === val; }, // Equality
+        '!=': function(attr, val) { return attr !== val; }, // Inequality
+        '~=': function(attr, val) { // Match one of space seperated words 
+            var s = ' ';
+            return (s + attr + s).indexOf((s + val + s)) > -1;
+        },
+        '|=': function(attr, val) { return attr === val || attr.slice(0, val.length + 1) === val + '-'; }, // Matches value followed by optional hyphen
+        '^=': function(attr, val) { return attr.indexOf(val) === 0; }, // Match starts with value
+        '$=': function(attr, val) { return attr.slice(-val.length) === val; }, // Match ends with value
+        '*=': function(attr, val) { return attr.indexOf(val) > -1; }, // Match contains value as substring 
+        '': function(attr, val) { return attr; } // Just test for existence of attribute
+    },
+
+    /**
+     * List of pseudo-classes and corresponding boolean functions. 
+     * These functions are called with the current node, and any value that was parsed with the pseudo regex.
+     * @property pseudos
+     * @type object
+     */
+    pseudos: {
+        'root': function(node) {
+            return node === node.ownerDocument.documentElement;
+        },
+
+        'nth-child': function(node, val) {
+            return Y.Selector._getNth(node, val);
+        },
+
+        'nth-last-child': function(node, val) {
+            return Y.Selector._getNth(node, val, null, true);
+        },
+
+        'nth-of-type': function(node, val) {
+            return Y.Selector._getNth(node, val, node.tagName);
+        },
+         
+        'nth-last-of-type': function(node, val) {
+            return Y.Selector._getNth(node, val, node.tagName, true);
+        },
+         
+        'first-child': function(node) {
+            return Y.Selector._getChildren(node.parentNode)[0] === node;
+        },
+
+        'last-child': function(node) {
+            var children = Y.Selector._getChildren(node.parentNode);
+            return children[children.length - 1] === node;
+        },
+
+        'first-of-type': function(node, val) {
+            return Y.Selector._getChildren(node.parentNode, node.tagName)[0];
+        },
+         
+        'last-of-type': function(node, val) {
+            var children = Y.Selector._getChildren(node.parentNode, node.tagName);
+            return children[children.length - 1];
+        },
+         
+        'only-child': function(node) {
+            var children = Y.Selector._getChildren(node.parentNode);
+            return children.length === 1 && children[0] === node;
+        },
+
+        'only-of-type': function(node) {
+            return Y.Selector._getChildren(node.parentNode, node.tagName).length === 1;
+        },
+
+        'empty': function(node) {
+            return node.childNodes.length === 0;
+        },
+
+        'not': function(node, simple) {
+            return !Y.Selector.test(node, simple);
+        },
+
+        'contains': function(node, str) {
+            var text = node.innerText || node.textContent || '';
+            return text.indexOf(str) > -1;
+        },
+        'checked': function(node) {
+            return node.checked === true;
+        }
+    },
+
+    /**
+     * Test if the supplied node matches the supplied selector.
+     * @method test
+     *
+     * @param {HTMLElement | String} node An id or node reference to the HTMLElement being tested.
+     * @param {string} selector The CSS Selector to test the node against.
+     * @return{boolean} Whether or not the node matches the selector.
+     * @static
+    
+     */
+    test: function(node, selector) {
+        node = Y.Selector.document.getElementById(node) || node;
+
+        if (!node) {
+            return false;
+        }
+
+        var groups = selector ? selector.split(',') : [];
+        if (groups.length) {
+            for (var i = 0, len = groups.length; i < len; ++i) {
+                if ( Y.Selector._test(node, groups[i]) ) { // passes if ANY group matches
+                    return true;
+                }
+            }
+            return false;
+        }
+        return Y.Selector._test(node, selector);
+    },
+
+    _test: function(node, selector, token, deDupe) {
+        token = token || Y.Selector._tokenize(selector).pop() || {};
+
+        if (!node.tagName ||
+            (token.tag !== '*' && node.tagName !== token.tag) ||
+            (deDupe && node._found) ) {
+            return false;
+        }
+
+        if (token.attributes.length) {
+            var val,
+                ieFlag,
+                re_urls = Y.Selector._re.urls;
+
+            if (!node.attributes || !node.attributes.length) {
+                return false;
+            }
+            for (var i = 0, attr; attr = token.attributes[i++];) {
+                ieFlag = (re_urls.test(attr[0])) ? 2 : 0;
+                val = node.getAttribute(attr[0], ieFlag);
+                if (val === null || val === undefined) {
+                    return false;
+                }
+                if ( Y.Selector.operators[attr[1]] &&
+                        !Y.Selector.operators[attr[1]](val, attr[2])) {
+                    return false;
+                }
+            }
+        }
+
+        if (token.pseudos.length) {
+            for (var i = 0, len = token.pseudos.length; i < len; ++i) {
+                if (Y.Selector.pseudos[token.pseudos[i][0]] &&
+                        !Y.Selector.pseudos[token.pseudos[i][0]](node, token.pseudos[i][1])) {
+                    return false;
+                }
+            }
+        }
+
+        return (token.previous && token.previous.combinator !== ',') ?
+                Y.Selector._combinators[token.previous.combinator](node, token) :
+                true;
+    },
+
+    /**
+     * Filters a set of nodes based on a given CSS selector. 
+     * @method filter
+     *
+     * @param {array} nodes A set of nodes/ids to filter. 
+     * @param {string} selector The selector used to test each node.
+     * @return{array} An array of nodes from the supplied array that match the given selector.
+     * @static
+     */
+    filter: function(nodes, selector) {
+        nodes = nodes || [];
+
+        var node,
+            result = [],
+            tokens = Y.Selector._tokenize(selector);
+
+        if (!nodes.item) { // if not HTMLCollection, handle arrays of ids and/or nodes
+            for (var i = 0, len = nodes.length; i < len; ++i) {
+                if (!nodes[i].tagName) { // tagName limits to HTMLElements 
+                    node = Y.Selector.document.getElementById(nodes[i]);
+                    if (node) { // skip IDs that return null 
+                        nodes[i] = node;
+                    } else {
+                    }
+                }
+            }
+        }
+        result = Y.Selector._filter(nodes, Y.Selector._tokenize(selector)[0]);
+        return result;
+    },
+
+    _filter: function(nodes, token, firstOnly, deDupe) {
+        var result = firstOnly ? null : [],
+            foundCache = Y.Selector._foundCache;
+
+        for (var i = 0, len = nodes.length; i < len; i++) {
+            if (! Y.Selector._test(nodes[i], '', token, deDupe)) {
+                continue;
+            }
+
+            if (firstOnly) {
+                return nodes[i];
+            }
+            if (deDupe) {
+                if (nodes[i]._found) {
+                    continue;
+                }
+                nodes[i]._found = true;
+                foundCache[foundCache.length] = nodes[i];
+            }
+
+            result[result.length] = nodes[i];
+        }
+
+        return result;
+    },
+
+    /**
+     * 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 | String} root optional An id or HTMLElement to start the query from. Defaults to Selector.document.
+     * @param {Boolean} firstOnly optional Whether or not to return only the first match.
+     * @return {Array} An array of nodes that match the given selector.
+     * @static
+     */
+    query: function(selector, root, firstOnly) {
+        var result = Y.Selector._query(selector, root, firstOnly);
+        return result;
+    },
+
+
+    _query: function(selector, root, firstOnly, deDupe) {
+        var result =  (firstOnly) ? null : [],
+            node;
+
+        if (!selector) {
+            return result;
+        }
+
+        var groups = selector.split(','); // TODO: handle comma in attribute/pseudo
+
+        if (groups.length > 1) {
+            var found;
+            for (var i = 0, len = groups.length; i < len; ++i) {
+                found = arguments.callee(groups[i], root, firstOnly, true);
+                result = firstOnly ? found : result.concat(found); 
+            }
+            Y.Selector._clearFoundCache();
+            return result;
+        }
+
+        if (root && !root.nodeName) { // assume ID
+            root = Y.Selector.document.getElementById(root);
+            if (!root) {
+                return result;
+            }
+        }
+
+        root = root || Y.Selector.document;
+
+        if (root.nodeName !== '#document') { // prepend with root selector
+            Y.Dom.generateId(root); // TODO: cleanup after?
+            selector = root.tagName + '#' + root.id + ' ' + selector;
+            node = root;
+            root = root.ownerDocument;
+        }
+
+        var tokens = Y.Selector._tokenize(selector);
+        var idToken = tokens[Y.Selector._getIdTokenIndex(tokens)],
+            nodes = [],
+            id,
+            token = tokens.pop() || {};
+            
+        if (idToken) {
+            id = Y.Selector._getId(idToken.attributes);
+        }
+
+        // use id shortcut when possible
+        if (id) {
+            node = node || Y.Selector.document.getElementById(id);
+
+            if (node && (root.nodeName === '#document' || Y.Dom.isAncestor(root, node))) {
+                if ( Y.Selector._test(node, null, idToken) ) {
+                    if (idToken === token) {
+                        nodes = [node]; // simple selector
+                    } else if (idToken.combinator === ' ' || idToken.combinator === '>') {
+                        root = node; // start from here
+                    }
+                }
+            } else {
+                return result;
+            }
+        }
+
+        if (root && !nodes.length) {
+            nodes = root.getElementsByTagName(token.tag);
+        }
+
+        if (nodes.length) {
+            result = Y.Selector._filter(nodes, token, firstOnly, deDupe); 
+        }
+
+        return result;
+    },
+
+
+    _clearFoundCache: function() {
+        var foundCache = Y.Selector._foundCache;
+        for (var i = 0, len = foundCache.length; i < len; ++i) {
+            try { // IE no like delete
+                delete foundCache[i]._found;
+            } catch(e) {
+                foundCache[i].removeAttribute('_found');
+            }
+        }
+        foundCache = [];
+    },
+
+
+    _getRegExp: function(str, flags) {
+        var regexCache = Y.Selector._regexCache;
+        flags = flags || '';
+        if (!regexCache[str + flags]) {
+            regexCache[str + flags] = new RegExp(str, flags);
+        }
+        return regexCache[str + flags];
+    },
+
+    _getChildren: function() {
+        if (document.documentElement.children) { // document for capability test
+            return function(node, tag) {
+                return (tag) ? node.children.tags(tag) : node.children || [];
+            };
+        } else {
+            return function(node, tag) {
+                if (node._children) {
+                    return node._children;
+                }
+                var children = [],
+                    childNodes = node.childNodes;
+
+                for (var i = 0, len = childNodes.length; i < len; ++i) {
+                    if (childNodes[i].tagName) {
+                        if (!tag || childNodes[i].tagName === tag) {
+                            children[children.length] = childNodes[i];
+                        }
+                    }
+                }
+                node._children = children;
+                return children;
+            };
+        }
+    }(),
+
+    _combinators: {
+        ' ': function(node, token) {
+            while ( (node = node.parentNode) ) {
+                if (Y.Selector._test(node, '', token.previous)) {
+                    return true;
+                }
+            }  
+            return false;
+        },
+
+        '>': function(node, token) {
+            return Y.Selector._test(node.parentNode, null, token.previous);
+        },
+
+        '+': function(node, token) {
+            var sib = node.previousSibling;
+            while (sib && sib.nodeType !== 1) {
+                sib = sib.previousSibling;
+            }
+
+            if (sib && Y.Selector._test(sib, null, token.previous)) {
+                return true; 
+            }
+            return false;
+        },
+
+        '~': function(node, token) {
+            var sib = node.previousSibling;
+            while (sib) {
+                if (sib.nodeType === 1 && Y.Selector._test(sib, null, token.previous)) {
+                    return true;
+                }
+                sib = sib.previousSibling;
+            }
+
+            return false;
+        }
+    },
+
+
+    /*
+        an+b = get every _a_th node starting at the _b_th
+        0n+b = no repeat ("0" and "n" may both be omitted (together) , e.g. "0n+1" or "1", not "0+1"), return only the _b_th element
+        1n+b =  get every element starting from b ("1" may may be omitted, e.g. "1n+0" or "n+0" or "n")
+        an+0 = get every _a_th element, "0" may be omitted 
+    */
+    _getNth: function(node, expr, tag, reverse) {
+        Y.Selector._re.nth.test(expr);
+        var a = parseInt(RegExp.$1, 10), // include every _a_ elements (zero means no repeat, just first _a_)
+            n = RegExp.$2, // "n"
+            oddeven = RegExp.$3, // "odd" or "even"
+            b = parseInt(RegExp.$4, 10) || 0, // start scan from element _b_
+            result = [],
+            op;
+
+        var siblings = Y.Selector._getChildren(node.parentNode, tag);
+
+        if (oddeven) {
+            a = 2; // always every other
+            op = '+';
+            n = 'n';
+            b = (oddeven === 'odd') ? 1 : 0;
+        } else if ( isNaN(a) ) {
+            a = (n) ? 1 : 0; // start from the first or no repeat
+        }
+
+        if (a === 0) { // just the first
+            if (reverse) {
+                b = siblings.length - b + 1; 
+            }
+
+            if (siblings[b - 1] === node) {
+                return true;
+            } else {
+                return false;
+            }
+
+        } else if (a < 0) {
+            reverse = !!reverse;
+            a = Math.abs(a);
+        }
+
+        if (!reverse) {
+            for (var i = b - 1, len = siblings.length; i < len; i += a) {
+                if ( i >= 0 && siblings[i] === node ) {
+                    return true;
+                }
+            }
+        } else {
+            for (var i = siblings.length - b, len = siblings.length; i >= 0; i -= a) {
+                if ( i < len && siblings[i] === node ) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    },
+
+    _getId: function(attr) {
+        for (var i = 0, len = attr.length; i < len; ++i) {
+            if (attr[i][0] == 'id' && attr[i][1] === '=') {
+                return attr[i][2];
+            }
+        }
+    },
+
+    _getIdTokenIndex: function(tokens) {
+        for (var i = 0, len = tokens.length; i < len; ++i) {
+            if (Y.Selector._getId(tokens[i].attributes)) {
+                return i;
+            }
+        }
+        return -1;
+    },
+
+    _patterns: {
+        tag: /^((?:-?[_a-z]+[\w-]*)|\*)/i,
+        attributes: /^\[([a-z]+\w*)+([~\|\^\$\*!=]=?)?['"]?([^\]]*?)['"]?\]/i,
+        pseudos: /^:([-\w]+)(?:\(['"]?(.+)['"]?\))*/i,
+        combinator: /^\s*([>+~]|\s)\s*/
+    },
+
+    /**
+        Break selector into token units per simple selector.
+        Combinator is attached to left-hand selector.
+     */
+    _tokenize: function(selector) {
+        var token = {},     // one token per simple selector (left selector holds combinator)
+            tokens = [],    // array of tokens
+            id,             // unique id for the simple selector (if found)
+            found = false,  // whether or not any matches were found this pass
+            patterns = Y.Selector._patterns,
+            match;          // the regex match
+
+        selector = Y.Selector._replaceShorthand(selector); // convert ID and CLASS shortcuts to attributes
+
+        /*
+            Search for selector patterns, store, and strip them from the selector string
+            until no patterns match (invalid selector) or we run out of chars.
+
+            Multiple attributes and pseudos are allowed, in any order.
+            for example:
+                'form:first-child[type=button]:not(button)[lang|=en]'
+        */
+        do {
+            found = false; // reset after full pass
+            for (var re in patterns) {
+                if (YAHOO.lang.hasOwnProperty(patterns, re)) {
+                    if (re != 'tag' && re != 'combinator') { // only one allowed
+                        token[re] = token[re] || [];
+                    }
+                    if ( (match = patterns[re].exec(selector)) ) { // note assignment
+                        found = true;
+                        if (re != 'tag' && re != 'combinator') { // only one allowed
+                            // capture ID for fast path to element
+                            if (re === 'attributes' && match[1] === 'id') {
+                                token.id = match[3];
+                            }
+
+                            token[re].push(match.slice(1));
+                        } else { // single selector (tag, combinator)
+                            token[re] = match[1];
+                        }
+                        selector = selector.replace(match[0], ''); // strip current match from selector
+                        if (re === 'combinator' || !selector.length) { // next token or done
+                            token.attributes = Y.Selector._fixAttributes(token.attributes);
+                            token.pseudos = token.pseudos || [];
+                            token.tag = token.tag ? token.tag.toUpperCase() : '*';
+                            tokens.push(token);
+
+                            token = { // prep next token
+                                previous: token
+                            };
+                        }
+                    }
+                }
+            }
+        } while (found);
+
+        return tokens;
+    },
+
+
+    _fixAttributes: function(attr) {
+        var aliases = Y.Selector.attrAliases;
+        attr = attr || [];
+        for (var i = 0, len = attr.length; i < len; ++i) {
+            if (aliases[attr[i][0]]) { // convert reserved words, etc
+                attr[i][0] = aliases[attr[i][0]];
+            }
+            if (!attr[i][1]) { // use exists operator
+                attr[i][1] = '';
+            }
+        }
+        return attr;
+    },
+
+    _replaceShorthand: function(selector) {
+        var shorthand = Y.Selector.shorthand;
+
+        //var attrs = selector.match(Y.Selector._patterns.attributes); // pull attributes to avoid false pos on "." and "#"
+        var attrs = selector.match(Y.Selector._re.attr); // pull attributes to avoid false pos on "." and "#"
+        if (attrs) {
+            selector = selector.replace(Y.Selector._re.attr, 'REPLACED_ATTRIBUTE');
+        }
+        for (var re in shorthand) {
+            if (YAHOO.lang.hasOwnProperty(shorthand, re)) {
+                selector = selector.replace(Y.Selector._getRegExp(re, 'gi'), shorthand[re]);
+            }
+        }
+
+        if (attrs) {
+            for (var i = 0, len = attrs.length; i < len; ++i) {
+                selector = selector.replace('REPLACED_ATTRIBUTE', attrs[i]);
+            }
+        }
+        return selector;
+    }
+};
+
+if (YAHOO.env.ua.ie && YAHOO.env.ua.ie < 8) { // rewrite class for IE < 8
+    Y.Selector.attrAliases['class'] = 'className';
+    Y.Selector.attrAliases['for'] = 'htmlFor';
+}
+
+})();
+YAHOO.register("selector", YAHOO.util.Selector, {version: "2.7.0", build: "1799"});