Great Deal! Get Instant $10 FREE in Account on First Order + 10% Cashback on Every Order Order Now

Goal and Directions: In this activity, you will design and implement a Person class based on a UML class model. Complete the following tasks for this activity: Execution Execute this assignment...

1 answer below »

Goal and Directions:

In this activity, you will design and implement a Person class based on a UML class model. Complete the following tasks for this activity:

Execution

Execute this assignment according to the following guidelines:

  1. Create a UML diagram for a Person class by using your favorite UML drawing tool, such as Microsoft Word, Microsoft Visio, Draw.io, or something else. Create a variety of properties and methods that describe what a person’s attributes and actions. Students taking this course on campus should do an in-class activity with the whiteboard to model a Person class.

  2. Create a new Java Project using the File  New  Java Project menu items and name your project topic1-2. Also validate that your project is configured to use the JavaSE-1.8 JRE. Click the Finish button.

  3. Right click on the project folder within the Project and select the New  Class menu options. Name your class Person and put in a package named app. Click the public static void main() method creation option. Click Finish.

    1. Add the state variables that were modeled as class private member variables.

    2. Create a constructor that initializes your Person state variables with parameter values.

    3. Create a getter and setter method for all of the state variables using Eclipse Refactoring (use the Source  Generate Getter and Setters…. menu options).

    1. Add the behavior methods that were modeled as public class methods.

    2. Add console print statements to each method that displays appropriate testing messages.

    1. In the main() method, create an instance of the Person class and call each of the public methods.

  1. Run the Person class.

  2. Take a screenshot of the console when executing the Person class.

  3. Provide a brief (3- to 4-sentence) description of how and why the output was displayed.

  4. Using JavaDoc conventions using Eclipse (enter /** [return] above each class method), document your class and all methods. Generate the JavaDoc using Eclipse with following steps:

    1. Select the Project  Generate Javadoc… menu options.

    2. Select your project.

    3. Use the standard doclet.

    4. Set the location where you want the JavaDoc generated. The default location is the doc folder inside of the project.

    5. Click the Generate button.

    6. Validate the documentation by opening the index.html generated by JavaDoc.

  1. Create a UML class diagram of your Person class.

Deliverables:

The following need to be submitted as this part of the activity:

  1. Theory of operation write-ups.

  2. UML class diagram of the Person class.

  3. Screenshot of the console output when running the Person class.

  4. Submit a zip file of your source code, including the generated Javadoc files.



Part 2: Using the Debugger

Overview

Goal and Directions:

In this activity, you will be given some tutorials and various debugger operations, such as setting breakpoints, inspecting variables, stepping thru code, and inspecting the call stack, that you will practice using code developed in this activity. The following are requirements to complete this activity:

Execution

Execute this assignment according to the following guidelines:

  1. Read the Eclipse Debugger tutorial at http://www.vogella.com/tutorials/EclipseDebugging/article.html. Open the Debug Perspective in Eclipse. Inspect each of the Debugger Icons by hovering your mouse over each of the icons, as well as the Debug menu items located within the Run menu.

  2. Open the project from topic1-2 project.

  1. Setting Breakpoints:

    1. Open up the Person class.

    2. Set a breakpoint on one of the statements in the main() method and another breakpoint on one of the classes methods.

    3. Run the application in debug mode by clicking the Debug icon from the Eclipse toolbar.

    4. Take a screenshot of the first breakpoint stopped in the debugger.

    5. Click the Resume icon from the Eclipse toolbar.

    6. Take a screenshot of the second breakpoint stopped in the debugger.

    7. Remove all breakpoints.

    8. Click the Resume icon from the Eclipse toolbar.

  2. Inspecting Variables:

    1. Remove the breakpoints that were previously set.

    2. Set a new breakpoint on a different method in the class.

    3. Run the application in debug mode by clicking the Debug icon from the Eclipse toolbar.

    4. Inspect all of the class member variables in the Variables Window.

    5. Take a screenshot of the Variables Window in the debugger.

    6. Remove all breakpoints.

    7. Click the Resume icon from the Eclipse toolbar.

  3. Stepping Into a Function, Step Over Function, and Step Return from a function:

    1. Set a breakpoint on one of the statements in the main() that calls a method in the Person class.

    2. Run the application in debug mode by clicking the Debug icon from the Eclipse toolbar.

    3. Verify that code stopped at the breakpoint.

    4. Click the Step Into icon from the Eclipse toolbar to step into the method.

    5. Verify that you are in line 1 of the method.

    6. Click the Step Over icon from the Eclipse toolbar and inspect all local variables during each step. Continue clicking the Step Over icon until you have reached the last line of the method.

    7. Click the Step Return icon from the Eclipse toolbar.

    8. Verify that you are in the method callback in the main() method.

    9. Take a screenshot of the debugger.

    10. Click the Resume icon from the Eclipse toolbar.

    11. Remove all breakpoints.

  4. Inspecting the Call Stack:

    1. Set a breakpoint on one of the statements in the main() that calls a method in the Person class.

    2. Run the application in debug mode by clicking the Debug icon from the Eclipse toolbar.

    3. Verify that code stopped at the breakpoint.

    4. Click the Step Into icon from the Eclipse toolbar to step into the method.

    5. Verify that you are in line 1 of the method.

    6. Click the Step Over icon from the Eclipse toolbar and inspect all local variables during each step. Continue clicking the Step Over icon until you have reached the last line of the method.

    7. Inspect the Debug (Call Stack) Window.

    8. Take a screenshot of the Debug (Call Stack) Window.

    9. Remove all breakpoints.

    10. Click the Resume icon from the Eclipse toolbar.


Deliverables:

The following need to be submitted as this part of the activity:

  1. Screenshot from the Setting Breakpoints task.

  2. Screenshots from the Inspecting Variables task.

  3. Screenshots from the Stepping task.

  4. Screenshot from the Inspecting Call Stack task.


Answered Same Day Dec 20, 2021

Solution

Aditya answered on Dec 21 2021
150 Votes
New folde
eakpoint1.PNG
New folde
eakpoint2.PNG
New folde
eakpoint3.PNG
New folde
eakpoint4.PNG
New folde
classDiagram.PNG
New folde
doc/allclasses-index.html
JavaScript is disabled on your
owser.
Skip navigation links
        Package
        Class
        Use
        Tree
        Deprecated
        Index
        Help
SEARCH:
All Classes
Class Summary         Class        Description
        Person        Â 
Skip navigation links
        Package
        Class
        Use
        Tree
        Deprecated
        Index
        Help
New folde
doc/allpackages-index.html
JavaScript is disabled on your
owser.
Skip navigation links
        Package
        Class
        Use
        Tree
        Deprecated
        Index
        Help
SEARCH:
All Packages
Package Summary         Package        Description
        app        Â 
Skip navigation links
        Package
        Class
        Use
        Tree
        Deprecated
        Index
        Help
New folde
doc/app/class-use/Person.html
JavaScript is disabled on your
owser.
Skip navigation links
        Package
        Class
        Use
        Tree
        Deprecated
        Index
        Help
SEARCH:
Uses of Class
app.Person
No usage of app.Person
Skip navigation links
        Package
        Class
        Use
        Tree
        Deprecated
        Index
        Help
New folde
doc/app/package-summary.html
JavaScript is disabled on your
owser.
Skip navigation links
        Package
        Class
        Use
        Tree
        Deprecated
        Index
        Help
SEARCH:
Package app
        
Class Summary         Class        Description
        Person        Â 
Skip navigation links
        Package
        Class
        Use
        Tree
        Deprecated
        Index
        Help
New folde
doc/app/package-tree.html
JavaScript is disabled on your
owser.
Skip navigation links
        Package
        Class
        Use
        Tree
        Deprecated
        Index
        Help
SEARCH:
Hierarchy For Package app
Class Hierarchy
        java.lang.Object
        app.Person
Skip navigation links
        Package
        Class
        Use
        Tree
        Deprecated
        Index
        Help
New folde
doc/app/package-use.html
JavaScript is disabled on your
owser.
Skip navigation links
        Package
        Class
        Use
        Tree
        Deprecated
        Index
        Help
SEARCH:
Uses of Package
app
No usage of app
Skip navigation links
        Package
        Class
        Use
        Tree
        Deprecated
        Index
        Help
New folde
doc/app/Person.html
JavaScript is disabled on your
owser.
Skip navigation links
        Package
        Class
        Use
        Tree
        Deprecated
        Index
        Help
        Summary: 
        Nested | 
        Field | 
        Constr | 
        Method
        Detail: 
        Field | 
        Constr | 
        Method
SEARCH:
Package app
Class Person
java.lang.Object
app.Person
public class Person
extends java.lang.Object
        
Constructor Summary
Constructors         Constructor        Description
        Person​(java.lang.String firstName,
java.lang.String lastName,
int age,
double monthlySalary)        Â 
        
Method Summary
All MethodsStatic MethodsInstance MethodsConcrete Methods
        Modifier and Type        Method        Description
        int        getAge()        Â 
        java.lang.String        getFirstName()        Â 
        java.lang.String        getLastName()        Â 
        double        getMonthlySalary()        Â 
        double        getYearlySalary()        Â 
        static void        main​(java.lang.String[] args)        Â 
        void        print()        Â 
        void        setAge​(int age)        Â 
        void        setFirstName​(java.lang.String firstName)        Â 
        void        setLastName​(java.lang.String lastName)        Â 
        void        setMonthlySalary​(double monthlySalary)        Â 
Methods inherited from class java.lang.Object
equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
        
Constructor Details
        
Person
public Person​(java.lang.String firstName,
java.lang.String lastName,
int age,
double monthlySalary)
        
Method Details
        
getFirstName
public java.lang.String getFirstName()
        
setFirstName
public void setFirstName​(java.lang.String firstName)
        
getLastName
public java.lang.String getLastName()
        
setLastName
public void setLastName​(java.lang.String lastName)
        
getAge
public int getAge()
        
setAge
public void setAge​(int age)
        
getMonthlySalary
public double getMonthlySalary()
        
setMonthlySalary
public void setMonthlySalary​(double monthlySalary)
        
getYearlySalary
public double getYearlySalary()
        
print
public void print()
        
main
public static void main​(java.lang.String[] args)
Skip navigation links
        Package
        Class
        Use
        Tree
        Deprecated
        Index
        Help
        Summary: 
        Nested | 
        Field | 
        Constr | 
        Method
        Detail: 
        Field | 
        Constr | 
        Method
New folde
doc/constant-values.html
JavaScript is disabled on your
owser.
Skip navigation links
        Package
        Class
        Use
        Tree
        Deprecated
        Index
        Help
SEARCH:
Constant Field Values
Contents
Skip navigation links
        Package
        Class
        Use
        Tree
        Deprecated
        Index
        Help
New folde
doc/deprecated-list.html
JavaScript is disabled on your
owser.
Skip navigation links
        Package
        Class
        Use
        Tree
        Deprecated
        Index
        Help
SEARCH:
Deprecated API
Contents
Skip navigation links
        Package
        Class
        Use
        Tree
        Deprecated
        Index
        Help
New folde
doc/element-list
app
New folde
doc/help-doc.html
JavaScript is disabled on your
owser.
Skip navigation links
        Package
        Class
        Use
        Tree
        Deprecated
        Index
        Help
SEARCH:
How This API Document Is Organized
This API (Application Programming Interface) document has pages co
esponding to the items in the navigation bar, described as follows.
        
Package
Each package has a page that contains a list of its classes and interfaces, with a summary for each. These pages may contain six categories:
        Interfaces
        Classes
        Enums
        Exceptions
        E
ors
        Annotation Types
        
Class or Interface
Each class, interface, nested class and nested interface has its own separate page. Each of these pages has three sections consisting of a class/interface description, summary tables, and detailed member descriptions:
        Class Inheritance Diagram
        Direct Subclasses
        All Known Subinterfaces
        All Known Implementing Classes
        Class or Interface Declaration
        Class or Interface Description
        Nested Class Summary
        Field Summary
        Property Summary
        Constructor Summary
        Method Summary
        Field Details
        Property Details
        Constructor Details
        Method Details
Each summary entry contains the first sentence from the detailed description for that item. The summary entries are alphabetical, while the detailed descriptions are in the order they appear in the source code. This preserves the logical groupings established by the programmer.
        
Annotation Type
Each annotation type has its own separate page with the following sections:
        Annotation Type Declaration
        Annotation Type Description
        Required Element Summary
        Optional Element Summary
        Element Details
        
Enum
Each enum has its own separate page with the following sections:
        Enum Declaration
        Enum Description
        Enum Constant Summary
        Enum Constant Details
        
Use
Each documented package, class and interface has its own Use page. This page describes what packages, classes, methods, constructors and fields use any part of the given class or package. Given a class or interface A, its "Use" page includes subclasses of A, fields declared as A, methods that return A, and methods and constructors with parameters of type A. You can access this page by first going to the package, class or interface, then clicking on the "Use" link in the navigation bar.
        
Tree (Class Hierarchy)
There is a Class Hierarchy page for all packages, plus a hierarchy for each package. Each hierarchy page contains a list of classes and a list of interfaces. Classes are organized by inheritance structure starting with java.lang.Object. Interfaces do not inherit from java.lang.Object.
        When viewing the Overview page, clicking on "Tree" displays the hierarchy for all packages.
        When viewing a particular package, class or interface page, clicking on "Tree" displays the hierarchy for only that package.
        
Deprecated API
The Deprecated API page lists all of the API that have been deprecated. A deprecated API is not recommended for use, generally due to improvements, and a replacement API is usually given. Deprecated APIs may be removed in future implementations.
        
Index
The Index contains an alphabetic index of all classes, interfaces, constructors, methods, and fields, as well as lists of all packages and all classes.
        
Serialized Form
Each serializable or externalizable class has a description of its serialization fields and methods. This information is of interest to re-implementors, not to developers using the API. While there is no link in the navigation bar, you can get to this information by going to any serialized class and clicking "Serialized Form" in the "See also" section of the class description.
        
Constant Field Values
The Constant Field Values page lists the static final fields and their values.
        
Search
You can search for definitions of modules, packages, types, fields, methods, system properties and other terms defined in the API, using some or all of the name, optionally using "camel-case" a
eviations. For example:
        j.l.obj will match "java.lang.Object"
        InpStr will match "java.io.InputStream"
        HM.cK will match "java.util.HashMap.containsKey(Object)"
Refer to the Javadoc Search Specification for a full description of search features.
This help file applies to API documentation generated by the standard doclet.
Skip navigation links
        Package
        Class
        Use
        Tree
        Deprecated
        Index
        Help
New folde
doc/index.html
JavaScript is disabled on your
owser.
app/package-summary.html
New folde
doc/index-files/index-1.html
JavaScript is disabled on your
owser.
Skip navigation links
        Package
        Class
        Use
        Tree
        Deprecated
        Index
        Help
SEARCH:
Index
A G M P S 
All Classes|All Packages
A
        app - package app
        Â 
A G M P S 
All Classes|All Packages
Skip navigation links
        Package
        Class
        Use
        Tree
        Deprecated
        Index
        Help
New folde
doc/index-files/index-2.html
JavaScript is disabled on your
owser.
Skip navigation links
        Package
        Class
        Use
        Tree
        Deprecated
        Index
        Help
SEARCH:
Index
A G M P S 
All Classes|All Packages
G
        getAge() - Method in class app.Person
        Â 
        getFirstName() - Method in class app.Person
        Â 
        getLastName() - Method in class app.Person
        Â 
        getMonthlySalary() - Method in class app.Person
        Â 
        getYearlySalary() - Method in class app.Person
        Â 
A G M P S 
All Classes|All Packages
Skip navigation links
        Package
        Class
        Use
        Tree
        Deprecated
        Index
        Help
New folde
doc/index-files/index-3.html
JavaScript is disabled on your
owser.
Skip navigation links
        Package
        Class
        Use
        Tree
        Deprecated
        Index
        Help
SEARCH:
Index
A G M P S 
All Classes|All Packages
M
        main(String[]) - Static method in class app.Person
        Â 
A G M P S 
All Classes|All Packages
Skip navigation links
        Package
        Class
        Use
        Tree
        Deprecated
        Index
        Help
New folde
doc/index-files/index-4.html
JavaScript is disabled on your
owser.
Skip navigation links
        Package
        Class
        Use
        Tree
        Deprecated
        Index
        Help
SEARCH:
Index
A G M P S 
All Classes|All Packages
P
        Person - Class in app
        Â 
        Person(String, String, int, double) - Constructor for class app.Person
        Â 
        print() - Method in class app.Person
        Â 
A G M P S 
All Classes|All Packages
Skip navigation links
        Package
        Class
        Use
        Tree
        Deprecated
        Index
        Help
New folde
doc/index-files/index-5.html
JavaScript is disabled on your
owser.
Skip navigation links
        Package
        Class
        Use
        Tree
        Deprecated
        Index
        Help
SEARCH:
Index
A G M P S 
All Classes|All Packages
S
        setAge(int) - Method in class app.Person
        Â 
        setFirstName(String) - Method in class app.Person
        Â 
        setLastName(String) - Method in class app.Person
        Â 
        setMonthlySalary(double) - Method in class app.Person
        Â 
A G M P S 
All Classes|All Packages
Skip navigation links
        Package
        Class
        Use
        Tree
        Deprecated
        Index
        Help
New folde
doc/member-search-index.js
memberSearchIndex = [{"p":"app","c":"Person","l":"getAge()"},{"p":"app","c":"Person","l":"getFirstName()"},{"p":"app","c":"Person","l":"getLastName()"},{"p":"app","c":"Person","l":"getMonthlySalary()"},{"p":"app","c":"Person","l":"getYearlySalary()"},{"p":"app","c":"Person","l":"main(String[])","url":"main(java.lang.String[])"},{"p":"app","c":"Person","l":"Person(String, String, int, double)","url":"%3Cinit%3E(java.lang.String,java.lang.String,int,double)"},{"p":"app","c":"Person","l":"print()"},{"p":"app","c":"Person","l":"setAge(int)"},{"p":"app","c":"Person","l":"setFirstName(String)","url":"setFirstName(java.lang.String)"},{"p":"app","c":"Person","l":"setLastName(String)","url":"setLastName(java.lang.String)"},{"p":"app","c":"Person","l":"setMonthlySalary(double)"}]
New folde
doc/member-search-index.zip
member-search-index.json
[{"p":"app","c":"Person","l":"getAge()"},{"p":"app","c":"Person","l":"getFirstName()"},{"p":"app","c":"Person","l":"getLastName()"},{"p":"app","c":"Person","l":"getMonthlySalary()"},{"p":"app","c":"Person","l":"getYearlySalary()"},{"p":"app","c":"Person","l":"main(String[])","url":"main(java.lang.String[])"},{"p":"app","c":"Person","l":"Person(String, String, int, double)","url":"%3Cinit%3E(java.lang.String,java.lang.String,int,double)"},{"p":"app","c":"Person","l":"print()"},{"p":"app","c":"Person","l":"setAge(int)"},{"p":"app","c":"Person","l":"setFirstName(String)","url":"setFirstName(java.lang.String)"},{"p":"app","c":"Person","l":"setLastName(String)","url":"setLastName(java.lang.String)"},{"p":"app","c":"Person","l":"setMonthlySalary(double)"}]
New folde
doc/overview-tree.html
JavaScript is disabled on your
owser.
Skip navigation links
        Package
        Class
        Use
        Tree
        Deprecated
        Index
        Help
SEARCH:
Hierarchy For All Packages
Package Hierarchies:
        app
Class Hierarchy
        java.lang.Object
        app.Person
Skip navigation links
        Package
        Class
        Use
        Tree
        Deprecated
        Index
        Help
New folde
doc/package-search-index.js
packageSearchIndex = [{"l":"All Packages","url":"allpackages-index.html"},{"l":"app"}]
New folde
doc/package-search-index.zip
package-search-index.json
[{"l":"All Packages","url":"allpackages-index.html"},{"l":"app"}]
New folde
doc
esources/glass.png
New folde
doc
esources/x.png
New folde
doc/script.js
*
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied wa
anty of MERCHANTABILITY o
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
var moduleSearchIndex;
var packageSearchIndex;
var typeSearchIndex;
var memberSearchIndex;
var tagSearchIndex;
function loadScripts(doc, tag) {
createElem(doc, tag, 'script-di
jszip/dist/jszip.js');
createElem(doc, tag, 'script-di
jszip-utils/dist/jszip-utils.js');
if (window.navigator.userAgent.indexOf('MSIE ') > 0 || window.navigator.userAgent.indexOf('Trident/') > 0 ||
window.navigator.userAgent.indexOf('Edge/') > 0) {
createElem(doc, tag, 'script-di
jszip-utils/dist/jszip-utils-ie.js');
}
createElem(doc, tag, 'search.js');
$.get(pathtoroot + "module-search-index.zip")
.done(function() {
JSZipUtils.getBinaryContent(pathtoroot + "module-search-index.zip", function(e, data) {
JSZip.loadAsync(data).then(function(zip){
zip.file("module-search-index.json").async("text").then(function(content){
moduleSearchIndex = JSON.parse(content);
});
});
});
});
$.get(pathtoroot + "package-search-index.zip")
.done(function() {
JSZipUtils.getBinaryContent(pathtoroot + "package-search-index.zip", function(e, data) {
JSZip.loadAsync(data).then(function(zip){
zip.file("package-search-index.json").async("text").then(function(content){
packageSearchIndex = JSON.parse(content);
});
});
});
});
$.get(pathtoroot + "type-search-index.zip")
.done(function() {
JSZipUtils.getBinaryContent(pathtoroot + "type-search-index.zip", function(e, data) {
JSZip.loadAsync(data).then(function(zip){
zip.file("type-search-index.json").async("text").then(function(content){
typeSearchIndex = JSON.parse(content);
});
});
});
});
$.get(pathtoroot + "member-search-index.zip")
.done(function() {
JSZipUtils.getBinaryContent(pathtoroot + "member-search-index.zip", function(e, data) {
JSZip.loadAsync(data).then(function(zip){
zip.file("member-search-index.json").async("text").then(function(content){
memberSearchIndex = JSON.parse(content);
});
});
});
});
$.get(pathtoroot + "tag-search-index.zip")
.done(function() {
JSZipUtils.getBinaryContent(pathtoroot + "tag-search-index.zip", function(e, data) {
JSZip.loadAsync(data).then(function(zip){
zip.file("tag-search-index.json").async("text").then(function(content){
tagSearchIndex = JSON.parse(content);
});
});
});
});
if (!moduleSearchIndex) {
createElem(doc, tag, 'module-search-index.js');
}
if (!packageSearchIndex) {
createElem(doc, tag, 'package-search-index.js');
}
if (!typeSearchIndex) {
createElem(doc, tag, 'type-search-index.js');
}
if (!memberSearchIndex) {
createElem(doc, tag, 'member-search-index.js');
}
if (!tagSearchIndex) {
createElem(doc, tag, 'tag-search-index.js');
}
}
function createElem(doc, tag, path) {
var script = doc.createElement(tag);
var scriptElement = doc.getElementsByTagName(tag)[0];
script.src = pathtoroot + path;
scriptElement.parentNode.insertBefore(script, scriptElement);
}
function show(type) {
count = 0;
for (var key in data) {
var row = document.getElementById(key);
if ((data[key] & type) !== 0) {
row.style.display = '';
row.className = (count++ % 2) ? rowColor : altColor;
}
else
row.style.display = 'none';
}
updateTabs(type);
}
function updateTabs(type) {
var firstRow = document.getElementById(Object.keys(data)[0]);
var table = firstRow.closest('table');
for (var value in tabs) {
var tab = document.getElementById(tabs[value][0]);
if (value == type) {
tab.className = activeTableTab;
tab.innerHTML = tabs[value][1];
tab.setAttribute('aria-selected', true);
tab.setAttribute('tabindex',0);
table.setAttribute('aria-labelledby', tabs[value][0]);
}
else {
tab.className = tableTab;
tab.setAttribute('aria-selected', false);
tab.setAttribute('tabindex',-1);
tab.setAttribute('onclick', "show("+ value + ")");
tab.innerHTML = tabs[value][1];
}
}
}
function switchTab(e) {
if (e.keyCode == 37 || e.keyCode == 38) {
$("[aria-selected=true]").prev().click().focus();
e.preventDefault();
}
if (e.keyCode == 39 || e.keyCode == 40) {
$("[aria-selected=true]").next().click().focus();
e.preventDefault();
}
}
New folde
doc/script-di
external/jquery/jquery.js
*!
* jQuery JavaScript Li
ary v3.4.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: 2019-05-01T21:04Z
*
( 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 E
or( "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 a
= [];
var document = window.document;
var getProto = Object.getPrototypeOf;
var slice = a
.slice;
var concat = a
.concat;
var push = a
.push;
var indexOf = a
.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
owsers, 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 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
owsers 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
owsing-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
va
    version = "3.4.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 e
or to be thrown if not included)
        return new jQuery.fn.init( selector, context );
    },
    
Support: Android <=4.0 only
    
Make sure we trim BOM and NBSP
    rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;
jQuery.fn = jQuery.prototype = {
    
The cu
ent version of jQuery being used
    jquery: version,
    constructor: jQuery,
    
The default length of a jQuery object is 0
    length: 0,
    toA
ay: function() {
        return slice.call( this );
    },
    
Get the Nth element in the matched element set OR
    
Get the whole matched element set as a clean a
ay
    get: function( num ) {
        
Return all the elements in a clean a
ay
        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 a
ay 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 );
    },
    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 A
ay's method, not like a jQuery method.
    push: push,
    sort: a
.sort,
    splice: a
.splice
};
jQuery.extend = jQuery.fn.extend = function() {
    var options, name, src, copy, copyIsA
ay, 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 a
ays
                if ( deep && copy && ( jQuery.isPlainObject( copy ) ||
                    ( copyIsA
ay = A
ay.isA
ay( copy ) ) ) ) {
                    src = target[ name ];
                    
Ensure proper type for the source value
                    if ( copyIsA
ay && !A
ay.isA
ay( src ) ) {
                        clone = [];
                    } else if ( !copyIsA
ay && !jQuery.isPlainObject( src ) ) {
                        clone = {};
                    } else {
                        clone = src;
                    }
                    copyIsA
ay = false;
                    
Never move original objects, clone them
                    target[ name ] = jQuery.extend( deep, clone, copy );
                
Don't
ing 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,
    e
or: function( msg ) {
        throw new E
or( 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 global context
    globalEval: function( code, options ) {
        DOMEval( code, { nonce: options && options.nonce } );
    },
    each: function( obj, callback ) {
        var length, i = 0;
        if ( isA
ayLike( obj ) ) {
            length = obj.length;
            for ( ; i < length; i++ ) {
                if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {
                    
eak;
                }
            }
        } else {
            for ( i in obj ) {
                if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {
                    
eak;
                }
            }
        }
        return obj;
    },
    
Support: Android <=4.0 only
    trim: function( text ) {
        return text == null ?
            "" :
            ( text + "" ).replace( rtrim, "" );
    },
    
results is for internal usage only
    makeA
ay: function( a
, results ) {
        var ret = results || [];
        if ( a
!= null ) {
            if ( isA
ayLike( Object( a
) ) ) {
                jQuery.merge( ret,
                    typeof a
=== "string" ?
                    [ a
] : a
                );
            } else {
                push.call( ret, a
);
            }
        }
        return ret;
    },
    inA
ay: function( elem, a
, i ) {
        return a
== null ? -1 : indexOf.call( a
, elem, i );
    },
    
Support: Android <=4.0 only, PhantomJS 1 only
    
push.apply(_, a
aylike) 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 a
ay, 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 a
ay, translating each of the items to their new values
        if ( isA
ayLike( 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 a
ays
        return concat.apply( [], ret );
    },
    
A global GUID counter for objects
    guid: 1,
    
jQuery.support is not used in Core but other projects attach thei
    
properties to it so it needs to exist.
    support: support
} );
if ( typeof Symbol === "function" ) {
    jQuery.fn[ Symbol.iterator ] = a
[ Symbol.iterator ];
}
Populate the class2type map
jQuery.each( "Boolean Number String Function A
ay Date RegExp Object E
or Symbol".split( " " ),
function( i, name ) {
    class2type[ "[object " + name + "]" ] = name.toLowerCase();
} );
function isA
ayLike( obj ) {
    
Support: real iOS 8.2 only (not reproducible in simulator)
    
`in` check used to prevent JIT e
or (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 === "a
ay" || length === 0 ||
        typeof length === "number" && length > 0 && ( length - 1 ) in obj;
}
var Sizzle =
*!
* Sizzle CSS Selector Engine v2.3.4
* https:
sizzlejs.com
*
* Copyright JS Foundation and other contributors
* Released under the MIT license
* https:
js.foundation
*
* Date: 2019-04-08
*
(function( window ) {
var i,
    support,
    Expr,
    getText,
    isXML,
    tokenize,
    compile,
    select,
    outermostContext,
    sortInput,
    hasDuplicate,
    
Local document vars
    setDocument,
    document,
    docElem,
    documentIsHTML,
    
uggyQSA,
    
uggyMatches,
    matches,
    contains,
    
Instance-specific data
    expando = "sizzle" + 1 * new Date(),
    prefe
edDoc = window.document,
    di
uns = 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,
    a
= [],
    pop = a
.pop,
    push_native = a
.push,
    push = a
.push,
    slice = a
.slice,
    
Use a stripped-down indexOf as it's faster than native
    
https:
jsperf.com/thor-indexof-vs-fo
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]",
    
http:
www.w3.org/TR/CSS21/syndata.html#value-def-identifie
    identifier = "(?:\\\\.|[\\w-]|[^\0-\\xa0])+",
    
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 latte
    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 li
aries 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
etrievable 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-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ),
    funescape = function( _, escaped, escapedWhitespace ) {
        var high = "0x" + escaped - 0x10000;
        
NaN means non-codepoint
        
Support: Firefox<24
        
Workaround e
oneous numeric interpretation of +"0x"
        return high !== high || escapedWhitespace ?
            escaped :
            high < 0 ?
                
BMP codepoint
                String.fromCharCode( high + 0x10000 ) :
                
Supplemental Plane codepoint (su
ogate pair)
                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"
    
e
or 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(
        (a
= slice.call( prefe
edDoc.childNodes )),
        prefe
edDoc.childNodes
    );
    
Support: Android<4.0
    
Detect silently failing push.apply
    a
[ prefe
edDoc.childNodes.length ].nodeType;
} catch ( e ) {
    push = { apply: a
.length ?
        
Leverage slice if possible
        function( target, els ) {
            push_native.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 ) {
        if ( ( context ? context.ownerDocument || context : prefe
edDoc ) !== document ) {
            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 selecto
                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 selecto
                } else if ( match[2] ) {
                    push.apply( results, context.getElementsByTagName( selector ) );
                    return results;
                
Class selecto
                } 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 + " " ] &&
                (!
uggyQSA || !
uggyQSA.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 o
                
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.
                
Thanks to Andrew Dupont for this technique.
                if ( nodeType === 1 && rdescend.test( selector ) ) {
                    
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 + " " + toSelector( groups[i] );
                    }
                    newSelector = groups.join( "," );
                    
Expand context for sibling selectors
                    newContext = rsibling.test( selector ) && testContext( context.parentNode ) ||
                        context;
                }
                try {
                    push.apply( results,
                        newContext.querySelectorAll( newSelector )
                    );
                    return results;
                } catch ( qsaE
or ) {
                    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 a
= attrs.split("|"),
        i = a
.length;
    while ( i-- ) {
        Expr.attrHandle[ a
[i] ] = handler;
    }
}
**
* Checks document order of two siblings
* @param {Element} a
* @param {Element}
* @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows
*
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:
ugs.jquery.com/ticket/4833
    return !rhtml.test( namespace || docElem && docElem.nodeName || "HTML" );
};
**
* Sets document-related variables once based on the cu
ent document
* @param {Element|Object} [doc] An element or document object to use to set the document
* @returns {Object} Returns the cu
ent document
*
setDocument = Sizzle.setDocument = function( node ) {
    var hasCompare, subWindow,
        doc = node ? node.ownerDocument || node : prefe
edDoc;
    
Return early if doc is invalid or already selected
    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
    
Accessing iframe documents after unload throws "permission denied" e
ors (jQuery #13936)
    if ( prefe
edDoc !== 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 );
        }
    }
    /* 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
oken 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 (
oken) 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/matchesSelecto
    ---------------------------------------------------------------------- *
    
QSA and matchesSelector support
    
matchesSelector(:active) reports false when true (IE9/Opera 11.5)
    
uggyMatches = [];
    
qSa(:focus) reports false when true (Chrome 21)
    
We allow this because of a bug in IE8/9 that throws an e
o
    
whenever `document.activeElement` is accessed on an iframe
    
So, we allow :focus to pass through QSA all the time to avoid the IE e
o
    
See https:
ugs.jquery.com/ticket/13378
    
uggyQSA = [];
    if ( (support.qsa = rnative.test( document.querySelectorAll )) ) {
        
Build QSA regex
        
Regex strategy adopted from Diego Perini
        assert(function( el ) {
            
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:
ugs.jquery.com/ticket/12359
            docElem.appendChild( el ).innerHTML = "a>" +
                "option
select>";
            
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 ) {
                
uggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" );
            }
            
FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
            
IE8 throws e
or here and will not see later tests
            if ( el.querySelectorAll(":enabled").length !== 2 ) {
                
uggyQSA.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 ) {
                
uggyQSA.push( ":enabled", ":disabled" );
            }
            
Opera 10-11 does not throw on post-comma invalid pseudos
            el.querySelectorAll("*,:x");
            
uggyQSA.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 matchesSelecto
            
on a disconnected node (IE 9)
            support.disconnectedMatch = matches.call( el, "*" );
            
This should fail with an exception
            
Gecko does not e
or, returns false instead
            matches.call( el, "[s!='']:x" );
            
uggyMatches.push( "!=", pseudos );
        });
    }
    
uggyQSA =
uggyQSA.length && new RegExp(
uggyQSA.join("|") );
    
uggyMatches =
uggyMatches.length && new RegExp(
uggyMatches.join("|") );
    /* Contains
    ---------------------------------------------------------------------- *
    hasCompare = rnative.test( docElem.compareDocumentPosition );
    
Element contains anothe
    
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
        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 prefe
ed document
            if ( a === document || a.ownerDocument === prefe
edDoc && contains(prefe
edDoc, a) ) {
                return -1;
            }
            if ( b === document || b.ownerDocument === prefe
edDoc && contains(prefe
edDoc, b) ) {
                return 1;
            }
            
Maintain original orde
            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 ) {
            return a === document ? -1 :
                b === document ? 1 :
                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 ancesto
            siblingCheck( ap[i], bp[i] ) :
            
Otherwise nodes in our document sort first
            ap[i] === prefe
edDoc ? -1 :
            bp[i] === prefe
edDoc ? 1 :
            0;
    };
    return document;
};
Sizzle.matches = function( expr, elements ) {
    return Sizzle( expr, null, null, elements );
};
Sizzle.matchesSelector = function( elem, expr ) {
    
Set document vars if needed
    if ( ( elem.ownerDocument || elem ) !== document ) {
        setDocument( elem );
    }
    if ( support.matchesSelector && documentIsHTML &&
        !nonnativeSelectorCache[ expr + " " ] &&
        ( !
uggyMatches || !
uggyMatches.test( expr ) ) &&
        ( !
uggyQSA || !
uggyQSA.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
    if ( ( context.ownerDocument || context ) !== document ) {
        setDocument( context );
    }
    return contains( context, elem );
};
Sizzle.attr = function( elem, name ) {
    
Set document vars if needed
    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.e
or = function( msg ) {
    throw new E
or( "Syntax e
or, unrecognized expression: " + msg );
};
**
* Document sorting and removing duplicates
* @param {A
ayLike} 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 a
ay of DOM nodes
* @param {A
ay|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 a
ay
        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 use
    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.e
or( 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.e
or( 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 += "";
                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;
            };
        },
        "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 ] === di
uns && 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
eak
                                if ( node.nodeType === 1 && ++diff && node === elem ) {
                                    uniqueCache[ type ] = [ di
uns, nodeIndex, diff ];
                                    
eak;
                                }
                            }
                        } 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 ] === di
uns && 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 ] = [ di
uns, diff ];
                                        }
                                        if ( node === elem ) {
                                            
eak;
                                        }
                                    }
                                }
                            }
                        }
                        
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.e
or( "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() selecto
        
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 identifie
            if ( !ridentifier.test(lang || "") ) {
                Sizzle.e
or( "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 ) {
                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 ) {
            
eak;
        }
    }
    
Return the length of the invalid excess
    
if we're just parsing
    
Otherwise, throw an e
or or return tokens
    return parseOnly ?
        soFar.length :
        soFar ?
            Sizzle.e
or( 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 ancesto
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 ancesto
preceding elements
        function( elem, context, xml ) {
            var oldCache, uniqueCache, outerCache,
                newCache = [ di
uns, doneName ];
            
We can't set a
itrary 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 ] === di
uns && 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 postFilte
        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 matche
            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 ] ) {
                        
eak;
                    }
                }
                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 di
uns iff this is the outermost matche
                di
unsUnique = (di
uns += contextBackup == null ? 1 : Math.random() || 0.1),
                len = elems.length;
            if ( outermost ) {
                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;
                    if ( !context && elem.ownerDocument !== document ) {
                        setDocument( elem );
                        xml = !documentIsHTML;
                    }
                    while ( (matcher = elementMatchers[j++]) ) {
                        if ( matcher( elem, context || document, xml) ) {
                            results.push( elem );
                            
eak;
                        }
                    }
                    if ( outermost ) {
                        di
uns = di
unsUnique;
                    }
                }
                
Track unmatched elements for set filters
                if ( bySet ) {
                    
They will have gone through all possible matchers
                    if ( (elem = !matcher && elem) ) {
                        matchedCount--;
                    }
                    
Lengthen the a
ay 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 );
                }
            }
            
Ove
ide manipulation of globals by nested matchers
            if ( outermost ) {
                di
uns = di
unsUnique;
                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 {A
ay} [results]
* @param {A
ay} [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 combinato
            if ( Expr.relative[ (type = token.type) ] ) {
                
eak;
            }
            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;
                    }
                    
eak;
                }
            }
        }
    }
    
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/li
ary/ms536429%28VS.85%29.aspx
if ( !assert(function( el ) {
    el.innerHTML = "
a>";
    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;
        }
    });
}
eturn 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 ) ) {
                
eak;
            }
            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;
        } );
    }
    
A
aylike of elements (jQuery, arguments, A
ay)
    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( expr, jQuery.grep( elems, function( elem ) {
        return elem.nodeType === 1;
    } ) );
};
jQuery.fn.extend( {
    find: function( selector ) {
        var i, ret,
            len = this.length,
            self = this;
        if ( typeof selector !== "string" ) {
            return this.pushStack( jQuery( selector ).filter( function() {
                for ( i = 0; i < len; i++ ) {
                    if ( jQuery.contains( self[ i ], this ) ) {
                        return true;
                    }
                }
            } ) );
        }
        ret = this.pushStack( [] );
        for ( i = 0; i < len; i++ ) {
            jQuery.find( selector, self[ i ], ret );
        }
        return len > 1 ? jQuery.uniqueSort( ret ) : ret;
    },
    filter: function( selector ) {
        return this.pushStack( winnow( this, selector || [], false ) );
    },
    not: function( selector ) {
        return this.pushStack( winnow( this, selector || [], true ) );
    },
    is: function( selector ) {
        return !!winnow(
            this,
            
If this is a positional
elative selector, check membership in the returned set
            
so $("p:first").is("p:last") won't return true for a doc with two "p".
            typeof selector === "string" && rneedsContext.test( selector ) ?
                jQuery( selector ) :
                selector || [],
            false
        ).length;
    }
} );
Initialize a jQuery object
A central reference to the root jQuery(document)
var rootjQuery,
    
A simple way to check for HTML strings
    
Prioritize #id over to avoid XSS via location.hash (#9521)
    
Strict HTML recognition (#11290: must start with <)
    
Shortcut simple #id case for speed
    rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/,
    init = jQuery.fn.init = function( selector, context, root ) {
        var match, elem;
        
HANDLE: $(""), $(null), $(undefined), $(false)
        if ( !selector ) {
            return this;
        }
        
Method init() accepts an alternate rootjQuery
        
so migrate can support jQuery.sub (gh-2101)
        root = root || rootjQuery;
        
Handle HTML strings
        if ( typeof selector === "string" ) {
            if ( selector[ 0 ] === "<" &&
                selector[ selector.length - 1 ] === ">" &&
                selector.length >= 3 ) {
                
Assume that strings that start and end with
are HTML and skip the regex check
                match = [ null, selector, null ];
            } else {
                match = rquickExpr.exec( selector );
            }
            
Match html or make sure no context is specified for #id
            if ( match && ( match[ 1 ] || !context ) ) {
                
HANDLE: $(html) -> $(a
ay)
                if ( match[ 1 ] ) {
                    context = context instanceof jQuery ? context[ 0 ] : context;
                    
Option to run scripts is true for back-compat
                    
Intentionally let the e
or be thrown if parseHTML is not present
                    jQuery.merge( this, jQuery.parseHTML(
                        match[ 1 ],
                        context && context.nodeType ? context.ownerDocument || context : document,
                        true
                    ) );
                    
HANDLE: $(html, props)
                    if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) {
                        for ( match in context ) {
                            
Properties of context are called as methods if possible
                            if ( isFunction( this[ match ] ) ) {
                                this[ match ]( context[ match ] );
                            
...and otherwise set as attributes
                            } else {
                                this.attr( match, context[ match ] );
                            }
                        }
                    }
                    return this;
                
HANDLE: $(#id)
                } else {
                    elem = document.getElementById( match[ 2 ] );
                    if ( elem ) {
                        
Inject the element directly into the jQuery object
                        this[ 0 ] = elem;
                        this.length = 1;
                    }
                    return this;
                }
            
HANDLE: $(expr, $(...))
            } else if ( !context || context.jquery ) {
                return ( context || root ).find( selector );
            
HANDLE: $(expr, context)
            
(which is just equivalent to: $(context).find(expr)
            } else {
                return this.constructor( context ).find( selector );
            }
        
HANDLE: $(DOMElement)
        } else if ( selector.nodeType ) {
            this[ 0 ] = selector;
            this.length = 1;
            return this;
        
HANDLE: $(function)
        
Shortcut for document ready
        } else if ( isFunction( selector ) ) {
            return root.ready !== undefined ?
                root.ready( selector ) :
                
Execute immediately if ready is not present
                selector( jQuery );
        }
        return jQuery.makeA
ay( selector, this );
    };
Give the init function the jQuery prototype for later instantiation
init.prototype = jQuery.fn;
Initialize central reference
ootjQuery = jQuery( document );
var rparentsprev = /^(?:parents|prev(?:Until|All))/,
    
Methods guaranteed to produce a unique set when starting from a unique set
    guaranteedUnique = {
        children: true,
        contents: true,
        next: true,
        prev: true
    };
jQuery.fn.extend( {
    has: function( target ) {
        var targets = jQuery( target, this ),
            l = targets.length;
        return this.filter( function() {
            var i = 0;
            for ( ; i < l; i++ ) {
                if ( jQuery.contains( this, targets[ i ] ) ) {
                    return true;
                }
            }
        } );
    },
    closest: function( selectors, context ) {
        var cur,
            i = 0,
            l = this.length,
            matched = [],
            targets = typeof selectors !== "string" && jQuery( selectors );
        
Positional selectors never match, since there's no _selection_ context
        if ( !rneedsContext.test( selectors ) ) {
            for ( ; i < l; i++ ) {
                for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) {
                    
Always skip document fragments
                    if ( cur.nodeType < 11 && ( targets ?
                        targets.index( cur ) > -1 :
                        
Don't pass non-elements to Sizzle
                        cur.nodeType === 1 &&
                            jQuery.find.matchesSelector( cur, selectors ) ) ) {
                        matched.push( cur );
                        
eak;
                    }
                }
            }
        }
        return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched );
    },
    
Determine the position of an element within the set
    index: function( elem ) {
        
No argument, return index in parent
        if ( !elem ) {
            return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1;
        }
        
Index in selecto
        if ( typeof elem === "string" ) {
            return indexOf.call( jQuery( elem ), this[ 0 ] );
        }
        
Locate the position of the desired element
        return indexOf.call( this,
            
If it receives a jQuery object, the first element is used
            elem.jquery ? elem[ 0 ] : elem
        );
    },
    add: function( selector, context ) {
        return this.pushStack(
            jQuery.uniqueSort(
                jQuery.merge( this.get(), jQuery( selector, context ) )
            )
        );
    },
    addBack: function( selector ) {
        return this.add( selector == null ?
            this.prevObject : this.prevObject.filter( selector )
        );
    }
} );
function sibling( cur, dir ) {
    while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {}
    return cur;
}
jQuery.each( {
    parent: function( elem ) {
        var parent = elem.parentNode;
        return parent && parent.nodeType !== 11 ? parent : null;
    },
    parents: function( elem ) {
        return dir( elem, "parentNode" );
    },
    parentsUntil: function( elem, i, until ) {
        return dir( elem, "parentNode", until );
    },
    next: function( elem ) {
        return sibling( elem, "nextSibling" );
    },
    prev: function( elem ) {
        return sibling( elem, "previousSibling" );
    },
    nextAll: function( elem ) {
        return dir( elem, "nextSibling" );
    },
    prevAll: function( elem ) {
        return dir( elem, "previousSibling" );
    },
    nextUntil: function( elem, i, until ) {
        return dir( elem, "nextSibling", until );
    },
    prevUntil: function( elem, i, until ) {
        return dir( elem, "previousSibling", until );
    },
    siblings: function( elem ) {
        return siblings( ( elem.parentNode || {} ).firstChild, elem );
    },
    children: function( elem ) {
        return siblings( elem.firstChild );
    },
    contents: function( elem ) {
        if ( typeof elem.contentDocument !== "undefined" ) {
            return elem.contentDocument;
        }
        
Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only
        
Treat the template element as a regular one in
owsers that
        
don't support it.
        if ( nodeName( elem, "template" ) ) {
            elem = elem.content || elem;
        }
        return jQuery.merge( [], elem.childNodes );
    }
}, function( name, fn ) {
    jQuery.fn[ name ] = function( until, selector ) {
        var matched = jQuery.map( this, fn, until );
        if ( name.slice( -5 ) !== "Until" ) {
            selector = until;
        }
        if ( selector && typeof selector === "string" ) {
            matched = jQuery.filter( selector, matched );
        }
        if ( this.length > 1 ) {
            
Remove duplicates
            if ( !guaranteedUnique[ name ] ) {
                jQuery.uniqueSort( matched );
            }
            
Reverse order for parents* and prev-derivatives
            if ( rparentsprev.test( name ) ) {
                matched.reverse();
            }
        }
        return this.pushStack( matched );
    };
} );
var rnothtmlwhite = ( /[^\x20\t\r\n\f]+/g );
Convert String-formatted options into Object-formatted ones
function createOptions( options ) {
    var object = {};
    jQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) {
        object[ flag ] = true;
    } );
    return object;
}
*
* Create a callback list using the following parameters:
*
*    options: an optional list of space-separated options that will change how
*            the callback list behaves or a more traditional option object
*
* By default a callback list will act like an event callback list and can be
* "fired" multiple times.
*
* Possible options:
*
*    once:            will ensure the callback list can only be fired once (like a Defe
ed)
*
*    memory:            will keep track of previous values and will call any callback added
*                    after the list has been fired right away with the latest "memorized"
*                    values (like a Defe
ed)
*
*    unique:            will ensure a callback can only be added once (no duplicate in the list)
*
*    stopOnFalse:    inte
upt callings when a callback returns false
*
*
jQuery.Callbacks = function( options ) {
    
Convert options from String-formatted to Object-formatted if needed
    
(we check in cache first)
    options = typeof options === "string" ?
        createOptions( options ) :
        jQuery.extend( {}, options );
    var
Flag to know if list is cu
ently firing
        firing,
        
Last fire value for non-forgettable lists
        memory,
        
Flag to know if list was already fired
        fired,
        
Flag to prevent firing
        locked,
        
Actual callback list
        list = [],
        
Queue of execution data for repeatable lists
        queue = [],
        
Index of cu
ently firing callback (modified by add
emove as needed)
        firingIndex = -1,
        
Fire callbacks
        fire = function() {
            
Enforce single-firing
            locked = locked || options.once;
            
Execute callbacks for all pending executions,
            
respecting firingIndex ove
ides and runtime changes
            fired = firing = true;
            for ( ; queue.length; firingIndex = -1 ) {
                memory = queue.shift();
                while ( ++firingIndex < list.length ) {
                    
Run callback and check for early termination
                    if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false &&
                        options.stopOnFalse ) {
                        
Jump to end and forget the data so .add doesn't re-fire
                        firingIndex = list.length;
                        memory = false;
                    }
                }
            }
            
Forget the data if we're done with it
            if ( !options.memory ) {
                memory = false;
            }
            firing = false;
            
Clean up if we're done firing for good
            if ( locked ) {
                
Keep an empty list if we have data for future add calls
                if ( memory ) {
                    list = [];
                
Otherwise, this object is spent
                } else {
                    list = "";
                }
            }
        },
        
Actual Callbacks object
        self = {
            
Add a callback or a collection of callbacks to the list
            add: function() {
                if ( list ) {
                    
If we have memory from a past run, we should fire after adding
                    if ( memory && !firing ) {
                        firingIndex = list.length - 1;
                        queue.push( memory );
                    }
                    ( function add( args ) {
                        jQuery.each( args, function( _, arg ) {
                            if ( isFunction( arg ) ) {
                                if ( !options.unique || !self.has( arg ) ) {
                                    list.push( arg );
                                }
                            } else if ( arg && arg.length && toType( arg ) !== "string" ) {
                                
Inspect recursively
                                add( arg );
                            }
                        } );
                    } )( arguments );
                    if ( memory && !firing ) {
                        fire();
                    }
                }
                return this;
            },
            
Remove a callback from the list
            remove: function() {
                jQuery.each( arguments, function( _, arg ) {
                    var index;
                    while ( ( index = jQuery.inA
ay( arg, list, index ) ) > -1 ) {
                        list.splice( index, 1 );
                        
Handle firing indexes
                        if ( index <= firingIndex ) {
                            firingIndex--;
                        }
                    }
                } );
                return this;
            },
            
Check if a given callback is in the list.
            
If no argument is given, return whether or not list has callbacks attached.
            has: function( fn ) {
                return fn ?
                    jQuery.inA
ay( fn, list ) > -1 :
                    list.length > 0;
            },
            
Remove all callbacks from the list
            empty: function() {
                if ( list ) {
                    list = [];
                }
                return this;
            },
            
Disable .fire and .add
            
Abort any cu
ent/pending executions
            
Clear all callbacks and values
            disable: function() {
                locked = queue = [];
                list = memory = "";
                return this;
            },
            disabled: function() {
                return !list;
            },
            
Disable .fire
            
Also disable .add unless we have memory (since it would have no effect)
            
Abort any pending executions
            lock: function() {
                locked = queue = [];
                if ( !memory && !firing ) {
                    list = memory = "";
                }
                return this;
            },
            locked: function() {
                return !!locked;
            },
            
Call all callbacks with the given context and arguments
            fireWith: function( context, args ) {
                if ( !locked ) {
                    args = args || [];
                    args = [ context, args.slice ? args.slice() : args ];
                    queue.push( args );
                    if ( !firing ) {
                        fire();
                    }
                }
                return this;
            },
            
Call all the callbacks with the given arguments
            fire: function() {
                self.fireWith( this, arguments );
                return this;
            },
            
To know if the callbacks have already been called at least once
            fired: function() {
                return !!fired;
            }
        };
    return self;
};
function Identity( v ) {
    return v;
}
function Thrower( ex ) {
    throw ex;
}
function adoptValue( value, resolve, reject, noValue ) {
    var method;
    try {
        
Check for promise aspect first to privilege synchronous behavio
        if ( value && isFunction( ( method = value.promise ) ) ) {
            method.call( value ).done( resolve ).fail( reject );
        
Other thenables
        } else if ( value && isFunction( ( method = value.then ) ) ) {
            method.call( value, resolve, reject );
        
Other non-thenables
        } else {
            
Control `resolve` arguments by letting A
ay#slice cast boolean `noValue` to integer:
            
* false: [ value ].slice( 0 ) => resolve( value )
            
* true: [ value ].slice( 1 ) => resolve()
            resolve.apply( undefined, [ value ].slice( noValue ) );
        }
    
For Promises/A+, convert exceptions into rejections
    
Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in
    
Defe
ed#then to conditionally suppress rejection.
    } catch ( value ) {
        
Support: Android 4.0 only
        
Strict mode functions invoked without .call/.apply get global-object context
        reject.apply( undefined, [ value ] );
    }
}
jQuery.extend( {
    Defe
ed: function( func ) {
        var tuples = [
                
action, add listener, callbacks,
                
... .then handlers, argument index, [final state]
                [ "notify", "progress", jQuery.Callbacks( "memory" ),
                    jQuery.Callbacks( "memory" ), 2 ],
                [ "resolve", "done", jQuery.Callbacks( "once memory" ),
                    jQuery.Callbacks( "once memory" ), 0, "resolved" ],
                [ "reject", "fail", jQuery.Callbacks( "once memory" ),
                    jQuery.Callbacks( "once memory" ), 1, "rejected" ]
            ],
            state = "pending",
            promise = {
                state: function() {
                    return state;
                },
                always: function() {
                    defe
ed.done( arguments ).fail( arguments );
                    return this;
                },
                "catch": function( fn ) {
                    return promise.then( null, fn );
                },
                
Keep pipe for back-compat
                pipe: function( /* fnDone, fnFail, fnProgress */ ) {
                    var fns = arguments;
                    return jQuery.Defe
ed( function( newDefer ) {
                        jQuery.each( tuples, function( i, tuple ) {
                            
Map tuples (progress, done, fail) to arguments (done, fail, progress)
                            var fn = isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ];
                            
defe
ed.progress(function() { bind to newDefer or newDefer.notify })
                            
defe
ed.done(function() { bind to newDefer or newDefer.resolve })
                            
defe
ed.fail(function() { bind to newDefer or newDefer.reject })
                            defe
ed[ tuple[ 1 ] ]( function() {
                                var returned = fn && fn.apply( this, arguments );
                                if ( returned && isFunction( returned.promise ) ) {
                                    returned.promise()
                                        .progress( newDefer.notify )
                                        .done( newDefer.resolve )
                                        .fail( newDefer.reject );
                                } else {
                                    newDefer[ tuple[ 0 ] + "With" ](
                                        this,
                                        fn ? [ returned ] : arguments
                                    );
                                }
                            } );
                        } );
                        fns = null;
                    } ).promise();
                },
                then: function( onFulfilled, onRejected, onProgress ) {
                    var maxDepth = 0;
                    function resolve( depth, defe
ed, handler, special ) {
                        return function() {
                            var that = this,
                                args = arguments,
                                mightThrow = function() {
                                    var returned, then;
                                    
Support: Promises/A+ section 2.3.3.3.3
                                    
https:
promisesaplus.com/#point-59
                                    
Ignore double-resolution attempts
                                    if ( depth < maxDepth ) {
                                        return;
                                    }
                                    returned = handler.apply( that, args );
                                    
Support: Promises/A+ section 2.3.1
                                    
https:
promisesaplus.com/#point-48
                                    if ( returned === defe
ed.promise() ) {
                                        throw new TypeE
or( "Thenable self-resolution" );
                                    }
                                    
Support: Promises/A+ sections 2.3.3.1, 3.5
                                    
https:
promisesaplus.com/#point-54
                                    
https:
promisesaplus.com/#point-75
                                    
Retrieve `then` only once
                                    then = returned &&
                                        
Support: Promises/A+ section 2.3.4
                                        
https:
promisesaplus.com/#point-64
                                        
Only check objects and functions for thenability
                                        ( typeof returned === "object" ||
                                            typeof returned === "function" ) &&
                                        returned.then;
                                    
Handle a returned thenable
                                    if ( isFunction( then ) ) {
                                        
Special processors (notify) just wait for resolution
                                        if ( special ) {
                                            then.call(
                                                returned,
                                                resolve( maxDepth, defe
ed, Identity, special ),
                                                resolve( maxDepth, defe
ed, Thrower, special )
                                            );
                                        
Normal processors (resolve) also hook into progress
                                        } else {
                                            
...and disregard older resolution values
                                            maxDepth++;
                                            then.call(
                                                returned,
                                                resolve( maxDepth, defe
ed, Identity, special ),
                                                resolve( maxDepth, defe
ed, Thrower, special ),
                                                resolve( maxDepth, defe
ed, Identity,
                                                    defe
ed.notifyWith )
                                            );
                                        }
                                    
Handle all other returned values
                                    } else {
                                        
Only substitute handlers pass on context
                                        
and multiple values (non-spec behavior)
                                        if ( handler !== Identity ) {
                                            that = undefined;
                                            args = [ returned ];
                                        }
                                        
Process the value(s)
                                        
Default process is resolve
                                        ( special || defe
ed.resolveWith )( that, args );
                                    }
                                },
                                
Only normal processors (resolve) catch and reject exceptions
                                process = special ?
                                    mightThrow :
                                    function() {
                                        try {
                                            mightThrow();
                                        } catch ( e ) {
                                            if ( jQuery.Defe
ed.exceptionHook ) {
                                                jQuery.Defe
ed.exceptionHook( e,
                                                    process.stackTrace );
                                            }
                                            
Support: Promises/A+ section 2.3.3.3.4.1
                                            
https:
promisesaplus.com/#point-61
                                            
Ignore post-resolution exceptions
                                            if ( depth + 1 >= maxDepth ) {
                                                
Only substitute handlers pass on context
                                                
and multiple values (non-spec behavior)
                                                if ( handler !== Thrower ) {
                                                    that = undefined;
                                                    args = [ e ];
                                                }
                                                defe
ed.rejectWith( that, args );
                                            }
                                        }
                                    };
                            
Support: Promises/A+ section 2.3.3.3.1
                            
https:
promisesaplus.com/#point-57
                            
Re-resolve promises immediately to dodge false rejection from
                            
subsequent e
ors
                            if ( depth ) {
                                process();
                            } else {
                                
Call an optional hook to record the stack, in case of exception
                                
since it's otherwise lost when execution goes async
                                if ( jQuery.Defe
ed.getStackHook ) {
                                    process.stackTrace = jQuery.Defe
ed.getStackHook();
                                }
                                window.setTimeout( process );
                            }
                        };
                    }
                    return jQuery.Defe
ed( function( newDefer ) {
                        
progress_handlers.add( ... )
                        tuples[ 0 ][ 3 ].add(
                            resolve(
                                0,
                                newDefer,
                                isFunction( onProgress ) ?
                                    onProgress :
                                    Identity,
                                newDefer.notifyWith
                            )
                        );
                        
fulfilled_handlers.add( ... )
                        tuples[ 1 ][ 3 ].add(
                            resolve(
                                0,
                                newDefer,
                                isFunction( onFulfilled ) ?
                                    onFulfilled :
                                    Identity
                            )
                        );
                        
rejected_handlers.add( ... )
                        tuples[ 2 ][ 3 ].add(
                            resolve(
                                0,
                                newDefer,
                                isFunction( onRejected ) ?
                                    onRejected :
                                    Throwe
                            )
                        );
                    } ).promise();
                },
                
