WordPress.org

Make WordPress Core

Changeset 24781


Ignore:
Timestamp:
07/23/2013 03:28:25 PM (8 years ago)
Author:
nacin
Message:

Use production version of jQuery Migrate when not SCRIPT_DEBUG, which silences issues.

Minify jQuery as well. These were both unminified for ease of debugging.

fixes #24821.

Location:
trunk/wp-includes
Files:
1 added
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/wp-includes/js/jquery/jquery.js

    r24546 r24781  
    1 /*!
    2  * jQuery JavaScript Library v1.10.2
    3  * http://jquery.com/
    4  *
    5  * Includes Sizzle.js
    6  * http://sizzlejs.com/
    7  *
    8  * Copyright 2005, 2013 jQuery Foundation, Inc. and other contributors
    9  * Released under the MIT license
    10  * http://jquery.org/license
    11  *
    12  * Date: 2013-07-03T13:48Z
    13  */
    14 (function( window, undefined ) {
    15 
    16 // Can't do this because several apps including ASP.NET trace
    17 // the stack via arguments.caller.callee and Firefox dies if
    18 // you try to trace through "use strict" call chains. (#13335)
    19 // Support: Firefox 18+
    20 //"use strict";
    21 var
    22     // The deferred used on DOM ready
    23     readyList,
    24 
    25     // A central reference to the root jQuery(document)
    26     rootjQuery,
    27 
    28     // Support: IE<10
    29     // For `typeof xmlNode.method` instead of `xmlNode.method !== undefined`
    30     core_strundefined = typeof undefined,
    31 
    32     // Use the correct document accordingly with window argument (sandbox)
    33     location = window.location,
    34     document = window.document,
    35     docElem = document.documentElement,
    36 
    37     // Map over jQuery in case of overwrite
    38     _jQuery = window.jQuery,
    39 
    40     // Map over the $ in case of overwrite
    41     _$ = window.$,
    42 
    43     // [[Class]] -> type pairs
    44     class2type = {},
    45 
    46     // List of deleted data cache ids, so we can reuse them
    47     core_deletedIds = [],
    48 
    49     core_version = "1.10.2",
    50 
    51     // Save a reference to some core methods
    52     core_concat = core_deletedIds.concat,
    53     core_push = core_deletedIds.push,
    54     core_slice = core_deletedIds.slice,
    55     core_indexOf = core_deletedIds.indexOf,
    56     core_toString = class2type.toString,
    57     core_hasOwn = class2type.hasOwnProperty,
    58     core_trim = core_version.trim,
    59 
    60     // Define a local copy of jQuery
    61     jQuery = function( selector, context ) {
    62         // The jQuery object is actually just the init constructor 'enhanced'
    63         return new jQuery.fn.init( selector, context, rootjQuery );
    64     },
    65 
    66     // Used for matching numbers
    67     core_pnum = /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,
    68 
    69     // Used for splitting on whitespace
    70     core_rnotwhite = /\S+/g,
    71 
    72     // Make sure we trim BOM and NBSP (here's looking at you, Safari 5.0 and IE)
    73     rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,
    74 
    75     // A simple way to check for HTML strings
    76     // Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
    77     // Strict HTML recognition (#11290: must start with <)
    78     rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,
    79 
    80     // Match a standalone tag
    81     rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>|)$/,
    82 
    83     // JSON RegExp
    84     rvalidchars = /^[\],:{}\s]*$/,
    85     rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g,
    86     rvalidescape = /\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,
    87     rvalidtokens = /"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g,
    88 
    89     // Matches dashed string for camelizing
    90     rmsPrefix = /^-ms-/,
    91     rdashAlpha = /-([\da-z])/gi,
    92 
    93     // Used by jQuery.camelCase as callback to replace()
    94     fcamelCase = function( all, letter ) {
    95         return letter.toUpperCase();
    96     },
    97 
    98     // The ready event handler
    99     completed = function( event ) {
    100 
    101         // readyState === "complete" is good enough for us to call the dom ready in oldIE
    102         if ( document.addEventListener || event.type === "load" || document.readyState === "complete" ) {
    103             detach();
    104             jQuery.ready();
    105         }
    106     },
    107     // Clean-up method for dom ready events
    108     detach = function() {
    109         if ( document.addEventListener ) {
    110             document.removeEventListener( "DOMContentLoaded", completed, false );
    111             window.removeEventListener( "load", completed, false );
    112 
    113         } else {
    114             document.detachEvent( "onreadystatechange", completed );
    115             window.detachEvent( "onload", completed );
    116         }
    117     };
    118 
    119 jQuery.fn = jQuery.prototype = {
    120     // The current version of jQuery being used
    121     jquery: core_version,
    122 
    123     constructor: jQuery,
    124     init: function( selector, context, rootjQuery ) {
    125         var match, elem;
    126 
    127         // HANDLE: $(""), $(null), $(undefined), $(false)
    128         if ( !selector ) {
    129             return this;
    130         }
    131 
    132         // Handle HTML strings
    133         if ( typeof selector === "string" ) {
    134             if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
    135                 // Assume that strings that start and end with <> are HTML and skip the regex check
    136                 match = [ null, selector, null ];
    137 
    138             } else {
    139                 match = rquickExpr.exec( selector );
    140             }
    141 
    142             // Match html or make sure no context is specified for #id
    143             if ( match && (match[1] || !context) ) {
    144 
    145                 // HANDLE: $(html) -> $(array)
    146                 if ( match[1] ) {
    147                     context = context instanceof jQuery ? context[0] : context;
    148 
    149                     // scripts is true for back-compat
    150                     jQuery.merge( this, jQuery.parseHTML(
    151                         match[1],
    152                         context && context.nodeType ? context.ownerDocument || context : document,
    153                         true
    154                     ) );
    155 
    156                     // HANDLE: $(html, props)
    157                     if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {
    158                         for ( match in context ) {
    159                             // Properties of context are called as methods if possible
    160                             if ( jQuery.isFunction( this[ match ] ) ) {
    161                                 this[ match ]( context[ match ] );
    162 
    163                             // ...and otherwise set as attributes
    164                             } else {
    165                                 this.attr( match, context[ match ] );
    166                             }
    167                         }
    168                     }
    169 
    170                     return this;
    171 
    172                 // HANDLE: $(#id)
    173                 } else {
    174                     elem = document.getElementById( match[2] );
    175 
    176                     // Check parentNode to catch when Blackberry 4.6 returns
    177                     // nodes that are no longer in the document #6963
    178                     if ( elem && elem.parentNode ) {
    179                         // Handle the case where IE and Opera return items
    180                         // by name instead of ID
    181                         if ( elem.id !== match[2] ) {
    182                             return rootjQuery.find( selector );
    183                         }
    184 
    185                         // Otherwise, we inject the element directly into the jQuery object
    186                         this.length = 1;
    187                         this[0] = elem;
    188                     }
    189 
    190                     this.context = document;
    191                     this.selector = selector;
    192                     return this;
    193                 }
    194 
    195             // HANDLE: $(expr, $(...))
    196             } else if ( !context || context.jquery ) {
    197                 return ( context || rootjQuery ).find( selector );
    198 
    199             // HANDLE: $(expr, context)
    200             // (which is just equivalent to: $(context).find(expr)
    201             } else {
    202                 return this.constructor( context ).find( selector );
    203             }
    204 
    205         // HANDLE: $(DOMElement)
    206         } else if ( selector.nodeType ) {
    207             this.context = this[0] = selector;
    208             this.length = 1;
    209             return this;
    210 
    211         // HANDLE: $(function)
    212         // Shortcut for document ready
    213         } else if ( jQuery.isFunction( selector ) ) {
    214             return rootjQuery.ready( selector );
    215         }
    216 
    217         if ( selector.selector !== undefined ) {
    218             this.selector = selector.selector;
    219             this.context = selector.context;
    220         }
    221 
    222         return jQuery.makeArray( selector, this );
    223     },
    224 
    225     // Start with an empty selector
    226     selector: "",
    227 
    228     // The default length of a jQuery object is 0
    229     length: 0,
    230 
    231     toArray: function() {
    232         return core_slice.call( this );
    233     },
    234 
    235     // Get the Nth element in the matched element set OR
    236     // Get the whole matched element set as a clean array
    237     get: function( num ) {
    238         return num == null ?
    239 
    240             // Return a 'clean' array
    241             this.toArray() :
    242 
    243             // Return just the object
    244             ( num < 0 ? this[ this.length + num ] : this[ num ] );
    245     },
    246 
    247     // Take an array of elements and push it onto the stack
    248     // (returning the new matched element set)
    249     pushStack: function( elems ) {
    250 
    251         // Build a new jQuery matched element set
    252         var ret = jQuery.merge( this.constructor(), elems );
    253 
    254         // Add the old object onto the stack (as a reference)
    255         ret.prevObject = this;
    256         ret.context = this.context;
    257 
    258         // Return the newly-formed element set
    259         return ret;
    260     },
    261 
    262     // Execute a callback for every element in the matched set.
    263     // (You can seed the arguments with an array of args, but this is
    264     // only used internally.)
    265     each: function( callback, args ) {
    266         return jQuery.each( this, callback, args );
    267     },
    268 
    269     ready: function( fn ) {
    270         // Add the callback
    271         jQuery.ready.promise().done( fn );
    272 
    273         return this;
    274     },
    275 
    276     slice: function() {
    277         return this.pushStack( core_slice.apply( this, arguments ) );
    278     },
    279 
    280     first: function() {
    281         return this.eq( 0 );
    282     },
    283 
    284     last: function() {
    285         return this.eq( -1 );
    286     },
    287 
    288     eq: function( i ) {
    289         var len = this.length,
    290             j = +i + ( i < 0 ? len : 0 );
    291         return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] );
    292     },
    293 
    294     map: function( callback ) {
    295         return this.pushStack( jQuery.map(this, function( elem, i ) {
    296             return callback.call( elem, i, elem );
    297         }));
    298     },
    299 
    300     end: function() {
    301         return this.prevObject || this.constructor(null);
    302     },
    303 
    304     // For internal use only.
    305     // Behaves like an Array's method, not like a jQuery method.
    306     push: core_push,
    307     sort: [].sort,
    308     splice: [].splice
    309 };
    310 
    311 // Give the init function the jQuery prototype for later instantiation
    312 jQuery.fn.init.prototype = jQuery.fn;
    313 
    314 jQuery.extend = jQuery.fn.extend = function() {
    315     var src, copyIsArray, copy, name, options, clone,
    316         target = arguments[0] || {},
    317         i = 1,
    318         length = arguments.length,
    319         deep = false;
    320 
    321     // Handle a deep copy situation
    322     if ( typeof target === "boolean" ) {
    323         deep = target;
    324         target = arguments[1] || {};
    325         // skip the boolean and the target
    326         i = 2;
    327     }
    328 
    329     // Handle case when target is a string or something (possible in deep copy)
    330     if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
    331         target = {};
    332     }
    333 
    334     // extend jQuery itself if only one argument is passed
    335     if ( length === i ) {
    336         target = this;
    337         --i;
    338     }
    339 
    340     for ( ; i < length; i++ ) {
    341         // Only deal with non-null/undefined values
    342         if ( (options = arguments[ i ]) != null ) {
    343             // Extend the base object
    344             for ( name in options ) {
    345                 src = target[ name ];
    346                 copy = options[ name ];
    347 
    348                 // Prevent never-ending loop
    349                 if ( target === copy ) {
    350                     continue;
    351                 }
    352 
    353                 // Recurse if we're merging plain objects or arrays
    354                 if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
    355                     if ( copyIsArray ) {
    356                         copyIsArray = false;
    357                         clone = src && jQuery.isArray(src) ? src : [];
    358 
    359                     } else {
    360                         clone = src && jQuery.isPlainObject(src) ? src : {};
    361                     }
    362 
    363                     // Never move original objects, clone them
    364                     target[ name ] = jQuery.extend( deep, clone, copy );
    365 
    366                 // Don't bring in undefined values
    367                 } else if ( copy !== undefined ) {
    368                     target[ name ] = copy;
    369                 }
    370             }
    371         }
    372     }
    373 
    374     // Return the modified object
    375     return target;
    376 };
    377 
    378 jQuery.extend({
    379     // Unique for each copy of jQuery on the page
    380     // Non-digits removed to match rinlinejQuery
    381     expando: "jQuery" + ( core_version + Math.random() ).replace( /\D/g, "" ),
    382 
    383     noConflict: function( deep ) {
    384         if ( window.$ === jQuery ) {
    385             window.$ = _$;
    386         }
    387 
    388         if ( deep && window.jQuery === jQuery ) {
    389             window.jQuery = _jQuery;
    390         }
    391 
    392         return jQuery;
    393     },
    394 
    395     // Is the DOM ready to be used? Set to true once it occurs.
    396     isReady: false,
    397 
    398     // A counter to track how many items to wait for before
    399     // the ready event fires. See #6781
    400     readyWait: 1,
    401 
    402     // Hold (or release) the ready event
    403     holdReady: function( hold ) {
    404         if ( hold ) {
    405             jQuery.readyWait++;
    406         } else {
    407             jQuery.ready( true );
    408         }
    409     },
    410 
    411     // Handle when the DOM is ready
    412     ready: function( wait ) {
    413 
    414         // Abort if there are pending holds or we're already ready
    415         if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
    416             return;
    417         }
    418 
    419         // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
    420         if ( !document.body ) {
    421             return setTimeout( jQuery.ready );
    422         }
    423 
    424         // Remember that the DOM is ready
    425         jQuery.isReady = true;
    426 
    427         // If a normal DOM Ready event fired, decrement, and wait if need be
    428         if ( wait !== true && --jQuery.readyWait > 0 ) {
    429             return;
    430         }
    431 
    432         // If there are functions bound, to execute
    433         readyList.resolveWith( document, [ jQuery ] );
    434 
    435         // Trigger any bound ready events
    436         if ( jQuery.fn.trigger ) {
    437             jQuery( document ).trigger("ready").off("ready");
    438         }
    439     },
    440 
    441     // See test/unit/core.js for details concerning isFunction.
    442     // Since version 1.3, DOM methods and functions like alert
    443     // aren't supported. They return false on IE (#2968).
    444     isFunction: function( obj ) {
    445         return jQuery.type(obj) === "function";
    446     },
    447 
    448     isArray: Array.isArray || function( obj ) {
    449         return jQuery.type(obj) === "array";
    450     },
    451 
    452     isWindow: function( obj ) {
    453         /* jshint eqeqeq: false */
    454         return obj != null && obj == obj.window;
    455     },
    456 
    457     isNumeric: function( obj ) {
    458         return !isNaN( parseFloat(obj) ) && isFinite( obj );
    459     },
    460 
    461     type: function( obj ) {
    462         if ( obj == null ) {
    463             return String( obj );
    464         }
    465         return typeof obj === "object" || typeof obj === "function" ?
    466             class2type[ core_toString.call(obj) ] || "object" :
    467             typeof obj;
    468     },
    469 
    470     isPlainObject: function( obj ) {
    471         var key;
    472 
    473         // Must be an Object.
    474         // Because of IE, we also have to check the presence of the constructor property.
    475         // Make sure that DOM nodes and window objects don't pass through, as well
    476         if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
    477             return false;
    478         }
    479 
    480         try {
    481             // Not own constructor property must be Object
    482             if ( obj.constructor &&
    483                 !core_hasOwn.call(obj, "constructor") &&
    484                 !core_hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
    485                 return false;
    486             }
    487         } catch ( e ) {
    488             // IE8,9 Will throw exceptions on certain host objects #9897
    489             return false;
    490         }
    491 
    492         // Support: IE<9
    493         // Handle iteration over inherited properties before own properties.
    494         if ( jQuery.support.ownLast ) {
    495             for ( key in obj ) {
    496                 return core_hasOwn.call( obj, key );
    497             }
    498         }
    499 
    500         // Own properties are enumerated firstly, so to speed up,
    501         // if last one is own, then all properties are own.
    502         for ( key in obj ) {}
    503 
    504         return key === undefined || core_hasOwn.call( obj, key );
    505     },
    506 
    507     isEmptyObject: function( obj ) {
    508         var name;
    509         for ( name in obj ) {
    510             return false;
    511         }
    512         return true;
    513     },
    514 
    515     error: function( msg ) {
    516         throw new Error( msg );
    517     },
    518 
    519     // data: string of html
    520     // context (optional): If specified, the fragment will be created in this context, defaults to document
    521     // keepScripts (optional): If true, will include scripts passed in the html string
    522     parseHTML: function( data, context, keepScripts ) {
    523         if ( !data || typeof data !== "string" ) {
    524             return null;
    525         }
    526         if ( typeof context === "boolean" ) {
    527             keepScripts = context;
    528             context = false;
    529         }
    530         context = context || document;
    531 
    532         var parsed = rsingleTag.exec( data ),
    533             scripts = !keepScripts && [];
    534 
    535         // Single tag
    536         if ( parsed ) {
    537             return [ context.createElement( parsed[1] ) ];
    538         }
    539 
    540         parsed = jQuery.buildFragment( [ data ], context, scripts );
    541         if ( scripts ) {
    542             jQuery( scripts ).remove();
    543         }
    544         return jQuery.merge( [], parsed.childNodes );
    545     },
    546 
    547     parseJSON: function( data ) {
    548         // Attempt to parse using the native JSON parser first
    549         if ( window.JSON && window.JSON.parse ) {
    550             return window.JSON.parse( data );
    551         }
    552 
    553         if ( data === null ) {
    554             return data;
    555         }
    556 
    557         if ( typeof data === "string" ) {
    558 
    559             // Make sure leading/trailing whitespace is removed (IE can't handle it)
    560             data = jQuery.trim( data );
    561 
    562             if ( data ) {
    563                 // Make sure the incoming data is actual JSON
    564                 // Logic borrowed from http://json.org/json2.js
    565                 if ( rvalidchars.test( data.replace( rvalidescape, "@" )
    566                     .replace( rvalidtokens, "]" )
    567                     .replace( rvalidbraces, "")) ) {
    568 
    569                     return ( new Function( "return " + data ) )();
    570                 }
    571             }
    572         }
    573 
    574         jQuery.error( "Invalid JSON: " + data );
    575     },
    576 
    577     // Cross-browser xml parsing
    578     parseXML: function( data ) {
    579         var xml, tmp;
    580         if ( !data || typeof data !== "string" ) {
    581             return null;
    582         }
    583         try {
    584             if ( window.DOMParser ) { // Standard
    585                 tmp = new DOMParser();
    586                 xml = tmp.parseFromString( data , "text/xml" );
    587             } else { // IE
    588                 xml = new ActiveXObject( "Microsoft.XMLDOM" );
    589                 xml.async = "false";
    590                 xml.loadXML( data );
    591             }
    592         } catch( e ) {
    593             xml = undefined;
    594         }
    595         if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) {
    596             jQuery.error( "Invalid XML: " + data );
    597         }
    598         return xml;
    599     },
    600 
    601     noop: function() {},
    602 
    603     // Evaluates a script in a global context
    604     // Workarounds based on findings by Jim Driscoll
    605     // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context
    606     globalEval: function( data ) {
    607         if ( data && jQuery.trim( data ) ) {
    608             // We use execScript on Internet Explorer
    609             // We use an anonymous function so that context is window
    610             // rather than jQuery in Firefox
    611             ( window.execScript || function( data ) {
    612                 window[ "eval" ].call( window, data );
    613             } )( data );
    614         }
    615     },
    616 
    617     // Convert dashed to camelCase; used by the css and data modules
    618     // Microsoft forgot to hump their vendor prefix (#9572)
    619     camelCase: function( string ) {
    620         return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
    621     },
    622 
    623     nodeName: function( elem, name ) {
    624         return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
    625     },
    626 
    627     // args is for internal usage only
    628     each: function( obj, callback, args ) {
    629         var value,
    630             i = 0,
    631             length = obj.length,
    632             isArray = isArraylike( obj );
    633 
    634         if ( args ) {
    635             if ( isArray ) {
    636                 for ( ; i < length; i++ ) {
    637                     value = callback.apply( obj[ i ], args );
    638 
    639                     if ( value === false ) {
    640                         break;
    641                     }
    642                 }
    643             } else {
    644                 for ( i in obj ) {
    645                     value = callback.apply( obj[ i ], args );
    646 
    647                     if ( value === false ) {
    648                         break;
    649                     }
    650                 }
    651             }
    652 
    653         // A special, fast, case for the most common use of each
    654         } else {
    655             if ( isArray ) {
    656                 for ( ; i < length; i++ ) {
    657                     value = callback.call( obj[ i ], i, obj[ i ] );
    658 
    659                     if ( value === false ) {
    660                         break;
    661                     }
    662                 }
    663             } else {
    664                 for ( i in obj ) {
    665                     value = callback.call( obj[ i ], i, obj[ i ] );
    666 
    667                     if ( value === false ) {
    668                         break;
    669                     }
    670                 }
    671             }
    672         }
    673 
    674         return obj;
    675     },
    676 
    677     // Use native String.trim function wherever possible
    678     trim: core_trim && !core_trim.call("\uFEFF\xA0") ?
    679         function( text ) {
    680             return text == null ?
    681                 "" :
    682                 core_trim.call( text );
    683         } :
    684 
    685         // Otherwise use our own trimming functionality
    686         function( text ) {
    687             return text == null ?
    688                 "" :
    689                 ( text + "" ).replace( rtrim, "" );
    690         },
    691 
    692     // results is for internal usage only
    693     makeArray: function( arr, results ) {
    694         var ret = results || [];
    695 
    696         if ( arr != null ) {
    697             if ( isArraylike( Object(arr) ) ) {
    698                 jQuery.merge( ret,
    699                     typeof arr === "string" ?
    700                     [ arr ] : arr
    701                 );
    702             } else {
    703                 core_push.call( ret, arr );
    704             }
    705         }
    706 
    707         return ret;
    708     },
    709 
    710     inArray: function( elem, arr, i ) {
    711         var len;
    712 
    713         if ( arr ) {
    714             if ( core_indexOf ) {
    715                 return core_indexOf.call( arr, elem, i );
    716             }
    717 
    718             len = arr.length;
    719             i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;
    720 
    721             for ( ; i < len; i++ ) {
    722                 // Skip accessing in sparse arrays
    723                 if ( i in arr && arr[ i ] === elem ) {
    724                     return i;
    725                 }
    726             }
    727         }
    728 
    729         return -1;
    730     },
    731 
    732     merge: function( first, second ) {
    733         var l = second.length,
    734             i = first.length,
    735             j = 0;
    736 
    737         if ( typeof l === "number" ) {
    738             for ( ; j < l; j++ ) {
    739                 first[ i++ ] = second[ j ];
    740             }
    741         } else {
    742             while ( second[j] !== undefined ) {
    743                 first[ i++ ] = second[ j++ ];
    744             }
    745         }
    746 
    747         first.length = i;
    748 
    749         return first;
    750     },
    751 
    752     grep: function( elems, callback, inv ) {
    753         var retVal,
    754             ret = [],
    755             i = 0,
    756             length = elems.length;
    757         inv = !!inv;
    758 
    759         // Go through the array, only saving the items
    760         // that pass the validator function
    761         for ( ; i < length; i++ ) {
    762             retVal = !!callback( elems[ i ], i );
    763             if ( inv !== retVal ) {
    764                 ret.push( elems[ i ] );
    765             }
    766         }
    767 
    768         return ret;
    769     },
    770 
    771     // arg is for internal usage only
    772     map: function( elems, callback, arg ) {
    773         var value,
    774             i = 0,
    775             length = elems.length,
    776             isArray = isArraylike( elems ),
    777             ret = [];
    778 
    779         // Go through the array, translating each of the items to their
    780         if ( isArray ) {
    781             for ( ; i < length; i++ ) {
    782                 value = callback( elems[ i ], i, arg );
    783 
    784                 if ( value != null ) {
    785                     ret[ ret.length ] = value;
    786                 }
    787             }
    788 
    789         // Go through every key on the object,
    790         } else {
    791             for ( i in elems ) {
    792                 value = callback( elems[ i ], i, arg );
    793 
    794                 if ( value != null ) {
    795                     ret[ ret.length ] = value;
    796                 }
    797             }
    798         }
    799 
    800         // Flatten any nested arrays
    801         return core_concat.apply( [], ret );
    802     },
    803 
    804     // A global GUID counter for objects
    805     guid: 1,
    806 
    807     // Bind a function to a context, optionally partially applying any
    808     // arguments.
    809     proxy: function( fn, context ) {
    810         var args, proxy, tmp;
    811 
    812         if ( typeof context === "string" ) {
    813             tmp = fn[ context ];
    814             context = fn;
    815             fn = tmp;
    816         }
    817 
    818         // Quick check to determine if target is callable, in the spec
    819         // this throws a TypeError, but we will just return undefined.
    820         if ( !jQuery.isFunction( fn ) ) {
    821             return undefined;
    822         }
    823 
    824         // Simulated bind
    825         args = core_slice.call( arguments, 2 );
    826         proxy = function() {
    827             return fn.apply( context || this, args.concat( core_slice.call( arguments ) ) );
    828         };
    829 
    830         // Set the guid of unique handler to the same of original handler, so it can be removed
    831         proxy.guid = fn.guid = fn.guid || jQuery.guid++;
    832 
    833         return proxy;
    834     },
    835 
    836     // Multifunctional method to get and set values of a collection
    837     // The value/s can optionally be executed if it's a function
    838     access: function( elems, fn, key, value, chainable, emptyGet, raw ) {
    839         var i = 0,
    840             length = elems.length,
    841             bulk = key == null;
    842 
    843         // Sets many values
    844         if ( jQuery.type( key ) === "object" ) {
    845             chainable = true;
    846             for ( i in key ) {
    847                 jQuery.access( elems, fn, i, key[i], true, emptyGet, raw );
    848             }
    849 
    850         // Sets one value
    851         } else if ( value !== undefined ) {
    852             chainable = true;
    853 
    854             if ( !jQuery.isFunction( value ) ) {
    855                 raw = true;
    856             }
    857 
    858             if ( bulk ) {
    859                 // Bulk operations run against the entire set
    860                 if ( raw ) {
    861                     fn.call( elems, value );
    862                     fn = null;
    863 
    864                 // ...except when executing function values
    865                 } else {
    866                     bulk = fn;
    867                     fn = function( elem, key, value ) {
    868                         return bulk.call( jQuery( elem ), value );
    869                     };
    870                 }
    871             }
    872 
    873             if ( fn ) {
    874                 for ( ; i < length; i++ ) {
    875                     fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) );
    876                 }
    877             }
    878         }
    879 
    880         return chainable ?
    881             elems :
    882 
    883             // Gets
    884             bulk ?
    885                 fn.call( elems ) :
    886                 length ? fn( elems[0], key ) : emptyGet;
    887     },
    888 
    889     now: function() {
    890         return ( new Date() ).getTime();
    891     },
    892 
    893     // A method for quickly swapping in/out CSS properties to get correct calculations.
    894     // Note: this method belongs to the css module but it's needed here for the support module.
    895     // If support gets modularized, this method should be moved back to the css module.
    896     swap: function( elem, options, callback, args ) {
    897         var ret, name,
    898             old = {};
    899 
    900         // Remember the old values, and insert the new ones
    901         for ( name in options ) {
    902             old[ name ] = elem.style[ name ];
    903             elem.style[ name ] = options[ name ];
    904         }
    905 
    906         ret = callback.apply( elem, args || [] );
    907 
    908         // Revert the old values
    909         for ( name in options ) {
    910             elem.style[ name ] = old[ name ];
    911         }
    912 
    913         return ret;
    914     }
    915 });
    916 
    917 jQuery.ready.promise = function( obj ) {
    918     if ( !readyList ) {
    919 
    920         readyList = jQuery.Deferred();
    921 
    922         // Catch cases where $(document).ready() is called after the browser event has already occurred.
    923         // we once tried to use readyState "interactive" here, but it caused issues like the one
    924         // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15
    925         if ( document.readyState === "complete" ) {
    926             // Handle it asynchronously to allow scripts the opportunity to delay ready
    927             setTimeout( jQuery.ready );
    928 
    929         // Standards-based browsers support DOMContentLoaded
    930         } else if ( document.addEventListener ) {
    931             // Use the handy event callback
    932             document.addEventListener( "DOMContentLoaded", completed, false );
    933 
    934             // A fallback to window.onload, that will always work
    935             window.addEventListener( "load", completed, false );
    936 
    937         // If IE event model is used
    938         } else {
    939             // Ensure firing before onload, maybe late but safe also for iframes
    940             document.attachEvent( "onreadystatechange", completed );
    941 
    942             // A fallback to window.onload, that will always work
    943             window.attachEvent( "onload", completed );
    944 
    945             // If IE and not a frame
    946             // continually check to see if the document is ready
    947             var top = false;
    948 
    949             try {
    950                 top = window.frameElement == null && document.documentElement;
    951             } catch(e) {}
    952 
    953             if ( top && top.doScroll ) {
    954                 (function doScrollCheck() {
    955                     if ( !jQuery.isReady ) {
    956 
    957                         try {
    958                             // Use the trick by Diego Perini
    959                             // http://javascript.nwbox.com/IEContentLoaded/
    960                             top.doScroll("left");
    961                         } catch(e) {
    962                             return setTimeout( doScrollCheck, 50 );
    963                         }
    964 
    965                         // detach all dom ready events
    966                         detach();
    967 
    968                         // and execute any waiting functions
    969                         jQuery.ready();
    970                     }
    971                 })();
    972             }
    973         }
    974     }
    975     return readyList.promise( obj );
    976 };
    977 
    978 // Populate the class2type map
    979 jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {
    980     class2type[ "[object " + name + "]" ] = name.toLowerCase();
    981 });
    982 
    983 function isArraylike( obj ) {
    984     var length = obj.length,
    985         type = jQuery.type( obj );
    986 
    987     if ( jQuery.isWindow( obj ) ) {
    988         return false;
    989     }
    990 
    991     if ( obj.nodeType === 1 && length ) {
    992         return true;
    993     }
    994 
    995     return type === "array" || type !== "function" &&
    996         ( length === 0 ||
    997         typeof length === "number" && length > 0 && ( length - 1 ) in obj );
    998 }
    999 
    1000 // All jQuery objects should point back to these
    1001 rootjQuery = jQuery(document);
    1002 /*!
    1003  * Sizzle CSS Selector Engine v1.10.2
    1004  * http://sizzlejs.com/
    1005  *
    1006  * Copyright 2013 jQuery Foundation, Inc. and other contributors
    1007  * Released under the MIT license
    1008  * http://jquery.org/license
    1009  *
    1010  * Date: 2013-07-03
    1011  */
    1012 (function( window, undefined ) {
    1013 
    1014 var i,
    1015     support,
    1016     cachedruns,
    1017     Expr,
    1018     getText,
    1019     isXML,
    1020     compile,
    1021     outermostContext,
    1022     sortInput,
    1023 
    1024     // Local document vars
    1025     setDocument,
    1026     document,
    1027     docElem,
    1028     documentIsHTML,
    1029     rbuggyQSA,
    1030     rbuggyMatches,
    1031     matches,
    1032     contains,
    1033 
    1034     // Instance-specific data
    1035     expando = "sizzle" + -(new Date()),
    1036     preferredDoc = window.document,
    1037     dirruns = 0,
    1038     done = 0,
    1039     classCache = createCache(),
    1040     tokenCache = createCache(),
    1041     compilerCache = createCache(),
    1042     hasDuplicate = false,
    1043     sortOrder = function( a, b ) {
    1044         if ( a === b ) {
    1045             hasDuplicate = true;
    1046             return 0;
    1047         }
    1048         return 0;
    1049     },
    1050 
    1051     // General-purpose constants
    1052     strundefined = typeof undefined,
    1053     MAX_NEGATIVE = 1 << 31,
    1054 
    1055     // Instance methods
    1056     hasOwn = ({}).hasOwnProperty,
    1057     arr = [],
    1058     pop = arr.pop,
    1059     push_native = arr.push,
    1060     push = arr.push,
    1061     slice = arr.slice,
    1062     // Use a stripped-down indexOf if we can't use a native one
    1063     indexOf = arr.indexOf || function( elem ) {
    1064         var i = 0,
    1065             len = this.length;
    1066         for ( ; i < len; i++ ) {
    1067             if ( this[i] === elem ) {
    1068                 return i;
    1069             }
    1070         }
    1071         return -1;
    1072     },
    1073 
    1074     booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",
    1075 
    1076     // Regular expressions
    1077 
    1078     // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace
    1079     whitespace = "[\\x20\\t\\r\\n\\f]",
    1080     // http://www.w3.org/TR/css3-syntax/#characters
    1081     characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",
    1082 
    1083     // Loosely modeled on CSS identifier characters
    1084     // An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors
    1085     // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
    1086     identifier = characterEncoding.replace( "w", "w#" ),
    1087 
    1088     // Acceptable operators http://www.w3.org/TR/selectors/#attribute-selectors
    1089     attributes = "\\[" + whitespace + "*(" + characterEncoding + ")" + whitespace +
    1090         "*(?:([*^$|!~]?=)" + whitespace + "*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|(" + identifier + ")|)|)" + whitespace + "*\\]",
    1091 
    1092     // Prefer arguments quoted,
    1093     //   then not containing pseudos/brackets,
    1094     //   then attribute selectors/non-parenthetical expressions,
    1095     //   then anything else
    1096     // These preferences are here to reduce the number of selectors
    1097     //   needing tokenize in the PSEUDO preFilter
    1098     pseudos = ":(" + characterEncoding + ")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|" + attributes.replace( 3, 8 ) + ")*)|.*)\\)|)",
    1099 
    1100     // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
    1101     rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),
    1102 
    1103     rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
    1104     rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ),
    1105 
    1106     rsibling = new RegExp( whitespace + "*[+~]" ),
    1107     rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*)" + whitespace + "*\\]", "g" ),
    1108 
    1109     rpseudo = new RegExp( pseudos ),
    1110     ridentifier = new RegExp( "^" + identifier + "$" ),
    1111 
    1112     matchExpr = {
    1113         "ID": new RegExp( "^#(" + characterEncoding + ")" ),
    1114         "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ),
    1115         "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ),
    1116         "ATTR": new RegExp( "^" + attributes ),
    1117         "PSEUDO": new RegExp( "^" + pseudos ),
    1118         "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
    1119             "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
    1120             "*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
    1121         "bool": new RegExp( "^(?:" + booleans + ")$", "i" ),
    1122         // For use in libraries implementing .is()
    1123         // We use this for POS matching in `select`
    1124         "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
    1125             whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
    1126     },
    1127 
    1128     rnative = /^[^{]+\{\s*\[native \w/,
    1129 
    1130     // Easily-parseable/retrievable ID or TAG or CLASS selectors
    1131     rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
    1132 
    1133     rinputs = /^(?:input|select|textarea|button)$/i,
    1134     rheader = /^h\d$/i,
    1135 
    1136     rescape = /'|\\/g,
    1137 
    1138     // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
    1139     runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ),
    1140     funescape = function( _, escaped, escapedWhitespace ) {
    1141         var high = "0x" + escaped - 0x10000;
    1142         // NaN means non-codepoint
    1143         // Support: Firefox
    1144         // Workaround erroneous numeric interpretation of +"0x"
    1145         return high !== high || escapedWhitespace ?
    1146             escaped :
    1147             // BMP codepoint
    1148             high < 0 ?
    1149                 String.fromCharCode( high + 0x10000 ) :
    1150                 // Supplemental Plane codepoint (surrogate pair)
    1151                 String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
    1152     };
    1153 
    1154 // Optimize for push.apply( _, NodeList )
    1155 try {
    1156     push.apply(
    1157         (arr = slice.call( preferredDoc.childNodes )),
    1158         preferredDoc.childNodes
    1159     );
    1160     // Support: Android<4.0
    1161     // Detect silently failing push.apply
    1162     arr[ preferredDoc.childNodes.length ].nodeType;
    1163 } catch ( e ) {
    1164     push = { apply: arr.length ?
    1165 
    1166         // Leverage slice if possible
    1167         function( target, els ) {
    1168             push_native.apply( target, slice.call(els) );
    1169         } :
    1170 
    1171         // Support: IE<9
    1172         // Otherwise append directly
    1173         function( target, els ) {
    1174             var j = target.length,
    1175                 i = 0;
    1176             // Can't trust NodeList.length
    1177             while ( (target[j++] = els[i++]) ) {}
    1178             target.length = j - 1;
    1179         }
    1180     };
    1181 }
    1182 
    1183 function Sizzle( selector, context, results, seed ) {
    1184     var match, elem, m, nodeType,
    1185         // QSA vars
    1186         i, groups, old, nid, newContext, newSelector;
    1187 
    1188     if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
    1189         setDocument( context );
    1190     }
    1191 
    1192     context = context || document;
    1193     results = results || [];
    1194 
    1195     if ( !selector || typeof selector !== "string" ) {
    1196         return results;
    1197     }
    1198 
    1199     if ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) {
    1200         return [];
    1201     }
    1202 
    1203     if ( documentIsHTML && !seed ) {
    1204 
    1205         // Shortcuts
    1206         if ( (match = rquickExpr.exec( selector )) ) {
    1207             // Speed-up: Sizzle("#ID")
    1208             if ( (m = match[1]) ) {
    1209                 if ( nodeType === 9 ) {
    1210                     elem = context.getElementById( m );
    1211                     // Check parentNode to catch when Blackberry 4.6 returns
    1212                     // nodes that are no longer in the document #6963
    1213                     if ( elem && elem.parentNode ) {
    1214                         // Handle the case where IE, Opera, and Webkit return items
    1215                         // by name instead of ID
    1216                         if ( elem.id === m ) {
    1217                             results.push( elem );
    1218                             return results;
    1219                         }
    1220                     } else {
    1221                         return results;
    1222                     }
    1223                 } else {
    1224                     // Context is not a document
    1225                     if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) &&
    1226                         contains( context, elem ) && elem.id === m ) {
    1227                         results.push( elem );
    1228                         return results;
    1229                     }
    1230                 }
    1231 
    1232             // Speed-up: Sizzle("TAG")
    1233             } else if ( match[2] ) {
    1234                 push.apply( results, context.getElementsByTagName( selector ) );
    1235                 return results;
    1236 
    1237             // Speed-up: Sizzle(".CLASS")
    1238             } else if ( (m = match[3]) && support.getElementsByClassName && context.getElementsByClassName ) {
    1239                 push.apply( results, context.getElementsByClassName( m ) );
    1240                 return results;
    1241             }
    1242         }
    1243 
    1244         // QSA path
    1245         if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {
    1246             nid = old = expando;
    1247             newContext = context;
    1248             newSelector = nodeType === 9 && selector;
    1249 
    1250             // qSA works strangely on Element-rooted queries
    1251             // We can work around this by specifying an extra ID on the root
    1252             // and working up from there (Thanks to Andrew Dupont for the technique)
    1253             // IE 8 doesn't work on object elements
    1254             if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
    1255                 groups = tokenize( selector );
    1256 
    1257                 if ( (old = context.getAttribute("id")) ) {
    1258                     nid = old.replace( rescape, "\\$&" );
    1259                 } else {
    1260                     context.setAttribute( "id", nid );
    1261                 }
    1262                 nid = "[id='" + nid + "'] ";
    1263 
    1264                 i = groups.length;
    1265                 while ( i-- ) {
    1266                     groups[i] = nid + toSelector( groups[i] );
    1267                 }
    1268                 newContext = rsibling.test( selector ) && context.parentNode || context;
    1269                 newSelector = groups.join(",");
    1270             }
    1271 
    1272             if ( newSelector ) {
    1273                 try {
    1274                     push.apply( results,
    1275                         newContext.querySelectorAll( newSelector )
    1276                     );
    1277                     return results;
    1278                 } catch(qsaError) {
    1279                 } finally {
    1280                     if ( !old ) {
    1281                         context.removeAttribute("id");
    1282                     }
    1283                 }
    1284             }
    1285         }
    1286     }
    1287 
    1288     // All others
    1289     return select( selector.replace( rtrim, "$1" ), context, results, seed );
    1290 }
    1291 
    1292 /**
    1293  * Create key-value caches of limited size
    1294  * @returns {Function(string, Object)} Returns the Object data after storing it on itself with
    1295  *  property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
    1296  *  deleting the oldest entry
    1297  */
    1298 function createCache() {
    1299     var keys = [];
    1300 
    1301     function cache( key, value ) {
    1302         // Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
    1303         if ( keys.push( key += " " ) > Expr.cacheLength ) {
    1304             // Only keep the most recent entries
    1305             delete cache[ keys.shift() ];
    1306         }
    1307         return (cache[ key ] = value);
    1308     }
    1309     return cache;
    1310 }
    1311 
    1312 /**
    1313  * Mark a function for special use by Sizzle
    1314  * @param {Function} fn The function to mark
    1315  */
    1316 function markFunction( fn ) {
    1317     fn[ expando ] = true;
    1318     return fn;
    1319 }
    1320 
    1321 /**
    1322  * Support testing using an element
    1323  * @param {Function} fn Passed the created div and expects a boolean result
    1324  */
    1325 function assert( fn ) {
    1326     var div = document.createElement("div");
    1327 
    1328     try {
    1329         return !!fn( div );
    1330     } catch (e) {
    1331         return false;
    1332     } finally {
    1333         // Remove from its parent by default
    1334         if ( div.parentNode ) {
    1335             div.parentNode.removeChild( div );
    1336         }
    1337         // release memory in IE
    1338         div = null;
    1339     }
    1340 }
    1341 
    1342 /**
    1343  * Adds the same handler for all of the specified attrs
    1344  * @param {String} attrs Pipe-separated list of attributes
    1345  * @param {Function} handler The method that will be applied
    1346  */
    1347 function addHandle( attrs, handler ) {
    1348     var arr = attrs.split("|"),
    1349         i = attrs.length;
    1350 
    1351     while ( i-- ) {
    1352         Expr.attrHandle[ arr[i] ] = handler;
    1353     }
    1354 }
    1355 
    1356 /**
    1357  * Checks document order of two siblings
    1358  * @param {Element} a
    1359  * @param {Element} b
    1360  * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b
    1361  */
    1362 function siblingCheck( a, b ) {
    1363     var cur = b && a,
    1364         diff = cur && a.nodeType === 1 && b.nodeType === 1 &&
    1365             ( ~b.sourceIndex || MAX_NEGATIVE ) -
    1366             ( ~a.sourceIndex || MAX_NEGATIVE );
    1367 
    1368     // Use IE sourceIndex if available on both nodes
    1369     if ( diff ) {
    1370         return diff;
    1371     }
    1372 
    1373     // Check if b follows a
    1374     if ( cur ) {
    1375         while ( (cur = cur.nextSibling) ) {
    1376             if ( cur === b ) {
    1377                 return -1;
    1378             }
    1379         }
    1380     }
    1381 
    1382     return a ? 1 : -1;
    1383 }
    1384 
    1385 /**
    1386  * Returns a function to use in pseudos for input types
    1387  * @param {String} type
    1388  */
    1389 function createInputPseudo( type ) {
    1390     return function( elem ) {
    1391         var name = elem.nodeName.toLowerCase();
    1392         return name === "input" && elem.type === type;
    1393     };
    1394 }
    1395 
    1396 /**
    1397  * Returns a function to use in pseudos for buttons
    1398  * @param {String} type
    1399  */
    1400 function createButtonPseudo( type ) {
    1401     return function( elem ) {
    1402         var name = elem.nodeName.toLowerCase();
    1403         return (name === "input" || name === "button") && elem.type === type;
    1404     };
    1405 }
    1406 
    1407 /**
    1408  * Returns a function to use in pseudos for positionals
    1409  * @param {Function} fn
    1410  */
    1411 function createPositionalPseudo( fn ) {
    1412     return markFunction(function( argument ) {
    1413         argument = +argument;
    1414         return markFunction(function( seed, matches ) {
    1415             var j,
    1416                 matchIndexes = fn( [], seed.length, argument ),
    1417                 i = matchIndexes.length;
    1418 
    1419             // Match elements found at the specified indexes
    1420             while ( i-- ) {
    1421                 if ( seed[ (j = matchIndexes[i]) ] ) {
    1422                     seed[j] = !(matches[j] = seed[j]);
    1423                 }
    1424             }
    1425         });
    1426     });
    1427 }
    1428 
    1429 /**
    1430  * Detect xml
    1431  * @param {Element|Object} elem An element or a document
    1432  */
    1433 isXML = Sizzle.isXML = function( elem ) {
    1434     // documentElement is verified for cases where it doesn't yet exist
    1435     // (such as loading iframes in IE - #4833)
    1436     var documentElement = elem && (elem.ownerDocument || elem).documentElement;
    1437     return documentElement ? documentElement.nodeName !== "HTML" : false;
    1438 };
    1439 
    1440 // Expose support vars for convenience
    1441 support = Sizzle.support = {};
    1442 
    1443 /**
    1444  * Sets document-related variables once based on the current document
    1445  * @param {Element|Object} [doc] An element or document object to use to set the document
    1446  * @returns {Object} Returns the current document
    1447  */
    1448 setDocument = Sizzle.setDocument = function( node ) {
    1449     var doc = node ? node.ownerDocument || node : preferredDoc,
    1450         parent = doc.defaultView;
    1451 
    1452     // If no document and documentElement is available, return
    1453     if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
    1454         return document;
    1455     }
    1456 
    1457     // Set our document
    1458     document = doc;
    1459     docElem = doc.documentElement;
    1460 
    1461     // Support tests
    1462     documentIsHTML = !isXML( doc );
    1463 
    1464     // Support: IE>8
    1465     // If iframe document is assigned to "document" variable and if iframe has been reloaded,
    1466     // IE will throw "permission denied" error when accessing "document" variable, see jQuery #13936
    1467     // IE6-8 do not support the defaultView property so parent will be undefined
    1468     if ( parent && parent.attachEvent && parent !== parent.top ) {
    1469         parent.attachEvent( "onbeforeunload", function() {
    1470             setDocument();
    1471         });
    1472     }
    1473 
    1474     /* Attributes
    1475     ---------------------------------------------------------------------- */
    1476 
    1477     // Support: IE<8
    1478     // Verify that getAttribute really returns attributes and not properties (excepting IE8 booleans)
    1479     support.attributes = assert(function( div ) {
    1480         div.className = "i";
    1481         return !div.getAttribute("className");
    1482     });
    1483 
    1484     /* getElement(s)By*
    1485     ---------------------------------------------------------------------- */
    1486 
    1487     // Check if getElementsByTagName("*") returns only elements
    1488     support.getElementsByTagName = assert(function( div ) {
    1489         div.appendChild( doc.createComment("") );
    1490         return !div.getElementsByTagName("*").length;
    1491     });
    1492 
    1493     // Check if getElementsByClassName can be trusted
    1494     support.getElementsByClassName = assert(function( div ) {
    1495         div.innerHTML = "<div class='a'></div><div class='a i'></div>";
    1496 
    1497         // Support: Safari<4
    1498         // Catch class over-caching
    1499         div.firstChild.className = "i";
    1500         // Support: Opera<10
    1501         // Catch gEBCN failure to find non-leading classes
    1502         return div.getElementsByClassName("i").length === 2;
    1503     });
    1504 
    1505     // Support: IE<10
    1506     // Check if getElementById returns elements by name
    1507     // The broken getElementById methods don't pick up programatically-set names,
    1508     // so use a roundabout getElementsByName test
    1509     support.getById = assert(function( div ) {
    1510         docElem.appendChild( div ).id = expando;
    1511         return !doc.getElementsByName || !doc.getElementsByName( expando ).length;
    1512     });
    1513 
    1514     // ID find and filter
    1515     if ( support.getById ) {
    1516         Expr.find["ID"] = function( id, context ) {
    1517             if ( typeof context.getElementById !== strundefined && documentIsHTML ) {
    1518                 var m = context.getElementById( id );
    1519                 // Check parentNode to catch when Blackberry 4.6 returns
    1520                 // nodes that are no longer in the document #6963
    1521                 return m && m.parentNode ? [m] : [];
    1522             }
    1523         };
    1524         Expr.filter["ID"] = function( id ) {
    1525             var attrId = id.replace( runescape, funescape );
    1526             return function( elem ) {
    1527                 return elem.getAttribute("id") === attrId;
    1528             };
    1529         };
    1530     } else {
    1531         // Support: IE6/7
    1532         // getElementById is not reliable as a find shortcut
    1533         delete Expr.find["ID"];
    1534 
    1535         Expr.filter["ID"] =  function( id ) {
    1536             var attrId = id.replace( runescape, funescape );
    1537             return function( elem ) {
    1538                 var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id");
    1539                 return node && node.value === attrId;
    1540             };
    1541         };
    1542     }
    1543 
    1544     // Tag
    1545     Expr.find["TAG"] = support.getElementsByTagName ?
    1546         function( tag, context ) {
    1547             if ( typeof context.getElementsByTagName !== strundefined ) {
    1548                 return context.getElementsByTagName( tag );
    1549             }
    1550         } :
    1551         function( tag, context ) {
    1552             var elem,
    1553                 tmp = [],
    1554                 i = 0,
    1555                 results = context.getElementsByTagName( tag );
    1556 
    1557             // Filter out possible comments
    1558             if ( tag === "*" ) {
    1559                 while ( (elem = results[i++]) ) {
    1560                     if ( elem.nodeType === 1 ) {
    1561                         tmp.push( elem );
    1562                     }
    1563                 }
    1564 
    1565                 return tmp;
    1566             }
    1567             return results;
    1568         };
    1569 
    1570     // Class
    1571     Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) {
    1572         if ( typeof context.getElementsByClassName !== strundefined && documentIsHTML ) {
    1573             return context.getElementsByClassName( className );
    1574         }
    1575     };
    1576 
    1577     /* QSA/matchesSelector
    1578     ---------------------------------------------------------------------- */
    1579 
    1580     // QSA and matchesSelector support
    1581 
    1582     // matchesSelector(:active) reports false when true (IE9/Opera 11.5)
    1583     rbuggyMatches = [];
    1584 
    1585     // qSa(:focus) reports false when true (Chrome 21)
    1586     // We allow this because of a bug in IE8/9 that throws an error
    1587     // whenever `document.activeElement` is accessed on an iframe
    1588     // So, we allow :focus to pass through QSA all the time to avoid the IE error
    1589     // See http://bugs.jquery.com/ticket/13378
    1590     rbuggyQSA = [];
    1591 
    1592     if ( (support.qsa = rnative.test( doc.querySelectorAll )) ) {
    1593         // Build QSA regex
    1594         // Regex strategy adopted from Diego Perini
    1595         assert(function( div ) {
    1596             // Select is set to empty string on purpose
    1597             // This is to test IE's treatment of not explicitly
    1598             // setting a boolean content attribute,
    1599             // since its presence should be enough
    1600             // http://bugs.jquery.com/ticket/12359
    1601             div.innerHTML = "<select><option selected=''></option></select>";
    1602 
    1603             // Support: IE8
    1604             // Boolean attributes and "value" are not treated correctly
    1605             if ( !div.querySelectorAll("[selected]").length ) {
    1606                 rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" );
    1607             }
    1608 
    1609             // Webkit/Opera - :checked should return selected option elements
    1610             // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
    1611             // IE8 throws error here and will not see later tests
    1612             if ( !div.querySelectorAll(":checked").length ) {
    1613                 rbuggyQSA.push(":checked");
    1614             }
    1615         });
    1616 
    1617         assert(function( div ) {
    1618 
    1619             // Support: Opera 10-12/IE8
    1620             // ^= $= *= and empty values
    1621             // Should not select anything
    1622             // Support: Windows 8 Native Apps
    1623             // The type attribute is restricted during .innerHTML assignment
    1624             var input = doc.createElement("input");
    1625             input.setAttribute( "type", "hidden" );
    1626             div.appendChild( input ).setAttribute( "t", "" );
    1627 
    1628             if ( div.querySelectorAll("[t^='']").length ) {
    1629                 rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" );
    1630             }
    1631 
    1632             // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
    1633             // IE8 throws error here and will not see later tests
    1634             if ( !div.querySelectorAll(":enabled").length ) {
    1635                 rbuggyQSA.push( ":enabled", ":disabled" );
    1636             }
    1637 
    1638             // Opera 10-11 does not throw on post-comma invalid pseudos
    1639             div.querySelectorAll("*,:x");
    1640             rbuggyQSA.push(",.*:");
    1641         });
    1642     }
    1643 
    1644     if ( (support.matchesSelector = rnative.test( (matches = docElem.webkitMatchesSelector ||
    1645         docElem.mozMatchesSelector ||
    1646         docElem.oMatchesSelector ||
    1647         docElem.msMatchesSelector) )) ) {
    1648 
    1649         assert(function( div ) {
    1650             // Check to see if it's possible to do matchesSelector
    1651             // on a disconnected node (IE 9)
    1652             support.disconnectedMatch = matches.call( div, "div" );
    1653 
    1654             // This should fail with an exception
    1655             // Gecko does not error, returns false instead
    1656             matches.call( div, "[s!='']:x" );
    1657             rbuggyMatches.push( "!=", pseudos );
    1658         });
    1659     }
    1660 
    1661     rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") );
    1662     rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") );
    1663 
    1664     /* Contains
    1665     ---------------------------------------------------------------------- */
    1666 
    1667     // Element contains another
    1668     // Purposefully does not implement inclusive descendent
    1669     // As in, an element does not contain itself
    1670     contains = rnative.test( docElem.contains ) || docElem.compareDocumentPosition ?
    1671         function( a, b ) {
    1672             var adown = a.nodeType === 9 ? a.documentElement : a,
    1673                 bup = b && b.parentNode;
    1674             return a === bup || !!( bup && bup.nodeType === 1 && (
    1675                 adown.contains ?
    1676                     adown.contains( bup ) :
    1677                     a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
    1678             ));
    1679         } :
    1680         function( a, b ) {
    1681             if ( b ) {
    1682                 while ( (b = b.parentNode) ) {
    1683                     if ( b === a ) {
    1684                         return true;
    1685                     }
    1686                 }
    1687             }
    1688             return false;
    1689         };
    1690 
    1691     /* Sorting
    1692     ---------------------------------------------------------------------- */
    1693 
    1694     // Document order sorting
    1695     sortOrder = docElem.compareDocumentPosition ?
    1696     function( a, b ) {
    1697 
    1698         // Flag for duplicate removal
    1699         if ( a === b ) {
    1700             hasDuplicate = true;
    1701             return 0;
    1702         }
    1703 
    1704         var compare = b.compareDocumentPosition && a.compareDocumentPosition && a.compareDocumentPosition( b );
    1705 
    1706         if ( compare ) {
    1707             // Disconnected nodes
    1708             if ( compare & 1 ||
    1709                 (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {
    1710 
    1711                 // Choose the first element that is related to our preferred document
    1712                 if ( a === doc || contains(preferredDoc, a) ) {
    1713                     return -1;
    1714                 }
    1715                 if ( b === doc || contains(preferredDoc, b) ) {
    1716                     return 1;
    1717                 }
    1718 
    1719                 // Maintain original order
    1720                 return sortInput ?
    1721                     ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) :
    1722                     0;
    1723             }
    1724 
    1725             return compare & 4 ? -1 : 1;
    1726         }
    1727 
    1728         // Not directly comparable, sort on existence of method
    1729         return a.compareDocumentPosition ? -1 : 1;
    1730     } :
    1731     function( a, b ) {
    1732         var cur,
    1733             i = 0,
    1734             aup = a.parentNode,
    1735             bup = b.parentNode,
    1736             ap = [ a ],
    1737             bp = [ b ];
    1738 
    1739         // Exit early if the nodes are identical
    1740         if ( a === b ) {
    1741             hasDuplicate = true;
    1742             return 0;
    1743 
    1744         // Parentless nodes are either documents or disconnected
    1745         } else if ( !aup || !bup ) {
    1746             return a === doc ? -1 :
    1747                 b === doc ? 1 :
    1748                 aup ? -1 :
    1749                 bup ? 1 :
    1750                 sortInput ?
    1751                 ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) :
    1752                 0;
    1753 
    1754         // If the nodes are siblings, we can do a quick check
    1755         } else if ( aup === bup ) {
    1756             return siblingCheck( a, b );
    1757         }
    1758 
    1759         // Otherwise we need full lists of their ancestors for comparison
    1760         cur = a;
    1761         while ( (cur = cur.parentNode) ) {
    1762             ap.unshift( cur );
    1763         }
    1764         cur = b;
    1765         while ( (cur = cur.parentNode) ) {
    1766             bp.unshift( cur );
    1767         }
    1768 
    1769         // Walk down the tree looking for a discrepancy
    1770         while ( ap[i] === bp[i] ) {
    1771             i++;
    1772         }
    1773 
    1774         return i ?
    1775             // Do a sibling check if the nodes have a common ancestor
    1776             siblingCheck( ap[i], bp[i] ) :
    1777 
    1778             // Otherwise nodes in our document sort first
    1779             ap[i] === preferredDoc ? -1 :
    1780             bp[i] === preferredDoc ? 1 :
    1781             0;
    1782     };
    1783 
    1784     return doc;
    1785 };
    1786 
    1787 Sizzle.matches = function( expr, elements ) {
    1788     return Sizzle( expr, null, null, elements );
    1789 };
    1790 
    1791 Sizzle.matchesSelector = function( elem, expr ) {
    1792     // Set document vars if needed
    1793     if ( ( elem.ownerDocument || elem ) !== document ) {
    1794         setDocument( elem );
    1795     }
    1796 
    1797     // Make sure that attribute selectors are quoted
    1798     expr = expr.replace( rattributeQuotes, "='$1']" );
    1799 
    1800     if ( support.matchesSelector && documentIsHTML &&
    1801         ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&
    1802         ( !rbuggyQSA     || !rbuggyQSA.test( expr ) ) ) {
    1803 
    1804         try {
    1805             var ret = matches.call( elem, expr );
    1806 
    1807             // IE 9's matchesSelector returns false on disconnected nodes
    1808             if ( ret || support.disconnectedMatch ||
    1809                     // As well, disconnected nodes are said to be in a document
    1810                     // fragment in IE 9
    1811                     elem.document && elem.document.nodeType !== 11 ) {
    1812                 return ret;
    1813             }
    1814         } catch(e) {}
    1815     }
    1816 
    1817     return Sizzle( expr, document, null, [elem] ).length > 0;
    1818 };
    1819 
    1820 Sizzle.contains = function( context, elem ) {
    1821     // Set document vars if needed
    1822     if ( ( context.ownerDocument || context ) !== document ) {
    1823         setDocument( context );
    1824     }
    1825     return contains( context, elem );
    1826 };
    1827 
    1828 Sizzle.attr = function( elem, name ) {
    1829     // Set document vars if needed
    1830     if ( ( elem.ownerDocument || elem ) !== document ) {
    1831         setDocument( elem );
    1832     }
    1833 
    1834     var fn = Expr.attrHandle[ name.toLowerCase() ],
    1835         // Don't get fooled by Object.prototype properties (jQuery #13807)
    1836         val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?
    1837             fn( elem, name, !documentIsHTML ) :
    1838             undefined;
    1839 
    1840     return val === undefined ?
    1841         support.attributes || !documentIsHTML ?
    1842             elem.getAttribute( name ) :
    1843             (val = elem.getAttributeNode(name)) && val.specified ?
    1844                 val.value :
    1845                 null :
    1846         val;
    1847 };
    1848 
    1849 Sizzle.error = function( msg ) {
    1850     throw new Error( "Syntax error, unrecognized expression: " + msg );
    1851 };
    1852 
    1853 /**
    1854  * Document sorting and removing duplicates
    1855  * @param {ArrayLike} results
    1856  */
    1857 Sizzle.uniqueSort = function( results ) {
    1858     var elem,
    1859         duplicates = [],
    1860         j = 0,
    1861         i = 0;
    1862 
    1863     // Unless we *know* we can detect duplicates, assume their presence
    1864     hasDuplicate = !support.detectDuplicates;
    1865     sortInput = !support.sortStable && results.slice( 0 );
    1866     results.sort( sortOrder );
    1867 
    1868     if ( hasDuplicate ) {
    1869         while ( (elem = results[i++]) ) {
    1870             if ( elem === results[ i ] ) {
    1871                 j = duplicates.push( i );
    1872             }
    1873         }
    1874         while ( j-- ) {
    1875             results.splice( duplicates[ j ], 1 );
    1876         }
    1877     }
    1878 
    1879     return results;
    1880 };
    1881 
    1882 /**
    1883  * Utility function for retrieving the text value of an array of DOM nodes
    1884  * @param {Array|Element} elem
    1885  */
    1886 getText = Sizzle.getText = function( elem ) {
    1887     var node,
    1888         ret = "",
    1889         i = 0,
    1890         nodeType = elem.nodeType;
    1891 
    1892     if ( !nodeType ) {
    1893         // If no nodeType, this is expected to be an array
    1894         for ( ; (node = elem[i]); i++ ) {
    1895             // Do not traverse comment nodes
    1896             ret += getText( node );
    1897         }
    1898     } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
    1899         // Use textContent for elements
    1900         // innerText usage removed for consistency of new lines (see #11153)
    1901         if ( typeof elem.textContent === "string" ) {
    1902             return elem.textContent;
    1903         } else {
    1904             // Traverse its children
    1905             for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
    1906                 ret += getText( elem );
    1907             }
    1908         }
    1909     } else if ( nodeType === 3 || nodeType === 4 ) {
    1910         return elem.nodeValue;
    1911     }
    1912     // Do not include comment or processing instruction nodes
    1913 
    1914     return ret;
    1915 };
    1916 
    1917 Expr = Sizzle.selectors = {
    1918 
    1919     // Can be adjusted by the user
    1920     cacheLength: 50,
    1921 
    1922     createPseudo: markFunction,
    1923 
    1924     match: matchExpr,
    1925 
    1926     attrHandle: {},
    1927 
    1928     find: {},
    1929 
    1930     relative: {
    1931         ">": { dir: "parentNode", first: true },
    1932         " ": { dir: "parentNode" },
    1933         "+": { dir: "previousSibling", first: true },
    1934         "~": { dir: "previousSibling" }
    1935     },
    1936 
    1937     preFilter: {
    1938         "ATTR": function( match ) {
    1939             match[1] = match[1].replace( runescape, funescape );
    1940 
    1941             // Move the given value to match[3] whether quoted or unquoted
    1942             match[3] = ( match[4] || match[5] || "" ).replace( runescape, funescape );
    1943 
    1944             if ( match[2] === "~=" ) {
    1945                 match[3] = " " + match[3] + " ";
    1946             }
    1947 
    1948             return match.slice( 0, 4 );
    1949         },
    1950 
    1951         "CHILD": function( match ) {
    1952             /* matches from matchExpr["CHILD"]
    1953                 1 type (only|nth|...)
    1954                 2 what (child|of-type)
    1955                 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
    1956                 4 xn-component of xn+y argument ([+-]?\d*n|)
    1957                 5 sign of xn-component
    1958                 6 x of xn-component
    1959                 7 sign of y-component
    1960                 8 y of y-component
    1961             */
    1962             match[1] = match[1].toLowerCase();
    1963 
    1964             if ( match[1].slice( 0, 3 ) === "nth" ) {
    1965                 // nth-* requires argument
    1966                 if ( !match[3] ) {
    1967                     Sizzle.error( match[0] );
    1968                 }
    1969 
    1970                 // numeric x and y parameters for Expr.filter.CHILD
    1971                 // remember that false/true cast respectively to 0/1
    1972                 match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) );
    1973                 match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" );
    1974 
    1975             // other types prohibit arguments
    1976             } else if ( match[3] ) {
    1977                 Sizzle.error( match[0] );
    1978             }
    1979 
    1980             return match;
    1981         },
    1982 
    1983         "PSEUDO": function( match ) {
    1984             var excess,
    1985                 unquoted = !match[5] && match[2];
    1986 
    1987             if ( matchExpr["CHILD"].test( match[0] ) ) {
    1988                 return null;
    1989             }
    1990 
    1991             // Accept quoted arguments as-is
    1992             if ( match[3] && match[4] !== undefined ) {
    1993                 match[2] = match[4];
    1994 
    1995             // Strip excess characters from unquoted arguments
    1996             } else if ( unquoted && rpseudo.test( unquoted ) &&
    1997                 // Get excess from tokenize (recursively)
    1998                 (excess = tokenize( unquoted, true )) &&
    1999                 // advance to the next closing parenthesis
    2000                 (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {
    2001 
    2002                 // excess is a negative index
    2003                 match[0] = match[0].slice( 0, excess );
    2004                 match[2] = unquoted.slice( 0, excess );
    2005             }
    2006 
    2007             // Return only captures needed by the pseudo filter method (type and argument)
    2008             return match.slice( 0, 3 );
    2009         }
    2010     },
    2011 
    2012     filter: {
    2013 
    2014         "TAG": function( nodeNameSelector ) {
    2015             var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();
    2016             return nodeNameSelector === "*" ?
    2017                 function() { return true; } :
    2018                 function( elem ) {
    2019                     return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
    2020                 };
    2021         },
    2022 
    2023         "CLASS": function( className ) {
    2024             var pattern = classCache[ className + " " ];
    2025 
    2026             return pattern ||
    2027                 (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&
    2028                 classCache( className, function( elem ) {
    2029                     return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== strundefined && elem.getAttribute("class") || "" );
    2030                 });
    2031         },
    2032 
    2033         "ATTR": function( name, operator, check ) {
    2034             return function( elem ) {
    2035                 var result = Sizzle.attr( elem, name );
    2036 
    2037                 if ( result == null ) {
    2038                     return operator === "!=";
    2039                 }
    2040                 if ( !operator ) {
    2041                     return true;
    2042                 }
    2043 
    2044                 result += "";
    2045 
    2046                 return operator === "=" ? result === check :
    2047                     operator === "!=" ? result !== check :
    2048                     operator === "^=" ? check && result.indexOf( check ) === 0 :
    2049                     operator === "*=" ? check && result.indexOf( check ) > -1 :
    2050                     operator === "$=" ? check && result.slice( -check.length ) === check :
    2051                     operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 :
    2052                     operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
    2053                     false;
    2054             };
    2055         },
    2056 
    2057         "CHILD": function( type, what, argument, first, last ) {
    2058             var simple = type.slice( 0, 3 ) !== "nth",
    2059                 forward = type.slice( -4 ) !== "last",
    2060                 ofType = what === "of-type";
    2061 
    2062             return first === 1 && last === 0 ?
    2063 
    2064                 // Shortcut for :nth-*(n)
    2065                 function( elem ) {
    2066                     return !!elem.parentNode;
    2067                 } :
    2068 
    2069                 function( elem, context, xml ) {
    2070                     var cache, outerCache, node, diff, nodeIndex, start,
    2071                         dir = simple !== forward ? "nextSibling" : "previousSibling",
    2072                         parent = elem.parentNode,
    2073                         name = ofType && elem.nodeName.toLowerCase(),
    2074                         useCache = !xml && !ofType;
    2075 
    2076                     if ( parent ) {
    2077 
    2078                         // :(first|last|only)-(child|of-type)
    2079                         if ( simple ) {
    2080                             while ( dir ) {
    2081                                 node = elem;
    2082                                 while ( (node = node[ dir ]) ) {
    2083                                     if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) {
    2084                                         return false;
    2085                                     }
    2086                                 }
    2087                                 // Reverse direction for :only-* (if we haven't yet done so)
    2088                                 start = dir = type === "only" && !start && "nextSibling";
    2089                             }
    2090                             return true;
    2091                         }
    2092 
    2093                         start = [ forward ? parent.firstChild : parent.lastChild ];
    2094 
    2095                         // non-xml :nth-child(...) stores cache data on `parent`
    2096                         if ( forward && useCache ) {
    2097                             // Seek `elem` from a previously-cached index
    2098                             outerCache = parent[ expando ] || (parent[ expando ] = {});
    2099                             cache = outerCache[ type ] || [];
    2100                             nodeIndex = cache[0] === dirruns && cache[1];
    2101                             diff = cache[0] === dirruns && cache[2];
    2102                             node = nodeIndex && parent.childNodes[ nodeIndex ];
    2103 
    2104                             while ( (node = ++nodeIndex && node && node[ dir ] ||
    2105 
    2106                                 // Fallback to seeking `elem` from the start
    2107                                 (diff = nodeIndex = 0) || start.pop()) ) {
    2108 
    2109                                 // When found, cache indexes on `parent` and break
    2110                                 if ( node.nodeType === 1 && ++diff && node === elem ) {
    2111                                     outerCache[ type ] = [ dirruns, nodeIndex, diff ];
    2112                                     break;
    2113                                 }
    2114                             }
    2115 
    2116                         // Use previously-cached element index if available
    2117                         } else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) {
    2118                             diff = cache[1];
    2119 
    2120                         // xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...)
    2121                         } else {
    2122                             // Use the same loop as above to seek `elem` from the start
    2123                             while ( (node = ++nodeIndex && node && node[ dir ] ||
    2124                                 (diff = nodeIndex = 0) || start.pop()) ) {
    2125 
    2126                                 if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) {
    2127                                     // Cache the index of each encountered element
    2128                                     if ( useCache ) {
    2129                                         (node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ];
    2130                                     }
    2131 
    2132                                     if ( node === elem ) {
    2133                                         break;
    2134                                     }
    2135                                 }
    2136                             }
    2137                         }
    2138 
    2139                         // Incorporate the offset, then check against cycle size
    2140                         diff -= last;
    2141                         return diff === first || ( diff % first === 0 && diff / first >= 0 );
    2142                     }
    2143                 };
    2144         },
    2145 
    2146         "PSEUDO": function( pseudo, argument ) {
    2147             // pseudo-class names are case-insensitive
    2148             // http://www.w3.org/TR/selectors/#pseudo-classes
    2149             // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
    2150             // Remember that setFilters inherits from pseudos
    2151             var args,
    2152                 fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
    2153                     Sizzle.error( "unsupported pseudo: " + pseudo );
    2154 
    2155             // The user may use createPseudo to indicate that
    2156             // arguments are needed to create the filter function
    2157             // just as Sizzle does
    2158             if ( fn[ expando ] ) {
    2159                 return fn( argument );
    2160             }
    2161 
    2162             // But maintain support for old signatures
    2163             if ( fn.length > 1 ) {
    2164                 args = [ pseudo, pseudo, "", argument ];
    2165                 return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
    2166                     markFunction(function( seed, matches ) {
    2167                         var idx,
    2168                             matched = fn( seed, argument ),
    2169                             i = matched.length;
    2170                         while ( i-- ) {
    2171                             idx = indexOf.call( seed, matched[i] );
    2172                             seed[ idx ] = !( matches[ idx ] = matched[i] );
    2173                         }
    2174                     }) :
    2175                     function( elem ) {
    2176                         return fn( elem, 0, args );
    2177                     };
    2178             }
    2179 
    2180             return fn;
    2181         }
    2182     },
    2183 
    2184     pseudos: {
    2185         // Potentially complex pseudos
    2186         "not": markFunction(function( selector ) {
    2187             // Trim the selector passed to compile
    2188             // to avoid treating leading and trailing
    2189             // spaces as combinators
    2190             var input = [],
    2191                 results = [],
    2192                 matcher = compile( selector.replace( rtrim, "$1" ) );
    2193 
    2194             return matcher[ expando ] ?
    2195                 markFunction(function( seed, matches, context, xml ) {
    2196                     var elem,
    2197                         unmatched = matcher( seed, null, xml, [] ),
    2198                         i = seed.length;
    2199 
    2200                     // Match elements unmatched by `matcher`
    2201                     while ( i-- ) {
    2202                         if ( (elem = unmatched[i]) ) {
    2203                             seed[i] = !(matches[i] = elem);
    2204                         }
    2205                     }
    2206                 }) :
    2207                 function( elem, context, xml ) {
    2208                     input[0] = elem;
    2209                     matcher( input, null, xml, results );
    2210                     return !results.pop();
    2211                 };
    2212         }),
    2213 
    2214         "has": markFunction(function( selector ) {
    2215             return function( elem ) {
    2216                 return Sizzle( selector, elem ).length > 0;
    2217             };
    2218         }),
    2219 
    2220         "contains": markFunction(function( text ) {
    2221             return function( elem ) {
    2222                 return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
    2223             };
    2224         }),
    2225 
    2226         // "Whether an element is represented by a :lang() selector
    2227         // is based solely on the element's language value
    2228         // being equal to the identifier C,
    2229         // or beginning with the identifier C immediately followed by "-".
    2230         // The matching of C against the element's language value is performed case-insensitively.
    2231         // The identifier C does not have to be a valid language name."
    2232         // http://www.w3.org/TR/selectors/#lang-pseudo
    2233         "lang": markFunction( function( lang ) {
    2234             // lang value must be a valid identifier
    2235             if ( !ridentifier.test(lang || "") ) {
    2236                 Sizzle.error( "unsupported lang: " + lang );
    2237             }
    2238             lang = lang.replace( runescape, funescape ).toLowerCase();
    2239             return function( elem ) {
    2240                 var elemLang;
    2241                 do {
    2242                     if ( (elemLang = documentIsHTML ?
    2243                         elem.lang :
    2244                         elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) {
    2245 
    2246                         elemLang = elemLang.toLowerCase();
    2247                         return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
    2248                     }
    2249                 } while ( (elem = elem.parentNode) && elem.nodeType === 1 );
    2250                 return false;
    2251             };
    2252         }),
    2253 
    2254         // Miscellaneous
    2255         "target": function( elem ) {
    2256             var hash = window.location && window.location.hash;
    2257             return hash && hash.slice( 1 ) === elem.id;
    2258         },
    2259 
    2260         "root": function( elem ) {
    2261             return elem === docElem;
    2262         },
    2263 
    2264         "focus": function( elem ) {
    2265             return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
    2266         },
    2267 
    2268         // Boolean properties
    2269         "enabled": function( elem ) {
    2270             return elem.disabled === false;
    2271         },
    2272 
    2273         "disabled": function( elem ) {
    2274             return elem.disabled === true;
    2275         },
    2276 
    2277         "checked": function( elem ) {
    2278             // In CSS3, :checked should return both checked and selected elements
    2279             // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
    2280             var nodeName = elem.nodeName.toLowerCase();
    2281             return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
    2282         },
    2283 
    2284         "selected": function( elem ) {
    2285             // Accessing this property makes selected-by-default
    2286             // options in Safari work properly
    2287             if ( elem.parentNode ) {
    2288                 elem.parentNode.selectedIndex;
    2289             }
    2290 
    2291             return elem.selected === true;
    2292         },
    2293 
    2294         // Contents
    2295         "empty": function( elem ) {
    2296             // http://www.w3.org/TR/selectors/#empty-pseudo
    2297             // :empty is only affected by element nodes and content nodes(including text(3), cdata(4)),
    2298             //   not comment, processing instructions, or others
    2299             // Thanks to Diego Perini for the nodeName shortcut
    2300             //   Greater than "@" means alpha characters (specifically not starting with "#" or "?")
    2301             for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
    2302                 if ( elem.nodeName > "@" || elem.nodeType === 3 || elem.nodeType === 4 ) {
    2303                     return false;
    2304                 }
    2305             }
    2306             return true;
    2307         },
    2308 
    2309         "parent": function( elem ) {
    2310             return !Expr.pseudos["empty"]( elem );
    2311         },
    2312 
    2313         // Element/input types
    2314         "header": function( elem ) {
    2315             return rheader.test( elem.nodeName );
    2316         },
    2317 
    2318         "input": function( elem ) {
    2319             return rinputs.test( elem.nodeName );
    2320         },
    2321 
    2322         "button": function( elem ) {
    2323             var name = elem.nodeName.toLowerCase();
    2324             return name === "input" && elem.type === "button" || name === "button";
    2325         },
    2326 
    2327         "text": function( elem ) {
    2328             var attr;
    2329             // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc)
    2330             // use getAttribute instead to test this case
    2331             return elem.nodeName.toLowerCase() === "input" &&
    2332                 elem.type === "text" &&
    2333                 ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === elem.type );
    2334         },
    2335 
    2336         // Position-in-collection
    2337         "first": createPositionalPseudo(function() {
    2338             return [ 0 ];
    2339         }),
    2340 
    2341         "last": createPositionalPseudo(function( matchIndexes, length ) {
    2342             return [ length - 1 ];
    2343         }),
    2344 
    2345         "eq": createPositionalPseudo(function( matchIndexes, length, argument ) {
    2346             return [ argument < 0 ? argument + length : argument ];
    2347         }),
    2348 
    2349         "even": createPositionalPseudo(function( matchIndexes, length ) {
    2350             var i = 0;
    2351             for ( ; i < length; i += 2 ) {
    2352                 matchIndexes.push( i );
    2353             }
    2354             return matchIndexes;
    2355         }),
    2356 
    2357         "odd": createPositionalPseudo(function( matchIndexes, length ) {
    2358             var i = 1;
    2359             for ( ; i < length; i += 2 ) {
    2360                 matchIndexes.push( i );
    2361             }
    2362             return matchIndexes;
    2363         }),
    2364 
    2365         "lt": createPositionalPseudo(function( matchIndexes, length, argument ) {
    2366             var i = argument < 0 ? argument + length : argument;
    2367             for ( ; --i >= 0; ) {
    2368                 matchIndexes.push( i );
    2369             }
    2370             return matchIndexes;
    2371         }),
    2372 
    2373         "gt": createPositionalPseudo(function( matchIndexes, length, argument ) {
    2374             var i = argument < 0 ? argument + length : argument;
    2375             for ( ; ++i < length; ) {
    2376                 matchIndexes.push( i );
    2377             }
    2378             return matchIndexes;
    2379         })
    2380     }
    2381 };
    2382 
    2383 Expr.pseudos["nth"] = Expr.pseudos["eq"];
    2384 
    2385 // Add button/input type pseudos
    2386 for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
    2387     Expr.pseudos[ i ] = createInputPseudo( i );
    2388 }
    2389 for ( i in { submit: true, reset: true } ) {
    2390     Expr.pseudos[ i ] = createButtonPseudo( i );
    2391 }
    2392 
    2393 // Easy API for creating new setFilters
    2394 function setFilters() {}
    2395 setFilters.prototype = Expr.filters = Expr.pseudos;
    2396 Expr.setFilters = new setFilters();
    2397 
    2398 function tokenize( selector, parseOnly ) {
    2399     var matched, match, tokens, type,
    2400         soFar, groups, preFilters,
    2401         cached = tokenCache[ selector + " " ];
    2402 
    2403     if ( cached ) {
    2404         return parseOnly ? 0 : cached.slice( 0 );
    2405     }
    2406 
    2407     soFar = selector;
    2408     groups = [];
    2409     preFilters = Expr.preFilter;
    2410 
    2411     while ( soFar ) {
    2412 
    2413         // Comma and first run
    2414         if ( !matched || (match = rcomma.exec( soFar )) ) {
    2415             if ( match ) {
    2416                 // Don't consume trailing commas as valid
    2417                 soFar = soFar.slice( match[0].length ) || soFar;
    2418             }
    2419             groups.push( tokens = [] );
    2420         }
    2421 
    2422         matched = false;
    2423 
    2424         // Combinators
    2425         if ( (match = rcombinators.exec( soFar )) ) {
    2426             matched = match.shift();
    2427             tokens.push({
    2428                 value: matched,
    2429                 // Cast descendant combinators to space
    2430                 type: match[0].replace( rtrim, " " )
    2431             });
    2432             soFar = soFar.slice( matched.length );
    2433         }
    2434 
    2435         // Filters
    2436         for ( type in Expr.filter ) {
    2437             if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
    2438                 (match = preFilters[ type ]( match ))) ) {
    2439                 matched = match.shift();
    2440                 tokens.push({
    2441                     value: matched,
    2442                     type: type,
    2443                     matches: match
    2444                 });
    2445                 soFar = soFar.slice( matched.length );
    2446             }
    2447         }
    2448 
    2449         if ( !matched ) {
    2450             break;
    2451         }
    2452     }
    2453 
    2454     // Return the length of the invalid excess
    2455     // if we're just parsing
    2456     // Otherwise, throw an error or return tokens
    2457     return parseOnly ?
    2458         soFar.length :
    2459         soFar ?
    2460             Sizzle.error( selector ) :
    2461             // Cache the tokens
    2462             tokenCache( selector, groups ).slice( 0 );
    2463 }
    2464 
    2465 function toSelector( tokens ) {
    2466     var i = 0,
    2467         len = tokens.length,
    2468         selector = "";
    2469     for ( ; i < len; i++ ) {
    2470         selector += tokens[i].value;
    2471     }
    2472     return selector;
    2473 }
    2474 
    2475 function addCombinator( matcher, combinator, base ) {
    2476     var dir = combinator.dir,
    2477         checkNonElements = base && dir === "parentNode",
    2478         doneName = done++;
    2479 
    2480     return combinator.first ?
    2481         // Check against closest ancestor/preceding element
    2482         function( elem, context, xml ) {
    2483             while ( (elem = elem[ dir ]) ) {
    2484                 if ( elem.nodeType === 1 || checkNonElements ) {
    2485                     return matcher( elem, context, xml );
    2486                 }
    2487             }
    2488         } :
    2489 
    2490         // Check against all ancestor/preceding elements
    2491         function( elem, context, xml ) {
    2492             var data, cache, outerCache,
    2493                 dirkey = dirruns + " " + doneName;
    2494 
    2495             // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching
    2496             if ( xml ) {
    2497                 while ( (elem = elem[ dir ]) ) {
    2498                     if ( elem.nodeType === 1 || checkNonElements ) {
    2499                         if ( matcher( elem, context, xml ) ) {
    2500                             return true;
    2501                         }
    2502                     }
    2503                 }
    2504             } else {
    2505                 while ( (elem = elem[ dir ]) ) {
    2506                     if ( elem.nodeType === 1 || checkNonElements ) {
    2507                         outerCache = elem[ expando ] || (elem[ expando ] = {});
    2508                         if ( (cache = outerCache[ dir ]) && cache[0] === dirkey ) {
    2509                             if ( (data = cache[1]) === true || data === cachedruns ) {
    2510                                 return data === true;
    2511                             }
    2512                         } else {
    2513                             cache = outerCache[ dir ] = [ dirkey ];
    2514                             cache[1] = matcher( elem, context, xml ) || cachedruns;
    2515                             if ( cache[1] === true ) {
    2516                                 return true;
    2517                             }
    2518                         }
    2519                     }
    2520                 }
    2521             }
    2522         };
    2523 }
    2524 
    2525 function elementMatcher( matchers ) {
    2526     return matchers.length > 1 ?
    2527         function( elem, context, xml ) {
    2528             var i = matchers.length;
    2529             while ( i-- ) {
    2530                 if ( !matchers[i]( elem, context, xml ) ) {
    2531                     return false;
    2532                 }
    2533             }
    2534             return true;
    2535         } :
    2536         matchers[0];
    2537 }
    2538 
    2539 function condense( unmatched, map, filter, context, xml ) {
    2540     var elem,
    2541         newUnmatched = [],
    2542         i = 0,
    2543         len = unmatched.length,
    2544         mapped = map != null;
    2545 
    2546     for ( ; i < len; i++ ) {
    2547         if ( (elem = unmatched[i]) ) {
    2548             if ( !filter || filter( elem, context, xml ) ) {
    2549                 newUnmatched.push( elem );
    2550                 if ( mapped ) {
    2551                     map.push( i );
    2552                 }
    2553             }
    2554         }
    2555     }
    2556 
    2557     return newUnmatched;
    2558 }
    2559 
    2560 function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
    2561     if ( postFilter && !postFilter[ expando ] ) {
    2562         postFilter = setMatcher( postFilter );
    2563     }
    2564     if ( postFinder && !postFinder[ expando ] ) {
    2565         postFinder = setMatcher( postFinder, postSelector );
    2566     }
    2567     return markFunction(function( seed, results, context, xml ) {
    2568         var temp, i, elem,
    2569             preMap = [],
    2570             postMap = [],
    2571             preexisting = results.length,
    2572 
    2573             // Get initial elements from seed or context
    2574             elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ),
    2575 
    2576             // Prefilter to get matcher input, preserving a map for seed-results synchronization
    2577             matcherIn = preFilter && ( seed || !selector ) ?
    2578                 condense( elems, preMap, preFilter, context, xml ) :
    2579                 elems,
    2580 
    2581             matcherOut = matcher ?
    2582                 // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
    2583                 postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
    2584 
    2585                     // ...intermediate processing is necessary
    2586                     [] :
    2587 
    2588                     // ...otherwise use results directly
    2589                     results :
    2590                 matcherIn;
    2591 
    2592         // Find primary matches
    2593         if ( matcher ) {
    2594             matcher( matcherIn, matcherOut, context, xml );
    2595         }
    2596 
    2597         // Apply postFilter
    2598         if ( postFilter ) {
    2599             temp = condense( matcherOut, postMap );
    2600             postFilter( temp, [], context, xml );
    2601 
    2602             // Un-match failing elements by moving them back to matcherIn
    2603             i = temp.length;
    2604             while ( i-- ) {
    2605                 if ( (elem = temp[i]) ) {
    2606                     matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);
    2607                 }
    2608             }
    2609         }
    2610 
    2611         if ( seed ) {
    2612             if ( postFinder || preFilter ) {
    2613                 if ( postFinder ) {
    2614                     // Get the final matcherOut by condensing this intermediate into postFinder contexts
    2615                     temp = [];
    2616                     i = matcherOut.length;
    2617                     while ( i-- ) {
    2618                         if ( (elem = matcherOut[i]) ) {
    2619                             // Restore matcherIn since elem is not yet a final match
    2620                             temp.push( (matcherIn[i] = elem) );
    2621                         }
    2622                     }
    2623                     postFinder( null, (matcherOut = []), temp, xml );
    2624                 }
    2625 
    2626                 // Move matched elements from seed to results to keep them synchronized
    2627                 i = matcherOut.length;
    2628                 while ( i-- ) {
    2629                     if ( (elem = matcherOut[i]) &&
    2630                         (temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > -1 ) {
    2631 
    2632                         seed[temp] = !(results[temp] = elem);
    2633                     }
    2634                 }
    2635             }
    2636 
    2637         // Add elements to results, through postFinder if defined
    2638         } else {
    2639             matcherOut = condense(
    2640                 matcherOut === results ?
    2641                     matcherOut.splice( preexisting, matcherOut.length ) :
    2642                     matcherOut
    2643             );
    2644             if ( postFinder ) {
    2645                 postFinder( null, results, matcherOut, xml );
    2646             } else {
    2647                 push.apply( results, matcherOut );
    2648             }
    2649         }
    2650     });
    2651 }
    2652 
    2653 function matcherFromTokens( tokens ) {
    2654     var checkContext, matcher, j,
    2655         len = tokens.length,
    2656         leadingRelative = Expr.relative[ tokens[0].type ],
    2657         implicitRelative = leadingRelative || Expr.relative[" "],
    2658         i = leadingRelative ? 1 : 0,
    2659 
    2660         // The foundational matcher ensures that elements are reachable from top-level context(s)
    2661         matchContext = addCombinator( function( elem ) {
    2662             return elem === checkContext;
    2663         }, implicitRelative, true ),
    2664         matchAnyContext = addCombinator( function( elem ) {
    2665             return indexOf.call( checkContext, elem ) > -1;
    2666         }, implicitRelative, true ),
    2667         matchers = [ function( elem, context, xml ) {
    2668             return ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
    2669                 (checkContext = context).nodeType ?
    2670                     matchContext( elem, context, xml ) :
    2671                     matchAnyContext( elem, context, xml ) );
    2672         } ];
    2673 
    2674     for ( ; i < len; i++ ) {
    2675         if ( (matcher = Expr.relative[ tokens[i].type ]) ) {
    2676             matchers = [ addCombinator(elementMatcher( matchers ), matcher) ];
    2677         } else {
    2678             matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );
    2679 
    2680             // Return special upon seeing a positional matcher
    2681             if ( matcher[ expando ] ) {
    2682                 // Find the next relative operator (if any) for proper handling
    2683                 j = ++i;
    2684                 for ( ; j < len; j++ ) {
    2685                     if ( Expr.relative[ tokens[j].type ] ) {
    2686                         break;
    2687                     }
    2688                 }
    2689                 return setMatcher(
    2690                     i > 1 && elementMatcher( matchers ),
    2691                     i > 1 && toSelector(
    2692                         // If the preceding token was a descendant combinator, insert an implicit any-element `*`
    2693                         tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" })
    2694                     ).replace( rtrim, "$1" ),
    2695                     matcher,
    2696                     i < j && matcherFromTokens( tokens.slice( i, j ) ),
    2697                     j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),
    2698                     j < len && toSelector( tokens )
    2699                 );
    2700             }
    2701             matchers.push( matcher );
    2702         }
    2703     }
    2704 
    2705     return elementMatcher( matchers );
    2706 }
    2707 
    2708 function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
    2709     // A counter to specify which element is currently being matched
    2710     var matcherCachedRuns = 0,
    2711         bySet = setMatchers.length > 0,
    2712         byElement = elementMatchers.length > 0,
    2713         superMatcher = function( seed, context, xml, results, expandContext ) {
    2714             var elem, j, matcher,
    2715                 setMatched = [],
    2716                 matchedCount = 0,
    2717                 i = "0",
    2718                 unmatched = seed && [],
    2719                 outermost = expandContext != null,
    2720                 contextBackup = outermostContext,
    2721                 // We must always have either seed elements or context
    2722                 elems = seed || byElement && Expr.find["TAG"]( "*", expandContext && context.parentNode || context ),
    2723                 // Use integer dirruns iff this is the outermost matcher
    2724                 dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1);
    2725 
    2726             if ( outermost ) {
    2727                 outermostContext = context !== document && context;
    2728                 cachedruns = matcherCachedRuns;
    2729             }
    2730 
    2731             // Add elements passing elementMatchers directly to results
    2732             // Keep `i` a string if there are no elements so `matchedCount` will be "00" below
    2733             for ( ; (elem = elems[i]) != null; i++ ) {
    2734                 if ( byElement && elem ) {
    2735                     j = 0;
    2736                     while ( (matcher = elementMatchers[j++]) ) {
    2737                         if ( matcher( elem, context, xml ) ) {
    2738                             results.push( elem );
    2739                             break;
    2740                         }
    2741                     }
    2742                     if ( outermost ) {
    2743                         dirruns = dirrunsUnique;
    2744                         cachedruns = ++matcherCachedRuns;
    2745                     }
    2746                 }
    2747 
    2748                 // Track unmatched elements for set filters
    2749                 if ( bySet ) {
    2750                     // They will have gone through all possible matchers
    2751                     if ( (elem = !matcher && elem) ) {
    2752                         matchedCount--;
    2753                     }
    2754 
    2755                     // Lengthen the array for every element, matched or not
    2756                     if ( seed ) {
    2757                         unmatched.push( elem );
    2758                     }
    2759                 }
    2760             }
    2761 
    2762             // Apply set filters to unmatched elements
    2763             matchedCount += i;
    2764             if ( bySet && i !== matchedCount ) {
    2765                 j = 0;
    2766                 while ( (matcher = setMatchers[j++]) ) {
    2767                     matcher( unmatched, setMatched, context, xml );
    2768                 }
    2769 
    2770                 if ( seed ) {
    2771                     // Reintegrate element matches to eliminate the need for sorting
    2772                     if ( matchedCount > 0 ) {
    2773                         while ( i-- ) {
    2774                             if ( !(unmatched[i] || setMatched[i]) ) {
    2775                                 setMatched[i] = pop.call( results );
    2776                             }
    2777                         }
    2778                     }
    2779 
    2780                     // Discard index placeholder values to get only actual matches
    2781                     setMatched = condense( setMatched );
    2782                 }
    2783 
    2784                 // Add matches to results
    2785                 push.apply( results, setMatched );
    2786 
    2787                 // Seedless set matches succeeding multiple successful matchers stipulate sorting
    2788                 if ( outermost && !seed && setMatched.length > 0 &&
    2789                     ( matchedCount + setMatchers.length ) > 1 ) {
    2790 
    2791                     Sizzle.uniqueSort( results );
    2792                 }
    2793             }
    2794 
    2795             // Override manipulation of globals by nested matchers
    2796             if ( outermost ) {
    2797                 dirruns = dirrunsUnique;
    2798                 outermostContext = contextBackup;
    2799             }
    2800 
    2801             return unmatched;
    2802         };
    2803 
    2804     return bySet ?
    2805         markFunction( superMatcher ) :
    2806         superMatcher;
    2807 }
    2808 
    2809 compile = Sizzle.compile = function( selector, group /* Internal Use Only */ ) {
    2810     var i,
    2811         setMatchers = [],
    2812         elementMatchers = [],
    2813         cached = compilerCache[ selector + " " ];
    2814 
    2815     if ( !cached ) {
    2816         // Generate a function of recursive functions that can be used to check each element
    2817         if ( !group ) {
    2818             group = tokenize( selector );
    2819         }
    2820         i = group.length;
    2821         while ( i-- ) {
    2822             cached = matcherFromTokens( group[i] );
    2823             if ( cached[ expando ] ) {
    2824                 setMatchers.push( cached );
    2825             } else {
    2826                 elementMatchers.push( cached );
    2827             }
    2828         }
    2829 
    2830         // Cache the compiled function
    2831         cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );
    2832     }
    2833     return cached;
    2834 };
    2835 
    2836 function multipleContexts( selector, contexts, results ) {
    2837     var i = 0,
    2838         len = contexts.length;
    2839     for ( ; i < len; i++ ) {
    2840         Sizzle( selector, contexts[i], results );
    2841     }
    2842     return results;
    2843 }
    2844 
    2845 function select( selector, context, results, seed ) {
    2846     var i, tokens, token, type, find,
    2847         match = tokenize( selector );
    2848 
    2849     if ( !seed ) {
    2850         // Try to minimize operations if there is only one group
    2851         if ( match.length === 1 ) {
    2852 
    2853             // Take a shortcut and set the context if the root selector is an ID
    2854             tokens = match[0] = match[0].slice( 0 );
    2855             if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&
    2856                     support.getById && context.nodeType === 9 && documentIsHTML &&
    2857                     Expr.relative[ tokens[1].type ] ) {
    2858 
    2859                 context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];
    2860                 if ( !context ) {
    2861                     return results;
    2862                 }
    2863                 selector = selector.slice( tokens.shift().value.length );
    2864             }
    2865 
    2866             // Fetch a seed set for right-to-left matching
    2867             i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length;
    2868             while ( i-- ) {
    2869                 token = tokens[i];
    2870 
    2871                 // Abort if we hit a combinator
    2872                 if ( Expr.relative[ (type = token.type) ] ) {
    2873                     break;
    2874                 }
    2875                 if ( (find = Expr.find[ type ]) ) {
    2876                     // Search, expanding context for leading sibling combinators
    2877                     if ( (seed = find(
    2878                         token.matches[0].replace( runescape, funescape ),
    2879                         rsibling.test( tokens[0].type ) && context.parentNode || context
    2880                     )) ) {
    2881 
    2882                         // If seed is empty or no tokens remain, we can return early
    2883                         tokens.splice( i, 1 );
    2884                         selector = seed.length && toSelector( tokens );
    2885                         if ( !selector ) {
    2886                             push.apply( results, seed );
    2887                             return results;
    2888                         }
    2889 
    2890                         break;
    2891                     }
    2892                 }
    2893             }
    2894         }
    2895     }
    2896 
    2897     // Compile and execute a filtering function
    2898     // Provide `match` to avoid retokenization if we modified the selector above
    2899     compile( selector, match )(
    2900         seed,
    2901         context,
    2902         !documentIsHTML,
    2903         results,
    2904         rsibling.test( selector )
    2905     );
    2906     return results;
    2907 }
    2908 
    2909 // One-time assignments
    2910 
    2911 // Sort stability
    2912 support.sortStable = expando.split("").sort( sortOrder ).join("") === expando;
    2913 
    2914 // Support: Chrome<14
    2915 // Always assume duplicates if they aren't passed to the comparison function
    2916 support.detectDuplicates = hasDuplicate;
    2917 
    2918 // Initialize against the default document
    2919 setDocument();
    2920 
    2921 // Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)
    2922 // Detached nodes confoundingly follow *each other*
    2923 support.sortDetached = assert(function( div1 ) {
    2924     // Should return 1, but returns 4 (following)
    2925     return div1.compareDocumentPosition( document.createElement("div") ) & 1;
    2926 });
    2927 
    2928 // Support: IE<8
    2929 // Prevent attribute/property "interpolation"
    2930 // http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
    2931 if ( !assert(function( div ) {
    2932     div.innerHTML = "<a href='#'></a>";
    2933     return div.firstChild.getAttribute("href") === "#" ;
    2934 }) ) {
    2935     addHandle( "type|href|height|width", function( elem, name, isXML ) {
    2936         if ( !isXML ) {
    2937             return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 );
    2938         }
    2939     });
    2940 }
    2941 
    2942 // Support: IE<9
    2943 // Use defaultValue in place of getAttribute("value")
    2944 if ( !support.attributes || !assert(function( div ) {
    2945     div.innerHTML = "<input/>";
    2946     div.firstChild.setAttribute( "value", "" );
    2947     return div.firstChild.getAttribute( "value" ) === "";
    2948 }) ) {
    2949     addHandle( "value", function( elem, name, isXML ) {
    2950         if ( !isXML && elem.nodeName.toLowerCase() === "input" ) {
    2951             return elem.defaultValue;
    2952         }
    2953     });
    2954 }
    2955 
    2956 // Support: IE<9
    2957 // Use getAttributeNode to fetch booleans when getAttribute lies
    2958 if ( !assert(function( div ) {
    2959     return div.getAttribute("disabled") == null;
    2960 }) ) {
    2961     addHandle( booleans, function( elem, name, isXML ) {
    2962         var val;
    2963         if ( !isXML ) {
    2964             return (val = elem.getAttributeNode( name )) && val.specified ?
    2965                 val.value :
    2966                 elem[ name ] === true ? name.toLowerCase() : null;
    2967         }
    2968     });
    2969 }
    2970 
    2971 jQuery.find = Sizzle;
    2972 jQuery.expr = Sizzle.selectors;
    2973 jQuery.expr[":"] = jQuery.expr.pseudos;
    2974 jQuery.unique = Sizzle.uniqueSort;
    2975 jQuery.text = Sizzle.getText;
    2976 jQuery.isXMLDoc = Sizzle.isXML;
    2977 jQuery.contains = Sizzle.contains;
    2978 
    2979 
    2980 })( window );
    2981 // String to Object options format cache
    2982 var optionsCache = {};
    2983 
    2984 // Convert String-formatted options into Object-formatted ones and store in cache
    2985 function createOptions( options ) {
    2986     var object = optionsCache[ options ] = {};
    2987     jQuery.each( options.match( core_rnotwhite ) || [], function( _, flag ) {
    2988         object[ flag ] = true;
    2989     });
    2990     return object;
    2991 }
    2992 
    2993 /*
    2994  * Create a callback list using the following parameters:
    2995  *
    2996  *  options: an optional list of space-separated options that will change how
    2997  *          the callback list behaves or a more traditional option object
    2998  *
    2999  * By default a callback list will act like an event callback list and can be
    3000  * "fired" multiple times.
    3001  *
    3002  * Possible options:
    3003  *
    3004  *  once:           will ensure the callback list can only be fired once (like a Deferred)
    3005  *
    3006  *  memory:         will keep track of previous values and will call any callback added
    3007  *                  after the list has been fired right away with the latest "memorized"
    3008  *                  values (like a Deferred)
    3009  *
    3010  *  unique:         will ensure a callback can only be added once (no duplicate in the list)
    3011  *
    3012  *  stopOnFalse:    interrupt callings when a callback returns false
    3013  *
    3014  */
    3015 jQuery.Callbacks = function( options ) {
    3016 
    3017     // Convert options from String-formatted to Object-formatted if needed
    3018     // (we check in cache first)
    3019     options = typeof options === "string" ?
    3020         ( optionsCache[ options ] || createOptions( options ) ) :
    3021         jQuery.extend( {}, options );
    3022 
    3023     var // Flag to know if list is currently firing
    3024         firing,
    3025         // Last fire value (for non-forgettable lists)
    3026         memory,
    3027         // Flag to know if list was already fired
    3028         fired,
    3029         // End of the loop when firing
    3030         firingLength,
    3031         // Index of currently firing callback (modified by remove if needed)
    3032         firingIndex,
    3033         // First callback to fire (used internally by add and fireWith)
    3034         firingStart,
    3035         // Actual callback list
    3036         list = [],
    3037         // Stack of fire calls for repeatable lists
    3038         stack = !options.once && [],
    3039         // Fire callbacks
    3040         fire = function( data ) {
    3041             memory = options.memory && data;
    3042             fired = true;
    3043             firingIndex = firingStart || 0;
    3044             firingStart = 0;
    3045             firingLength = list.length;
    3046             firing = true;
    3047             for ( ; list && firingIndex < firingLength; firingIndex++ ) {
    3048                 if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {
    3049                     memory = false; // To prevent further calls using add
    3050                     break;
    3051                 }
    3052             }
    3053             firing = false;
    3054             if ( list ) {
    3055                 if ( stack ) {
    3056                     if ( stack.length ) {
    3057                         fire( stack.shift() );
    3058                     }
    3059                 } else if ( memory ) {
    3060                     list = [];
    3061                 } else {
    3062                     self.disable();
    3063                 }
    3064             }
    3065         },
    3066         // Actual Callbacks object
    3067         self = {
    3068             // Add a callback or a collection of callbacks to the list
    3069             add: function() {
    3070                 if ( list ) {
    3071                     // First, we save the current length
    3072                     var start = list.length;
    3073                     (function add( args ) {
    3074                         jQuery.each( args, function( _, arg ) {
    3075                             var type = jQuery.type( arg );
    3076                             if ( type === "function" ) {
    3077                                 if ( !options.unique || !self.has( arg ) ) {
    3078                                     list.push( arg );
    3079                                 }
    3080                             } else if ( arg && arg.length && type !== "string" ) {
    3081                                 // Inspect recursively
    3082                                 add( arg );
    3083                             }
    3084                         });
    3085                     })( arguments );
    3086                     // Do we need to add the callbacks to the
    3087                     // current firing batch?
    3088                     if ( firing ) {
    3089                         firingLength = list.length;
    3090                     // With memory, if we're not firing then
    3091                     // we should call right away
    3092                     } else if ( memory ) {
    3093                         firingStart = start;
    3094                         fire( memory );
    3095                     }
    3096                 }
    3097                 return this;
    3098             },
    3099             // Remove a callback from the list
    3100             remove: function() {
    3101                 if ( list ) {
    3102                     jQuery.each( arguments, function( _, arg ) {
    3103                         var index;
    3104                         while( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
    3105                             list.splice( index, 1 );
    3106                             // Handle firing indexes
    3107                             if ( firing ) {
    3108                                 if ( index <= firingLength ) {
    3109                                     firingLength--;
    3110                                 }
    3111                                 if ( index <= firingIndex ) {
    3112                                     firingIndex--;
    3113                                 }
    3114                             }
    3115                         }
    3116                     });
    3117                 }
    3118                 return this;
    3119             },
    3120             // Check if a given callback is in the list.
    3121             // If no argument is given, return whether or not list has callbacks attached.
    3122             has: function( fn ) {
    3123                 return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length );
    3124             },
    3125             // Remove all callbacks from the list
    3126             empty: function() {
    3127                 list = [];
    3128                 firingLength = 0;
    3129                 return this;
    3130             },
    3131             // Have the list do nothing anymore
    3132             disable: function() {
    3133                 list = stack = memory = undefined;
    3134                 return this;
    3135             },
    3136             // Is it disabled?
    3137             disabled: function() {
    3138                 return !list;
    3139             },
    3140             // Lock the list in its current state
    3141             lock: function() {
    3142                 stack = undefined;
    3143                 if ( !memory ) {
    3144                     self.disable();
    3145                 }
    3146                 return this;
    3147             },
    3148             // Is it locked?
    3149             locked: function() {
    3150                 return !stack;
    3151             },
    3152             // Call all callbacks with the given context and arguments
    3153             fireWith: function( context, args ) {
    3154                 if ( list && ( !fired || stack ) ) {
    3155                     args = args || [];
    3156                     args = [ context, args.slice ? args.slice() : args ];
    3157                     if ( firing ) {
    3158                         stack.push( args );
    3159                     } else {
    3160                         fire( args );
    3161                     }
    3162                 }
    3163                 return this;
    3164             },
    3165             // Call all the callbacks with the given arguments
    3166             fire: function() {
    3167                 self.fireWith( this, arguments );
    3168                 return this;
    3169             },
    3170             // To know if the callbacks have already been called at least once
    3171             fired: function() {
    3172                 return !!fired;
    3173             }
    3174         };
    3175 
    3176     return self;
    3177 };
    3178 jQuery.extend({
    3179 
    3180     Deferred: function( func ) {
    3181         var tuples = [
    3182                 // action, add listener, listener list, final state
    3183                 [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ],
    3184                 [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ],
    3185                 [ "notify", "progress", jQuery.Callbacks("memory") ]
    3186             ],
    3187             state = "pending",
    3188             promise = {
    3189                 state: function() {
    3190                     return state;
    3191                 },
    3192                 always: function() {
    3193                     deferred.done( arguments ).fail( arguments );
    3194                     return this;
    3195                 },
    3196                 then: function( /* fnDone, fnFail, fnProgress */ ) {
    3197                     var fns = arguments;
    3198                     return jQuery.Deferred(function( newDefer ) {
    3199                         jQuery.each( tuples, function( i, tuple ) {
    3200                             var action = tuple[ 0 ],
    3201                                 fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];
    3202                             // deferred[ done | fail | progress ] for forwarding actions to newDefer
    3203                             deferred[ tuple[1] ](function() {
    3204                                 var returned = fn && fn.apply( this, arguments );
    3205                                 if ( returned && jQuery.isFunction( returned.promise ) ) {
    3206                                     returned.promise()
    3207                                         .done( newDefer.resolve )
    3208                                         .fail( newDefer.reject )
    3209                                         .progress( newDefer.notify );
    3210                                 } else {
    3211                                     newDefer[ action + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments );
    3212                                 }
    3213                             });
    3214                         });
    3215                         fns = null;
    3216                     }).promise();
    3217                 },
    3218                 // Get a promise for this deferred
    3219                 // If obj is provided, the promise aspect is added to the object
    3220                 promise: function( obj ) {
    3221                     return obj != null ? jQuery.extend( obj, promise ) : promise;
    3222                 }
    3223             },
    3224             deferred = {};
    3225 
    3226         // Keep pipe for back-compat
    3227         promise.pipe = promise.then;
    3228 
    3229         // Add list-specific methods
    3230         jQuery.each( tuples, function( i, tuple ) {
    3231             var list = tuple[ 2 ],
    3232                 stateString = tuple[ 3 ];
    3233 
    3234             // promise[ done | fail | progress ] = list.add
    3235             promise[ tuple[1] ] = list.add;
    3236 
    3237             // Handle state
    3238             if ( stateString ) {
    3239                 list.add(function() {
    3240                     // state = [ resolved | rejected ]
    3241                     state = stateString;
    3242 
    3243                 // [ reject_list | resolve_list ].disable; progress_list.lock
    3244                 }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );
    3245             }
    3246 
    3247             // deferred[ resolve | reject | notify ]
    3248             deferred[ tuple[0] ] = function() {
    3249                 deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments );
    3250                 return this;
    3251             };
    3252             deferred[ tuple[0] + "With" ] = list.fireWith;
    3253         });
    3254 
    3255         // Make the deferred a promise
    3256         promise.promise( deferred );
    3257 
    3258         // Call given func if any
    3259         if ( func ) {
    3260             func.call( deferred, deferred );
    3261         }
    3262 
    3263         // All done!
    3264         return deferred;
    3265     },
    3266 
    3267     // Deferred helper
    3268     when: function( subordinate /* , ..., subordinateN */ ) {
    3269         var i = 0,
    3270             resolveValues = core_slice.call( arguments ),
    3271             length = resolveValues.length,
    3272 
    3273             // the count of uncompleted subordinates
    3274             remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,
    3275 
    3276             // the master Deferred. If resolveValues consist of only a single Deferred, just use that.
    3277             deferred = remaining === 1 ? subordinate : jQuery.Deferred(),
    3278 
    3279             // Update function for both resolve and progress values
    3280             updateFunc = function( i, contexts, values ) {
    3281                 return function( value ) {
    3282                     contexts[ i ] = this;
    3283                     values[ i ] = arguments.length > 1 ? core_slice.call( arguments ) : value;
    3284                     if( values === progressValues ) {
    3285                         deferred.notifyWith( contexts, values );
    3286                     } else if ( !( --remaining ) ) {
    3287                         deferred.resolveWith( contexts, values );
    3288                     }
    3289                 };
    3290             },
    3291 
    3292             progressValues, progressContexts, resolveContexts;
    3293 
    3294         // add listeners to Deferred subordinates; treat others as resolved
    3295         if ( length > 1 ) {
    3296             progressValues = new Array( length );
    3297             progressContexts = new Array( length );
    3298             resolveContexts = new Array( length );
    3299             for ( ; i < length; i++ ) {
    3300                 if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {
    3301                     resolveValues[ i ].promise()
    3302                         .done( updateFunc( i, resolveContexts, resolveValues ) )
    3303                         .fail( deferred.reject )
    3304                         .progress( updateFunc( i, progressContexts, progressValues ) );
    3305                 } else {
    3306                     --remaining;
    3307                 }
    3308             }
    3309         }
    3310 
    3311         // if we're not waiting on anything, resolve the master
    3312         if ( !remaining ) {
    3313             deferred.resolveWith( resolveContexts, resolveValues );
    3314         }
    3315 
    3316         return deferred.promise();
    3317     }
    3318 });
    3319 jQuery.support = (function( support ) {
    3320 
    3321     var all, a, input, select, fragment, opt, eventName, isSupported, i,
    3322         div = document.createElement("div");
    3323 
    3324     // Setup
    3325     div.setAttribute( "className", "t" );
    3326     div.innerHTML = "  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>";
    3327 
    3328     // Finish early in limited (non-browser) environments
    3329     all = div.getElementsByTagName("*") || [];
    3330     a = div.getElementsByTagName("a")[ 0 ];
    3331     if ( !a || !a.style || !all.length ) {
    3332         return support;
    3333     }
    3334 
    3335     // First batch of tests
    3336     select = document.createElement("select");
    3337     opt = select.appendChild( document.createElement("option") );
    3338     input = div.getElementsByTagName("input")[ 0 ];
    3339 
    3340     a.style.cssText = "top:1px;float:left;opacity:.5";
    3341 
    3342     // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)
    3343     support.getSetAttribute = div.className !== "t";
    3344 
    3345     // IE strips leading whitespace when .innerHTML is used
    3346     support.leadingWhitespace = div.firstChild.nodeType === 3;
    3347 
    3348     // Make sure that tbody elements aren't automatically inserted
    3349     // IE will insert them into empty tables
    3350     support.tbody = !div.getElementsByTagName("tbody").length;
    3351 
    3352     // Make sure that link elements get serialized correctly by innerHTML
    3353     // This requires a wrapper element in IE
    3354     support.htmlSerialize = !!div.getElementsByTagName("link").length;
    3355 
    3356     // Get the style information from getAttribute
    3357     // (IE uses .cssText instead)
    3358     support.style = /top/.test( a.getAttribute("style") );
    3359 
    3360     // Make sure that URLs aren't manipulated
    3361     // (IE normalizes it by default)
    3362     support.hrefNormalized = a.getAttribute("href") === "/a";
    3363 
    3364     // Make sure that element opacity exists
    3365     // (IE uses filter instead)
    3366     // Use a regex to work around a WebKit issue. See #5145
    3367     support.opacity = /^0.5/.test( a.style.opacity );
    3368 
    3369     // Verify style float existence
    3370     // (IE uses styleFloat instead of cssFloat)
    3371     support.cssFloat = !!a.style.cssFloat;
    3372 
    3373     // Check the default checkbox/radio value ("" on WebKit; "on" elsewhere)
    3374     support.checkOn = !!input.value;
    3375 
    3376     // Make sure that a selected-by-default option has a working selected property.
    3377     // (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
    3378     support.optSelected = opt.selected;
    3379 
    3380     // Tests for enctype support on a form (#6743)
    3381     support.enctype = !!document.createElement("form").enctype;
    3382 
    3383     // Makes sure cloning an html5 element does not cause problems
    3384     // Where outerHTML is undefined, this still works
    3385     support.html5Clone = document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav></:nav>";
    3386 
    3387     // Will be defined later
    3388     support.inlineBlockNeedsLayout = false;
    3389     support.shrinkWrapBlocks = false;
    3390     support.pixelPosition = false;
    3391     support.deleteExpando = true;
    3392     support.noCloneEvent = true;
    3393     support.reliableMarginRight = true;
    3394     support.boxSizingReliable = true;
    3395 
    3396     // Make sure checked status is properly cloned
    3397     input.checked = true;
    3398     support.noCloneChecked = input.cloneNode( true ).checked;
    3399 
    3400     // Make sure that the options inside disabled selects aren't marked as disabled
    3401     // (WebKit marks them as disabled)
    3402     select.disabled = true;
    3403     support.optDisabled = !opt.disabled;
    3404 
    3405     // Support: IE<9
    3406     try {
    3407         delete div.test;
    3408     } catch( e ) {
    3409         support.deleteExpando = false;
    3410     }
    3411 
    3412     // Check if we can trust getAttribute("value")
    3413     input = document.createElement("input");
    3414     input.setAttribute( "value", "" );
    3415     support.input = input.getAttribute( "value" ) === "";
    3416 
    3417     // Check if an input maintains its value after becoming a radio
    3418     input.value = "t";
    3419     input.setAttribute( "type", "radio" );
    3420     support.radioValue = input.value === "t";
    3421 
    3422     // #11217 - WebKit loses check when the name is after the checked attribute
    3423     input.setAttribute( "checked", "t" );
    3424     input.setAttribute( "name", "t" );
    3425 
    3426     fragment = document.createDocumentFragment();
    3427     fragment.appendChild( input );
    3428 
    3429     // Check if a disconnected checkbox will retain its checked
    3430     // value of true after appended to the DOM (IE6/7)
    3431     support.appendChecked = input.checked;
    3432 
    3433     // WebKit doesn't clone checked state correctly in fragments
    3434     support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;
    3435 
    3436     // Support: IE<9
    3437     // Opera does not clone events (and typeof div.attachEvent === undefined).
    3438     // IE9-10 clones events bound via attachEvent, but they don't trigger with .click()
    3439     if ( div.attachEvent ) {
    3440         div.attachEvent( "onclick", function() {
    3441             support.noCloneEvent = false;
    3442         });
    3443 
    3444         div.cloneNode( true ).click();
    3445     }
    3446 
    3447     // Support: IE<9 (lack submit/change bubble), Firefox 17+ (lack focusin event)
    3448     // Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP)
    3449     for ( i in { submit: true, change: true, focusin: true }) {
    3450         div.setAttribute( eventName = "on" + i, "t" );
    3451 
    3452         support[ i + "Bubbles" ] = eventName in window || div.attributes[ eventName ].expando === false;
    3453     }
    3454 
    3455     div.style.backgroundClip = "content-box";
    3456     div.cloneNode( true ).style.backgroundClip = "";
    3457     support.clearCloneStyle = div.style.backgroundClip === "content-box";
    3458 
    3459     // Support: IE<9
    3460     // Iteration over object's inherited properties before its own.
    3461     for ( i in jQuery( support ) ) {
    3462         break;
    3463     }
    3464     support.ownLast = i !== "0";
    3465 
    3466     // Run tests that need a body at doc ready
    3467     jQuery(function() {
    3468         var container, marginDiv, tds,
    3469             divReset = "padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;",
    3470             body = document.getElementsByTagName("body")[0];
    3471 
    3472         if ( !body ) {
    3473             // Return for frameset docs that don't have a body
    3474             return;
    3475         }
    3476 
    3477         container = document.createElement("div");
    3478         container.style.cssText = "border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px";
    3479 
    3480         body.appendChild( container ).appendChild( div );
    3481 
    3482         // Support: IE8
    3483         // Check if table cells still have offsetWidth/Height when they are set
    3484         // to display:none and there are still other visible table cells in a
    3485         // table row; if so, offsetWidth/Height are not reliable for use when
    3486         // determining if an element has been hidden directly using
    3487         // display:none (it is still safe to use offsets if a parent element is
    3488         // hidden; don safety goggles and see bug #4512 for more information).
    3489         div.innerHTML = "<table><tr><td></td><td>t</td></tr></table>";
    3490         tds = div.getElementsByTagName("td");
    3491         tds[ 0 ].style.cssText = "padding:0;margin:0;border:0;display:none";
    3492         isSupported = ( tds[ 0 ].offsetHeight === 0 );
    3493 
    3494         tds[ 0 ].style.display = "";
    3495         tds[ 1 ].style.display = "none";
    3496 
    3497         // Support: IE8
    3498         // Check if empty table cells still have offsetWidth/Height
    3499         support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );
    3500 
    3501         // Check box-sizing and margin behavior.
    3502         div.innerHTML = "";
    3503         div.style.cssText = "box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;";
    3504 
    3505         // Workaround failing boxSizing test due to offsetWidth returning wrong value
    3506         // with some non-1 values of body zoom, ticket #13543
    3507         jQuery.swap( body, body.style.zoom != null ? { zoom: 1 } : {}, function() {
    3508             support.boxSizing = div.offsetWidth === 4;
    3509         });
    3510 
    3511         // Use window.getComputedStyle because jsdom on node.js will break without it.
    3512         if ( window.getComputedStyle ) {
    3513             support.pixelPosition = ( window.getComputedStyle( div, null ) || {} ).top !== "1%";
    3514             support.boxSizingReliable = ( window.getComputedStyle( div, null ) || { width: "4px" } ).width === "4px";
    3515 
    3516             // Check if div with explicit width and no margin-right incorrectly
    3517             // gets computed margin-right based on width of container. (#3333)
    3518             // Fails in WebKit before Feb 2011 nightlies
    3519             // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
    3520             marginDiv = div.appendChild( document.createElement("div") );
    3521             marginDiv.style.cssText = div.style.cssText = divReset;
    3522             marginDiv.style.marginRight = marginDiv.style.width = "0";
    3523             div.style.width = "1px";
    3524 
    3525             support.reliableMarginRight =
    3526                 !parseFloat( ( window.getComputedStyle( marginDiv, null ) || {} ).marginRight );
    3527         }
    3528 
    3529         if ( typeof div.style.zoom !== core_strundefined ) {
    3530             // Support: IE<8
    3531             // Check if natively block-level elements act like inline-block
    3532             // elements when setting their display to 'inline' and giving
    3533             // them layout
    3534             div.innerHTML = "";
    3535             div.style.cssText = divReset + "width:1px;padding:1px;display:inline;zoom:1";
    3536             support.inlineBlockNeedsLayout = ( div.offsetWidth === 3 );
    3537 
    3538             // Support: IE6
    3539             // Check if elements with layout shrink-wrap their children
    3540             div.style.display = "block";
    3541             div.innerHTML = "<div></div>";
    3542             div.firstChild.style.width = "5px";
    3543             support.shrinkWrapBlocks = ( div.offsetWidth !== 3 );
    3544 
    3545             if ( support.inlineBlockNeedsLayout ) {
    3546                 // Prevent IE 6 from affecting layout for positioned elements #11048
    3547                 // Prevent IE from shrinking the body in IE 7 mode #12869
    3548                 // Support: IE<8
    3549                 body.style.zoom = 1;
    3550             }
    3551         }
    3552 
    3553         body.removeChild( container );
    3554 
    3555         // Null elements to avoid leaks in IE
    3556         container = div = tds = marginDiv = null;
    3557     });
    3558 
    3559     // Null elements to avoid leaks in IE
    3560     all = select = fragment = opt = a = input = null;
    3561 
    3562     return support;
    3563 })({});
    3564 
    3565 var rbrace = /(?:\{[\s\S]*\}|\[[\s\S]*\])$/,
    3566     rmultiDash = /([A-Z])/g;
    3567 
    3568 function internalData( elem, name, data, pvt /* Internal Use Only */ ){
    3569     if ( !jQuery.acceptData( elem ) ) {
    3570         return;
    3571     }
    3572 
    3573     var ret, thisCache,
    3574         internalKey = jQuery.expando,
    3575 
    3576         // We have to handle DOM nodes and JS objects differently because IE6-7
    3577         // can't GC object references properly across the DOM-JS boundary
    3578         isNode = elem.nodeType,
    3579 
    3580         // Only DOM nodes need the global jQuery cache; JS object data is
    3581         // attached directly to the object so GC can occur automatically
    3582         cache = isNode ? jQuery.cache : elem,
    3583 
    3584         // Only defining an ID for JS objects if its cache already exists allows
    3585         // the code to shortcut on the same path as a DOM node with no cache
    3586         id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey;
    3587 
    3588     // Avoid doing any more work than we need to when trying to get data on an
    3589     // object that has no data at all
    3590     if ( (!id || !cache[id] || (!pvt && !cache[id].data)) && data === undefined && typeof name === "string" ) {
    3591         return;
    3592     }
    3593 
    3594     if ( !id ) {
    3595         // Only DOM nodes need a new unique ID for each element since their data
    3596         // ends up in the global cache
    3597         if ( isNode ) {
    3598             id = elem[ internalKey ] = core_deletedIds.pop() || jQuery.guid++;
    3599         } else {
    3600             id = internalKey;
    3601         }
    3602     }
    3603 
    3604     if ( !cache[ id ] ) {
    3605         // Avoid exposing jQuery metadata on plain JS objects when the object
    3606         // is serialized using JSON.stringify
    3607         cache[ id ] = isNode ? {} : { toJSON: jQuery.noop };
    3608     }
    3609 
    3610     // An object can be passed to jQuery.data instead of a key/value pair; this gets
    3611     // shallow copied over onto the existing cache
    3612     if ( typeof name === "object" || typeof name === "function" ) {
    3613         if ( pvt ) {
    3614             cache[ id ] = jQuery.extend( cache[ id ], name );
    3615         } else {
    3616             cache[ id ].data = jQuery.extend( cache[ id ].data, name );
    3617         }
    3618     }
    3619 
    3620     thisCache = cache[ id ];
    3621 
    3622     // jQuery data() is stored in a separate object inside the object's internal data
    3623     // cache in order to avoid key collisions between internal data and user-defined
    3624     // data.
    3625     if ( !pvt ) {
    3626         if ( !thisCache.data ) {
    3627             thisCache.data = {};
    3628         }
    3629 
    3630         thisCache = thisCache.data;
    3631     }
    3632 
    3633     if ( data !== undefined ) {
    3634         thisCache[ jQuery.camelCase( name ) ] = data;
    3635     }
    3636 
    3637     // Check for both converted-to-camel and non-converted data property names
    3638     // If a data property was specified
    3639     if ( typeof name === "string" ) {
    3640 
    3641         // First Try to find as-is property data
    3642         ret = thisCache[ name ];
    3643 
    3644         // Test for null|undefined property data
    3645         if ( ret == null ) {
    3646 
    3647             // Try to find the camelCased property
    3648             ret = thisCache[ jQuery.camelCase( name ) ];
    3649         }
    3650     } else {
    3651         ret = thisCache;
    3652     }
    3653 
    3654     return ret;
    3655 }
    3656 
    3657 function internalRemoveData( elem, name, pvt ) {
    3658     if ( !jQuery.acceptData( elem ) ) {
    3659         return;
    3660     }
    3661 
    3662     var thisCache, i,
    3663         isNode = elem.nodeType,
    3664 
    3665         // See jQuery.data for more information
    3666         cache = isNode ? jQuery.cache : elem,
    3667         id = isNode ? elem[ jQuery.expando ] : jQuery.expando;
    3668 
    3669     // If there is already no cache entry for this object, there is no
    3670     // purpose in continuing
    3671     if ( !cache[ id ] ) {
    3672         return;
    3673     }
    3674 
    3675     if ( name ) {
    3676 
    3677         thisCache = pvt ? cache[ id ] : cache[ id ].data;
    3678 
    3679         if ( thisCache ) {
    3680 
    3681             // Support array or space separated string names for data keys
    3682             if ( !jQuery.isArray( name ) ) {
    3683 
    3684                 // try the string as a key before any manipulation
    3685                 if ( name in thisCache ) {
    3686                     name = [ name ];
    3687                 } else {
    3688 
    3689                     // split the camel cased version by spaces unless a key with the spaces exists
    3690                     name = jQuery.camelCase( name );
    3691                     if ( name in thisCache ) {
    3692                         name = [ name ];
    3693                     } else {
    3694                         name = name.split(" ");
    3695                     }
    3696                 }
    3697             } else {
    3698                 // If "name" is an array of keys...
    3699                 // When data is initially created, via ("key", "val") signature,
    3700                 // keys will be converted to camelCase.
    3701                 // Since there is no way to tell _how_ a key was added, remove
    3702                 // both plain key and camelCase key. #12786
    3703                 // This will only penalize the array argument path.
    3704                 name = name.concat( jQuery.map( name, jQuery.camelCase ) );
    3705             }
    3706 
    3707             i = name.length;
    3708             while ( i-- ) {
    3709                 delete thisCache[ name[i] ];
    3710             }
    3711 
    3712             // If there is no data left in the cache, we want to continue
    3713             // and let the cache object itself get destroyed
    3714             if ( pvt ? !isEmptyDataObject(thisCache) : !jQuery.isEmptyObject(thisCache) ) {
    3715                 return;
    3716             }
    3717         }
    3718     }
    3719 
    3720     // See jQuery.data for more information
    3721     if ( !pvt ) {
    3722         delete cache[ id ].data;
    3723 
    3724         // Don't destroy the parent cache unless the internal data object
    3725         // had been the only thing left in it
    3726         if ( !isEmptyDataObject( cache[ id ] ) ) {
    3727             return;
    3728         }
    3729     }
    3730 
    3731     // Destroy the cache
    3732     if ( isNode ) {
    3733         jQuery.cleanData( [ elem ], true );
    3734 
    3735     // Use delete when supported for expandos or `cache` is not a window per isWindow (#10080)
    3736     /* jshint eqeqeq: false */
    3737     } else if ( jQuery.support.deleteExpando || cache != cache.window ) {
    3738         /* jshint eqeqeq: true */
    3739         delete cache[ id ];
    3740 
    3741     // When all else fails, null
    3742     } else {
    3743         cache[ id ] = null;
    3744     }
    3745 }
    3746 
    3747 jQuery.extend({
    3748     cache: {},
    3749 
    3750     // The following elements throw uncatchable exceptions if you
    3751     // attempt to add expando properties to them.
    3752     noData: {
    3753         "applet": true,
    3754         "embed": true,
    3755         // Ban all objects except for Flash (which handle expandos)
    3756         "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
    3757     },
    3758 
    3759     hasData: function( elem ) {
    3760         elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
    3761         return !!elem && !isEmptyDataObject( elem );
    3762     },
    3763 
    3764     data: function( elem, name, data ) {
    3765         return internalData( elem, name, data );
    3766     },
    3767 
    3768     removeData: function( elem, name ) {
    3769         return internalRemoveData( elem, name );
    3770     },
    3771 
    3772     // For internal use only.
    3773     _data: function( elem, name, data ) {
    3774         return internalData( elem, name, data, true );
    3775     },
    3776 
    3777     _removeData: function( elem, name ) {
    3778         return internalRemoveData( elem, name, true );
    3779     },
    3780 
    3781     // A method for determining if a DOM node can handle the data expando
    3782     acceptData: function( elem ) {
    3783         // Do not set data on non-element because it will not be cleared (#8335).
    3784         if ( elem.nodeType && elem.nodeType !== 1 && elem.nodeType !== 9 ) {
    3785             return false;
    3786         }
    3787 
    3788         var noData = elem.nodeName && jQuery.noData[ elem.nodeName.toLowerCase() ];
    3789 
    3790         // nodes accept data unless otherwise specified; rejection can be conditional
    3791         return !noData || noData !== true && elem.getAttribute("classid") === noData;
    3792     }
    3793 });
    3794 
    3795 jQuery.fn.extend({
    3796     data: function( key, value ) {
    3797         var attrs, name,
    3798             data = null,
    3799             i = 0,
    3800             elem = this[0];
    3801 
    3802         // Special expections of .data basically thwart jQuery.access,
    3803         // so implement the relevant behavior ourselves
    3804 
    3805         // Gets all values
    3806         if ( key === undefined ) {
    3807             if ( this.length ) {
    3808                 data = jQuery.data( elem );
    3809 
    3810                 if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) {
    3811                     attrs = elem.attributes;
    3812                     for ( ; i < attrs.length; i++ ) {
    3813                         name = attrs[i].name;
    3814 
    3815                         if ( name.indexOf("data-") === 0 ) {
    3816                             name = jQuery.camelCase( name.slice(5) );
    3817 
    3818                             dataAttr( elem, name, data[ name ] );
    3819                         }
    3820                     }
    3821                     jQuery._data( elem, "parsedAttrs", true );
    3822                 }
    3823             }
    3824 
    3825             return data;
    3826         }
    3827 
    3828         // Sets multiple values
    3829         if ( typeof key === "object" ) {
    3830             return this.each(function() {
    3831                 jQuery.data( this, key );
    3832             });
    3833         }
    3834 
    3835         return arguments.length > 1 ?
    3836 
    3837             // Sets one value
    3838             this.each(function() {
    3839                 jQuery.data( this, key, value );
    3840             }) :
    3841 
    3842             // Gets one value
    3843             // Try to fetch any internally stored data first
    3844             elem ? dataAttr( elem, key, jQuery.data( elem, key ) ) : null;
    3845     },
    3846 
    3847     removeData: function( key ) {
    3848         return this.each(function() {
    3849             jQuery.removeData( this, key );
    3850         });
    3851     }
    3852 });
    3853 
    3854 function dataAttr( elem, key, data ) {
    3855     // If nothing was found internally, try to fetch any
    3856     // data from the HTML5 data-* attribute
    3857     if ( data === undefined && elem.nodeType === 1 ) {
    3858 
    3859         var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();
    3860 
    3861         data = elem.getAttribute( name );
    3862 
    3863         if ( typeof data === "string" ) {
    3864             try {
    3865                 data = data === "true" ? true :
    3866                     data === "false" ? false :
    3867                     data === "null" ? null :
    3868                     // Only convert to a number if it doesn't change the string
    3869                     +data + "" === data ? +data :
    3870                     rbrace.test( data ) ? jQuery.parseJSON( data ) :
    3871                         data;
    3872             } catch( e ) {}
    3873 
    3874             // Make sure we set the data so it isn't changed later
    3875             jQuery.data( elem, key, data );
    3876 
    3877         } else {
    3878             data = undefined;
    3879         }
    3880     }
    3881 
    3882     return data;
    3883 }
    3884 
    3885 // checks a cache object for emptiness
    3886 function isEmptyDataObject( obj ) {
    3887     var name;
    3888     for ( name in obj ) {
    3889 
    3890         // if the public data object is empty, the private is still empty
    3891         if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) {
    3892             continue;
    3893         }
    3894         if ( name !== "toJSON" ) {
    3895             return false;
    3896         }
    3897     }
    3898 
    3899     return true;
    3900 }
    3901 jQuery.extend({
    3902     queue: function( elem, type, data ) {
    3903         var queue;
    3904 
    3905         if ( elem ) {
    3906             type = ( type || "fx" ) + "queue";
    3907             queue = jQuery._data( elem, type );
    3908 
    3909             // Speed up dequeue by getting out quickly if this is just a lookup
    3910             if ( data ) {
    3911                 if ( !queue || jQuery.isArray(data) ) {
    3912                     queue = jQuery._data( elem, type, jQuery.makeArray(data) );
    3913                 } else {
    3914                     queue.push( data );
    3915                 }
    3916             }
    3917             return queue || [];
    3918         }
    3919     },
    3920 
    3921     dequeue: function( elem, type ) {
    3922         type = type || "fx";
    3923 
    3924         var queue = jQuery.queue( elem, type ),
    3925             startLength = queue.length,
    3926             fn = queue.shift(),
    3927             hooks = jQuery._queueHooks( elem, type ),
    3928             next = function() {
    3929                 jQuery.dequeue( elem, type );
    3930             };
    3931 
    3932         // If the fx queue is dequeued, always remove the progress sentinel
    3933         if ( fn === "inprogress" ) {
    3934             fn = queue.shift();
    3935             startLength--;
    3936         }
    3937 
    3938         if ( fn ) {
    3939 
    3940             // Add a progress sentinel to prevent the fx queue from being
    3941             // automatically dequeued
    3942             if ( type === "fx" ) {
    3943                 queue.unshift( "inprogress" );
    3944             }
    3945 
    3946             // clear up the last queue stop function
    3947             delete hooks.stop;
    3948             fn.call( elem, next, hooks );
    3949         }
    3950 
    3951         if ( !startLength && hooks ) {
    3952             hooks.empty.fire();
    3953         }
    3954     },
    3955 
    3956     // not intended for public consumption - generates a queueHooks object, or returns the current one
    3957     _queueHooks: function( elem, type ) {
    3958         var key = type + "queueHooks";
    3959         return jQuery._data( elem, key ) || jQuery._data( elem, key, {
    3960             empty: jQuery.Callbacks("once memory").add(function() {
    3961                 jQuery._removeData( elem, type + "queue" );
    3962                 jQuery._removeData( elem, key );
    3963             })
    3964         });
    3965     }
    3966 });
    3967 
    3968 jQuery.fn.extend({
    3969     queue: function( type, data ) {
    3970         var setter = 2;
    3971 
    3972         if ( typeof type !== "string" ) {
    3973             data = type;
    3974             type = "fx";
    3975             setter--;
    3976         }
    3977 
    3978         if ( arguments.length < setter ) {
    3979             return jQuery.queue( this[0], type );
    3980         }
    3981 
    3982         return data === undefined ?
    3983             this :
    3984             this.each(function() {
    3985                 var queue = jQuery.queue( this, type, data );
    3986 
    3987                 // ensure a hooks for this queue
    3988                 jQuery._queueHooks( this, type );
    3989 
    3990                 if ( type === "fx" && queue[0] !== "inprogress" ) {
    3991                     jQuery.dequeue( this, type );
    3992                 }
    3993             });
    3994     },
    3995     dequeue: function( type ) {
    3996         return this.each(function() {
    3997             jQuery.dequeue( this, type );
    3998         });
    3999     },
    4000     // Based off of the plugin by Clint Helfers, with permission.
    4001     // http://blindsignals.com/index.php/2009/07/jquery-delay/
    4002     delay: function( time, type ) {
    4003         time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
    4004         type = type || "fx";
    4005 
    4006         return this.queue( type, function( next, hooks ) {
    4007             var timeout = setTimeout( next, time );
    4008             hooks.stop = function() {
    4009                 clearTimeout( timeout );
    4010             };
    4011         });
    4012     },
    4013     clearQueue: function( type ) {
    4014         return this.queue( type || "fx", [] );
    4015     },
    4016     // Get a promise resolved when queues of a certain type
    4017     // are emptied (fx is the type by default)
    4018     promise: function( type, obj ) {
    4019         var tmp,
    4020             count = 1,
    4021             defer = jQuery.Deferred(),
    4022             elements = this,
    4023             i = this.length,
    4024             resolve = function() {
    4025                 if ( !( --count ) ) {
    4026                     defer.resolveWith( elements, [ elements ] );
    4027                 }
    4028             };
    4029 
    4030         if ( typeof type !== "string" ) {
    4031             obj = type;
    4032             type = undefined;
    4033         }
    4034         type = type || "fx";
    4035 
    4036         while( i-- ) {
    4037             tmp = jQuery._data( elements[ i ], type + "queueHooks" );
    4038             if ( tmp && tmp.empty ) {
    4039                 count++;
    4040                 tmp.empty.add( resolve );
    4041             }
    4042         }
    4043         resolve();
    4044         return defer.promise( obj );
    4045     }
    4046 });
    4047 var nodeHook, boolHook,
    4048     rclass = /[\t\r\n\f]/g,
    4049     rreturn = /\r/g,
    4050     rfocusable = /^(?:input|select|textarea|button|object)$/i,
    4051     rclickable = /^(?:a|area)$/i,
    4052     ruseDefault = /^(?:checked|selected)$/i,
    4053     getSetAttribute = jQuery.support.getSetAttribute,
    4054     getSetInput = jQuery.support.input;
    4055 
    4056 jQuery.fn.extend({
    4057     attr: function( name, value ) {
    4058         return jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 );
    4059     },
    4060 
    4061     removeAttr: function( name ) {
    4062         return this.each(function() {
    4063             jQuery.removeAttr( this, name );
    4064         });
    4065     },
    4066 
    4067     prop: function( name, value ) {
    4068         return jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 );
    4069     },
    4070 
    4071     removeProp: function( name ) {
    4072         name = jQuery.propFix[ name ] || name;
    4073         return this.each(function() {
    4074             // try/catch handles cases where IE balks (such as removing a property on window)
    4075             try {
    4076                 this[ name ] = undefined;
    4077                 delete this[ name ];
    4078             } catch( e ) {}
    4079         });
    4080     },
    4081 
    4082     addClass: function( value ) {
    4083         var classes, elem, cur, clazz, j,
    4084             i = 0,
    4085             len = this.length,
    4086             proceed = typeof value === "string" && value;
    4087 
    4088         if ( jQuery.isFunction( value ) ) {
    4089             return this.each(function( j ) {
    4090                 jQuery( this ).addClass( value.call( this, j, this.className ) );
    4091             });
    4092         }
    4093 
    4094         if ( proceed ) {
    4095             // The disjunction here is for better compressibility (see removeClass)
    4096             classes = ( value || "" ).match( core_rnotwhite ) || [];
    4097 
    4098             for ( ; i < len; i++ ) {
    4099                 elem = this[ i ];
    4100                 cur = elem.nodeType === 1 && ( elem.className ?
    4101                     ( " " + elem.className + " " ).replace( rclass, " " ) :
    4102                     " "
    4103                 );
    4104 
    4105                 if ( cur ) {
    4106                     j = 0;
    4107                     while ( (clazz = classes[j++]) ) {
    4108                         if ( cur.indexOf( " " + clazz + " " ) < 0 ) {
    4109                             cur += clazz + " ";
    4110                         }
    4111                     }
    4112                     elem.className = jQuery.trim( cur );
    4113 
    4114                 }
    4115             }
    4116         }
    4117 
    4118         return this;
    4119     },
    4120 
    4121     removeClass: function( value ) {
    4122         var classes, elem, cur, clazz, j,
    4123             i = 0,
    4124             len = this.length,
    4125             proceed = arguments.length === 0 || typeof value === "string" && value;
    4126 
    4127         if ( jQuery.isFunction( value ) ) {
    4128             return this.each(function( j ) {
    4129                 jQuery( this ).removeClass( value.call( this, j, this.className ) );
    4130             });
    4131         }
    4132         if ( proceed ) {
    4133             classes = ( value || "" ).match( core_rnotwhite ) || [];
    4134 
    4135             for ( ; i < len; i++ ) {
    4136                 elem = this[ i ];
    4137                 // This expression is here for better compressibility (see addClass)
    4138                 cur = elem.nodeType === 1 && ( elem.className ?
    4139                     ( " " + elem.className + " " ).replace( rclass, " " ) :
    4140                     ""
    4141                 );
    4142 
    4143                 if ( cur ) {
    4144                     j = 0;
    4145                     while ( (clazz = classes[j++]) ) {
    4146                         // Remove *all* instances
    4147                         while ( cur.indexOf( " " + clazz + " " ) >= 0 ) {
    4148                             cur = cur.replace( " " + clazz + " ", " " );
    4149                         }
    4150                     }
    4151                     elem.className = value ? jQuery.trim( cur ) : "";
    4152                 }
    4153             }
    4154         }
    4155 
    4156         return this;
    4157     },
    4158 
    4159     toggleClass: function( value, stateVal ) {
    4160         var type = typeof value;
    4161 
    4162         if ( typeof stateVal === "boolean" && type === "string" ) {
    4163             return stateVal ? this.addClass( value ) : this.removeClass( value );
    4164         }
    4165 
    4166         if ( jQuery.isFunction( value ) ) {
    4167             return this.each(function( i ) {
    4168                 jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );
    4169             });
    4170         }
    4171 
    4172         return this.each(function() {
    4173             if ( type === "string" ) {
    4174                 // toggle individual class names
    4175                 var className,
    4176                     i = 0,
    4177                     self = jQuery( this ),
    4178                     classNames = value.match( core_rnotwhite ) || [];
    4179 
    4180                 while ( (className = classNames[ i++ ]) ) {
    4181                     // check each className given, space separated list
    4182                     if ( self.hasClass( className ) ) {
    4183                         self.removeClass( className );
    4184                     } else {
    4185                         self.addClass( className );
    4186                     }
    4187                 }
    4188 
    4189             // Toggle whole class name
    4190             } else if ( type === core_strundefined || type === "boolean" ) {
    4191                 if ( this.className ) {
    4192                     // store className if set
    4193                     jQuery._data( this, "__className__", this.className );
    4194                 }
    4195 
    4196                 // If the element has a class name or if we're passed "false",
    4197                 // then remove the whole classname (if there was one, the above saved it).
    4198                 // Otherwise bring back whatever was previously saved (if anything),
    4199                 // falling back to the empty string if nothing was stored.
    4200                 this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || "";
    4201             }
    4202         });
    4203     },
    4204 
    4205     hasClass: function( selector ) {
    4206         var className = " " + selector + " ",
    4207             i = 0,
    4208             l = this.length;
    4209         for ( ; i < l; i++ ) {
    4210             if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) {
    4211                 return true;
    4212             }
    4213         }
    4214 
    4215         return false;
    4216     },
    4217 
    4218     val: function( value ) {
    4219         var ret, hooks, isFunction,
    4220             elem = this[0];
    4221 
    4222         if ( !arguments.length ) {
    4223             if ( elem ) {
    4224                 hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];
    4225 
    4226                 if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
    4227                     return ret;
    4228                 }
    4229 
    4230                 ret = elem.value;
    4231 
    4232                 return typeof ret === "string" ?
    4233                     // handle most common string cases
    4234                     ret.replace(rreturn, "") :
    4235                     // handle cases where value is null/undef or number
    4236                     ret == null ? "" : ret;
    4237             }
    4238 
    4239             return;
    4240         }
    4241 
    4242         isFunction = jQuery.isFunction( value );
    4243 
    4244         return this.each(function( i ) {
    4245             var val;
    4246 
    4247             if ( this.nodeType !== 1 ) {
    4248                 return;
    4249             }
    4250 
    4251             if ( isFunction ) {
    4252                 val = value.call( this, i, jQuery( this ).val() );
    4253             } else {
    4254                 val = value;
    4255             }
    4256 
    4257             // Treat null/undefined as ""; convert numbers to string
    4258             if ( val == null ) {
    4259                 val = "";
    4260             } else if ( typeof val === "number" ) {
    4261                 val += "";
    4262             } else if ( jQuery.isArray( val ) ) {
    4263                 val = jQuery.map(val, function ( value ) {
    4264                     return value == null ? "" : value + "";
    4265                 });
    4266             }
    4267 
    4268             hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
    4269 
    4270             // If set returns undefined, fall back to normal setting
    4271             if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
    4272                 this.value = val;
    4273             }
    4274         });
    4275     }
    4276 });
    4277 
    4278 jQuery.extend({
    4279     valHooks: {
    4280         option: {
    4281             get: function( elem ) {
    4282                 // Use proper attribute retrieval(#6932, #12072)
    4283                 var val = jQuery.find.attr( elem, "value" );
    4284                 return val != null ?
    4285                     val :
    4286                     elem.text;
    4287             }
    4288         },
    4289         select: {
    4290             get: function( elem ) {
    4291                 var value, option,
    4292                     options = elem.options,
    4293                     index = elem.selectedIndex,
    4294                     one = elem.type === "select-one" || index < 0,
    4295                     values = one ? null : [],
    4296                     max = one ? index + 1 : options.length,
    4297                     i = index < 0 ?
    4298                         max :
    4299                         one ? index : 0;
    4300 
    4301                 // Loop through all the selected options
    4302                 for ( ; i < max; i++ ) {
    4303                     option = options[ i ];
    4304 
    4305                     // oldIE doesn't update selected after form reset (#2551)
    4306                     if ( ( option.selected || i === index ) &&
    4307                             // Don't return options that are disabled or in a disabled optgroup
    4308                             ( jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null ) &&
    4309                             ( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) {
    4310 
    4311                         // Get the specific value for the option
    4312                         value = jQuery( option ).val();
    4313 
    4314                         // We don't need an array for one selects
    4315                         if ( one ) {
    4316                             return value;
    4317                         }
    4318 
    4319                         // Multi-Selects return an array
    4320                         values.push( value );
    4321                     }
    4322                 }
    4323 
    4324                 return values;
    4325             },
    4326 
    4327             set: function( elem, value ) {
    4328                 var optionSet, option,
    4329                     options = elem.options,
    4330                     values = jQuery.makeArray( value ),
    4331                     i = options.length;
    4332 
    4333                 while ( i-- ) {
    4334                     option = options[ i ];
    4335                     if ( (option.selected = jQuery.inArray( jQuery(option).val(), values ) >= 0) ) {
    4336                         optionSet = true;
    4337                     }
    4338                 }
    4339 
    4340                 // force browsers to behave consistently when non-matching value is set
    4341                 if ( !optionSet ) {
    4342                     elem.selectedIndex = -1;
    4343                 }
    4344                 return values;
    4345             }
    4346         }
    4347     },
    4348 
    4349     attr: function( elem, name, value ) {
    4350         var hooks, ret,
    4351             nType = elem.nodeType;
    4352 
    4353         // don't get/set attributes on text, comment and attribute nodes
    4354         if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
    4355             return;
    4356         }
    4357 
    4358         // Fallback to prop when attributes are not supported
    4359         if ( typeof elem.getAttribute === core_strundefined ) {
    4360             return jQuery.prop( elem, name, value );
    4361         }
    4362 
    4363         // All attributes are lowercase
    4364         // Grab necessary hook if one is defined
    4365         if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {
    4366             name = name.toLowerCase();
    4367             hooks = jQuery.attrHooks[ name ] ||
    4368                 ( jQuery.expr.match.bool.test( name ) ? boolHook : nodeHook );
    4369         }
    4370 
    4371         if ( value !== undefined ) {
    4372 
    4373             if ( value === null ) {
    4374                 jQuery.removeAttr( elem, name );
    4375 
    4376             } else if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
    4377                 return ret;
    4378 
    4379             } else {
    4380                 elem.setAttribute( name, value + "" );
    4381                 return value;
    4382             }
    4383 
    4384         } else if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
    4385             return ret;
    4386 
    4387         } else {
    4388             ret = jQuery.find.attr( elem, name );
    4389 
    4390             // Non-existent attributes return null, we normalize to undefined
    4391             return ret == null ?
    4392                 undefined :
    4393                 ret;
    4394         }
    4395     },
    4396 
    4397     removeAttr: function( elem, value ) {
    4398         var name, propName,
    4399             i = 0,
    4400             attrNames = value && value.match( core_rnotwhite );
    4401 
    4402         if ( attrNames && elem.nodeType === 1 ) {
    4403             while ( (name = attrNames[i++]) ) {
    4404                 propName = jQuery.propFix[ name ] || name;
    4405 
    4406                 // Boolean attributes get special treatment (#10870)
    4407                 if ( jQuery.expr.match.bool.test( name ) ) {
    4408                     // Set corresponding property to false
    4409                     if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) {
    4410                         elem[ propName ] = false;
    4411                     // Support: IE<9
    4412                     // Also clear defaultChecked/defaultSelected (if appropriate)
    4413                     } else {
    4414                         elem[ jQuery.camelCase( "default-" + name ) ] =
    4415                             elem[ propName ] = false;
    4416                     }
    4417 
    4418                 // See #9699 for explanation of this approach (setting first, then removal)
    4419                 } else {
    4420                     jQuery.attr( elem, name, "" );
    4421                 }
    4422 
    4423                 elem.removeAttribute( getSetAttribute ? name : propName );
    4424             }
    4425         }
    4426     },
    4427 
    4428     attrHooks: {
    4429         type: {
    4430             set: function( elem, value ) {
    4431                 if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) {
    4432                     // Setting the type on a radio button after the value resets the value in IE6-9
    4433                     // Reset value to default in case type is set after value during creation
    4434                     var val = elem.value;
    4435                     elem.setAttribute( "type", value );
    4436                     if ( val ) {
    4437                         elem.value = val;
    4438                     }
    4439                     return value;
    4440                 }
    4441             }
    4442         }
    4443     },
    4444 
    4445     propFix: {
    4446         "for": "htmlFor",
    4447         "class": "className"
    4448     },
    4449 
    4450     prop: function( elem, name, value ) {
    4451         var ret, hooks, notxml,
    4452             nType = elem.nodeType;
    4453 
    4454         // don't get/set properties on text, comment and attribute nodes
    4455         if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
    4456             return;
    4457         }
    4458 
    4459         notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
    4460 
    4461         if ( notxml ) {
    4462             // Fix name and attach hooks
    4463             name = jQuery.propFix[ name ] || name;
    4464             hooks = jQuery.propHooks[ name ];
    4465         }
    4466 
    4467         if ( value !== undefined ) {
    4468             return hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ?
    4469                 ret :
    4470                 ( elem[ name ] = value );
    4471 
    4472         } else {
    4473             return hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ?
    4474                 ret :
    4475                 elem[ name ];
    4476         }
    4477     },
    4478 
    4479     propHooks: {
    4480         tabIndex: {
    4481             get: function( elem ) {
    4482                 // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
    4483                 // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
    4484                 // Use proper attribute retrieval(#12072)
    4485                 var tabindex = jQuery.find.attr( elem, "tabindex" );
    4486 
    4487                 return tabindex ?
    4488                     parseInt( tabindex, 10 ) :
    4489                     rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
    4490                         0 :
    4491                         -1;
    4492             }
    4493         }
    4494     }
    4495 });
    4496 
    4497 // Hooks for boolean attributes
    4498 boolHook = {
    4499     set: function( elem, value, name ) {
    4500         if ( value === false ) {
    4501             // Remove boolean attributes when set to false
    4502             jQuery.removeAttr( elem, name );
    4503         } else if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) {
    4504             // IE<8 needs the *property* name
    4505             elem.setAttribute( !getSetAttribute && jQuery.propFix[ name ] || name, name );
    4506 
    4507         // Use defaultChecked and defaultSelected for oldIE
    4508         } else {
    4509             elem[ jQuery.camelCase( "default-" + name ) ] = elem[ name ] = true;
    4510         }
    4511 
    4512         return name;
    4513     }
    4514 };
    4515 jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) {
    4516     var getter = jQuery.expr.attrHandle[ name ] || jQuery.find.attr;
    4517 
    4518     jQuery.expr.attrHandle[ name ] = getSetInput && getSetAttribute || !ruseDefault.test( name ) ?
    4519         function( elem, name, isXML ) {
    4520             var fn = jQuery.expr.attrHandle[ name ],
    4521                 ret = isXML ?
    4522                     undefined :
    4523                     /* jshint eqeqeq: false */
    4524                     (jQuery.expr.attrHandle[ name ] = undefined) !=
    4525                         getter( elem, name, isXML ) ?
    4526 
    4527                         name.toLowerCase() :
    4528                         null;
    4529             jQuery.expr.attrHandle[ name ] = fn;
    4530             return ret;
    4531         } :
    4532         function( elem, name, isXML ) {
    4533             return isXML ?
    4534                 undefined :
    4535                 elem[ jQuery.camelCase( "default-" + name ) ] ?
    4536                     name.toLowerCase() :
    4537                     null;
    4538         };
    4539 });
    4540 
    4541 // fix oldIE attroperties
    4542 if ( !getSetInput || !getSetAttribute ) {
    4543     jQuery.attrHooks.value = {
    4544         set: function( elem, value, name ) {
    4545             if ( jQuery.nodeName( elem, "input" ) ) {
    4546                 // Does not return so that setAttribute is also used
    4547                 elem.defaultValue = value;
    4548             } else {
    4549                 // Use nodeHook if defined (#1954); otherwise setAttribute is fine
    4550                 return nodeHook && nodeHook.set( elem, value, name );
    4551             }
    4552         }
    4553     };
    4554 }
    4555 
    4556 // IE6/7 do not support getting/setting some attributes with get/setAttribute
    4557 if ( !getSetAttribute ) {
    4558 
    4559     // Use this for any attribute in IE6/7
    4560     // This fixes almost every IE6/7 issue
    4561     nodeHook = {
    4562         set: function( elem, value, name ) {
    4563             // Set the existing or create a new attribute node
    4564             var ret = elem.getAttributeNode( name );
    4565             if ( !ret ) {
    4566                 elem.setAttributeNode(
    4567                     (ret = elem.ownerDocument.createAttribute( name ))
    4568                 );
    4569             }
    4570 
    4571             ret.value = value += "";
    4572 
    4573             // Break association with cloned elements by also using setAttribute (#9646)
    4574             return name === "value" || value === elem.getAttribute( name ) ?
    4575                 value :
    4576                 undefined;
    4577         }
    4578     };
    4579     jQuery.expr.attrHandle.id = jQuery.expr.attrHandle.name = jQuery.expr.attrHandle.coords =
    4580         // Some attributes are constructed with empty-string values when not defined
    4581         function( elem, name, isXML ) {
    4582             var ret;
    4583             return isXML ?
    4584                 undefined :
    4585                 (ret = elem.getAttributeNode( name )) && ret.value !== "" ?
    4586                     ret.value :
    4587                     null;
    4588         };
    4589     jQuery.valHooks.button = {
    4590         get: function( elem, name ) {
    4591             var ret = elem.getAttributeNode( name );
    4592             return ret && ret.specified ?
    4593                 ret.value :
    4594                 undefined;
    4595         },
    4596         set: nodeHook.set
    4597     };
    4598 
    4599     // Set contenteditable to false on removals(#10429)
    4600     // Setting to empty string throws an error as an invalid value
    4601     jQuery.attrHooks.contenteditable = {
    4602         set: function( elem, value, name ) {
    4603             nodeHook.set( elem, value === "" ? false : value, name );
    4604         }
    4605     };
    4606 
    4607     // Set width and height to auto instead of 0 on empty string( Bug #8150 )
    4608     // This is for removals
    4609     jQuery.each([ "width", "height" ], function( i, name ) {
    4610         jQuery.attrHooks[ name ] = {
    4611             set: function( elem, value ) {
    4612                 if ( value === "" ) {
    4613                     elem.setAttribute( name, "auto" );
    4614                     return value;
    4615                 }
    4616             }
    4617         };
    4618     });
    4619 }
    4620 
    4621 
    4622 // Some attributes require a special call on IE
    4623 // http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
    4624 if ( !jQuery.support.hrefNormalized ) {
    4625     // href/src property should get the full normalized URL (#10299/#12915)
    4626     jQuery.each([ "href", "src" ], function( i, name ) {
    4627         jQuery.propHooks[ name ] = {
    4628             get: function( elem ) {
    4629                 return elem.getAttribute( name, 4 );
    4630             }
    4631         };
    4632     });
    4633 }
    4634 
    4635 if ( !jQuery.support.style ) {
    4636     jQuery.attrHooks.style = {
    4637         get: function( elem ) {
    4638             // Return undefined in the case of empty string
    4639             // Note: IE uppercases css property names, but if we were to .toLowerCase()
    4640             // .cssText, that would destroy case senstitivity in URL's, like in "background"
    4641             return elem.style.cssText || undefined;
    4642         },
    4643         set: function( elem, value ) {
    4644             return ( elem.style.cssText = value + "" );
    4645         }
    4646     };
    4647 }
    4648 
    4649 // Safari mis-reports the default selected property of an option
    4650 // Accessing the parent's selectedIndex property fixes it
    4651 if ( !jQuery.support.optSelected ) {
    4652     jQuery.propHooks.selected = {
    4653         get: function( elem ) {
    4654             var parent = elem.parentNode;
    4655 
    4656             if ( parent ) {
    4657                 parent.selectedIndex;
    4658 
    4659                 // Make sure that it also works with optgroups, see #5701
    4660                 if ( parent.parentNode ) {
    4661                     parent.parentNode.selectedIndex;
    4662                 }
    4663             }
    4664             return null;
    4665         }
    4666     };
    4667 }
    4668 
    4669 jQuery.each([
    4670     "tabIndex",
    4671     "readOnly",
    4672     "maxLength",
    4673     "cellSpacing",
    4674     "cellPadding",
    4675     "rowSpan",
    4676     "colSpan",
    4677     "useMap",
    4678     "frameBorder",
    4679     "contentEditable"
    4680 ], function() {
    4681     jQuery.propFix[ this.toLowerCase() ] = this;
    4682 });
    4683 
    4684 // IE6/7 call enctype encoding
    4685 if ( !jQuery.support.enctype ) {
    4686     jQuery.propFix.enctype = "encoding";
    4687 }
    4688 
    4689 // Radios and checkboxes getter/setter
    4690 jQuery.each([ "radio", "checkbox" ], function() {
    4691     jQuery.valHooks[ this ] = {
    4692         set: function( elem, value ) {
    4693             if ( jQuery.isArray( value ) ) {
    4694                 return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );
    4695             }
    4696         }
    4697     };
    4698     if ( !jQuery.support.checkOn ) {
    4699         jQuery.valHooks[ this ].get = function( elem ) {
    4700             // Support: Webkit
    4701             // "" is returned instead of "on" if a value isn't specified
    4702             return elem.getAttribute("value") === null ? "on" : elem.value;
    4703         };
    4704     }
    4705 });
    4706 var rformElems = /^(?:input|select|textarea)$/i,
    4707     rkeyEvent = /^key/,
    4708     rmouseEvent = /^(?:mouse|contextmenu)|click/,
    4709     rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
    4710     rtypenamespace = /^([^.]*)(?:\.(.+)|)$/;
    4711 
    4712 function returnTrue() {
    4713     return true;
    4714 }
    4715 
    4716 function returnFalse() {
    4717     return false;
    4718 }
    4719 
    4720 function safeActiveElement() {
    4721     try {
    4722         return document.activeElement;
    4723     } catch ( err ) { }
    4724 }
    4725 
    4726 /*
    4727  * Helper functions for managing events -- not part of the public interface.
    4728  * Props to Dean Edwards' addEvent library for many of the ideas.
    4729  */
    4730 jQuery.event = {
    4731 
    4732     global: {},
    4733 
    4734     add: function( elem, types, handler, data, selector ) {
    4735         var tmp, events, t, handleObjIn,
    4736             special, eventHandle, handleObj,
    4737             handlers, type, namespaces, origType,
    4738             elemData = jQuery._data( elem );
    4739 
    4740         // Don't attach events to noData or text/comment nodes (but allow plain objects)
    4741         if ( !elemData ) {
    4742             return;
    4743         }
    4744 
    4745         // Caller can pass in an object of custom data in lieu of the handler
    4746         if ( handler.handler ) {
    4747             handleObjIn = handler;
    4748             handler = handleObjIn.handler;
    4749             selector = handleObjIn.selector;
    4750         }
    4751 
    4752         // Make sure that the handler has a unique ID, used to find/remove it later
    4753         if ( !handler.guid ) {
    4754             handler.guid = jQuery.guid++;
    4755         }
    4756 
    4757         // Init the element's event structure and main handler, if this is the first
    4758         if ( !(events = elemData.events) ) {
    4759             events = elemData.events = {};
    4760         }
    4761         if ( !(eventHandle = elemData.handle) ) {
    4762             eventHandle = elemData.handle = function( e ) {
    4763                 // Discard the second event of a jQuery.event.trigger() and
    4764                 // when an event is called after a page has unloaded
    4765                 return typeof jQuery !== core_strundefined && (!e || jQuery.event.triggered !== e.type) ?
    4766                     jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :
    4767                     undefined;
    4768             };
    4769             // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events
    4770             eventHandle.elem = elem;
    4771         }
    4772 
    4773         // Handle multiple events separated by a space
    4774         types = ( types || "" ).match( core_rnotwhite ) || [""];
    4775         t = types.length;
    4776         while ( t-- ) {
    4777             tmp = rtypenamespace.exec( types[t] ) || [];
    4778             type = origType = tmp[1];
    4779             namespaces = ( tmp[2] || "" ).split( "." ).sort();
    4780 
    4781             // There *must* be a type, no attaching namespace-only handlers
    4782             if ( !type ) {
    4783                 continue;
    4784             }
    4785 
    4786             // If event changes its type, use the special event handlers for the changed type
    4787             special = jQuery.event.special[ type ] || {};
    4788 
    4789             // If selector defined, determine special event api type, otherwise given type
    4790             type = ( selector ? special.delegateType : special.bindType ) || type;
    4791 
    4792             // Update special based on newly reset type
    4793             special = jQuery.event.special[ type ] || {};
    4794 
    4795             // handleObj is passed to all event handlers
    4796             handleObj = jQuery.extend({
    4797                 type: type,
    4798                 origType: origType,
    4799                 data: data,
    4800                 handler: handler,
    4801                 guid: handler.guid,
    4802                 selector: selector,
    4803                 needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
    4804                 namespace: namespaces.join(".")
    4805             }, handleObjIn );
    4806 
    4807             // Init the event handler queue if we're the first
    4808             if ( !(handlers = events[ type ]) ) {
    4809                 handlers = events[ type ] = [];
    4810                 handlers.delegateCount = 0;
    4811 
    4812                 // Only use addEventListener/attachEvent if the special events handler returns false
    4813                 if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
    4814                     // Bind the global event handler to the element
    4815                     if ( elem.addEventListener ) {
    4816                         elem.addEventListener( type, eventHandle, false );
    4817 
    4818                     } else if ( elem.attachEvent ) {
    4819                         elem.attachEvent( "on" + type, eventHandle );
    4820                     }
    4821                 }
    4822             }
    4823 
    4824             if ( special.add ) {
    4825                 special.add.call( elem, handleObj );
    4826 
    4827                 if ( !handleObj.handler.guid ) {
    4828                     handleObj.handler.guid = handler.guid;
    4829                 }
    4830             }
    4831 
    4832             // Add to the element's handler list, delegates in front
    4833             if ( selector ) {
    4834                 handlers.splice( handlers.delegateCount++, 0, handleObj );
    4835             } else {
    4836                 handlers.push( handleObj );
    4837             }
    4838 
    4839             // Keep track of which events have ever been used, for event optimization
    4840             jQuery.event.global[ type ] = true;
    4841         }
    4842 
    4843         // Nullify elem to prevent memory leaks in IE
    4844         elem = null;
    4845     },
    4846 
    4847     // Detach an event or set of events from an element
    4848     remove: function( elem, types, handler, selector, mappedTypes ) {
    4849         var j, handleObj, tmp,
    4850             origCount, t, events,
    4851             special, handlers, type,
    4852             namespaces, origType,
    4853             elemData = jQuery.hasData( elem ) && jQuery._data( elem );
    4854 
    4855         if ( !elemData || !(events = elemData.events) ) {
    4856             return;
    4857         }
    4858 
    4859         // Once for each type.namespace in types; type may be omitted
    4860         types = ( types || "" ).match( core_rnotwhite ) || [""];
    4861         t = types.length;
    4862         while ( t-- ) {
    4863             tmp = rtypenamespace.exec( types[t] ) || [];
    4864             type = origType = tmp[1];
    4865             namespaces = ( tmp[2] || "" ).split( "." ).sort();
    4866 
    4867             // Unbind all events (on this namespace, if provided) for the element
    4868             if ( !type ) {
    4869                 for ( type in events ) {
    4870                     jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
    4871                 }
    4872                 continue;
    4873             }
    4874 
    4875             special = jQuery.event.special[ type ] || {};
    4876             type = ( selector ? special.delegateType : special.bindType ) || type;
    4877             handlers = events[ type ] || [];
    4878             tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" );
    4879 
    4880             // Remove matching events
    4881             origCount = j = handlers.length;
    4882             while ( j-- ) {
    4883                 handleObj = handlers[ j ];
    4884 
    4885                 if ( ( mappedTypes || origType === handleObj.origType ) &&
    4886                     ( !handler || handler.guid === handleObj.guid ) &&
    4887                     ( !tmp || tmp.test( handleObj.namespace ) ) &&
    4888                     ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) {
    4889                     handlers.splice( j, 1 );
    4890 
    4891                     if ( handleObj.selector ) {
    4892                         handlers.delegateCount--;
    4893                     }
    4894                     if ( special.remove ) {
    4895                         special.remove.call( elem, handleObj );
    4896                     }
    4897                 }
    4898             }
    4899 
    4900             // Remove generic event handler if we removed something and no more handlers exist
    4901             // (avoids potential for endless recursion during removal of special event handlers)
    4902             if ( origCount && !handlers.length ) {
    4903                 if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
    4904                     jQuery.removeEvent( elem, type, elemData.handle );
    4905                 }
    4906 
    4907                 delete events[ type ];
    4908             }
    4909         }
    4910 
    4911         // Remove the expando if it's no longer used
    4912         if ( jQuery.isEmptyObject( events ) ) {
    4913             delete elemData.handle;
    4914 
    4915             // removeData also checks for emptiness and clears the expando if empty
    4916             // so use it instead of delete
    4917             jQuery._removeData( elem, "events" );
    4918         }
    4919     },
    4920 
    4921     trigger: function( event, data, elem, onlyHandlers ) {
    4922         var handle, ontype, cur,
    4923             bubbleType, special, tmp, i,
    4924             eventPath = [ elem || document ],
    4925             type = core_hasOwn.call( event, "type" ) ? event.type : event,
    4926             namespaces = core_hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : [];
    4927 
    4928         cur = tmp = elem = elem || document;
    4929 
    4930         // Don't do events on text and comment nodes
    4931         if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
    4932             return;
    4933         }
    4934 
    4935         // focus/blur morphs to focusin/out; ensure we're not firing them right now
    4936         if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
    4937             return;
    4938         }
    4939 
    4940         if ( type.indexOf(".") >= 0 ) {
    4941             // Namespaced trigger; create a regexp to match event type in handle()
    4942             namespaces = type.split(".");
    4943             type = namespaces.shift();
    4944             namespaces.sort();
    4945         }
    4946         ontype = type.indexOf(":") < 0 && "on" + type;
    4947 
    4948         // Caller can pass in a jQuery.Event object, Object, or just an event type string
    4949         event = event[ jQuery.expando ] ?
    4950             event :
    4951             new jQuery.Event( type, typeof event === "object" && event );
    4952 
    4953         // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)
    4954         event.isTrigger = onlyHandlers ? 2 : 3;
    4955         event.namespace = namespaces.join(".");
    4956         event.namespace_re = event.namespace ?
    4957             new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) :
    4958             null;
    4959 
    4960         // Clean up the event in case it is being reused
    4961         event.result = undefined;
    4962         if ( !event.target ) {
    4963             event.target = elem;
    4964         }
    4965 
    4966         // Clone any incoming data and prepend the event, creating the handler arg list
    4967         data = data == null ?
    4968             [ event ] :
    4969             jQuery.makeArray( data, [ event ] );
    4970 
    4971         // Allow special events to draw outside the lines
    4972         special = jQuery.event.special[ type ] || {};
    4973         if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {
    4974             return;
    4975         }
    4976 
    4977         // Determine event propagation path in advance, per W3C events spec (#9951)
    4978         // Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
    4979         if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {
    4980 
    4981             bubbleType = special.delegateType || type;
    4982             if ( !rfocusMorph.test( bubbleType + type ) ) {
    4983                 cur = cur.parentNode;
    4984             }
    4985             for ( ; cur; cur = cur.parentNode ) {
    4986                 eventPath.push( cur );
    4987                 tmp = cur;
    4988             }
    4989 
    4990             // Only add window if we got to document (e.g., not plain obj or detached DOM)
    4991             if ( tmp === (elem.ownerDocument || document) ) {
    4992                 eventPath.push( tmp.defaultView || tmp.parentWindow || window );
    4993             }
    4994         }
    4995 
    4996         // Fire handlers on the event path
    4997         i = 0;
    4998         while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) {
    4999 
    5000             event.type = i > 1 ?
    5001                 bubbleType :
    5002                 special.bindType || type;
    5003 
    5004             // jQuery handler
    5005             handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" );
    5006             if ( handle ) {
    5007                 handle.apply( cur, data );
    5008             }
    5009 
    5010             // Native handler
    5011             handle = ontype && cur[ ontype ];
    5012             if ( handle && jQuery.acceptData( cur ) && handle.apply && handle.apply( cur, data ) === false ) {
    5013                 event.preventDefault();
    5014             }
    5015         }
    5016         event.type = type;
    5017 
    5018         // If nobody prevented the default action, do it now
    5019         if ( !onlyHandlers && !event.isDefaultPrevented() ) {
    5020 
    5021             if ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) &&
    5022                 jQuery.acceptData( elem ) ) {
    5023 
    5024                 // Call a native DOM method on the target with the same name name as the event.
    5025                 // Can't use an .isFunction() check here because IE6/7 fails that test.
    5026                 // Don't do default actions on window, that's where global variables be (#6170)
    5027                 if ( ontype && elem[ type ] && !jQuery.isWindow( elem ) ) {
    5028 
    5029                     // Don't re-trigger an onFOO event when we call its FOO() method
    5030                     tmp = elem[ ontype ];
    5031 
    5032                     if ( tmp ) {
    5033                         elem[ ontype ] = null;
    5034                     }
    5035 
    5036                     // Prevent re-triggering of the same event, since we already bubbled it above
    5037                     jQuery.event.triggered = type;
    5038                     try {
    5039                         elem[ type ]();
    5040                     } catch ( e ) {
    5041                         // IE<9 dies on focus/blur to hidden element (#1486,#12518)
    5042                         // only reproducible on winXP IE8 native, not IE9 in IE8 mode
    5043                     }
    5044                     jQuery.event.triggered = undefined;
    5045 
    5046                     if ( tmp ) {
    5047                         elem[ ontype ] = tmp;
    5048                     }
    5049                 }
    5050             }
    5051         }
    5052 
    5053         return event.result;
    5054     },
    5055 
    5056     dispatch: function( event ) {
    5057 
    5058         // Make a writable jQuery.Event from the native event object
    5059         event = jQuery.event.fix( event );
    5060 
    5061         var i, ret, handleObj, matched, j,
    5062             handlerQueue = [],
    5063             args = core_slice.call( arguments ),
    5064             handlers = ( jQuery._data( this, "events" ) || {} )[ event.type ] || [],
    5065             special = jQuery.event.special[ event.type ] || {};
    5066 
    5067         // Use the fix-ed jQuery.Event rather than the (read-only) native event
    5068         args[0] = event;
    5069         event.delegateTarget = this;
    5070 
    5071         // Call the preDispatch hook for the mapped type, and let it bail if desired
    5072         if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
    5073             return;
    5074         }
    5075 
    5076         // Determine handlers
    5077         handlerQueue = jQuery.event.handlers.call( this, event, handlers );
    5078 
    5079         // Run delegates first; they may want to stop propagation beneath us
    5080         i = 0;
    5081         while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) {
    5082             event.currentTarget = matched.elem;
    5083 
    5084             j = 0;
    5085             while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) {
    5086 
    5087                 // Triggered event must either 1) have no namespace, or
    5088                 // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).
    5089                 if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) {
    5090 
    5091                     event.handleObj = handleObj;
    5092                     event.data = handleObj.data;
    5093 
    5094                     ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )
    5095                             .apply( matched.elem, args );
    5096 
    5097                     if ( ret !== undefined ) {
    5098                         if ( (event.result = ret) === false ) {
    5099                             event.preventDefault();
    5100                             event.stopPropagation();
    5101                         }
    5102                     }
    5103                 }
    5104             }
    5105         }
    5106 
    5107         // Call the postDispatch hook for the mapped type
    5108         if ( special.postDispatch ) {
    5109             special.postDispatch.call( this, event );
    5110         }
    5111 
    5112         return event.result;
    5113     },
    5114 
    5115     handlers: function( event, handlers ) {
    5116         var sel, handleObj, matches, i,
    5117             handlerQueue = [],
    5118             delegateCount = handlers.delegateCount,
    5119             cur = event.target;
    5120 
    5121         // Find delegate handlers
    5122         // Black-hole SVG <use> instance trees (#13180)
    5123         // Avoid non-left-click bubbling in Firefox (#3861)
    5124         if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) {
    5125 
    5126             /* jshint eqeqeq: false */
    5127             for ( ; cur != this; cur = cur.parentNode || this ) {
    5128                 /* jshint eqeqeq: true */
    5129 
    5130                 // Don't check non-elements (#13208)
    5131                 // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)
    5132                 if ( cur.nodeType === 1 && (cur.disabled !== true || event.type !== "click") ) {
    5133                     matches = [];
    5134                     for ( i = 0; i < delegateCount; i++ ) {
    5135                         handleObj = handlers[ i ];
    5136 
    5137                         // Don't conflict with Object.prototype properties (#13203)
    5138                         sel = handleObj.selector + " ";
    5139 
    5140                         if ( matches[ sel ] === undefined ) {
    5141                             matches[ sel ] = handleObj.needsContext ?
    5142                                 jQuery( sel, this ).index( cur ) >= 0 :
    5143                                 jQuery.find( sel, this, null, [ cur ] ).length;
    5144                         }
    5145                         if ( matches[ sel ] ) {
    5146                             matches.push( handleObj );
    5147                         }
    5148                     }
    5149                     if ( matches.length ) {
    5150                         handlerQueue.push({ elem: cur, handlers: matches });
    5151                     }
    5152                 }
    5153             }
    5154         }
    5155 
    5156         // Add the remaining (directly-bound) handlers
    5157         if ( delegateCount < handlers.length ) {
    5158             handlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) });
    5159         }
    5160 
    5161         return handlerQueue;
    5162     },
    5163 
    5164     fix: function( event ) {
    5165         if ( event[ jQuery.expando ] ) {
    5166             return event;
    5167         }
    5168 
    5169         // Create a writable copy of the event object and normalize some properties
    5170         var i, prop, copy,
    5171             type = event.type,
    5172             originalEvent = event,
    5173             fixHook = this.fixHooks[ type ];
    5174 
    5175         if ( !fixHook ) {
    5176             this.fixHooks[ type ] = fixHook =
    5177                 rmouseEvent.test( type ) ? this.mouseHooks :
    5178                 rkeyEvent.test( type ) ? this.keyHooks :
    5179                 {};
    5180         }
    5181         copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;
    5182 
    5183         event = new jQuery.Event( originalEvent );
    5184 
    5185         i = copy.length;
    5186         while ( i-- ) {
    5187             prop = copy[ i ];
    5188             event[ prop ] = originalEvent[ prop ];
    5189         }
    5190 
    5191         // Support: IE<9
    5192         // Fix target property (#1925)
    5193         if ( !event.target ) {
    5194             event.target = originalEvent.srcElement || document;
    5195         }
    5196 
    5197         // Support: Chrome 23+, Safari?
    5198         // Target should not be a text node (#504, #13143)
    5199         if ( event.target.nodeType === 3 ) {
    5200             event.target = event.target.parentNode;
    5201         }
    5202 
    5203         // Support: IE<9
    5204         // For mouse/key events, metaKey==false if it's undefined (#3368, #11328)
    5205         event.metaKey = !!event.metaKey;
    5206 
    5207         return fixHook.filter ? fixHook.filter( event, originalEvent ) : event;
    5208     },
    5209 
    5210     // Includes some event props shared by KeyEvent and MouseEvent
    5211     props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),
    5212 
    5213     fixHooks: {},
    5214 
    5215     keyHooks: {
    5216         props: "char charCode key keyCode".split(" "),
    5217         filter: function( event, original ) {
    5218 
    5219             // Add which for key events
    5220             if ( event.which == null ) {
    5221                 event.which = original.charCode != null ? original.charCode : original.keyCode;
    5222             }
    5223 
    5224             return event;
    5225         }
    5226     },
    5227 
    5228     mouseHooks: {
    5229         props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),
    5230         filter: function( event, original ) {
    5231             var body, eventDoc, doc,
    5232                 button = original.button,
    5233                 fromElement = original.fromElement;
    5234 
    5235             // Calculate pageX/Y if missing and clientX/Y available
    5236             if ( event.pageX == null && original.clientX != null ) {
    5237                 eventDoc = event.target.ownerDocument || document;
    5238                 doc = eventDoc.documentElement;
    5239                 body = eventDoc.body;
    5240 
    5241                 event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );
    5242                 event.pageY = original.clientY + ( doc && doc.scrollTop  || body && body.scrollTop  || 0 ) - ( doc && doc.clientTop  || body && body.clientTop  || 0 );
    5243             }
    5244 
    5245             // Add relatedTarget, if necessary
    5246             if ( !event.relatedTarget && fromElement ) {
    5247                 event.relatedTarget = fromElement === event.target ? original.toElement : fromElement;
    5248             }
    5249 
    5250             // Add which for click: 1 === left; 2 === middle; 3 === right
    5251             // Note: button is not normalized, so don't use it
    5252             if ( !event.which && button !== undefined ) {
    5253                 event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
    5254             }
    5255 
    5256             return event;
    5257         }
    5258     },
    5259 
    5260     special: {
    5261         load: {
    5262             // Prevent triggered image.load events from bubbling to window.load
    5263             noBubble: true
    5264         },
    5265         focus: {
    5266             // Fire native event if possible so blur/focus sequence is correct
    5267             trigger: function() {
    5268                 if ( this !== safeActiveElement() && this.focus ) {
    5269                     try {
    5270                         this.focus();
    5271                         return false;
    5272                     } catch ( e ) {
    5273                         // Support: IE<9
    5274                         // If we error on focus to hidden element (#1486, #12518),
    5275                         // let .trigger() run the handlers
    5276                     }
    5277                 }
    5278             },
    5279             delegateType: "focusin"
    5280         },
    5281         blur: {
    5282             trigger: function() {
    5283                 if ( this === safeActiveElement() && this.blur ) {
    5284                     this.blur();
    5285                     return false;
    5286                 }
    5287             },
    5288             delegateType: "focusout"
    5289         },
    5290         click: {
    5291             // For checkbox, fire native event so checked state will be right
    5292             trigger: function() {
    5293                 if ( jQuery.nodeName( this, "input" ) && this.type === "checkbox" && this.click ) {
    5294                     this.click();
    5295                     return false;
    5296                 }
    5297             },
    5298 
    5299             // For cross-browser consistency, don't fire native .click() on links
    5300             _default: function( event ) {
    5301                 return jQuery.nodeName( event.target, "a" );
    5302             }
    5303         },
    5304 
    5305         beforeunload: {
    5306             postDispatch: function( event ) {
    5307 
    5308                 // Even when returnValue equals to undefined Firefox will still show alert
    5309                 if ( event.result !== undefined ) {
    5310                     event.originalEvent.returnValue = event.result;
    5311                 }
    5312             }
    5313         }
    5314     },
    5315 
    5316     simulate: function( type, elem, event, bubble ) {
    5317         // Piggyback on a donor event to simulate a different one.
    5318         // Fake originalEvent to avoid donor's stopPropagation, but if the
    5319         // simulated event prevents default then we do the same on the donor.
    5320         var e = jQuery.extend(
    5321             new jQuery.Event(),
    5322             event,
    5323             {
    5324                 type: type,
    5325                 isSimulated: true,
    5326                 originalEvent: {}
    5327             }
    5328         );
    5329         if ( bubble ) {
    5330             jQuery.event.trigger( e, null, elem );
    5331         } else {
    5332             jQuery.event.dispatch.call( elem, e );
    5333         }
    5334         if ( e.isDefaultPrevented() ) {
    5335             event.preventDefault();
    5336         }
    5337     }
    5338 };
    5339 
    5340 jQuery.removeEvent = document.removeEventListener ?
    5341     function( elem, type, handle ) {
    5342         if ( elem.removeEventListener ) {
    5343             elem.removeEventListener( type, handle, false );
    5344         }
    5345     } :
    5346     function( elem, type, handle ) {
    5347         var name = "on" + type;
    5348 
    5349         if ( elem.detachEvent ) {
    5350 
    5351             // #8545, #7054, preventing memory leaks for custom events in IE6-8
    5352             // detachEvent needed property on element, by name of that event, to properly expose it to GC
    5353             if ( typeof elem[ name ] === core_strundefined ) {
    5354                 elem[ name ] = null;
    5355             }
    5356 
    5357             elem.detachEvent( name, handle );
    5358         }
    5359     };
    5360 
    5361 jQuery.Event = function( src, props ) {
    5362     // Allow instantiation without the 'new' keyword
    5363     if ( !(this instanceof jQuery.Event) ) {
    5364         return new jQuery.Event( src, props );
    5365     }
    5366 
    5367     // Event object
    5368     if ( src && src.type ) {
    5369         this.originalEvent = src;
    5370         this.type = src.type;
    5371 
    5372         // Events bubbling up the document may have been marked as prevented
    5373         // by a handler lower down the tree; reflect the correct value.
    5374         this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false ||
    5375             src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse;
    5376 
    5377     // Event type
    5378     } else {
    5379         this.type = src;
    5380     }
    5381 
    5382     // Put explicitly provided properties onto the event object
    5383     if ( props ) {
    5384         jQuery.extend( this, props );
    5385     }
    5386 
    5387     // Create a timestamp if incoming event doesn't have one
    5388     this.timeStamp = src && src.timeStamp || jQuery.now();
    5389 
    5390     // Mark it as fixed
    5391     this[ jQuery.expando ] = true;
    5392 };
    5393 
    5394 // jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
    5395 // http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
    5396 jQuery.Event.prototype = {
    5397     isDefaultPrevented: returnFalse,
    5398     isPropagationStopped: returnFalse,
    5399     isImmediatePropagationStopped: returnFalse,
    5400 
    5401     preventDefault: function() {
    5402         var e = this.originalEvent;
    5403 
    5404         this.isDefaultPrevented = returnTrue;
    5405         if ( !e ) {
    5406             return;
    5407         }
    5408 
    5409         // If preventDefault exists, run it on the original event
    5410         if ( e.preventDefault ) {
    5411             e.preventDefault();
    5412 
    5413         // Support: IE
    5414         // Otherwise set the returnValue property of the original event to false
    5415         } else {
    5416             e.returnValue = false;
    5417         }
    5418     },
    5419     stopPropagation: function() {
    5420         var e = this.originalEvent;
    5421 
    5422         this.isPropagationStopped = returnTrue;
    5423         if ( !e ) {
    5424             return;
    5425         }
    5426         // If stopPropagation exists, run it on the original event
    5427         if ( e.stopPropagation ) {
    5428             e.stopPropagation();
    5429         }
    5430 
    5431         // Support: IE
    5432         // Set the cancelBubble property of the original event to true
    5433         e.cancelBubble = true;
    5434     },
    5435     stopImmediatePropagation: function() {
    5436         this.isImmediatePropagationStopped = returnTrue;
    5437         this.stopPropagation();
    5438     }
    5439 };
    5440 
    5441 // Create mouseenter/leave events using mouseover/out and event-time checks
    5442 jQuery.each({
    5443     mouseenter: "mouseover",
    5444     mouseleave: "mouseout"
    5445 }, function( orig, fix ) {
    5446     jQuery.event.special[ orig ] = {
    5447         delegateType: fix,
    5448         bindType: fix,
    5449 
    5450         handle: function( event ) {
    5451             var ret,
    5452                 target = this,
    5453                 related = event.relatedTarget,
    5454                 handleObj = event.handleObj;
    5455 
    5456             // For mousenter/leave call the handler if related is outside the target.
    5457             // NB: No relatedTarget if the mouse left/entered the browser window
    5458             if ( !related || (related !== target && !jQuery.contains( target, related )) ) {
    5459                 event.type = handleObj.origType;
    5460                 ret = handleObj.handler.apply( this, arguments );
    5461                 event.type = fix;
    5462             }
    5463             return ret;
    5464         }
    5465     };
    5466 });
    5467 
    5468 // IE submit delegation
    5469 if ( !jQuery.support.submitBubbles ) {
    5470 
    5471     jQuery.event.special.submit = {
    5472         setup: function() {
    5473             // Only need this for delegated form submit events
    5474             if ( jQuery.nodeName( this, "form" ) ) {
    5475                 return false;
    5476             }
    5477 
    5478             // Lazy-add a submit handler when a descendant form may potentially be submitted
    5479             jQuery.event.add( this, "click._submit keypress._submit", function( e ) {
    5480                 // Node name check avoids a VML-related crash in IE (#9807)
    5481                 var elem = e.target,
    5482                     form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined;
    5483                 if ( form && !jQuery._data( form, "submitBubbles" ) ) {
    5484                     jQuery.event.add( form, "submit._submit", function( event ) {
    5485                         event._submit_bubble = true;
    5486                     });
    5487                     jQuery._data( form, "submitBubbles", true );
    5488                 }
    5489             });
    5490             // return undefined since we don't need an event listener
    5491         },
    5492 
    5493         postDispatch: function( event ) {
    5494             // If form was submitted by the user, bubble the event up the tree
    5495             if ( event._submit_bubble ) {
    5496                 delete event._submit_bubble;
    5497                 if ( this.parentNode && !event.isTrigger ) {
    5498                     jQuery.event.simulate( "submit", this.parentNode, event, true );
    5499                 }
    5500             }
    5501         },
    5502 
    5503         teardown: function() {
    5504             // Only need this for delegated form submit events
    5505             if ( jQuery.nodeName( this, "form" ) ) {
    5506                 return false;
    5507             }
    5508 
    5509             // Remove delegated handlers; cleanData eventually reaps submit handlers attached above
    5510             jQuery.event.remove( this, "._submit" );
    5511         }
    5512     };
    5513 }
    5514 
    5515 // IE change delegation and checkbox/radio fix
    5516 if ( !jQuery.support.changeBubbles ) {
    5517 
    5518     jQuery.event.special.change = {
    5519 
    5520         setup: function() {
    5521 
    5522             if ( rformElems.test( this.nodeName ) ) {
    5523                 // IE doesn't fire change on a check/radio until blur; trigger it on click
    5524                 // after a propertychange. Eat the blur-change in special.change.handle.
    5525                 // This still fires onchange a second time for check/radio after blur.
    5526                 if ( this.type === "checkbox" || this.type === "radio" ) {
    5527                     jQuery.event.add( this, "propertychange._change", function( event ) {
    5528                         if ( event.originalEvent.propertyName === "checked" ) {
    5529                             this._just_changed = true;
    5530                         }
    5531                     });
    5532                     jQuery.event.add( this, "click._change", function( event ) {
    5533                         if ( this._just_changed && !event.isTrigger ) {
    5534                             this._just_changed = false;
    5535                         }
    5536                         // Allow triggered, simulated change events (#11500)
    5537                         jQuery.event.simulate( "change", this, event, true );
    5538                     });
    5539                 }
    5540                 return false;
    5541             }
    5542             // Delegated event; lazy-add a change handler on descendant inputs
    5543             jQuery.event.add( this, "beforeactivate._change", function( e ) {
    5544                 var elem = e.target;
    5545 
    5546                 if ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, "changeBubbles" ) ) {
    5547                     jQuery.event.add( elem, "change._change", function( event ) {
    5548                         if ( this.parentNode && !event.isSimulated && !event.isTrigger ) {
    5549                             jQuery.event.simulate( "change", this.parentNode, event, true );
    5550                         }
    5551                     });
    5552                     jQuery._data( elem, "changeBubbles", true );
    5553                 }
    5554             });
    5555         },
    5556 
    5557         handle: function( event ) {
    5558             var elem = event.target;
    5559 
    5560             // Swallow native change events from checkbox/radio, we already triggered them above
    5561             if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) {
    5562                 return event.handleObj.handler.apply( this, arguments );
    5563             }
    5564         },
    5565 
    5566         teardown: function() {
    5567             jQuery.event.remove( this, "._change" );
    5568 
    5569             return !rformElems.test( this.nodeName );
    5570         }
    5571     };
    5572 }
    5573 
    5574 // Create "bubbling" focus and blur events
    5575 if ( !jQuery.support.focusinBubbles ) {
    5576     jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
    5577 
    5578         // Attach a single capturing handler while someone wants focusin/focusout
    5579         var attaches = 0,
    5580             handler = function( event ) {
    5581                 jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );
    5582             };
    5583 
    5584         jQuery.event.special[ fix ] = {
    5585             setup: function() {
    5586                 if ( attaches++ === 0 ) {
    5587                     document.addEventListener( orig, handler, true );
    5588                 }
    5589             },
    5590             teardown: function() {
    5591                 if ( --attaches === 0 ) {
    5592                     document.removeEventListener( orig, handler, true );
    5593                 }
    5594             }
    5595         };
    5596     });
    5597 }
    5598 
    5599 jQuery.fn.extend({
    5600 
    5601     on: function( types, selector, data, fn, /*INTERNAL*/ one ) {
    5602         var type, origFn;
    5603 
    5604         // Types can be a map of types/handlers
    5605         if ( typeof types === "object" ) {
    5606             // ( types-Object, selector, data )
    5607             if ( typeof selector !== "string" ) {
    5608                 // ( types-Object, data )
    5609                 data = data || selector;
    5610                 selector = undefined;
    5611             }
    5612             for ( type in types ) {
    5613                 this.on( type, selector, data, types[ type ], one );
    5614             }
    5615             return this;
    5616         }
    5617 
    5618         if ( data == null && fn == null ) {
    5619             // ( types, fn )
    5620             fn = selector;
    5621             data = selector = undefined;
    5622         } else if ( fn == null ) {
    5623             if ( typeof selector === "string" ) {
    5624                 // ( types, selector, fn )
    5625                 fn = data;
    5626                 data = undefined;
    5627             } else {
    5628                 // ( types, data, fn )
    5629                 fn = data;
    5630                 data = selector;
    5631                 selector = undefined;
    5632             }
    5633         }
    5634         if ( fn === false ) {
    5635             fn = returnFalse;
    5636         } else if ( !fn ) {
    5637             return this;
    5638         }
    5639 
    5640         if ( one === 1 ) {
    5641             origFn = fn;
    5642             fn = function( event ) {
    5643                 // Can use an empty set, since event contains the info
    5644                 jQuery().off( event );
    5645                 return origFn.apply( this, arguments );
    5646             };
    5647             // Use same guid so caller can remove using origFn
    5648             fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
    5649         }
    5650         return this.each( function() {
    5651             jQuery.event.add( this, types, fn, data, selector );
    5652         });
    5653     },
    5654     one: function( types, selector, data, fn ) {
    5655         return this.on( types, selector, data, fn, 1 );
    5656     },
    5657     off: function( types, selector, fn ) {
    5658         var handleObj, type;
    5659         if ( types && types.preventDefault && types.handleObj ) {
    5660             // ( event )  dispatched jQuery.Event
    5661             handleObj = types.handleObj;
    5662             jQuery( types.delegateTarget ).off(
    5663                 handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType,
    5664                 handleObj.selector,
    5665                 handleObj.handler
    5666             );
    5667             return this;
    5668         }
    5669         if ( typeof types === "object" ) {
    5670             // ( types-object [, selector] )
    5671             for ( type in types ) {
    5672                 this.off( type, selector, types[ type ] );
    5673             }
    5674             return this;
    5675         }
    5676         if ( selector === false || typeof selector === "function" ) {
    5677             // ( types [, fn] )
    5678             fn = selector;
    5679             selector = undefined;
    5680         }
    5681         if ( fn === false ) {
    5682             fn = returnFalse;
    5683         }
    5684         return this.each(function() {
    5685             jQuery.event.remove( this, types, fn, selector );
    5686         });
    5687     },
    5688 
    5689     trigger: function( type, data ) {
    5690         return this.each(function() {
    5691             jQuery.event.trigger( type, data, this );
    5692         });
    5693     },
    5694     triggerHandler: function( type, data ) {
    5695         var elem = this[0];
    5696         if ( elem ) {
    5697             return jQuery.event.trigger( type, data, elem, true );
    5698         }
    5699     }
    5700 });
    5701 var isSimple = /^.[^:#\[\.,]*$/,
    5702     rparentsprev = /^(?:parents|prev(?:Until|All))/,
    5703     rneedsContext = jQuery.expr.match.needsContext,
    5704     // methods guaranteed to produce a unique set when starting from a unique set
    5705     guaranteedUnique = {
    5706         children: true,
    5707         contents: true,
    5708         next: true,
    5709         prev: true
    5710     };
    5711 
    5712 jQuery.fn.extend({
    5713     find: function( selector ) {
    5714         var i,
    5715             ret = [],
    5716             self = this,
    5717             len = self.length;
    5718 
    5719         if ( typeof selector !== "string" ) {
    5720             return this.pushStack( jQuery( selector ).filter(function() {
    5721                 for ( i = 0; i < len; i++ ) {
    5722                     if ( jQuery.contains( self[ i ], this ) ) {
    5723                         return true;
    5724                     }
    5725                 }
    5726             }) );
    5727         }
    5728 
    5729         for ( i = 0; i < len; i++ ) {
    5730             jQuery.find( selector, self[ i ], ret );
    5731         }
    5732 
    5733         // Needed because $( selector, context ) becomes $( context ).find( selector )
    5734         ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret );
    5735         ret.selector = this.selector ? this.selector + " " + selector : selector;
    5736         return ret;
    5737     },
    5738 
    5739     has: function( target ) {
    5740         var i,
    5741             targets = jQuery( target, this ),
    5742             len = targets.length;
    5743 
    5744         return this.filter(function() {
    5745             for ( i = 0; i < len; i++ ) {
    5746                 if ( jQuery.contains( this, targets[i] ) ) {
    5747                     return true;
    5748                 }
    5749             }
    5750         });
    5751     },
    5752 
    5753     not: function( selector ) {
    5754         return this.pushStack( winnow(this, selector || [], true) );
    5755     },
    5756 
    5757     filter: function( selector ) {
    5758         return this.pushStack( winnow(this, selector || [], false) );
    5759     },
    5760 
    5761     is: function( selector ) {
    5762         return !!winnow(
    5763             this,
    5764 
    5765             // If this is a positional/relative selector, check membership in the returned set
    5766             // so $("p:first").is("p:last") won't return true for a doc with two "p".
    5767             typeof selector === "string" && rneedsContext.test( selector ) ?
    5768                 jQuery( selector ) :
    5769                 selector || [],
    5770             false
    5771         ).length;
    5772     },
    5773 
    5774     closest: function( selectors, context ) {
    5775         var cur,
    5776             i = 0,
    5777             l = this.length,
    5778             ret = [],
    5779             pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ?
    5780                 jQuery( selectors, context || this.context ) :
    5781                 0;
    5782 
    5783         for ( ; i < l; i++ ) {
    5784             for ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) {
    5785                 // Always skip document fragments
    5786                 if ( cur.nodeType < 11 && (pos ?
    5787                     pos.index(cur) > -1 :
    5788 
    5789                     // Don't pass non-elements to Sizzle
    5790                     cur.nodeType === 1 &&
    5791                         jQuery.find.matchesSelector(cur, selectors)) ) {
    5792 
    5793                     cur = ret.push( cur );
    5794                     break;
    5795                 }
    5796             }
    5797         }
    5798 
    5799         return this.pushStack( ret.length > 1 ? jQuery.unique( ret ) : ret );
    5800     },
    5801 
    5802     // Determine the position of an element within
    5803     // the matched set of elements
    5804     index: function( elem ) {
    5805 
    5806         // No argument, return index in parent
    5807         if ( !elem ) {
    5808             return ( this[0] && this[0].parentNode ) ? this.first().prevAll().length : -1;
    5809         }
    5810 
    5811         // index in selector
    5812         if ( typeof elem === "string" ) {
    5813             return jQuery.inArray( this[0], jQuery( elem ) );
    5814         }
    5815 
    5816         // Locate the position of the desired element
    5817         return jQuery.inArray(
    5818             // If it receives a jQuery object, the first element is used
    5819             elem.jquery ? elem[0] : elem, this );
    5820     },
    5821 
    5822     add: function( selector, context ) {
    5823         var set = typeof selector === "string" ?
    5824                 jQuery( selector, context ) :
    5825                 jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ),
    5826             all = jQuery.merge( this.get(), set );
    5827 
    5828         return this.pushStack( jQuery.unique(all) );
    5829     },
    5830 
    5831     addBack: function( selector ) {
    5832         return this.add( selector == null ?
    5833             this.prevObject : this.prevObject.filter(selector)
    5834         );
    5835     }
    5836 });
    5837 
    5838 function sibling( cur, dir ) {
    5839     do {
    5840         cur = cur[ dir ];
    5841     } while ( cur && cur.nodeType !== 1 );
    5842 
    5843     return cur;
    5844 }
    5845 
    5846 jQuery.each({
    5847     parent: function( elem ) {
    5848         var parent = elem.parentNode;
    5849         return parent && parent.nodeType !== 11 ? parent : null;
    5850     },
    5851     parents: function( elem ) {
    5852         return jQuery.dir( elem, "parentNode" );
    5853     },
    5854     parentsUntil: function( elem, i, until ) {
    5855         return jQuery.dir( elem, "parentNode", until );
    5856     },
    5857     next: function( elem ) {
    5858         return sibling( elem, "nextSibling" );
    5859     },
    5860     prev: function( elem ) {
    5861         return sibling( elem, "previousSibling" );
    5862     },
    5863     nextAll: function( elem ) {
    5864         return jQuery.dir( elem, "nextSibling" );
    5865     },
    5866     prevAll: function( elem ) {
    5867         return jQuery.dir( elem, "previousSibling" );
    5868     },
    5869     nextUntil: function( elem, i, until ) {
    5870         return jQuery.dir( elem, "nextSibling", until );
    5871     },
    5872     prevUntil: function( elem, i, until ) {
    5873         return jQuery.dir( elem, "previousSibling", until );
    5874     },
    5875     siblings: function( elem ) {
    5876         return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );
    5877     },
    5878     children: function( elem ) {
    5879         return jQuery.sibling( elem.firstChild );
    5880     },
    5881     contents: function( elem ) {
    5882         return jQuery.nodeName( elem, "iframe" ) ?
    5883             elem.contentDocument || elem.contentWindow.document :
    5884             jQuery.merge( [], elem.childNodes );
    5885     }
    5886 }, function( name, fn ) {
    5887     jQuery.fn[ name ] = function( until, selector ) {
    5888         var ret = jQuery.map( this, fn, until );
    5889 
    5890         if ( name.slice( -5 ) !== "Until" ) {
    5891             selector = until;
    5892         }
    5893 
    5894         if ( selector && typeof selector === "string" ) {
    5895             ret = jQuery.filter( selector, ret );
    5896         }
    5897 
    5898         if ( this.length > 1 ) {
    5899             // Remove duplicates
    5900             if ( !guaranteedUnique[ name ] ) {
    5901                 ret = jQuery.unique( ret );
    5902             }
    5903 
    5904             // Reverse order for parents* and prev-derivatives
    5905             if ( rparentsprev.test( name ) ) {
    5906                 ret = ret.reverse();
    5907             }
    5908         }
    5909 
    5910         return this.pushStack( ret );
    5911     };
    5912 });
    5913 
    5914 jQuery.extend({
    5915     filter: function( expr, elems, not ) {
    5916         var elem = elems[ 0 ];
    5917 
    5918         if ( not ) {
    5919             expr = ":not(" + expr + ")";
    5920         }
    5921 
    5922         return elems.length === 1 && elem.nodeType === 1 ?
    5923             jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] :
    5924             jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) {
    5925                 return elem.nodeType === 1;
    5926             }));
    5927     },
    5928 
    5929     dir: function( elem, dir, until ) {
    5930         var matched = [],
    5931             cur = elem[ dir ];
    5932 
    5933         while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {
    5934             if ( cur.nodeType === 1 ) {
    5935                 matched.push( cur );
    5936             }
    5937             cur = cur[dir];
    5938         }
    5939         return matched;
    5940     },
    5941 
    5942     sibling: function( n, elem ) {
    5943         var r = [];
    5944 
    5945         for ( ; n; n = n.nextSibling ) {
    5946             if ( n.nodeType === 1 && n !== elem ) {
    5947                 r.push( n );
    5948             }
    5949         }
    5950 
    5951         return r;
    5952     }
    5953 });
    5954 
    5955 // Implement the identical functionality for filter and not
    5956 function winnow( elements, qualifier, not ) {
    5957     if ( jQuery.isFunction( qualifier ) ) {
    5958         return jQuery.grep( elements, function( elem, i ) {
    5959             /* jshint -W018 */
    5960             return !!qualifier.call( elem, i, elem ) !== not;
    5961         });
    5962 
    5963     }
    5964 
    5965     if ( qualifier.nodeType ) {
    5966         return jQuery.grep( elements, function( elem ) {
    5967             return ( elem === qualifier ) !== not;
    5968         });
    5969 
    5970     }
    5971 
    5972     if ( typeof qualifier === "string" ) {
    5973         if ( isSimple.test( qualifier ) ) {
    5974             return jQuery.filter( qualifier, elements, not );
    5975         }
    5976 
    5977         qualifier = jQuery.filter( qualifier, elements );
    5978     }
    5979 
    5980     return jQuery.grep( elements, function( elem ) {
    5981         return ( jQuery.inArray( elem, qualifier ) >= 0 ) !== not;
    5982     });
    5983 }
    5984 function createSafeFragment( document ) {
    5985     var list = nodeNames.split( "|" ),
    5986         safeFrag = document.createDocumentFragment();
    5987 
    5988     if ( safeFrag.createElement ) {
    5989         while ( list.length ) {
    5990             safeFrag.createElement(
    5991                 list.pop()
    5992             );
    5993         }
    5994     }
    5995     return safeFrag;
    5996 }
    5997 
    5998 var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" +
    5999         "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",
    6000     rinlinejQuery = / jQuery\d+="(?:null|\d+)"/g,
    6001     rnoshimcache = new RegExp("<(?:" + nodeNames + ")[\\s/>]", "i"),
    6002     rleadingWhitespace = /^\s+/,
    6003     rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,
    6004     rtagName = /<([\w:]+)/,
    6005     rtbody = /<tbody/i,
    6006     rhtml = /<|&#?\w+;/,
    6007     rnoInnerhtml = /<(?:script|style|link)/i,
    6008     manipulation_rcheckableType = /^(?:checkbox|radio)$/i,
    6009     // checked="checked" or checked
    6010     rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
    6011     rscriptType = /^$|\/(?:java|ecma)script/i,
    6012     rscriptTypeMasked = /^true\/(.*)/,
    6013     rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,
    6014 
    6015     // We have to close these tags to support XHTML (#13200)
    6016     wrapMap = {
    6017         option: [ 1, "<select multiple='multiple'>", "</select>" ],
    6018         legend: [ 1, "<fieldset>", "</fieldset>" ],
    6019         area: [ 1, "<map>", "</map>" ],
    6020         param: [ 1, "<object>", "</object>" ],
    6021         thead: [ 1, "<table>", "</table>" ],
    6022         tr: [ 2, "<table><tbody>", "</tbody></table>" ],
    6023         col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ],
    6024         td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
    6025 
    6026         // IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags,
    6027         // unless wrapped in a div with non-breaking characters in front of it.
    6028         _default: jQuery.support.htmlSerialize ? [ 0, "", "" ] : [ 1, "X<div>", "</div>"  ]
    6029     },
    6030     safeFragment = createSafeFragment( document ),
    6031     fragmentDiv = safeFragment.appendChild( document.createElement("div") );
    6032 
    6033 wrapMap.optgroup = wrapMap.option;
    6034 wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
    6035 wrapMap.th = wrapMap.td;
    6036 
    6037 jQuery.fn.extend({
    6038     text: function( value ) {
    6039         return jQuery.access( this, function( value ) {
    6040             return value === undefined ?
    6041                 jQuery.text( this ) :
    6042                 this.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) );
    6043         }, null, value, arguments.length );
    6044     },
    6045 
    6046     append: function() {
    6047         return this.domManip( arguments, function( elem ) {
    6048             if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
    6049                 var target = manipulationTarget( this, elem );
    6050                 target.appendChild( elem );
    6051             }
    6052         });
    6053     },
    6054 
    6055     prepend: function() {
    6056         return this.domManip( arguments, function( elem ) {
    6057             if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
    6058                 var target = manipulationTarget( this, elem );
    6059                 target.insertBefore( elem, target.firstChild );
    6060             }
    6061         });
    6062     },
    6063 
    6064     before: function() {
    6065         return this.domManip( arguments, function( elem ) {
    6066             if ( this.parentNode ) {
    6067                 this.parentNode.insertBefore( elem, this );
    6068             }
    6069         });
    6070     },
    6071 
    6072     after: function() {
    6073         return this.domManip( arguments, function( elem ) {
    6074             if ( this.parentNode ) {
    6075                 this.parentNode.insertBefore( elem, this.nextSibling );
    6076             }
    6077         });
    6078     },
    6079 
    6080     // keepData is for internal use only--do not document
    6081     remove: function( selector, keepData ) {
    6082         var elem,
    6083             elems = selector ? jQuery.filter( selector, this ) : this,
    6084             i = 0;
    6085