/*!
 * Sizzle CSS Selector Engine
 * Copyright 2012 jQuery Foundation and other contributors
 * Released under the MIT license
 * http://sizzlejs.com/
 */
KISSY.add('sizzle', function () {

    var cachedruns,
        assertGetIdNotName,
        Expr,
        getText,
        isXML,
        contains,
        compile,
        sortOrder,
        hasDuplicate,
        outermostContext,

        strundefined = "undefined",

    // Used in sorting
        MAX_NEGATIVE = 1 << 31,
        baseHasDuplicate = true,

        expando = ( "sizcache" + Math.random() ).replace(".", ""),

        Token = String,
        document = window.document,
        docElem = document.documentElement,
        dirruns = 0,
        done = 0,
        pop = [].pop,
        push = [].push,
        slice = [].slice,
    // Use a stripped-down indexOf if a native one is unavailable
        indexOf = [].indexOf || function (elem) {
            var i = 0,
                len = this.length;
            for (; i < len; i++) {
                if (this[i] === elem) {
                    return i;
                }
            }
            return -1;
        },

    // Augment a function for special use by Sizzle
        markFunction = function (fn, value) {
            fn[ expando ] = value == null || value;
            return fn;
        },

        createCache = function () {
            var cache = {},
                keys = [];

            return markFunction(function (key, value) {
                // Only keep the most recent entries
                if (keys.push(key) > Expr.cacheLength) {
                    delete cache[ keys.shift() ];
                }

                // Retrieve with (key + " ") to avoid collision with native Object.prototype properties (see Issue #157)
                return (cache[ key + " " ] = value);
            }, cache);
        },

        classCache = createCache(),
        tokenCache = createCache(),
        compilerCache = createCache(),

    // Regex

    // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace
        whitespace = "[\\x20\\t\\r\\n\\f]",
    // http://www.w3.org/TR/css3-syntax/#characters
        characterEncoding = "(?:\\\\.|[-\\w]|[^\\x00-\\xa0])+",

    // Loosely modeled on CSS identifier characters
    // An unquoted value should be a CSS identifier (http://www.w3.org/TR/css3-selectors/#attribute-selectors)
    // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
        identifier = characterEncoding.replace("w", "w#"),

    // Acceptable operators http://www.w3.org/TR/selectors/#attribute-selectors
        operators = "([*^$|!~]?=)",
        attributes = "\\[" + whitespace + "*(" + characterEncoding + ")" + whitespace +
            "*(?:" + operators + whitespace + "*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|(" + identifier + ")|)|)" + whitespace + "*\\]",

    // Prefer arguments not in parens/brackets,
    //   then attribute selectors and non-pseudos (denoted by :),
    //   then anything else
    // These preferences are here to reduce the number of selectors
    //   needing tokenize in the PSEUDO preFilter
        pseudos = ":(" + characterEncoding + ")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|([^()[\\]]*|(?:(?:" + attributes + ")|[^:]|\\\\.)*|.*))\\)|)",

    // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
        rtrim = new RegExp("^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g"),

        rcomma = new RegExp("^" + whitespace + "*," + whitespace + "*"),
        rcombinators = new RegExp("^" + whitespace + "*([\\x20\\t\\r\\n\\f>+~])" + whitespace + "*"),
        rpseudo = new RegExp(pseudos),

    // Easily-parseable/retrievable ID or TAG or CLASS selectors
        rquickExpr = /^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/,

        rsibling = /[\x20\t\r\n\f]*[+~]/,

        rheader = /h\d/i,
        rinputs = /input|select|textarea|button/i,

        rbackslash = /\\(?!\\)/g,

        matchExpr = {
            "ID": new RegExp("^#(" + characterEncoding + ")"),
            "CLASS": new RegExp("^\\.(" + characterEncoding + ")"),
            "NAME": new RegExp("^\\[name=['\"]?(" + characterEncoding + ")['\"]?\\]"),
            "TAG": new RegExp("^(" + characterEncoding.replace("w", "w*") + ")"),
            "ATTR": new RegExp("^" + attributes),
            "PSEUDO": new RegExp("^" + pseudos),
            "CHILD": new RegExp("^:(only|nth|first|last)-child(?:\\(" + whitespace +
                "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
                "*(\\d+)|))" + whitespace + "*\\)|)", "i"),
            // For use in libraries implementing .is()
            // We use this for POS matching in `select`
            "needsContext": new RegExp("^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
                whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i")
        },

    // Support

    // Used for testing something on an element
        assert = function (fn) {
            var div = document.createElement("div");

            try {
                return fn(div);
            } catch (e) {
                return false;
            } finally {
                // release memory in IE
                div = null;
            }
        },

    // Check if getElementsByTagName("*") returns only elements
        assertTagNameNoComments = assert(function (div) {
            div.appendChild(document.createComment(""));
            return !div.getElementsByTagName("*").length;
        }),

    // Check if getAttribute returns normalized href attributes
        assertHrefNotNormalized = assert(function (div) {
            div.innerHTML = "<a href='#'></a>";
            return div.firstChild && typeof div.firstChild.getAttribute !== strundefined &&
                div.firstChild.getAttribute("href") === "#";
        }),

    // Check if attributes should be retrieved by attribute nodes
        assertAttributes = assert(function (div) {
            div.innerHTML = "<select></select>";
            var type = typeof div.lastChild.getAttribute("multiple");
            // IE8 returns a string for some attributes even when not present
            return type !== "boolean" && type !== "string";
        }),

    // Check if getElementsByClassName can be trusted
        assertUsableClassName = assert(function (div) {
            // Opera can't find a second classname (in 9.6)
            div.innerHTML = "<div class='hidden e'></div><div class='hidden'></div>";
            if (!div.getElementsByClassName || !div.getElementsByClassName("e").length) {
                return false;
            }

            // Safari 3.2 caches class attributes and doesn't catch changes
            div.lastChild.className = "e";
            return div.getElementsByClassName("e").length === 2;
        }),

    // Check if getElementById returns elements by name
    // Check if getElementsByName privileges form controls or returns elements by ID
        assertUsableName = assert(function (div) {
            // Inject content
            div.id = expando + 0;
            div.innerHTML = "<a name='" + expando + "'></a><div name='" + expando + "'></div>";
            docElem.insertBefore(div, docElem.firstChild);

            // Test
            var pass = document.getElementsByName &&
                // buggy browsers will return fewer than the correct 2
                document.getElementsByName(expando).length === 2 +
                    // buggy browsers will return more than the correct 0
                    document.getElementsByName(expando + 0).length;
            assertGetIdNotName = !document.getElementById(expando);

            // Cleanup
            docElem.removeChild(div);

            return pass;
        });

// If slice is not available, provide a backup
    try {
        slice.call(docElem.childNodes, 0)[0].nodeType;
    } catch (e) {
        slice = function (i) {
            var elem,
                results = [];
            for (; (elem = this[i]); i++) {
                results.push(elem);
            }
            return results;
        };
    }

    function Sizzle(selector, context, results, seed) {
        results = results || [];
        context = context || document;
        var match, elem, xml, m,
            nodeType = context.nodeType;

        if (!selector || typeof selector !== "string") {
            return results;
        }

        if (nodeType !== 1 && nodeType !== 9) {
            return [];
        }

        xml = isXML(context);

        if (!xml && !seed) {
            if ((match = rquickExpr.exec(selector))) {
                // Speed-up: Sizzle("#ID")
                if ((m = match[1])) {
                    if (nodeType === 9) {
                        elem = context.getElementById(m);
                        // Check parentNode to catch when Blackberry 4.6 returns
                        // nodes that are no longer in the document #6963
                        if (elem && elem.parentNode) {
                            // Handle the case where IE, Opera, and Webkit return items
                            // by name instead of ID
                            if (elem.id === m) {
                                results.push(elem);
                                return results;
                            }
                        } else {
                            return results;
                        }
                    } else {
                        // Context is not a document
                        if (context.ownerDocument && (elem = context.ownerDocument.getElementById(m)) &&
                            contains(context, elem) && elem.id === m) {
                            results.push(elem);
                            return results;
                        }
                    }

                    // Speed-up: Sizzle("TAG")
                } else if (match[2]) {
                    push.apply(results, slice.call(context.getElementsByTagName(selector), 0));
                    return results;

                    // Speed-up: Sizzle(".CLASS")
                } else if ((m = match[3]) && assertUsableClassName && context.getElementsByClassName) {
                    push.apply(results, slice.call(context.getElementsByClassName(m), 0));
                    return results;
                }
            }
        }

        // All others
        return select(selector.replace(rtrim, "$1"), context, results, seed, xml);
    }

    Sizzle.matches = function (expr, elements) {
        return Sizzle(expr, null, null, elements);
    };

    Sizzle.matchesSelector = function (elem, expr) {
        return Sizzle(expr, null, null, [ elem ]).length > 0;
    };

// Returns a function to use in pseudos for input types
    function createInputPseudo(type) {
        return function (elem) {
            var name = elem.nodeName.toLowerCase();
            return name === "input" && elem.type === type;
        };
    }

// Returns a function to use in pseudos for buttons
    function createButtonPseudo(type) {
        return function (elem) {
            var name = elem.nodeName.toLowerCase();
            return (name === "input" || name === "button") && elem.type === type;
        };
    }

// Returns a function to use in pseudos for positionals
    function createPositionalPseudo(fn) {
        return markFunction(function (argument) {
            argument = +argument;
            return markFunction(function (seed, matches) {
                var j,
                    matchIndexes = fn([], seed.length, argument),
                    i = matchIndexes.length;

                // Match elements found at the specified indexes
                while (i--) {
                    if (seed[ (j = matchIndexes[i]) ]) {
                        seed[j] = !(matches[j] = seed[j]);
                    }
                }
            });
        });
    }

    /**
     * Utility function for retrieving the text value of an array of DOM nodes
     * @param {Array|Element} elem
     */
    getText = Sizzle.getText = function (elem) {
        var node,
            ret = "",
            i = 0,
            nodeType = elem.nodeType;

        if (nodeType) {
            if (nodeType === 1 || nodeType === 9 || nodeType === 11) {
                // Use textContent for elements
                // innerText usage removed for consistency of new lines (see #11153)
                if (typeof elem.textContent === "string") {
                    return elem.textContent;
                } else {
                    // Traverse its children
                    for (elem = elem.firstChild; elem; elem = elem.nextSibling) {
                        ret += getText(elem);
                    }
                }
            } else if (nodeType === 3 || nodeType === 4) {
                return elem.nodeValue;
            }
            // Do not include comment or processing instruction nodes
        } else {

            // If no nodeType, this is expected to be an array
            for (; (node = elem[i]); i++) {
                // Do not traverse comment nodes
                ret += getText(node);
            }
        }
        return ret;
    };

    isXML = Sizzle.isXML = function (elem) {
        // documentElement is verified for cases where it doesn't yet exist
        // (such as loading iframes in IE - #4833)
        var documentElement = elem && (elem.ownerDocument || elem).documentElement;
        return documentElement ? documentElement.nodeName !== "HTML" : false;
    };

// Element contains another
    contains = Sizzle.contains = docElem.contains ?
        function (a, b) {
            var adown = a.nodeType === 9 ? a.documentElement : a,
                bup = b && b.parentNode;
            return a === bup || !!( bup && bup.nodeType === 1 && adown.contains && adown.contains(bup) );
        } :
        docElem.compareDocumentPosition ?
            function (a, b) {
                return b && !!( a.compareDocumentPosition(b) & 16 );
            } :
            function (a, b) {
                while ((b = b.parentNode)) {
                    if (b === a) {
                        return true;
                    }
                }
                return false;
            };

    Sizzle.attr = function (elem, name) {
        var val,
            xml = isXML(elem);

        if (!xml) {
            name = name.toLowerCase();
        }
        if ((val = Expr.attrHandle[ name ])) {
            return val(elem);
        }
        if (xml || assertAttributes) {
            return elem.getAttribute(name);
        }
        val = elem.getAttributeNode(name);
        return val ?
            typeof elem[ name ] === "boolean" ?
                elem[ name ] ? name : null :
                val.specified ? val.value : null :
            null;
    };

    Expr = Sizzle.selectors = {

        // Can be adjusted by the user
        cacheLength: 50,

        createPseudo: markFunction,

        match: matchExpr,

        // IE6/7 return a modified href
        attrHandle: assertHrefNotNormalized ?
        {} :
        {
            "href": function (elem) {
                return elem.getAttribute("href", 2);
            },
            "type": function (elem) {
                return elem.getAttribute("type");
            }
        },

        find: {
            "ID": assertGetIdNotName ?
                function (id, context, xml) {
                    if (typeof context.getElementById !== strundefined && !xml) {
                        var m = context.getElementById(id);
                        // Check parentNode to catch when Blackberry 4.6 returns
                        // nodes that are no longer in the document #6963
                        return m && m.parentNode ? [m] : [];
                    }
                } :
                function (id, context, xml) {
                    if (typeof context.getElementById !== strundefined && !xml) {
                        var m = context.getElementById(id);

                        return m ?
                            m.id === id || typeof m.getAttributeNode !== strundefined && m.getAttributeNode("id").value === id ?
                                [m] :
                                undefined :
                            [];
                    }
                },

            "TAG": assertTagNameNoComments ?
                function (tag, context) {
                    if (typeof context.getElementsByTagName !== strundefined) {
                        return context.getElementsByTagName(tag);
                    }
                } :
                function (tag, context) {
                    var results = context.getElementsByTagName(tag);

                    // Filter out possible comments
                    if (tag === "*") {
                        var elem,
                            tmp = [],
                            i = 0;

                        for (; (elem = results[i]); i++) {
                            if (elem.nodeType === 1) {
                                tmp.push(elem);
                            }
                        }

                        return tmp;
                    }
                    return results;
                },

            "NAME": assertUsableName && function (tag, context) {
                if (typeof context.getElementsByName !== strundefined) {
                    return context.getElementsByName(name);
                }
            },

            "CLASS": assertUsableClassName && function (className, context, xml) {
                if (typeof context.getElementsByClassName !== strundefined && !xml) {
                    return context.getElementsByClassName(className);
                }
            }
        },

        relative: {
            ">": { dir: "parentNode", first: true },
            " ": { dir: "parentNode" },
            "+": { dir: "previousSibling", first: true },
            "~": { dir: "previousSibling" }
        },

        preFilter: {
            "ATTR": function (match) {
                match[1] = match[1].replace(rbackslash, "");

                // Move the given value to match[3] whether quoted or unquoted
                match[3] = ( match[4] || match[5] || "" ).replace(rbackslash, "");

                if (match[2] === "~=") {
                    match[3] = " " + match[3] + " ";
                }

                return match.slice(0, 4);
            },

            "CHILD": function (match) {
                /* matches from matchExpr["CHILD"]
                 1 type (only|nth|...)
                 2 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
                 3 xn-component of xn+y argument ([+-]?\d*n|)
                 4 sign of xn-component
                 5 x of xn-component
                 6 sign of y-component
                 7 y of y-component
                 */
                match[1] = match[1].toLowerCase();

                if (match[1] === "nth") {
                    // nth-child requires argument
                    if (!match[2]) {
                        Sizzle.error(match[0]);
                    }

                    // numeric x and y parameters for Expr.filter.CHILD
                    // remember that false/true cast respectively to 0/1
                    match[3] = +( match[3] ? match[4] + (match[5] || 1) : 2 * ( match[2] === "even" || match[2] === "odd" ) );
                    match[4] = +( ( match[6] + match[7] ) || match[2] === "odd" );

                    // other types prohibit arguments
                } else if (match[2]) {
                    Sizzle.error(match[0]);
                }

                return match;
            },

            "PSEUDO": function (match) {
                var unquoted, excess;
                if (matchExpr["CHILD"].test(match[0])) {
                    return null;
                }

                if (match[3]) {
                    match[2] = match[3];
                } else if ((unquoted = match[4])) {
                    // Only check arguments that contain a pseudo
                    if (rpseudo.test(unquoted) &&
                        // Get excess from tokenize (recursively)
                        (excess = tokenize(unquoted, true)) &&
                        // advance to the next closing parenthesis
                        (excess = unquoted.indexOf(")", unquoted.length - excess) - unquoted.length)) {

                        // excess is a negative index
                        unquoted = unquoted.slice(0, excess);
                        match[0] = match[0].slice(0, excess);
                    }
                    match[2] = unquoted;
                }

                // Return only captures needed by the pseudo filter method (type and argument)
                return match.slice(0, 3);
            }
        },

        filter: {
            "ID": assertGetIdNotName ?
                function (id) {
                    id = id.replace(rbackslash, "");
                    return function (elem) {
                        return elem.getAttribute("id") === id;
                    };
                } :
                function (id) {
                    id = id.replace(rbackslash, "");
                    return function (elem) {
                        var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id");
                        return node && node.value === id;
                    };
                },

            "TAG": function (nodeName) {
                if (nodeName === "*") {
                    return function () {
                        return true;
                    };
                }
                nodeName = nodeName.replace(rbackslash, "").toLowerCase();

                return function (elem) {
                    return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
                };
            },

            "CLASS": function (className) {
                var pattern = classCache[ expando ][ className + " " ];

                return pattern ||
                    (pattern = new RegExp("(^|" + whitespace + ")" + className + "(" + whitespace + "|$)")) &&
                        classCache(className, function (elem) {
                            return pattern.test(elem.className || (typeof elem.getAttribute !== strundefined && elem.getAttribute("class")) || "");
                        });
            },

            "ATTR": function (name, operator, check) {
                return function (elem) {
                    var result = Sizzle.attr(elem, name);

                    if (result == null) {
                        return operator === "!=";
                    }
                    if (!operator) {
                        return true;
                    }

                    result += "";

                    return operator === "=" ? result === check :
                        operator === "!=" ? result !== check :
                            operator === "^=" ? check && result.indexOf(check) === 0 :
                                operator === "*=" ? check && result.indexOf(check) > -1 :
                                    operator === "$=" ? check && result.substr(result.length - check.length) === check :
                                        operator === "~=" ? ( " " + result + " " ).indexOf(check) > -1 :
                                            operator === "|=" ? result === check || result.substr(0, check.length + 1) === check + "-" :
                                                false;
                };
            },

            "CHILD": function (type, argument, first, last) {

                if (type === "nth") {
                    return function (elem) {
                        var node, diff,
                            parent = elem.parentNode;

                        if (first === 1 && last === 0) {
                            return true;
                        }

                        if (parent) {
                            diff = 0;
                            for (node = parent.firstChild; node; node = node.nextSibling) {
                                if (node.nodeType === 1) {
                                    diff++;
                                    if (elem === node) {
                                        break;
                                    }
                                }
                            }
                        }

                        // Incorporate the offset (or cast to NaN), then check against cycle size
                        diff -= last;
                        return diff === first || ( diff % first === 0 && diff / first >= 0 );
                    };
                }

                return function (elem) {
                    var node = elem;

                    switch (type) {
                        case "only":
                        case "first":
                            while ((node = node.previousSibling)) {
                                if (node.nodeType === 1) {
                                    return false;
                                }
                            }

                            if (type === "first") {
                                return true;
                            }

                            node = elem;

                        /* falls through */
                        case "last":
                            while ((node = node.nextSibling)) {
                                if (node.nodeType === 1) {
                                    return false;
                                }
                            }

                            return true;
                    }
                };
            },

            "PSEUDO": function (pseudo, argument) {
                // pseudo-class names are case-insensitive
                // http://www.w3.org/TR/selectors/#pseudo-classes
                // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
                // Remember that setFilters inherits from pseudos
                var args,
                    fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
                        Sizzle.error("unsupported pseudo: " + pseudo);

                // The user may use createPseudo to indicate that
                // arguments are needed to create the filter function
                // just as Sizzle does
                if (fn[ expando ]) {
                    return fn(argument);
                }

                // But maintain support for old signatures
                if (fn.length > 1) {
                    args = [ pseudo, pseudo, "", argument ];
                    return Expr.setFilters.hasOwnProperty(pseudo.toLowerCase()) ?
                        markFunction(function (seed, matches) {
                            var idx,
                                matched = fn(seed, argument),
                                i = matched.length;
                            while (i--) {
                                idx = indexOf.call(seed, matched[i]);
                                seed[ idx ] = !( matches[ idx ] = matched[i] );
                            }
                        }) :
                        function (elem) {
                            return fn(elem, 0, args);
                        };
                }

                return fn;
            }
        },

        pseudos: {
            "not": markFunction(function (selector) {
                // Trim the selector passed to compile
                // to avoid treating leading and trailing
                // spaces as combinators
                var input = [],
                    results = [],
                    matcher = compile(selector.replace(rtrim, "$1"));

                return matcher[ expando ] ?
                    markFunction(function (seed, matches, context, xml) {
                        var elem,
                            unmatched = matcher(seed, null, xml, []),
                            i = seed.length;

                        // Match elements unmatched by `matcher`
                        while (i--) {
                            if ((elem = unmatched[i])) {
                                seed[i] = !(matches[i] = elem);
                            }
                        }
                    }) :
                    function (elem, context, xml) {
                        input[0] = elem;
                        matcher(input, null, xml, results);
                        return !results.pop();
                    };
            }),

            "has": markFunction(function (selector) {
                return function (elem) {
                    return Sizzle(selector, elem).length > 0;
                };
            }),

            "contains": markFunction(function (text) {
                return function (elem) {
                    return ( elem.textContent || elem.innerText || getText(elem) ).indexOf(text) > -1;
                };
            }),

            "enabled": function (elem) {
                return elem.disabled === false;
            },

            "disabled": function (elem) {
                return elem.disabled === true;
            },

            "checked": function (elem) {
                // In CSS3, :checked should return both checked and selected elements
                // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
                var nodeName = elem.nodeName.toLowerCase();
                return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
            },

            "selected": function (elem) {
                // Accessing this property makes selected-by-default
                // options in Safari work properly
                if (elem.parentNode) {
                    elem.parentNode.selectedIndex;
                }

                return elem.selected === true;
            },

            "parent": function (elem) {
                return !Expr.pseudos["empty"](elem);
            },

            "empty": function (elem) {
                // http://www.w3.org/TR/selectors/#empty-pseudo
                // :empty is only affected by element nodes and content nodes(including text(3), cdata(4)),
                //   not comment, processing instructions, or others
                // Thanks to Diego Perini for the nodeName shortcut
                //   Greater than "@" means alpha characters (specifically not starting with "#" or "?")
                var nodeType;
                elem = elem.firstChild;
                while (elem) {
                    if (elem.nodeName > "@" || (nodeType = elem.nodeType) === 3 || nodeType === 4) {
                        return false;
                    }
                    elem = elem.nextSibling;
                }
                return true;
            },

            "header": function (elem) {
                return rheader.test(elem.nodeName);
            },

            "text": function (elem) {
                var type, attr;
                // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc)
                // use getAttribute instead to test this case
                return elem.nodeName.toLowerCase() === "input" &&
                    (type = elem.type) === "text" &&
                    ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === type );
            },

            // Input types
            "radio": createInputPseudo("radio"),
            "checkbox": createInputPseudo("checkbox"),
            "file": createInputPseudo("file"),
            "password": createInputPseudo("password"),
            "image": createInputPseudo("image"),

            "submit": createButtonPseudo("submit"),
            "reset": createButtonPseudo("reset"),

            "button": function (elem) {
                var name = elem.nodeName.toLowerCase();
                return name === "input" && elem.type === "button" || name === "button";
            },

            "input": function (elem) {
                return rinputs.test(elem.nodeName);
            },

            "focus": function (elem) {
                var doc = elem.ownerDocument;
                return elem === doc.activeElement && (!doc.hasFocus || doc.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
            },

            "active": function (elem) {
                return elem === elem.ownerDocument.activeElement;
            },

            // Positional types
            "first": createPositionalPseudo(function () {
                return [ 0 ];
            }),

            "last": createPositionalPseudo(function (matchIndexes, length) {
                return [ length - 1 ];
            }),

            "eq": createPositionalPseudo(function (matchIndexes, length, argument) {
                return [ argument < 0 ? argument + length : argument ];
            }),

            "even": createPositionalPseudo(function (matchIndexes, length) {
                for (var i = 0; i < length; i += 2) {
                    matchIndexes.push(i);
                }
                return matchIndexes;
            }),

            "odd": createPositionalPseudo(function (matchIndexes, length) {
                for (var i = 1; i < length; i += 2) {
                    matchIndexes.push(i);
                }
                return matchIndexes;
            }),

            "lt": createPositionalPseudo(function (matchIndexes, length, argument) {
                for (var i = argument < 0 ? argument + length : argument; --i >= 0;) {
                    matchIndexes.push(i);
                }
                return matchIndexes;
            }),

            "gt": createPositionalPseudo(function (matchIndexes, length, argument) {
                for (var i = argument < 0 ? argument + length : argument; ++i < length;) {
                    matchIndexes.push(i);
                }
                return matchIndexes;
            })
        }
    };

    function siblingCheck(a, b) {

        if (a && b) {
            var cur = a.nextSibling;

            while (cur) {
                if (cur === b) {
                    return -1;
                }

                cur = cur.nextSibling;
            }
        }

        return a ? 1 : -1;
    }

    sortOrder = docElem.compareDocumentPosition ?
        function (a, b) {
            var compare, parent;
            if (a === b) {
                hasDuplicate = true;
                return 0;
            }

            if (a.compareDocumentPosition && b.compareDocumentPosition) {
                if ((compare = a.compareDocumentPosition(b)) & 1 || (( parent = a.parentNode ) && parent.nodeType === 11)) {
                    if (a === document || contains(document, a)) {
                        return -1;
                    }
                    if (b === document || contains(document, b)) {
                        return 1;
                    }
                    return 0;
                }
                return compare & 4 ? -1 : 1;
            }

            return a.compareDocumentPosition ? -1 : 1;
        } :
        function (a, b) {
            // The nodes are identical, we can exit early
            if (a === b) {
                hasDuplicate = true;
                return 0;

                // Fallback to using sourceIndex (in IE) if it's available on both nodes
            } else if (a.sourceIndex && b.sourceIndex) {
                return ( ~b.sourceIndex || ( MAX_NEGATIVE ) ) - ( contains(document, a) && ~a.sourceIndex || ( MAX_NEGATIVE ) );
            }

            var i = 0,
                ap = [ a ],
                bp = [ b ],
                aup = a.parentNode,
                bup = b.parentNode,
                cur = aup;

            // If no parents were found then the nodes are disconnected
            if (a === document) {
                return -1;

            } else if (b === document) {
                return 1;

            } else if (!aup && !bup) {
                return 0;

            } else if (!bup) {
                return -1;

            } else if (!aup) {
                return 1;

                // If the nodes are siblings (or identical) we can do a quick check
            } else if (aup === bup) {
                return siblingCheck(a, b);
            }

            // Otherwise they're somewhere else in the tree so we need
            // to build up a full list of the parentNodes for comparison
            while (cur) {
                ap.unshift(cur);
                cur = cur.parentNode;
            }

            cur = bup;

            while (cur) {
                bp.unshift(cur);
                cur = cur.parentNode;
            }

            // Walk down the tree looking for a discrepancy
            while (ap[i] === bp[i]) {
                i++;
            }

            // Prefer our document
            if (i === 0) {
                if (ap[0] === document || contains(document, ap[0])) {
                    return -1;
                }
                if (bp[0] === document || contains(document, bp[0])) {
                    return 1;
                }
                return 0;
            }

            // We ended someplace up the tree so do a sibling check
            return siblingCheck(ap[i], bp[i]);
        };

// Always assume the presence of duplicates if sort doesn't
// pass them to our comparison function (as in Google Chrome).
    [0, 0].sort(sortOrder);
    baseHasDuplicate = !hasDuplicate;

// Document sorting and removing duplicates
    Sizzle.uniqueSort = function (results) {
        var elem,
            duplicates = [],
            i = 1,
            j = 0;

        hasDuplicate = baseHasDuplicate;
        results.sort(sortOrder);

        if (hasDuplicate) {
            for (; (elem = results[i]); i++) {
                if (elem === results[ i - 1 ]) {
                    j = duplicates.push(i);
                }
            }
            while (j--) {
                results.splice(duplicates[ j ], 1);
            }
        }

        return results;
    };

    Sizzle.error = function (msg) {
        throw new Error("Syntax error, unrecognized expression: " + msg);
    };

    function tokenize(selector, parseOnly) {
        var matched, match, tokens, type,
            soFar, groups, preFilters,
            cached = tokenCache[ expando ][ selector + " " ];

        if (cached) {
            return parseOnly ? 0 : cached.slice(0);
        }

        soFar = selector;
        groups = [];
        preFilters = Expr.preFilter;

        while (soFar) {

            // Comma and first run
            if (!matched || (match = rcomma.exec(soFar))) {
                if (match) {
                    // Don't consume trailing commas as valid
                    soFar = soFar.slice(match[0].length) || soFar;
                }
                groups.push(tokens = []);
            }

            matched = false;

            // Combinators
            if ((match = rcombinators.exec(soFar))) {
                tokens.push(matched = new Token(match.shift()));
                soFar = soFar.slice(matched.length);

                // Cast descendant combinators to space
                matched.type = match[0].replace(rtrim, " ");
            }

            // Filters
            for (type in Expr.filter) {
                if ((match = matchExpr[ type ].exec(soFar)) && (!preFilters[ type ] ||
                    (match = preFilters[ type ](match)))) {

                    tokens.push(matched = new Token(match.shift()));
                    soFar = soFar.slice(matched.length);
                    matched.type = type;
                    matched.matches = match;
                }
            }

            if (!matched) {
                break;
            }
        }

        // Return the length of the invalid excess
        // if we're just parsing
        // Otherwise, throw an error or return tokens
        return parseOnly ?
            soFar.length :
            soFar ?
                Sizzle.error(selector) :
                // Cache the tokens
                tokenCache(selector, groups).slice(0);
    }

    function addCombinator(matcher, combinator, base) {
        var dir = combinator.dir,
            checkNonElements = base && combinator.dir === "parentNode",
            doneName = done++;

        return combinator.first ?
            // Check against closest ancestor/preceding element
            function (elem, context, xml) {
                while ((elem = elem[ dir ])) {
                    if (checkNonElements || elem.nodeType === 1) {
                        return matcher(elem, context, xml);
                    }
                }
            } :

            // Check against all ancestor/preceding elements
            function (elem, context, xml) {
                // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching
                if (!xml) {
                    var cache,
                        dirkey = dirruns + " " + doneName + " ",
                        cachedkey = dirkey + cachedruns;
                    while ((elem = elem[ dir ])) {
                        if (checkNonElements || elem.nodeType === 1) {
                            if ((cache = elem[ expando ]) === cachedkey) {
                                return elem.sizset;
                            } else if (typeof cache === "string" && cache.indexOf(dirkey) === 0) {
                                if (elem.sizset) {
                                    return elem;
                                }
                            } else {
                                elem[ expando ] = cachedkey;
                                if (matcher(elem, context, xml)) {
                                    elem.sizset = true;
                                    return elem;
                                }
                                elem.sizset = false;
                            }
                        }
                    }
                } else {
                    while ((elem = elem[ dir ])) {
                        if (checkNonElements || elem.nodeType === 1) {
                            if (matcher(elem, context, xml)) {
                                return elem;
                            }
                        }
                    }
                }
            };
    }

    function elementMatcher(matchers) {
        return matchers.length > 1 ?
            function (elem, context, xml) {
                var i = matchers.length;
                while (i--) {
                    if (!matchers[i](elem, context, xml)) {
                        return false;
                    }
                }
                return true;
            } :
            matchers[0];
    }

    function condense(unmatched, map, filter, context, xml) {
        var elem,
            newUnmatched = [],
            i = 0,
            len = unmatched.length,
            mapped = map != null;

        for (; i < len; i++) {
            if ((elem = unmatched[i])) {
                if (!filter || filter(elem, context, xml)) {
                    newUnmatched.push(elem);
                    if (mapped) {
                        map.push(i);
                    }
                }
            }
        }

        return newUnmatched;
    }

    function setMatcher(preFilter, selector, matcher, postFilter, postFinder, postSelector) {
        if (postFilter && !postFilter[ expando ]) {
            postFilter = setMatcher(postFilter);
        }
        if (postFinder && !postFinder[ expando ]) {
            postFinder = setMatcher(postFinder, postSelector);
        }
        return markFunction(function (seed, results, context, xml) {
            var temp, i, elem,
                preMap = [],
                postMap = [],
                preexisting = results.length,

            // Get initial elements from seed or context
                elems = seed || multipleContexts(selector || "*", context.nodeType ? [ context ] : context, []),

            // Prefilter to get matcher input, preserving a map for seed-results synchronization
                matcherIn = preFilter && ( seed || !selector ) ?
                    condense(elems, preMap, preFilter, context, xml) :
                    elems,

                matcherOut = matcher ?
                    // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
                    postFinder || ( seed ? preFilter : preexisting || postFilter ) ?

                        // ...intermediate processing is necessary
                        [] :

                        // ...otherwise use results directly
                        results :
                    matcherIn;

            // Find primary matches
            if (matcher) {
                matcher(matcherIn, matcherOut, context, xml);
            }

            // Apply postFilter
            if (postFilter) {
                temp = condense(matcherOut, postMap);
                postFilter(temp, [], context, xml);

                // Un-match failing elements by moving them back to matcherIn
                i = temp.length;
                while (i--) {
                    if ((elem = temp[i])) {
                        matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);
                    }
                }
            }

            if (seed) {
                if (postFinder || preFilter) {
                    if (postFinder) {
                        // Get the final matcherOut by condensing this intermediate into postFinder contexts
                        temp = [];
                        i = matcherOut.length;
                        while (i--) {
                            if ((elem = matcherOut[i])) {
                                // Restore matcherIn since elem is not yet a final match
                                temp.push((matcherIn[i] = elem));
                            }
                        }
                        postFinder(null, (matcherOut = []), temp, xml);
                    }

                    // Move matched elements from seed to results to keep them synchronized
                    i = matcherOut.length;
                    while (i--) {
                        if ((elem = matcherOut[i]) &&
                            (temp = postFinder ? indexOf.call(seed, elem) : preMap[i]) > -1) {

                            seed[temp] = !(results[temp] = elem);
                        }
                    }
                }

                // Add elements to results, through postFinder if defined
            } else {
                matcherOut = condense(
                    matcherOut === results ?
                        matcherOut.splice(preexisting, matcherOut.length) :
                        matcherOut
                );
                if (postFinder) {
                    postFinder(null, results, matcherOut, xml);
                } else {
                    push.apply(results, matcherOut);
                }
            }
        });
    }

    function matcherFromTokens(tokens) {
        var checkContext, matcher, j,
            len = tokens.length,
            leadingRelative = Expr.relative[ tokens[0].type ],
            implicitRelative = leadingRelative || Expr.relative[" "],
            i = leadingRelative ? 1 : 0,

        // The foundational matcher ensures that elements are reachable from top-level context(s)
            matchContext = addCombinator(function (elem) {
                return elem === checkContext;
            }, implicitRelative, true),
            matchAnyContext = addCombinator(function (elem) {
                return indexOf.call(checkContext, elem) > -1;
            }, implicitRelative, true),
            matchers = [ function (elem, context, xml) {
                return ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
                    (checkContext = context).nodeType ?
                        matchContext(elem, context, xml) :
                        matchAnyContext(elem, context, xml) );
            } ];

        for (; i < len; i++) {
            if ((matcher = Expr.relative[ tokens[i].type ])) {
                matchers = [ addCombinator(elementMatcher(matchers), matcher) ];
            } else {
                matcher = Expr.filter[ tokens[i].type ].apply(null, tokens[i].matches);

                // Return special upon seeing a positional matcher
                if (matcher[ expando ]) {
                    // Find the next relative operator (if any) for proper handling
                    j = ++i;
                    for (; j < len; j++) {
                        if (Expr.relative[ tokens[j].type ]) {
                            break;
                        }
                    }
                    return setMatcher(
                        i > 1 && elementMatcher(matchers),
                        i > 1 && tokens.slice(0, i - 1).join("").replace(rtrim, "$1"),
                        matcher,
                        i < j && matcherFromTokens(tokens.slice(i, j)),
                        j < len && matcherFromTokens((tokens = tokens.slice(j))),
                        j < len && tokens.join("")
                    );
                }
                matchers.push(matcher);
            }
        }

        return elementMatcher(matchers);
    }

    function matcherFromGroupMatchers(elementMatchers, setMatchers) {
        // A counter to specify which element is currently being matched
        var matcherCachedRuns = 0,
            bySet = setMatchers.length > 0,
            byElement = elementMatchers.length > 0,
            superMatcher = function (seed, context, xml, results, expandContext) {
                var elem, j, matcher,
                    setMatched = [],
                    matchedCount = 0,
                    i = "0",
                    unmatched = seed && [],
                    outermost = expandContext != null,
                    contextBackup = outermostContext,
                // We must always have either seed elements or context
                    elems = seed || byElement && Expr.find["TAG"]("*", expandContext && context.parentNode || context),
                // Nested matchers should use non-integer dirruns
                    dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.E);

                if (outermost) {
                    outermostContext = context !== document && context;
                    cachedruns = matcherCachedRuns;
                }

                // Add elements passing elementMatchers directly to results
                for (; (elem = elems[i]) != null; i++) {
                    if (byElement && elem) {
                        for (j = 0; (matcher = elementMatchers[j]); j++) {
                            if (matcher(elem, context, xml)) {
                                results.push(elem);
                                break;
                            }
                        }
                        if (outermost) {
                            dirruns = dirrunsUnique;
                            cachedruns = ++matcherCachedRuns;
                        }
                    }

                    // Track unmatched elements for set filters
                    if (bySet) {
                        // They will have gone through all possible matchers
                        if ((elem = !matcher && elem)) {
                            matchedCount--;
                        }

                        // Lengthen the array for every element, matched or not
                        if (seed) {
                            unmatched.push(elem);
                        }
                    }
                }

                // Apply set filters to unmatched elements
                // `i` starts as a string, so matchedCount would equal "00" if there are no elements
                matchedCount += i;
                if (bySet && i !== matchedCount) {
                    for (j = 0; (matcher = setMatchers[j]); j++) {
                        matcher(unmatched, setMatched, context, xml);
                    }

                    if (seed) {
                        // Reintegrate element matches to eliminate the need for sorting
                        if (matchedCount > 0) {
                            while (i--) {
                                if (!(unmatched[i] || setMatched[i])) {
                                    setMatched[i] = pop.call(results);
                                }
                            }
                        }

                        // Discard index placeholder values to get only actual matches
                        setMatched = condense(setMatched);
                    }

                    // Add matches to results
                    push.apply(results, setMatched);

                    // Seedless set matches succeeding multiple successful matchers stipulate sorting
                    if (outermost && !seed && setMatched.length > 0 &&
                        ( matchedCount + setMatchers.length ) > 1) {

                        Sizzle.uniqueSort(results);
                    }
                }

                // Override manipulation of globals by nested matchers
                if (outermost) {
                    dirruns = dirrunsUnique;
                    outermostContext = contextBackup;
                }

                return unmatched;
            };

        return bySet ?
            markFunction(superMatcher) :
            superMatcher;
    }

    compile = Sizzle.compile = function (selector, group /* Internal Use Only */) {
        var i,
            setMatchers = [],
            elementMatchers = [],
            cached = compilerCache[ expando ][ selector + " " ];

        if (!cached) {
            // Generate a function of recursive functions that can be used to check each element
            if (!group) {
                group = tokenize(selector);
            }
            i = group.length;
            while (i--) {
                cached = matcherFromTokens(group[i]);
                if (cached[ expando ]) {
                    setMatchers.push(cached);
                } else {
                    elementMatchers.push(cached);
                }
            }

            // Cache the compiled function
            cached = compilerCache(selector, matcherFromGroupMatchers(elementMatchers, setMatchers));
        }
        return cached;
    };

    function multipleContexts(selector, contexts, results) {
        var i = 0,
            len = contexts.length;
        for (; i < len; i++) {
            Sizzle(selector, contexts[i], results);
        }
        return results;
    }

    function select(selector, context, results, seed, xml) {
        var i, tokens, token, type, find,
            match = tokenize(selector);

        if (!seed) {
            // Try to minimize operations if there is only one group
            if (match.length === 1) {

                // Take a shortcut and set the context if the root selector is an ID
                tokens = match[0] = match[0].slice(0);
                if (tokens.length > 2 && (token = tokens[0]).type === "ID" &&
                    context.nodeType === 9 && !xml &&
                    Expr.relative[ tokens[1].type ]) {

                    context = Expr.find["ID"](token.matches[0].replace(rbackslash, ""), context, xml)[0];
                    if (!context) {
                        return results;
                    }

                    selector = selector.slice(tokens.shift().length);
                }

                // Fetch a seed set for right-to-left matching
                for (i = matchExpr["needsContext"].test(selector) ? -1 : tokens.length - 1; i >= 0; i--) {
                    token = tokens[i];

                    // Abort if we hit a combinator
                    if (Expr.relative[ (type = token.type) ]) {
                        break;
                    }
                    if ((find = Expr.find[ type ])) {
                        // Search, expanding context for leading sibling combinators
                        if ((seed = find(
                            token.matches[0].replace(rbackslash, ""),
                            rsibling.test(tokens[0].type) && context.parentNode || context,
                            xml
                        ))) {

                            // If seed is empty or no tokens remain, we can return early
                            tokens.splice(i, 1);
                            selector = seed.length && tokens.join("");
                            if (!selector) {
                                push.apply(results, slice.call(seed, 0));
                                return results;
                            }

                            break;
                        }
                    }
                }
            }
        }

        // Compile and execute a filtering function
        // Provide `match` to avoid retokenization if we modified the selector above
        compile(selector, match)(
            seed,
            context,
            xml,
            results,
            rsibling.test(selector)
        );
        return results;
    }

    if (document.querySelectorAll) {
        (function () {
            var disconnectedMatch,
                oldSelect = select,
                rescape = /'|\\/g,
                rattributeQuotes = /\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g,

            // qSa(:focus) reports false when true (Chrome 21), no need to also add to buggyMatches since matches checks buggyQSA
            // A support test would require too much code (would include document ready)
                rbuggyQSA = [ ":focus" ],

            // matchesSelector(:active) reports false when true (IE9/Opera 11.5)
            // A support test would require too much code (would include document ready)
            // just skip matchesSelector for :active
                rbuggyMatches = [ ":active" ],
                matches = docElem.matchesSelector ||
                    docElem.mozMatchesSelector ||
                    docElem.webkitMatchesSelector ||
                    docElem.oMatchesSelector ||
                    docElem.msMatchesSelector;

            // Build QSA regex
            // Regex strategy adopted from Diego Perini
            assert(function (div) {
                // Select is set to empty string on purpose
                // This is to test IE's treatment of not explictly
                // setting a boolean content attribute,
                // since its presence should be enough
                // http://bugs.jquery.com/ticket/12359
                div.innerHTML = "<select><option selected=''></option></select>";

                // IE8 - Some boolean attributes are not treated correctly
                if (!div.querySelectorAll("[selected]").length) {
                    rbuggyQSA.push("\\[" + whitespace + "*(?:checked|disabled|ismap|multiple|readonly|selected|value)");
                }

                // Webkit/Opera - :checked should return selected option elements
                // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
                // IE8 throws error here (do not put tests after this one)
                if (!div.querySelectorAll(":checked").length) {
                    rbuggyQSA.push(":checked");
                }
            });

            assert(function (div) {

                // Opera 10-12/IE9 - ^= $= *= and empty values
                // Should not select anything
                div.innerHTML = "<p test=''></p>";
                if (div.querySelectorAll("[test^='']").length) {
                    rbuggyQSA.push("[*^$]=" + whitespace + "*(?:\"\"|'')");
                }

                // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
                // IE8 throws error here (do not put tests after this one)
                div.innerHTML = "<input type='hidden'/>";
                if (!div.querySelectorAll(":enabled").length) {
                    rbuggyQSA.push(":enabled", ":disabled");
                }
            });

            // rbuggyQSA always contains :focus, so no need for a length check
            rbuggyQSA = /* rbuggyQSA.length && */ new RegExp(rbuggyQSA.join("|"));

            select = function (selector, context, results, seed, xml) {
                // Only use querySelectorAll when not filtering,
                // when this is not xml,
                // and when no QSA bugs apply
                if (!seed && !xml && !rbuggyQSA.test(selector)) {
                    var groups, i,
                        old = true,
                        nid = expando,
                        newContext = context,
                        newSelector = context.nodeType === 9 && selector;

                    // qSA works strangely on Element-rooted queries
                    // We can work around this by specifying an extra ID on the root
                    // and working up from there (Thanks to Andrew Dupont for the technique)
                    // IE 8 doesn't work on object elements
                    if (context.nodeType === 1 && context.nodeName.toLowerCase() !== "object") {
                        groups = tokenize(selector);

                        if ((old = context.getAttribute("id"))) {
                            nid = old.replace(rescape, "\\$&");
                        } else {
                            context.setAttribute("id", nid);
                        }
                        nid = "[id='" + nid + "'] ";

                        i = groups.length;
                        while (i--) {
                            groups[i] = nid + groups[i].join("");
                        }
                        newContext = rsibling.test(selector) && context.parentNode || context;
                        newSelector = groups.join(",");
                    }

                    if (newSelector) {
                        try {
                            push.apply(results, slice.call(newContext.querySelectorAll(
                                newSelector
                            ), 0));
                            return results;
                        } catch (qsaError) {
                        } finally {
                            if (!old) {
                                context.removeAttribute("id");
                            }
                        }
                    }
                }

                return oldSelect(selector, context, results, seed, xml);
            };

            if (matches) {
                assert(function (div) {
                    // Check to see if it's possible to do matchesSelector
                    // on a disconnected node (IE 9)
                    disconnectedMatch = matches.call(div, "div");

                    // This should fail with an exception
                    // Gecko does not error, returns false instead
                    try {
                        matches.call(div, "[test!='']:sizzle");
                        rbuggyMatches.push("!=", pseudos);
                    } catch (e) {
                    }
                });

                // rbuggyMatches always contains :active and :focus, so no need for a length check
                rbuggyMatches = /* rbuggyMatches.length && */ new RegExp(rbuggyMatches.join("|"));

                Sizzle.matchesSelector = function (elem, expr) {
                    // Make sure that attribute selectors are quoted
                    expr = expr.replace(rattributeQuotes, "='$1']");

                    // rbuggyMatches always contains :active, so no need for an existence check
                    if (!isXML(elem) && !rbuggyMatches.test(expr) && !rbuggyQSA.test(expr)) {
                        try {
                            var ret = matches.call(elem, expr);

                            // IE 9's matchesSelector returns false on disconnected nodes
                            if (ret || disconnectedMatch ||
                                // As well, disconnected nodes are said to be in a document
                                // fragment in IE 9
                                elem.document && elem.document.nodeType !== 11) {
                                return ret;
                            }
                        } catch (e) {
                        }
                    }

                    return Sizzle(expr, null, null, [ elem ]).length > 0;
                };
            }
        })();
    }

// Deprecated
    Expr.pseudos["nth"] = Expr.pseudos["eq"];

// Easy API for creating new setFilters
    function setFilters() {
    }

    Expr.filters = setFilters.prototype = Expr.pseudos;
    Expr.setFilters = new setFilters();

// EXPOSE
    return Sizzle;
});