Get a promise for this defe
ed
                
If obj is provided, the promise aspect is added to the object
                promise: function( obj ) {
                    return obj != null ? jQuery.extend( obj, promise ) : promise;
                }
            },
            defe
ed = {};
        
Add list-specific methods
        jQuery.each( tuples, function( i, tuple ) {
            var list = tuple[ 2 ],
                stateString = tuple[ 5 ];
            
promise.progress = list.add
            
promise.done = list.add
            
promise.fail = list.add
            promise[ tuple[ 1 ] ] = list.add;
            
Handle state
            if ( stateString ) {
                list.add(
                    function() {
                        
state = "resolved" (i.e., fulfilled)
                        
state = "rejected"
                        state = stateString;
                    },
                    
rejected_callbacks.disable
                    
fulfilled_callbacks.disable
                    tuples[ 3 - i ][ 2 ].disable,
                    
rejected_handlers.disable
                    
fulfilled_handlers.disable
                    tuples[ 3 - i ][ 3 ].disable,
                    
progress_callbacks.lock
                    tuples[ 0 ][ 2 ].lock,
                    
progress_handlers.lock
                    tuples[ 0 ][ 3 ].lock
                );
            }
            
progress_handlers.fire
            
fulfilled_handlers.fire
            
rejected_handlers.fire
            list.add( tuple[ 3 ].fire );
            
defe
ed.notify = function() { defe
ed.notifyWith(...) }
            
defe
ed.resolve = function() { defe
ed.resolveWith(...) }
            
defe
ed.reject = function() { defe
ed.rejectWith(...) }
            defe
ed[ tuple[ 0 ] ] = function() {
                defe
ed[ tuple[ 0 ] + "With" ]( this === defe
ed ? undefined : this, arguments );
                return this;
            };
            
defe
ed.notifyWith = list.fireWith
            
defe
ed.resolveWith = list.fireWith
            
defe
ed.rejectWith = list.fireWith
            defe
ed[ tuple[ 0 ] + "With" ] = list.fireWith;
        } );
        
