asgn4/form.js XXXXXXXXXXfunction check() { XXXXXXXXXXvar message; XXXXXXXXXXvar name = document.forms["myForm"]["Name"].value; XXXXXXXXXXvar age = document.forms["myForm"]["Age"].value; XXXXXXXXXXvar...

1 answer below ยป
would it be possible to add some comments to the code here, I had these assignments done through you guys but need comments explaining what's going on.


asgn4/form.js function check() { var message; var name = document.forms["myForm"]["Name"].value; var age = document.forms["myForm"]["Age"].value; var address = document.forms["myForm"]["Address"].value; var phone = document.forms["myForm"]["Telephone"].value; var email = document.forms["myForm"]["Email"].value; var dvdRom = document.forms["myForm"]["DVD_ROM"].checked; var cardReader = document.forms["myForm"]["Card_Reader"].checked; var externalHDD = document.forms["myForm"]["ehd"].checked; var core6 = document.forms["myForm"]["6-core"].checked; var core8 = document.forms["myForm"]["8-core"].checked; var a1, a2, a3, a4, a5; if (dvdRom) { a1 = "DVD_ROM\n"; } else { a1 = ""; } if (cardReader) { a2 = "Card Reader\n"; } else { a2 = ""; } if (externalHDD) { a3 = "External Hard Drive\n"; } else { a3 = ""; } if (core6) { a4 = "2.6GHz 6-core"; } else { a4 = ""; } if (core8) { a5 = "2.4GHz 8-core 4.4 GHz"; } else { a5 = ""; } if (name == "" || age == "" || address == "" || phone == "" || email == "" || (!dvdRom && !cardReader && externalHDD) || (!core6 && !core8)) { alert("Please complete all of the form"); } else { const msg = `Thank you for your submission, ${name.split(" ")[0]}. Name:${name} Age:${age} Address:${address} Telephone:${phone} Email:${email} Your chosen processor speed is ${a4} ${a5}. With the following additional components: ${a1}${a2}${a3} `; alert(msg); } } asgn4/index.html Name: Age: Address: Telephone: Email: Tick all of the components you want include on your laptop: DVD_ROM Card Reader External Hard Drive Select the processor speed you requir: 2.6GHz 6-core 2.4GHz 8-core 4.4 GHz Hover your mouse over this paragraph to see jquery in action asgn4/jquery-3.5.1.js /*! * jQuery JavaScript Library v3.5.1 * https://jquery.com/ * * Includes Sizzle.js * https://sizzlejs.com/ * * Copyright JS Foundation and other contributors * Released under the MIT license * https://jquery.org/license * * Date: 2020-05-04T22:49Z */ ( function( global, factory ) { "use strict"; if ( typeof module === "object" && typeof module.exports === "object" ) { // For CommonJS and CommonJS-like environments where a proper `window` // is present, execute the factory and get jQuery. // For environments that do not have a `window` with a `document` // (such as Node.js), expose a factory as module.exports. // This accentuates the need for the creation of a real `window`. // e.g. var jQuery = require("jquery")(window); // See ticket #14549 for more info. module.exports = global.document ? factory( global, true ) : function( w ) { if ( !w.document ) { throw new Error( "jQuery requires a window with a document" ); } return factory( w ); }; } else { factory( global ); } // Pass this if window is not defined yet } )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) { // Edge <= 12="" -="" 13+,="" firefox=""><=18 -="" 45+,="" ie="" 10="" -="" 11,="" safari="" 5.1="" -="" 9+,="" ios="" 6="" -="" 9.1="" throw="" exceptions="" when="" non-strict="" code="" (e.g.,="" asp.net="" 4.5)="" accesses="" strict="" mode="" arguments.callee.caller="" (trac-13335).="" but="" as="" of="" jquery="" 3.0="" (2016),="" strict="" mode="" should="" be="" common="" enough="" that="" all="" such="" attempts="" are="" guarded="" in="" a="" try="" block.="" "use="" strict";="" var="" arr="[];" var="" getproto="Object.getPrototypeOf;" var="" slice="arr.slice;" var="" flat="arr.flat" function(="" array="" )="" {="" return="" arr.flat.call(="" array="" );="" }="" :="" function(="" array="" )="" {="" return="" arr.concat.apply(="" [],="" array="" );="" };="" var="" push="arr.push;" var="" indexof="arr.indexOf;" var="" class2type="{};" var="" tostring="class2type.toString;" var="" hasown="class2type.hasOwnProperty;" var="" fntostring="hasOwn.toString;" var="" objectfunctionstring="fnToString.call(" object="" );="" var="" support="{};" var="" isfunction="function" isfunction(="" obj="" )="" {="" support:="" chrome=""><=57, firefox=""><=52 in="" some="" browsers,="" typeof="" returns="" "function"="" for="" html="" elements="" (i.e.,="" `typeof="" document.createelement(="" "object"="" )="==" "function"`).="" we="" don't="" want="" to="" classify="" *any*="" dom="" node="" as="" a="" function.="" return="" typeof="" obj="==" "function"="" &&="" typeof="" obj.nodetype="" !="=" "number";="" };="" var="" iswindow="function" iswindow(="" obj="" )="" {="" return="" obj="" !="null" &&="" obj="==" obj.window;="" };="" var="" document="window.document;" var="" preservedscriptattributes="{" type:="" true,="" src:="" true,="" nonce:="" true,="" nomodule:="" true="" };="" function="" domeval(="" code,="" node,="" doc="" )="" {="" doc="doc" ||="" document;="" var="" i,="" val,="" script="doc.createElement(" "script"="" );="" script.text="code;" if="" (="" node="" )="" {="" for="" (="" i="" in="" preservedscriptattributes="" )="" {="" support:="" firefox="" 64+,="" edge="" 18+="" some="" browsers="" don't="" support="" the="" "nonce"="" property="" on="" scripts.="" on="" the="" other="" hand,="" just="" using="" `getattribute`="" is="" not="" enough="" as="" the="" `nonce`="" attribute="" is="" reset="" to="" an="" empty="" string="" whenever="" it="" becomes="" browsing-context="" connected.="" see="" https://github.com/whatwg/html/issues/2369="" see="" https://html.spec.whatwg.org/#nonce-attributes="" the="" `node.getattribute`="" check="" was="" added="" for="" the="" sake="" of="" `jquery.globaleval`="" so="" that="" it="" can="" fake="" a="" nonce-containing="" node="" via="" an="" object.="" val="node[" i="" ]="" ||="" node.getattribute="" &&="" node.getattribute(="" i="" );="" if="" (="" val="" )="" {="" script.setattribute(="" i,="" val="" );="" }="" }="" }="" doc.head.appendchild(="" script="" ).parentnode.removechild(="" script="" );="" }="" function="" totype(="" obj="" )="" {="" if="" (="" obj="=" null="" )="" {="" return="" obj="" +="" "";="" }="" support:="" android=""><=2.3 only (functionish regexp) return typeof obj === "object" || typeof obj === "function" ? class2type[ tostring.call( obj ) ] || "object" : typeof obj; } /* global symbol */ // defining this global in .eslintrc.json would create a danger of using the global // unguarded in another place, it seems safer to define global only for this module var version = "3.5.1", // define a local copy of jquery jquery = function( selector, context ) { // the jquery object is actually just the init constructor 'enhanced' // need init if jquery is called (just allow error to be thrown if not included) return new jquery.fn.init( selector, context ); }; jquery.fn = jquery.prototype = { // the current version of jquery being used jquery: version, constructor: jquery, // the default length of a jquery only="" (functionish="" regexp)="" return="" typeof="" obj="==" "object"="" ||="" typeof="" obj="==" "function"="" class2type[="" tostring.call(="" obj="" )="" ]="" ||="" "object"="" :="" typeof="" obj;="" }="" *="" global="" symbol="" */="" defining="" this="" global="" in="" .eslintrc.json="" would="" create="" a="" danger="" of="" using="" the="" global="" unguarded="" in="" another="" place,="" it="" seems="" safer="" to="" define="" global="" only="" for="" this="" module="" var="" version="3.5.1" ,="" define="" a="" local="" copy="" of="" jquery="" jquery="function(" selector,="" context="" )="" {="" the="" jquery="" object="" is="" actually="" just="" the="" init="" constructor="" 'enhanced'="" need="" init="" if="" jquery="" is="" called="" (just="" allow="" error="" to="" be="" thrown="" if="" not="" included)="" return="" new="" jquery.fn.init(="" selector,="" context="" );="" };="" jquery.fn="jQuery.prototype" =="" {="" the="" current="" version="" of="" jquery="" being="" used="" jquery:="" version,="" constructor:="" jquery,="" the="" default="" length="" of="" a="">
Answered Same DayNov 27, 2021

Answer To: asgn4/form.js XXXXXXXXXXfunction check() { XXXXXXXXXXvar message; XXXXXXXXXXvar name =...

Mohd answered on Nov 30 2021
143 Votes
solution/asgn4/form.js
// check function
function check() {
var message;
// getting each value from each field
var name = document.forms["myForm"]["Name"].value;
var age = document.forms["myForm"]["Age"].value;
var address = document.forms["myForm"]["Address"].value;
var phone = document.forms["myForm"]["Telephone"].value;
var email = document.forms["myForm"]["Email"].value;
// checking check boxes
var dvdRom = document.forms["myForm"]["DVD_ROM"].checked;
var cardReader = document.forms["myForm"]["Card_Reader"].checked;
var externalHDD = document.forms["myForm"]["ehd"].checked;
var core6 = document.forms["myForm"]["6-core"].checked;
var core8 = document.forms["myForm"]["8-core"].checked;
// checking logic for each check boxes
var a1, a2, a3, a4, a5;
if (dvdRom) {
a1 = "DVD_ROM\n";
} else {
a1 = "";
}
if (cardReader) {
a2 = "Card Reader\n";
} else {
a2 = "";
}
if (externalHDD) {
a3 = "External Hard Drive\n";
} else {
a3 = "";
}
if (core6) {
a4 = "2.6GHz 6-core";
} else {
a4 = "";
}
if (core8) {
a5 = "2.4GHz 8-core 4.4 GHz";
} else {
a5 = "";
}
// if any field is empty show alert message
if (
name == "" ||
age == "" ||
address == "" ||
phone == "" ||
email == "" ||
(!dvdRom && !cardReader && externalHDD) ||
(!core6 && !core8)
) {
alert("Please complete all of the form");
}
// else showing result in alert with appropriate answer
else {
const msg = `Thank you for your submission, ${name.split(" ")[0]}.
Name:${name}
Age:${age}
Address:${address}
Telephone:${phone}
Email:${email}
Your chosen processor speed is ${a4} ${a5}.
With the following additional components:
${a1}${a2}${a3}
`;
alert(msg);
}
}
solution/asgn4/index.html



Name:

Age:

Address:

Telephone:

Email:

Tick all of the components you want include on your laptop:
DVD_ROM

Card Reader

External Hard Drive

Select the processor speed you requir:
2.6GHz 6-core
2.4GHz 8-core 4.4 GHz




Hover your mouse over this paragraph to see jquery in action

solution/asgn4/jquery-3.5.1.js
/*!
* jQuery JavaScript Library v3.5.1
* https://jquery.com/
*
* Includes Sizzle.js
* https://sizzlejs.com/
*
* Copyright JS Foundation and other contributors
* Released under the MIT license
* https://jquery.org/license
*
* Date: 2020-05-04T22:49Z
*/
( function( global, factory ) {
    "use strict";
    if ( typeof module === "object" && typeof module.exports === "object" ) {
        // For CommonJS and CommonJS-like environments where a proper `window`
        // is present, execute the factory and get jQuery.
        // For environments that do not have a `window` with a `document`
        // (such as Node.js), expose a factory as module.exports.
        // This accentuates the need for the creation of a real `window`.
        // e.g. var jQuery = require("jquery")(window);
        // See ticket #14549 for more info.
        module.exports = global.document ?
            factory( global, true ) :
            function( w ) {
                if ( !w.document ) {
                    throw new Error( "jQuery requires a window with a document" );
                }
                return factory( w );
            };
    } else {
        factory( global );
    }
// Pass this if window is not defined yet
} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) {
// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1
// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode
// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common
// enough that all such attempts are guarded in a try block.
"use strict";
var arr = [];
var getProto = Object.getPrototypeOf;
var slice = arr.slice;
var flat = arr.flat ? function( array ) {
    return arr.flat.call( array );
} : function( array ) {
    return arr.concat.apply( [], array );
};
var push = arr.push;
var indexOf = arr.indexOf;
var class2type = {};
var toString = class2type.toString;
var hasOwn = class2type.hasOwnProperty;
var fnToString = hasOwn.toString;
var ObjectFunctionString = fnToString.call( Object );
var support = {};
var isFunction = function isFunction( obj ) {
// Support: Chrome <=57, Firefox <=52
// In some browsers, typeof returns "function" for HTML elements
// (i.e., `typeof document.createElement( "object" ) === "function"`).
// We don't want to classify *any* DOM node as a function.
return typeof obj === "function" && typeof obj.nodeType !== "number";
};
var isWindow = function isWindow( obj ) {
        return obj != null && obj === obj.window;
    };
var document = window.document;
    var preservedScriptAttributes = {
        type: true,
        src: true,
        nonce: true,
        noModule: true
    };
    function DOMEval( code, node, doc ) {
        doc = doc || document;
        var i, val,
            script = doc.createElement( "script" );
        script.text = code;
        if ( node ) {
            for ( i in preservedScriptAttributes ) {
                // Support: Firefox 64+, Edge 18+
                // Some browsers don't support the "nonce" property on scripts.
                // On the other hand, just using `getAttribute` is not enough as
                // the `nonce` attribute is reset to an empty string whenever it
                // becomes browsing-context connected.
                // See https://github.com/whatwg/html/issues/2369
                // See https://html.spec.whatwg.org/#nonce-attributes
                // The `node.getAttribute` check was added for the sake of
                // `jQuery.globalEval` so that it can fake a nonce-containing node
                // via an object.
                val = node[ i ] || node.getAttribute && node.getAttribute( i );
                if ( val ) {
                    script.setAttribute( i, val );
                }
            }
        }
        doc.head.appendChild( script ).parentNode.removeChild( script );
    }
function toType( obj ) {
    if ( obj == null ) {
        return obj + "";
    }
    // Support: Android <=2.3 only (functionish RegExp)
    return typeof obj === "object" || typeof obj === "function" ?
        class2type[ toString.call( obj ) ] || "object" :
        typeof obj;
}
/* global Symbol */
// Defining this global in .eslintrc.json would create a danger of using the global
// unguarded in another place, it seems safer to define global only for this module
var
    version = "3.5.1",
    // Define a local copy of jQuery
    jQuery = function( selector, context ) {
        // The jQuery object is actually just the init constructor 'enhanced'
        // Need init if jQuery is called (just allow error to be thrown if not included)
        return new jQuery.fn.init( selector, context );
    };
jQuery.fn = jQuery.prototype = {
    // The current version of jQuery being used
    jquery: version,
    constructor: jQuery,
    // The default length of a jQuery object is 0
    length: 0,
    toArray: function() {
        return slice.call( this );
    },
    // Get the Nth element in the matched element set OR
    // Get the whole matched element set as a clean array
    get: function( num ) {
        // Return all the elements in a clean array
        if ( num == null ) {
            return slice.call( this );
        }
        // Return just the one element from the set
        return num < 0 ? this[ num + this.length ] : this[ num ];
    },
    // Take an array of elements and push it onto the stack
    // (returning the new matched element set)
    pushStack: function( elems ) {
        // Build a new jQuery matched element set
        var ret = jQuery.merge( this.constructor(), elems );
        // Add the old object onto the stack (as a reference)
        ret.prevObject = this;
        // Return the newly-formed element set
        return ret;
    },
    // Execute a callback for every element in the matched set.
    each: function( callback ) {
        return jQuery.each( this, callback );
    },
    map: function( callback ) {
        return this.pushStack( jQuery.map( this, function( elem, i ) {
            return callback.call( elem, i, elem );
        } ) );
    },
    slice: function() {
        return this.pushStack( slice.apply( this, arguments ) );
    },
    first: function() {
        return this.eq( 0 );
    },
    last: function() {
        return this.eq( -1 );
    },
    even: function() {
        return this.pushStack( jQuery.grep( this, function( _elem, i ) {
            return ( i + 1 ) % 2;
        } ) );
    },
    odd: function() {
        return this.pushStack( jQuery.grep( this, function( _elem, i ) {
            return i % 2;
        } ) );
    },
    eq: function( i ) {
        var len = this.length,
            j = +i + ( i < 0 ? len : 0 );
        return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] );
    },
    end: function() {
        return this.prevObject || this.constructor();
    },
    // For internal use only.
    // Behaves like an Array's method, not like a jQuery method.
    push: push,
    sort: arr.sort,
    splice: arr.splice
};
jQuery.extend = jQuery.fn.extend = function() {
    var options, name, src, copy, copyIsArray, clone,
        target = arguments[ 0 ] || {},
        i = 1,
        length = arguments.length,
        deep = false;
    // Handle a deep copy situation
    if ( typeof target === "boolean" ) {
        deep = target;
        // Skip the boolean and the target
        target = arguments[ i ] || {};
        i++;
    }
    // Handle case when target is a string or something (possible in deep copy)
    if ( typeof target !== "object" && !isFunction( target ) ) {
        target = {};
    }
    // Extend jQuery itself if only one argument is passed
    if ( i === length ) {
        target = this;
        i--;
    }
    for ( ; i < length; i++ ) {
        // Only deal with non-null/undefined values
        if ( ( options = arguments[ i ] ) != null ) {
            // Extend the base object
            for ( name in options ) {
                copy = options[ name ];
                // Prevent Object.prototype pollution
                // Prevent never-ending loop
                if ( name === "__proto__" || target === copy ) {
                    continue;
                }
                // Recurse if we're merging plain objects or arrays
                if ( deep && copy && ( jQuery.isPlainObject( copy ) ||
                    ( copyIsArray = Array.isArray( copy ) ) ) ) {
                    src = target[ name ];
                    // Ensure proper type for the source value
                    if ( copyIsArray && !Array.isArray( src ) ) {
                        clone = [];
                    } else if ( !copyIsArray && !jQuery.isPlainObject( src ) ) {
                        clone = {};
                    } else {
                        clone = src;
                    }
                    copyIsArray = false;
                    // Never move original objects, clone them
                    target[ name ] = jQuery.extend( deep, clone, copy );
                // Don't bring in undefined values
                } else if ( copy !== undefined ) {
                    target[ name ] = copy;
                }
            }
        }
    }
    // Return the modified object
    return target;
};
jQuery.extend( {
    // Unique for each copy of jQuery on the page
    expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ),
    // Assume jQuery is ready without the ready module
    isReady: true,
    error: function( msg ) {
        throw new Error( msg );
    },
    noop: function() {},
    isPlainObject: function( obj ) {
        var proto, Ctor;
        // Detect obvious negatives
        // Use toString instead of jQuery.type to catch host objects
        if ( !obj || toString.call( obj ) !== "[object Object]" ) {
            return false;
        }
        proto = getProto( obj );
        // Objects with no prototype (e.g., `Object.create( null )`) are plain
        if ( !proto ) {
            return true;
        }
        // Objects with prototype are plain iff they were constructed by a global Object function
        Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor;
        return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString;
    },
    isEmptyObject: function( obj ) {
        var name;
        for ( name in obj ) {
            return false;
        }
        return true;
    },
    // Evaluates a script in a provided context; falls back to the global one
    // if not specified.
    globalEval: function( code, options, doc ) {
        DOMEval( code, { nonce: options && options.nonce }, doc );
    },
    each: function( obj, callback ) {
        var length, i = 0;
        if ( isArrayLike( obj ) ) {
            length = obj.length;
            for ( ; i < length; i++ ) {
                if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {
                    break;
                }
            }
        } else {
            for ( i in obj ) {
                if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {
                    break;
                }
            }
        }
        return obj;
    },
    // results is for internal usage only
    makeArray: function( arr, results ) {
        var ret = results || [];
        if ( arr != null ) {
            if ( isArrayLike( Object( arr ) ) ) {
                jQuery.merge( ret,
                    typeof arr === "string" ?
                    [ arr ] : arr
                );
            } else {
                push.call( ret, arr );
            }
        }
        return ret;
    },
    inArray: function( elem, arr, i ) {
        return arr == null ? -1 : indexOf.call( arr, elem, i );
    },
    // Support: Android <=4.0 only, PhantomJS 1 only
    // push.apply(_, arraylike) throws on ancient WebKit
    merge: function( first, second ) {
        var len = +second.length,
            j = 0,
            i = first.length;
        for ( ; j < len; j++ ) {
            first[ i++ ] = second[ j ];
        }
        first.length = i;
        return first;
    },
    grep: function( elems, callback, invert ) {
        var callbackInverse,
            matches = [],
            i = 0,
            length = elems.length,
            callbackExpect = !invert;
        // Go through the array, only saving the items
        // that pass the validator function
        for ( ; i < length; i++ ) {
            callbackInverse = !callback( elems[ i ], i );
            if ( callbackInverse !== callbackExpect ) {
                matches.push( elems[ i ] );
            }
        }
        return matches;
    },
    // arg is for internal usage only
    map: function( elems, callback, arg ) {
        var length, value,
            i = 0,
            ret = [];
        // Go through the array, translating each of the items to their new values
        if ( isArrayLike( elems ) ) {
            length = elems.length;
            for ( ; i < length; i++ ) {
                value = callback( elems[ i ], i, arg );
                if ( value != null ) {
                    ret.push( value );
                }
            }
        // Go through every key on the object,
        } else {
            for ( i in elems ) {
                value = callback( elems[ i ], i, arg );
                if ( value != null ) {
                    ret.push( value );
                }
            }
        }
        // Flatten any nested arrays
        return flat( ret );
    },
    // A global GUID counter for objects
    guid: 1,
    // jQuery.support is not used in Core but other projects attach their
    // properties to it so it needs to exist.
    support: support
} );
if ( typeof Symbol === "function" ) {
    jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ];
}
// Populate the class2type map
jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ),
function( _i, name ) {
    class2type[ "[object " + name + "]" ] = name.toLowerCase();
} );
function isArrayLike( obj ) {
    // Support: real iOS 8.2 only (not reproducible in simulator)
    // `in` check used to prevent JIT error (gh-2145)
    // hasOwn isn't used here due to false negatives
    // regarding Nodelist length in IE
    var length = !!obj && "length" in obj && obj.length,
        type = toType( obj );
    if ( isFunction( obj ) || isWindow( obj ) ) {
        return false;
    }
    return type === "array" || length === 0 ||
        typeof length === "number" && length > 0 && ( length - 1 ) in obj;
}
var Sizzle =
/*!
* Sizzle CSS Selector Engine v2.3.5
* https://sizzlejs.com/
*
* Copyright JS Foundation and other contributors
* Released under the MIT license
* https://js.foundation/
*
* Date: 2020-03-14
*/
( function( window ) {
var i,
    support,
    Expr,
    getText,
    isXML,
    tokenize,
    compile,
    select,
    outermostContext,
    sortInput,
    hasDuplicate,
    // Local document vars
    setDocument,
    document,
    docElem,
    documentIsHTML,
    rbuggyQSA,
    rbuggyMatches,
    matches,
    contains,
    // Instance-specific data
    expando = "sizzle" + 1 * new Date(),
    preferredDoc = window.document,
    dirruns = 0,
    done = 0,
    classCache = createCache(),
    tokenCache = createCache(),
    compilerCache = createCache(),
    nonnativeSelectorCache = createCache(),
    sortOrder = function( a, b ) {
        if ( a === b ) {
            hasDuplicate = true;
        }
        return 0;
    },
    // Instance methods
    hasOwn = ( {} ).hasOwnProperty,
    arr = [],
    pop = arr.pop,
    pushNative = arr.push,
    push = arr.push,
    slice = arr.slice,
    // Use a stripped-down indexOf as it's faster than native
    // https://jsperf.com/thor-indexof-vs-for/5
    indexOf = function( list, elem ) {
        var i = 0,
            len = list.length;
        for ( ; i < len; i++ ) {
            if ( list[ i ] === elem ) {
                return i;
            }
        }
        return -1;
    },
    booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|" +
        "ismap|loop|multiple|open|readonly|required|scoped",
    // Regular expressions
    // http://www.w3.org/TR/css3-selectors/#whitespace
    whitespace = "[\\x20\\t\\r\\n\\f]",
    // https://www.w3.org/TR/css-syntax-3/#ident-token-diagram
    identifier = "(?:\\\\[\\da-fA-F]{1,6}" + whitespace +
        "?|\\\\[^\\r\\n\\f]|[\\w-]|[^\0-\\x7f])+",
    // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors
    attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace +
        // Operator (capture 2)
        "*([*^$|!~]?=)" + whitespace +
        // "Attribute values must be CSS identifiers [capture 5]
        // or strings [capture 3 or capture 4]"
        "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" +
        whitespace + "*\\]",
    pseudos = ":(" + identifier + ")(?:\\((" +
        // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:
        // 1. quoted (capture 3; capture 4 or capture 5)
        "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" +
        // 2. simple (capture 6)
        "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" +
        // 3. anything else (capture 2)
        ".*" +
        ")\\)|)",
    // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
    rwhitespace = new RegExp( whitespace + "+", "g" ),
    rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" +
        whitespace + "+$", "g" ),
    rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
    rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace +
        "*" ),
    rdescend = new RegExp( whitespace + "|>" ),
    rpseudo = new RegExp( pseudos ),
    ridentifier = new RegExp( "^" + identifier + "$" ),
    matchExpr = {
        "ID": new RegExp( "^#(" + identifier + ")" ),
        "CLASS": new RegExp( "^\\.(" + identifier + ")" ),
        "TAG": new RegExp( "^(" + identifier + "|[*])" ),
        "ATTR": new RegExp( "^" + attributes ),
        "PSEUDO": new RegExp( "^" + pseudos ),
        "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" +
            whitespace + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" +
            whitespace + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
        "bool": new RegExp( "^(?:" + booleans + ")$", "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" )
    },
    rhtml = /HTML$/i,
    rinputs = /^(?:input|select|textarea|button)$/i,
    rheader = /^h\d$/i,
    rnative = /^[^{]+\{\s*\[native \w/,
    // Easily-parseable/retrievable ID or TAG or CLASS selectors
    rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
    rsibling = /[+~]/,
    // CSS escapes
    // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
    runescape = new RegExp( "\\\\[\\da-fA-F]{1,6}" + whitespace + "?|\\\\([^\\r\\n\\f])", "g" ),
    funescape = function( escape, nonHex ) {
        var high = "0x" + escape.slice( 1 ) - 0x10000;
        return nonHex ?
            // Strip the backslash prefix from a non-hex escape sequence
            nonHex :
            // Replace a hexadecimal escape sequence with the encoded Unicode code point
            // Support: IE <=11+
            // For values outside the Basic Multilingual Plane (BMP), manually construct a
            // surrogate pair
            high < 0 ?
                String.fromCharCode( high + 0x10000 ) :
                String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
    },
    // CSS string/identifier serialization
    // https://drafts.csswg.org/cssom/#common-serializing-idioms
    rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,
    fcssescape = function( ch, asCodePoint ) {
        if ( asCodePoint ) {
            // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER
            if ( ch === "\0" ) {
                return "\uFFFD";
            }
            // Control characters and (dependent upon position) numbers get escaped as code points
            return ch.slice( 0, -1 ) + "\\" +
                ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " ";
        }
        // Other potentially-special ASCII characters get backslash-escaped
        return "\\" + ch;
    },
    // Used for iframes
    // See setDocument()
    // Removing the function wrapper causes a "Permission Denied"
    // error in IE
    unloadHandler = function() {
        setDocument();
    },
    inDisabledFieldset = addCombinator(
        function( elem ) {
            return elem.disabled === true && elem.nodeName.toLowerCase() === "fieldset";
        },
        { dir: "parentNode", next: "legend" }
    );
// Optimize for push.apply( _, NodeList )
try {
    push.apply(
        ( arr = slice.call( preferredDoc.childNodes ) ),
        preferredDoc.childNodes
    );
    // Support: Android<4.0
    // Detect silently failing push.apply
    // eslint-disable-next-line no-unused-expressions
    arr[ preferredDoc.childNodes.length ].nodeType;
} catch ( e ) {
    push = { apply: arr.length ?
        // Leverage slice if possible
        function( target, els ) {
            pushNative.apply( target, slice.call( els ) );
        } :
        // Support: IE<9
        // Otherwise append directly
        function( target, els ) {
            var j = target.length,
                i = 0;
            // Can't trust NodeList.length
            while ( ( target[ j++ ] = els[ i++ ] ) ) {}
            target.length = j - 1;
        }
    };
}
function Sizzle( selector, context, results, seed ) {
    var m, i, elem, nid, match, groups, newSelector,
        newContext = context && context.ownerDocument,
        // nodeType defaults to 9, since context defaults to document
        nodeType = context ? context.nodeType : 9;
    results = results || [];
    // Return early from calls with invalid selector or context
    if ( typeof selector !== "string" || !selector ||
        nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {
        return results;
    }
    // Try to shortcut find operations (as opposed to filters) in HTML documents
    if ( !seed ) {
        setDocument( context );
        context = context || document;
        if ( documentIsHTML ) {
            // If the selector is sufficiently simple, try using a "get*By*" DOM method
            // (excepting DocumentFragment context, where the methods don't exist)
            if ( nodeType !== 11 && ( match = rquickExpr.exec( selector ) ) ) {
                // ID selector
                if ( ( m = match[ 1 ] ) ) {
                    // Document context
                    if ( nodeType === 9 ) {
                        if ( ( elem = context.getElementById( m ) ) ) {
                            // Support: IE, Opera, Webkit
                            // TODO: identify versions
                            // getElementById can match elements by name instead of ID
                            if ( elem.id === m ) {
                                results.push( elem );
                                return results;
                            }
                        } else {
                            return results;
                        }
                    // Element context
                    } else {
                        // Support: IE, Opera, Webkit
                        // TODO: identify versions
                        // getElementById can match elements by name instead of ID
                        if ( newContext && ( elem = newContext.getElementById( m ) ) &&
                            contains( context, elem ) &&
                            elem.id === m ) {
                            results.push( elem );
                            return results;
                        }
                    }
                // Type selector
                } else if ( match[ 2 ] ) {
                    push.apply( results, context.getElementsByTagName( selector ) );
                    return results;
                // Class selector
                } else if ( ( m = match[ 3 ] ) && support.getElementsByClassName &&
                    context.getElementsByClassName ) {
                    push.apply( results, context.getElementsByClassName( m ) );
                    return results;
                }
            }
            // Take advantage of querySelectorAll
            if ( support.qsa &&
                !nonnativeSelectorCache[ selector + " " ] &&
                ( !rbuggyQSA || !rbuggyQSA.test( selector ) ) &&
                // Support: IE 8 only
                // Exclude object elements
                ( nodeType !== 1 || context.nodeName.toLowerCase() !== "object" ) ) {
                newSelector = selector;
                newContext = context;
                // qSA considers elements outside a scoping root when evaluating child or
                // descendant combinators, which is not what we want.
                // In such cases, we work around the behavior by prefixing every selector in the
                // list with an ID selector referencing the scope context.
                // The technique has to be used as well when a leading combinator is used
                // as such selectors are not recognized by querySelectorAll.
                // Thanks to Andrew Dupont for this technique.
                if ( nodeType === 1 &&
                    ( rdescend.test( selector ) || rcombinators.test( selector ) ) ) {
                    // Expand context for sibling selectors
                    newContext = rsibling.test( selector ) && testContext( context.parentNode ) ||
                        context;
                    // We can use :scope instead of the ID hack if the browser
                    // supports it & if we're not changing the context.
                    if ( newContext !== context || !support.scope ) {
                        // Capture the context ID, setting it first if necessary
                        if ( ( nid = context.getAttribute( "id" ) ) ) {
                            nid = nid.replace( rcssescape, fcssescape );
                        } else {
                            context.setAttribute( "id", ( nid = expando ) );
                        }
                    }
                    // Prefix every selector in the list
                    groups = tokenize( selector );
                    i = groups.length;
                    while ( i-- ) {
                        groups[ i ] = ( nid ? "#" + nid : ":scope" ) + " " +
                            toSelector( groups[ i ] );
                    }
                    newSelector = groups.join( "," );
                }
                try {
                    push.apply( results,
                        newContext.querySelectorAll( newSelector )
                    );
                    return results;
                } catch ( qsaError ) {
                    nonnativeSelectorCache( selector, true );
                } finally {
                    if ( nid === expando ) {
                        context.removeAttribute( "id" );
                    }
                }
            }
        }
    }
    // All others
    return select( selector.replace( rtrim, "$1" ), context, results, seed );
}
/**
* Create key-value caches of limited size
* @returns {function(string, object)} Returns the Object data after storing it on itself with
*    property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
*    deleting the oldest entry
*/
function createCache() {
    var keys = [];
    function cache( key, value ) {
        // Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
        if ( keys.push( key + " " ) > Expr.cacheLength ) {
            // Only keep the most recent entries
            delete cache[ keys.shift() ];
        }
        return ( cache[ key + " " ] = value );
    }
    return cache;
}
/**
* Mark a function for special use by Sizzle
* @param {Function} fn The function to mark
*/
function markFunction( fn ) {
    fn[ expando ] = true;
    return fn;
}
/**
* Support testing using an element
* @param {Function} fn Passed the created element and returns a boolean result
*/
function assert( fn ) {
    var el = document.createElement( "fieldset" );
    try {
        return !!fn( el );
    } catch ( e ) {
        return false;
    } finally {
        // Remove from its parent by default
        if ( el.parentNode ) {
            el.parentNode.removeChild( el );
        }
        // release memory in IE
        el = null;
    }
}
/**
* Adds the same handler for all of the specified attrs
* @param {String} attrs Pipe-separated list of attributes
* @param {Function} handler The method that will be applied
*/
function addHandle( attrs, handler ) {
    var arr = attrs.split( "|" ),
        i = arr.length;
    while ( i-- ) {
        Expr.attrHandle[ arr[ i ] ] = handler;
    }
}
/**
* Checks document order of two siblings
* @param {Element} a
* @param {Element} b
* @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b
*/
function siblingCheck( a, b ) {
    var cur = b && a,
        diff = cur && a.nodeType === 1 && b.nodeType === 1 &&
            a.sourceIndex - b.sourceIndex;
    // Use IE sourceIndex if available on both nodes
    if ( diff ) {
        return diff;
    }
    // Check if b follows a
    if ( cur ) {
        while ( ( cur = cur.nextSibling ) ) {
            if ( cur === b ) {
                return -1;
            }
        }
    }
    return a ? 1 : -1;
}
/**
* Returns a function to use in pseudos for input types
* @param {String} type
*/
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
* @param {String} type
*/
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 :enabled/:disabled
* @param {Boolean} disabled true for :disabled; false for :enabled
*/
function createDisabledPseudo( disabled ) {
    // Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable
    return function( elem ) {
        // Only certain elements can match :enabled or :disabled
        // https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled
        // https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled
        if ( "form" in elem ) {
            // Check for inherited disabledness on relevant non-disabled elements:
            // * listed form-associated elements in a disabled fieldset
            // https://html.spec.whatwg.org/multipage/forms.html#category-listed
            // https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled
            // * option elements in a disabled optgroup
            // https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled
            // All such elements have a "form" property.
            if ( elem.parentNode && elem.disabled === false ) {
                // Option elements defer to a parent optgroup if present
                if ( "label" in elem ) {
                    if ( "label" in elem.parentNode ) {
                        return elem.parentNode.disabled === disabled;
                    } else {
                        return elem.disabled === disabled;
                    }
                }
                // Support: IE 6 - 11
                // Use the isDisabled shortcut property to check for disabled fieldset ancestors
                return elem.isDisabled === disabled ||
                    // Where there is no isDisabled, check manually
                    /* jshint -W018 */
                    elem.isDisabled !== !disabled &&
                    inDisabledFieldset( elem ) === disabled;
            }
            return elem.disabled === disabled;
        // Try to winnow out elements that can't be disabled before trusting the disabled property.
        // Some victims get caught in our net (label, legend, menu, track), but it shouldn't
        // even exist on them, let alone have a boolean value.
        } else if ( "label" in elem ) {
            return elem.disabled === disabled;
        }
        // Remaining elements are neither :enabled nor :disabled
        return false;
    };
}
/**
* Returns a function to use in pseudos for positionals
* @param {Function} fn
*/
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 ] );
                }
            }
        } );
    } );
}
/**
* Checks a node for validity as a Sizzle context
* @param {Element|Object=} context
* @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value
*/
function testContext( context ) {
    return context && typeof context.getElementsByTagName !== "undefined" && context;
}
// Expose support vars for convenience
support = Sizzle.support = {};
/**
* Detects XML nodes
* @param {Element|Object} elem An element or a document
* @returns {Boolean} True iff elem is a non-HTML XML node
*/
isXML = Sizzle.isXML = function( elem ) {
    var namespace = elem.namespaceURI,
        docElem = ( elem.ownerDocument || elem ).documentElement;
    // Support: IE <=8
    // Assume HTML when documentElement doesn't yet exist, such as inside loading iframes
    // https://bugs.jquery.com/ticket/4833
    return !rhtml.test( namespace || docElem && docElem.nodeName || "HTML" );
};
/**
* Sets document-related variables once based on the current document
* @param {Element|Object} [doc] An element or document object to use to set the document
* @returns {Object} Returns the current document
*/
setDocument = Sizzle.setDocument = function( node ) {
    var hasCompare, subWindow,
        doc = node ? node.ownerDocument || node : preferredDoc;
    // Return early if doc is invalid or already selected
    // Support: IE 11+, Edge 17 - 18+
    // IE/Edge sometimes throw a "Permission denied" error when strict-comparing
    // two documents; shallow comparisons work.
    // eslint-disable-next-line eqeqeq
    if ( doc == document || doc.nodeType !== 9 || !doc.documentElement ) {
        return document;
    }
    // Update global variables
    document = doc;
    docElem = document.documentElement;
    documentIsHTML = !isXML( document );
    // Support: IE 9 - 11+, Edge 12 - 18+
    // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936)
    // Support: IE 11+, Edge 17 - 18+
    // IE/Edge sometimes throw a "Permission denied" error when strict-comparing
    // two documents; shallow comparisons work.
    // eslint-disable-next-line eqeqeq
    if ( preferredDoc != document &&
        ( subWindow = document.defaultView ) && subWindow.top !== subWindow ) {
        // Support: IE 11, Edge
        if ( subWindow.addEventListener ) {
            subWindow.addEventListener( "unload", unloadHandler, false );
        // Support: IE 9 - 10 only
        } else if ( subWindow.attachEvent ) {
            subWindow.attachEvent( "onunload", unloadHandler );
        }
    }
    // Support: IE 8 - 11+, Edge 12 - 18+, Chrome <=16 - 25 only, Firefox <=3.6 - 31 only,
    // Safari 4 - 5 only, Opera <=11.6 - 12.x only
    // IE/Edge & older browsers don't support the :scope pseudo-class.
    // Support: Safari 6.0 only
    // Safari 6.0 supports :scope but it's an alias of :root there.
    support.scope = assert( function( el ) {
        docElem.appendChild( el ).appendChild( document.createElement( "div" ) );
        return typeof el.querySelectorAll !== "undefined" &&
            !el.querySelectorAll( ":scope fieldset div" ).length;
    } );
    /* Attributes
    ---------------------------------------------------------------------- */
    // Support: IE<8
    // Verify that getAttribute really returns attributes and not properties
    // (excepting IE8 booleans)
    support.attributes = assert( function( el ) {
        el.className = "i";
        return !el.getAttribute( "className" );
    } );
    /* getElement(s)By*
    ---------------------------------------------------------------------- */
    // Check if getElementsByTagName("*") returns only elements
    support.getElementsByTagName = assert( function( el ) {
        el.appendChild( document.createComment( "" ) );
        return !el.getElementsByTagName( "*" ).length;
    } );
    // Support: IE<9
    support.getElementsByClassName = rnative.test( document.getElementsByClassName );
    // Support: IE<10
    // Check if getElementById returns elements by name
    // The broken getElementById methods don't pick up programmatically-set names,
    // so use a roundabout getElementsByName test
    support.getById = assert( function( el ) {
        docElem.appendChild( el ).id = expando;
        return !document.getElementsByName || !document.getElementsByName( expando ).length;
    } );
    // ID filter and find
    if ( support.getById ) {
        Expr.filter[ "ID" ] = function( id ) {
            var attrId = id.replace( runescape, funescape );
            return function( elem ) {
                return elem.getAttribute( "id" ) === attrId;
            };
        };
        Expr.find[ "ID" ] = function( id, context ) {
            if ( typeof context.getElementById !== "undefined" && documentIsHTML ) {
                var elem = context.getElementById( id );
                return elem ? [ elem ] : [];
            }
        };
    } else {
        Expr.filter[ "ID" ] = function( id ) {
            var attrId = id.replace( runescape, funescape );
            return function( elem ) {
                var node = typeof elem.getAttributeNode !== "undefined" &&
                    elem.getAttributeNode( "id" );
                return node && node.value === attrId;
            };
        };
        // Support: IE 6 - 7 only
        // getElementById is not reliable as a find shortcut
        Expr.find[ "ID" ] = function( id, context ) {
            if ( typeof context.getElementById !== "undefined" && documentIsHTML ) {
                var node, i, elems,
                    elem = context.getElementById( id );
                if ( elem ) {
                    // Verify the id attribute
                    node = elem.getAttributeNode( "id" );
                    if ( node && node.value === id ) {
                        return [ elem ];
                    }
                    // Fall back on getElementsByName
                    elems = context.getElementsByName( id );
                    i = 0;
                    while ( ( elem = elems[ i++ ] ) ) {
                        node = elem.getAttributeNode( "id" );
                        if ( node && node.value === id ) {
                            return [ elem ];
                        }
                    }
                }
                return [];
            }
        };
    }
    // Tag
    Expr.find[ "TAG" ] = support.getElementsByTagName ?
        function( tag, context ) {
            if ( typeof context.getElementsByTagName !== "undefined" ) {
                return context.getElementsByTagName( tag );
            // DocumentFragment nodes don't have gEBTN
            } else if ( support.qsa ) {
                return context.querySelectorAll( tag );
            }
        } :
        function( tag, context ) {
            var elem,
                tmp = [],
                i = 0,
                // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too
                results = context.getElementsByTagName( tag );
            // Filter out possible comments
            if ( tag === "*" ) {
                while ( ( elem = results[ i++ ] ) ) {
                    if ( elem.nodeType === 1 ) {
                        tmp.push( elem );
                    }
                }
                return tmp;
            }
            return results;
        };
    // Class
    Expr.find[ "CLASS" ] = support.getElementsByClassName && function( className, context ) {
        if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) {
            return context.getElementsByClassName( className );
        }
    };
    /* QSA/matchesSelector
    ---------------------------------------------------------------------- */
    // QSA and matchesSelector support
    // matchesSelector(:active) reports false when true (IE9/Opera 11.5)
    rbuggyMatches = [];
    // qSa(:focus) reports false when true (Chrome 21)
    // We allow this because of a bug in IE8/9 that throws an error
    // whenever `document.activeElement` is accessed on an iframe
    // So, we allow :focus to pass through QSA all the time to avoid the IE error
    // See https://bugs.jquery.com/ticket/13378
    rbuggyQSA = [];
    if ( ( support.qsa = rnative.test( document.querySelectorAll ) ) ) {
        // Build QSA regex
        // Regex strategy adopted from Diego Perini
        assert( function( el ) {
            var input;
            // Select is set to empty string on purpose
            // This is to test IE's treatment of not explicitly
            // setting a boolean content attribute,
            // since its presence should be enough
            // https://bugs.jquery.com/ticket/12359
            docElem.appendChild( el ).innerHTML = "" +
                "";
            // Support: IE8, Opera 11-12.16
            // Nothing should be selected when empty strings follow ^= or $= or *=
            // The test attribute must be unknown in Opera but "safe" for WinRT
            // https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section
            if ( el.querySelectorAll( "[msallowcapture^='']" ).length ) {
                rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" );
            }
            // Support: IE8
            // Boolean attributes and "value" are not treated correctly
            if ( !el.querySelectorAll( "[selected]" ).length ) {
                rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" );
            }
            // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+
            if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) {
                rbuggyQSA.push( "~=" );
            }
            // Support: IE 11+, Edge 15 - 18+
            // IE 11/Edge don't find elements on a `[name='']` query in some cases.
            // Adding a temporary attribute to the document before the selection works
            // around the issue.
            // Interestingly, IE 10 & older don't seem to have the issue.
            input = document.createElement( "input" );
            input.setAttribute( "name", "" );
            el.appendChild( input );
            if ( !el.querySelectorAll( "[name='']" ).length ) {
                rbuggyQSA.push( "\\[" + whitespace + "*name" + whitespace + "*=" +
                    whitespace + "*(?:''|\"\")" );
            }
            // Webkit/Opera - :checked should return selected option elements
            // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
            // IE8 throws error here and will not see later tests
            if ( !el.querySelectorAll( ":checked" ).length ) {
                rbuggyQSA.push( ":checked" );
            }
            // Support: Safari 8+, iOS 8+
            // https://bugs.webkit.org/show_bug.cgi?id=136851
            // In-page `selector#id sibling-combinator selector` fails
            if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) {
                rbuggyQSA.push( ".#.+[+~]" );
            }
            // Support: Firefox <=3.6 - 5 only
            // Old Firefox doesn't throw on a badly-escaped identifier.
            el.querySelectorAll( "\\\f" );
            rbuggyQSA.push( "[\\r\\n\\f]" );
        } );
        assert( function( el ) {
            el.innerHTML = "" +
                "";
            // Support: Windows 8 Native Apps
            // The type and name attributes are restricted during .innerHTML assignment
            var input = document.createElement( "input" );
            input.setAttribute( "type", "hidden" );
            el.appendChild( input ).setAttribute( "name", "D" );
            // Support: IE8
            // Enforce case-sensitivity of name attribute
            if ( el.querySelectorAll( "[name=d]" ).length ) {
                rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" );
            }
            // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
            // IE8 throws error here and will not see later tests
            if ( el.querySelectorAll( ":enabled" ).length !== 2 ) {
                rbuggyQSA.push( ":enabled", ":disabled" );
            }
            // Support: IE9-11+
            // IE's :disabled selector does not pick up the children of disabled fieldsets
            docElem.appendChild( el ).disabled = true;
            if ( el.querySelectorAll( ":disabled" ).length !== 2 ) {
                rbuggyQSA.push( ":enabled", ":disabled" );
            }
            // Support: Opera 10 - 11 only
            // Opera 10-11 does not throw on post-comma invalid pseudos
            el.querySelectorAll( "*,:x" );
            rbuggyQSA.push( ",.*:" );
        } );
    }
    if ( ( support.matchesSelector = rnative.test( ( matches = docElem.matches ||
        docElem.webkitMatchesSelector ||
        docElem.mozMatchesSelector ||
        docElem.oMatchesSelector ||
        docElem.msMatchesSelector ) ) ) ) {
        assert( function( el ) {
            // Check to see if it's possible to do matchesSelector
            // on a disconnected node (IE 9)
            support.disconnectedMatch = matches.call( el, "*" );
            // This should fail with an exception
            // Gecko does not error, returns false instead
            matches.call( el, "[s!='']:x" );
            rbuggyMatches.push( "!=", pseudos );
        } );
    }
    rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join( "|" ) );
    rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join( "|" ) );
    /* Contains
    ---------------------------------------------------------------------- */
    hasCompare = rnative.test( docElem.compareDocumentPosition );
    // Element contains another
    // Purposefully self-exclusive
    // As in, an element does not contain itself
    contains = hasCompare || rnative.test( 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 ) :
                    a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
            ) );
        } :
        function( a, b ) {
            if ( b ) {
                while ( ( b = b.parentNode ) ) {
                    if ( b === a ) {
                        return true;
                    }
                }
            }
            return false;
        };
    /* Sorting
    ---------------------------------------------------------------------- */
    // Document order sorting
    sortOrder = hasCompare ?
    function( a, b ) {
        // Flag for duplicate removal
        if ( a === b ) {
            hasDuplicate = true;
            return 0;
        }
        // Sort on method existence if only one input has compareDocumentPosition
        var compare = !a.compareDocumentPosition - !b.compareDocumentPosition;
        if ( compare ) {
            return compare;
        }
        // Calculate position if both inputs belong to the same document
        // Support: IE 11+, Edge 17 - 18+
        // IE/Edge sometimes throw a "Permission denied" error when strict-comparing
        // two documents; shallow comparisons work.
        // eslint-disable-next-line eqeqeq
        compare = ( a.ownerDocument || a ) == ( b.ownerDocument || b ) ?
            a.compareDocumentPosition( b ) :
            // Otherwise we know they are disconnected
            1;
        // Disconnected nodes
        if ( compare & 1 ||
            ( !support.sortDetached && b.compareDocumentPosition( a ) === compare ) ) {
            // Choose the first element that is related to our preferred document
            // Support: IE 11+, Edge 17 - 18+
            // IE/Edge sometimes throw a "Permission denied" error when strict-comparing
            // two documents; shallow comparisons work.
            // eslint-disable-next-line eqeqeq
            if ( a == document || a.ownerDocument == preferredDoc &&
                contains( preferredDoc, a ) ) {
                return -1;
            }
            // Support: IE 11+, Edge 17 - 18+
            // IE/Edge sometimes throw a "Permission denied" error when strict-comparing
            // two documents; shallow comparisons work.
            // eslint-disable-next-line eqeqeq
            if ( b == document || b.ownerDocument == preferredDoc &&
                contains( preferredDoc, b ) ) {
                return 1;
            }
            // Maintain original order
            return sortInput ?
                ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
                0;
        }
        return compare & 4 ? -1 : 1;
    } :
    function( a, b ) {
        // Exit early if the nodes are identical
        if ( a === b ) {
            hasDuplicate = true;
            return 0;
        }
        var cur,
            i = 0,
            aup = a.parentNode,
            bup = b.parentNode,
            ap = [ a ],
            bp = [ b ];
        // Parentless nodes are either documents or disconnected
        if ( !aup || !bup ) {
            // Support: IE 11+, Edge 17 - 18+
            // IE/Edge sometimes throw a "Permission denied" error when strict-comparing
            // two documents; shallow comparisons work.
            /* eslint-disable eqeqeq */
            return a == document ? -1 :
                b == document ? 1 :
                /* eslint-enable eqeqeq */
                aup ? -1 :
                bup ? 1 :
                sortInput ?
                ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
                0;
        // If the nodes are siblings, we can do a quick check
        } else if ( aup === bup ) {
            return siblingCheck( a, b );
        }
        // Otherwise we need full lists of their ancestors for comparison
        cur = a;
        while ( ( cur = cur.parentNode ) ) {
            ap.unshift( cur );
        }
        cur = b;
        while ( ( cur = cur.parentNode ) ) {
            bp.unshift( cur );
        }
        // Walk down the tree looking for a discrepancy
        while ( ap[ i ] === bp[ i ] ) {
            i++;
        }
        return i ?
            // Do a sibling check if the nodes have a common ancestor
            siblingCheck( ap[ i ], bp[ i ] ) :
            // Otherwise nodes in our document sort first
            // Support: IE 11+, Edge 17 - 18+
            // IE/Edge sometimes throw a "Permission denied" error when strict-comparing
            // two documents; shallow comparisons work.
            /* eslint-disable eqeqeq */
            ap[ i ] == preferredDoc ? -1 :
            bp[ i ] == preferredDoc ? 1 :
            /* eslint-enable eqeqeq */
            0;
    };
    return document;
};
Sizzle.matches = function( expr, elements ) {
    return Sizzle( expr, null, null, elements );
};
Sizzle.matchesSelector = function( elem, expr ) {
    setDocument( elem );
    if ( support.matchesSelector && documentIsHTML &&
        !nonnativeSelectorCache[ expr + " " ] &&
        ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&
        ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) {
        try {
            var ret = matches.call( elem, expr );
            // IE 9's matchesSelector returns false on disconnected nodes
            if ( ret || support.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 ) {
            nonnativeSelectorCache( expr, true );
        }
    }
    return Sizzle( expr, document, null, [ elem ] ).length > 0;
};
Sizzle.contains = function( context, elem ) {
    // Set document vars if needed
    // Support: IE 11+, Edge 17 - 18+
    // IE/Edge sometimes throw a "Permission denied" error when strict-comparing
    // two documents; shallow comparisons work.
    // eslint-disable-next-line eqeqeq
    if ( ( context.ownerDocument || context ) != document ) {
        setDocument( context );
    }
    return contains( context, elem );
};
Sizzle.attr = function( elem, name ) {
    // Set document vars if needed
    // Support: IE 11+, Edge 17 - 18+
    // IE/Edge sometimes throw a "Permission denied" error when strict-comparing
    // two documents; shallow comparisons work.
    // eslint-disable-next-line eqeqeq
    if ( ( elem.ownerDocument || elem ) != document ) {
        setDocument( elem );
    }
    var fn = Expr.attrHandle[ name.toLowerCase() ],
        // Don't get fooled by Object.prototype properties (jQuery #13807)
        val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?
            fn( elem, name, !documentIsHTML ) :
            undefined;
    return val !== undefined ?
        val :
        support.attributes || !documentIsHTML ?
            elem.getAttribute( name ) :
            ( val = elem.getAttributeNode( name ) ) && val.specified ?
                val.value :
                null;
};
Sizzle.escape = function( sel ) {
    return ( sel + "" ).replace( rcssescape, fcssescape );
};
Sizzle.error = function( msg ) {
    throw new Error( "Syntax error, unrecognized expression: " + msg );
};
/**
* Document sorting and removing duplicates
* @param {ArrayLike} results
*/
Sizzle.uniqueSort = function( results ) {
    var elem,
        duplicates = [],
        j = 0,
        i = 0;
    // Unless we *know* we can detect duplicates, assume their presence
    hasDuplicate = !support.detectDuplicates;
    sortInput = !support.sortStable && results.slice( 0 );
    results.sort( sortOrder );
    if ( hasDuplicate ) {
        while ( ( elem = results[ i++ ] ) ) {
            if ( elem === results[ i ] ) {
                j = duplicates.push( i );
            }
        }
        while ( j-- ) {
            results.splice( duplicates[ j ], 1 );
        }
    }
    // Clear input after sorting to release objects
    // See https://github.com/jquery/sizzle/pull/225
    sortInput = null;
    return results;
};
/**
* 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 no nodeType, this is expected to be an array
        while ( ( node = elem[ i++ ] ) ) {
            // Do not traverse comment nodes
            ret += getText( node );
        }
    } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
        // Use textContent for elements
        // innerText usage removed for consistency of new lines (jQuery #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
    return ret;
};
Expr = Sizzle.selectors = {
    // Can be adjusted by the user
    cacheLength: 50,
    createPseudo: markFunction,
    match: matchExpr,
    attrHandle: {},
    find: {},
    relative: {
        ">": { dir: "parentNode", first: true },
        " ": { dir: "parentNode" },
        "+": { dir: "previousSibling", first: true },
        "~": { dir: "previousSibling" }
    },
    preFilter: {
        "ATTR": function( match ) {
            match[ 1 ] = match[ 1 ].replace( runescape, funescape );
            // Move the given value to match[3] whether quoted or unquoted
            match[ 3 ] = ( match[ 3 ] || match[ 4 ] ||
                match[ 5 ] || "" ).replace( runescape, funescape );
            if ( match[ 2 ] === "~=" ) {
                match[ 3 ] = " " + match[ 3 ] + " ";
            }
            return match.slice( 0, 4 );
        },
        "CHILD": function( match ) {
            /* matches from matchExpr["CHILD"]
                1 type (only|nth|...)
                2 what (child|of-type)
                3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
                4 xn-component of xn+y argument ([+-]?\d*n|)
                5 sign of xn-component
                6 x of xn-component
                7 sign of y-component
                8 y of y-component
            */
            match[ 1 ] = match[ 1 ].toLowerCase();
            if ( match[ 1 ].slice( 0, 3 ) === "nth" ) {
                // nth-* requires argument
                if ( !match[ 3 ] ) {
                    Sizzle.error( match[ 0 ] );
                }
                // numeric x and y parameters for Expr.filter.CHILD
                // remember that false/true cast respectively to 0/1
                match[ 4 ] = +( match[ 4 ] ?
                    match[ 5 ] + ( match[ 6 ] || 1 ) :
                    2 * ( match[ 3 ] === "even" || match[ 3 ] === "odd" ) );
                match[ 5 ] = +( ( match[ 7 ] + match[ 8 ] ) || match[ 3 ] === "odd" );
                // other types prohibit arguments
            } else if ( match[ 3 ] ) {
                Sizzle.error( match[ 0 ] );
            }
            return match;
        },
        "PSEUDO": function( match ) {
            var excess,
                unquoted = !match[ 6 ] && match[ 2 ];
            if ( matchExpr[ "CHILD" ].test( match[ 0 ] ) ) {
                return null;
            }
            // Accept quoted arguments as-is
            if ( match[ 3 ] ) {
                match[ 2 ] = match[ 4 ] || match[ 5 ] || "";
            // Strip excess characters from unquoted arguments
            } else if ( unquoted && 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
                match[ 0 ] = match[ 0 ].slice( 0, excess );
                match[ 2 ] = unquoted.slice( 0, excess );
            }
            // Return only captures needed by the pseudo filter method (type and argument)
            return match.slice( 0, 3 );
        }
    },
    filter: {
        "TAG": function( nodeNameSelector ) {
            var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();
            return nodeNameSelector === "*" ?
                function() {
                    return true;
                } :
                function( elem ) {
                    return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
                };
        },
        "CLASS": function( className ) {
            var pattern = classCache[ className + " " ];
            return pattern ||
                ( pattern = new RegExp( "(^|" + whitespace +
                    ")" + className + "(" + whitespace + "|$)" ) ) && classCache(
                        className, function( elem ) {
                            return pattern.test(
                                typeof elem.className === "string" && elem.className ||
                                typeof elem.getAttribute !== "undefined" &&
                                    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 += "";
                /* eslint-disable max-len */
                return operator === "=" ? result === check :
                    operator === "!=" ? result !== check :
                    operator === "^=" ? check && result.indexOf( check ) === 0 :
                    operator === "*=" ? check && result.indexOf( check ) > -1 :
                    operator === "$=" ? check && result.slice( -check.length ) === check :
                    operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 :
                    operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
                    false;
                /* eslint-enable max-len */
            };
        },
        "CHILD": function( type, what, _argument, first, last ) {
            var simple = type.slice( 0, 3 ) !== "nth",
                forward = type.slice( -4 ) !== "last",
                ofType = what === "of-type";
            return first === 1 && last === 0 ?
                // Shortcut for :nth-*(n)
                function( elem ) {
                    return !!elem.parentNode;
                } :
                function( elem, _context, xml ) {
                    var cache, uniqueCache, outerCache, node, nodeIndex, start,
                        dir = simple !== forward ? "nextSibling" : "previousSibling",
                        parent = elem.parentNode,
                        name = ofType && elem.nodeName.toLowerCase(),
                        useCache = !xml && !ofType,
                        diff = false;
                    if ( parent ) {
                        // :(first|last|only)-(child|of-type)
                        if ( simple ) {
                            while ( dir ) {
                                node = elem;
                                while ( ( node = node[ dir ] ) ) {
                                    if ( ofType ?
                                        node.nodeName.toLowerCase() === name :
                                        node.nodeType === 1 ) {
                                        return false;
                                    }
                                }
                                // Reverse direction for :only-* (if we haven't yet done so)
                                start = dir = type === "only" && !start && "nextSibling";
                            }
                            return true;
                        }
                        start = [ forward ? parent.firstChild : parent.lastChild ];
                        // non-xml :nth-child(...) stores cache data on `parent`
                        if ( forward && useCache ) {
                            // Seek `elem` from a previously-cached index
                            // ...in a gzip-friendly way
                            node = parent;
                            outerCache = node[ expando ] || ( node[ expando ] = {} );
                            // Support: IE <9 only
                            // Defend against cloned attroperties (jQuery gh-1709)
                            uniqueCache = outerCache[ node.uniqueID ] ||
                                ( outerCache[ node.uniqueID ] = {} );
                            cache = uniqueCache[ type ] || [];
                            nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];
                            diff = nodeIndex && cache[ 2 ];
                            node = nodeIndex && parent.childNodes[ nodeIndex ];
                            while ( ( node = ++nodeIndex && node && node[ dir ] ||
                                // Fallback to seeking `elem` from the start
                                ( diff = nodeIndex = 0 ) || start.pop() ) ) {
                                // When found, cache indexes on `parent` and break
                                if ( node.nodeType === 1 && ++diff && node === elem ) {
                                    uniqueCache[ type ] = [ dirruns, nodeIndex, diff ];
                                    break;
                                }
                            }
                        } else {
                            // Use previously-cached element index if available
                            if ( useCache ) {
                                // ...in a gzip-friendly way
                                node = elem;
                                outerCache = node[ expando ] || ( node[ expando ] = {} );
                                // Support: IE <9 only
                                // Defend against cloned attroperties (jQuery gh-1709)
                                uniqueCache = outerCache[ node.uniqueID ] ||
                                    ( outerCache[ node.uniqueID ] = {} );
                                cache = uniqueCache[ type ] || [];
                                nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];
                                diff = nodeIndex;
                            }
                            // xml :nth-child(...)
                            // or :nth-last-child(...) or :nth(-last)?-of-type(...)
                            if ( diff === false ) {
                                // Use the same loop as above to seek `elem` from the start
                                while ( ( node = ++nodeIndex && node && node[ dir ] ||
                                    ( diff = nodeIndex = 0 ) || start.pop() ) ) {
                                    if ( ( ofType ?
                                        node.nodeName.toLowerCase() === name :
                                        node.nodeType === 1 ) &&
                                        ++diff ) {
                                        // Cache the index of each encountered element
                                        if ( useCache ) {
                                            outerCache = node[ expando ] ||
                                                ( node[ expando ] = {} );
                                            // Support: IE <9 only
                                            // Defend against cloned attroperties (jQuery gh-1709)
                                            uniqueCache = outerCache[ node.uniqueID ] ||
                                                ( outerCache[ node.uniqueID ] = {} );
                                            uniqueCache[ type ] = [ dirruns, diff ];
                                        }
                                        if ( node === elem ) {
                                            break;
                                        }
                                    }
                                }
                            }
                        }
                        // Incorporate the offset, then check against cycle size
                        diff -= last;
                        return diff === first || ( diff % first === 0 && diff / first >= 0 );
                    }
                };
        },
        "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( seed, matched[ i ] );
                            seed[ idx ] = !( matches[ idx ] = matched[ i ] );
                        }
                    } ) :
                    function( elem ) {
                        return fn( elem, 0, args );
                    };
            }
            return fn;
        }
    },
    pseudos: {
        // Potentially complex 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 );
                    // Don't keep the element (issue #299)
                    input[ 0 ] = null;
                    return !results.pop();
                };
        } ),
        "has": markFunction( function( selector ) {
            return function( elem ) {
                return Sizzle( selector, elem ).length > 0;
            };
        } ),
        "contains": markFunction( function( text ) {
            text = text.replace( runescape, funescape );
            return function( elem ) {
                return ( elem.textContent || getText( elem ) ).indexOf( text ) > -1;
            };
        } ),
        // "Whether an element is represented by a :lang() selector
        // is based solely on the element's language value
        // being equal to the identifier C,
        // or beginning with the identifier C immediately followed by "-".
        // The matching of C against the element's language value is performed case-insensitively.
        // The identifier C does not have to be a valid language name."
        // http://www.w3.org/TR/selectors/#lang-pseudo
        "lang": markFunction( function( lang ) {
            // lang value must be a valid identifier
            if ( !ridentifier.test( lang || "" ) ) {
                Sizzle.error( "unsupported lang: " + lang );
            }
            lang = lang.replace( runescape, funescape ).toLowerCase();
            return function( elem ) {
                var elemLang;
                do {
                    if ( ( elemLang = documentIsHTML ?
                        elem.lang :
                        elem.getAttribute( "xml:lang" ) || elem.getAttribute( "lang" ) ) ) {
                        elemLang = elemLang.toLowerCase();
                        return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
                    }
                } while ( ( elem = elem.parentNode ) && elem.nodeType === 1 );
                return false;
            };
        } ),
        // Miscellaneous
        "target": function( elem ) {
            var hash = window.location && window.location.hash;
            return hash && hash.slice( 1 ) === elem.id;
        },
        "root": function( elem ) {
            return elem === docElem;
        },
        "focus": function( elem ) {
            return elem === document.activeElement &&
                ( !document.hasFocus || document.hasFocus() ) &&
                !!( elem.type || elem.href || ~elem.tabIndex );
        },
        // Boolean properties
        "enabled": createDisabledPseudo( false ),
        "disabled": createDisabledPseudo( 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 ) {
                // eslint-disable-next-line no-unused-expressions
                elem.parentNode.selectedIndex;
            }
            return elem.selected === true;
        },
        // Contents
        "empty": function( elem ) {
            // http://www.w3.org/TR/selectors/#empty-pseudo
            // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),
            // but not by others (comment: 8; processing instruction: 7; etc.)
            // nodeType < 6 works because attributes (2) do not appear as children
            for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
                if ( elem.nodeType < 6 ) {
                    return false;
                }
            }
            return true;
        },
        "parent": function( elem ) {
            return !Expr.pseudos[ "empty" ]( elem );
        },
        // Element/input types
        "header": function( elem ) {
            return rheader.test( elem.nodeName );
        },
        "input": function( elem ) {
            return rinputs.test( elem.nodeName );
        },
        "button": function( elem ) {
            var name = elem.nodeName.toLowerCase();
            return name === "input" && elem.type === "button" || name === "button";
        },
        "text": function( elem ) {
            var attr;
            return elem.nodeName.toLowerCase() === "input" &&
                elem.type === "text" &&
                // Support: IE<8
                // New HTML5 attribute values (e.g., "search") appear with elem.type === "text"
                ( ( attr = elem.getAttribute( "type" ) ) == null ||
                    attr.toLowerCase() === "text" );
        },
        // Position-in-collection
        "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 ) {
            var i = 0;
            for ( ; i < length; i += 2 ) {
                matchIndexes.push( i );
            }
            return matchIndexes;
        } ),
        "odd": createPositionalPseudo( function( matchIndexes, length ) {
            var i = 1;
            for ( ; i < length; i += 2 ) {
                matchIndexes.push( i );
            }
            return matchIndexes;
        } ),
        "lt": createPositionalPseudo( function( matchIndexes, length, argument ) {
            var i = argument < 0 ?
                argument + length :
                argument > length ?
                    length :
                    argument;
            for ( ; --i >= 0; ) {
                matchIndexes.push( i );
            }
            return matchIndexes;
        } ),
        "gt": createPositionalPseudo( function( matchIndexes, length, argument ) {
            var i = argument < 0 ? argument + length : argument;
            for ( ; ++i < length; ) {
                matchIndexes.push( i );
            }
            return matchIndexes;
        } )
    }
};
Expr.pseudos[ "nth" ] = Expr.pseudos[ "eq" ];
// Add button/input type pseudos
for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
    Expr.pseudos[ i ] = createInputPseudo( i );
}
for ( i in { submit: true, reset: true } ) {
    Expr.pseudos[ i ] = createButtonPseudo( i );
}
// Easy API for creating new setFilters
function setFilters() {}
setFilters.prototype = Expr.filters = Expr.pseudos;
Expr.setFilters = new setFilters();
tokenize = Sizzle.tokenize = function( selector, parseOnly ) {
    var matched, match, tokens, type,
        soFar, groups, preFilters,
        cached = tokenCache[ 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 ) ) ) {
            matched = match.shift();
            tokens.push( {
                value: matched,
                // Cast descendant combinators to space
                type: match[ 0 ].replace( rtrim, " " )
            } );
            soFar = soFar.slice( matched.length );
        }
        // Filters
        for ( type in Expr.filter ) {
            if ( ( match = matchExpr[ type ].exec( soFar ) ) && ( !preFilters[ type ] ||
                ( match = preFilters[ type ]( match ) ) ) ) {
                matched = match.shift();
                tokens.push( {
                    value: matched,
                    type: type,
                    matches: match
                } );
                soFar = soFar.slice( matched.length );
            }
        }
        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 toSelector( tokens ) {
    var i = 0,
        len = tokens.length,
        selector = "";
    for ( ; i < len; i++ ) {
        selector += tokens[ i ].value;
    }
    return selector;
}
function addCombinator( matcher, combinator, base ) {
    var dir = combinator.dir,
        skip = combinator.next,
        key = skip || dir,
        checkNonElements = base && key === "parentNode",
        doneName = done++;
    return combinator.first ?
        // Check against closest ancestor/preceding element
        function( elem, context, xml ) {
            while ( ( elem = elem[ dir ] ) ) {
                if ( elem.nodeType === 1 || checkNonElements ) {
                    return matcher( elem, context, xml );
                }
            }
            return false;
        } :
        // Check against all ancestor/preceding elements
        function( elem, context, xml ) {
            var oldCache, uniqueCache, outerCache,
                newCache = [ dirruns, doneName ];
            // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching
            if ( xml ) {
                while ( ( elem = elem[ dir ] ) ) {
                    if ( elem.nodeType === 1 || checkNonElements ) {
                        if ( matcher( elem, context, xml ) ) {
                            return true;
                        }
                    }
                }
            } else {
                while ( ( elem = elem[ dir ] ) ) {
                    if ( elem.nodeType === 1 || checkNonElements ) {
                        outerCache = elem[ expando ] || ( elem[ expando ] = {} );
                        // Support: IE <9 only
                        // Defend against cloned attroperties (jQuery gh-1709)
                        uniqueCache = outerCache[ elem.uniqueID ] ||
                            ( outerCache[ elem.uniqueID ] = {} );
                        if ( skip && skip === elem.nodeName.toLowerCase() ) {
                            elem = elem[ dir ] || elem;
                        } else if ( ( oldCache = uniqueCache[ key ] ) &&
                            oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {
                            // Assign to newCache so results back-propagate to previous elements
                            return ( newCache[ 2 ] = oldCache[ 2 ] );
                        } else {
                            // Reuse newcache so results back-propagate to previous elements
                            uniqueCache[ key ] = newCache;
                            // A match means we're done; a fail means we have to keep checking
                            if ( ( newCache[ 2 ] = matcher( elem, context, xml ) ) ) {
                                return true;
                            }
                        }
                    }
                }
            }
            return false;
        };
}
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 multipleContexts( selector, contexts, results ) {
    var i = 0,
        len = contexts.length;
    for ( ; i < len; i++ ) {
        Sizzle( selector, contexts[ i ], results );
    }
    return results;
}
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( 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( checkContext, elem ) > -1;
        }, implicitRelative, true ),
        matchers = [ function( elem, context, xml ) {
            var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
                ( checkContext = context ).nodeType ?
                    matchContext( elem, context, xml ) :
                    matchAnyContext( elem, context, xml ) );
            // Avoid hanging onto element (issue #299)
            checkContext = null;
            return ret;
        } ];
    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 && toSelector(
                    // If the preceding token was a descendant combinator, insert an implicit any-element `*`
                    tokens
                        .slice( 0, i - 1 )
                        .concat( { value: tokens[ i - 2 ].type === " " ? "*" : "" } )
                    ).replace( rtrim, "$1" ),
                    matcher,
                    i < j && matcherFromTokens( tokens.slice( i, j ) ),
                    j < len && matcherFromTokens( ( tokens = tokens.slice( j ) ) ),
                    j < len && toSelector( tokens )
                );
            }
            matchers.push( matcher );
        }
    }
    return elementMatcher( matchers );
}
function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
    var bySet = setMatchers.length > 0,
        byElement = elementMatchers.length > 0,
        superMatcher = function( seed, context, xml, results, outermost ) {
            var elem, j, matcher,
                matchedCount = 0,
                i = "0",
                unmatched = seed && [],
                setMatched = [],
                contextBackup = outermostContext,
                // We must always have either seed elements or outermost context
                elems = seed || byElement && Expr.find[ "TAG" ]( "*", outermost ),
                // Use integer dirruns iff this is the outermost matcher
                dirrunsUnique = ( dirruns += contextBackup == null ? 1 : Math.random() || 0.1 ),
                len = elems.length;
            if ( outermost ) {
                // Support: IE 11+, Edge 17 - 18+
                // IE/Edge sometimes throw a "Permission denied" error when strict-comparing
                // two documents; shallow comparisons work.
                // eslint-disable-next-line eqeqeq
                outermostContext = context == document || context || outermost;
            }
            // Add elements passing elementMatchers directly to results
            // Support: IE<9, Safari
            // Tolerate NodeList properties (IE: "length"; Safari: ) matching elements by id
            for ( ; i !== len && ( elem = elems[ i ] ) != null; i++ ) {
                if ( byElement && elem ) {
                    j = 0;
                    // Support: IE 11+, Edge 17 - 18+
                    // IE/Edge sometimes throw a "Permission denied" error when strict-comparing
                    // two documents; shallow comparisons work.
                    // eslint-disable-next-line eqeqeq
                    if ( !context && elem.ownerDocument != document ) {
                        setDocument( elem );
                        xml = !documentIsHTML;
                    }
                    while ( ( matcher = elementMatchers[ j++ ] ) ) {
                        if ( matcher( elem, context || document, xml ) ) {
                            results.push( elem );
                            break;
                        }
                    }
                    if ( outermost ) {
                        dirruns = dirrunsUnique;
                    }
                }
                // 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 );
                    }
                }
            }
            // `i` is now the count of elements visited above, and adding it to `matchedCount`
            // makes the latter nonnegative.
            matchedCount += i;
            // Apply set filters to unmatched elements
            // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount`
            // equals `i`), unless we didn't visit _any_ elements in the above loop because we have
            // no element matchers and no seed.
            // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that
            // case, which will result in a "00" `matchedCount` that differs from `i` but is also
            // numerically zero.
            if ( bySet && i !== matchedCount ) {
                j = 0;
                while ( ( matcher = setMatchers[ 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, match /* Internal Use Only */ ) {
    var i,
        setMatchers = [],
        elementMatchers = [],
        cached = compilerCache[ selector + " " ];
    if ( !cached ) {
        // Generate a function of recursive functions that can be used to check each element
        if ( !match ) {
            match = tokenize( selector );
        }
        i = match.length;
        while ( i-- ) {
            cached = matcherFromTokens( match[ i ] );
            if ( cached[ expando ] ) {
                setMatchers.push( cached );
            } else {
                elementMatchers.push( cached );
            }
        }
        // Cache the compiled function
        cached = compilerCache(
            selector,
            matcherFromGroupMatchers( elementMatchers, setMatchers )
        );
        // Save selector and tokenization
        cached.selector = selector;
    }
    return cached;
};
/**
* A low-level selection function that works with Sizzle's compiled
* selector functions
* @param {String|Function} selector A selector or a pre-compiled
* selector function built with Sizzle.compile
* @param {Element} context
* @param {Array} [results]
* @param {Array} [seed] A set of elements to match against
*/
select = Sizzle.select = function( selector, context, results, seed ) {
    var i, tokens, token, type, find,
        compiled = typeof selector === "function" && selector,
        match = !seed && tokenize( ( selector = compiled.selector || selector ) );
    results = results || [];
    // Try to minimize operations if there is only one selector in the list and no seed
    // (the latter of which guarantees us context)
    if ( match.length === 1 ) {
        // Reduce context if the leading compound selector is an ID
        tokens = match[ 0 ] = match[ 0 ].slice( 0 );
        if ( tokens.length > 2 && ( token = tokens[ 0 ] ).type === "ID" &&
            context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[ 1 ].type ] ) {
            context = ( Expr.find[ "ID" ]( token.matches[ 0 ]
                .replace( runescape, funescape ), context ) || [] )[ 0 ];
            if ( !context ) {
                return results;
            // Precompiled matchers will still verify ancestry, so step up a level
            } else if ( compiled ) {
                context = context.parentNode;
            }
            selector = selector.slice( tokens.shift().value.length );
        }
        // Fetch a seed set for right-to-left matching
        i = matchExpr[ "needsContext" ].test( selector ) ? 0 : tokens.length;
        while ( 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( runescape, funescape ),
                    rsibling.test( tokens[ 0 ].type ) && testContext( context.parentNode ) ||
                        context
                ) ) ) {
                    // If seed is empty or no tokens remain, we can return early
                    tokens.splice( i, 1 );
                    selector = seed.length && toSelector( tokens );
                    if ( !selector ) {
                        push.apply( results, seed );
                        return results;
                    }
                    break;
                }
            }
        }
    }
    // Compile and execute a filtering function if one is not provided
    // Provide `match` to avoid retokenization if we modified the selector above
    ( compiled || compile( selector, match ) )(
        seed,
        context,
        !documentIsHTML,
        results,
        !context || rsibling.test( selector ) && testContext( context.parentNode ) || context
    );
    return results;
};
// One-time assignments
// Sort stability
support.sortStable = expando.split( "" ).sort( sortOrder ).join( "" ) === expando;
// Support: Chrome 14-35+
// Always assume duplicates if they aren't passed to the comparison function
support.detectDuplicates = !!hasDuplicate;
// Initialize against the default document
setDocument();
// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)
// Detached nodes confoundingly follow *each other*
support.sortDetached = assert( function( el ) {
    // Should return 1, but returns 4 (following)
    return el.compareDocumentPosition( document.createElement( "fieldset" ) ) & 1;
} );
// Support: IE<8
// Prevent attribute/property "interpolation"
// https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
if ( !assert( function( el ) {
    el.innerHTML = "";
    return el.firstChild.getAttribute( "href" ) === "#";
} ) ) {
    addHandle( "type|href|height|width", function( elem, name, isXML ) {
        if ( !isXML ) {
            return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 );
        }
    } );
}
// Support: IE<9
// Use defaultValue in place of getAttribute("value")
if ( !support.attributes || !assert( function( el ) {
    el.innerHTML = "";
    el.firstChild.setAttribute( "value", "" );
    return el.firstChild.getAttribute( "value" ) === "";
} ) ) {
    addHandle( "value", function( elem, _name, isXML ) {
        if ( !isXML && elem.nodeName.toLowerCase() === "input" ) {
            return elem.defaultValue;
        }
    } );
}
// Support: IE<9
// Use getAttributeNode to fetch booleans when getAttribute lies
if ( !assert( function( el ) {
    return el.getAttribute( "disabled" ) == null;
} ) ) {
    addHandle( booleans, function( elem, name, isXML ) {
        var val;
        if ( !isXML ) {
            return elem[ name ] === true ? name.toLowerCase() :
                ( val = elem.getAttributeNode( name ) ) && val.specified ?
                    val.value :
                    null;
        }
    } );
}
return Sizzle;
} )( window );
jQuery.find = Sizzle;
jQuery.expr = Sizzle.selectors;
// Deprecated
jQuery.expr[ ":" ] = jQuery.expr.pseudos;
jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort;
jQuery.text = Sizzle.getText;
jQuery.isXMLDoc = Sizzle.isXML;
jQuery.contains = Sizzle.contains;
jQuery.escapeSelector = Sizzle.escape;
var dir = function( elem, dir, until ) {
    var matched = [],
        truncate = until !== undefined;
    while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) {
        if ( elem.nodeType === 1 ) {
            if ( truncate && jQuery( elem ).is( until ) ) {
                break;
            }
            matched.push( elem );
        }
    }
    return matched;
};
var siblings = function( n, elem ) {
    var matched = [];
    for ( ; n; n = n.nextSibling ) {
        if ( n.nodeType === 1 && n !== elem ) {
            matched.push( n );
        }
    }
    return matched;
};
var rneedsContext = jQuery.expr.match.needsContext;
function nodeName( elem, name ) {
return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
};
var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i );
// Implement the identical functionality for filter and not
function winnow( elements, qualifier, not ) {
    if ( isFunction( qualifier ) ) {
        return jQuery.grep( elements, function( elem, i ) {
            return !!qualifier.call( elem, i, elem ) !== not;
        } );
    }
    // Single element
    if ( qualifier.nodeType ) {
        return jQuery.grep( elements, function( elem ) {
            return ( elem === qualifier ) !== not;
        } );
    }
    // Arraylike of elements (jQuery, arguments, Array)
    if ( typeof qualifier !== "string" ) {
        return jQuery.grep( elements, function( elem ) {
            return ( indexOf.call( qualifier, elem ) > -1 ) !== not;
        } );
    }
    // Filtered directly for both simple and complex selectors
    return jQuery.filter( qualifier, elements, not );
}
jQuery.filter = function( expr, elems, not ) {
    var elem = elems[ 0 ];
    if ( not ) {
        expr = ":not(" + expr + ")";
    }
    if ( elems.length === 1 && elem.nodeType === 1 ) {
        return jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [];
    }
    return jQuery.find.matches(...
SOLUTION.PDF

Answer To This Question Is Available To Download

Related Questions & Answers

More Questions ยป

Submit New Assignment

Copy and Paste Your Assignment Here