Make the defe
ed a promise
        promise.promise( defe
ed );
        
Call given func if any
        if ( func ) {
            func.call( defe
ed, defe
ed );
        }
        
All done!
        return defe
ed;
    },
    
Defe
ed helpe
    when: function( singleValue ) {
        va
            
count of uncompleted subordinates
            remaining = arguments.length,
            
count of unprocessed arguments
            i = remaining,
            
subordinate fulfillment data
            resolveContexts = A
ay( i ),
            resolveValues = slice.call( arguments ),
            
the master Defe
ed
            master = jQuery.Defe
ed(),
            
subordinate callback factory
            updateFunc = function( i ) {
                return function( value ) {
                    resolveContexts[ i ] = this;
                    resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;
                    if ( !( --remaining ) ) {
                        master.resolveWith( resolveContexts, resolveValues );
                    }
                };
            };
        
Single- and empty arguments are adopted like Promise.resolve
        if ( remaining <= 1 ) {
            adoptValue( singleValue, master.done( updateFunc( i ) ).resolve, master.reject,
                !remaining );
            
Use .then() to unwrap secondary thenables (cf. gh-3000)
            if ( master.state() === "pending" ||
                isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) {
                return master.then();
            }
        }
        
Multiple arguments are aggregated like Promise.all a
ay elements
        while ( i-- ) {
            adoptValue( resolveValues[ i ], updateFunc( i ), master.reject );
        }
        return master.promise();
    }
} );
These usually indicate a programmer mistake during development,
warn about them ASAP rather than swallowing them by default.
var re
orNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)E
or$/;
jQuery.Defe
ed.exceptionHook = function( e
or, stack ) {
    
Support: IE 8 - 9 only
    
Console exists when dev tools are open, which can happen at any time
    if ( window.console && window.console.warn && e
or && re
orNames.test( e
or.name ) ) {
        window.console.warn( "jQuery.Defe
ed exception: " + e
or.message, e
or.stack, stack );
    }
};
jQuery.readyException = function( e
or ) {
    window.setTimeout( function() {
        throw e
or;
    } );
};
The defe
ed used on DOM ready
var readyList = jQuery.Defe
ed();
jQuery.fn.ready = function( fn ) {
    readyList
        .then( fn )
        
Wrap jQuery.readyException in a function so that the lookup
        
happens at the time of e
or handling instead of callback
        
registration.
        .catch( function( e
or ) {
            jQuery.readyException( e
or );
        } );
    return this;
};
jQuery.extend( {
    
Is the DOM ready to be used? Set to true once it occurs.
    isReady: false,
    
A counter to track how many items to wait for before
    
the ready event fires. See #6781
    readyWait: 1,
    
Handle when the DOM is ready
    ready: function( wait ) {
        
Abort if there are pending holds or we're already ready
        if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
            return;
        }
        
Remember that the DOM is ready
        jQuery.isReady = true;
        
If a normal DOM Ready event fired, decrement, and wait if need be
        if ( wait !== true && --jQuery.readyWait > 0 ) {
            return;
        }
        
If there are functions bound, to execute
        readyList.resolveWith( document, [ jQuery ] );
    }
} );
jQuery.ready.then = readyList.then;
The ready event handler and self cleanup method
function completed() {
    document.removeEventListener( "DOMContentLoaded", completed );
    window.removeEventListener( "load", completed );
    jQuery.ready();
}
Catch cases where $(document).ready() is called
after the
owser event has already occu
ed.
Support: IE <=9 - 10 only
Older IE sometimes signals "interactive" too soon
if ( document.readyState === "complete" ||
    ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) {
    
Handle it asynchronously to allow scripts the opportunity to delay ready
    window.setTimeout( jQuery.ready );
} else {
    
Use the handy event callback
    document.addEventListener( "DOMContentLoaded", completed );
    
A fallback to window.onload, that will always work
    window.addEventListener( "load", completed );
}
Multifunctional method to get and set values of a collection
The value/s can optionally be executed if it's a function
var access = function( elems, fn, key, value, chainable, emptyGet, raw ) {
    var i = 0,
        len = elems.length,
        bulk = key == null;
    
Sets many values
    if ( toType( key ) === "object" ) {
        chainable = true;
        for ( i in key ) {
            access( elems, fn, i, key[ i ], true, emptyGet, raw );
        }
    
Sets one value
    } else if ( value !== undefined ) {
        chainable = true;
        if ( !isFunction( value ) ) {
            raw = true;
        }
        if ( bulk ) {
            
Bulk operations run against the entire set
            if ( raw ) {
                fn.call( elems, value );
                fn = null;
            
...except when executing function values
            } else {
                bulk = fn;
                fn = function( elem, key, value ) {
                    return bulk.call( jQuery( elem ), value );
                };
            }
        }
        if ( fn ) {
            for ( ; i < len; i++ ) {
                fn(
                    elems[ i ], key, raw ?
                    value :
                    value.call( elems[ i ], i, fn( elems[ i ], key ) )
                );
            }
        }
    }
    if ( chainable ) {
        return elems;
    }
    
Gets
    if ( bulk ) {
        return fn.call( elems );
    }
    return len ? fn( elems[ 0 ], key ) : emptyGet;
};
Matches dashed string for camelizing
var rmsPrefix = /^-ms-/,
    rdashAlpha = /-([a-z])/g;
Used by camelCase as callback to replace()
function fcamelCase( all, letter ) {
    return letter.toUpperCase();
}
Convert dashed to camelCase; used by the css and data modules
Support: IE <=9 - 11, Edge 12 - 15
Microsoft forgot to hump their vendor prefix (#9572)
function camelCase( string ) {
    return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
}
var acceptData = function( owner ) {
    
Accepts only:
    
- Node
    
- Node.ELEMENT_NODE
    
- Node.DOCUMENT_NODE
    
- Object
    
- Any
    return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType );
};
function Data() {
    this.expando = jQuery.expando + Data.uid++;
}
Data.uid = 1;
Data.prototype = {
    cache: function( owner ) {
        
Check if the owner object already has a cache
        var value = owner[ this.expando ];
        
If not, create one
        if ( !value ) {
            value = {};
            
We can accept data for non-element nodes in modern
owsers,
            
but we should not, see #8335.
            
Always return an empty object.
            if ( acceptData( owner ) ) {
                
If it is a node unlikely to be stringify-ed or looped ove
                
use plain assignment
                if ( owner.nodeType ) {
                    owner[ this.expando ] = value;
                
Otherwise secure it in a non-enumerable property
                
configurable must be true to allow the property to be
                
deleted when data is removed
                } else {
                    Object.defineProperty( owner, this.expando, {
                        value: value,
                        configurable: true
                    } );
                }
            }
        }
        return value;
    },
    set: function( owner, data, value ) {
        var prop,
            cache = this.cache( owner );
        
Handle: [ owner, key, value ] args
        
Always use camelCase key (gh-2257)
        if ( typeof data === "string" ) {
            cache[ camelCase( data ) ] = value;
        
Handle: [ owner, { properties } ] args
        } else {
            
Copy the properties one-by-one to the cache object
            for ( prop in data ) {
                cache[ camelCase( prop ) ] = data[ prop ];
            }
        }
        return cache;
    },
    get: function( owner, key ) {
        return key === undefined ?
            this.cache( owner ) :
            
Always use camelCase key (gh-2257)
            owner[ this.expando ] && owner[ this.expando ][ camelCase( key ) ];
    },
    access: function( owner, key, value ) {
        
In cases where either:
        
        
1. No key was specified
        
2. A string key was specified, but no value provided
        
        
Take the "read" path and allow the get method to determine
        
which value to return, respectively either:
        
        
1. The entire cache object
        
2. The data stored at the key
        
        if ( key === undefined ||
                ( ( key && typeof key === "string" ) && value === undefined ) ) {
            return this.get( owner, key );
        }
        
When the key is not a string, or both a key and value
        
are specified, set or extend (existing objects) with either:
        
        
1. An object of properties
        
2. A key and value
        
        this.set( owner, key, value );
        
Since the "set" path can have two possible entry points
        
return the expected data based on which path was taken[*]
        return value !== undefined ? value : key;
    },
    remove: function( owner, key ) {
        var i,
            cache = owner[ this.expando ];
        if ( cache === undefined ) {
            return;
        }
        if ( key !== undefined ) {
            
Support a
ay or space separated string of keys
            if ( A
ay.isA
ay( key ) ) {
                
If key is an a
ay of keys...
                
We always set camelCase keys, so remove that.
                key = key.map( camelCase );
            } else {
                key = camelCase( key );
                
If a key with the spaces exists, use it.
                
Otherwise, create an a
ay by matching non-whitespace
                key = key in cache ?
                    [ key ] :
                    ( key.match( rnothtmlwhite ) || [] );
            }
            i = key.length;
            while ( i-- ) {
                delete cache[ key[ i ] ];
            }
        }
        
Remove the expando if there's no more data
        if ( key === undefined || jQuery.isEmptyObject( cache ) ) {
            
Support: Chrome <=35 - 45
            
Webkit & Blink performance suffers when deleting properties
            
from DOM nodes, so set to undefined instead
            
https:
ugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted)
            if ( owner.nodeType ) {
                owner[ this.expando ] = undefined;
            } else {
                delete owner[ this.expando ];
            }
        }
    },
    hasData: function( owner ) {
        var cache = owner[ this.expando ];
        return cache !== undefined && !jQuery.isEmptyObject( cache );
    }
};
var dataPriv = new Data();
var dataUser = new Data();
    Implementation Summary
    1. Enforce API surface and semantic compatibility with 1.9.x
anch
    2. Improve the module's maintainability by reducing the storage
        paths to a single mechanism.
    3. Use the same single mechanism to support "private" and "user" data.
    4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData)
    5. Avoid exposing implementation details on user objects (eg. expando properties)
    6. Provide a clear path for implementation upgrade to WeakMap in 2014
var
ace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,
    rmultiDash = /[A-Z]/g;
function getData( data ) {
    if ( data === "true" ) {
        return true;
    }
    if ( data === "false" ) {
        return false;
    }
    if ( data === "null" ) {
        return null;
    }
    
Only convert to a number if it doesn't change the string
    if ( data === +data + "" ) {
        return +data;
    }
    if (
ace.test( data ) ) {
        return JSON.parse( data );
    }
    return data;
}
function dataAttr( elem, key, data ) {
    var name;
    
If nothing was found internally, try to fetch any
    
data from the HTML5 data-* attribute
    if ( data === undefined && elem.nodeType === 1 ) {
        name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase();
        data = elem.getAttribute( name );
        if ( typeof data === "string" ) {
            try {
                data = getData( data );
            } catch ( e ) {}
            
Make sure we set the data so it isn't changed late
            dataUser.set( elem, key, data );
        } else {
            data = undefined;
        }
    }
    return data;
}
jQuery.extend( {
    hasData: function( elem ) {
        return dataUser.hasData( elem ) || dataPriv.hasData( elem );
    },
    data: function( elem, name, data ) {
        return dataUser.access( elem, name, data );
    },
    removeData: function( elem, name ) {
        dataUser.remove( elem, name );
    },
    
TODO: Now that all calls to _data and _removeData have been replaced
    
with direct calls to dataPriv methods, these can be deprecated.
    _data: function( elem, name, data ) {
        return dataPriv.access( elem, name, data );
    },
    _removeData: function( elem, name ) {
        dataPriv.remove( elem, name );
    }
} );
jQuery.fn.extend( {
    data: function( key, value ) {
        var i, name, data,
            elem = this[ 0 ],
            attrs = elem && elem.attributes;
        
Gets all values
        if ( key === undefined ) {
            if ( this.length ) {
                data = dataUser.get( elem );
                if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) {
                    i = attrs.length;
                    while ( i-- ) {
                        
Support: IE 11 only
                        
The attrs elements can be null (#14894)
                        if ( attrs[ i ] ) {
                            name = attrs[ i ].name;
                            if ( name.indexOf( "data-" ) === 0 ) {
                                name = camelCase( name.slice( 5 ) );
                                dataAttr( elem, name, data[ name ] );
                            }
                        }
                    }
                    dataPriv.set( elem, "hasDataAttrs", true );
                }
            }
            return data;
        }
        
Sets multiple values
        if ( typeof key === "object" ) {
            return this.each( function() {
                dataUser.set( this, key );
            } );
        }
        return access( this, function( value ) {
            var data;
            
The calling jQuery object (element matches) is not empty
            
(and therefore has an element appears at this[ 0 ]) and the
            
`value` parameter was not undefined. An empty jQuery object
            
will result in `undefined` for elem = this[ 0 ] which will
            
throw an exception if an attempt to read a data cache is made.
            if ( elem && value === undefined ) {
                
Attempt to get data from the cache
                
The key will always be camelCased in Data
                data = dataUser.get( elem, key );
                if ( data !== undefined ) {
                    return data;
                }
                
Attempt to "discover" the data in
                
HTML5 custom data-* attrs
                data = dataAttr( elem, key );
                if ( data !== undefined ) {
                    return data;
                }
                
We tried really hard, but the data doesn't exist.
                return;
            }
            
Set the data...
            this.each( function() {
                
We always store the camelCased key
                dataUser.set( this, key, value );
            } );
        }, null, value, arguments.length > 1, null, true );
    },
    removeData: function( key ) {
        return this.each( function() {
            dataUser.remove( this, key );
        } );
    }
} );
jQuery.extend( {
    queue: function( elem, type, data ) {
        var queue;
        if ( elem ) {
            type = ( type || "fx" ) + "queue";
            queue = dataPriv.get( elem, type );
            
Speed up dequeue by getting out quickly if this is just a lookup
            if ( data ) {
                if ( !queue || A
ay.isA
ay( data ) ) {
                    queue = dataPriv.access( elem, type, jQuery.makeA
ay( data ) );
                } else {
                    queue.push( data );
                }
            }
            return queue || [];
        }
    },
    dequeue: function( elem, type ) {
        type = type || "fx";
        var queue = jQuery.queue( elem, type ),
            startLength = queue.length,
            fn = queue.shift(),
            hooks = jQuery._queueHooks( elem, type ),
            next = function() {
                jQuery.dequeue( elem, type );
            };
        
If the fx queue is dequeued, always remove the progress sentinel
        if ( fn === "inprogress" ) {
            fn = queue.shift();
            startLength--;
        }
        if ( fn ) {
            
Add a progress sentinel to prevent the fx queue from being
            
automatically dequeued
            if ( type === "fx" ) {
                queue.unshift( "inprogress" );
            }
            
Clear up the last queue stop function
            delete hooks.stop;
            fn.call( elem, next, hooks );
        }
        if ( !startLength && hooks ) {
            hooks.empty.fire();
        }
    },
    
Not public - generate a queueHooks object, or return the cu
ent one
    _queueHooks: function( elem, type ) {
        var key = type + "queueHooks";
        return dataPriv.get( elem, key ) || dataPriv.access( elem, key, {
            empty: jQuery.Callbacks( "once memory" ).add( function() {
                dataPriv.remove( elem, [ type + "queue", key ] );
            } )
        } );
    }
} );
jQuery.fn.extend( {
    queue: function( type, data ) {
        var setter = 2;
        if ( typeof type !== "string" ) {
            data = type;
            type = "fx";
            setter--;
        }
        if ( arguments.length < setter ) {
            return jQuery.queue( this[ 0 ], type );
        }
        return data === undefined ?
            this :
            this.each( function() {
                var queue = jQuery.queue( this, type, data );
                
Ensure a hooks for this queue
                jQuery._queueHooks( this, type );
                if ( type === "fx" && queue[ 0 ] !== "inprogress" ) {
                    jQuery.dequeue( this, type );
                }
            } );
    },
    dequeue: function( type ) {
        return this.each( function() {
            jQuery.dequeue( this, type );
        } );
    },
    clearQueue: function( type ) {
        return this.queue( type || "fx", [] );
    },
    
Get a promise resolved when queues of a certain type
    
are emptied (fx is the type by default)
    promise: function( type, obj ) {
        var tmp,
            count = 1,
            defer = jQuery.Defe
ed(),
            elements = this,
            i = this.length,
            resolve = function() {
                if ( !( --count ) ) {
                    defer.resolveWith( elements, [ elements ] );
                }
            };
        if ( typeof type !== "string" ) {
            obj = type;
            type = undefined;
        }
        type = type || "fx";
        while ( i-- ) {
            tmp = dataPriv.get( elements[ i ], type + "queueHooks" );
            if ( tmp && tmp.empty ) {
                count++;
                tmp.empty.add( resolve );
            }
        }
        resolve();
        return defer.promise( obj );
    }
} );
var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source;
var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" );
var cssExpand = [ "Top", "Right", "Bottom", "Left" ];
var documentElement = document.documentElement;
    var isAttached = function( elem ) {
            return jQuery.contains( elem.ownerDocument, elem );
        },
        composed = { composed: true };
    
Support: IE 9 - 11+, Edge 12 - 18+, iOS 10.0 - 10.2 only
    
Check attachment across shadow DOM boundaries when possible (gh-3504)
    
Support: iOS 10.0-10.2 only
    
Early iOS 10 versions support `attachShadow` but not `getRootNode`,
    
leading to e
ors. We need to check for `getRootNode`.
    if ( documentElement.getRootNode ) {
        isAttached = function( elem ) {
            return jQuery.contains( elem.ownerDocument, elem ) ||
                elem.getRootNode( composed ) === elem.ownerDocument;
        };
    }
var isHiddenWithinTree = function( elem, el ) {
        
isHiddenWithinTree might be called from jQuery#filter function;
        
in that case, element will be second argument
        elem = el || elem;
        
Inline style trumps all
        return elem.style.display === "none" ||
            elem.style.display === "" &&
            
Otherwise, check computed style
            
Support: Firefox <=43 - 45
            
Disconnected elements can have computed display: none, so first confirm that elem is
            
in the document.
            isAttached( elem ) &&
            jQuery.css( elem, "display" ) === "none";
    };
var swap = function( elem, options, callback, args ) {
    var ret, name,
        old = {};
    
Remember the old values, and insert the new ones
    for ( name in options ) {
        old[ name ] = elem.style[ name ];
        elem.style[ name ] = options[ name ];
    }
    ret = callback.apply( elem, args || [] );
    
Revert the old values
    for ( name in options ) {
        elem.style[ name ] = old[ name ];
    }
    return ret;
};
function adjustCSS( elem, prop, valueParts, tween ) {
    var adjusted, scale,
        maxIterations = 20,
        cu
entValue = tween ?
            function() {
                return tween.cur();
            } :
            function() {
                return jQuery.css( elem, prop, "" );
            },
        initial = cu
entValue(),
        unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ),
        
Starting value computation is required for potential unit mismatches
        initialInUnit = elem.nodeType &&
            ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) &&
            rcssNum.exec( jQuery.css( elem, prop ) );
    if ( initialInUnit && initialInUnit[ 3 ] !== unit ) {
        
Support: Firefox <=54
        
Halve the iteration target value to prevent interference from CSS upper bounds (gh-2144)
        initial = initial / 2;
        
Trust units reported by jQuery.css
        unit = unit || initialInUnit[ 3 ];
        
Iteratively approximate from a nonzero starting point
        initialInUnit = +initial || 1;
        while ( maxIterations-- ) {
            
Evaluate and update our best guess (doubling guesses that zero out).
            
Finish if the scale equals or crosses 1 (making the old*new product non-positive).
            jQuery.style( elem, prop, initialInUnit + unit );
            if ( ( 1 - scale ) * ( 1 - ( scale = cu
entValue() / initial || 0.5 ) ) <= 0 ) {
                maxIterations = 0;
            }
            initialInUnit = initialInUnit / scale;
        }
        initialInUnit = initialInUnit * 2;
        jQuery.style( elem, prop, initialInUnit + unit );
        
Make sure we update the tween properties later on
        valueParts = valueParts || [];
    }
    if ( valueParts ) {
        initialInUnit = +initialInUnit || +initial || 0;
        
Apply relative offset (+=/-=) if specified
        adjusted = valueParts[ 1 ] ?
            initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] :
            +valueParts[ 2 ];
        if ( tween ) {
            tween.unit = unit;
            tween.start = initialInUnit;
            tween.end = adjusted;
        }
    }
    return adjusted;
}
var defaultDisplayMap = {};
function getDefaultDisplay( elem ) {
    var temp,
        doc = elem.ownerDocument,
        nodeName = elem.nodeName,
        display = defaultDisplayMap[ nodeName ];
    if ( display ) {
        return display;
    }
    temp = doc.body.appendChild( doc.createElement( nodeName ) );
    display = jQuery.css( temp, "display" );
    temp.parentNode.removeChild( temp );
    if ( display === "none" ) {
        display = "block";
    }
    defaultDisplayMap[ nodeName ] = display;
    return display;
}
function showHide( elements, show ) {
    var display, elem,
        values = [],
        index = 0,
        length = elements.length;
    
Determine new display value for elements that need to change
    for ( ; index < length; index++ ) {
        elem = elements[ index ];
        if ( !elem.style ) {
            continue;
        }
        display = elem.style.display;
        if ( show ) {
            
Since we force visibility upon cascade-hidden elements, an immediate (and slow)
            
check is required in this first loop unless we have a nonempty display value (eithe
            
inline or about-to-be-restored)
            if ( display === "none" ) {
                values[ index ] = dataPriv.get( elem, "display" ) || null;
                if ( !values[ index ] ) {
                    elem.style.display = "";
                }
            }
            if ( elem.style.display === "" && isHiddenWithinTree( elem ) ) {
                values[ index ] = getDefaultDisplay( elem );
            }
        } else {
            if ( display !== "none" ) {
                values[ index ] = "none";
                
Remember what we're overwriting
                dataPriv.set( elem, "display", display );
            }
        }
    }
    
Set the display of the elements in a second loop to avoid constant reflow
    for ( index = 0; index < length; index++ ) {
        if ( values[ index ] != null ) {
            elements[ index ].style.display = values[ index ];
        }
    }
    return elements;
}
jQuery.fn.extend( {
    show: function() {
        return showHide( this, true );
    },
    hide: function() {
        return showHide( this );
    },
    toggle: function( state ) {
        if ( typeof state === "boolean" ) {
            return state ? this.show() : this.hide();
        }
        return this.each( function() {
            if ( isHiddenWithinTree( this ) ) {
                jQuery( this ).show();
            } else {
                jQuery( this ).hide();
            }
        } );
    }
} );
var rcheckableType = ( /^(?:checkbox|radio)$/i );
var rtagName = (
([a-z][^\/\0>\x20\t\r\n\f]*)/i );
var rscriptType = ( /^$|^module$|\/(?:java|ecma)script/i );
We have to close these tags to support XHTML (#13200)
var wrapMap = {
    
Support: IE <=9 only
    option: [ 1, "