· 9 years ago · Jan 16, 2017, 04:12 PM
1import { Component, ElementRef, NgZone, OnInit, ViewChild, Input, ChangeDetectionStrategy } from "@angular/core";
2import { TextField } from "ui/text-field";
3import { WebView } from "ui/web-view";
4import { View } from "ui/core/view";
5import { Page } from "ui/page";
6import { screen } from "platform";
7import * as fs from "file-system";
8
9import { Todo, TodoStatus, TodoStatusList, Header} from "../../shared/checklist/checklist";
10import { AnswerService } from "../../shared/answers/answer.service";
11import * as SocialShare from "nativescript-social-share";
12import { RouterExtensions } from "nativescript-angular/router";
13import { ActivatedRoute, Params } from "@angular/router";
14import 'rxjs/add/operator/switchMap';
15
16@Component({
17 selector: "answer",
18 templateUrl: "pages/answers/answers.html",
19 styleUrls: ["pages/answers/answers-common.css", "pages/answers/answers.css"],
20 providers: [AnswerService]
21})
22export class AnswerComponent implements OnInit {
23 isLoading = false;
24 listLoaded = false;
25 selectedAnswer: any = {
26 question: {
27 name: ""
28 }
29 };
30 answerId: Number;
31 selectedHeader: any = {};
32 wvWidth: Number;
33 wvHeight: Number;
34 wordCloudHTML: string;
35
36 constructor(
37 private answerService: AnswerService,
38 // private zone: NgZone,
39 private route: ActivatedRoute,
40 private router: RouterExtensions,
41 private page: Page) {
42 this.route.params.subscribe((params: any) => {
43 this.answerId = +params.id
44 this.wvHeight = screen.mainScreen.widthDIPs * 9 / 16;
45 })
46 }
47
48 ngOnInit() {
49 this.isLoading = true;
50 this.answerService.load()
51 .subscribe(answers => {
52 this.selectedAnswer = answers.filter((answer)=>answer.id == this.answerId)[0];
53 this.wordCloudHTML = this.loadWordCloud(this.selectedAnswer.transcript);
54 this.isLoading = false;
55 this.listLoaded = true;
56 //guidelinesWebView.width * 9 / 16
57 console.log(this.wordCloudHTML)
58 });
59
60 }
61
62 getIFrameURL(str) {
63 let firstQuote = str.indexOf('"') + 1;
64 let lastQuote = str.indexOf('"', firstQuote);
65 return str.substring(firstQuote, lastQuote)
66 }
67
68 setHeight() {
69 let guidelinesWebView = <WebView>this.page.getViewById("guidelines");
70 // guidelinesWebView.height = guidelinesWebView.width;
71 let width = guidelinesWebView.getMeasuredWidth();
72 guidelinesWebView.setMeasuredDimension(width, width*9/16);
73 }
74
75 private loadWordCloud(transcript: string) {
76 let wordCount = {};
77 let total = 0;
78 transcript.split(" ").forEach(word => {
79 if (wordCount.hasOwnProperty(word)) {
80 wordCount[word] += 1
81 } else {
82 wordCount[word] = 1
83 }
84 total += 1;
85 });
86 let weights = Object.keys(wordCount).map(key => {
87 return {
88 "text": key,
89 "weight": wordCount[key] / total
90 }
91 });
92
93 let stringWeights = JSON.stringify(weights.map(weight => JSON.stringify(weight)));
94
95 console.log(stringWeights);
96
97 return `<!DOCTYPE html>
98 <html>
99 <head>
100 <title>MyTitle</title>
101 <meta charset="utf-8" />
102 <style>
103 div.jqcloud{overflow:hidden;position:relative}div.jqcloud span{padding:0}div.jqcloud{font-family:Helvetica,Arial,sans-serif;font-size:10px;line-height:normal}div.jqcloud a{font-size:inherit;text-decoration:none}div.jqcloud span.w10{font-size:550%}div.jqcloud span.w9{font-size:500%}div.jqcloud span.w8{font-size:450%}div.jqcloud span.w7{font-size:400%}div.jqcloud span.w6{font-size:350%}div.jqcloud span.w5{font-size:300%}div.jqcloud span.w4{font-size:250%}div.jqcloud span.w3{font-size:200%}div.jqcloud span.w2{font-size:150%}div.jqcloud span.w1{font-size:100%}div.jqcloud{color:#09f}div.jqcloud a{color:inherit}div.jqcloud a:hover,div.jqcloud span.w10,div.jqcloud span.w8,div.jqcloud span.w9{color:#0cf}div.jqcloud span.w7{color:#39d}div.jqcloud span.w6{color:#90c5f0}div.jqcloud span.w5{color:#90a0dd}div.jqcloud span.w4{color:#90c5f0}div.jqcloud span.w3{color:#a0ddff}div.jqcloud span.w2{color:#9ce}div.jqcloud span.w1{color:#aab5f0}
104 </style>
105 </head>
106 <body>
107 <div id="cloud" style="height:300px;"></div>
108 <script>
109(function( global, factory ) {
110
111 if ( typeof module === "object" && typeof module.exports === "object" ) {
112
113 module.exports = global.document ?
114 factory( global, true ) :
115 function( w ) {
116 if ( !w.document ) {
117 throw new Error( "jQuery requires a window with a document" );
118 }
119 return factory( w );
120 };
121 } else {
122 factory( global );
123 }
124
125// Pass this if window is not defined yet
126}(typeof window !== "undefined" ? window : this, function( window, noGlobal ) {
127
128// Support: Firefox 18+
129// Can't be in strict mode, several libs including ASP.NET trace
130// the stack via arguments.caller.callee and Firefox dies if
131// you try to trace through "use strict" call chains. (#13335)
132//"use strict";
133var arr = [];
134
135var document = window.document;
136
137var slice = arr.slice;
138
139var concat = arr.concat;
140
141var push = arr.push;
142
143var indexOf = arr.indexOf;
144
145var class2type = {};
146
147var toString = class2type.toString;
148
149var hasOwn = class2type.hasOwnProperty;
150
151var support = {};
152
153
154
155var
156 version = "2.2.4",
157
158 // Define a local copy of jQuery
159 jQuery = function( selector, context ) {
160
161 // The jQuery object is actually just the init constructor 'enhanced'
162 // Need init if jQuery is called (just allow error to be thrown if not included)
163 return new jQuery.fn.init( selector, context );
164 },
165
166 // Support: Android<4.1
167 // Make sure we trim BOM and NBSP
168 rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,
169
170 // Matches dashed string for camelizing
171 rmsPrefix = /^-ms-/,
172 rdashAlpha = /-([\da-z])/gi,
173
174 // Used by jQuery.camelCase as callback to replace()
175 fcamelCase = function( all, letter ) {
176 return letter.toUpperCase();
177 };
178
179jQuery.fn = jQuery.prototype = {
180
181 // The current version of jQuery being used
182 jquery: version,
183
184 constructor: jQuery,
185
186 // Start with an empty selector
187 selector: "",
188
189 // The default length of a jQuery object is 0
190 length: 0,
191
192 toArray: function() {
193 return slice.call( this );
194 },
195
196 // Get the Nth element in the matched element set OR
197 // Get the whole matched element set as a clean array
198 get: function( num ) {
199 return num != null ?
200
201 // Return just the one element from the set
202 ( num < 0 ? this[ num + this.length ] : this[ num ] ) :
203
204 // Return all the elements in a clean array
205 slice.call( this );
206 },
207
208 // Take an array of elements and push it onto the stack
209 // (returning the new matched element set)
210 pushStack: function( elems ) {
211
212 // Build a new jQuery matched element set
213 var ret = jQuery.merge( this.constructor(), elems );
214
215 // Add the old object onto the stack (as a reference)
216 ret.prevObject = this;
217 ret.context = this.context;
218
219 // Return the newly-formed element set
220 return ret;
221 },
222
223 // Execute a callback for every element in the matched set.
224 each: function( callback ) {
225 return jQuery.each( this, callback );
226 },
227
228 map: function( callback ) {
229 return this.pushStack( jQuery.map( this, function( elem, i ) {
230 return callback.call( elem, i, elem );
231 } ) );
232 },
233
234 slice: function() {
235 return this.pushStack( slice.apply( this, arguments ) );
236 },
237
238 first: function() {
239 return this.eq( 0 );
240 },
241
242 last: function() {
243 return this.eq( -1 );
244 },
245
246 eq: function( i ) {
247 var len = this.length,
248 j = +i + ( i < 0 ? len : 0 );
249 return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] );
250 },
251
252 end: function() {
253 return this.prevObject || this.constructor();
254 },
255
256 // For internal use only.
257 // Behaves like an Array's method, not like a jQuery method.
258 push: push,
259 sort: arr.sort,
260 splice: arr.splice
261};
262
263jQuery.extend = jQuery.fn.extend = function() {
264 var options, name, src, copy, copyIsArray, clone,
265 target = arguments[ 0 ] || {},
266 i = 1,
267 length = arguments.length,
268 deep = false;
269
270 // Handle a deep copy situation
271 if ( typeof target === "boolean" ) {
272 deep = target;
273
274 // Skip the boolean and the target
275 target = arguments[ i ] || {};
276 i++;
277 }
278
279 // Handle case when target is a string or something (possible in deep copy)
280 if ( typeof target !== "object" && !jQuery.isFunction( target ) ) {
281 target = {};
282 }
283
284 // Extend jQuery itself if only one argument is passed
285 if ( i === length ) {
286 target = this;
287 i--;
288 }
289
290 for ( ; i < length; i++ ) {
291
292 // Only deal with non-null/undefined values
293 if ( ( options = arguments[ i ] ) != null ) {
294
295 // Extend the base object
296 for ( name in options ) {
297 src = target[ name ];
298 copy = options[ name ];
299
300 // Prevent never-ending loop
301 if ( target === copy ) {
302 continue;
303 }
304
305 // Recurse if we're merging plain objects or arrays
306 if ( deep && copy && ( jQuery.isPlainObject( copy ) ||
307 ( copyIsArray = jQuery.isArray( copy ) ) ) ) {
308
309 if ( copyIsArray ) {
310 copyIsArray = false;
311 clone = src && jQuery.isArray( src ) ? src : [];
312
313 } else {
314 clone = src && jQuery.isPlainObject( src ) ? src : {};
315 }
316
317 // Never move original objects, clone them
318 target[ name ] = jQuery.extend( deep, clone, copy );
319
320 // Don't bring in undefined values
321 } else if ( copy !== undefined ) {
322 target[ name ] = copy;
323 }
324 }
325 }
326 }
327
328 // Return the modified object
329 return target;
330};
331
332jQuery.extend( {
333
334 // Unique for each copy of jQuery on the page
335 expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ),
336
337 // Assume jQuery is ready without the ready module
338 isReady: true,
339
340 error: function( msg ) {
341 throw new Error( msg );
342 },
343
344 noop: function() {},
345
346 isFunction: function( obj ) {
347 return jQuery.type( obj ) === "function";
348 },
349
350 isArray: Array.isArray,
351
352 isWindow: function( obj ) {
353 return obj != null && obj === obj.window;
354 },
355
356 isNumeric: function( obj ) {
357
358 // parseFloat NaNs numeric-cast false positives (null|true|false|"")
359 // ...but misinterprets leading-number strings, particularly hex literals ("0x...")
360 // subtraction forces infinities to NaN
361 // adding 1 corrects loss of precision from parseFloat (#15100)
362 var realStringObj = obj && obj.toString();
363 return !jQuery.isArray( obj ) && ( realStringObj - parseFloat( realStringObj ) + 1 ) >= 0;
364 },
365
366 isPlainObject: function( obj ) {
367 var key;
368
369 // Not plain objects:
370 // - Any object or value whose internal [[Class]] property is not "[object Object]"
371 // - DOM nodes
372 // - window
373 if ( jQuery.type( obj ) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
374 return false;
375 }
376
377 // Not own constructor property must be Object
378 if ( obj.constructor &&
379 !hasOwn.call( obj, "constructor" ) &&
380 !hasOwn.call( obj.constructor.prototype || {}, "isPrototypeOf" ) ) {
381 return false;
382 }
383
384 // Own properties are enumerated firstly, so to speed up,
385 // if last one is own, then all properties are own
386 for ( key in obj ) {}
387
388 return key === undefined || hasOwn.call( obj, key );
389 },
390
391 isEmptyObject: function( obj ) {
392 var name;
393 for ( name in obj ) {
394 return false;
395 }
396 return true;
397 },
398
399 type: function( obj ) {
400 if ( obj == null ) {
401 return obj + "";
402 }
403
404 // Support: Android<4.0, iOS<6 (functionish RegExp)
405 return typeof obj === "object" || typeof obj === "function" ?
406 class2type[ toString.call( obj ) ] || "object" :
407 typeof obj;
408 },
409
410 // Evaluates a script in a global context
411 globalEval: function( code ) {
412 var script,
413 indirect = eval;
414
415 code = jQuery.trim( code );
416
417 if ( code ) {
418
419 // If the code includes a valid, prologue position
420 // strict mode pragma, execute code by injecting a
421 // script tag into the document.
422 if ( code.indexOf( "use strict" ) === 1 ) {
423 script = document.createElement( "script" );
424 script.text = code;
425 document.head.appendChild( script ).parentNode.removeChild( script );
426 } else {
427
428 // Otherwise, avoid the DOM node creation, insertion
429 // and removal by using an indirect global eval
430
431 indirect( code );
432 }
433 }
434 },
435
436 // Convert dashed to camelCase; used by the css and data modules
437 // Support: IE9-11+
438 // Microsoft forgot to hump their vendor prefix (#9572)
439 camelCase: function( string ) {
440 return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
441 },
442
443 nodeName: function( elem, name ) {
444 return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
445 },
446
447 each: function( obj, callback ) {
448 var length, i = 0;
449
450 if ( isArrayLike( obj ) ) {
451 length = obj.length;
452 for ( ; i < length; i++ ) {
453 if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {
454 break;
455 }
456 }
457 } else {
458 for ( i in obj ) {
459 if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {
460 break;
461 }
462 }
463 }
464
465 return obj;
466 },
467
468 // Support: Android<4.1
469 trim: function( text ) {
470 return text == null ?
471 "" :
472 ( text + "" ).replace( rtrim, "" );
473 },
474
475 // results is for internal usage only
476 makeArray: function( arr, results ) {
477 var ret = results || [];
478
479 if ( arr != null ) {
480 if ( isArrayLike( Object( arr ) ) ) {
481 jQuery.merge( ret,
482 typeof arr === "string" ?
483 [ arr ] : arr
484 );
485 } else {
486 push.call( ret, arr );
487 }
488 }
489
490 return ret;
491 },
492
493 inArray: function( elem, arr, i ) {
494 return arr == null ? -1 : indexOf.call( arr, elem, i );
495 },
496
497 merge: function( first, second ) {
498 var len = +second.length,
499 j = 0,
500 i = first.length;
501
502 for ( ; j < len; j++ ) {
503 first[ i++ ] = second[ j ];
504 }
505
506 first.length = i;
507
508 return first;
509 },
510
511 grep: function( elems, callback, invert ) {
512 var callbackInverse,
513 matches = [],
514 i = 0,
515 length = elems.length,
516 callbackExpect = !invert;
517
518 // Go through the array, only saving the items
519 // that pass the validator function
520 for ( ; i < length; i++ ) {
521 callbackInverse = !callback( elems[ i ], i );
522 if ( callbackInverse !== callbackExpect ) {
523 matches.push( elems[ i ] );
524 }
525 }
526
527 return matches;
528 },
529
530 // arg is for internal usage only
531 map: function( elems, callback, arg ) {
532 var length, value,
533 i = 0,
534 ret = [];
535
536 // Go through the array, translating each of the items to their new values
537 if ( isArrayLike( elems ) ) {
538 length = elems.length;
539 for ( ; i < length; i++ ) {
540 value = callback( elems[ i ], i, arg );
541
542 if ( value != null ) {
543 ret.push( value );
544 }
545 }
546
547 // Go through every key on the object,
548 } else {
549 for ( i in elems ) {
550 value = callback( elems[ i ], i, arg );
551
552 if ( value != null ) {
553 ret.push( value );
554 }
555 }
556 }
557
558 // Flatten any nested arrays
559 return concat.apply( [], ret );
560 },
561
562 // A global GUID counter for objects
563 guid: 1,
564
565 // Bind a function to a context, optionally partially applying any
566 // arguments.
567 proxy: function( fn, context ) {
568 var tmp, args, proxy;
569
570 if ( typeof context === "string" ) {
571 tmp = fn[ context ];
572 context = fn;
573 fn = tmp;
574 }
575
576 // Quick check to determine if target is callable, in the spec
577 // this throws a TypeError, but we will just return undefined.
578 if ( !jQuery.isFunction( fn ) ) {
579 return undefined;
580 }
581
582 // Simulated bind
583 args = slice.call( arguments, 2 );
584 proxy = function() {
585 return fn.apply( context || this, args.concat( slice.call( arguments ) ) );
586 };
587
588 // Set the guid of unique handler to the same of original handler, so it can be removed
589 proxy.guid = fn.guid = fn.guid || jQuery.guid++;
590
591 return proxy;
592 },
593
594 now: Date.now,
595
596 // jQuery.support is not used in Core but other projects attach their
597 // properties to it so it needs to exist.
598 support: support
599} );
600
601// JSHint would error on this code due to the Symbol not being defined in ES5.
602// Defining this global in .jshintrc would create a danger of using the global
603// unguarded in another place, it seems safer to just disable JSHint for these
604// three lines.
605/* jshint ignore: start */
606if ( typeof Symbol === "function" ) {
607 jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ];
608}
609/* jshint ignore: end */
610
611// Populate the class2type map
612jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ),
613function( i, name ) {
614 class2type[ "[object " + name + "]" ] = name.toLowerCase();
615} );
616
617function isArrayLike( obj ) {
618
619 // Support: iOS 8.2 (not reproducible in simulator)
620 // hasOwn isn't used here due to false negatives
621 // regarding Nodelist length in IE
622 var length = !!obj && "length" in obj && obj.length,
623 type = jQuery.type( obj );
624
625 if ( type === "function" || jQuery.isWindow( obj ) ) {
626 return false;
627 }
628
629 return type === "array" || length === 0 ||
630 typeof length === "number" && length > 0 && ( length - 1 ) in obj;
631}
632var Sizzle =
633/*!
634 * Sizzle CSS Selector Engine v2.2.1
635 * http://sizzlejs.com/
636 *
637 * Copyright jQuery Foundation and other contributors
638 * Released under the MIT license
639 * http://jquery.org/license
640 *
641 * Date: 2015-10-17
642 */
643(function( window ) {
644
645var i,
646 support,
647 Expr,
648 getText,
649 isXML,
650 tokenize,
651 compile,
652 select,
653 outermostContext,
654 sortInput,
655 hasDuplicate,
656
657 // Local document vars
658 setDocument,
659 document,
660 docElem,
661 documentIsHTML,
662 rbuggyQSA,
663 rbuggyMatches,
664 matches,
665 contains,
666
667 // Instance-specific data
668 expando = "sizzle" + 1 * new Date(),
669 preferredDoc = window.document,
670 dirruns = 0,
671 done = 0,
672 classCache = createCache(),
673 tokenCache = createCache(),
674 compilerCache = createCache(),
675 sortOrder = function( a, b ) {
676 if ( a === b ) {
677 hasDuplicate = true;
678 }
679 return 0;
680 },
681
682 // General-purpose constants
683 MAX_NEGATIVE = 1 << 31,
684
685 // Instance methods
686 hasOwn = ({}).hasOwnProperty,
687 arr = [],
688 pop = arr.pop,
689 push_native = arr.push,
690 push = arr.push,
691 slice = arr.slice,
692 // Use a stripped-down indexOf as it's faster than native
693 // http://jsperf.com/thor-indexof-vs-for/5
694 indexOf = function( list, elem ) {
695 var i = 0,
696 len = list.length;
697 for ( ; i < len; i++ ) {
698 if ( list[i] === elem ) {
699 return i;
700 }
701 }
702 return -1;
703 },
704
705 booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",
706
707 // Regular expressions
708
709 // http://www.w3.org/TR/css3-selectors/#whitespace
710 whitespace = "[\\x20\\t\\r\\n\\f]",
711
712 // http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
713 identifier = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",
714
715 // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors
716 attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace +
717 // Operator (capture 2)
718 "*([*^$|!~]?=)" + whitespace +
719 // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]"
720 "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace +
721 "*\\]",
722
723 pseudos = ":(" + identifier + ")(?:\\((" +
724 // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:
725 // 1. quoted (capture 3; capture 4 or capture 5)
726 "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" +
727 // 2. simple (capture 6)
728 "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" +
729 // 3. anything else (capture 2)
730 ".*" +
731 ")\\)|)",
732
733 // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
734 rwhitespace = new RegExp( whitespace + "+", "g" ),
735 rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),
736
737 rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
738 rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ),
739
740 rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ),
741
742 rpseudo = new RegExp( pseudos ),
743 ridentifier = new RegExp( "^" + identifier + "$" ),
744
745 matchExpr = {
746 "ID": new RegExp( "^#(" + identifier + ")" ),
747 "CLASS": new RegExp( "^\\.(" + identifier + ")" ),
748 "TAG": new RegExp( "^(" + identifier + "|[*])" ),
749 "ATTR": new RegExp( "^" + attributes ),
750 "PSEUDO": new RegExp( "^" + pseudos ),
751 "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
752 "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
753 "*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
754 "bool": new RegExp( "^(?:" + booleans + ")$", "i" ),
755 // For use in libraries implementing .is()
756 "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
757 whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
758 },
759
760 rinputs = /^(?:input|select|textarea|button)$/i,
761 rheader = /^h\d$/i,
762
763 rnative = /^[^{]+\{\s*\[native \w/,
764
765 // Easily-parseable/retrievable ID or TAG or CLASS selectors
766 rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
767
768 rsibling = /[+~]/,
769 rescape = /'|\\/g,
770
771 // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
772 runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ),
773 funescape = function( _, escaped, escapedWhitespace ) {
774 var high = "0x" + escaped - 0x10000;
775 // NaN means non-codepoint
776 // Support: Firefox<24
777 // Workaround erroneous numeric interpretation of +"0x"
778 return high !== high || escapedWhitespace ?
779 escaped :
780 high < 0 ?
781 // BMP codepoint
782 String.fromCharCode( high + 0x10000 ) :
783 // Supplemental Plane codepoint (surrogate pair)
784 String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
785 },
786
787 // Used for iframes
788 // See setDocument()
789 // Removing the function wrapper causes a "Permission Denied"
790 // error in IE
791 unloadHandler = function() {
792 setDocument();
793 };
794
795// Optimize for push.apply( _, NodeList )
796try {
797 push.apply(
798 (arr = slice.call( preferredDoc.childNodes )),
799 preferredDoc.childNodes
800 );
801 // Support: Android<4.0
802 // Detect silently failing push.apply
803 arr[ preferredDoc.childNodes.length ].nodeType;
804} catch ( e ) {
805 push = { apply: arr.length ?
806
807 // Leverage slice if possible
808 function( target, els ) {
809 push_native.apply( target, slice.call(els) );
810 } :
811
812 // Support: IE<9
813 // Otherwise append directly
814 function( target, els ) {
815 var j = target.length,
816 i = 0;
817 // Can't trust NodeList.length
818 while ( (target[j++] = els[i++]) ) {}
819 target.length = j - 1;
820 }
821 };
822}
823
824function Sizzle( selector, context, results, seed ) {
825 var m, i, elem, nid, nidselect, match, groups, newSelector,
826 newContext = context && context.ownerDocument,
827
828 // nodeType defaults to 9, since context defaults to document
829 nodeType = context ? context.nodeType : 9;
830
831 results = results || [];
832
833 // Return early from calls with invalid selector or context
834 if ( typeof selector !== "string" || !selector ||
835 nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {
836
837 return results;
838 }
839
840 // Try to shortcut find operations (as opposed to filters) in HTML documents
841 if ( !seed ) {
842
843 if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
844 setDocument( context );
845 }
846 context = context || document;
847
848 if ( documentIsHTML ) {
849
850 // If the selector is sufficiently simple, try using a "get*By*" DOM method
851 // (excepting DocumentFragment context, where the methods don't exist)
852 if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) {
853
854 // ID selector
855 if ( (m = match[1]) ) {
856
857 // Document context
858 if ( nodeType === 9 ) {
859 if ( (elem = context.getElementById( m )) ) {
860
861 // Support: IE, Opera, Webkit
862 // TODO: identify versions
863 // getElementById can match elements by name instead of ID
864 if ( elem.id === m ) {
865 results.push( elem );
866 return results;
867 }
868 } else {
869 return results;
870 }
871
872 // Element context
873 } else {
874
875 // Support: IE, Opera, Webkit
876 // TODO: identify versions
877 // getElementById can match elements by name instead of ID
878 if ( newContext && (elem = newContext.getElementById( m )) &&
879 contains( context, elem ) &&
880 elem.id === m ) {
881
882 results.push( elem );
883 return results;
884 }
885 }
886
887 // Type selector
888 } else if ( match[2] ) {
889 push.apply( results, context.getElementsByTagName( selector ) );
890 return results;
891
892 // Class selector
893 } else if ( (m = match[3]) && support.getElementsByClassName &&
894 context.getElementsByClassName ) {
895
896 push.apply( results, context.getElementsByClassName( m ) );
897 return results;
898 }
899 }
900
901 // Take advantage of querySelectorAll
902 if ( support.qsa &&
903 !compilerCache[ selector + " " ] &&
904 (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {
905
906 if ( nodeType !== 1 ) {
907 newContext = context;
908 newSelector = selector;
909
910 // qSA looks outside Element context, which is not what we want
911 // Thanks to Andrew Dupont for this workaround technique
912 // Support: IE <=8
913 // Exclude object elements
914 } else if ( context.nodeName.toLowerCase() !== "object" ) {
915
916 // Capture the context ID, setting it first if necessary
917 if ( (nid = context.getAttribute( "id" )) ) {
918 nid = nid.replace( rescape, "\\$&" );
919 } else {
920 context.setAttribute( "id", (nid = expando) );
921 }
922
923 // Prefix every selector in the list
924 groups = tokenize( selector );
925 i = groups.length;
926 nidselect = ridentifier.test( nid ) ? "#" + nid : "[id='" + nid + "']";
927 while ( i-- ) {
928 groups[i] = nidselect + " " + toSelector( groups[i] );
929 }
930 newSelector = groups.join( "," );
931
932 // Expand context for sibling selectors
933 newContext = rsibling.test( selector ) && testContext( context.parentNode ) ||
934 context;
935 }
936
937 if ( newSelector ) {
938 try {
939 push.apply( results,
940 newContext.querySelectorAll( newSelector )
941 );
942 return results;
943 } catch ( qsaError ) {
944 } finally {
945 if ( nid === expando ) {
946 context.removeAttribute( "id" );
947 }
948 }
949 }
950 }
951 }
952 }
953
954 // All others
955 return select( selector.replace( rtrim, "$1" ), context, results, seed );
956}
957
958/**
959 * Create key-value caches of limited size
960 * @returns {function(string, object)} Returns the Object data after storing it on itself with
961 * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
962 * deleting the oldest entry
963 */
964function createCache() {
965 var keys = [];
966
967 function cache( key, value ) {
968 // Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
969 if ( keys.push( key + " " ) > Expr.cacheLength ) {
970 // Only keep the most recent entries
971 delete cache[ keys.shift() ];
972 }
973 return (cache[ key + " " ] = value);
974 }
975 return cache;
976}
977
978/**
979 * Mark a function for special use by Sizzle
980 * @param {Function} fn The function to mark
981 */
982function markFunction( fn ) {
983 fn[ expando ] = true;
984 return fn;
985}
986
987/**
988 * Support testing using an element
989 * @param {Function} fn Passed the created div and expects a boolean result
990 */
991function assert( fn ) {
992 var div = document.createElement("div");
993
994 try {
995 return !!fn( div );
996 } catch (e) {
997 return false;
998 } finally {
999 // Remove from its parent by default
1000 if ( div.parentNode ) {
1001 div.parentNode.removeChild( div );
1002 }
1003 // release memory in IE
1004 div = null;
1005 }
1006}
1007
1008/**
1009 * Adds the same handler for all of the specified attrs
1010 * @param {String} attrs Pipe-separated list of attributes
1011 * @param {Function} handler The method that will be applied
1012 */
1013function addHandle( attrs, handler ) {
1014 var arr = attrs.split("|"),
1015 i = arr.length;
1016
1017 while ( i-- ) {
1018 Expr.attrHandle[ arr[i] ] = handler;
1019 }
1020}
1021
1022/**
1023 * Checks document order of two siblings
1024 * @param {Element} a
1025 * @param {Element} b
1026 * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b
1027 */
1028function siblingCheck( a, b ) {
1029 var cur = b && a,
1030 diff = cur && a.nodeType === 1 && b.nodeType === 1 &&
1031 ( ~b.sourceIndex || MAX_NEGATIVE ) -
1032 ( ~a.sourceIndex || MAX_NEGATIVE );
1033
1034 // Use IE sourceIndex if available on both nodes
1035 if ( diff ) {
1036 return diff;
1037 }
1038
1039 // Check if b follows a
1040 if ( cur ) {
1041 while ( (cur = cur.nextSibling) ) {
1042 if ( cur === b ) {
1043 return -1;
1044 }
1045 }
1046 }
1047
1048 return a ? 1 : -1;
1049}
1050
1051/**
1052 * Returns a function to use in pseudos for input types
1053 * @param {String} type
1054 */
1055function createInputPseudo( type ) {
1056 return function( elem ) {
1057 var name = elem.nodeName.toLowerCase();
1058 return name === "input" && elem.type === type;
1059 };
1060}
1061
1062/**
1063 * Returns a function to use in pseudos for buttons
1064 * @param {String} type
1065 */
1066function createButtonPseudo( type ) {
1067 return function( elem ) {
1068 var name = elem.nodeName.toLowerCase();
1069 return (name === "input" || name === "button") && elem.type === type;
1070 };
1071}
1072
1073/**
1074 * Returns a function to use in pseudos for positionals
1075 * @param {Function} fn
1076 */
1077function createPositionalPseudo( fn ) {
1078 return markFunction(function( argument ) {
1079 argument = +argument;
1080 return markFunction(function( seed, matches ) {
1081 var j,
1082 matchIndexes = fn( [], seed.length, argument ),
1083 i = matchIndexes.length;
1084
1085 // Match elements found at the specified indexes
1086 while ( i-- ) {
1087 if ( seed[ (j = matchIndexes[i]) ] ) {
1088 seed[j] = !(matches[j] = seed[j]);
1089 }
1090 }
1091 });
1092 });
1093}
1094
1095/**
1096 * Checks a node for validity as a Sizzle context
1097 * @param {Element|Object=} context
1098 * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value
1099 */
1100function testContext( context ) {
1101 return context && typeof context.getElementsByTagName !== "undefined" && context;
1102}
1103
1104// Expose support vars for convenience
1105support = Sizzle.support = {};
1106
1107/**
1108 * Detects XML nodes
1109 * @param {Element|Object} elem An element or a document
1110 * @returns {Boolean} True iff elem is a non-HTML XML node
1111 */
1112isXML = Sizzle.isXML = function( elem ) {
1113 // documentElement is verified for cases where it doesn't yet exist
1114 // (such as loading iframes in IE - #4833)
1115 var documentElement = elem && (elem.ownerDocument || elem).documentElement;
1116 return documentElement ? documentElement.nodeName !== "HTML" : false;
1117};
1118
1119/**
1120 * Sets document-related variables once based on the current document
1121 * @param {Element|Object} [doc] An element or document object to use to set the document
1122 * @returns {Object} Returns the current document
1123 */
1124setDocument = Sizzle.setDocument = function( node ) {
1125 var hasCompare, parent,
1126 doc = node ? node.ownerDocument || node : preferredDoc;
1127
1128 // Return early if doc is invalid or already selected
1129 if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
1130 return document;
1131 }
1132
1133 // Update global variables
1134 document = doc;
1135 docElem = document.documentElement;
1136 documentIsHTML = !isXML( document );
1137
1138 // Support: IE 9-11, Edge
1139 // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936)
1140 if ( (parent = document.defaultView) && parent.top !== parent ) {
1141 // Support: IE 11
1142 if ( parent.addEventListener ) {
1143 parent.addEventListener( "unload", unloadHandler, false );
1144
1145 // Support: IE 9 - 10 only
1146 } else if ( parent.attachEvent ) {
1147 parent.attachEvent( "onunload", unloadHandler );
1148 }
1149 }
1150
1151 /* Attributes
1152 ---------------------------------------------------------------------- */
1153
1154 // Support: IE<8
1155 // Verify that getAttribute really returns attributes and not properties
1156 // (excepting IE8 booleans)
1157 support.attributes = assert(function( div ) {
1158 div.className = "i";
1159 return !div.getAttribute("className");
1160 });
1161
1162 /* getElement(s)By*
1163 ---------------------------------------------------------------------- */
1164
1165 // Check if getElementsByTagName("*") returns only elements
1166 support.getElementsByTagName = assert(function( div ) {
1167 div.appendChild( document.createComment("") );
1168 return !div.getElementsByTagName("*").length;
1169 });
1170
1171 // Support: IE<9
1172 support.getElementsByClassName = rnative.test( document.getElementsByClassName );
1173
1174 // Support: IE<10
1175 // Check if getElementById returns elements by name
1176 // The broken getElementById methods don't pick up programatically-set names,
1177 // so use a roundabout getElementsByName test
1178 support.getById = assert(function( div ) {
1179 docElem.appendChild( div ).id = expando;
1180 return !document.getElementsByName || !document.getElementsByName( expando ).length;
1181 });
1182
1183 // ID find and filter
1184 if ( support.getById ) {
1185 Expr.find["ID"] = function( id, context ) {
1186 if ( typeof context.getElementById !== "undefined" && documentIsHTML ) {
1187 var m = context.getElementById( id );
1188 return m ? [ m ] : [];
1189 }
1190 };
1191 Expr.filter["ID"] = function( id ) {
1192 var attrId = id.replace( runescape, funescape );
1193 return function( elem ) {
1194 return elem.getAttribute("id") === attrId;
1195 };
1196 };
1197 } else {
1198 // Support: IE6/7
1199 // getElementById is not reliable as a find shortcut
1200 delete Expr.find["ID"];
1201
1202 Expr.filter["ID"] = function( id ) {
1203 var attrId = id.replace( runescape, funescape );
1204 return function( elem ) {
1205 var node = typeof elem.getAttributeNode !== "undefined" &&
1206 elem.getAttributeNode("id");
1207 return node && node.value === attrId;
1208 };
1209 };
1210 }
1211
1212 // Tag
1213 Expr.find["TAG"] = support.getElementsByTagName ?
1214 function( tag, context ) {
1215 if ( typeof context.getElementsByTagName !== "undefined" ) {
1216 return context.getElementsByTagName( tag );
1217
1218 // DocumentFragment nodes don't have gEBTN
1219 } else if ( support.qsa ) {
1220 return context.querySelectorAll( tag );
1221 }
1222 } :
1223
1224 function( tag, context ) {
1225 var elem,
1226 tmp = [],
1227 i = 0,
1228 // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too
1229 results = context.getElementsByTagName( tag );
1230
1231 // Filter out possible comments
1232 if ( tag === "*" ) {
1233 while ( (elem = results[i++]) ) {
1234 if ( elem.nodeType === 1 ) {
1235 tmp.push( elem );
1236 }
1237 }
1238
1239 return tmp;
1240 }
1241 return results;
1242 };
1243
1244 // Class
1245 Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) {
1246 if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) {
1247 return context.getElementsByClassName( className );
1248 }
1249 };
1250
1251 /* QSA/matchesSelector
1252 ---------------------------------------------------------------------- */
1253
1254 // QSA and matchesSelector support
1255
1256 // matchesSelector(:active) reports false when true (IE9/Opera 11.5)
1257 rbuggyMatches = [];
1258
1259 // qSa(:focus) reports false when true (Chrome 21)
1260 // We allow this because of a bug in IE8/9 that throws an error
1261 // So, we allow :focus to pass through QSA all the time to avoid the IE error
1262 // See http://bugs.jquery.com/ticket/13378
1263 rbuggyQSA = [];
1264
1265 if ( (support.qsa = rnative.test( document.querySelectorAll )) ) {
1266 // Build QSA regex
1267 // Regex strategy adopted from Diego Perini
1268 assert(function( div ) {
1269 // Select is set to empty string on purpose
1270 // This is to test IE's treatment of not explicitly
1271 // setting a boolean content attribute,
1272 // since its presence should be enough
1273 // http://bugs.jquery.com/ticket/12359
1274 docElem.appendChild( div ).innerHTML = "<a id='" + expando + "'></a>" +
1275 "<select id='" + expando + "-\r\\' msallowcapture=''>" +
1276 "<option selected=''></option></select>";
1277
1278 // Support: IE8, Opera 11-12.16
1279 // Nothing should be selected when empty strings follow ^= or $= or *=
1280 // The test attribute must be unknown in Opera but "safe" for WinRT
1281 // http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section
1282 if ( div.querySelectorAll("[msallowcapture^='']").length ) {
1283 rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" );
1284 }
1285
1286 // Support: IE8
1287 // Boolean attributes and "value" are not treated correctly
1288 if ( !div.querySelectorAll("[selected]").length ) {
1289 rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" );
1290 }
1291
1292 // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+
1293 if ( !div.querySelectorAll( "[id~=" + expando + "-]" ).length ) {
1294 rbuggyQSA.push("~=");
1295 }
1296
1297 // Webkit/Opera - :checked should return selected option elements
1298 // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
1299 // IE8 throws error here and will not see later tests
1300 if ( !div.querySelectorAll(":checked").length ) {
1301 rbuggyQSA.push(":checked");
1302 }
1303
1304 // Support: Safari 8+, iOS 8+
1305 // https://bugs.webkit.org/show_bug.cgi?id=136851
1306 if ( !div.querySelectorAll( "a#" + expando + "+*" ).length ) {
1307 rbuggyQSA.push(".#.+[+~]");
1308 }
1309 });
1310
1311 assert(function( div ) {
1312 // Support: Windows 8 Native Apps
1313 // The type and name attributes are restricted during .innerHTML assignment
1314 var input = document.createElement("input");
1315 input.setAttribute( "type", "hidden" );
1316 div.appendChild( input ).setAttribute( "name", "D" );
1317
1318 // Support: IE8
1319 // Enforce case-sensitivity of name attribute
1320 if ( div.querySelectorAll("[name=d]").length ) {
1321 rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" );
1322 }
1323
1324 // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
1325 // IE8 throws error here and will not see later tests
1326 if ( !div.querySelectorAll(":enabled").length ) {
1327 rbuggyQSA.push( ":enabled", ":disabled" );
1328 }
1329
1330 // Opera 10-11 does not throw on post-comma invalid pseudos
1331 div.querySelectorAll("*,:x");
1332 rbuggyQSA.push(",.*:");
1333 });
1334 }
1335
1336 if ( (support.matchesSelector = rnative.test( (matches = docElem.matches ||
1337 docElem.webkitMatchesSelector ||
1338 docElem.mozMatchesSelector ||
1339 docElem.oMatchesSelector ||
1340 docElem.msMatchesSelector) )) ) {
1341
1342 assert(function( div ) {
1343 // Check to see if it's possible to do matchesSelector
1344 // on a disconnected node (IE 9)
1345 support.disconnectedMatch = matches.call( div, "div" );
1346
1347 // This should fail with an exception
1348 // Gecko does not error, returns false instead
1349 matches.call( div, "[s!='']:x" );
1350 rbuggyMatches.push( "!=", pseudos );
1351 });
1352 }
1353
1354 rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") );
1355 rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") );
1356
1357 /* Contains
1358 ---------------------------------------------------------------------- */
1359 hasCompare = rnative.test( docElem.compareDocumentPosition );
1360
1361 // Element contains another
1362 // Purposefully self-exclusive
1363 // As in, an element does not contain itself
1364 contains = hasCompare || rnative.test( docElem.contains ) ?
1365 function( a, b ) {
1366 var adown = a.nodeType === 9 ? a.documentElement : a,
1367 bup = b && b.parentNode;
1368 return a === bup || !!( bup && bup.nodeType === 1 && (
1369 adown.contains ?
1370 adown.contains( bup ) :
1371 a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
1372 ));
1373 } :
1374 function( a, b ) {
1375 if ( b ) {
1376 while ( (b = b.parentNode) ) {
1377 if ( b === a ) {
1378 return true;
1379 }
1380 }
1381 }
1382 return false;
1383 };
1384
1385 /* Sorting
1386 ---------------------------------------------------------------------- */
1387
1388 // Document order sorting
1389 sortOrder = hasCompare ?
1390 function( a, b ) {
1391
1392 // Flag for duplicate removal
1393 if ( a === b ) {
1394 hasDuplicate = true;
1395 return 0;
1396 }
1397
1398 // Sort on method existence if only one input has compareDocumentPosition
1399 var compare = !a.compareDocumentPosition - !b.compareDocumentPosition;
1400 if ( compare ) {
1401 return compare;
1402 }
1403
1404 // Calculate position if both inputs belong to the same document
1405 compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ?
1406 a.compareDocumentPosition( b ) :
1407
1408 // Otherwise we know they are disconnected
1409 1;
1410
1411 // Disconnected nodes
1412 if ( compare & 1 ||
1413 (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {
1414
1415 // Choose the first element that is related to our preferred document
1416 if ( a === document || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {
1417 return -1;
1418 }
1419 if ( b === document || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) {
1420 return 1;
1421 }
1422
1423 // Maintain original order
1424 return sortInput ?
1425 ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
1426 0;
1427 }
1428
1429 return compare & 4 ? -1 : 1;
1430 } :
1431 function( a, b ) {
1432 // Exit early if the nodes are identical
1433 if ( a === b ) {
1434 hasDuplicate = true;
1435 return 0;
1436 }
1437
1438 var cur,
1439 i = 0,
1440 aup = a.parentNode,
1441 bup = b.parentNode,
1442 ap = [ a ],
1443 bp = [ b ];
1444
1445 // Parentless nodes are either documents or disconnected
1446 if ( !aup || !bup ) {
1447 return a === document ? -1 :
1448 b === document ? 1 :
1449 aup ? -1 :
1450 bup ? 1 :
1451 sortInput ?
1452 ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
1453 0;
1454
1455 // If the nodes are siblings, we can do a quick check
1456 } else if ( aup === bup ) {
1457 return siblingCheck( a, b );
1458 }
1459
1460 // Otherwise we need full lists of their ancestors for comparison
1461 cur = a;
1462 while ( (cur = cur.parentNode) ) {
1463 ap.unshift( cur );
1464 }
1465 cur = b;
1466 while ( (cur = cur.parentNode) ) {
1467 bp.unshift( cur );
1468 }
1469
1470 // Walk down the tree looking for a discrepancy
1471 while ( ap[i] === bp[i] ) {
1472 i++;
1473 }
1474
1475 return i ?
1476 // Do a sibling check if the nodes have a common ancestor
1477 siblingCheck( ap[i], bp[i] ) :
1478
1479 // Otherwise nodes in our document sort first
1480 ap[i] === preferredDoc ? -1 :
1481 bp[i] === preferredDoc ? 1 :
1482 0;
1483 };
1484
1485 return document;
1486};
1487
1488Sizzle.matches = function( expr, elements ) {
1489 return Sizzle( expr, null, null, elements );
1490};
1491
1492Sizzle.matchesSelector = function( elem, expr ) {
1493 // Set document vars if needed
1494 if ( ( elem.ownerDocument || elem ) !== document ) {
1495 setDocument( elem );
1496 }
1497
1498 // Make sure that attribute selectors are quoted
1499 expr = expr.replace( rattributeQuotes, "='$1']" );
1500
1501 if ( support.matchesSelector && documentIsHTML &&
1502 !compilerCache[ expr + " " ] &&
1503 ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&
1504 ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) {
1505
1506 try {
1507 var ret = matches.call( elem, expr );
1508
1509 // IE 9's matchesSelector returns false on disconnected nodes
1510 if ( ret || support.disconnectedMatch ||
1511 // As well, disconnected nodes are said to be in a document
1512 // fragment in IE 9
1513 elem.document && elem.document.nodeType !== 11 ) {
1514 return ret;
1515 }
1516 } catch (e) {}
1517 }
1518
1519 return Sizzle( expr, document, null, [ elem ] ).length > 0;
1520};
1521
1522Sizzle.contains = function( context, elem ) {
1523 // Set document vars if needed
1524 if ( ( context.ownerDocument || context ) !== document ) {
1525 setDocument( context );
1526 }
1527 return contains( context, elem );
1528};
1529
1530Sizzle.attr = function( elem, name ) {
1531 // Set document vars if needed
1532 if ( ( elem.ownerDocument || elem ) !== document ) {
1533 setDocument( elem );
1534 }
1535
1536 var fn = Expr.attrHandle[ name.toLowerCase() ],
1537 // Don't get fooled by Object.prototype properties (jQuery #13807)
1538 val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?
1539 fn( elem, name, !documentIsHTML ) :
1540 undefined;
1541
1542 return val !== undefined ?
1543 val :
1544 support.attributes || !documentIsHTML ?
1545 elem.getAttribute( name ) :
1546 (val = elem.getAttributeNode(name)) && val.specified ?
1547 val.value :
1548 null;
1549};
1550
1551Sizzle.error = function( msg ) {
1552 throw new Error( "Syntax error, unrecognized expression: " + msg );
1553};
1554
1555/**
1556 * Document sorting and removing duplicates
1557 * @param {ArrayLike} results
1558 */
1559Sizzle.uniqueSort = function( results ) {
1560 var elem,
1561 duplicates = [],
1562 j = 0,
1563 i = 0;
1564
1565 // Unless we *know* we can detect duplicates, assume their presence
1566 hasDuplicate = !support.detectDuplicates;
1567 sortInput = !support.sortStable && results.slice( 0 );
1568 results.sort( sortOrder );
1569
1570 if ( hasDuplicate ) {
1571 while ( (elem = results[i++]) ) {
1572 if ( elem === results[ i ] ) {
1573 j = duplicates.push( i );
1574 }
1575 }
1576 while ( j-- ) {
1577 results.splice( duplicates[ j ], 1 );
1578 }
1579 }
1580
1581 // Clear input after sorting to release objects
1582 // See https://github.com/jquery/sizzle/pull/225
1583 sortInput = null;
1584
1585 return results;
1586};
1587
1588/**
1589 * Utility function for retrieving the text value of an array of DOM nodes
1590 * @param {Array|Element} elem
1591 */
1592getText = Sizzle.getText = function( elem ) {
1593 var node,
1594 ret = "",
1595 i = 0,
1596 nodeType = elem.nodeType;
1597
1598 if ( !nodeType ) {
1599 // If no nodeType, this is expected to be an array
1600 while ( (node = elem[i++]) ) {
1601 // Do not traverse comment nodes
1602 ret += getText( node );
1603 }
1604 } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
1605 // Use textContent for elements
1606 // innerText usage removed for consistency of new lines (jQuery #11153)
1607 if ( typeof elem.textContent === "string" ) {
1608 return elem.textContent;
1609 } else {
1610 // Traverse its children
1611 for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
1612 ret += getText( elem );
1613 }
1614 }
1615 } else if ( nodeType === 3 || nodeType === 4 ) {
1616 return elem.nodeValue;
1617 }
1618 // Do not include comment or processing instruction nodes
1619
1620 return ret;
1621};
1622
1623Expr = Sizzle.selectors = {
1624
1625 // Can be adjusted by the user
1626 cacheLength: 50,
1627
1628 createPseudo: markFunction,
1629
1630 match: matchExpr,
1631
1632 attrHandle: {},
1633
1634 find: {},
1635
1636 relative: {
1637 ">": { dir: "parentNode", first: true },
1638 " ": { dir: "parentNode" },
1639 "+": { dir: "previousSibling", first: true },
1640 "~": { dir: "previousSibling" }
1641 },
1642
1643 preFilter: {
1644 "ATTR": function( match ) {
1645 match[1] = match[1].replace( runescape, funescape );
1646
1647 // Move the given value to match[3] whether quoted or unquoted
1648 match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape );
1649
1650 if ( match[2] === "~=" ) {
1651 match[3] = " " + match[3] + " ";
1652 }
1653
1654 return match.slice( 0, 4 );
1655 },
1656
1657 "CHILD": function( match ) {
1658 /* matches from matchExpr["CHILD"]
1659 1 type (only|nth|...)
1660 2 what (child|of-type)
1661 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
1662 4 xn-component of xn+y argument ([+-]?\d*n|)
1663 5 sign of xn-component
1664 6 x of xn-component
1665 7 sign of y-component
1666 8 y of y-component
1667 */
1668 match[1] = match[1].toLowerCase();
1669
1670 if ( match[1].slice( 0, 3 ) === "nth" ) {
1671 // nth-* requires argument
1672 if ( !match[3] ) {
1673 Sizzle.error( match[0] );
1674 }
1675
1676 // numeric x and y parameters for Expr.filter.CHILD
1677 // remember that false/true cast respectively to 0/1
1678 match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) );
1679 match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" );
1680
1681 // other types prohibit arguments
1682 } else if ( match[3] ) {
1683 Sizzle.error( match[0] );
1684 }
1685
1686 return match;
1687 },
1688
1689 "PSEUDO": function( match ) {
1690 var excess,
1691 unquoted = !match[6] && match[2];
1692
1693 if ( matchExpr["CHILD"].test( match[0] ) ) {
1694 return null;
1695 }
1696
1697 // Accept quoted arguments as-is
1698 if ( match[3] ) {
1699 match[2] = match[4] || match[5] || "";
1700
1701 // Strip excess characters from unquoted arguments
1702 } else if ( unquoted && rpseudo.test( unquoted ) &&
1703 // Get excess from tokenize (recursively)
1704 (excess = tokenize( unquoted, true )) &&
1705 // advance to the next closing parenthesis
1706 (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {
1707
1708 // excess is a negative index
1709 match[0] = match[0].slice( 0, excess );
1710 match[2] = unquoted.slice( 0, excess );
1711 }
1712
1713 // Return only captures needed by the pseudo filter method (type and argument)
1714 return match.slice( 0, 3 );
1715 }
1716 },
1717
1718 filter: {
1719
1720 "TAG": function( nodeNameSelector ) {
1721 var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();
1722 return nodeNameSelector === "*" ?
1723 function() { return true; } :
1724 function( elem ) {
1725 return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
1726 };
1727 },
1728
1729 "CLASS": function( className ) {
1730 var pattern = classCache[ className + " " ];
1731
1732 return pattern ||
1733 (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&
1734 classCache( className, function( elem ) {
1735 return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" );
1736 });
1737 },
1738
1739 "ATTR": function( name, operator, check ) {
1740 return function( elem ) {
1741 var result = Sizzle.attr( elem, name );
1742
1743 if ( result == null ) {
1744 return operator === "!=";
1745 }
1746 if ( !operator ) {
1747 return true;
1748 }
1749
1750 result += "";
1751
1752 return operator === "=" ? result === check :
1753 operator === "!=" ? result !== check :
1754 operator === "^=" ? check && result.indexOf( check ) === 0 :
1755 operator === "*=" ? check && result.indexOf( check ) > -1 :
1756 operator === "$=" ? check && result.slice( -check.length ) === check :
1757 operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 :
1758 operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
1759 false;
1760 };
1761 },
1762
1763 "CHILD": function( type, what, argument, first, last ) {
1764 var simple = type.slice( 0, 3 ) !== "nth",
1765 forward = type.slice( -4 ) !== "last",
1766 ofType = what === "of-type";
1767
1768 return first === 1 && last === 0 ?
1769
1770 // Shortcut for :nth-*(n)
1771 function( elem ) {
1772 return !!elem.parentNode;
1773 } :
1774
1775 function( elem, context, xml ) {
1776 var cache, uniqueCache, outerCache, node, nodeIndex, start,
1777 dir = simple !== forward ? "nextSibling" : "previousSibling",
1778 parent = elem.parentNode,
1779 name = ofType && elem.nodeName.toLowerCase(),
1780 useCache = !xml && !ofType,
1781 diff = false;
1782
1783 if ( parent ) {
1784
1785 // :(first|last|only)-(child|of-type)
1786 if ( simple ) {
1787 while ( dir ) {
1788 node = elem;
1789 while ( (node = node[ dir ]) ) {
1790 if ( ofType ?
1791 node.nodeName.toLowerCase() === name :
1792 node.nodeType === 1 ) {
1793
1794 return false;
1795 }
1796 }
1797 // Reverse direction for :only-* (if we haven't yet done so)
1798 start = dir = type === "only" && !start && "nextSibling";
1799 }
1800 return true;
1801 }
1802
1803 start = [ forward ? parent.firstChild : parent.lastChild ];
1804
1805 if ( forward && useCache ) {
1806
1807
1808 // ...in a gzip-friendly way
1809 node = parent;
1810 outerCache = node[ expando ] || (node[ expando ] = {});
1811
1812 // Support: IE <9 only
1813 // Defend against cloned attroperties (jQuery gh-1709)
1814 uniqueCache = outerCache[ node.uniqueID ] ||
1815 (outerCache[ node.uniqueID ] = {});
1816
1817 cache = uniqueCache[ type ] || [];
1818 nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];
1819 diff = nodeIndex && cache[ 2 ];
1820 node = nodeIndex && parent.childNodes[ nodeIndex ];
1821
1822 while ( (node = ++nodeIndex && node && node[ dir ] ||
1823
1824 (diff = nodeIndex = 0) || start.pop()) ) {
1825
1826 if ( node.nodeType === 1 && ++diff && node === elem ) {
1827 uniqueCache[ type ] = [ dirruns, nodeIndex, diff ];
1828 break;
1829 }
1830 }
1831
1832 } else {
1833 // Use previously-cached element index if available
1834 if ( useCache ) {
1835 // ...in a gzip-friendly way
1836 node = elem;
1837 outerCache = node[ expando ] || (node[ expando ] = {});
1838
1839 // Support: IE <9 only
1840 // Defend against cloned attroperties (jQuery gh-1709)
1841 uniqueCache = outerCache[ node.uniqueID ] ||
1842 (outerCache[ node.uniqueID ] = {});
1843
1844 cache = uniqueCache[ type ] || [];
1845 nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];
1846 diff = nodeIndex;
1847 }
1848
1849 // xml :nth-child(...)
1850 // or :nth-last-child(...) or :nth(-last)?-of-type(...)
1851 if ( diff === false ) {
1852 while ( (node = ++nodeIndex && node && node[ dir ] ||
1853 (diff = nodeIndex = 0) || start.pop()) ) {
1854
1855 if ( ( ofType ?
1856 node.nodeName.toLowerCase() === name :
1857 node.nodeType === 1 ) &&
1858 ++diff ) {
1859
1860 // Cache the index of each encountered element
1861 if ( useCache ) {
1862 outerCache = node[ expando ] || (node[ expando ] = {});
1863
1864 // Support: IE <9 only
1865 // Defend against cloned attroperties (jQuery gh-1709)
1866 uniqueCache = outerCache[ node.uniqueID ] ||
1867 (outerCache[ node.uniqueID ] = {});
1868
1869 uniqueCache[ type ] = [ dirruns, diff ];
1870 }
1871
1872 if ( node === elem ) {
1873 break;
1874 }
1875 }
1876 }
1877 }
1878 }
1879
1880 // Incorporate the offset, then check against cycle size
1881 diff -= last;
1882 return diff === first || ( diff % first === 0 && diff / first >= 0 );
1883 }
1884 };
1885 },
1886
1887 "PSEUDO": function( pseudo, argument ) {
1888 // pseudo-class names are case-insensitive
1889 // http://www.w3.org/TR/selectors/#pseudo-classes
1890 // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
1891 // Remember that setFilters inherits from pseudos
1892 var args,
1893 fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
1894 Sizzle.error( "unsupported pseudo: " + pseudo );
1895
1896 // The user may use createPseudo to indicate that
1897 // arguments are needed to create the filter function
1898 // just as Sizzle does
1899 if ( fn[ expando ] ) {
1900 return fn( argument );
1901 }
1902
1903 // But maintain support for old signatures
1904 if ( fn.length > 1 ) {
1905 args = [ pseudo, pseudo, "", argument ];
1906 return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
1907 markFunction(function( seed, matches ) {
1908 var idx,
1909 matched = fn( seed, argument ),
1910 i = matched.length;
1911 while ( i-- ) {
1912 idx = indexOf( seed, matched[i] );
1913 seed[ idx ] = !( matches[ idx ] = matched[i] );
1914 }
1915 }) :
1916 function( elem ) {
1917 return fn( elem, 0, args );
1918 };
1919 }
1920
1921 return fn;
1922 }
1923 },
1924
1925 pseudos: {
1926 // Potentially complex pseudos
1927 "not": markFunction(function( selector ) {
1928 // Trim the selector passed to compile
1929 // to avoid treating leading and trailing
1930 // spaces as combinators
1931 var input = [],
1932 results = [],
1933 matcher = compile( selector.replace( rtrim, "$1" ) );
1934
1935 return matcher[ expando ] ?
1936 markFunction(function( seed, matches, context, xml ) {
1937 var elem,
1938 unmatched = matcher( seed, null, xml, [] ),
1939 i = seed.length;
1940
1941 while ( i-- ) {
1942 if ( (elem = unmatched[i]) ) {
1943 seed[i] = !(matches[i] = elem);
1944 }
1945 }
1946 }) :
1947 function( elem, context, xml ) {
1948 input[0] = elem;
1949 matcher( input, null, xml, results );
1950 // Don't keep the element (issue #299)
1951 input[0] = null;
1952 return !results.pop();
1953 };
1954 }),
1955
1956 "has": markFunction(function( selector ) {
1957 return function( elem ) {
1958 return Sizzle( selector, elem ).length > 0;
1959 };
1960 }),
1961
1962 "contains": markFunction(function( text ) {
1963 text = text.replace( runescape, funescape );
1964 return function( elem ) {
1965 return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
1966 };
1967 }),
1968
1969 // "Whether an element is represented by a :lang() selector
1970 // is based solely on the element's language value
1971 // being equal to the identifier C,
1972 // or beginning with the identifier C immediately followed by "-".
1973 // The matching of C against the element's language value is performed case-insensitively.
1974 // The identifier C does not have to be a valid language name."
1975 // http://www.w3.org/TR/selectors/#lang-pseudo
1976 "lang": markFunction( function( lang ) {
1977 // lang value must be a valid identifier
1978 if ( !ridentifier.test(lang || "") ) {
1979 Sizzle.error( "unsupported lang: " + lang );
1980 }
1981 lang = lang.replace( runescape, funescape ).toLowerCase();
1982 return function( elem ) {
1983 var elemLang;
1984 do {
1985 if ( (elemLang = documentIsHTML ?
1986 elem.lang :
1987 elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) {
1988
1989 elemLang = elemLang.toLowerCase();
1990 return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
1991 }
1992 } while ( (elem = elem.parentNode) && elem.nodeType === 1 );
1993 return false;
1994 };
1995 }),
1996
1997 // Miscellaneous
1998 "target": function( elem ) {
1999 var hash = window.location && window.location.hash;
2000 return hash && hash.slice( 1 ) === elem.id;
2001 },
2002
2003 "root": function( elem ) {
2004 return elem === docElem;
2005 },
2006
2007 "focus": function( elem ) {
2008 return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
2009 },
2010
2011 // Boolean properties
2012 "enabled": function( elem ) {
2013 return elem.disabled === false;
2014 },
2015
2016 "disabled": function( elem ) {
2017 return elem.disabled === true;
2018 },
2019
2020 "checked": function( elem ) {
2021 // In CSS3, :checked should return both checked and selected elements
2022 // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
2023 var nodeName = elem.nodeName.toLowerCase();
2024 return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
2025 },
2026
2027 "selected": function( elem ) {
2028 // Accessing this property makes selected-by-default
2029 // options in Safari work properly
2030 if ( elem.parentNode ) {
2031 elem.parentNode.selectedIndex;
2032 }
2033
2034 return elem.selected === true;
2035 },
2036
2037 // Contents
2038 "empty": function( elem ) {
2039 // http://www.w3.org/TR/selectors/#empty-pseudo
2040 // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),
2041 // but not by others (comment: 8; processing instruction: 7; etc.)
2042 // nodeType < 6 works because attributes (2) do not appear as children
2043 for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
2044 if ( elem.nodeType < 6 ) {
2045 return false;
2046 }
2047 }
2048 return true;
2049 },
2050
2051 "parent": function( elem ) {
2052 return !Expr.pseudos["empty"]( elem );
2053 },
2054
2055 // Element/input types
2056 "header": function( elem ) {
2057 return rheader.test( elem.nodeName );
2058 },
2059
2060 "input": function( elem ) {
2061 return rinputs.test( elem.nodeName );
2062 },
2063
2064 "button": function( elem ) {
2065 var name = elem.nodeName.toLowerCase();
2066 return name === "input" && elem.type === "button" || name === "button";
2067 },
2068
2069 "text": function( elem ) {
2070 var attr;
2071 return elem.nodeName.toLowerCase() === "input" &&
2072 elem.type === "text" &&
2073
2074 // Support: IE<8
2075 // New HTML5 attribute values (e.g., "search") appear with elem.type === "text"
2076 ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" );
2077 },
2078
2079 // Position-in-collection
2080 "first": createPositionalPseudo(function() {
2081 return [ 0 ];
2082 }),
2083
2084 "last": createPositionalPseudo(function( matchIndexes, length ) {
2085 return [ length - 1 ];
2086 }),
2087
2088 "eq": createPositionalPseudo(function( matchIndexes, length, argument ) {
2089 return [ argument < 0 ? argument + length : argument ];
2090 }),
2091
2092 "even": createPositionalPseudo(function( matchIndexes, length ) {
2093 var i = 0;
2094 for ( ; i < length; i += 2 ) {
2095 matchIndexes.push( i );
2096 }
2097 return matchIndexes;
2098 }),
2099
2100 "odd": createPositionalPseudo(function( matchIndexes, length ) {
2101 var i = 1;
2102 for ( ; i < length; i += 2 ) {
2103 matchIndexes.push( i );
2104 }
2105 return matchIndexes;
2106 }),
2107
2108 "lt": createPositionalPseudo(function( matchIndexes, length, argument ) {
2109 var i = argument < 0 ? argument + length : argument;
2110 for ( ; --i >= 0; ) {
2111 matchIndexes.push( i );
2112 }
2113 return matchIndexes;
2114 }),
2115
2116 "gt": createPositionalPseudo(function( matchIndexes, length, argument ) {
2117 var i = argument < 0 ? argument + length : argument;
2118 for ( ; ++i < length; ) {
2119 matchIndexes.push( i );
2120 }
2121 return matchIndexes;
2122 })
2123 }
2124};
2125
2126Expr.pseudos["nth"] = Expr.pseudos["eq"];
2127
2128// Add button/input type pseudos
2129for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
2130 Expr.pseudos[ i ] = createInputPseudo( i );
2131}
2132for ( i in { submit: true, reset: true } ) {
2133 Expr.pseudos[ i ] = createButtonPseudo( i );
2134}
2135
2136// Easy API for creating new setFilters
2137function setFilters() {}
2138setFilters.prototype = Expr.filters = Expr.pseudos;
2139Expr.setFilters = new setFilters();
2140
2141tokenize = Sizzle.tokenize = function( selector, parseOnly ) {
2142 var matched, match, tokens, type,
2143 soFar, groups, preFilters,
2144 cached = tokenCache[ selector + " " ];
2145
2146 if ( cached ) {
2147 return parseOnly ? 0 : cached.slice( 0 );
2148 }
2149
2150 soFar = selector;
2151 groups = [];
2152 preFilters = Expr.preFilter;
2153
2154 while ( soFar ) {
2155
2156 // Comma and first run
2157 if ( !matched || (match = rcomma.exec( soFar )) ) {
2158 if ( match ) {
2159 // Don't consume trailing commas as valid
2160 soFar = soFar.slice( match[0].length ) || soFar;
2161 }
2162 groups.push( (tokens = []) );
2163 }
2164
2165 matched = false;
2166
2167 // Combinators
2168 if ( (match = rcombinators.exec( soFar )) ) {
2169 matched = match.shift();
2170 tokens.push({
2171 value: matched,
2172 // Cast descendant combinators to space
2173 type: match[0].replace( rtrim, " " )
2174 });
2175 soFar = soFar.slice( matched.length );
2176 }
2177
2178 // Filters
2179 for ( type in Expr.filter ) {
2180 if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
2181 (match = preFilters[ type ]( match ))) ) {
2182 matched = match.shift();
2183 tokens.push({
2184 value: matched,
2185 type: type,
2186 matches: match
2187 });
2188 soFar = soFar.slice( matched.length );
2189 }
2190 }
2191
2192 if ( !matched ) {
2193 break;
2194 }
2195 }
2196
2197 // Return the length of the invalid excess
2198 // if we're just parsing
2199 // Otherwise, throw an error or return tokens
2200 return parseOnly ?
2201 soFar.length :
2202 soFar ?
2203 Sizzle.error( selector ) :
2204 // Cache the tokens
2205 tokenCache( selector, groups ).slice( 0 );
2206};
2207
2208function toSelector( tokens ) {
2209 var i = 0,
2210 len = tokens.length,
2211 selector = "";
2212 for ( ; i < len; i++ ) {
2213 selector += tokens[i].value;
2214 }
2215 return selector;
2216}
2217
2218function addCombinator( matcher, combinator, base ) {
2219 var dir = combinator.dir,
2220 checkNonElements = base && dir === "parentNode",
2221 doneName = done++;
2222
2223 return combinator.first ?
2224 // Check against closest ancestor/preceding element
2225 function( elem, context, xml ) {
2226 while ( (elem = elem[ dir ]) ) {
2227 if ( elem.nodeType === 1 || checkNonElements ) {
2228 return matcher( elem, context, xml );
2229 }
2230 }
2231 } :
2232
2233 // Check against all ancestor/preceding elements
2234 function( elem, context, xml ) {
2235 var oldCache, uniqueCache, outerCache,
2236 newCache = [ dirruns, doneName ];
2237
2238 // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching
2239 if ( xml ) {
2240 while ( (elem = elem[ dir ]) ) {
2241 if ( elem.nodeType === 1 || checkNonElements ) {
2242 if ( matcher( elem, context, xml ) ) {
2243 return true;
2244 }
2245 }
2246 }
2247 } else {
2248 while ( (elem = elem[ dir ]) ) {
2249 if ( elem.nodeType === 1 || checkNonElements ) {
2250 outerCache = elem[ expando ] || (elem[ expando ] = {});
2251
2252 // Support: IE <9 only
2253 // Defend against cloned attroperties (jQuery gh-1709)
2254 uniqueCache = outerCache[ elem.uniqueID ] || (outerCache[ elem.uniqueID ] = {});
2255
2256 if ( (oldCache = uniqueCache[ dir ]) &&
2257 oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {
2258
2259 // Assign to newCache so results back-propagate to previous elements
2260 return (newCache[ 2 ] = oldCache[ 2 ]);
2261 } else {
2262 // Reuse newcache so results back-propagate to previous elements
2263 uniqueCache[ dir ] = newCache;
2264
2265 // A match means we're done; a fail means we have to keep checking
2266 if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) {
2267 return true;
2268 }
2269 }
2270 }
2271 }
2272 }
2273 };
2274}
2275
2276function elementMatcher( matchers ) {
2277 return matchers.length > 1 ?
2278 function( elem, context, xml ) {
2279 var i = matchers.length;
2280 while ( i-- ) {
2281 if ( !matchers[i]( elem, context, xml ) ) {
2282 return false;
2283 }
2284 }
2285 return true;
2286 } :
2287 matchers[0];
2288}
2289
2290function multipleContexts( selector, contexts, results ) {
2291 var i = 0,
2292 len = contexts.length;
2293 for ( ; i < len; i++ ) {
2294 Sizzle( selector, contexts[i], results );
2295 }
2296 return results;
2297}
2298
2299function condense( unmatched, map, filter, context, xml ) {
2300 var elem,
2301 newUnmatched = [],
2302 i = 0,
2303 len = unmatched.length,
2304 mapped = map != null;
2305
2306 for ( ; i < len; i++ ) {
2307 if ( (elem = unmatched[i]) ) {
2308 if ( !filter || filter( elem, context, xml ) ) {
2309 newUnmatched.push( elem );
2310 if ( mapped ) {
2311 map.push( i );
2312 }
2313 }
2314 }
2315 }
2316
2317 return newUnmatched;
2318}
2319
2320function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
2321 if ( postFilter && !postFilter[ expando ] ) {
2322 postFilter = setMatcher( postFilter );
2323 }
2324 if ( postFinder && !postFinder[ expando ] ) {
2325 postFinder = setMatcher( postFinder, postSelector );
2326 }
2327 return markFunction(function( seed, results, context, xml ) {
2328 var temp, i, elem,
2329 preMap = [],
2330 postMap = [],
2331 preexisting = results.length,
2332
2333 // Get initial elements from seed or context
2334 elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ),
2335
2336 // Prefilter to get matcher input, preserving a map for seed-results synchronization
2337 matcherIn = preFilter && ( seed || !selector ) ?
2338 condense( elems, preMap, preFilter, context, xml ) :
2339 elems,
2340
2341 matcherOut = matcher ?
2342 // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
2343 postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
2344
2345 // ...intermediate processing is necessary
2346 [] :
2347
2348 // ...otherwise use results directly
2349 results :
2350 matcherIn;
2351
2352 // Find primary matches
2353 if ( matcher ) {
2354 matcher( matcherIn, matcherOut, context, xml );
2355 }
2356
2357 // Apply postFilter
2358 if ( postFilter ) {
2359 temp = condense( matcherOut, postMap );
2360 postFilter( temp, [], context, xml );
2361
2362 // Un-match failing elements by moving them back to matcherIn
2363 i = temp.length;
2364 while ( i-- ) {
2365 if ( (elem = temp[i]) ) {
2366 matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);
2367 }
2368 }
2369 }
2370
2371 if ( seed ) {
2372 if ( postFinder || preFilter ) {
2373 if ( postFinder ) {
2374 // Get the final matcherOut by condensing this intermediate into postFinder contexts
2375 temp = [];
2376 i = matcherOut.length;
2377 while ( i-- ) {
2378 if ( (elem = matcherOut[i]) ) {
2379 // Restore matcherIn since elem is not yet a final match
2380 temp.push( (matcherIn[i] = elem) );
2381 }
2382 }
2383 postFinder( null, (matcherOut = []), temp, xml );
2384 }
2385
2386 // Move matched elements from seed to results to keep them synchronized
2387 i = matcherOut.length;
2388 while ( i-- ) {
2389 if ( (elem = matcherOut[i]) &&
2390 (temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) {
2391
2392 seed[temp] = !(results[temp] = elem);
2393 }
2394 }
2395 }
2396
2397 // Add elements to results, through postFinder if defined
2398 } else {
2399 matcherOut = condense(
2400 matcherOut === results ?
2401 matcherOut.splice( preexisting, matcherOut.length ) :
2402 matcherOut
2403 );
2404 if ( postFinder ) {
2405 postFinder( null, results, matcherOut, xml );
2406 } else {
2407 push.apply( results, matcherOut );
2408 }
2409 }
2410 });
2411}
2412
2413function matcherFromTokens( tokens ) {
2414 var checkContext, matcher, j,
2415 len = tokens.length,
2416 leadingRelative = Expr.relative[ tokens[0].type ],
2417 implicitRelative = leadingRelative || Expr.relative[" "],
2418 i = leadingRelative ? 1 : 0,
2419
2420 // The foundational matcher ensures that elements are reachable from top-level context(s)
2421 matchContext = addCombinator( function( elem ) {
2422 return elem === checkContext;
2423 }, implicitRelative, true ),
2424 matchAnyContext = addCombinator( function( elem ) {
2425 return indexOf( checkContext, elem ) > -1;
2426 }, implicitRelative, true ),
2427 matchers = [ function( elem, context, xml ) {
2428 var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
2429 (checkContext = context).nodeType ?
2430 matchContext( elem, context, xml ) :
2431 matchAnyContext( elem, context, xml ) );
2432 // Avoid hanging onto element (issue #299)
2433 checkContext = null;
2434 return ret;
2435 } ];
2436
2437 for ( ; i < len; i++ ) {
2438 if ( (matcher = Expr.relative[ tokens[i].type ]) ) {
2439 matchers = [ addCombinator(elementMatcher( matchers ), matcher) ];
2440 } else {
2441 matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );
2442
2443 // Return special upon seeing a positional matcher
2444 if ( matcher[ expando ] ) {
2445 // Find the next relative operator (if any) for proper handling
2446 j = ++i;
2447 for ( ; j < len; j++ ) {
2448 if ( Expr.relative[ tokens[j].type ] ) {
2449 break;
2450 }
2451 }
2452 return setMatcher(
2453 i > 1 && elementMatcher( matchers ),
2454 i > 1 && toSelector(
2455 tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" })
2456 ).replace( rtrim, "$1" ),
2457 matcher,
2458 i < j && matcherFromTokens( tokens.slice( i, j ) ),
2459 j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),
2460 j < len && toSelector( tokens )
2461 );
2462 }
2463 matchers.push( matcher );
2464 }
2465 }
2466
2467 return elementMatcher( matchers );
2468}
2469
2470function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
2471 var bySet = setMatchers.length > 0,
2472 byElement = elementMatchers.length > 0,
2473 superMatcher = function( seed, context, xml, results, outermost ) {
2474 var elem, j, matcher,
2475 matchedCount = 0,
2476 i = "0",
2477 unmatched = seed && [],
2478 setMatched = [],
2479 contextBackup = outermostContext,
2480 // We must always have either seed elements or outermost context
2481 elems = seed || byElement && Expr.find["TAG"]( "*", outermost ),
2482 // Use integer dirruns iff this is the outermost matcher
2483 dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1),
2484 len = elems.length;
2485
2486 if ( outermost ) {
2487 outermostContext = context === document || context || outermost;
2488 }
2489
2490 // Add elements passing elementMatchers directly to results
2491 // Support: IE<9, Safari
2492 // Tolerate NodeList properties (IE: "length"; Safari: <number>) matching elements by id
2493 for ( ; i !== len && (elem = elems[i]) != null; i++ ) {
2494 if ( byElement && elem ) {
2495 j = 0;
2496 if ( !context && elem.ownerDocument !== document ) {
2497 setDocument( elem );
2498 xml = !documentIsHTML;
2499 }
2500 while ( (matcher = elementMatchers[j++]) ) {
2501 if ( matcher( elem, context || document, xml) ) {
2502 results.push( elem );
2503 break;
2504 }
2505 }
2506 if ( outermost ) {
2507 dirruns = dirrunsUnique;
2508 }
2509 }
2510
2511 // Track unmatched elements for set filters
2512 if ( bySet ) {
2513 // They will have gone through all possible matchers
2514 if ( (elem = !matcher && elem) ) {
2515 matchedCount--;
2516 }
2517
2518 // Lengthen the array for every element, matched or not
2519 if ( seed ) {
2520 unmatched.push( elem );
2521 }
2522 }
2523 }
2524
2525 matchedCount += i;
2526
2527 if ( bySet && i !== matchedCount ) {
2528 j = 0;
2529 while ( (matcher = setMatchers[j++]) ) {
2530 matcher( unmatched, setMatched, context, xml );
2531 }
2532
2533 if ( seed ) {
2534 // Reintegrate element matches to eliminate the need for sorting
2535 if ( matchedCount > 0 ) {
2536 while ( i-- ) {
2537 if ( !(unmatched[i] || setMatched[i]) ) {
2538 setMatched[i] = pop.call( results );
2539 }
2540 }
2541 }
2542
2543 // Discard index placeholder values to get only actual matches
2544 setMatched = condense( setMatched );
2545 }
2546
2547 // Add matches to results
2548 push.apply( results, setMatched );
2549
2550 // Seedless set matches succeeding multiple successful matchers stipulate sorting
2551 if ( outermost && !seed && setMatched.length > 0 &&
2552 ( matchedCount + setMatchers.length ) > 1 ) {
2553
2554 Sizzle.uniqueSort( results );
2555 }
2556 }
2557
2558 // Override manipulation of globals by nested matchers
2559 if ( outermost ) {
2560 dirruns = dirrunsUnique;
2561 outermostContext = contextBackup;
2562 }
2563
2564 return unmatched;
2565 };
2566
2567 return bySet ?
2568 markFunction( superMatcher ) :
2569 superMatcher;
2570}
2571
2572compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) {
2573 var i,
2574 setMatchers = [],
2575 elementMatchers = [],
2576 cached = compilerCache[ selector + " " ];
2577
2578 if ( !cached ) {
2579 // Generate a function of recursive functions that can be used to check each element
2580 if ( !match ) {
2581 match = tokenize( selector );
2582 }
2583 i = match.length;
2584 while ( i-- ) {
2585 cached = matcherFromTokens( match[i] );
2586 if ( cached[ expando ] ) {
2587 setMatchers.push( cached );
2588 } else {
2589 elementMatchers.push( cached );
2590 }
2591 }
2592
2593 // Cache the compiled function
2594 cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );
2595
2596 // Save selector and tokenization
2597 cached.selector = selector;
2598 }
2599 return cached;
2600};
2601
2602/**
2603 * A low-level selection function that works with Sizzle's compiled
2604 * selector functions
2605 * @param {String|Function} selector A selector or a pre-compiled
2606 * selector function built with Sizzle.compile
2607 * @param {Element} context
2608 * @param {Array} [results]
2609 * @param {Array} [seed] A set of elements to match against
2610 */
2611select = Sizzle.select = function( selector, context, results, seed ) {
2612 var i, tokens, token, type, find,
2613 compiled = typeof selector === "function" && selector,
2614 match = !seed && tokenize( (selector = compiled.selector || selector) );
2615
2616 results = results || [];
2617
2618 // Try to minimize operations if there is only one selector in the list and no seed
2619 // (the latter of which guarantees us context)
2620 if ( match.length === 1 ) {
2621
2622 // Reduce context if the leading compound selector is an ID
2623 tokens = match[0] = match[0].slice( 0 );
2624 if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&
2625 support.getById && context.nodeType === 9 && documentIsHTML &&
2626 Expr.relative[ tokens[1].type ] ) {
2627
2628 context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];
2629 if ( !context ) {
2630 return results;
2631
2632 // Precompiled matchers will still verify ancestry, so step up a level
2633 } else if ( compiled ) {
2634 context = context.parentNode;
2635 }
2636
2637 selector = selector.slice( tokens.shift().value.length );
2638 }
2639
2640 // Fetch a seed set for right-to-left matching
2641 i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length;
2642 while ( i-- ) {
2643 token = tokens[i];
2644
2645 // Abort if we hit a combinator
2646 if ( Expr.relative[ (type = token.type) ] ) {
2647 break;
2648 }
2649 if ( (find = Expr.find[ type ]) ) {
2650 // Search, expanding context for leading sibling combinators
2651 if ( (seed = find(
2652 token.matches[0].replace( runescape, funescape ),
2653 rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context
2654 )) ) {
2655
2656 // If seed is empty or no tokens remain, we can return early
2657 tokens.splice( i, 1 );
2658 selector = seed.length && toSelector( tokens );
2659 if ( !selector ) {
2660 push.apply( results, seed );
2661 return results;
2662 }
2663
2664 break;
2665 }
2666 }
2667 }
2668 }
2669
2670 // Compile and execute a filtering function if one is not provided
2671 ( compiled || compile( selector, match ) )(
2672 seed,
2673 context,
2674 !documentIsHTML,
2675 results,
2676 !context || rsibling.test( selector ) && testContext( context.parentNode ) || context
2677 );
2678 return results;
2679};
2680
2681// One-time assignments
2682
2683// Sort stability
2684support.sortStable = expando.split("").sort( sortOrder ).join("") === expando;
2685
2686// Support: Chrome 14-35+
2687// Always assume duplicates if they aren't passed to the comparison function
2688support.detectDuplicates = !!hasDuplicate;
2689
2690// Initialize against the default document
2691setDocument();
2692
2693// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)
2694// Detached nodes confoundingly follow *each other*
2695support.sortDetached = assert(function( div1 ) {
2696 // Should return 1, but returns 4 (following)
2697 return div1.compareDocumentPosition( document.createElement("div") ) & 1;
2698});
2699
2700// Support: IE<8
2701// Prevent attribute/property "interpolation"
2702// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
2703if ( !assert(function( div ) {
2704 div.innerHTML = "<a href='#'></a>";
2705 return div.firstChild.getAttribute("href") === "#" ;
2706}) ) {
2707 addHandle( "type|href|height|width", function( elem, name, isXML ) {
2708 if ( !isXML ) {
2709 return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 );
2710 }
2711 });
2712}
2713
2714// Support: IE<9
2715// Use defaultValue in place of getAttribute("value")
2716if ( !support.attributes || !assert(function( div ) {
2717 div.innerHTML = "<input/>";
2718 div.firstChild.setAttribute( "value", "" );
2719 return div.firstChild.getAttribute( "value" ) === "";
2720}) ) {
2721 addHandle( "value", function( elem, name, isXML ) {
2722 if ( !isXML && elem.nodeName.toLowerCase() === "input" ) {
2723 return elem.defaultValue;
2724 }
2725 });
2726}
2727
2728// Support: IE<9
2729// Use getAttributeNode to fetch booleans when getAttribute lies
2730if ( !assert(function( div ) {
2731 return div.getAttribute("disabled") == null;
2732}) ) {
2733 addHandle( booleans, function( elem, name, isXML ) {
2734 var val;
2735 if ( !isXML ) {
2736 return elem[ name ] === true ? name.toLowerCase() :
2737 (val = elem.getAttributeNode( name )) && val.specified ?
2738 val.value :
2739 null;
2740 }
2741 });
2742}
2743
2744return Sizzle;
2745
2746})( window );
2747
2748
2749
2750jQuery.find = Sizzle;
2751jQuery.expr = Sizzle.selectors;
2752jQuery.expr[ ":" ] = jQuery.expr.pseudos;
2753jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort;
2754jQuery.text = Sizzle.getText;
2755jQuery.isXMLDoc = Sizzle.isXML;
2756jQuery.contains = Sizzle.contains;
2757
2758
2759
2760var dir = function( elem, dir, until ) {
2761 var matched = [],
2762 truncate = until !== undefined;
2763
2764 while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) {
2765 if ( elem.nodeType === 1 ) {
2766 if ( truncate && jQuery( elem ).is( until ) ) {
2767 break;
2768 }
2769 matched.push( elem );
2770 }
2771 }
2772 return matched;
2773};
2774
2775
2776var siblings = function( n, elem ) {
2777 var matched = [];
2778
2779 for ( ; n; n = n.nextSibling ) {
2780 if ( n.nodeType === 1 && n !== elem ) {
2781 matched.push( n );
2782 }
2783 }
2784
2785 return matched;
2786};
2787
2788
2789var rneedsContext = jQuery.expr.match.needsContext;
2790
2791var rsingleTag = ( /^<([\w-]+)\s*\/?>(?:<\/\1>|)$/ );
2792
2793
2794
2795var risSimple = /^.[^:#\[\.,]*$/;
2796
2797// Implement the identical functionality for filter and not
2798function winnow( elements, qualifier, not ) {
2799 if ( jQuery.isFunction( qualifier ) ) {
2800 return jQuery.grep( elements, function( elem, i ) {
2801 /* jshint -W018 */
2802 return !!qualifier.call( elem, i, elem ) !== not;
2803 } );
2804
2805 }
2806
2807 if ( qualifier.nodeType ) {
2808 return jQuery.grep( elements, function( elem ) {
2809 return ( elem === qualifier ) !== not;
2810 } );
2811
2812 }
2813
2814 if ( typeof qualifier === "string" ) {
2815 if ( risSimple.test( qualifier ) ) {
2816 return jQuery.filter( qualifier, elements, not );
2817 }
2818
2819 qualifier = jQuery.filter( qualifier, elements );
2820 }
2821
2822 return jQuery.grep( elements, function( elem ) {
2823 return ( indexOf.call( qualifier, elem ) > -1 ) !== not;
2824 } );
2825}
2826
2827jQuery.filter = function( expr, elems, not ) {
2828 var elem = elems[ 0 ];
2829
2830 if ( not ) {
2831 expr = ":not(" + expr + ")";
2832 }
2833
2834 return elems.length === 1 && elem.nodeType === 1 ?
2835 jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] :
2836 jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) {
2837 return elem.nodeType === 1;
2838 } ) );
2839};
2840
2841jQuery.fn.extend( {
2842 find: function( selector ) {
2843 var i,
2844 len = this.length,
2845 ret = [],
2846 self = this;
2847
2848 if ( typeof selector !== "string" ) {
2849 return this.pushStack( jQuery( selector ).filter( function() {
2850 for ( i = 0; i < len; i++ ) {
2851 if ( jQuery.contains( self[ i ], this ) ) {
2852 return true;
2853 }
2854 }
2855 } ) );
2856 }
2857
2858 for ( i = 0; i < len; i++ ) {
2859 jQuery.find( selector, self[ i ], ret );
2860 }
2861
2862 // Needed because $( selector, context ) becomes $( context ).find( selector )
2863 ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret );
2864 ret.selector = this.selector ? this.selector + " " + selector : selector;
2865 return ret;
2866 },
2867 filter: function( selector ) {
2868 return this.pushStack( winnow( this, selector || [], false ) );
2869 },
2870 not: function( selector ) {
2871 return this.pushStack( winnow( this, selector || [], true ) );
2872 },
2873 is: function( selector ) {
2874 return !!winnow(
2875 this,
2876
2877 // If this is a positional/relative selector, check membership in the returned set
2878 // so $("p:first").is("p:last") won't return true for a doc with two "p".
2879 typeof selector === "string" && rneedsContext.test( selector ) ?
2880 jQuery( selector ) :
2881 selector || [],
2882 false
2883 ).length;
2884 }
2885} );
2886
2887
2888// Initialize a jQuery object
2889
2890
2891// A central reference to the root jQuery(document)
2892var rootjQuery,
2893
2894 // A simple way to check for HTML strings
2895 // Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
2896 // Strict HTML recognition (#11290: must start with <)
2897 rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,
2898
2899 init = jQuery.fn.init = function( selector, context, root ) {
2900 var match, elem;
2901
2902 // HANDLE: $(""), $(null), $(undefined), $(false)
2903 if ( !selector ) {
2904 return this;
2905 }
2906
2907 // Method init() accepts an alternate rootjQuery
2908 // so migrate can support jQuery.sub (gh-2101)
2909 root = root || rootjQuery;
2910
2911 // Handle HTML strings
2912 if ( typeof selector === "string" ) {
2913 if ( selector[ 0 ] === "<" &&
2914 selector[ selector.length - 1 ] === ">" &&
2915 selector.length >= 3 ) {
2916
2917 // Assume that strings that start and end with <> are HTML and skip the regex check
2918 match = [ null, selector, null ];
2919
2920 } else {
2921 match = rquickExpr.exec( selector );
2922 }
2923
2924 // Match html or make sure no context is specified for #id
2925 if ( match && ( match[ 1 ] || !context ) ) {
2926
2927 // HANDLE: $(html) -> $(array)
2928 if ( match[ 1 ] ) {
2929 context = context instanceof jQuery ? context[ 0 ] : context;
2930
2931 // Option to run scripts is true for back-compat
2932 // Intentionally let the error be thrown if parseHTML is not present
2933 jQuery.merge( this, jQuery.parseHTML(
2934 match[ 1 ],
2935 context && context.nodeType ? context.ownerDocument || context : document,
2936 true
2937 ) );
2938
2939 // HANDLE: $(html, props)
2940 if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) {
2941 for ( match in context ) {
2942
2943 // Properties of context are called as methods if possible
2944 if ( jQuery.isFunction( this[ match ] ) ) {
2945 this[ match ]( context[ match ] );
2946
2947 // ...and otherwise set as attributes
2948 } else {
2949 this.attr( match, context[ match ] );
2950 }
2951 }
2952 }
2953
2954 return this;
2955
2956 // HANDLE: $(#id)
2957 } else {
2958 elem = document.getElementById( match[ 2 ] );
2959
2960 // Support: Blackberry 4.6
2961 // gEBID returns nodes no longer in the document (#6963)
2962 if ( elem && elem.parentNode ) {
2963
2964 // Inject the element directly into the jQuery object
2965 this.length = 1;
2966 this[ 0 ] = elem;
2967 }
2968
2969 this.context = document;
2970 this.selector = selector;
2971 return this;
2972 }
2973
2974 // HANDLE: $(expr, $(...))
2975 } else if ( !context || context.jquery ) {
2976 return ( context || root ).find( selector );
2977
2978 // HANDLE: $(expr, context)
2979 // (which is just equivalent to: $(context).find(expr)
2980 } else {
2981 return this.constructor( context ).find( selector );
2982 }
2983
2984 // HANDLE: $(DOMElement)
2985 } else if ( selector.nodeType ) {
2986 this.context = this[ 0 ] = selector;
2987 this.length = 1;
2988 return this;
2989
2990 // HANDLE: $(function)
2991 // Shortcut for document ready
2992 } else if ( jQuery.isFunction( selector ) ) {
2993 return root.ready !== undefined ?
2994 root.ready( selector ) :
2995
2996 // Execute immediately if ready is not present
2997 selector( jQuery );
2998 }
2999
3000 if ( selector.selector !== undefined ) {
3001 this.selector = selector.selector;
3002 this.context = selector.context;
3003 }
3004
3005 return jQuery.makeArray( selector, this );
3006 };
3007
3008// Give the init function the jQuery prototype for later instantiation
3009init.prototype = jQuery.fn;
3010
3011// Initialize central reference
3012rootjQuery = jQuery( document );
3013
3014
3015var rparentsprev = /^(?:parents|prev(?:Until|All))/,
3016
3017 // Methods guaranteed to produce a unique set when starting from a unique set
3018 guaranteedUnique = {
3019 children: true,
3020 contents: true,
3021 next: true,
3022 prev: true
3023 };
3024
3025jQuery.fn.extend( {
3026 has: function( target ) {
3027 var targets = jQuery( target, this ),
3028 l = targets.length;
3029
3030 return this.filter( function() {
3031 var i = 0;
3032 for ( ; i < l; i++ ) {
3033 if ( jQuery.contains( this, targets[ i ] ) ) {
3034 return true;
3035 }
3036 }
3037 } );
3038 },
3039
3040 closest: function( selectors, context ) {
3041 var cur,
3042 i = 0,
3043 l = this.length,
3044 matched = [],
3045 pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ?
3046 jQuery( selectors, context || this.context ) :
3047 0;
3048
3049 for ( ; i < l; i++ ) {
3050 for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) {
3051
3052 // Always skip document fragments
3053 if ( cur.nodeType < 11 && ( pos ?
3054 pos.index( cur ) > -1 :
3055
3056 // Don't pass non-elements to Sizzle
3057 cur.nodeType === 1 &&
3058 jQuery.find.matchesSelector( cur, selectors ) ) ) {
3059
3060 matched.push( cur );
3061 break;
3062 }
3063 }
3064 }
3065
3066 return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched );
3067 },
3068
3069 // Determine the position of an element within the set
3070 index: function( elem ) {
3071
3072 // No argument, return index in parent
3073 if ( !elem ) {
3074 return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1;
3075 }
3076
3077 // Index in selector
3078 if ( typeof elem === "string" ) {
3079 return indexOf.call( jQuery( elem ), this[ 0 ] );
3080 }
3081
3082 // Locate the position of the desired element
3083 return indexOf.call( this,
3084
3085 // If it receives a jQuery object, the first element is used
3086 elem.jquery ? elem[ 0 ] : elem
3087 );
3088 },
3089
3090 add: function( selector, context ) {
3091 return this.pushStack(
3092 jQuery.uniqueSort(
3093 jQuery.merge( this.get(), jQuery( selector, context ) )
3094 )
3095 );
3096 },
3097
3098 addBack: function( selector ) {
3099 return this.add( selector == null ?
3100 this.prevObject : this.prevObject.filter( selector )
3101 );
3102 }
3103} );
3104
3105function sibling( cur, dir ) {
3106 while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {}
3107 return cur;
3108}
3109
3110jQuery.each( {
3111 parent: function( elem ) {
3112 var parent = elem.parentNode;
3113 return parent && parent.nodeType !== 11 ? parent : null;
3114 },
3115 parents: function( elem ) {
3116 return dir( elem, "parentNode" );
3117 },
3118 parentsUntil: function( elem, i, until ) {
3119 return dir( elem, "parentNode", until );
3120 },
3121 next: function( elem ) {
3122 return sibling( elem, "nextSibling" );
3123 },
3124 prev: function( elem ) {
3125 return sibling( elem, "previousSibling" );
3126 },
3127 nextAll: function( elem ) {
3128 return dir( elem, "nextSibling" );
3129 },
3130 prevAll: function( elem ) {
3131 return dir( elem, "previousSibling" );
3132 },
3133 nextUntil: function( elem, i, until ) {
3134 return dir( elem, "nextSibling", until );
3135 },
3136 prevUntil: function( elem, i, until ) {
3137 return dir( elem, "previousSibling", until );
3138 },
3139 siblings: function( elem ) {
3140 return siblings( ( elem.parentNode || {} ).firstChild, elem );
3141 },
3142 children: function( elem ) {
3143 return siblings( elem.firstChild );
3144 },
3145 contents: function( elem ) {
3146 return elem.contentDocument || jQuery.merge( [], elem.childNodes );
3147 }
3148}, function( name, fn ) {
3149 jQuery.fn[ name ] = function( until, selector ) {
3150 var matched = jQuery.map( this, fn, until );
3151
3152 if ( name.slice( -5 ) !== "Until" ) {
3153 selector = until;
3154 }
3155
3156 if ( selector && typeof selector === "string" ) {
3157 matched = jQuery.filter( selector, matched );
3158 }
3159
3160 if ( this.length > 1 ) {
3161
3162 // Remove duplicates
3163 if ( !guaranteedUnique[ name ] ) {
3164 jQuery.uniqueSort( matched );
3165 }
3166
3167 // Reverse order for parents* and prev-derivatives
3168 if ( rparentsprev.test( name ) ) {
3169 matched.reverse();
3170 }
3171 }
3172
3173 return this.pushStack( matched );
3174 };
3175} );
3176var rnotwhite = ( /\S+/g );
3177
3178
3179
3180// Convert String-formatted options into Object-formatted ones
3181function createOptions( options ) {
3182 var object = {};
3183 jQuery.each( options.match( rnotwhite ) || [], function( _, flag ) {
3184 object[ flag ] = true;
3185 } );
3186 return object;
3187}
3188
3189/*
3190 * Create a callback list using the following parameters:
3191 *
3192 * options: an optional list of space-separated options that will change how
3193 * the callback list behaves or a more traditional option object
3194 *
3195 * By default a callback list will act like an event callback list and can be
3196 * "fired" multiple times.
3197 *
3198 * Possible options:
3199 *
3200 * once: will ensure the callback list can only be fired once (like a Deferred)
3201 *
3202 * memory: will keep track of previous values and will call any callback added
3203 * after the list has been fired right away with the latest "memorized"
3204 * values (like a Deferred)
3205 *
3206 * unique: will ensure a callback can only be added once (no duplicate in the list)
3207 *
3208 * stopOnFalse: interrupt callings when a callback returns false
3209 *
3210 */
3211jQuery.Callbacks = function( options ) {
3212
3213 // Convert options from String-formatted to Object-formatted if needed
3214 // (we check in cache first)
3215 options = typeof options === "string" ?
3216 createOptions( options ) :
3217 jQuery.extend( {}, options );
3218
3219 var // Flag to know if list is currently firing
3220 firing,
3221
3222 // Last fire value for non-forgettable lists
3223 memory,
3224
3225 // Flag to know if list was already fired
3226 fired,
3227
3228 // Flag to prevent firing
3229 locked,
3230
3231 // Actual callback list
3232 list = [],
3233
3234 // Queue of execution data for repeatable lists
3235 queue = [],
3236
3237 // Index of currently firing callback (modified by add/remove as needed)
3238 firingIndex = -1,
3239
3240 // Fire callbacks
3241 fire = function() {
3242
3243 // Enforce single-firing
3244 locked = options.once;
3245
3246 // Execute callbacks for all pending executions,
3247 // respecting firingIndex overrides and runtime changes
3248 fired = firing = true;
3249 for ( ; queue.length; firingIndex = -1 ) {
3250 memory = queue.shift();
3251 while ( ++firingIndex < list.length ) {
3252
3253 // Run callback and check for early termination
3254 if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false &&
3255 options.stopOnFalse ) {
3256
3257 // Jump to end and forget the data so .add doesn't re-fire
3258 firingIndex = list.length;
3259 memory = false;
3260 }
3261 }
3262 }
3263
3264 // Forget the data if we're done with it
3265 if ( !options.memory ) {
3266 memory = false;
3267 }
3268
3269 firing = false;
3270
3271 // Clean up if we're done firing for good
3272 if ( locked ) {
3273
3274 // Keep an empty list if we have data for future add calls
3275 if ( memory ) {
3276 list = [];
3277
3278 // Otherwise, this object is spent
3279 } else {
3280 list = "";
3281 }
3282 }
3283 },
3284
3285 // Actual Callbacks object
3286 self = {
3287
3288 // Add a callback or a collection of callbacks to the list
3289 add: function() {
3290 if ( list ) {
3291
3292 // If we have memory from a past run, we should fire after adding
3293 if ( memory && !firing ) {
3294 firingIndex = list.length - 1;
3295 queue.push( memory );
3296 }
3297
3298 ( function add( args ) {
3299 jQuery.each( args, function( _, arg ) {
3300 if ( jQuery.isFunction( arg ) ) {
3301 if ( !options.unique || !self.has( arg ) ) {
3302 list.push( arg );
3303 }
3304 } else if ( arg && arg.length && jQuery.type( arg ) !== "string" ) {
3305
3306 // Inspect recursively
3307 add( arg );
3308 }
3309 } );
3310 } )( arguments );
3311
3312 if ( memory && !firing ) {
3313 fire();
3314 }
3315 }
3316 return this;
3317 },
3318
3319 // Remove a callback from the list
3320 remove: function() {
3321 jQuery.each( arguments, function( _, arg ) {
3322 var index;
3323 while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
3324 list.splice( index, 1 );
3325
3326 // Handle firing indexes
3327 if ( index <= firingIndex ) {
3328 firingIndex--;
3329 }
3330 }
3331 } );
3332 return this;
3333 },
3334
3335 // Check if a given callback is in the list.
3336 // If no argument is given, return whether or not list has callbacks attached.
3337 has: function( fn ) {
3338 return fn ?
3339 jQuery.inArray( fn, list ) > -1 :
3340 list.length > 0;
3341 },
3342
3343 // Remove all callbacks from the list
3344 empty: function() {
3345 if ( list ) {
3346 list = [];
3347 }
3348 return this;
3349 },
3350
3351 // Disable .fire and .add
3352 // Abort any current/pending executions
3353 // Clear all callbacks and values
3354 disable: function() {
3355 locked = queue = [];
3356 list = memory = "";
3357 return this;
3358 },
3359 disabled: function() {
3360 return !list;
3361 },
3362
3363 // Disable .fire
3364 // Also disable .add unless we have memory (since it would have no effect)
3365 // Abort any pending executions
3366 lock: function() {
3367 locked = queue = [];
3368 if ( !memory ) {
3369 list = memory = "";
3370 }
3371 return this;
3372 },
3373 locked: function() {
3374 return !!locked;
3375 },
3376
3377 // Call all callbacks with the given context and arguments
3378 fireWith: function( context, args ) {
3379 if ( !locked ) {
3380 args = args || [];
3381 args = [ context, args.slice ? args.slice() : args ];
3382 queue.push( args );
3383 if ( !firing ) {
3384 fire();
3385 }
3386 }
3387 return this;
3388 },
3389
3390 // Call all the callbacks with the given arguments
3391 fire: function() {
3392 self.fireWith( this, arguments );
3393 return this;
3394 },
3395
3396 // To know if the callbacks have already been called at least once
3397 fired: function() {
3398 return !!fired;
3399 }
3400 };
3401
3402 return self;
3403};
3404
3405
3406jQuery.extend( {
3407
3408 Deferred: function( func ) {
3409 var tuples = [
3410
3411 // action, add listener, listener list, final state
3412 [ "resolve", "done", jQuery.Callbacks( "once memory" ), "resolved" ],
3413 [ "reject", "fail", jQuery.Callbacks( "once memory" ), "rejected" ],
3414 [ "notify", "progress", jQuery.Callbacks( "memory" ) ]
3415 ],
3416 state = "pending",
3417 promise = {
3418 state: function() {
3419 return state;
3420 },
3421 always: function() {
3422 deferred.done( arguments ).fail( arguments );
3423 return this;
3424 },
3425 then: function( /* fnDone, fnFail, fnProgress */ ) {
3426 var fns = arguments;
3427 return jQuery.Deferred( function( newDefer ) {
3428 jQuery.each( tuples, function( i, tuple ) {
3429 var fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];
3430
3431 // deferred[ done | fail | progress ] for forwarding actions to newDefer
3432 deferred[ tuple[ 1 ] ]( function() {
3433 var returned = fn && fn.apply( this, arguments );
3434 if ( returned && jQuery.isFunction( returned.promise ) ) {
3435 returned.promise()
3436 .progress( newDefer.notify )
3437 .done( newDefer.resolve )
3438 .fail( newDefer.reject );
3439 } else {
3440 newDefer[ tuple[ 0 ] + "With" ](
3441 this === promise ? newDefer.promise() : this,
3442 fn ? [ returned ] : arguments
3443 );
3444 }
3445 } );
3446 } );
3447 fns = null;
3448 } ).promise();
3449 },
3450
3451 // Get a promise for this deferred
3452 // If obj is provided, the promise aspect is added to the object
3453 promise: function( obj ) {
3454 return obj != null ? jQuery.extend( obj, promise ) : promise;
3455 }
3456 },
3457 deferred = {};
3458
3459 // Keep pipe for back-compat
3460 promise.pipe = promise.then;
3461
3462 // Add list-specific methods
3463 jQuery.each( tuples, function( i, tuple ) {
3464 var list = tuple[ 2 ],
3465 stateString = tuple[ 3 ];
3466
3467 // promise[ done | fail | progress ] = list.add
3468 promise[ tuple[ 1 ] ] = list.add;
3469
3470 // Handle state
3471 if ( stateString ) {
3472 list.add( function() {
3473
3474 // state = [ resolved | rejected ]
3475 state = stateString;
3476
3477 // [ reject_list | resolve_list ].disable; progress_list.lock
3478 }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );
3479 }
3480
3481 // deferred[ resolve | reject | notify ]
3482 deferred[ tuple[ 0 ] ] = function() {
3483 deferred[ tuple[ 0 ] + "With" ]( this === deferred ? promise : this, arguments );
3484 return this;
3485 };
3486 deferred[ tuple[ 0 ] + "With" ] = list.fireWith;
3487 } );
3488
3489 // Make the deferred a promise
3490 promise.promise( deferred );
3491
3492 // Call given func if any
3493 if ( func ) {
3494 func.call( deferred, deferred );
3495 }
3496
3497 // All done!
3498 return deferred;
3499 },
3500
3501 // Deferred helper
3502 when: function( subordinate /* , ..., subordinateN */ ) {
3503 var i = 0,
3504 resolveValues = slice.call( arguments ),
3505 length = resolveValues.length,
3506
3507 // the count of uncompleted subordinates
3508 remaining = length !== 1 ||
3509 ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,
3510
3511 // the master Deferred.
3512 // If resolveValues consist of only a single Deferred, just use that.
3513 deferred = remaining === 1 ? subordinate : jQuery.Deferred(),
3514
3515 // Update function for both resolve and progress values
3516 updateFunc = function( i, contexts, values ) {
3517 return function( value ) {
3518 contexts[ i ] = this;
3519 values[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;
3520 if ( values === progressValues ) {
3521 deferred.notifyWith( contexts, values );
3522 } else if ( !( --remaining ) ) {
3523 deferred.resolveWith( contexts, values );
3524 }
3525 };
3526 },
3527
3528 progressValues, progressContexts, resolveContexts;
3529
3530 // Add listeners to Deferred subordinates; treat others as resolved
3531 if ( length > 1 ) {
3532 progressValues = new Array( length );
3533 progressContexts = new Array( length );
3534 resolveContexts = new Array( length );
3535 for ( ; i < length; i++ ) {
3536 if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {
3537 resolveValues[ i ].promise()
3538 .progress( updateFunc( i, progressContexts, progressValues ) )
3539 .done( updateFunc( i, resolveContexts, resolveValues ) )
3540 .fail( deferred.reject );
3541 } else {
3542 --remaining;
3543 }
3544 }
3545 }
3546
3547 // If we're not waiting on anything, resolve the master
3548 if ( !remaining ) {
3549 deferred.resolveWith( resolveContexts, resolveValues );
3550 }
3551
3552 return deferred.promise();
3553 }
3554} );
3555
3556
3557// The deferred used on DOM ready
3558var readyList;
3559
3560jQuery.fn.ready = function( fn ) {
3561
3562 // Add the callback
3563 jQuery.ready.promise().done( fn );
3564
3565 return this;
3566};
3567
3568jQuery.extend( {
3569
3570 // Is the DOM ready to be used? Set to true once it occurs.
3571 isReady: false,
3572
3573 // A counter to track how many items to wait for before
3574 // the ready event fires. See #6781
3575 readyWait: 1,
3576
3577 // Hold (or release) the ready event
3578 holdReady: function( hold ) {
3579 if ( hold ) {
3580 jQuery.readyWait++;
3581 } else {
3582 jQuery.ready( true );
3583 }
3584 },
3585
3586 // Handle when the DOM is ready
3587 ready: function( wait ) {
3588
3589 // Abort if there are pending holds or we're already ready
3590 if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
3591 return;
3592 }
3593
3594 // Remember that the DOM is ready
3595 jQuery.isReady = true;
3596
3597 // If a normal DOM Ready event fired, decrement, and wait if need be
3598 if ( wait !== true && --jQuery.readyWait > 0 ) {
3599 return;
3600 }
3601
3602 // If there are functions bound, to execute
3603 readyList.resolveWith( document, [ jQuery ] );
3604
3605 // Trigger any bound ready events
3606 if ( jQuery.fn.triggerHandler ) {
3607 jQuery( document ).triggerHandler( "ready" );
3608 jQuery( document ).off( "ready" );
3609 }
3610 }
3611} );
3612
3613/**
3614 * The ready event handler and self cleanup method
3615 */
3616function completed() {
3617 document.removeEventListener( "DOMContentLoaded", completed );
3618 window.removeEventListener( "load", completed );
3619 jQuery.ready();
3620}
3621
3622jQuery.ready.promise = function( obj ) {
3623 if ( !readyList ) {
3624
3625 readyList = jQuery.Deferred();
3626
3627 // Catch cases where $(document).ready() is called
3628 // after the browser event has already occurred.
3629 // Support: IE9-10 only
3630 // Older IE sometimes signals "interactive" too soon
3631 if ( document.readyState === "complete" ||
3632 ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) {
3633
3634 // Handle it asynchronously to allow scripts the opportunity to delay ready
3635 window.setTimeout( jQuery.ready );
3636
3637 } else {
3638
3639 // Use the handy event callback
3640 document.addEventListener( "DOMContentLoaded", completed );
3641
3642 // A fallback to window.onload, that will always work
3643 window.addEventListener( "load", completed );
3644 }
3645 }
3646 return readyList.promise( obj );
3647};
3648
3649// Kick off the DOM ready check even if the user does not
3650jQuery.ready.promise();
3651
3652
3653
3654
3655// Multifunctional method to get and set values of a collection
3656// The value/s can optionally be executed if it's a function
3657var access = function( elems, fn, key, value, chainable, emptyGet, raw ) {
3658 var i = 0,
3659 len = elems.length,
3660 bulk = key == null;
3661
3662 // Sets many values
3663 if ( jQuery.type( key ) === "object" ) {
3664 chainable = true;
3665 for ( i in key ) {
3666 access( elems, fn, i, key[ i ], true, emptyGet, raw );
3667 }
3668
3669 // Sets one value
3670 } else if ( value !== undefined ) {
3671 chainable = true;
3672
3673 if ( !jQuery.isFunction( value ) ) {
3674 raw = true;
3675 }
3676
3677 if ( bulk ) {
3678
3679 // Bulk operations run against the entire set
3680 if ( raw ) {
3681 fn.call( elems, value );
3682 fn = null;
3683
3684 // ...except when executing function values
3685 } else {
3686 bulk = fn;
3687 fn = function( elem, key, value ) {
3688 return bulk.call( jQuery( elem ), value );
3689 };
3690 }
3691 }
3692
3693 if ( fn ) {
3694 for ( ; i < len; i++ ) {
3695 fn(
3696 elems[ i ], key, raw ?
3697 value :
3698 value.call( elems[ i ], i, fn( elems[ i ], key ) )
3699 );
3700 }
3701 }
3702 }
3703
3704 return chainable ?
3705 elems :
3706
3707 // Gets
3708 bulk ?
3709 fn.call( elems ) :
3710 len ? fn( elems[ 0 ], key ) : emptyGet;
3711};
3712var acceptData = function( owner ) {
3713
3714 // Accepts only:
3715 // - Node
3716 // - Node.ELEMENT_NODE
3717 // - Node.DOCUMENT_NODE
3718 // - Object
3719 // - Any
3720 /* jshint -W018 */
3721 return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType );
3722};
3723
3724
3725
3726
3727function Data() {
3728 this.expando = jQuery.expando + Data.uid++;
3729}
3730
3731Data.uid = 1;
3732
3733Data.prototype = {
3734
3735 register: function( owner, initial ) {
3736 var value = initial || {};
3737
3738 // If it is a node unlikely to be stringify-ed or looped over
3739 // use plain assignment
3740 if ( owner.nodeType ) {
3741 owner[ this.expando ] = value;
3742
3743 // Otherwise secure it in a non-enumerable, non-writable property
3744 // configurability must be true to allow the property to be
3745 // deleted with the delete operator
3746 } else {
3747 Object.defineProperty( owner, this.expando, {
3748 value: value,
3749 writable: true,
3750 configurable: true
3751 } );
3752 }
3753 return owner[ this.expando ];
3754 },
3755 cache: function( owner ) {
3756
3757 // We can accept data for non-element nodes in modern browsers,
3758 // but we should not, see #8335.
3759 // Always return an empty object.
3760 if ( !acceptData( owner ) ) {
3761 return {};
3762 }
3763
3764 // Check if the owner object already has a cache
3765 var value = owner[ this.expando ];
3766
3767 // If not, create one
3768 if ( !value ) {
3769 value = {};
3770
3771 // We can accept data for non-element nodes in modern browsers,
3772 // but we should not, see #8335.
3773 // Always return an empty object.
3774 if ( acceptData( owner ) ) {
3775
3776 // If it is a node unlikely to be stringify-ed or looped over
3777 // use plain assignment
3778 if ( owner.nodeType ) {
3779 owner[ this.expando ] = value;
3780
3781 // Otherwise secure it in a non-enumerable property
3782 // configurable must be true to allow the property to be
3783 // deleted when data is removed
3784 } else {
3785 Object.defineProperty( owner, this.expando, {
3786 value: value,
3787 configurable: true
3788 } );
3789 }
3790 }
3791 }
3792
3793 return value;
3794 },
3795 set: function( owner, data, value ) {
3796 var prop,
3797 cache = this.cache( owner );
3798
3799 // Handle: [ owner, key, value ] args
3800 if ( typeof data === "string" ) {
3801 cache[ data ] = value;
3802
3803 // Handle: [ owner, { properties } ] args
3804 } else {
3805
3806 // Copy the properties one-by-one to the cache object
3807 for ( prop in data ) {
3808 cache[ prop ] = data[ prop ];
3809 }
3810 }
3811 return cache;
3812 },
3813 get: function( owner, key ) {
3814 return key === undefined ?
3815 this.cache( owner ) :
3816 owner[ this.expando ] && owner[ this.expando ][ key ];
3817 },
3818 access: function( owner, key, value ) {
3819 var stored;
3820
3821 // In cases where either:
3822 //
3823 // 1. No key was specified
3824 // 2. A string key was specified, but no value provided
3825 //
3826 // Take the "read" path and allow the get method to determine
3827 // which value to return, respectively either:
3828 //
3829 // 1. The entire cache object
3830 // 2. The data stored at the key
3831 //
3832 if ( key === undefined ||
3833 ( ( key && typeof key === "string" ) && value === undefined ) ) {
3834
3835 stored = this.get( owner, key );
3836
3837 return stored !== undefined ?
3838 stored : this.get( owner, jQuery.camelCase( key ) );
3839 }
3840
3841 // When the key is not a string, or both a key and value
3842 // are specified, set or extend (existing objects) with either:
3843 //
3844 // 1. An object of properties
3845 // 2. A key and value
3846 //
3847 this.set( owner, key, value );
3848
3849 // Since the "set" path can have two possible entry points
3850 // return the expected data based on which path was taken[*]
3851 return value !== undefined ? value : key;
3852 },
3853 remove: function( owner, key ) {
3854 var i, name, camel,
3855 cache = owner[ this.expando ];
3856
3857 if ( cache === undefined ) {
3858 return;
3859 }
3860
3861 if ( key === undefined ) {
3862 this.register( owner );
3863
3864 } else {
3865
3866 // Support array or space separated string of keys
3867 if ( jQuery.isArray( key ) ) {
3868
3869 // If "name" is an array of keys...
3870 // When data is initially created, via ("key", "val") signature,
3871 // keys will be converted to camelCase.
3872 // Since there is no way to tell _how_ a key was added, remove
3873 // both plain key and camelCase key. #12786
3874 // This will only penalize the array argument path.
3875 name = key.concat( key.map( jQuery.camelCase ) );
3876 } else {
3877 camel = jQuery.camelCase( key );
3878
3879 // Try the string as a key before any manipulation
3880 if ( key in cache ) {
3881 name = [ key, camel ];
3882 } else {
3883
3884 // If a key with the spaces exists, use it.
3885 // Otherwise, create an array by matching non-whitespace
3886 name = camel;
3887 name = name in cache ?
3888 [ name ] : ( name.match( rnotwhite ) || [] );
3889 }
3890 }
3891
3892 i = name.length;
3893
3894 while ( i-- ) {
3895 delete cache[ name[ i ] ];
3896 }
3897 }
3898
3899 // Remove the expando if there's no more data
3900 if ( key === undefined || jQuery.isEmptyObject( cache ) ) {
3901
3902 // Support: Chrome <= 35-45+
3903 // Webkit & Blink performance suffers when deleting properties
3904 // from DOM nodes, so set to undefined instead
3905 // https://code.google.com/p/chromium/issues/detail?id=378607
3906 if ( owner.nodeType ) {
3907 owner[ this.expando ] = undefined;
3908 } else {
3909 delete owner[ this.expando ];
3910 }
3911 }
3912 },
3913 hasData: function( owner ) {
3914 var cache = owner[ this.expando ];
3915 return cache !== undefined && !jQuery.isEmptyObject( cache );
3916 }
3917};
3918var dataPriv = new Data();
3919
3920var dataUser = new Data();
3921
3922
3923
3924// Implementation Summary
3925//
3926// 1. Enforce API surface and semantic compatibility with 1.9.x branch
3927// 2. Improve the module's maintainability by reducing the storage
3928// paths to a single mechanism.
3929// 3. Use the same single mechanism to support "private" and "user" data.
3930// 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData)
3931// 5. Avoid exposing implementation details on user objects (eg. expando properties)
3932// 6. Provide a clear path for implementation upgrade to WeakMap in 2014
3933
3934var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,
3935 rmultiDash = /[A-Z]/g;
3936
3937function dataAttr( elem, key, data ) {
3938 var name;
3939
3940 // If nothing was found internally, try to fetch any
3941 // data from the HTML5 data-* attribute
3942 if ( data === undefined && elem.nodeType === 1 ) {
3943 name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase();
3944 data = elem.getAttribute( name );
3945
3946 if ( typeof data === "string" ) {
3947 try {
3948 data = data === "true" ? true :
3949 data === "false" ? false :
3950 data === "null" ? null :
3951
3952 // Only convert to a number if it doesn't change the string
3953 +data + "" === data ? +data :
3954 rbrace.test( data ) ? jQuery.parseJSON( data ) :
3955 data;
3956 } catch ( e ) {}
3957
3958 // Make sure we set the data so it isn't changed later
3959 dataUser.set( elem, key, data );
3960 } else {
3961 data = undefined;
3962 }
3963 }
3964 return data;
3965}
3966
3967jQuery.extend( {
3968 hasData: function( elem ) {
3969 return dataUser.hasData( elem ) || dataPriv.hasData( elem );
3970 },
3971
3972 data: function( elem, name, data ) {
3973 return dataUser.access( elem, name, data );
3974 },
3975
3976 removeData: function( elem, name ) {
3977 dataUser.remove( elem, name );
3978 },
3979
3980 // TODO: Now that all calls to _data and _removeData have been replaced
3981 // with direct calls to dataPriv methods, these can be deprecated.
3982 _data: function( elem, name, data ) {
3983 return dataPriv.access( elem, name, data );
3984 },
3985
3986 _removeData: function( elem, name ) {
3987 dataPriv.remove( elem, name );
3988 }
3989} );
3990
3991jQuery.fn.extend( {
3992 data: function( key, value ) {
3993 var i, name, data,
3994 elem = this[ 0 ],
3995 attrs = elem && elem.attributes;
3996
3997 // Gets all values
3998 if ( key === undefined ) {
3999 if ( this.length ) {
4000 data = dataUser.get( elem );
4001
4002 if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) {
4003 i = attrs.length;
4004 while ( i-- ) {
4005
4006 // Support: IE11+
4007 // The attrs elements can be null (#14894)
4008 if ( attrs[ i ] ) {
4009 name = attrs[ i ].name;
4010 if ( name.indexOf( "data-" ) === 0 ) {
4011 name = jQuery.camelCase( name.slice( 5 ) );
4012 dataAttr( elem, name, data[ name ] );
4013 }
4014 }
4015 }
4016 dataPriv.set( elem, "hasDataAttrs", true );
4017 }
4018 }
4019
4020 return data;
4021 }
4022
4023 // Sets multiple values
4024 if ( typeof key === "object" ) {
4025 return this.each( function() {
4026 dataUser.set( this, key );
4027 } );
4028 }
4029
4030 return access( this, function( value ) {
4031 var data, camelKey;
4032
4033 if ( elem && value === undefined ) {
4034
4035 // Attempt to get data from the cache
4036 // with the key as-is
4037 data = dataUser.get( elem, key ) ||
4038
4039 // Try to find dashed key if it exists (gh-2779)
4040 // This is for 2.2.x only
4041 dataUser.get( elem, key.replace( rmultiDash, "-$&" ).toLowerCase() );
4042
4043 if ( data !== undefined ) {
4044 return data;
4045 }
4046
4047 camelKey = jQuery.camelCase( key );
4048
4049 // Attempt to get data from the cache
4050 // with the key camelized
4051 data = dataUser.get( elem, camelKey );
4052 if ( data !== undefined ) {
4053 return data;
4054 }
4055
4056 // Attempt to "discover" the data in
4057 // HTML5 custom data-* attrs
4058 data = dataAttr( elem, camelKey, undefined );
4059 if ( data !== undefined ) {
4060 return data;
4061 }
4062
4063 // We tried really hard, but the data doesn't exist.
4064 return;
4065 }
4066
4067 // Set the data...
4068 camelKey = jQuery.camelCase( key );
4069 this.each( function() {
4070
4071 // First, attempt to store a copy or reference of any
4072 // data that might've been store with a camelCased key.
4073 var data = dataUser.get( this, camelKey );
4074
4075 // For HTML5 data-* attribute interop, we have to
4076 // store property names with dashes in a camelCase form.
4077 // This might not apply to all properties...*
4078 dataUser.set( this, camelKey, value );
4079
4080 // *... In the case of properties that might _actually_
4081 // have dashes, we need to also store a copy of that
4082 // unchanged property.
4083 if ( key.indexOf( "-" ) > -1 && data !== undefined ) {
4084 dataUser.set( this, key, value );
4085 }
4086 } );
4087 }, null, value, arguments.length > 1, null, true );
4088 },
4089
4090 removeData: function( key ) {
4091 return this.each( function() {
4092 dataUser.remove( this, key );
4093 } );
4094 }
4095} );
4096
4097
4098jQuery.extend( {
4099 queue: function( elem, type, data ) {
4100 var queue;
4101
4102 if ( elem ) {
4103 type = ( type || "fx" ) + "queue";
4104 queue = dataPriv.get( elem, type );
4105
4106 // Speed up dequeue by getting out quickly if this is just a lookup
4107 if ( data ) {
4108 if ( !queue || jQuery.isArray( data ) ) {
4109 queue = dataPriv.access( elem, type, jQuery.makeArray( data ) );
4110 } else {
4111 queue.push( data );
4112 }
4113 }
4114 return queue || [];
4115 }
4116 },
4117
4118 dequeue: function( elem, type ) {
4119 type = type || "fx";
4120
4121 var queue = jQuery.queue( elem, type ),
4122 startLength = queue.length,
4123 fn = queue.shift(),
4124 hooks = jQuery._queueHooks( elem, type ),
4125 next = function() {
4126 jQuery.dequeue( elem, type );
4127 };
4128
4129 // If the fx queue is dequeued, always remove the progress sentinel
4130 if ( fn === "inprogress" ) {
4131 fn = queue.shift();
4132 startLength--;
4133 }
4134
4135 if ( fn ) {
4136
4137 // Add a progress sentinel to prevent the fx queue from being
4138 // automatically dequeued
4139 if ( type === "fx" ) {
4140 queue.unshift( "inprogress" );
4141 }
4142
4143 // Clear up the last queue stop function
4144 delete hooks.stop;
4145 fn.call( elem, next, hooks );
4146 }
4147
4148 if ( !startLength && hooks ) {
4149 hooks.empty.fire();
4150 }
4151 },
4152
4153 // Not public - generate a queueHooks object, or return the current one
4154 _queueHooks: function( elem, type ) {
4155 var key = type + "queueHooks";
4156 return dataPriv.get( elem, key ) || dataPriv.access( elem, key, {
4157 empty: jQuery.Callbacks( "once memory" ).add( function() {
4158 dataPriv.remove( elem, [ type + "queue", key ] );
4159 } )
4160 } );
4161 }
4162} );
4163
4164jQuery.fn.extend( {
4165 queue: function( type, data ) {
4166 var setter = 2;
4167
4168 if ( typeof type !== "string" ) {
4169 data = type;
4170 type = "fx";
4171 setter--;
4172 }
4173
4174 if ( arguments.length < setter ) {
4175 return jQuery.queue( this[ 0 ], type );
4176 }
4177
4178 return data === undefined ?
4179 this :
4180 this.each( function() {
4181 var queue = jQuery.queue( this, type, data );
4182
4183 // Ensure a hooks for this queue
4184 jQuery._queueHooks( this, type );
4185
4186 if ( type === "fx" && queue[ 0 ] !== "inprogress" ) {
4187 jQuery.dequeue( this, type );
4188 }
4189 } );
4190 },
4191 dequeue: function( type ) {
4192 return this.each( function() {
4193 jQuery.dequeue( this, type );
4194 } );
4195 },
4196 clearQueue: function( type ) {
4197 return this.queue( type || "fx", [] );
4198 },
4199
4200 // Get a promise resolved when queues of a certain type
4201 // are emptied (fx is the type by default)
4202 promise: function( type, obj ) {
4203 var tmp,
4204 count = 1,
4205 defer = jQuery.Deferred(),
4206 elements = this,
4207 i = this.length,
4208 resolve = function() {
4209 if ( !( --count ) ) {
4210 defer.resolveWith( elements, [ elements ] );
4211 }
4212 };
4213
4214 if ( typeof type !== "string" ) {
4215 obj = type;
4216 type = undefined;
4217 }
4218 type = type || "fx";
4219
4220 while ( i-- ) {
4221 tmp = dataPriv.get( elements[ i ], type + "queueHooks" );
4222 if ( tmp && tmp.empty ) {
4223 count++;
4224 tmp.empty.add( resolve );
4225 }
4226 }
4227 resolve();
4228 return defer.promise( obj );
4229 }
4230} );
4231var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source;
4232
4233var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" );
4234
4235
4236var cssExpand = [ "Top", "Right", "Bottom", "Left" ];
4237
4238var isHidden = function( elem, el ) {
4239
4240 // isHidden might be called from jQuery#filter function;
4241 // in that case, element will be second argument
4242 elem = el || elem;
4243 return jQuery.css( elem, "display" ) === "none" ||
4244 !jQuery.contains( elem.ownerDocument, elem );
4245 };
4246
4247
4248
4249function adjustCSS( elem, prop, valueParts, tween ) {
4250 var adjusted,
4251 scale = 1,
4252 maxIterations = 20,
4253 currentValue = tween ?
4254 function() { return tween.cur(); } :
4255 function() { return jQuery.css( elem, prop, "" ); },
4256 initial = currentValue(),
4257 unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ),
4258
4259 // Starting value computation is required for potential unit mismatches
4260 initialInUnit = ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) &&
4261 rcssNum.exec( jQuery.css( elem, prop ) );
4262
4263 if ( initialInUnit && initialInUnit[ 3 ] !== unit ) {
4264
4265 // Trust units reported by jQuery.css
4266 unit = unit || initialInUnit[ 3 ];
4267
4268 // Make sure we update the tween properties later on
4269 valueParts = valueParts || [];
4270
4271 // Iteratively approximate from a nonzero starting point
4272 initialInUnit = +initial || 1;
4273
4274 do {
4275
4276 // If previous iteration zeroed out, double until we get *something*.
4277 // Use string for doubling so we don't accidentally see scale as unchanged below
4278 scale = scale || ".5";
4279
4280 // Adjust and apply
4281 initialInUnit = initialInUnit / scale;
4282 jQuery.style( elem, prop, initialInUnit + unit );
4283
4284 // Update scale, tolerating zero or NaN from tween.cur()
4285 // Break the loop if scale is unchanged or perfect, or if we've just had enough.
4286 } while (
4287 scale !== ( scale = currentValue() / initial ) && scale !== 1 && --maxIterations
4288 );
4289 }
4290
4291 if ( valueParts ) {
4292 initialInUnit = +initialInUnit || +initial || 0;
4293
4294 // Apply relative offset (+=/-=) if specified
4295 adjusted = valueParts[ 1 ] ?
4296 initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] :
4297 +valueParts[ 2 ];
4298 if ( tween ) {
4299 tween.unit = unit;
4300 tween.start = initialInUnit;
4301 tween.end = adjusted;
4302 }
4303 }
4304 return adjusted;
4305}
4306var rcheckableType = ( /^(?:checkbox|radio)$/i );
4307
4308var rtagName = ( /<([\w:-]+)/ );
4309
4310var rscriptType = ( /^$|\/(?:java|ecma)script/i );
4311
4312
4313
4314// We have to close these tags to support XHTML (#13200)
4315var wrapMap = {
4316
4317 // Support: IE9
4318 option: [ 1, "<select multiple='multiple'>", "</select>" ],
4319
4320 // XHTML parsers do not magically insert elements in the
4321 // same way that tag soup parsers do. So we cannot shorten
4322 // this by omitting <tbody> or other required elements.
4323 thead: [ 1, "<table>", "</table>" ],
4324 col: [ 2, "<table><colgroup>", "</colgroup></table>" ],
4325 tr: [ 2, "<table><tbody>", "</tbody></table>" ],
4326 td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
4327
4328 _default: [ 0, "", "" ]
4329};
4330
4331// Support: IE9
4332wrapMap.optgroup = wrapMap.option;
4333
4334wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
4335wrapMap.th = wrapMap.td;
4336
4337
4338function getAll( context, tag ) {
4339
4340 // Support: IE9-11+
4341 // Use typeof to avoid zero-argument method invocation on host objects (#15151)
4342 var ret = typeof context.getElementsByTagName !== "undefined" ?
4343 context.getElementsByTagName( tag || "*" ) :
4344 typeof context.querySelectorAll !== "undefined" ?
4345 context.querySelectorAll( tag || "*" ) :
4346 [];
4347
4348 return tag === undefined || tag && jQuery.nodeName( context, tag ) ?
4349 jQuery.merge( [ context ], ret ) :
4350 ret;
4351}
4352
4353
4354// Mark scripts as having already been evaluated
4355function setGlobalEval( elems, refElements ) {
4356 var i = 0,
4357 l = elems.length;
4358
4359 for ( ; i < l; i++ ) {
4360 dataPriv.set(
4361 elems[ i ],
4362 "globalEval",
4363 !refElements || dataPriv.get( refElements[ i ], "globalEval" )
4364 );
4365 }
4366}
4367
4368
4369var rhtml = /<|&#?\w+;/;
4370
4371function buildFragment( elems, context, scripts, selection, ignored ) {
4372 var elem, tmp, tag, wrap, contains, j,
4373 fragment = context.createDocumentFragment(),
4374 nodes = [],
4375 i = 0,
4376 l = elems.length;
4377
4378 for ( ; i < l; i++ ) {
4379 elem = elems[ i ];
4380
4381 if ( elem || elem === 0 ) {
4382
4383 // Add nodes directly
4384 if ( jQuery.type( elem ) === "object" ) {
4385
4386 // Support: Android<4.1, PhantomJS<2
4387 // push.apply(_, arraylike) throws on ancient WebKit
4388 jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );
4389
4390 // Convert non-html into a text node
4391 } else if ( !rhtml.test( elem ) ) {
4392 nodes.push( context.createTextNode( elem ) );
4393
4394 // Convert html into DOM nodes
4395 } else {
4396 tmp = tmp || fragment.appendChild( context.createElement( "div" ) );
4397
4398 // Deserialize a standard representation
4399 tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase();
4400 wrap = wrapMap[ tag ] || wrapMap._default;
4401 tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ];
4402
4403 // Descend through wrappers to the right content
4404 j = wrap[ 0 ];
4405 while ( j-- ) {
4406 tmp = tmp.lastChild;
4407 }
4408
4409 // Support: Android<4.1, PhantomJS<2
4410 // push.apply(_, arraylike) throws on ancient WebKit
4411 jQuery.merge( nodes, tmp.childNodes );
4412
4413 // Remember the top-level container
4414 tmp = fragment.firstChild;
4415
4416 // Ensure the created nodes are orphaned (#12392)
4417 tmp.textContent = "";
4418 }
4419 }
4420 }
4421
4422 // Remove wrapper from fragment
4423 fragment.textContent = "";
4424
4425 i = 0;
4426 while ( ( elem = nodes[ i++ ] ) ) {
4427
4428 // Skip elements already in the context collection (trac-4087)
4429 if ( selection && jQuery.inArray( elem, selection ) > -1 ) {
4430 if ( ignored ) {
4431 ignored.push( elem );
4432 }
4433 continue;
4434 }
4435
4436 contains = jQuery.contains( elem.ownerDocument, elem );
4437
4438 // Append to fragment
4439 tmp = getAll( fragment.appendChild( elem ), "script" );
4440
4441 // Preserve script evaluation history
4442 if ( contains ) {
4443 setGlobalEval( tmp );
4444 }
4445
4446 // Capture executables
4447 if ( scripts ) {
4448 j = 0;
4449 while ( ( elem = tmp[ j++ ] ) ) {
4450 if ( rscriptType.test( elem.type || "" ) ) {
4451 scripts.push( elem );
4452 }
4453 }
4454 }
4455 }
4456
4457 return fragment;
4458}
4459
4460
4461( function() {
4462 var fragment = document.createDocumentFragment(),
4463 div = fragment.appendChild( document.createElement( "div" ) ),
4464 input = document.createElement( "input" );
4465
4466 // Support: Android 4.0-4.3, Safari<=5.1
4467 // Check state lost if the name is set (#11217)
4468 // Support: Windows Web Apps (WWA)
4469 input.setAttribute( "type", "radio" );
4470 input.setAttribute( "checked", "checked" );
4471 input.setAttribute( "name", "t" );
4472
4473 div.appendChild( input );
4474
4475 // Support: Safari<=5.1, Android<4.2
4476 // Older WebKit doesn't clone checked state correctly in fragments
4477 support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked;
4478
4479 // Support: IE<=11+
4480 // Make sure textarea (and checkbox) defaultValue is properly cloned
4481 div.innerHTML = "<textarea>x</textarea>";
4482 support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;
4483} )();
4484
4485
4486var
4487 rkeyEvent = /^key/,
4488 rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/,
4489 rtypenamespace = /^([^.]*)(?:\.(.+)|)/;
4490
4491function returnTrue() {
4492 return true;
4493}
4494
4495function returnFalse() {
4496 return false;
4497}
4498
4499// Support: IE9
4500// See #13393 for more info
4501function safeActiveElement() {
4502 try {
4503 return document.activeElement;
4504 } catch ( err ) { }
4505}
4506
4507function on( elem, types, selector, data, fn, one ) {
4508 var origFn, type;
4509
4510 // Types can be a map of types/handlers
4511 if ( typeof types === "object" ) {
4512
4513 // ( types-Object, selector, data )
4514 if ( typeof selector !== "string" ) {
4515
4516 // ( types-Object, data )
4517 data = data || selector;
4518 selector = undefined;
4519 }
4520 for ( type in types ) {
4521 on( elem, type, selector, data, types[ type ], one );
4522 }
4523 return elem;
4524 }
4525
4526 if ( data == null && fn == null ) {
4527
4528 // ( types, fn )
4529 fn = selector;
4530 data = selector = undefined;
4531 } else if ( fn == null ) {
4532 if ( typeof selector === "string" ) {
4533
4534 // ( types, selector, fn )
4535 fn = data;
4536 data = undefined;
4537 } else {
4538
4539 // ( types, data, fn )
4540 fn = data;
4541 data = selector;
4542 selector = undefined;
4543 }
4544 }
4545 if ( fn === false ) {
4546 fn = returnFalse;
4547 } else if ( !fn ) {
4548 return elem;
4549 }
4550
4551 if ( one === 1 ) {
4552 origFn = fn;
4553 fn = function( event ) {
4554
4555 // Can use an empty set, since event contains the info
4556 jQuery().off( event );
4557 return origFn.apply( this, arguments );
4558 };
4559
4560 // Use same guid so caller can remove using origFn
4561 fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
4562 }
4563 return elem.each( function() {
4564 jQuery.event.add( this, types, fn, data, selector );
4565 } );
4566}
4567
4568/*
4569 * Helper functions for managing events -- not part of the public interface.
4570 * Props to Dean Edwards' addEvent library for many of the ideas.
4571 */
4572jQuery.event = {
4573
4574 global: {},
4575
4576 add: function( elem, types, handler, data, selector ) {
4577
4578 var handleObjIn, eventHandle, tmp,
4579 events, t, handleObj,
4580 special, handlers, type, namespaces, origType,
4581 elemData = dataPriv.get( elem );
4582
4583 // Don't attach events to noData or text/comment nodes (but allow plain objects)
4584 if ( !elemData ) {
4585 return;
4586 }
4587
4588 // Caller can pass in an object of custom data in lieu of the handler
4589 if ( handler.handler ) {
4590 handleObjIn = handler;
4591 handler = handleObjIn.handler;
4592 selector = handleObjIn.selector;
4593 }
4594
4595 // Make sure that the handler has a unique ID, used to find/remove it later
4596 if ( !handler.guid ) {
4597 handler.guid = jQuery.guid++;
4598 }
4599
4600 // Init the element's event structure and main handler, if this is the first
4601 if ( !( events = elemData.events ) ) {
4602 events = elemData.events = {};
4603 }
4604 if ( !( eventHandle = elemData.handle ) ) {
4605 eventHandle = elemData.handle = function( e ) {
4606
4607 // Discard the second event of a jQuery.event.trigger() and
4608 // when an event is called after a page has unloaded
4609 return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ?
4610 jQuery.event.dispatch.apply( elem, arguments ) : undefined;
4611 };
4612 }
4613
4614 // Handle multiple events separated by a space
4615 types = ( types || "" ).match( rnotwhite ) || [ "" ];
4616 t = types.length;
4617 while ( t-- ) {
4618 tmp = rtypenamespace.exec( types[ t ] ) || [];
4619 type = origType = tmp[ 1 ];
4620 namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort();
4621
4622 // There *must* be a type, no attaching namespace-only handlers
4623 if ( !type ) {
4624 continue;
4625 }
4626
4627 // If event changes its type, use the special event handlers for the changed type
4628 special = jQuery.event.special[ type ] || {};
4629
4630 // If selector defined, determine special event api type, otherwise given type
4631 type = ( selector ? special.delegateType : special.bindType ) || type;
4632
4633 // Update special based on newly reset type
4634 special = jQuery.event.special[ type ] || {};
4635
4636 // handleObj is passed to all event handlers
4637 handleObj = jQuery.extend( {
4638 type: type,
4639 origType: origType,
4640 data: data,
4641 handler: handler,
4642 guid: handler.guid,
4643 selector: selector,
4644 needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
4645 namespace: namespaces.join( "." )
4646 }, handleObjIn );
4647
4648 // Init the event handler queue if we're the first
4649 if ( !( handlers = events[ type ] ) ) {
4650 handlers = events[ type ] = [];
4651 handlers.delegateCount = 0;
4652
4653 // Only use addEventListener if the special events handler returns false
4654 if ( !special.setup ||
4655 special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
4656
4657 if ( elem.addEventListener ) {
4658 elem.addEventListener( type, eventHandle );
4659 }
4660 }
4661 }
4662
4663 if ( special.add ) {
4664 special.add.call( elem, handleObj );
4665
4666 if ( !handleObj.handler.guid ) {
4667 handleObj.handler.guid = handler.guid;
4668 }
4669 }
4670
4671 // Add to the element's handler list, delegates in front
4672 if ( selector ) {
4673 handlers.splice( handlers.delegateCount++, 0, handleObj );
4674 } else {
4675 handlers.push( handleObj );
4676 }
4677
4678 // Keep track of which events have ever been used, for event optimization
4679 jQuery.event.global[ type ] = true;
4680 }
4681
4682 },
4683
4684 // Detach an event or set of events from an element
4685 remove: function( elem, types, handler, selector, mappedTypes ) {
4686
4687 var j, origCount, tmp,
4688 events, t, handleObj,
4689 special, handlers, type, namespaces, origType,
4690 elemData = dataPriv.hasData( elem ) && dataPriv.get( elem );
4691
4692 if ( !elemData || !( events = elemData.events ) ) {
4693 return;
4694 }
4695
4696 // Once for each type.namespace in types; type may be omitted
4697 types = ( types || "" ).match( rnotwhite ) || [ "" ];
4698 t = types.length;
4699 while ( t-- ) {
4700 tmp = rtypenamespace.exec( types[ t ] ) || [];
4701 type = origType = tmp[ 1 ];
4702 namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort();
4703
4704 // Unbind all events (on this namespace, if provided) for the element
4705 if ( !type ) {
4706 for ( type in events ) {
4707 jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
4708 }
4709 continue;
4710 }
4711
4712 special = jQuery.event.special[ type ] || {};
4713 type = ( selector ? special.delegateType : special.bindType ) || type;
4714 handlers = events[ type ] || [];
4715 tmp = tmp[ 2 ] &&
4716 new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" );
4717
4718 // Remove matching events
4719 origCount = j = handlers.length;
4720 while ( j-- ) {
4721 handleObj = handlers[ j ];
4722
4723 if ( ( mappedTypes || origType === handleObj.origType ) &&
4724 ( !handler || handler.guid === handleObj.guid ) &&
4725 ( !tmp || tmp.test( handleObj.namespace ) ) &&
4726 ( !selector || selector === handleObj.selector ||
4727 selector === "**" && handleObj.selector ) ) {
4728 handlers.splice( j, 1 );
4729
4730 if ( handleObj.selector ) {
4731 handlers.delegateCount--;
4732 }
4733 if ( special.remove ) {
4734 special.remove.call( elem, handleObj );
4735 }
4736 }
4737 }
4738
4739 // Remove generic event handler if we removed something and no more handlers exist
4740 // (avoids potential for endless recursion during removal of special event handlers)
4741 if ( origCount && !handlers.length ) {
4742 if ( !special.teardown ||
4743 special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
4744
4745 jQuery.removeEvent( elem, type, elemData.handle );
4746 }
4747
4748 delete events[ type ];
4749 }
4750 }
4751
4752 // Remove data and the expando if it's no longer used
4753 if ( jQuery.isEmptyObject( events ) ) {
4754 dataPriv.remove( elem, "handle events" );
4755 }
4756 },
4757
4758 dispatch: function( event ) {
4759
4760 // Make a writable jQuery.Event from the native event object
4761 event = jQuery.event.fix( event );
4762
4763 var i, j, ret, matched, handleObj,
4764 handlerQueue = [],
4765 args = slice.call( arguments ),
4766 handlers = ( dataPriv.get( this, "events" ) || {} )[ event.type ] || [],
4767 special = jQuery.event.special[ event.type ] || {};
4768
4769 // Use the fix-ed jQuery.Event rather than the (read-only) native event
4770 args[ 0 ] = event;
4771 event.delegateTarget = this;
4772
4773 // Call the preDispatch hook for the mapped type, and let it bail if desired
4774 if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
4775 return;
4776 }
4777
4778 // Determine handlers
4779 handlerQueue = jQuery.event.handlers.call( this, event, handlers );
4780
4781 // Run delegates first; they may want to stop propagation beneath us
4782 i = 0;
4783 while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) {
4784 event.currentTarget = matched.elem;
4785
4786 j = 0;
4787 while ( ( handleObj = matched.handlers[ j++ ] ) &&
4788 !event.isImmediatePropagationStopped() ) {
4789
4790 // Triggered event must either 1) have no namespace, or 2) have namespace(s)
4791 // a subset or equal to those in the bound event (both can have no namespace).
4792 if ( !event.rnamespace || event.rnamespace.test( handleObj.namespace ) ) {
4793
4794 event.handleObj = handleObj;
4795 event.data = handleObj.data;
4796
4797 ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle ||
4798 handleObj.handler ).apply( matched.elem, args );
4799
4800 if ( ret !== undefined ) {
4801 if ( ( event.result = ret ) === false ) {
4802 event.preventDefault();
4803 event.stopPropagation();
4804 }
4805 }
4806 }
4807 }
4808 }
4809
4810 // Call the postDispatch hook for the mapped type
4811 if ( special.postDispatch ) {
4812 special.postDispatch.call( this, event );
4813 }
4814
4815 return event.result;
4816 },
4817
4818 handlers: function( event, handlers ) {
4819 var i, matches, sel, handleObj,
4820 handlerQueue = [],
4821 delegateCount = handlers.delegateCount,
4822 cur = event.target;
4823
4824 // Support (at least): Chrome, IE9
4825 // Find delegate handlers
4826 // Black-hole SVG <use> instance trees (#13180)
4827 //
4828 // Support: Firefox<=42+
4829 // Avoid non-left-click in FF but don't block IE radio events (#3861, gh-2343)
4830 if ( delegateCount && cur.nodeType &&
4831 ( event.type !== "click" || isNaN( event.button ) || event.button < 1 ) ) {
4832
4833 for ( ; cur !== this; cur = cur.parentNode || this ) {
4834
4835 // Don't check non-elements (#13208)
4836 // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)
4837 if ( cur.nodeType === 1 && ( cur.disabled !== true || event.type !== "click" ) ) {
4838 matches = [];
4839 for ( i = 0; i < delegateCount; i++ ) {
4840 handleObj = handlers[ i ];
4841
4842 // Don't conflict with Object.prototype properties (#13203)
4843 sel = handleObj.selector + " ";
4844
4845 if ( matches[ sel ] === undefined ) {
4846 matches[ sel ] = handleObj.needsContext ?
4847 jQuery( sel, this ).index( cur ) > -1 :
4848 jQuery.find( sel, this, null, [ cur ] ).length;
4849 }
4850 if ( matches[ sel ] ) {
4851 matches.push( handleObj );
4852 }
4853 }
4854 if ( matches.length ) {
4855 handlerQueue.push( { elem: cur, handlers: matches } );
4856 }
4857 }
4858 }
4859 }
4860
4861 // Add the remaining (directly-bound) handlers
4862 if ( delegateCount < handlers.length ) {
4863 handlerQueue.push( { elem: this, handlers: handlers.slice( delegateCount ) } );
4864 }
4865
4866 return handlerQueue;
4867 },
4868
4869 // Includes some event props shared by KeyEvent and MouseEvent
4870 props: ( "altKey bubbles cancelable ctrlKey currentTarget detail eventPhase " +
4871 "metaKey relatedTarget shiftKey target timeStamp view which" ).split( " " ),
4872
4873 fixHooks: {},
4874
4875 keyHooks: {
4876 props: "char charCode key keyCode".split( " " ),
4877 filter: function( event, original ) {
4878
4879 // Add which for key events
4880 if ( event.which == null ) {
4881 event.which = original.charCode != null ? original.charCode : original.keyCode;
4882 }
4883
4884 return event;
4885 }
4886 },
4887
4888 mouseHooks: {
4889 props: ( "button buttons clientX clientY offsetX offsetY pageX pageY " +
4890 "screenX screenY toElement" ).split( " " ),
4891 filter: function( event, original ) {
4892 var eventDoc, doc, body,
4893 button = original.button;
4894
4895 // Calculate pageX/Y if missing and clientX/Y available
4896 if ( event.pageX == null && original.clientX != null ) {
4897 eventDoc = event.target.ownerDocument || document;
4898 doc = eventDoc.documentElement;
4899 body = eventDoc.body;
4900
4901 event.pageX = original.clientX +
4902 ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) -
4903 ( doc && doc.clientLeft || body && body.clientLeft || 0 );
4904 event.pageY = original.clientY +
4905 ( doc && doc.scrollTop || body && body.scrollTop || 0 ) -
4906 ( doc && doc.clientTop || body && body.clientTop || 0 );
4907 }
4908
4909 // Add which for click: 1 === left; 2 === middle; 3 === right
4910 // Note: button is not normalized, so don't use it
4911 if ( !event.which && button !== undefined ) {
4912 event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
4913 }
4914
4915 return event;
4916 }
4917 },
4918
4919 fix: function( event ) {
4920 if ( event[ jQuery.expando ] ) {
4921 return event;
4922 }
4923
4924 // Create a writable copy of the event object and normalize some properties
4925 var i, prop, copy,
4926 type = event.type,
4927 originalEvent = event,
4928 fixHook = this.fixHooks[ type ];
4929
4930 if ( !fixHook ) {
4931 this.fixHooks[ type ] = fixHook =
4932 rmouseEvent.test( type ) ? this.mouseHooks :
4933 rkeyEvent.test( type ) ? this.keyHooks :
4934 {};
4935 }
4936 copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;
4937
4938 event = new jQuery.Event( originalEvent );
4939
4940 i = copy.length;
4941 while ( i-- ) {
4942 prop = copy[ i ];
4943 event[ prop ] = originalEvent[ prop ];
4944 }
4945
4946 // Support: Cordova 2.5 (WebKit) (#13255)
4947 // All events should have a target; Cordova deviceready doesn't
4948 if ( !event.target ) {
4949 event.target = document;
4950 }
4951
4952 // Support: Safari 6.0+, Chrome<28
4953 // Target should not be a text node (#504, #13143)
4954 if ( event.target.nodeType === 3 ) {
4955 event.target = event.target.parentNode;
4956 }
4957
4958 return fixHook.filter ? fixHook.filter( event, originalEvent ) : event;
4959 },
4960
4961 special: {
4962 load: {
4963
4964 // Prevent triggered image.load events from bubbling to window.load
4965 noBubble: true
4966 },
4967 focus: {
4968
4969 // Fire native event if possible so blur/focus sequence is correct
4970 trigger: function() {
4971 if ( this !== safeActiveElement() && this.focus ) {
4972 this.focus();
4973 return false;
4974 }
4975 },
4976 delegateType: "focusin"
4977 },
4978 blur: {
4979 trigger: function() {
4980 if ( this === safeActiveElement() && this.blur ) {
4981 this.blur();
4982 return false;
4983 }
4984 },
4985 delegateType: "focusout"
4986 },
4987 click: {
4988
4989 // For checkbox, fire native event so checked state will be right
4990 trigger: function() {
4991 if ( this.type === "checkbox" && this.click && jQuery.nodeName( this, "input" ) ) {
4992 this.click();
4993 return false;
4994 }
4995 },
4996
4997 // For cross-browser consistency, don't fire native .click() on links
4998 _default: function( event ) {
4999 return jQuery.nodeName( event.target, "a" );
5000 }
5001 },
5002
5003 beforeunload: {
5004 postDispatch: function( event ) {
5005
5006 // Support: Firefox 20+
5007 // Firefox doesn't alert if the returnValue field is not set.
5008 if ( event.result !== undefined && event.originalEvent ) {
5009 event.originalEvent.returnValue = event.result;
5010 }
5011 }
5012 }
5013 }
5014};
5015
5016jQuery.removeEvent = function( elem, type, handle ) {
5017
5018 // This "if" is needed for plain objects
5019 if ( elem.removeEventListener ) {
5020 elem.removeEventListener( type, handle );
5021 }
5022};
5023
5024jQuery.Event = function( src, props ) {
5025
5026 // Allow instantiation without the 'new' keyword
5027 if ( !( this instanceof jQuery.Event ) ) {
5028 return new jQuery.Event( src, props );
5029 }
5030
5031 // Event object
5032 if ( src && src.type ) {
5033 this.originalEvent = src;
5034 this.type = src.type;
5035
5036 // Events bubbling up the document may have been marked as prevented
5037 // by a handler lower down the tree; reflect the correct value.
5038 this.isDefaultPrevented = src.defaultPrevented ||
5039 src.defaultPrevented === undefined &&
5040
5041 // Support: Android<4.0
5042 src.returnValue === false ?
5043 returnTrue :
5044 returnFalse;
5045
5046 // Event type
5047 } else {
5048 this.type = src;
5049 }
5050
5051 // Put explicitly provided properties onto the event object
5052 if ( props ) {
5053 jQuery.extend( this, props );
5054 }
5055
5056 // Create a timestamp if incoming event doesn't have one
5057 this.timeStamp = src && src.timeStamp || jQuery.now();
5058
5059 // Mark it as fixed
5060 this[ jQuery.expando ] = true;
5061};
5062
5063// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
5064// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
5065jQuery.Event.prototype = {
5066 constructor: jQuery.Event,
5067 isDefaultPrevented: returnFalse,
5068 isPropagationStopped: returnFalse,
5069 isImmediatePropagationStopped: returnFalse,
5070 isSimulated: false,
5071
5072 preventDefault: function() {
5073 var e = this.originalEvent;
5074
5075 this.isDefaultPrevented = returnTrue;
5076
5077 if ( e && !this.isSimulated ) {
5078 e.preventDefault();
5079 }
5080 },
5081 stopPropagation: function() {
5082 var e = this.originalEvent;
5083
5084 this.isPropagationStopped = returnTrue;
5085
5086 if ( e && !this.isSimulated ) {
5087 e.stopPropagation();
5088 }
5089 },
5090 stopImmediatePropagation: function() {
5091 var e = this.originalEvent;
5092
5093 this.isImmediatePropagationStopped = returnTrue;
5094
5095 if ( e && !this.isSimulated ) {
5096 e.stopImmediatePropagation();
5097 }
5098
5099 this.stopPropagation();
5100 }
5101};
5102
5103// Create mouseenter/leave events using mouseover/out and event-time checks
5104// so that event delegation works in jQuery.
5105// Do the same for pointerenter/pointerleave and pointerover/pointerout
5106//
5107// Support: Safari 7 only
5108// Safari sends mouseenter too often; see:
5109// https://code.google.com/p/chromium/issues/detail?id=470258
5110// for the description of the bug (it existed in older Chrome versions as well).
5111jQuery.each( {
5112 mouseenter: "mouseover",
5113 mouseleave: "mouseout",
5114 pointerenter: "pointerover",
5115 pointerleave: "pointerout"
5116}, function( orig, fix ) {
5117 jQuery.event.special[ orig ] = {
5118 delegateType: fix,
5119 bindType: fix,
5120
5121 handle: function( event ) {
5122 var ret,
5123 target = this,
5124 related = event.relatedTarget,
5125 handleObj = event.handleObj;
5126
5127 // For mouseenter/leave call the handler if related is outside the target.
5128 // NB: No relatedTarget if the mouse left/entered the browser window
5129 if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) {
5130 event.type = handleObj.origType;
5131 ret = handleObj.handler.apply( this, arguments );
5132 event.type = fix;
5133 }
5134 return ret;
5135 }
5136 };
5137} );
5138
5139jQuery.fn.extend( {
5140 on: function( types, selector, data, fn ) {
5141 return on( this, types, selector, data, fn );
5142 },
5143 one: function( types, selector, data, fn ) {
5144 return on( this, types, selector, data, fn, 1 );
5145 },
5146 off: function( types, selector, fn ) {
5147 var handleObj, type;
5148 if ( types && types.preventDefault && types.handleObj ) {
5149
5150 // ( event ) dispatched jQuery.Event
5151 handleObj = types.handleObj;
5152 jQuery( types.delegateTarget ).off(
5153 handleObj.namespace ?
5154 handleObj.origType + "." + handleObj.namespace :
5155 handleObj.origType,
5156 handleObj.selector,
5157 handleObj.handler
5158 );
5159 return this;
5160 }
5161 if ( typeof types === "object" ) {
5162
5163 // ( types-object [, selector] )
5164 for ( type in types ) {
5165 this.off( type, selector, types[ type ] );
5166 }
5167 return this;
5168 }
5169 if ( selector === false || typeof selector === "function" ) {
5170
5171 // ( types [, fn] )
5172 fn = selector;
5173 selector = undefined;
5174 }
5175 if ( fn === false ) {
5176 fn = returnFalse;
5177 }
5178 return this.each( function() {
5179 jQuery.event.remove( this, types, fn, selector );
5180 } );
5181 }
5182} );
5183
5184
5185var
5186 rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi,
5187
5188 // Support: IE 10-11, Edge 10240+
5189 // In IE/Edge using regex groups here causes severe slowdowns.
5190 // See https://connect.microsoft.com/IE/feedback/details/1736512/
5191 rnoInnerhtml = /<script|<style|<link/i,
5192
5193 // checked="checked" or checked
5194 rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
5195 rscriptTypeMasked = /^true\/(.*)/,
5196 rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g;
5197
5198// Manipulating tables requires a tbody
5199function manipulationTarget( elem, content ) {
5200 return jQuery.nodeName( elem, "table" ) &&
5201 jQuery.nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ?
5202
5203 elem.getElementsByTagName( "tbody" )[ 0 ] ||
5204 elem.appendChild( elem.ownerDocument.createElement( "tbody" ) ) :
5205 elem;
5206}
5207
5208// Replace/restore the type attribute of script elements for safe DOM manipulation
5209function disableScript( elem ) {
5210 elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type;
5211 return elem;
5212}
5213function restoreScript( elem ) {
5214 var match = rscriptTypeMasked.exec( elem.type );
5215
5216 if ( match ) {
5217 elem.type = match[ 1 ];
5218 } else {
5219 elem.removeAttribute( "type" );
5220 }
5221
5222 return elem;
5223}
5224
5225function cloneCopyEvent( src, dest ) {
5226 var i, l, type, pdataOld, pdataCur, udataOld, udataCur, events;
5227
5228 if ( dest.nodeType !== 1 ) {
5229 return;
5230 }
5231
5232 // 1. Copy private data: events, handlers, etc.
5233 if ( dataPriv.hasData( src ) ) {
5234 pdataOld = dataPriv.access( src );
5235 pdataCur = dataPriv.set( dest, pdataOld );
5236 events = pdataOld.events;
5237
5238 if ( events ) {
5239 delete pdataCur.handle;
5240 pdataCur.events = {};
5241
5242 for ( type in events ) {
5243 for ( i = 0, l = events[ type ].length; i < l; i++ ) {
5244 jQuery.event.add( dest, type, events[ type ][ i ] );
5245 }
5246 }
5247 }
5248 }
5249
5250 // 2. Copy user data
5251 if ( dataUser.hasData( src ) ) {
5252 udataOld = dataUser.access( src );
5253 udataCur = jQuery.extend( {}, udataOld );
5254
5255 dataUser.set( dest, udataCur );
5256 }
5257}
5258
5259// Fix IE bugs, see support tests
5260function fixInput( src, dest ) {
5261 var nodeName = dest.nodeName.toLowerCase();
5262
5263 // Fails to persist the checked state of a cloned checkbox or radio button.
5264 if ( nodeName === "input" && rcheckableType.test( src.type ) ) {
5265 dest.checked = src.checked;
5266
5267 // Fails to return the selected option to the default selected state when cloning options
5268 } else if ( nodeName === "input" || nodeName === "textarea" ) {
5269 dest.defaultValue = src.defaultValue;
5270 }
5271}
5272
5273function domManip( collection, args, callback, ignored ) {
5274
5275 // Flatten any nested arrays
5276 args = concat.apply( [], args );
5277
5278 var fragment, first, scripts, hasScripts, node, doc,
5279 i = 0,
5280 l = collection.length,
5281 iNoClone = l - 1,
5282 value = args[ 0 ],
5283 isFunction = jQuery.isFunction( value );
5284
5285 // We can't cloneNode fragments that contain checked, in WebKit
5286 if ( isFunction ||
5287 ( l > 1 && typeof value === "string" &&
5288 !support.checkClone && rchecked.test( value ) ) ) {
5289 return collection.each( function( index ) {
5290 var self = collection.eq( index );
5291 if ( isFunction ) {
5292 args[ 0 ] = value.call( this, index, self.html() );
5293 }
5294 domManip( self, args, callback, ignored );
5295 } );
5296 }
5297
5298 if ( l ) {
5299 fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored );
5300 first = fragment.firstChild;
5301
5302 if ( fragment.childNodes.length === 1 ) {
5303 fragment = first;
5304 }
5305
5306 // Require either new content or an interest in ignored elements to invoke the callback
5307 if ( first || ignored ) {
5308 scripts = jQuery.map( getAll( fragment, "script" ), disableScript );
5309 hasScripts = scripts.length;
5310
5311 // Use the original fragment for the last item
5312 // instead of the first because it can end up
5313 // being emptied incorrectly in certain situations (#8070).
5314 for ( ; i < l; i++ ) {
5315 node = fragment;
5316
5317 if ( i !== iNoClone ) {
5318 node = jQuery.clone( node, true, true );
5319
5320 // Keep references to cloned scripts for later restoration
5321 if ( hasScripts ) {
5322
5323 // Support: Android<4.1, PhantomJS<2
5324 // push.apply(_, arraylike) throws on ancient WebKit
5325 jQuery.merge( scripts, getAll( node, "script" ) );
5326 }
5327 }
5328
5329 callback.call( collection[ i ], node, i );
5330 }
5331
5332 if ( hasScripts ) {
5333 doc = scripts[ scripts.length - 1 ].ownerDocument;
5334
5335 // Reenable scripts
5336 jQuery.map( scripts, restoreScript );
5337
5338 // Evaluate executable scripts on first document insertion
5339 for ( i = 0; i < hasScripts; i++ ) {
5340 node = scripts[ i ];
5341 if ( rscriptType.test( node.type || "" ) &&
5342 !dataPriv.access( node, "globalEval" ) &&
5343 jQuery.contains( doc, node ) ) {
5344
5345 if ( node.src ) {
5346
5347 // Optional AJAX dependency, but won't run scripts if not present
5348 if ( jQuery._evalUrl ) {
5349 jQuery._evalUrl( node.src );
5350 }
5351 } else {
5352 jQuery.globalEval( node.textContent.replace( rcleanScript, "" ) );
5353 }
5354 }
5355 }
5356 }
5357 }
5358 }
5359
5360 return collection;
5361}
5362
5363function remove( elem, selector, keepData ) {
5364 var node,
5365 nodes = selector ? jQuery.filter( selector, elem ) : elem,
5366 i = 0;
5367
5368 for ( ; ( node = nodes[ i ] ) != null; i++ ) {
5369 if ( !keepData && node.nodeType === 1 ) {
5370 jQuery.cleanData( getAll( node ) );
5371 }
5372
5373 if ( node.parentNode ) {
5374 if ( keepData && jQuery.contains( node.ownerDocument, node ) ) {
5375 setGlobalEval( getAll( node, "script" ) );
5376 }
5377 node.parentNode.removeChild( node );
5378 }
5379 }
5380
5381 return elem;
5382}
5383
5384jQuery.extend( {
5385 htmlPrefilter: function( html ) {
5386 return html.replace( rxhtmlTag, "<$1></$2>" );
5387 },
5388
5389 clone: function( elem, dataAndEvents, deepDataAndEvents ) {
5390 var i, l, srcElements, destElements,
5391 clone = elem.cloneNode( true ),
5392 inPage = jQuery.contains( elem.ownerDocument, elem );
5393
5394 // Fix IE cloning issues
5395 if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) &&
5396 !jQuery.isXMLDoc( elem ) ) {
5397
5398 // We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2
5399 destElements = getAll( clone );
5400 srcElements = getAll( elem );
5401
5402 for ( i = 0, l = srcElements.length; i < l; i++ ) {
5403 fixInput( srcElements[ i ], destElements[ i ] );
5404 }
5405 }
5406
5407 // Copy the events from the original to the clone
5408 if ( dataAndEvents ) {
5409 if ( deepDataAndEvents ) {
5410 srcElements = srcElements || getAll( elem );
5411 destElements = destElements || getAll( clone );
5412
5413 for ( i = 0, l = srcElements.length; i < l; i++ ) {
5414 cloneCopyEvent( srcElements[ i ], destElements[ i ] );
5415 }
5416 } else {
5417 cloneCopyEvent( elem, clone );
5418 }
5419 }
5420
5421 // Preserve script evaluation history
5422 destElements = getAll( clone, "script" );
5423 if ( destElements.length > 0 ) {
5424 setGlobalEval( destElements, !inPage && getAll( elem, "script" ) );
5425 }
5426
5427 // Return the cloned set
5428 return clone;
5429 },
5430
5431 cleanData: function( elems ) {
5432 var data, elem, type,
5433 special = jQuery.event.special,
5434 i = 0;
5435
5436 for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) {
5437 if ( acceptData( elem ) ) {
5438 if ( ( data = elem[ dataPriv.expando ] ) ) {
5439 if ( data.events ) {
5440 for ( type in data.events ) {
5441 if ( special[ type ] ) {
5442 jQuery.event.remove( elem, type );
5443
5444 // This is a shortcut to avoid jQuery.event.remove's overhead
5445 } else {
5446 jQuery.removeEvent( elem, type, data.handle );
5447 }
5448 }
5449 }
5450
5451 // Support: Chrome <= 35-45+
5452 // Assign undefined instead of using delete, see Data#remove
5453 elem[ dataPriv.expando ] = undefined;
5454 }
5455 if ( elem[ dataUser.expando ] ) {
5456
5457 // Support: Chrome <= 35-45+
5458 // Assign undefined instead of using delete, see Data#remove
5459 elem[ dataUser.expando ] = undefined;
5460 }
5461 }
5462 }
5463 }
5464} );
5465
5466jQuery.fn.extend( {
5467
5468 // Keep domManip exposed until 3.0 (gh-2225)
5469 domManip: domManip,
5470
5471 detach: function( selector ) {
5472 return remove( this, selector, true );
5473 },
5474
5475 remove: function( selector ) {
5476 return remove( this, selector );
5477 },
5478
5479 text: function( value ) {
5480 return access( this, function( value ) {
5481 return value === undefined ?
5482 jQuery.text( this ) :
5483 this.empty().each( function() {
5484 if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
5485 this.textContent = value;
5486 }
5487 } );
5488 }, null, value, arguments.length );
5489 },
5490
5491 append: function() {
5492 return domManip( this, arguments, function( elem ) {
5493 if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
5494 var target = manipulationTarget( this, elem );
5495 target.appendChild( elem );
5496 }
5497 } );
5498 },
5499
5500 prepend: function() {
5501 return domManip( this, arguments, function( elem ) {
5502 if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
5503 var target = manipulationTarget( this, elem );
5504 target.insertBefore( elem, target.firstChild );
5505 }
5506 } );
5507 },
5508
5509 before: function() {
5510 return domManip( this, arguments, function( elem ) {
5511 if ( this.parentNode ) {
5512 this.parentNode.insertBefore( elem, this );
5513 }
5514 } );
5515 },
5516
5517 after: function() {
5518 return domManip( this, arguments, function( elem ) {
5519 if ( this.parentNode ) {
5520 this.parentNode.insertBefore( elem, this.nextSibling );
5521 }
5522 } );
5523 },
5524
5525 empty: function() {
5526 var elem,
5527 i = 0;
5528
5529 for ( ; ( elem = this[ i ] ) != null; i++ ) {
5530 if ( elem.nodeType === 1 ) {
5531
5532 // Prevent memory leaks
5533 jQuery.cleanData( getAll( elem, false ) );
5534
5535 // Remove any remaining nodes
5536 elem.textContent = "";
5537 }
5538 }
5539
5540 return this;
5541 },
5542
5543 clone: function( dataAndEvents, deepDataAndEvents ) {
5544 dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
5545 deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
5546
5547 return this.map( function() {
5548 return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
5549 } );
5550 },
5551
5552 html: function( value ) {
5553 return access( this, function( value ) {
5554 var elem = this[ 0 ] || {},
5555 i = 0,
5556 l = this.length;
5557
5558 if ( value === undefined && elem.nodeType === 1 ) {
5559 return elem.innerHTML;
5560 }
5561
5562 // See if we can take a shortcut and just use innerHTML
5563 if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
5564 !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) {
5565
5566 value = jQuery.htmlPrefilter( value );
5567
5568 try {
5569 for ( ; i < l; i++ ) {
5570 elem = this[ i ] || {};
5571
5572 // Remove element nodes and prevent memory leaks
5573 if ( elem.nodeType === 1 ) {
5574 jQuery.cleanData( getAll( elem, false ) );
5575 elem.innerHTML = value;
5576 }
5577 }
5578
5579 elem = 0;
5580
5581 // If using innerHTML throws an exception, use the fallback method
5582 } catch ( e ) {}
5583 }
5584
5585 if ( elem ) {
5586 this.empty().append( value );
5587 }
5588 }, null, value, arguments.length );
5589 },
5590
5591 replaceWith: function() {
5592 var ignored = [];
5593
5594 // Make the changes, replacing each non-ignored context element with the new content
5595 return domManip( this, arguments, function( elem ) {
5596 var parent = this.parentNode;
5597
5598 if ( jQuery.inArray( this, ignored ) < 0 ) {
5599 jQuery.cleanData( getAll( this ) );
5600 if ( parent ) {
5601 parent.replaceChild( elem, this );
5602 }
5603 }
5604
5605 // Force callback invocation
5606 }, ignored );
5607 }
5608} );
5609
5610jQuery.each( {
5611 appendTo: "append",
5612 prependTo: "prepend",
5613 insertBefore: "before",
5614 insertAfter: "after",
5615 replaceAll: "replaceWith"
5616}, function( name, original ) {
5617 jQuery.fn[ name ] = function( selector ) {
5618 var elems,
5619 ret = [],
5620 insert = jQuery( selector ),
5621 last = insert.length - 1,
5622 i = 0;
5623
5624 for ( ; i <= last; i++ ) {
5625 elems = i === last ? this : this.clone( true );
5626 jQuery( insert[ i ] )[ original ]( elems );
5627
5628 // Support: QtWebKit
5629 // .get() because push.apply(_, arraylike) throws
5630 push.apply( ret, elems.get() );
5631 }
5632
5633 return this.pushStack( ret );
5634 };
5635} );
5636
5637
5638var iframe,
5639 elemdisplay = {
5640
5641 // Support: Firefox
5642 // We have to pre-define these values for FF (#10227)
5643 HTML: "block",
5644 BODY: "block"
5645 };
5646
5647/**
5648 * Retrieve the actual display of a element
5649 * @param {String} name nodeName of the element
5650 * @param {Object} doc Document object
5651 */
5652
5653// Called only from within defaultDisplay
5654function actualDisplay( name, doc ) {
5655 var elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ),
5656
5657 display = jQuery.css( elem[ 0 ], "display" );
5658
5659 // We don't have any data stored on the element,
5660 // so use "detach" method as fast way to get rid of the element
5661 elem.detach();
5662
5663 return display;
5664}
5665
5666/**
5667 * Try to determine the default display value of an element
5668 * @param {String} nodeName
5669 */
5670function defaultDisplay( nodeName ) {
5671 var doc = document,
5672 display = elemdisplay[ nodeName ];
5673
5674 if ( !display ) {
5675 display = actualDisplay( nodeName, doc );
5676
5677 // If the simple way fails, read from inside an iframe
5678 if ( display === "none" || !display ) {
5679
5680 // Use the already-created iframe if possible
5681 iframe = ( iframe || jQuery( "<iframe frameborder='0' width='0' height='0'/>" ) )
5682 .appendTo( doc.documentElement );
5683
5684 // Always write a new HTML skeleton so Webkit and Firefox don't choke on reuse
5685 doc = iframe[ 0 ].contentDocument;
5686
5687 // Support: IE
5688 doc.write();
5689 doc.close();
5690
5691 display = actualDisplay( nodeName, doc );
5692 iframe.detach();
5693 }
5694
5695 // Store the correct default display
5696 elemdisplay[ nodeName ] = display;
5697 }
5698
5699 return display;
5700}
5701var rmargin = ( /^margin/ );
5702
5703var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" );
5704
5705var getStyles = function( elem ) {
5706
5707 // Support: IE<=11+, Firefox<=30+ (#15098, #14150)
5708 // IE throws on elements created in popups
5709 // FF meanwhile throws on frame elements through "defaultView.getComputedStyle"
5710 var view = elem.ownerDocument.defaultView;
5711
5712 if ( !view || !view.opener ) {
5713 view = window;
5714 }
5715
5716 return view.getComputedStyle( elem );
5717 };
5718
5719var swap = function( elem, options, callback, args ) {
5720 var ret, name,
5721 old = {};
5722
5723 // Remember the old values, and insert the new ones
5724 for ( name in options ) {
5725 old[ name ] = elem.style[ name ];
5726 elem.style[ name ] = options[ name ];
5727 }
5728
5729 ret = callback.apply( elem, args || [] );
5730
5731 // Revert the old values
5732 for ( name in options ) {
5733 elem.style[ name ] = old[ name ];
5734 }
5735
5736 return ret;
5737};
5738
5739
5740var documentElement = document.documentElement;
5741
5742
5743
5744( function() {
5745 var pixelPositionVal, boxSizingReliableVal, pixelMarginRightVal, reliableMarginLeftVal,
5746 container = document.createElement( "div" ),
5747 div = document.createElement( "div" );
5748
5749 // Finish early in limited (non-browser) environments
5750 if ( !div.style ) {
5751 return;
5752 }
5753
5754 // Support: IE9-11+
5755 // Style of cloned element affects source element cloned (#8908)
5756 div.style.backgroundClip = "content-box";
5757 div.cloneNode( true ).style.backgroundClip = "";
5758 support.clearCloneStyle = div.style.backgroundClip === "content-box";
5759
5760 container.style.cssText = "border:0;width:8px;height:0;top:0;left:-9999px;" +
5761 "padding:0;margin-top:1px;position:absolute";
5762 container.appendChild( div );
5763
5764 // Executing both pixelPosition & boxSizingReliable tests require only one layout
5765 // so they're executed at the same time to save the second computation.
5766 function computeStyleTests() {
5767 div.style.cssText =
5768
5769 // Support: Firefox<29, Android 2.3
5770 // Vendor-prefix box-sizing
5771 "-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;" +
5772 "position:relative;display:block;" +
5773 "margin:auto;border:1px;padding:1px;" +
5774 "top:1%;width:50%";
5775 div.innerHTML = "";
5776 documentElement.appendChild( container );
5777
5778 var divStyle = window.getComputedStyle( div );
5779 pixelPositionVal = divStyle.top !== "1%";
5780 reliableMarginLeftVal = divStyle.marginLeft === "2px";
5781 boxSizingReliableVal = divStyle.width === "4px";
5782
5783 // Support: Android 4.0 - 4.3 only
5784 // Some styles come back with percentage values, even though they shouldn't
5785 div.style.marginRight = "50%";
5786 pixelMarginRightVal = divStyle.marginRight === "4px";
5787
5788 documentElement.removeChild( container );
5789 }
5790
5791 jQuery.extend( support, {
5792 pixelPosition: function() {
5793
5794 // This test is executed only once but we still do memoizing
5795 // since we can use the boxSizingReliable pre-computing.
5796 // No need to check if the test was already performed, though.
5797 computeStyleTests();
5798 return pixelPositionVal;
5799 },
5800 boxSizingReliable: function() {
5801 if ( boxSizingReliableVal == null ) {
5802 computeStyleTests();
5803 }
5804 return boxSizingReliableVal;
5805 },
5806 pixelMarginRight: function() {
5807
5808 // Support: Android 4.0-4.3
5809 // We're checking for boxSizingReliableVal here instead of pixelMarginRightVal
5810 // since that compresses better and they're computed together anyway.
5811 if ( boxSizingReliableVal == null ) {
5812 computeStyleTests();
5813 }
5814 return pixelMarginRightVal;
5815 },
5816 reliableMarginLeft: function() {
5817
5818 // Support: IE <=8 only, Android 4.0 - 4.3 only, Firefox <=3 - 37
5819 if ( boxSizingReliableVal == null ) {
5820 computeStyleTests();
5821 }
5822 return reliableMarginLeftVal;
5823 },
5824 reliableMarginRight: function() {
5825
5826 // Support: Android 2.3
5827 // Check if div with explicit width and no margin-right incorrectly
5828 // gets computed margin-right based on width of container. (#3333)
5829 // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
5830 // This support function is only executed once so no memoizing is needed.
5831 var ret,
5832 marginDiv = div.appendChild( document.createElement( "div" ) );
5833
5834 // Reset CSS: box-sizing; display; margin; border; padding
5835 marginDiv.style.cssText = div.style.cssText =
5836
5837 // Support: Android 2.3
5838 // Vendor-prefix box-sizing
5839 "-webkit-box-sizing:content-box;box-sizing:content-box;" +
5840 "display:block;margin:0;border:0;padding:0";
5841 marginDiv.style.marginRight = marginDiv.style.width = "0";
5842 div.style.width = "1px";
5843 documentElement.appendChild( container );
5844
5845 ret = !parseFloat( window.getComputedStyle( marginDiv ).marginRight );
5846
5847 documentElement.removeChild( container );
5848 div.removeChild( marginDiv );
5849
5850 return ret;
5851 }
5852 } );
5853} )();
5854
5855
5856function curCSS( elem, name, computed ) {
5857 var width, minWidth, maxWidth, ret,
5858 style = elem.style;
5859
5860 computed = computed || getStyles( elem );
5861 ret = computed ? computed.getPropertyValue( name ) || computed[ name ] : undefined;
5862
5863 // Support: Opera 12.1x only
5864 // Fall back to style even without computed
5865 // computed is undefined for elems on document fragments
5866 if ( ( ret === "" || ret === undefined ) && !jQuery.contains( elem.ownerDocument, elem ) ) {
5867 ret = jQuery.style( elem, name );
5868 }
5869
5870 // Support: IE9
5871 // getPropertyValue is only needed for .css('filter') (#12537)
5872 if ( computed ) {
5873
5874 // A tribute to the "awesome hack by Dean Edwards"
5875 // Android Browser returns percentage for some values,
5876 // but width seems to be reliably pixels.
5877 // This is against the CSSOM draft spec:
5878 // http://dev.w3.org/csswg/cssom/#resolved-values
5879 if ( !support.pixelMarginRight() && rnumnonpx.test( ret ) && rmargin.test( name ) ) {
5880
5881 // Remember the original values
5882 width = style.width;
5883 minWidth = style.minWidth;
5884 maxWidth = style.maxWidth;
5885
5886 // Put in the new values to get a computed value out
5887 style.minWidth = style.maxWidth = style.width = ret;
5888 ret = computed.width;
5889
5890 // Revert the changed values
5891 style.width = width;
5892 style.minWidth = minWidth;
5893 style.maxWidth = maxWidth;
5894 }
5895 }
5896
5897 return ret !== undefined ?
5898
5899 // Support: IE9-11+
5900 // IE returns zIndex value as an integer.
5901 ret + "" :
5902 ret;
5903}
5904
5905
5906function addGetHookIf( conditionFn, hookFn ) {
5907
5908 // Define the hook, we'll check on the first run if it's really needed.
5909 return {
5910 get: function() {
5911 if ( conditionFn() ) {
5912
5913 // Hook not needed (or it's not possible to use it due
5914 // to missing dependency), remove it.
5915 delete this.get;
5916 return;
5917 }
5918
5919 // Hook needed; redefine it so that the support test is not executed again.
5920 return ( this.get = hookFn ).apply( this, arguments );
5921 }
5922 };
5923}
5924
5925
5926var
5927
5928 // Swappable if display is none or starts with table
5929 // except "table", "table-cell", or "table-caption"
5930 // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
5931 rdisplayswap = /^(none|table(?!-c[ea]).+)/,
5932
5933 cssShow = { position: "absolute", visibility: "hidden", display: "block" },
5934 cssNormalTransform = {
5935 letterSpacing: "0",
5936 fontWeight: "400"
5937 },
5938
5939 cssPrefixes = [ "Webkit", "O", "Moz", "ms" ],
5940 emptyStyle = document.createElement( "div" ).style;
5941
5942// Return a css property mapped to a potentially vendor prefixed property
5943function vendorPropName( name ) {
5944
5945 // Shortcut for names that are not vendor prefixed
5946 if ( name in emptyStyle ) {
5947 return name;
5948 }
5949
5950 // Check for vendor prefixed names
5951 var capName = name[ 0 ].toUpperCase() + name.slice( 1 ),
5952 i = cssPrefixes.length;
5953
5954 while ( i-- ) {
5955 name = cssPrefixes[ i ] + capName;
5956 if ( name in emptyStyle ) {
5957 return name;
5958 }
5959 }
5960}
5961
5962function setPositiveNumber( elem, value, subtract ) {
5963
5964 // Any relative (+/-) values have already been
5965 // normalized at this point
5966 var matches = rcssNum.exec( value );
5967 return matches ?
5968
5969 // Guard against undefined "subtract", e.g., when used as in cssHooks
5970 Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) :
5971 value;
5972}
5973
5974function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {
5975 var i = extra === ( isBorderBox ? "border" : "content" ) ?
5976
5977 // If we already have the right measurement, avoid augmentation
5978 4 :
5979
5980 // Otherwise initialize for horizontal or vertical properties
5981 name === "width" ? 1 : 0,
5982
5983 val = 0;
5984
5985 for ( ; i < 4; i += 2 ) {
5986
5987 // Both box models exclude margin, so add it if we want it
5988 if ( extra === "margin" ) {
5989 val += jQuery.css( elem, extra + cssExpand[ i ], true, styles );
5990 }
5991
5992 if ( isBorderBox ) {
5993
5994 // border-box includes padding, so remove it if we want content
5995 if ( extra === "content" ) {
5996 val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
5997 }
5998
5999 // At this point, extra isn't border nor margin, so remove border
6000 if ( extra !== "margin" ) {
6001 val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
6002 }
6003 } else {
6004
6005 // At this point, extra isn't content, so add padding
6006 val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
6007
6008 // At this point, extra isn't content nor padding, so add border
6009 if ( extra !== "padding" ) {
6010 val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
6011 }
6012 }
6013 }
6014
6015 return val;
6016}
6017
6018function getWidthOrHeight( elem, name, extra ) {
6019
6020 // Start with offset property, which is equivalent to the border-box value
6021 var valueIsBorderBox = true,
6022 val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
6023 styles = getStyles( elem ),
6024 isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box";
6025
6026 // Some non-html elements return undefined for offsetWidth, so check for null/undefined
6027 // svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285
6028 // MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668
6029 if ( val <= 0 || val == null ) {
6030
6031 // Fall back to computed then uncomputed css if necessary
6032 val = curCSS( elem, name, styles );
6033 if ( val < 0 || val == null ) {
6034 val = elem.style[ name ];
6035 }
6036
6037 // Computed unit is not pixels. Stop here and return.
6038 if ( rnumnonpx.test( val ) ) {
6039 return val;
6040 }
6041
6042 // Check for style in case a browser which returns unreliable values
6043 // for getComputedStyle silently falls back to the reliable elem.style
6044 valueIsBorderBox = isBorderBox &&
6045 ( support.boxSizingReliable() || val === elem.style[ name ] );
6046
6047 // Normalize "", auto, and prepare for extra
6048 val = parseFloat( val ) || 0;
6049 }
6050
6051 // Use the active box-sizing model to add/subtract irrelevant styles
6052 return ( val +
6053 augmentWidthOrHeight(
6054 elem,
6055 name,
6056 extra || ( isBorderBox ? "border" : "content" ),
6057 valueIsBorderBox,
6058 styles
6059 )
6060 ) + "px";
6061}
6062
6063function showHide( elements, show ) {
6064 var display, elem, hidden,
6065 values = [],
6066 index = 0,
6067 length = elements.length;
6068
6069 for ( ; index < length; index++ ) {
6070 elem = elements[ index ];
6071 if ( !elem.style ) {
6072 continue;
6073 }
6074
6075 values[ index ] = dataPriv.get( elem, "olddisplay" );
6076 display = elem.style.display;
6077 if ( show ) {
6078
6079 // Reset the inline display of this element to learn if it is
6080 // being hidden by cascaded rules or not
6081 if ( !values[ index ] && display === "none" ) {
6082 elem.style.display = "";
6083 }
6084
6085 // Set elements which have been overridden with display: none
6086 // in a stylesheet to whatever the default browser style is
6087 // for such an element
6088 if ( elem.style.display === "" && isHidden( elem ) ) {
6089 values[ index ] = dataPriv.access(
6090 elem,
6091 "olddisplay",
6092 defaultDisplay( elem.nodeName )
6093 );
6094 }
6095 } else {
6096 hidden = isHidden( elem );
6097
6098 if ( display !== "none" || !hidden ) {
6099 dataPriv.set(
6100 elem,
6101 "olddisplay",
6102 hidden ? display : jQuery.css( elem, "display" )
6103 );
6104 }
6105 }
6106 }
6107
6108 // Set the display of most of the elements in a second loop
6109 // to avoid the constant reflow
6110 for ( index = 0; index < length; index++ ) {
6111 elem = elements[ index ];
6112 if ( !elem.style ) {
6113 continue;
6114 }
6115 if ( !show || elem.style.display === "none" || elem.style.display === "" ) {
6116 elem.style.display = show ? values[ index ] || "" : "none";
6117 }
6118 }
6119
6120 return elements;
6121}
6122
6123jQuery.extend( {
6124
6125 // Add in style property hooks for overriding the default
6126 // behavior of getting and setting a style property
6127 cssHooks: {
6128 opacity: {
6129 get: function( elem, computed ) {
6130 if ( computed ) {
6131
6132 // We should always get a number back from opacity
6133 var ret = curCSS( elem, "opacity" );
6134 return ret === "" ? "1" : ret;
6135 }
6136 }
6137 }
6138 },
6139
6140 // Don't automatically add "px" to these possibly-unitless properties
6141 cssNumber: {
6142 "animationIterationCount": true,
6143 "columnCount": true,
6144 "fillOpacity": true,
6145 "flexGrow": true,
6146 "flexShrink": true,
6147 "fontWeight": true,
6148 "lineHeight": true,
6149 "opacity": true,
6150 "order": true,
6151 "orphans": true,
6152 "widows": true,
6153 "zIndex": true,
6154 "zoom": true
6155 },
6156
6157 // Add in properties whose names you wish to fix before
6158 // setting or getting the value
6159 cssProps: {
6160 "float": "cssFloat"
6161 },
6162
6163 // Get and set the style property on a DOM Node
6164 style: function( elem, name, value, extra ) {
6165
6166 // Don't set styles on text and comment nodes
6167 if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
6168 return;
6169 }
6170
6171 // Make sure that we're working with the right name
6172 var ret, type, hooks,
6173 origName = jQuery.camelCase( name ),
6174 style = elem.style;
6175
6176 name = jQuery.cssProps[ origName ] ||
6177 ( jQuery.cssProps[ origName ] = vendorPropName( origName ) || origName );
6178
6179 // Gets hook for the prefixed version, then unprefixed version
6180 hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
6181
6182 // Check if we're setting a value
6183 if ( value !== undefined ) {
6184 type = typeof value;
6185
6186 // Convert "+=" or "-=" to relative numbers (#7345)
6187 if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) {
6188 value = adjustCSS( elem, name, ret );
6189
6190 // Fixes bug #9237
6191 type = "number";
6192 }
6193
6194 // Make sure that null and NaN values aren't set (#7116)
6195 if ( value == null || value !== value ) {
6196 return;
6197 }
6198
6199 // If a number was passed in, add the unit (except for certain CSS properties)
6200 if ( type === "number" ) {
6201 value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" );
6202 }
6203
6204 // Support: IE9-11+
6205 // background-* props affect original clone's values
6206 if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) {
6207 style[ name ] = "inherit";
6208 }
6209
6210 // If a hook was provided, use that value, otherwise just set the specified value
6211 if ( !hooks || !( "set" in hooks ) ||
6212 ( value = hooks.set( elem, value, extra ) ) !== undefined ) {
6213
6214 style[ name ] = value;
6215 }
6216
6217 } else {
6218
6219 // If a hook was provided get the non-computed value from there
6220 if ( hooks && "get" in hooks &&
6221 ( ret = hooks.get( elem, false, extra ) ) !== undefined ) {
6222
6223 return ret;
6224 }
6225
6226 // Otherwise just get the value from the style object
6227 return style[ name ];
6228 }
6229 },
6230
6231 css: function( elem, name, extra, styles ) {
6232 var val, num, hooks,
6233 origName = jQuery.camelCase( name );
6234
6235 // Make sure that we're working with the right name
6236 name = jQuery.cssProps[ origName ] ||
6237 ( jQuery.cssProps[ origName ] = vendorPropName( origName ) || origName );
6238
6239 // Try prefixed name followed by the unprefixed name
6240 hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
6241
6242 // If a hook was provided get the computed value from there
6243 if ( hooks && "get" in hooks ) {
6244 val = hooks.get( elem, true, extra );
6245 }
6246
6247 // Otherwise, if a way to get the computed value exists, use that
6248 if ( val === undefined ) {
6249 val = curCSS( elem, name, styles );
6250 }
6251
6252 // Convert "normal" to computed value
6253 if ( val === "normal" && name in cssNormalTransform ) {
6254 val = cssNormalTransform[ name ];
6255 }
6256
6257 // Make numeric if forced or a qualifier was provided and val looks numeric
6258 if ( extra === "" || extra ) {
6259 num = parseFloat( val );
6260 return extra === true || isFinite( num ) ? num || 0 : val;
6261 }
6262 return val;
6263 }
6264} );
6265
6266jQuery.each( [ "height", "width" ], function( i, name ) {
6267 jQuery.cssHooks[ name ] = {
6268 get: function( elem, computed, extra ) {
6269 if ( computed ) {
6270
6271 // Certain elements can have dimension info if we invisibly show them
6272 // but it must have a current display style that would benefit
6273 return rdisplayswap.test( jQuery.css( elem, "display" ) ) &&
6274 elem.offsetWidth === 0 ?
6275 swap( elem, cssShow, function() {
6276 return getWidthOrHeight( elem, name, extra );
6277 } ) :
6278 getWidthOrHeight( elem, name, extra );
6279 }
6280 },
6281
6282 set: function( elem, value, extra ) {
6283 var matches,
6284 styles = extra && getStyles( elem ),
6285 subtract = extra && augmentWidthOrHeight(
6286 elem,
6287 name,
6288 extra,
6289 jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
6290 styles
6291 );
6292
6293 // Convert to pixels if value adjustment is needed
6294 if ( subtract && ( matches = rcssNum.exec( value ) ) &&
6295 ( matches[ 3 ] || "px" ) !== "px" ) {
6296
6297 elem.style[ name ] = value;
6298 value = jQuery.css( elem, name );
6299 }
6300
6301 return setPositiveNumber( elem, value, subtract );
6302 }
6303 };
6304} );
6305
6306jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft,
6307 function( elem, computed ) {
6308 if ( computed ) {
6309 return ( parseFloat( curCSS( elem, "marginLeft" ) ) ||
6310 elem.getBoundingClientRect().left -
6311 swap( elem, { marginLeft: 0 }, function() {
6312 return elem.getBoundingClientRect().left;
6313 } )
6314 ) + "px";
6315 }
6316 }
6317);
6318
6319// Support: Android 2.3
6320jQuery.cssHooks.marginRight = addGetHookIf( support.reliableMarginRight,
6321 function( elem, computed ) {
6322 if ( computed ) {
6323 return swap( elem, { "display": "inline-block" },
6324 curCSS, [ elem, "marginRight" ] );
6325 }
6326 }
6327);
6328
6329// These hooks are used by animate to expand properties
6330jQuery.each( {
6331 margin: "",
6332 padding: "",
6333 border: "Width"
6334}, function( prefix, suffix ) {
6335 jQuery.cssHooks[ prefix + suffix ] = {
6336 expand: function( value ) {
6337 var i = 0,
6338 expanded = {},
6339
6340 // Assumes a single number if not a string
6341 parts = typeof value === "string" ? value.split( " " ) : [ value ];
6342
6343 for ( ; i < 4; i++ ) {
6344 expanded[ prefix + cssExpand[ i ] + suffix ] =
6345 parts[ i ] || parts[ i - 2 ] || parts[ 0 ];
6346 }
6347
6348 return expanded;
6349 }
6350 };
6351
6352 if ( !rmargin.test( prefix ) ) {
6353 jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;
6354 }
6355} );
6356
6357jQuery.fn.extend( {
6358 css: function( name, value ) {
6359 return access( this, function( elem, name, value ) {
6360 var styles, len,
6361 map = {},
6362 i = 0;
6363
6364 if ( jQuery.isArray( name ) ) {
6365 styles = getStyles( elem );
6366 len = name.length;
6367
6368 for ( ; i < len; i++ ) {
6369 map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );
6370 }
6371
6372 return map;
6373 }
6374
6375 return value !== undefined ?
6376 jQuery.style( elem, name, value ) :
6377 jQuery.css( elem, name );
6378 }, name, value, arguments.length > 1 );
6379 },
6380 show: function() {
6381 return showHide( this, true );
6382 },
6383 hide: function() {
6384 return showHide( this );
6385 },
6386 toggle: function( state ) {
6387 if ( typeof state === "boolean" ) {
6388 return state ? this.show() : this.hide();
6389 }
6390
6391 return this.each( function() {
6392 if ( isHidden( this ) ) {
6393 jQuery( this ).show();
6394 } else {
6395 jQuery( this ).hide();
6396 }
6397 } );
6398 }
6399} );
6400
6401
6402function Tween( elem, options, prop, end, easing ) {
6403 return new Tween.prototype.init( elem, options, prop, end, easing );
6404}
6405jQuery.Tween = Tween;
6406
6407Tween.prototype = {
6408 constructor: Tween,
6409 init: function( elem, options, prop, end, easing, unit ) {
6410 this.elem = elem;
6411 this.prop = prop;
6412 this.easing = easing || jQuery.easing._default;
6413 this.options = options;
6414 this.start = this.now = this.cur();
6415 this.end = end;
6416 this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" );
6417 },
6418 cur: function() {
6419 var hooks = Tween.propHooks[ this.prop ];
6420
6421 return hooks && hooks.get ?
6422 hooks.get( this ) :
6423 Tween.propHooks._default.get( this );
6424 },
6425 run: function( percent ) {
6426 var eased,
6427 hooks = Tween.propHooks[ this.prop ];
6428
6429 if ( this.options.duration ) {
6430 this.pos = eased = jQuery.easing[ this.easing ](
6431 percent, this.options.duration * percent, 0, 1, this.options.duration
6432 );
6433 } else {
6434 this.pos = eased = percent;
6435 }
6436 this.now = ( this.end - this.start ) * eased + this.start;
6437
6438 if ( this.options.step ) {
6439 this.options.step.call( this.elem, this.now, this );
6440 }
6441
6442 if ( hooks && hooks.set ) {
6443 hooks.set( this );
6444 } else {
6445 Tween.propHooks._default.set( this );
6446 }
6447 return this;
6448 }
6449};
6450
6451Tween.prototype.init.prototype = Tween.prototype;
6452
6453Tween.propHooks = {
6454 _default: {
6455 get: function( tween ) {
6456 var result;
6457
6458 // Use a property on the element directly when it is not a DOM element,
6459 // or when there is no matching style property that exists.
6460 if ( tween.elem.nodeType !== 1 ||
6461 tween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) {
6462 return tween.elem[ tween.prop ];
6463 }
6464
6465 // Passing an empty string as a 3rd parameter to .css will automatically
6466 // attempt a parseFloat and fallback to a string if the parse fails.
6467 // Simple values such as "10px" are parsed to Float;
6468 // complex values such as "rotate(1rad)" are returned as-is.
6469 result = jQuery.css( tween.elem, tween.prop, "" );
6470
6471 // Empty strings, null, undefined and "auto" are converted to 0.
6472 return !result || result === "auto" ? 0 : result;
6473 },
6474 set: function( tween ) {
6475
6476 // Use step hook for back compat.
6477 // Use cssHook if its there.
6478 // Use .style if available and use plain properties where available.
6479 if ( jQuery.fx.step[ tween.prop ] ) {
6480 jQuery.fx.step[ tween.prop ]( tween );
6481 } else if ( tween.elem.nodeType === 1 &&
6482 ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null ||
6483 jQuery.cssHooks[ tween.prop ] ) ) {
6484 jQuery.style( tween.elem, tween.prop, tween.now + tween.unit );
6485 } else {
6486 tween.elem[ tween.prop ] = tween.now;
6487 }
6488 }
6489 }
6490};
6491
6492// Support: IE9
6493// Panic based approach to setting things on disconnected nodes
6494Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {
6495 set: function( tween ) {
6496 if ( tween.elem.nodeType && tween.elem.parentNode ) {
6497 tween.elem[ tween.prop ] = tween.now;
6498 }
6499 }
6500};
6501
6502jQuery.easing = {
6503 linear: function( p ) {
6504 return p;
6505 },
6506 swing: function( p ) {
6507 return 0.5 - Math.cos( p * Math.PI ) / 2;
6508 },
6509 _default: "swing"
6510};
6511
6512jQuery.fx = Tween.prototype.init;
6513
6514// Back Compat <1.8 extension point
6515jQuery.fx.step = {};
6516
6517
6518
6519
6520var
6521 fxNow, timerId,
6522 rfxtypes = /^(?:toggle|show|hide)$/,
6523 rrun = /queueHooks$/;
6524
6525// Animations created synchronously will run synchronously
6526function createFxNow() {
6527 window.setTimeout( function() {
6528 fxNow = undefined;
6529 } );
6530 return ( fxNow = jQuery.now() );
6531}
6532
6533// Generate parameters to create a standard animation
6534function genFx( type, includeWidth ) {
6535 var which,
6536 i = 0,
6537 attrs = { height: type };
6538
6539 // If we include width, step value is 1 to do all cssExpand values,
6540 // otherwise step value is 2 to skip over Left and Right
6541 includeWidth = includeWidth ? 1 : 0;
6542 for ( ; i < 4 ; i += 2 - includeWidth ) {
6543 which = cssExpand[ i ];
6544 attrs[ "margin" + which ] = attrs[ "padding" + which ] = type;
6545 }
6546
6547 if ( includeWidth ) {
6548 attrs.opacity = attrs.width = type;
6549 }
6550
6551 return attrs;
6552}
6553
6554function createTween( value, prop, animation ) {
6555 var tween,
6556 collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ),
6557 index = 0,
6558 length = collection.length;
6559 for ( ; index < length; index++ ) {
6560 if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) {
6561
6562 // We're done with this property
6563 return tween;
6564 }
6565 }
6566}
6567
6568function defaultPrefilter( elem, props, opts ) {
6569 /* jshint validthis: true */
6570 var prop, value, toggle, tween, hooks, oldfire, display, checkDisplay,
6571 anim = this,
6572 orig = {},
6573 style = elem.style,
6574 hidden = elem.nodeType && isHidden( elem ),
6575 dataShow = dataPriv.get( elem, "fxshow" );
6576
6577 // Handle queue: false promises
6578 if ( !opts.queue ) {
6579 hooks = jQuery._queueHooks( elem, "fx" );
6580 if ( hooks.unqueued == null ) {
6581 hooks.unqueued = 0;
6582 oldfire = hooks.empty.fire;
6583 hooks.empty.fire = function() {
6584 if ( !hooks.unqueued ) {
6585 oldfire();
6586 }
6587 };
6588 }
6589 hooks.unqueued++;
6590
6591 anim.always( function() {
6592
6593 // Ensure the complete handler is called before this completes
6594 anim.always( function() {
6595 hooks.unqueued--;
6596 if ( !jQuery.queue( elem, "fx" ).length ) {
6597 hooks.empty.fire();
6598 }
6599 } );
6600 } );
6601 }
6602
6603 // Height/width overflow pass
6604 if ( elem.nodeType === 1 && ( "height" in props || "width" in props ) ) {
6605
6606 // Make sure that nothing sneaks out
6607 // Record all 3 overflow attributes because IE9-10 do not
6608 // change the overflow attribute when overflowX and
6609 // overflowY are set to the same value
6610 opts.overflow = [ style.overflow, style.overflowX, style.overflowY ];
6611
6612 // Set display property to inline-block for height/width
6613 // animations on inline elements that are having width/height animated
6614 display = jQuery.css( elem, "display" );
6615
6616 // Test default display if display is currently "none"
6617 checkDisplay = display === "none" ?
6618 dataPriv.get( elem, "olddisplay" ) || defaultDisplay( elem.nodeName ) : display;
6619
6620 if ( checkDisplay === "inline" && jQuery.css( elem, "float" ) === "none" ) {
6621 style.display = "inline-block";
6622 }
6623 }
6624
6625 if ( opts.overflow ) {
6626 style.overflow = "hidden";
6627 anim.always( function() {
6628 style.overflow = opts.overflow[ 0 ];
6629 style.overflowX = opts.overflow[ 1 ];
6630 style.overflowY = opts.overflow[ 2 ];
6631 } );
6632 }
6633
6634 // show/hide pass
6635 for ( prop in props ) {
6636 value = props[ prop ];
6637 if ( rfxtypes.exec( value ) ) {
6638 delete props[ prop ];
6639 toggle = toggle || value === "toggle";
6640 if ( value === ( hidden ? "hide" : "show" ) ) {
6641
6642 // If there is dataShow left over from a stopped hide or show
6643 // and we are going to proceed with show, we should pretend to be hidden
6644 if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) {
6645 hidden = true;
6646 } else {
6647 continue;
6648 }
6649 }
6650 orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop );
6651
6652 // Any non-fx value stops us from restoring the original display value
6653 } else {
6654 display = undefined;
6655 }
6656 }
6657
6658 if ( !jQuery.isEmptyObject( orig ) ) {
6659 if ( dataShow ) {
6660 if ( "hidden" in dataShow ) {
6661 hidden = dataShow.hidden;
6662 }
6663 } else {
6664 dataShow = dataPriv.access( elem, "fxshow", {} );
6665 }
6666
6667 // Store state if its toggle - enables .stop().toggle() to "reverse"
6668 if ( toggle ) {
6669 dataShow.hidden = !hidden;
6670 }
6671 if ( hidden ) {
6672 jQuery( elem ).show();
6673 } else {
6674 anim.done( function() {
6675 jQuery( elem ).hide();
6676 } );
6677 }
6678 anim.done( function() {
6679 var prop;
6680
6681 dataPriv.remove( elem, "fxshow" );
6682 for ( prop in orig ) {
6683 jQuery.style( elem, prop, orig[ prop ] );
6684 }
6685 } );
6686 for ( prop in orig ) {
6687 tween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim );
6688
6689 if ( !( prop in dataShow ) ) {
6690 dataShow[ prop ] = tween.start;
6691 if ( hidden ) {
6692 tween.end = tween.start;
6693 tween.start = prop === "width" || prop === "height" ? 1 : 0;
6694 }
6695 }
6696 }
6697
6698 // If this is a noop like .hide().hide(), restore an overwritten display value
6699 } else if ( ( display === "none" ? defaultDisplay( elem.nodeName ) : display ) === "inline" ) {
6700 style.display = display;
6701 }
6702}
6703
6704function propFilter( props, specialEasing ) {
6705 var index, name, easing, value, hooks;
6706
6707 // camelCase, specialEasing and expand cssHook pass
6708 for ( index in props ) {
6709 name = jQuery.camelCase( index );
6710 easing = specialEasing[ name ];
6711 value = props[ index ];
6712 if ( jQuery.isArray( value ) ) {
6713 easing = value[ 1 ];
6714 value = props[ index ] = value[ 0 ];
6715 }
6716
6717 if ( index !== name ) {
6718 props[ name ] = value;
6719 delete props[ index ];
6720 }
6721
6722 hooks = jQuery.cssHooks[ name ];
6723 if ( hooks && "expand" in hooks ) {
6724 value = hooks.expand( value );
6725 delete props[ name ];
6726
6727 // Not quite $.extend, this won't overwrite existing keys.
6728 // Reusing 'index' because we have the correct "name"
6729 for ( index in value ) {
6730 if ( !( index in props ) ) {
6731 props[ index ] = value[ index ];
6732 specialEasing[ index ] = easing;
6733 }
6734 }
6735 } else {
6736 specialEasing[ name ] = easing;
6737 }
6738 }
6739}
6740
6741function Animation( elem, properties, options ) {
6742 var result,
6743 stopped,
6744 index = 0,
6745 length = Animation.prefilters.length,
6746 deferred = jQuery.Deferred().always( function() {
6747
6748 // Don't match elem in the :animated selector
6749 delete tick.elem;
6750 } ),
6751 tick = function() {
6752 if ( stopped ) {
6753 return false;
6754 }
6755 var currentTime = fxNow || createFxNow(),
6756 remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
6757
6758 // Support: Android 2.3
6759 temp = remaining / animation.duration || 0,
6760 percent = 1 - temp,
6761 index = 0,
6762 length = animation.tweens.length;
6763
6764 for ( ; index < length ; index++ ) {
6765 animation.tweens[ index ].run( percent );
6766 }
6767
6768 deferred.notifyWith( elem, [ animation, percent, remaining ] );
6769
6770 if ( percent < 1 && length ) {
6771 return remaining;
6772 } else {
6773 deferred.resolveWith( elem, [ animation ] );
6774 return false;
6775 }
6776 },
6777 animation = deferred.promise( {
6778 elem: elem,
6779 props: jQuery.extend( {}, properties ),
6780 opts: jQuery.extend( true, {
6781 specialEasing: {},
6782 easing: jQuery.easing._default
6783 }, options ),
6784 originalProperties: properties,
6785 originalOptions: options,
6786 startTime: fxNow || createFxNow(),
6787 duration: options.duration,
6788 tweens: [],
6789 createTween: function( prop, end ) {
6790 var tween = jQuery.Tween( elem, animation.opts, prop, end,
6791 animation.opts.specialEasing[ prop ] || animation.opts.easing );
6792 animation.tweens.push( tween );
6793 return tween;
6794 },
6795 stop: function( gotoEnd ) {
6796 var index = 0,
6797
6798 // If we are going to the end, we want to run all the tweens
6799 // otherwise we skip this part
6800 length = gotoEnd ? animation.tweens.length : 0;
6801 if ( stopped ) {
6802 return this;
6803 }
6804 stopped = true;
6805 for ( ; index < length ; index++ ) {
6806 animation.tweens[ index ].run( 1 );
6807 }
6808
6809 // Resolve when we played the last frame; otherwise, reject
6810 if ( gotoEnd ) {
6811 deferred.notifyWith( elem, [ animation, 1, 0 ] );
6812 deferred.resolveWith( elem, [ animation, gotoEnd ] );
6813 } else {
6814 deferred.rejectWith( elem, [ animation, gotoEnd ] );
6815 }
6816 return this;
6817 }
6818 } ),
6819 props = animation.props;
6820
6821 propFilter( props, animation.opts.specialEasing );
6822
6823 for ( ; index < length ; index++ ) {
6824 result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts );
6825 if ( result ) {
6826 if ( jQuery.isFunction( result.stop ) ) {
6827 jQuery._queueHooks( animation.elem, animation.opts.queue ).stop =
6828 jQuery.proxy( result.stop, result );
6829 }
6830 return result;
6831 }
6832 }
6833
6834 jQuery.map( props, createTween, animation );
6835
6836 if ( jQuery.isFunction( animation.opts.start ) ) {
6837 animation.opts.start.call( elem, animation );
6838 }
6839
6840 jQuery.fx.timer(
6841 jQuery.extend( tick, {
6842 elem: elem,
6843 anim: animation,
6844 queue: animation.opts.queue
6845 } )
6846 );
6847
6848 // attach callbacks from options
6849 return animation.progress( animation.opts.progress )
6850 .done( animation.opts.done, animation.opts.complete )
6851 .fail( animation.opts.fail )
6852 .always( animation.opts.always );
6853}
6854
6855jQuery.Animation = jQuery.extend( Animation, {
6856 tweeners: {
6857 "*": [ function( prop, value ) {
6858 var tween = this.createTween( prop, value );
6859 adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween );
6860 return tween;
6861 } ]
6862 },
6863
6864 tweener: function( props, callback ) {
6865 if ( jQuery.isFunction( props ) ) {
6866 callback = props;
6867 props = [ "*" ];
6868 } else {
6869 props = props.match( rnotwhite );
6870 }
6871
6872 var prop,
6873 index = 0,
6874 length = props.length;
6875
6876 for ( ; index < length ; index++ ) {
6877 prop = props[ index ];
6878 Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || [];
6879 Animation.tweeners[ prop ].unshift( callback );
6880 }
6881 },
6882
6883 prefilters: [ defaultPrefilter ],
6884
6885 prefilter: function( callback, prepend ) {
6886 if ( prepend ) {
6887 Animation.prefilters.unshift( callback );
6888 } else {
6889 Animation.prefilters.push( callback );
6890 }
6891 }
6892} );
6893
6894jQuery.speed = function( speed, easing, fn ) {
6895 var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
6896 complete: fn || !fn && easing ||
6897 jQuery.isFunction( speed ) && speed,
6898 duration: speed,
6899 easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing
6900 };
6901
6902 opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ?
6903 opt.duration : opt.duration in jQuery.fx.speeds ?
6904 jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;
6905
6906 // Normalize opt.queue - true/undefined/null -> "fx"
6907 if ( opt.queue == null || opt.queue === true ) {
6908 opt.queue = "fx";
6909 }
6910
6911 // Queueing
6912 opt.old = opt.complete;
6913
6914 opt.complete = function() {
6915 if ( jQuery.isFunction( opt.old ) ) {
6916 opt.old.call( this );
6917 }
6918
6919 if ( opt.queue ) {
6920 jQuery.dequeue( this, opt.queue );
6921 }
6922 };
6923
6924 return opt;
6925};
6926
6927jQuery.fn.extend( {
6928 fadeTo: function( speed, to, easing, callback ) {
6929
6930 // Show any hidden elements after setting opacity to 0
6931 return this.filter( isHidden ).css( "opacity", 0 ).show()
6932
6933 // Animate to the value specified
6934 .end().animate( { opacity: to }, speed, easing, callback );
6935 },
6936 animate: function( prop, speed, easing, callback ) {
6937 var empty = jQuery.isEmptyObject( prop ),
6938 optall = jQuery.speed( speed, easing, callback ),
6939 doAnimation = function() {
6940
6941 // Operate on a copy of prop so per-property easing won't be lost
6942 var anim = Animation( this, jQuery.extend( {}, prop ), optall );
6943
6944 // Empty animations, or finishing resolves immediately
6945 if ( empty || dataPriv.get( this, "finish" ) ) {
6946 anim.stop( true );
6947 }
6948 };
6949 doAnimation.finish = doAnimation;
6950
6951 return empty || optall.queue === false ?
6952 this.each( doAnimation ) :
6953 this.queue( optall.queue, doAnimation );
6954 },
6955 stop: function( type, clearQueue, gotoEnd ) {
6956 var stopQueue = function( hooks ) {
6957 var stop = hooks.stop;
6958 delete hooks.stop;
6959 stop( gotoEnd );
6960 };
6961
6962 if ( typeof type !== "string" ) {
6963 gotoEnd = clearQueue;
6964 clearQueue = type;
6965 type = undefined;
6966 }
6967 if ( clearQueue && type !== false ) {
6968 this.queue( type || "fx", [] );
6969 }
6970
6971 return this.each( function() {
6972 var dequeue = true,
6973 index = type != null && type + "queueHooks",
6974 timers = jQuery.timers,
6975 data = dataPriv.get( this );
6976
6977 if ( index ) {
6978 if ( data[ index ] && data[ index ].stop ) {
6979 stopQueue( data[ index ] );
6980 }
6981 } else {
6982 for ( index in data ) {
6983 if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {
6984 stopQueue( data[ index ] );
6985 }
6986 }
6987 }
6988
6989 for ( index = timers.length; index--; ) {
6990 if ( timers[ index ].elem === this &&
6991 ( type == null || timers[ index ].queue === type ) ) {
6992
6993 timers[ index ].anim.stop( gotoEnd );
6994 dequeue = false;
6995 timers.splice( index, 1 );
6996 }
6997 }
6998
6999 // Start the next in the queue if the last step wasn't forced.
7000 // Timers currently will call their complete callbacks, which
7001 // will dequeue but only if they were gotoEnd.
7002 if ( dequeue || !gotoEnd ) {
7003 jQuery.dequeue( this, type );
7004 }
7005 } );
7006 },
7007 finish: function( type ) {
7008 if ( type !== false ) {
7009 type = type || "fx";
7010 }
7011 return this.each( function() {
7012 var index,
7013 data = dataPriv.get( this ),
7014 queue = data[ type + "queue" ],
7015 hooks = data[ type + "queueHooks" ],
7016 timers = jQuery.timers,
7017 length = queue ? queue.length : 0;
7018
7019 // Enable finishing flag on private data
7020 data.finish = true;
7021
7022 // Empty the queue first
7023 jQuery.queue( this, type, [] );
7024
7025 if ( hooks && hooks.stop ) {
7026 hooks.stop.call( this, true );
7027 }
7028
7029 // Look for any active animations, and finish them
7030 for ( index = timers.length; index--; ) {
7031 if ( timers[ index ].elem === this && timers[ index ].queue === type ) {
7032 timers[ index ].anim.stop( true );
7033 timers.splice( index, 1 );
7034 }
7035 }
7036
7037 // Look for any animations in the old queue and finish them
7038 for ( index = 0; index < length; index++ ) {
7039 if ( queue[ index ] && queue[ index ].finish ) {
7040 queue[ index ].finish.call( this );
7041 }
7042 }
7043
7044 // Turn off finishing flag
7045 delete data.finish;
7046 } );
7047 }
7048} );
7049
7050jQuery.each( [ "toggle", "show", "hide" ], function( i, name ) {
7051 var cssFn = jQuery.fn[ name ];
7052 jQuery.fn[ name ] = function( speed, easing, callback ) {
7053 return speed == null || typeof speed === "boolean" ?
7054 cssFn.apply( this, arguments ) :
7055 this.animate( genFx( name, true ), speed, easing, callback );
7056 };
7057} );
7058
7059// Generate shortcuts for custom animations
7060jQuery.each( {
7061 slideDown: genFx( "show" ),
7062 slideUp: genFx( "hide" ),
7063 slideToggle: genFx( "toggle" ),
7064 fadeIn: { opacity: "show" },
7065 fadeOut: { opacity: "hide" },
7066 fadeToggle: { opacity: "toggle" }
7067}, function( name, props ) {
7068 jQuery.fn[ name ] = function( speed, easing, callback ) {
7069 return this.animate( props, speed, easing, callback );
7070 };
7071} );
7072
7073jQuery.timers = [];
7074jQuery.fx.tick = function() {
7075 var timer,
7076 i = 0,
7077 timers = jQuery.timers;
7078
7079 fxNow = jQuery.now();
7080
7081 for ( ; i < timers.length; i++ ) {
7082 timer = timers[ i ];
7083
7084 // Checks the timer has not already been removed
7085 if ( !timer() && timers[ i ] === timer ) {
7086 timers.splice( i--, 1 );
7087 }
7088 }
7089
7090 if ( !timers.length ) {
7091 jQuery.fx.stop();
7092 }
7093 fxNow = undefined;
7094};
7095
7096jQuery.fx.timer = function( timer ) {
7097 jQuery.timers.push( timer );
7098 if ( timer() ) {
7099 jQuery.fx.start();
7100 } else {
7101 jQuery.timers.pop();
7102 }
7103};
7104
7105jQuery.fx.interval = 13;
7106jQuery.fx.start = function() {
7107 if ( !timerId ) {
7108 timerId = window.setInterval( jQuery.fx.tick, jQuery.fx.interval );
7109 }
7110};
7111
7112jQuery.fx.stop = function() {
7113 window.clearInterval( timerId );
7114
7115 timerId = null;
7116};
7117
7118jQuery.fx.speeds = {
7119 slow: 600,
7120 fast: 200,
7121
7122 // Default speed
7123 _default: 400
7124};
7125
7126
7127// Based off of the plugin by Clint Helfers, with permission.
7128// http://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/
7129jQuery.fn.delay = function( time, type ) {
7130 time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
7131 type = type || "fx";
7132
7133 return this.queue( type, function( next, hooks ) {
7134 var timeout = window.setTimeout( next, time );
7135 hooks.stop = function() {
7136 window.clearTimeout( timeout );
7137 };
7138 } );
7139};
7140
7141
7142( function() {
7143 var input = document.createElement( "input" ),
7144 select = document.createElement( "select" ),
7145 opt = select.appendChild( document.createElement( "option" ) );
7146
7147 input.type = "checkbox";
7148
7149 // Support: iOS<=5.1, Android<=4.2+
7150 // Default value for a checkbox should be "on"
7151 support.checkOn = input.value !== "";
7152
7153 // Support: IE<=11+
7154 // Must access selectedIndex to make default options select
7155 support.optSelected = opt.selected;
7156
7157 // Support: Android<=2.3
7158 // Options inside disabled selects are incorrectly marked as disabled
7159 select.disabled = true;
7160 support.optDisabled = !opt.disabled;
7161
7162 // Support: IE<=11+
7163 // An input loses its value after becoming a radio
7164 input = document.createElement( "input" );
7165 input.value = "t";
7166 input.type = "radio";
7167 support.radioValue = input.value === "t";
7168} )();
7169
7170
7171var boolHook,
7172 attrHandle = jQuery.expr.attrHandle;
7173
7174jQuery.fn.extend( {
7175 attr: function( name, value ) {
7176 return access( this, jQuery.attr, name, value, arguments.length > 1 );
7177 },
7178
7179 removeAttr: function( name ) {
7180 return this.each( function() {
7181 jQuery.removeAttr( this, name );
7182 } );
7183 }
7184} );
7185
7186jQuery.extend( {
7187 attr: function( elem, name, value ) {
7188 var ret, hooks,
7189 nType = elem.nodeType;
7190
7191 // Don't get/set attributes on text, comment and attribute nodes
7192 if ( nType === 3 || nType === 8 || nType === 2 ) {
7193 return;
7194 }
7195
7196 // Fallback to prop when attributes are not supported
7197 if ( typeof elem.getAttribute === "undefined" ) {
7198 return jQuery.prop( elem, name, value );
7199 }
7200
7201 // All attributes are lowercase
7202 // Grab necessary hook if one is defined
7203 if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {
7204 name = name.toLowerCase();
7205 hooks = jQuery.attrHooks[ name ] ||
7206 ( jQuery.expr.match.bool.test( name ) ? boolHook : undefined );
7207 }
7208
7209 if ( value !== undefined ) {
7210 if ( value === null ) {
7211 jQuery.removeAttr( elem, name );
7212 return;
7213 }
7214
7215 if ( hooks && "set" in hooks &&
7216 ( ret = hooks.set( elem, value, name ) ) !== undefined ) {
7217 return ret;
7218 }
7219
7220 elem.setAttribute( name, value + "" );
7221 return value;
7222 }
7223
7224 if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) {
7225 return ret;
7226 }
7227
7228 ret = jQuery.find.attr( elem, name );
7229
7230 // Non-existent attributes return null, we normalize to undefined
7231 return ret == null ? undefined : ret;
7232 },
7233
7234 attrHooks: {
7235 type: {
7236 set: function( elem, value ) {
7237 if ( !support.radioValue && value === "radio" &&
7238 jQuery.nodeName( elem, "input" ) ) {
7239 var val = elem.value;
7240 elem.setAttribute( "type", value );
7241 if ( val ) {
7242 elem.value = val;
7243 }
7244 return value;
7245 }
7246 }
7247 }
7248 },
7249
7250 removeAttr: function( elem, value ) {
7251 var name, propName,
7252 i = 0,
7253 attrNames = value && value.match( rnotwhite );
7254
7255 if ( attrNames && elem.nodeType === 1 ) {
7256 while ( ( name = attrNames[ i++ ] ) ) {
7257 propName = jQuery.propFix[ name ] || name;
7258
7259 // Boolean attributes get special treatment (#10870)
7260 if ( jQuery.expr.match.bool.test( name ) ) {
7261
7262 // Set corresponding property to false
7263 elem[ propName ] = false;
7264 }
7265
7266 elem.removeAttribute( name );
7267 }
7268 }
7269 }
7270} );
7271
7272// Hooks for boolean attributes
7273boolHook = {
7274 set: function( elem, value, name ) {
7275 if ( value === false ) {
7276
7277 // Remove boolean attributes when set to false
7278 jQuery.removeAttr( elem, name );
7279 } else {
7280 elem.setAttribute( name, name );
7281 }
7282 return name;
7283 }
7284};
7285jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) {
7286 var getter = attrHandle[ name ] || jQuery.find.attr;
7287
7288 attrHandle[ name ] = function( elem, name, isXML ) {
7289 var ret, handle;
7290 if ( !isXML ) {
7291
7292 // Avoid an infinite loop by temporarily removing this function from the getter
7293 handle = attrHandle[ name ];
7294 attrHandle[ name ] = ret;
7295 ret = getter( elem, name, isXML ) != null ?
7296 name.toLowerCase() :
7297 null;
7298 attrHandle[ name ] = handle;
7299 }
7300 return ret;
7301 };
7302} );
7303
7304
7305
7306
7307var rfocusable = /^(?:input|select|textarea|button)$/i,
7308 rclickable = /^(?:a|area)$/i;
7309
7310jQuery.fn.extend( {
7311 prop: function( name, value ) {
7312 return access( this, jQuery.prop, name, value, arguments.length > 1 );
7313 },
7314
7315 removeProp: function( name ) {
7316 return this.each( function() {
7317 delete this[ jQuery.propFix[ name ] || name ];
7318 } );
7319 }
7320} );
7321
7322jQuery.extend( {
7323 prop: function( elem, name, value ) {
7324 var ret, hooks,
7325 nType = elem.nodeType;
7326
7327 // Don't get/set properties on text, comment and attribute nodes
7328 if ( nType === 3 || nType === 8 || nType === 2 ) {
7329 return;
7330 }
7331
7332 if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {
7333
7334 // Fix name and attach hooks
7335 name = jQuery.propFix[ name ] || name;
7336 hooks = jQuery.propHooks[ name ];
7337 }
7338
7339 if ( value !== undefined ) {
7340 if ( hooks && "set" in hooks &&
7341 ( ret = hooks.set( elem, value, name ) ) !== undefined ) {
7342 return ret;
7343 }
7344
7345 return ( elem[ name ] = value );
7346 }
7347
7348 if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) {
7349 return ret;
7350 }
7351
7352 return elem[ name ];
7353 },
7354
7355 propHooks: {
7356 tabIndex: {
7357 get: function( elem ) {
7358
7359 // elem.tabIndex doesn't always return the
7360 // correct value when it hasn't been explicitly set
7361 // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
7362 // Use proper attribute retrieval(#12072)
7363 var tabindex = jQuery.find.attr( elem, "tabindex" );
7364
7365 return tabindex ?
7366 parseInt( tabindex, 10 ) :
7367 rfocusable.test( elem.nodeName ) ||
7368 rclickable.test( elem.nodeName ) && elem.href ?
7369 0 :
7370 -1;
7371 }
7372 }
7373 },
7374
7375 propFix: {
7376 "for": "htmlFor",
7377 "class": "className"
7378 }
7379} );
7380
7381// Support: IE <=11 only
7382// Accessing the selectedIndex property
7383// forces the browser to respect setting selected
7384// on the option
7385// The getter ensures a default option is selected
7386// when in an optgroup
7387if ( !support.optSelected ) {
7388 jQuery.propHooks.selected = {
7389 get: function( elem ) {
7390 var parent = elem.parentNode;
7391 if ( parent && parent.parentNode ) {
7392 parent.parentNode.selectedIndex;
7393 }
7394 return null;
7395 },
7396 set: function( elem ) {
7397 var parent = elem.parentNode;
7398 if ( parent ) {
7399 parent.selectedIndex;
7400
7401 if ( parent.parentNode ) {
7402 parent.parentNode.selectedIndex;
7403 }
7404 }
7405 }
7406 };
7407}
7408
7409jQuery.each( [
7410 "tabIndex",
7411 "readOnly",
7412 "maxLength",
7413 "cellSpacing",
7414 "cellPadding",
7415 "rowSpan",
7416 "colSpan",
7417 "useMap",
7418 "frameBorder",
7419 "contentEditable"
7420], function() {
7421 jQuery.propFix[ this.toLowerCase() ] = this;
7422} );
7423
7424
7425
7426
7427var rclass = /[\t\r\n\f]/g;
7428
7429function getClass( elem ) {
7430 return elem.getAttribute && elem.getAttribute( "class" ) || "";
7431}
7432
7433jQuery.fn.extend( {
7434 addClass: function( value ) {
7435 var classes, elem, cur, curValue, clazz, j, finalValue,
7436 i = 0;
7437
7438 if ( jQuery.isFunction( value ) ) {
7439 return this.each( function( j ) {
7440 jQuery( this ).addClass( value.call( this, j, getClass( this ) ) );
7441 } );
7442 }
7443
7444 if ( typeof value === "string" && value ) {
7445 classes = value.match( rnotwhite ) || [];
7446
7447 while ( ( elem = this[ i++ ] ) ) {
7448 curValue = getClass( elem );
7449 cur = elem.nodeType === 1 &&
7450 ( " " + curValue + " " ).replace( rclass, " " );
7451
7452 if ( cur ) {
7453 j = 0;
7454 while ( ( clazz = classes[ j++ ] ) ) {
7455 if ( cur.indexOf( " " + clazz + " " ) < 0 ) {
7456 cur += clazz + " ";
7457 }
7458 }
7459
7460 // Only assign if different to avoid unneeded rendering.
7461 finalValue = jQuery.trim( cur );
7462 if ( curValue !== finalValue ) {
7463 elem.setAttribute( "class", finalValue );
7464 }
7465 }
7466 }
7467 }
7468
7469 return this;
7470 },
7471
7472 removeClass: function( value ) {
7473 var classes, elem, cur, curValue, clazz, j, finalValue,
7474 i = 0;
7475
7476 if ( jQuery.isFunction( value ) ) {
7477 return this.each( function( j ) {
7478 jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) );
7479 } );
7480 }
7481
7482 if ( !arguments.length ) {
7483 return this.attr( "class", "" );
7484 }
7485
7486 if ( typeof value === "string" && value ) {
7487 classes = value.match( rnotwhite ) || [];
7488
7489 while ( ( elem = this[ i++ ] ) ) {
7490 curValue = getClass( elem );
7491
7492 // This expression is here for better compressibility (see addClass)
7493 cur = elem.nodeType === 1 &&
7494 ( " " + curValue + " " ).replace( rclass, " " );
7495
7496 if ( cur ) {
7497 j = 0;
7498 while ( ( clazz = classes[ j++ ] ) ) {
7499
7500 // Remove *all* instances
7501 while ( cur.indexOf( " " + clazz + " " ) > -1 ) {
7502 cur = cur.replace( " " + clazz + " ", " " );
7503 }
7504 }
7505
7506 // Only assign if different to avoid unneeded rendering.
7507 finalValue = jQuery.trim( cur );
7508 if ( curValue !== finalValue ) {
7509 elem.setAttribute( "class", finalValue );
7510 }
7511 }
7512 }
7513 }
7514
7515 return this;
7516 },
7517
7518 toggleClass: function( value, stateVal ) {
7519 var type = typeof value;
7520
7521 if ( typeof stateVal === "boolean" && type === "string" ) {
7522 return stateVal ? this.addClass( value ) : this.removeClass( value );
7523 }
7524
7525 if ( jQuery.isFunction( value ) ) {
7526 return this.each( function( i ) {
7527 jQuery( this ).toggleClass(
7528 value.call( this, i, getClass( this ), stateVal ),
7529 stateVal
7530 );
7531 } );
7532 }
7533
7534 return this.each( function() {
7535 var className, i, self, classNames;
7536
7537 if ( type === "string" ) {
7538
7539 // Toggle individual class names
7540 i = 0;
7541 self = jQuery( this );
7542 classNames = value.match( rnotwhite ) || [];
7543
7544 while ( ( className = classNames[ i++ ] ) ) {
7545
7546 // Check each className given, space separated list
7547 if ( self.hasClass( className ) ) {
7548 self.removeClass( className );
7549 } else {
7550 self.addClass( className );
7551 }
7552 }
7553
7554 // Toggle whole class name
7555 } else if ( value === undefined || type === "boolean" ) {
7556 className = getClass( this );
7557 if ( className ) {
7558
7559 // Store className if set
7560 dataPriv.set( this, "__className__", className );
7561 }
7562
7563 // then remove the whole classname (if there was one, the above saved it).
7564 // Otherwise bring back whatever was previously saved (if anything),
7565 // falling back to the empty string if nothing was stored.
7566 if ( this.setAttribute ) {
7567 this.setAttribute( "class",
7568 className || value === false ?
7569 "" :
7570 dataPriv.get( this, "__className__" ) || ""
7571 );
7572 }
7573 }
7574 } );
7575 },
7576
7577 hasClass: function( selector ) {
7578 var className, elem,
7579 i = 0;
7580
7581 className = " " + selector + " ";
7582 while ( ( elem = this[ i++ ] ) ) {
7583 if ( elem.nodeType === 1 &&
7584 ( " " + getClass( elem ) + " " ).replace( rclass, " " )
7585 .indexOf( className ) > -1
7586 ) {
7587 return true;
7588 }
7589 }
7590
7591 return false;
7592 }
7593} );
7594
7595
7596
7597
7598var rreturn = /\r/g,
7599 rspaces = /[\x20\t\r\n\f]+/g;
7600
7601jQuery.fn.extend( {
7602 val: function( value ) {
7603 var hooks, ret, isFunction,
7604 elem = this[ 0 ];
7605
7606 if ( !arguments.length ) {
7607 if ( elem ) {
7608 hooks = jQuery.valHooks[ elem.type ] ||
7609 jQuery.valHooks[ elem.nodeName.toLowerCase() ];
7610
7611 if ( hooks &&
7612 "get" in hooks &&
7613 ( ret = hooks.get( elem, "value" ) ) !== undefined
7614 ) {
7615 return ret;
7616 }
7617
7618 ret = elem.value;
7619
7620 return typeof ret === "string" ?
7621
7622 // Handle most common string cases
7623 ret.replace( rreturn, "" ) :
7624
7625 // Handle cases where value is null/undef or number
7626 ret == null ? "" : ret;
7627 }
7628
7629 return;
7630 }
7631
7632 isFunction = jQuery.isFunction( value );
7633
7634 return this.each( function( i ) {
7635 var val;
7636
7637 if ( this.nodeType !== 1 ) {
7638 return;
7639 }
7640
7641 if ( isFunction ) {
7642 val = value.call( this, i, jQuery( this ).val() );
7643 } else {
7644 val = value;
7645 }
7646
7647 // Treat null/undefined as ""; convert numbers to string
7648 if ( val == null ) {
7649 val = "";
7650
7651 } else if ( typeof val === "number" ) {
7652 val += "";
7653
7654 } else if ( jQuery.isArray( val ) ) {
7655 val = jQuery.map( val, function( value ) {
7656 return value == null ? "" : value + "";
7657 } );
7658 }
7659
7660 hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
7661
7662 // If set returns undefined, fall back to normal setting
7663 if ( !hooks || !( "set" in hooks ) || hooks.set( this, val, "value" ) === undefined ) {
7664 this.value = val;
7665 }
7666 } );
7667 }
7668} );
7669
7670jQuery.extend( {
7671 valHooks: {
7672 option: {
7673 get: function( elem ) {
7674
7675 var val = jQuery.find.attr( elem, "value" );
7676 return val != null ?
7677 val :
7678
7679 // Support: IE10-11+
7680 // option.text throws exceptions (#14686, #14858)
7681 // Strip and collapse whitespace
7682 // https://html.spec.whatwg.org/#strip-and-collapse-whitespace
7683 jQuery.trim( jQuery.text( elem ) ).replace( rspaces, " " );
7684 }
7685 },
7686 select: {
7687 get: function( elem ) {
7688 var value, option,
7689 options = elem.options,
7690 index = elem.selectedIndex,
7691 one = elem.type === "select-one" || index < 0,
7692 values = one ? null : [],
7693 max = one ? index + 1 : options.length,
7694 i = index < 0 ?
7695 max :
7696 one ? index : 0;
7697
7698 // Loop through all the selected options
7699 for ( ; i < max; i++ ) {
7700 option = options[ i ];
7701
7702 // IE8-9 doesn't update selected after form reset (#2551)
7703 if ( ( option.selected || i === index ) &&
7704
7705 // Don't return options that are disabled or in a disabled optgroup
7706 ( support.optDisabled ?
7707 !option.disabled : option.getAttribute( "disabled" ) === null ) &&
7708 ( !option.parentNode.disabled ||
7709 !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) {
7710
7711 // Get the specific value for the option
7712 value = jQuery( option ).val();
7713
7714 // We don't need an array for one selects
7715 if ( one ) {
7716 return value;
7717 }
7718
7719 // Multi-Selects return an array
7720 values.push( value );
7721 }
7722 }
7723
7724 return values;
7725 },
7726
7727 set: function( elem, value ) {
7728 var optionSet, option,
7729 options = elem.options,
7730 values = jQuery.makeArray( value ),
7731 i = options.length;
7732
7733 while ( i-- ) {
7734 option = options[ i ];
7735 if ( option.selected =
7736 jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1
7737 ) {
7738 optionSet = true;
7739 }
7740 }
7741
7742 // Force browsers to behave consistently when non-matching value is set
7743 if ( !optionSet ) {
7744 elem.selectedIndex = -1;
7745 }
7746 return values;
7747 }
7748 }
7749 }
7750} );
7751
7752// Radios and checkboxes getter/setter
7753jQuery.each( [ "radio", "checkbox" ], function() {
7754 jQuery.valHooks[ this ] = {
7755 set: function( elem, value ) {
7756 if ( jQuery.isArray( value ) ) {
7757 return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 );
7758 }
7759 }
7760 };
7761 if ( !support.checkOn ) {
7762 jQuery.valHooks[ this ].get = function( elem ) {
7763 return elem.getAttribute( "value" ) === null ? "on" : elem.value;
7764 };
7765 }
7766} );
7767
7768
7769
7770
7771// Return jQuery for attributes-only inclusion
7772
7773
7774var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/;
7775
7776jQuery.extend( jQuery.event, {
7777
7778 trigger: function( event, data, elem, onlyHandlers ) {
7779
7780 var i, cur, tmp, bubbleType, ontype, handle, special,
7781 eventPath = [ elem || document ],
7782 type = hasOwn.call( event, "type" ) ? event.type : event,
7783 namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : [];
7784
7785 cur = tmp = elem = elem || document;
7786
7787 // Don't do events on text and comment nodes
7788 if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
7789 return;
7790 }
7791
7792 // focus/blur morphs to focusin/out; ensure we're not firing them right now
7793 if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
7794 return;
7795 }
7796
7797 if ( type.indexOf( "." ) > -1 ) {
7798
7799 // Namespaced trigger; create a regexp to match event type in handle()
7800 namespaces = type.split( "." );
7801 type = namespaces.shift();
7802 namespaces.sort();
7803 }
7804 ontype = type.indexOf( ":" ) < 0 && "on" + type;
7805
7806 // Caller can pass in a jQuery.Event object, Object, or just an event type string
7807 event = event[ jQuery.expando ] ?
7808 event :
7809 new jQuery.Event( type, typeof event === "object" && event );
7810
7811 // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)
7812 event.isTrigger = onlyHandlers ? 2 : 3;
7813 event.namespace = namespaces.join( "." );
7814 event.rnamespace = event.namespace ?
7815 new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) :
7816 null;
7817
7818 // Clean up the event in case it is being reused
7819 event.result = undefined;
7820 if ( !event.target ) {
7821 event.target = elem;
7822 }
7823
7824 // Clone any incoming data and prepend the event, creating the handler arg list
7825 data = data == null ?
7826 [ event ] :
7827 jQuery.makeArray( data, [ event ] );
7828
7829 // Allow special events to draw outside the lines
7830 special = jQuery.event.special[ type ] || {};
7831 if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {
7832 return;
7833 }
7834
7835 // Determine event propagation path in advance, per W3C events spec (#9951)
7836 // Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
7837 if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {
7838
7839 bubbleType = special.delegateType || type;
7840 if ( !rfocusMorph.test( bubbleType + type ) ) {
7841 cur = cur.parentNode;
7842 }
7843 for ( ; cur; cur = cur.parentNode ) {
7844 eventPath.push( cur );
7845 tmp = cur;
7846 }
7847
7848 // Only add window if we got to document (e.g., not plain obj or detached DOM)
7849 if ( tmp === ( elem.ownerDocument || document ) ) {
7850 eventPath.push( tmp.defaultView || tmp.parentWindow || window );
7851 }
7852 }
7853
7854 // Fire handlers on the event path
7855 i = 0;
7856 while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) {
7857
7858 event.type = i > 1 ?
7859 bubbleType :
7860 special.bindType || type;
7861
7862 // jQuery handler
7863 handle = ( dataPriv.get( cur, "events" ) || {} )[ event.type ] &&
7864 dataPriv.get( cur, "handle" );
7865 if ( handle ) {
7866 handle.apply( cur, data );
7867 }
7868
7869 // Native handler
7870 handle = ontype && cur[ ontype ];
7871 if ( handle && handle.apply && acceptData( cur ) ) {
7872 event.result = handle.apply( cur, data );
7873 if ( event.result === false ) {
7874 event.preventDefault();
7875 }
7876 }
7877 }
7878 event.type = type;
7879
7880 // If nobody prevented the default action, do it now
7881 if ( !onlyHandlers && !event.isDefaultPrevented() ) {
7882
7883 if ( ( !special._default ||
7884 special._default.apply( eventPath.pop(), data ) === false ) &&
7885 acceptData( elem ) ) {
7886
7887 // Call a native DOM method on the target with the same name name as the event.
7888 // Don't do default actions on window, that's where global variables be (#6170)
7889 if ( ontype && jQuery.isFunction( elem[ type ] ) && !jQuery.isWindow( elem ) ) {
7890
7891 // Don't re-trigger an onFOO event when we call its FOO() method
7892 tmp = elem[ ontype ];
7893
7894 if ( tmp ) {
7895 elem[ ontype ] = null;
7896 }
7897
7898 // Prevent re-triggering of the same event, since we already bubbled it above
7899 jQuery.event.triggered = type;
7900 elem[ type ]();
7901 jQuery.event.triggered = undefined;
7902
7903 if ( tmp ) {
7904 elem[ ontype ] = tmp;
7905 }
7906 }
7907 }
7908 }
7909
7910 return event.result;
7911 },
7912
7913 // Piggyback on a donor event to simulate a different one
7914 simulate: function( type, elem, event ) {
7915 var e = jQuery.extend(
7916 new jQuery.Event(),
7917 event,
7918 {
7919 type: type,
7920 isSimulated: true
7921 }
7922 );
7923
7924 jQuery.event.trigger( e, null, elem );
7925 }
7926
7927} );
7928
7929jQuery.fn.extend( {
7930
7931 trigger: function( type, data ) {
7932 return this.each( function() {
7933 jQuery.event.trigger( type, data, this );
7934 } );
7935 },
7936 triggerHandler: function( type, data ) {
7937 var elem = this[ 0 ];
7938 if ( elem ) {
7939 return jQuery.event.trigger( type, data, elem, true );
7940 }
7941 }
7942} );
7943
7944
7945jQuery.each( ( "blur focus focusin focusout load resize scroll unload click dblclick " +
7946 "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
7947 "change select submit keydown keypress keyup error contextmenu" ).split( " " ),
7948 function( i, name ) {
7949
7950 // Handle event binding
7951 jQuery.fn[ name ] = function( data, fn ) {
7952 return arguments.length > 0 ?
7953 this.on( name, null, data, fn ) :
7954 this.trigger( name );
7955 };
7956} );
7957
7958jQuery.fn.extend( {
7959 hover: function( fnOver, fnOut ) {
7960 return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
7961 }
7962} );
7963
7964
7965
7966
7967support.focusin = "onfocusin" in window;
7968
7969
7970// Support: Firefox
7971// Firefox doesn't have focus(in | out) events
7972// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787
7973//
7974// Support: Chrome, Safari
7975// focus(in | out) events fire after focus & blur events,
7976// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order
7977// Related ticket - https://code.google.com/p/chromium/issues/detail?id=449857
7978if ( !support.focusin ) {
7979 jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) {
7980
7981 // Attach a single capturing handler on the document while someone wants focusin/focusout
7982 var handler = function( event ) {
7983 jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) );
7984 };
7985
7986 jQuery.event.special[ fix ] = {
7987 setup: function() {
7988 var doc = this.ownerDocument || this,
7989 attaches = dataPriv.access( doc, fix );
7990
7991 if ( !attaches ) {
7992 doc.addEventListener( orig, handler, true );
7993 }
7994 dataPriv.access( doc, fix, ( attaches || 0 ) + 1 );
7995 },
7996 teardown: function() {
7997 var doc = this.ownerDocument || this,
7998 attaches = dataPriv.access( doc, fix ) - 1;
7999
8000 if ( !attaches ) {
8001 doc.removeEventListener( orig, handler, true );
8002 dataPriv.remove( doc, fix );
8003
8004 } else {
8005 dataPriv.access( doc, fix, attaches );
8006 }
8007 }
8008 };
8009 } );
8010}
8011var location = window.location;
8012
8013var nonce = jQuery.now();
8014
8015var rquery = ( /\?/ );
8016
8017
8018
8019// Support: Android 2.3
8020// Workaround failure to string-cast null input
8021jQuery.parseJSON = function( data ) {
8022 return JSON.parse( data + "" );
8023};
8024
8025
8026// Cross-browser xml parsing
8027jQuery.parseXML = function( data ) {
8028 var xml;
8029 if ( !data || typeof data !== "string" ) {
8030 return null;
8031 }
8032
8033 // Support: IE9
8034 try {
8035 xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" );
8036 } catch ( e ) {
8037 xml = undefined;
8038 }
8039
8040 if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) {
8041 jQuery.error( "Invalid XML: " + data );
8042 }
8043 return xml;
8044};
8045
8046
8047var
8048 rhash = /#.*$/,
8049 rts = /([?&])_=[^&]*/,
8050 rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg,
8051
8052 // #7653, #8125, #8152: local protocol detection
8053 rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,
8054 rnoContent = /^(?:GET|HEAD)$/,
8055 rprotocol = /^\/\//,
8056
8057 /* Prefilters
8058 * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
8059 * 2) These are called:
8060 * - BEFORE asking for a transport
8061 * - AFTER param serialization (s.data is a string if s.processData is true)
8062 * 3) key is the dataType
8063 * 4) the catchall symbol "*" can be used
8064 * 5) execution will start with transport dataType and THEN continue down to "*" if needed
8065 */
8066 prefilters = {},
8067
8068 /* Transports bindings
8069 * 1) key is the dataType
8070 * 2) the catchall symbol "*" can be used
8071 * 3) selection will start with transport dataType and THEN go to "*" if needed
8072 */
8073 transports = {},
8074
8075 // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
8076 allTypes = "*/".concat( "*" ),
8077
8078 // Anchor tag for parsing the document origin
8079 originAnchor = document.createElement( "a" );
8080 originAnchor.href = location.href;
8081
8082// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
8083function addToPrefiltersOrTransports( structure ) {
8084
8085 // dataTypeExpression is optional and defaults to "*"
8086 return function( dataTypeExpression, func ) {
8087
8088 if ( typeof dataTypeExpression !== "string" ) {
8089 func = dataTypeExpression;
8090 dataTypeExpression = "*";
8091 }
8092
8093 var dataType,
8094 i = 0,
8095 dataTypes = dataTypeExpression.toLowerCase().match( rnotwhite ) || [];
8096
8097 if ( jQuery.isFunction( func ) ) {
8098
8099 // For each dataType in the dataTypeExpression
8100 while ( ( dataType = dataTypes[ i++ ] ) ) {
8101
8102 // Prepend if requested
8103 if ( dataType[ 0 ] === "+" ) {
8104 dataType = dataType.slice( 1 ) || "*";
8105 ( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func );
8106
8107 // Otherwise append
8108 } else {
8109 ( structure[ dataType ] = structure[ dataType ] || [] ).push( func );
8110 }
8111 }
8112 }
8113 };
8114}
8115
8116// Base inspection function for prefilters and transports
8117function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {
8118
8119 var inspected = {},
8120 seekingTransport = ( structure === transports );
8121
8122 function inspect( dataType ) {
8123 var selected;
8124 inspected[ dataType ] = true;
8125 jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {
8126 var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );
8127 if ( typeof dataTypeOrTransport === "string" &&
8128 !seekingTransport && !inspected[ dataTypeOrTransport ] ) {
8129
8130 options.dataTypes.unshift( dataTypeOrTransport );
8131 inspect( dataTypeOrTransport );
8132 return false;
8133 } else if ( seekingTransport ) {
8134 return !( selected = dataTypeOrTransport );
8135 }
8136 } );
8137 return selected;
8138 }
8139
8140 return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" );
8141}
8142
8143// A special extend for ajax options
8144// that takes "flat" options (not to be deep extended)
8145// Fixes #9887
8146function ajaxExtend( target, src ) {
8147 var key, deep,
8148 flatOptions = jQuery.ajaxSettings.flatOptions || {};
8149
8150 for ( key in src ) {
8151 if ( src[ key ] !== undefined ) {
8152 ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ];
8153 }
8154 }
8155 if ( deep ) {
8156 jQuery.extend( true, target, deep );
8157 }
8158
8159 return target;
8160}
8161
8162/* Handles responses to an ajax request:
8163 * - finds the right dataType (mediates between content-type and expected dataType)
8164 * - returns the corresponding response
8165 */
8166function ajaxHandleResponses( s, jqXHR, responses ) {
8167
8168 var ct, type, finalDataType, firstDataType,
8169 contents = s.contents,
8170 dataTypes = s.dataTypes;
8171
8172 // Remove auto dataType and get content-type in the process
8173 while ( dataTypes[ 0 ] === "*" ) {
8174 dataTypes.shift();
8175 if ( ct === undefined ) {
8176 ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" );
8177 }
8178 }
8179
8180 // Check if we're dealing with a known content-type
8181 if ( ct ) {
8182 for ( type in contents ) {
8183 if ( contents[ type ] && contents[ type ].test( ct ) ) {
8184 dataTypes.unshift( type );
8185 break;
8186 }
8187 }
8188 }
8189
8190 // Check to see if we have a response for the expected dataType
8191 if ( dataTypes[ 0 ] in responses ) {
8192 finalDataType = dataTypes[ 0 ];
8193 } else {
8194
8195 // Try convertible dataTypes
8196 for ( type in responses ) {
8197 if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) {
8198 finalDataType = type;
8199 break;
8200 }
8201 if ( !firstDataType ) {
8202 firstDataType = type;
8203 }
8204 }
8205
8206 // Or just use first one
8207 finalDataType = finalDataType || firstDataType;
8208 }
8209
8210 // If we found a dataType
8211 // We add the dataType to the list if needed
8212 // and return the corresponding response
8213 if ( finalDataType ) {
8214 if ( finalDataType !== dataTypes[ 0 ] ) {
8215 dataTypes.unshift( finalDataType );
8216 }
8217 return responses[ finalDataType ];
8218 }
8219}
8220
8221/* Chain conversions given the request and the original response
8222 * Also sets the responseXXX fields on the jqXHR instance
8223 */
8224function ajaxConvert( s, response, jqXHR, isSuccess ) {
8225 var conv2, current, conv, tmp, prev,
8226 converters = {},
8227
8228 // Work with a copy of dataTypes in case we need to modify it for conversion
8229 dataTypes = s.dataTypes.slice();
8230
8231 // Create converters map with lowercased keys
8232 if ( dataTypes[ 1 ] ) {
8233 for ( conv in s.converters ) {
8234 converters[ conv.toLowerCase() ] = s.converters[ conv ];
8235 }
8236 }
8237
8238 current = dataTypes.shift();
8239
8240 // Convert to each sequential dataType
8241 while ( current ) {
8242
8243 if ( s.responseFields[ current ] ) {
8244 jqXHR[ s.responseFields[ current ] ] = response;
8245 }
8246
8247 // Apply the dataFilter if provided
8248 if ( !prev && isSuccess && s.dataFilter ) {
8249 response = s.dataFilter( response, s.dataType );
8250 }
8251
8252 prev = current;
8253 current = dataTypes.shift();
8254
8255 if ( current ) {
8256
8257 // There's only work to do if current dataType is non-auto
8258 if ( current === "*" ) {
8259
8260 current = prev;
8261
8262 // Convert response if prev dataType is non-auto and differs from current
8263 } else if ( prev !== "*" && prev !== current ) {
8264
8265 // Seek a direct converter
8266 conv = converters[ prev + " " + current ] || converters[ "* " + current ];
8267
8268 // If none found, seek a pair
8269 if ( !conv ) {
8270 for ( conv2 in converters ) {
8271
8272 // If conv2 outputs current
8273 tmp = conv2.split( " " );
8274 if ( tmp[ 1 ] === current ) {
8275
8276 // If prev can be converted to accepted input
8277 conv = converters[ prev + " " + tmp[ 0 ] ] ||
8278 converters[ "* " + tmp[ 0 ] ];
8279 if ( conv ) {
8280
8281 // Condense equivalence converters
8282 if ( conv === true ) {
8283 conv = converters[ conv2 ];
8284
8285 // Otherwise, insert the intermediate dataType
8286 } else if ( converters[ conv2 ] !== true ) {
8287 current = tmp[ 0 ];
8288 dataTypes.unshift( tmp[ 1 ] );
8289 }
8290 break;
8291 }
8292 }
8293 }
8294 }
8295
8296 // Apply converter (if not an equivalence)
8297 if ( conv !== true ) {
8298
8299 // Unless errors are allowed to bubble, catch and return them
8300 if ( conv && s.throws ) {
8301 response = conv( response );
8302 } else {
8303 try {
8304 response = conv( response );
8305 } catch ( e ) {
8306 return {
8307 state: "parsererror",
8308 error: conv ? e : "No conversion from " + prev + " to " + current
8309 };
8310 }
8311 }
8312 }
8313 }
8314 }
8315 }
8316
8317 return { state: "success", data: response };
8318}
8319
8320jQuery.extend( {
8321
8322 // Counter for holding the number of active queries
8323 active: 0,
8324
8325 // Last-Modified header cache for next request
8326 lastModified: {},
8327 etag: {},
8328
8329 ajaxSettings: {
8330 url: location.href,
8331 type: "GET",
8332 isLocal: rlocalProtocol.test( location.protocol ),
8333 global: true,
8334 processData: true,
8335 async: true,
8336 contentType: "application/x-www-form-urlencoded; charset=UTF-8",
8337 /*
8338 timeout: 0,
8339 data: null,
8340 dataType: null,
8341 username: null,
8342 password: null,
8343 cache: null,
8344 throws: false,
8345 traditional: false,
8346 headers: {},
8347 */
8348
8349 accepts: {
8350 "*": allTypes,
8351 text: "text/plain",
8352 html: "text/html",
8353 xml: "application/xml, text/xml",
8354 json: "application/json, text/javascript"
8355 },
8356
8357 contents: {
8358 xml: /\bxml\b/,
8359 html: /\bhtml/,
8360 json: /\bjson\b/
8361 },
8362
8363 responseFields: {
8364 xml: "responseXML",
8365 text: "responseText",
8366 json: "responseJSON"
8367 },
8368
8369 // Data converters
8370 // Keys separate source (or catchall "*") and destination types with a single space
8371 converters: {
8372
8373 // Convert anything to text
8374 "* text": String,
8375
8376 // Text to html (true = no transformation)
8377 "text html": true,
8378
8379 // Evaluate text as a json expression
8380 "text json": jQuery.parseJSON,
8381
8382 // Parse text as xml
8383 "text xml": jQuery.parseXML
8384 },
8385
8386 // For options that shouldn't be deep extended:
8387 // you can add your own custom options here if
8388 // and when you create one that shouldn't be
8389 // deep extended (see ajaxExtend)
8390 flatOptions: {
8391 url: true,
8392 context: true
8393 }
8394 },
8395
8396 // Creates a full fledged settings object into target
8397 // with both ajaxSettings and settings fields.
8398 // If target is omitted, writes into ajaxSettings.
8399 ajaxSetup: function( target, settings ) {
8400 return settings ?
8401
8402 // Building a settings object
8403 ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :
8404
8405 // Extending ajaxSettings
8406 ajaxExtend( jQuery.ajaxSettings, target );
8407 },
8408
8409 ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
8410 ajaxTransport: addToPrefiltersOrTransports( transports ),
8411
8412 // Main method
8413 ajax: function( url, options ) {
8414
8415 // If url is an object, simulate pre-1.5 signature
8416 if ( typeof url === "object" ) {
8417 options = url;
8418 url = undefined;
8419 }
8420
8421 // Force options to be an object
8422 options = options || {};
8423
8424 var transport,
8425
8426 // URL without anti-cache param
8427 cacheURL,
8428
8429 // Response headers
8430 responseHeadersString,
8431 responseHeaders,
8432
8433 // timeout handle
8434 timeoutTimer,
8435
8436 // Url cleanup var
8437 urlAnchor,
8438
8439 // To know if global events are to be dispatched
8440 fireGlobals,
8441
8442 // Loop variable
8443 i,
8444
8445 // Create the final options object
8446 s = jQuery.ajaxSetup( {}, options ),
8447
8448 // Callbacks context
8449 callbackContext = s.context || s,
8450
8451 // Context for global events is callbackContext if it is a DOM node or jQuery collection
8452 globalEventContext = s.context &&
8453 ( callbackContext.nodeType || callbackContext.jquery ) ?
8454 jQuery( callbackContext ) :
8455 jQuery.event,
8456
8457 // Deferreds
8458 deferred = jQuery.Deferred(),
8459 completeDeferred = jQuery.Callbacks( "once memory" ),
8460
8461 // Status-dependent callbacks
8462 statusCode = s.statusCode || {},
8463
8464 // Headers (they are sent all at once)
8465 requestHeaders = {},
8466 requestHeadersNames = {},
8467
8468 // The jqXHR state
8469 state = 0,
8470
8471 // Default abort message
8472 strAbort = "canceled",
8473
8474 // Fake xhr
8475 jqXHR = {
8476 readyState: 0,
8477
8478 // Builds headers hashtable if needed
8479 getResponseHeader: function( key ) {
8480 var match;
8481 if ( state === 2 ) {
8482 if ( !responseHeaders ) {
8483 responseHeaders = {};
8484 while ( ( match = rheaders.exec( responseHeadersString ) ) ) {
8485 responseHeaders[ match[ 1 ].toLowerCase() ] = match[ 2 ];
8486 }
8487 }
8488 match = responseHeaders[ key.toLowerCase() ];
8489 }
8490 return match == null ? null : match;
8491 },
8492
8493 // Raw string
8494 getAllResponseHeaders: function() {
8495 return state === 2 ? responseHeadersString : null;
8496 },
8497
8498 // Caches the header
8499 setRequestHeader: function( name, value ) {
8500 var lname = name.toLowerCase();
8501 if ( !state ) {
8502 name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;
8503 requestHeaders[ name ] = value;
8504 }
8505 return this;
8506 },
8507
8508 // Overrides response content-type header
8509 overrideMimeType: function( type ) {
8510 if ( !state ) {
8511 s.mimeType = type;
8512 }
8513 return this;
8514 },
8515
8516 // Status-dependent callbacks
8517 statusCode: function( map ) {
8518 var code;
8519 if ( map ) {
8520 if ( state < 2 ) {
8521 for ( code in map ) {
8522
8523 // Lazy-add the new callback in a way that preserves old ones
8524 statusCode[ code ] = [ statusCode[ code ], map[ code ] ];
8525 }
8526 } else {
8527
8528 // Execute the appropriate callbacks
8529 jqXHR.always( map[ jqXHR.status ] );
8530 }
8531 }
8532 return this;
8533 },
8534
8535 // Cancel the request
8536 abort: function( statusText ) {
8537 var finalText = statusText || strAbort;
8538 if ( transport ) {
8539 transport.abort( finalText );
8540 }
8541 done( 0, finalText );
8542 return this;
8543 }
8544 };
8545
8546 // Attach deferreds
8547 deferred.promise( jqXHR ).complete = completeDeferred.add;
8548 jqXHR.success = jqXHR.done;
8549 jqXHR.error = jqXHR.fail;
8550
8551 // Remove hash character (#7531: and string promotion)
8552 // Add protocol if not provided (prefilters might expect it)
8553 // Handle falsy url in the settings object (#10093: consistency with old signature)
8554 // We also use the url parameter if available
8555 s.url = ( ( url || s.url || location.href ) + "" ).replace( rhash, "" )
8556 .replace( rprotocol, location.protocol + "//" );
8557
8558 // Alias method option to type as per ticket #12004
8559 s.type = options.method || options.type || s.method || s.type;
8560
8561 // Extract dataTypes list
8562 s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().match( rnotwhite ) || [ "" ];
8563
8564 // A cross-domain request is in order when the origin doesn't match the current origin.
8565 if ( s.crossDomain == null ) {
8566 urlAnchor = document.createElement( "a" );
8567
8568 // Support: IE8-11+
8569 // IE throws exception if url is malformed, e.g. http://example.com:80x/
8570 try {
8571 urlAnchor.href = s.url;
8572
8573 // Support: IE8-11+
8574 // Anchor's host property isn't correctly set when s.url is relative
8575 urlAnchor.href = urlAnchor.href;
8576 s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !==
8577 urlAnchor.protocol + "//" + urlAnchor.host;
8578 } catch ( e ) {
8579
8580 // If there is an error parsing the URL, assume it is crossDomain,
8581 // it can be rejected by the transport if it is invalid
8582 s.crossDomain = true;
8583 }
8584 }
8585
8586 // Convert data if not already a string
8587 if ( s.data && s.processData && typeof s.data !== "string" ) {
8588 s.data = jQuery.param( s.data, s.traditional );
8589 }
8590
8591 // Apply prefilters
8592 inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
8593
8594 // If request was aborted inside a prefilter, stop there
8595 if ( state === 2 ) {
8596 return jqXHR;
8597 }
8598
8599 // We can fire global events as of now if asked to
8600 // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118)
8601 fireGlobals = jQuery.event && s.global;
8602
8603 // Watch for a new set of requests
8604 if ( fireGlobals && jQuery.active++ === 0 ) {
8605 jQuery.event.trigger( "ajaxStart" );
8606 }
8607
8608 // Uppercase the type
8609 s.type = s.type.toUpperCase();
8610
8611 // Determine if request has content
8612 s.hasContent = !rnoContent.test( s.type );
8613
8614 // Save the URL in case we're toying with the If-Modified-Since
8615 // and/or If-None-Match header later on
8616 cacheURL = s.url;
8617
8618 // More options handling for requests with no content
8619 if ( !s.hasContent ) {
8620
8621 // If data is available, append data to url
8622 if ( s.data ) {
8623 cacheURL = ( s.url += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data );
8624
8625 // #9682: remove data so that it's not used in an eventual retry
8626 delete s.data;
8627 }
8628
8629 // Add anti-cache in url if needed
8630 if ( s.cache === false ) {
8631 s.url = rts.test( cacheURL ) ?
8632
8633 // If there is already a '_' parameter, set its value
8634 cacheURL.replace( rts, "$1_=" + nonce++ ) :
8635
8636 // Otherwise add one to the end
8637 cacheURL + ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + nonce++;
8638 }
8639 }
8640
8641 // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
8642 if ( s.ifModified ) {
8643 if ( jQuery.lastModified[ cacheURL ] ) {
8644 jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] );
8645 }
8646 if ( jQuery.etag[ cacheURL ] ) {
8647 jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] );
8648 }
8649 }
8650
8651 // Set the correct header, if data is being sent
8652 if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
8653 jqXHR.setRequestHeader( "Content-Type", s.contentType );
8654 }
8655
8656 // Set the Accepts header for the server, depending on the dataType
8657 jqXHR.setRequestHeader(
8658 "Accept",
8659 s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ?
8660 s.accepts[ s.dataTypes[ 0 ] ] +
8661 ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
8662 s.accepts[ "*" ]
8663 );
8664
8665 // Check for headers option
8666 for ( i in s.headers ) {
8667 jqXHR.setRequestHeader( i, s.headers[ i ] );
8668 }
8669
8670 // Allow custom headers/mimetypes and early abort
8671 if ( s.beforeSend &&
8672 ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {
8673
8674 // Abort if not done already and return
8675 return jqXHR.abort();
8676 }
8677
8678 // Aborting is no longer a cancellation
8679 strAbort = "abort";
8680
8681 // Install callbacks on deferreds
8682 for ( i in { success: 1, error: 1, complete: 1 } ) {
8683 jqXHR[ i ]( s[ i ] );
8684 }
8685
8686 // Get transport
8687 transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
8688
8689 // If no transport, we auto-abort
8690 if ( !transport ) {
8691 done( -1, "No Transport" );
8692 } else {
8693 jqXHR.readyState = 1;
8694
8695 // Send global event
8696 if ( fireGlobals ) {
8697 globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
8698 }
8699
8700 // If request was aborted inside ajaxSend, stop there
8701 if ( state === 2 ) {
8702 return jqXHR;
8703 }
8704
8705 // Timeout
8706 if ( s.async && s.timeout > 0 ) {
8707 timeoutTimer = window.setTimeout( function() {
8708 jqXHR.abort( "timeout" );
8709 }, s.timeout );
8710 }
8711
8712 try {
8713 state = 1;
8714 transport.send( requestHeaders, done );
8715 } catch ( e ) {
8716
8717 // Propagate exception as error if not done
8718 if ( state < 2 ) {
8719 done( -1, e );
8720
8721 // Simply rethrow otherwise
8722 } else {
8723 throw e;
8724 }
8725 }
8726 }
8727
8728 // Callback for when everything is done
8729 function done( status, nativeStatusText, responses, headers ) {
8730 var isSuccess, success, error, response, modified,
8731 statusText = nativeStatusText;
8732
8733 // Called once
8734 if ( state === 2 ) {
8735 return;
8736 }
8737
8738 // State is "done" now
8739 state = 2;
8740
8741 // Clear timeout if it exists
8742 if ( timeoutTimer ) {
8743 window.clearTimeout( timeoutTimer );
8744 }
8745
8746 // Dereference transport for early garbage collection
8747 // (no matter how long the jqXHR object will be used)
8748 transport = undefined;
8749
8750 // Cache response headers
8751 responseHeadersString = headers || "";
8752
8753 // Set readyState
8754 jqXHR.readyState = status > 0 ? 4 : 0;
8755
8756 // Determine if successful
8757 isSuccess = status >= 200 && status < 300 || status === 304;
8758
8759 // Get response data
8760 if ( responses ) {
8761 response = ajaxHandleResponses( s, jqXHR, responses );
8762 }
8763
8764 // Convert no matter what (that way responseXXX fields are always set)
8765 response = ajaxConvert( s, response, jqXHR, isSuccess );
8766
8767 // If successful, handle type chaining
8768 if ( isSuccess ) {
8769
8770 // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
8771 if ( s.ifModified ) {
8772 modified = jqXHR.getResponseHeader( "Last-Modified" );
8773 if ( modified ) {
8774 jQuery.lastModified[ cacheURL ] = modified;
8775 }
8776 modified = jqXHR.getResponseHeader( "etag" );
8777 if ( modified ) {
8778 jQuery.etag[ cacheURL ] = modified;
8779 }
8780 }
8781
8782 // if no content
8783 if ( status === 204 || s.type === "HEAD" ) {
8784 statusText = "nocontent";
8785
8786 // if not modified
8787 } else if ( status === 304 ) {
8788 statusText = "notmodified";
8789
8790 // If we have data, let's convert it
8791 } else {
8792 statusText = response.state;
8793 success = response.data;
8794 error = response.error;
8795 isSuccess = !error;
8796 }
8797 } else {
8798
8799 // Extract error from statusText and normalize for non-aborts
8800 error = statusText;
8801 if ( status || !statusText ) {
8802 statusText = "error";
8803 if ( status < 0 ) {
8804 status = 0;
8805 }
8806 }
8807 }
8808
8809 // Set data for the fake xhr object
8810 jqXHR.status = status;
8811 jqXHR.statusText = ( nativeStatusText || statusText ) + "";
8812
8813 // Success/Error
8814 if ( isSuccess ) {
8815 deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
8816 } else {
8817 deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
8818 }
8819
8820 // Status-dependent callbacks
8821 jqXHR.statusCode( statusCode );
8822 statusCode = undefined;
8823
8824 if ( fireGlobals ) {
8825 globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError",
8826 [ jqXHR, s, isSuccess ? success : error ] );
8827 }
8828
8829 // Complete
8830 completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );
8831
8832 if ( fireGlobals ) {
8833 globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
8834
8835 // Handle the global AJAX counter
8836 if ( !( --jQuery.active ) ) {
8837 jQuery.event.trigger( "ajaxStop" );
8838 }
8839 }
8840 }
8841
8842 return jqXHR;
8843 },
8844
8845 getJSON: function( url, data, callback ) {
8846 return jQuery.get( url, data, callback, "json" );
8847 },
8848
8849 getScript: function( url, callback ) {
8850 return jQuery.get( url, undefined, callback, "script" );
8851 }
8852} );
8853
8854jQuery.each( [ "get", "post" ], function( i, method ) {
8855 jQuery[ method ] = function( url, data, callback, type ) {
8856
8857 // Shift arguments if data argument was omitted
8858 if ( jQuery.isFunction( data ) ) {
8859 type = type || callback;
8860 callback = data;
8861 data = undefined;
8862 }
8863
8864 // The url can be an options object (which then must have .url)
8865 return jQuery.ajax( jQuery.extend( {
8866 url: url,
8867 type: method,
8868 dataType: type,
8869 data: data,
8870 success: callback
8871 }, jQuery.isPlainObject( url ) && url ) );
8872 };
8873} );
8874
8875
8876jQuery._evalUrl = function( url ) {
8877 return jQuery.ajax( {
8878 url: url,
8879
8880 // Make this explicit, since user can override this through ajaxSetup (#11264)
8881 type: "GET",
8882 dataType: "script",
8883 async: false,
8884 global: false,
8885 "throws": true
8886 } );
8887};
8888
8889
8890jQuery.fn.extend( {
8891 wrapAll: function( html ) {
8892 var wrap;
8893
8894 if ( jQuery.isFunction( html ) ) {
8895 return this.each( function( i ) {
8896 jQuery( this ).wrapAll( html.call( this, i ) );
8897 } );
8898 }
8899
8900 if ( this[ 0 ] ) {
8901
8902 // The elements to wrap the target around
8903 wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true );
8904
8905 if ( this[ 0 ].parentNode ) {
8906 wrap.insertBefore( this[ 0 ] );
8907 }
8908
8909 wrap.map( function() {
8910 var elem = this;
8911
8912 while ( elem.firstElementChild ) {
8913 elem = elem.firstElementChild;
8914 }
8915
8916 return elem;
8917 } ).append( this );
8918 }
8919
8920 return this;
8921 },
8922
8923 wrapInner: function( html ) {
8924 if ( jQuery.isFunction( html ) ) {
8925 return this.each( function( i ) {
8926 jQuery( this ).wrapInner( html.call( this, i ) );
8927 } );
8928 }
8929
8930 return this.each( function() {
8931 var self = jQuery( this ),
8932 contents = self.contents();
8933
8934 if ( contents.length ) {
8935 contents.wrapAll( html );
8936
8937 } else {
8938 self.append( html );
8939 }
8940 } );
8941 },
8942
8943 wrap: function( html ) {
8944 var isFunction = jQuery.isFunction( html );
8945
8946 return this.each( function( i ) {
8947 jQuery( this ).wrapAll( isFunction ? html.call( this, i ) : html );
8948 } );
8949 },
8950
8951 unwrap: function() {
8952 return this.parent().each( function() {
8953 if ( !jQuery.nodeName( this, "body" ) ) {
8954 jQuery( this ).replaceWith( this.childNodes );
8955 }
8956 } ).end();
8957 }
8958} );
8959
8960
8961jQuery.expr.filters.hidden = function( elem ) {
8962 return !jQuery.expr.filters.visible( elem );
8963};
8964jQuery.expr.filters.visible = function( elem ) {
8965
8966 // Support: Opera <= 12.12
8967 // Opera reports offsetWidths and offsetHeights less than zero on some elements
8968 // Use OR instead of AND as the element is not visible if either is true
8969 // See tickets #10406 and #13132
8970 return elem.offsetWidth > 0 || elem.offsetHeight > 0 || elem.getClientRects().length > 0;
8971};
8972
8973
8974
8975
8976var r20 = /%20/g,
8977 rbracket = /\[\]$/,
8978 rCRLF = /\r?\n/g,
8979 rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,
8980 rsubmittable = /^(?:input|select|textarea|keygen)/i;
8981
8982function buildParams( prefix, obj, traditional, add ) {
8983 var name;
8984
8985 if ( jQuery.isArray( obj ) ) {
8986
8987 // Serialize array item.
8988 jQuery.each( obj, function( i, v ) {
8989 if ( traditional || rbracket.test( prefix ) ) {
8990
8991 // Treat each array item as a scalar.
8992 add( prefix, v );
8993
8994 } else {
8995
8996 // Item is non-scalar (array or object), encode its numeric index.
8997 buildParams(
8998 prefix + "[" + ( typeof v === "object" && v != null ? i : "" ) + "]",
8999 v,
9000 traditional,
9001 add
9002 );
9003 }
9004 } );
9005
9006 } else if ( !traditional && jQuery.type( obj ) === "object" ) {
9007
9008 // Serialize object item.
9009 for ( name in obj ) {
9010 buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
9011 }
9012
9013 } else {
9014
9015 // Serialize scalar item.
9016 add( prefix, obj );
9017 }
9018}
9019
9020// Serialize an array of form elements or a set of
9021// key/values into a query string
9022jQuery.param = function( a, traditional ) {
9023 var prefix,
9024 s = [],
9025 add = function( key, value ) {
9026
9027 // If value is a function, invoke it and return its value
9028 value = jQuery.isFunction( value ) ? value() : ( value == null ? "" : value );
9029 s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
9030 };
9031
9032 // Set traditional to true for jQuery <= 1.3.2 behavior.
9033 if ( traditional === undefined ) {
9034 traditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;
9035 }
9036
9037 // If an array was passed in, assume that it is an array of form elements.
9038 if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
9039
9040 // Serialize the form elements
9041 jQuery.each( a, function() {
9042 add( this.name, this.value );
9043 } );
9044
9045 } else {
9046
9047 // If traditional, encode the "old" way (the way 1.3.2 or older
9048 // did it), otherwise encode params recursively.
9049 for ( prefix in a ) {
9050 buildParams( prefix, a[ prefix ], traditional, add );
9051 }
9052 }
9053
9054 // Return the resulting serialization
9055 return s.join( "&" ).replace( r20, "+" );
9056};
9057
9058jQuery.fn.extend( {
9059 serialize: function() {
9060 return jQuery.param( this.serializeArray() );
9061 },
9062 serializeArray: function() {
9063 return this.map( function() {
9064
9065 // Can add propHook for "elements" to filter or add form elements
9066 var elements = jQuery.prop( this, "elements" );
9067 return elements ? jQuery.makeArray( elements ) : this;
9068 } )
9069 .filter( function() {
9070 var type = this.type;
9071
9072 // Use .is( ":disabled" ) so that fieldset[disabled] works
9073 return this.name && !jQuery( this ).is( ":disabled" ) &&
9074 rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&
9075 ( this.checked || !rcheckableType.test( type ) );
9076 } )
9077 .map( function( i, elem ) {
9078 var val = jQuery( this ).val();
9079
9080 return val == null ?
9081 null :
9082 jQuery.isArray( val ) ?
9083 jQuery.map( val, function( val ) {
9084 return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
9085 } ) :
9086 { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
9087 } ).get();
9088 }
9089} );
9090
9091
9092jQuery.ajaxSettings.xhr = function() {
9093 try {
9094 return new window.XMLHttpRequest();
9095 } catch ( e ) {}
9096};
9097
9098var xhrSuccessStatus = {
9099
9100 // File protocol always yields status code 0, assume 200
9101 0: 200,
9102
9103 // Support: IE9
9104 // #1450: sometimes IE returns 1223 when it should be 204
9105 1223: 204
9106 },
9107 xhrSupported = jQuery.ajaxSettings.xhr();
9108
9109support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported );
9110support.ajax = xhrSupported = !!xhrSupported;
9111
9112jQuery.ajaxTransport( function( options ) {
9113 var callback, errorCallback;
9114
9115 // Cross domain only allowed if supported through XMLHttpRequest
9116 if ( support.cors || xhrSupported && !options.crossDomain ) {
9117 return {
9118 send: function( headers, complete ) {
9119 var i,
9120 xhr = options.xhr();
9121
9122 xhr.open(
9123 options.type,
9124 options.url,
9125 options.async,
9126 options.username,
9127 options.password
9128 );
9129
9130 // Apply custom fields if provided
9131 if ( options.xhrFields ) {
9132 for ( i in options.xhrFields ) {
9133 xhr[ i ] = options.xhrFields[ i ];
9134 }
9135 }
9136
9137 // Override mime type if needed
9138 if ( options.mimeType && xhr.overrideMimeType ) {
9139 xhr.overrideMimeType( options.mimeType );
9140 }
9141
9142 // X-Requested-With header
9143 // For cross-domain requests, seeing as conditions for a preflight are
9144 // akin to a jigsaw puzzle, we simply never set it to be sure.
9145 // (it can always be set on a per-request basis or even using ajaxSetup)
9146 // For same-domain requests, won't change header if already provided.
9147 if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) {
9148 headers[ "X-Requested-With" ] = "XMLHttpRequest";
9149 }
9150
9151 // Set headers
9152 for ( i in headers ) {
9153 xhr.setRequestHeader( i, headers[ i ] );
9154 }
9155
9156 // Callback
9157 callback = function( type ) {
9158 return function() {
9159 if ( callback ) {
9160 callback = errorCallback = xhr.onload =
9161 xhr.onerror = xhr.onabort = xhr.onreadystatechange = null;
9162
9163 if ( type === "abort" ) {
9164 xhr.abort();
9165 } else if ( type === "error" ) {
9166
9167 // Support: IE9
9168 // On a manual native abort, IE9 throws
9169 // errors on any property access that is not readyState
9170 if ( typeof xhr.status !== "number" ) {
9171 complete( 0, "error" );
9172 } else {
9173 complete(
9174
9175 // File: protocol always yields status 0; see #8605, #14207
9176 xhr.status,
9177 xhr.statusText
9178 );
9179 }
9180 } else {
9181 complete(
9182 xhrSuccessStatus[ xhr.status ] || xhr.status,
9183 xhr.statusText,
9184
9185 // Support: IE9 only
9186 // IE9 has no XHR2 but throws on binary (trac-11426)
9187 // For XHR2 non-text, let the caller handle it (gh-2498)
9188 ( xhr.responseType || "text" ) !== "text" ||
9189 typeof xhr.responseText !== "string" ?
9190 { binary: xhr.response } :
9191 { text: xhr.responseText },
9192 xhr.getAllResponseHeaders()
9193 );
9194 }
9195 }
9196 };
9197 };
9198
9199 // Listen to events
9200 xhr.onload = callback();
9201 errorCallback = xhr.onerror = callback( "error" );
9202
9203 // Support: IE9
9204 // Use onreadystatechange to replace onabort
9205 // to handle uncaught aborts
9206 if ( xhr.onabort !== undefined ) {
9207 xhr.onabort = errorCallback;
9208 } else {
9209 xhr.onreadystatechange = function() {
9210
9211 // Check readyState before timeout as it changes
9212 if ( xhr.readyState === 4 ) {
9213
9214 // Allow onerror to be called first,
9215 // but that will not handle a native abort
9216 // Also, save errorCallback to a variable
9217 // as xhr.onerror cannot be accessed
9218 window.setTimeout( function() {
9219 if ( callback ) {
9220 errorCallback();
9221 }
9222 } );
9223 }
9224 };
9225 }
9226
9227 // Create the abort callback
9228 callback = callback( "abort" );
9229
9230 try {
9231
9232 // Do send the request (this may raise an exception)
9233 xhr.send( options.hasContent && options.data || null );
9234 } catch ( e ) {
9235
9236 // #14683: Only rethrow if this hasn't been notified as an error yet
9237 if ( callback ) {
9238 throw e;
9239 }
9240 }
9241 },
9242
9243 abort: function() {
9244 if ( callback ) {
9245 callback();
9246 }
9247 }
9248 };
9249 }
9250} );
9251
9252
9253
9254
9255// Install script dataType
9256jQuery.ajaxSetup( {
9257 accepts: {
9258 script: "text/javascript, application/javascript, " +
9259 "application/ecmascript, application/x-ecmascript"
9260 },
9261 contents: {
9262 script: /\b(?:java|ecma)script\b/
9263 },
9264 converters: {
9265 "text script": function( text ) {
9266 jQuery.globalEval( text );
9267 return text;
9268 }
9269 }
9270} );
9271
9272// Handle cache's special case and crossDomain
9273jQuery.ajaxPrefilter( "script", function( s ) {
9274 if ( s.cache === undefined ) {
9275 s.cache = false;
9276 }
9277 if ( s.crossDomain ) {
9278 s.type = "GET";
9279 }
9280} );
9281
9282// Bind script tag hack transport
9283jQuery.ajaxTransport( "script", function( s ) {
9284
9285 // This transport only deals with cross domain requests
9286 if ( s.crossDomain ) {
9287 var script, callback;
9288 return {
9289 send: function( _, complete ) {
9290 script = jQuery( "<script>" ).prop( {
9291 charset: s.scriptCharset,
9292 src: s.url
9293 } ).on(
9294 "load error",
9295 callback = function( evt ) {
9296 script.remove();
9297 callback = null;
9298 if ( evt ) {
9299 complete( evt.type === "error" ? 404 : 200, evt.type );
9300 }
9301 }
9302 );
9303
9304 // Use native DOM manipulation to avoid our domManip AJAX trickery
9305 document.head.appendChild( script[ 0 ] );
9306 },
9307 abort: function() {
9308 if ( callback ) {
9309 callback();
9310 }
9311 }
9312 };
9313 }
9314} );
9315
9316
9317
9318
9319var oldCallbacks = [],
9320 rjsonp = /(=)\?(?=&|$)|\?\?/;
9321
9322// Default jsonp settings
9323jQuery.ajaxSetup( {
9324 jsonp: "callback",
9325 jsonpCallback: function() {
9326 var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce++ ) );
9327 this[ callback ] = true;
9328 return callback;
9329 }
9330} );
9331
9332// Detect, normalize options and install callbacks for jsonp requests
9333jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
9334
9335 var callbackName, overwritten, responseContainer,
9336 jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?
9337 "url" :
9338 typeof s.data === "string" &&
9339 ( s.contentType || "" )
9340 .indexOf( "application/x-www-form-urlencoded" ) === 0 &&
9341 rjsonp.test( s.data ) && "data"
9342 );
9343
9344 // Handle iff the expected data type is "jsonp" or we have a parameter to set
9345 if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) {
9346
9347 // Get callback name, remembering preexisting value associated with it
9348 callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ?
9349 s.jsonpCallback() :
9350 s.jsonpCallback;
9351
9352 // Insert callback into url or form data
9353 if ( jsonProp ) {
9354 s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName );
9355 } else if ( s.jsonp !== false ) {
9356 s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName;
9357 }
9358
9359 // Use data converter to retrieve json after script execution
9360 s.converters[ "script json" ] = function() {
9361 if ( !responseContainer ) {
9362 jQuery.error( callbackName + " was not called" );
9363 }
9364 return responseContainer[ 0 ];
9365 };
9366
9367 // Force json dataType
9368 s.dataTypes[ 0 ] = "json";
9369
9370 // Install callback
9371 overwritten = window[ callbackName ];
9372 window[ callbackName ] = function() {
9373 responseContainer = arguments;
9374 };
9375
9376 // Clean-up function (fires after converters)
9377 jqXHR.always( function() {
9378
9379 // If previous value didn't exist - remove it
9380 if ( overwritten === undefined ) {
9381 jQuery( window ).removeProp( callbackName );
9382
9383 // Otherwise restore preexisting value
9384 } else {
9385 window[ callbackName ] = overwritten;
9386 }
9387
9388 // Save back as free
9389 if ( s[ callbackName ] ) {
9390
9391 // Make sure that re-using the options doesn't screw things around
9392 s.jsonpCallback = originalSettings.jsonpCallback;
9393
9394 // Save the callback name for future use
9395 oldCallbacks.push( callbackName );
9396 }
9397
9398 // Call if it was a function and we have a response
9399 if ( responseContainer && jQuery.isFunction( overwritten ) ) {
9400 overwritten( responseContainer[ 0 ] );
9401 }
9402
9403 responseContainer = overwritten = undefined;
9404 } );
9405
9406 // Delegate to script
9407 return "script";
9408 }
9409} );
9410
9411
9412
9413
9414// Argument "data" should be string of html
9415// context (optional): If specified, the fragment will be created in this context,
9416// defaults to document
9417// keepScripts (optional): If true, will include scripts passed in the html string
9418jQuery.parseHTML = function( data, context, keepScripts ) {
9419 if ( !data || typeof data !== "string" ) {
9420 return null;
9421 }
9422 if ( typeof context === "boolean" ) {
9423 keepScripts = context;
9424 context = false;
9425 }
9426 context = context || document;
9427
9428 var parsed = rsingleTag.exec( data ),
9429 scripts = !keepScripts && [];
9430
9431 // Single tag
9432 if ( parsed ) {
9433 return [ context.createElement( parsed[ 1 ] ) ];
9434 }
9435
9436 parsed = buildFragment( [ data ], context, scripts );
9437
9438 if ( scripts && scripts.length ) {
9439 jQuery( scripts ).remove();
9440 }
9441
9442 return jQuery.merge( [], parsed.childNodes );
9443};
9444
9445
9446// Keep a copy of the old load method
9447var _load = jQuery.fn.load;
9448
9449/**
9450 * Load a url into a page
9451 */
9452jQuery.fn.load = function( url, params, callback ) {
9453 if ( typeof url !== "string" && _load ) {
9454 return _load.apply( this, arguments );
9455 }
9456
9457 var selector, type, response,
9458 self = this,
9459 off = url.indexOf( " " );
9460
9461 if ( off > -1 ) {
9462 selector = jQuery.trim( url.slice( off ) );
9463 url = url.slice( 0, off );
9464 }
9465
9466 // If it's a function
9467 if ( jQuery.isFunction( params ) ) {
9468
9469 // We assume that it's the callback
9470 callback = params;
9471 params = undefined;
9472
9473 // Otherwise, build a param string
9474 } else if ( params && typeof params === "object" ) {
9475 type = "POST";
9476 }
9477
9478 // If we have elements to modify, make the request
9479 if ( self.length > 0 ) {
9480 jQuery.ajax( {
9481 url: url,
9482
9483 // If "type" variable is undefined, then "GET" method will be used.
9484 // Make value of this field explicit since
9485 // user can override it through ajaxSetup method
9486 type: type || "GET",
9487 dataType: "html",
9488 data: params
9489 } ).done( function( responseText ) {
9490
9491 // Save response for use in complete callback
9492 response = arguments;
9493
9494 self.html( selector ?
9495
9496 // If a selector was specified, locate the right elements in a dummy div
9497 // Exclude scripts to avoid IE 'Permission Denied' errors
9498 jQuery( "<div>" ).append( jQuery.parseHTML( responseText ) ).find( selector ) :
9499
9500 // Otherwise use the full result
9501 responseText );
9502
9503 // If the request succeeds, this function gets "data", "status", "jqXHR"
9504 // but they are ignored because response was set above.
9505 // If it fails, this function gets "jqXHR", "status", "error"
9506 } ).always( callback && function( jqXHR, status ) {
9507 self.each( function() {
9508 callback.apply( this, response || [ jqXHR.responseText, status, jqXHR ] );
9509 } );
9510 } );
9511 }
9512
9513 return this;
9514};
9515
9516
9517
9518
9519// Attach a bunch of functions for handling common AJAX events
9520jQuery.each( [
9521 "ajaxStart",
9522 "ajaxStop",
9523 "ajaxComplete",
9524 "ajaxError",
9525 "ajaxSuccess",
9526 "ajaxSend"
9527], function( i, type ) {
9528 jQuery.fn[ type ] = function( fn ) {
9529 return this.on( type, fn );
9530 };
9531} );
9532
9533
9534
9535
9536jQuery.expr.filters.animated = function( elem ) {
9537 return jQuery.grep( jQuery.timers, function( fn ) {
9538 return elem === fn.elem;
9539 } ).length;
9540};
9541
9542
9543
9544
9545/**
9546 * Gets a window from an element
9547 */
9548function getWindow( elem ) {
9549 return jQuery.isWindow( elem ) ? elem : elem.nodeType === 9 && elem.defaultView;
9550}
9551
9552jQuery.offset = {
9553 setOffset: function( elem, options, i ) {
9554 var curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition,
9555 position = jQuery.css( elem, "position" ),
9556 curElem = jQuery( elem ),
9557 props = {};
9558
9559 // Set position first, in-case top/left are set even on static elem
9560 if ( position === "static" ) {
9561 elem.style.position = "relative";
9562 }
9563
9564 curOffset = curElem.offset();
9565 curCSSTop = jQuery.css( elem, "top" );
9566 curCSSLeft = jQuery.css( elem, "left" );
9567 calculatePosition = ( position === "absolute" || position === "fixed" ) &&
9568 ( curCSSTop + curCSSLeft ).indexOf( "auto" ) > -1;
9569
9570 // Need to be able to calculate position if either
9571 // top or left is auto and position is either absolute or fixed
9572 if ( calculatePosition ) {
9573 curPosition = curElem.position();
9574 curTop = curPosition.top;
9575 curLeft = curPosition.left;
9576
9577 } else {
9578 curTop = parseFloat( curCSSTop ) || 0;
9579 curLeft = parseFloat( curCSSLeft ) || 0;
9580 }
9581
9582 if ( jQuery.isFunction( options ) ) {
9583
9584 // Use jQuery.extend here to allow modification of coordinates argument (gh-1848)
9585 options = options.call( elem, i, jQuery.extend( {}, curOffset ) );
9586 }
9587
9588 if ( options.top != null ) {
9589 props.top = ( options.top - curOffset.top ) + curTop;
9590 }
9591 if ( options.left != null ) {
9592 props.left = ( options.left - curOffset.left ) + curLeft;
9593 }
9594
9595 if ( "using" in options ) {
9596 options.using.call( elem, props );
9597
9598 } else {
9599 curElem.css( props );
9600 }
9601 }
9602};
9603
9604jQuery.fn.extend( {
9605 offset: function( options ) {
9606 if ( arguments.length ) {
9607 return options === undefined ?
9608 this :
9609 this.each( function( i ) {
9610 jQuery.offset.setOffset( this, options, i );
9611 } );
9612 }
9613
9614 var docElem, win,
9615 elem = this[ 0 ],
9616 box = { top: 0, left: 0 },
9617 doc = elem && elem.ownerDocument;
9618
9619 if ( !doc ) {
9620 return;
9621 }
9622
9623 docElem = doc.documentElement;
9624
9625 // Make sure it's not a disconnected DOM node
9626 if ( !jQuery.contains( docElem, elem ) ) {
9627 return box;
9628 }
9629
9630 box = elem.getBoundingClientRect();
9631 win = getWindow( doc );
9632 return {
9633 top: box.top + win.pageYOffset - docElem.clientTop,
9634 left: box.left + win.pageXOffset - docElem.clientLeft
9635 };
9636 },
9637
9638 position: function() {
9639 if ( !this[ 0 ] ) {
9640 return;
9641 }
9642
9643 var offsetParent, offset,
9644 elem = this[ 0 ],
9645 parentOffset = { top: 0, left: 0 };
9646
9647 // Fixed elements are offset from window (parentOffset = {top:0, left: 0},
9648 // because it is its only offset parent
9649 if ( jQuery.css( elem, "position" ) === "fixed" ) {
9650
9651 // Assume getBoundingClientRect is there when computed position is fixed
9652 offset = elem.getBoundingClientRect();
9653
9654 } else {
9655
9656 // Get *real* offsetParent
9657 offsetParent = this.offsetParent();
9658
9659 // Get correct offsets
9660 offset = this.offset();
9661 if ( !jQuery.nodeName( offsetParent[ 0 ], "html" ) ) {
9662 parentOffset = offsetParent.offset();
9663 }
9664
9665 // Add offsetParent borders
9666 parentOffset.top += jQuery.css( offsetParent[ 0 ], "borderTopWidth", true );
9667 parentOffset.left += jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true );
9668 }
9669
9670 // Subtract parent offsets and element margins
9671 return {
9672 top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ),
9673 left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true )
9674 };
9675 },
9676
9677 // This method will return documentElement in the following cases:
9678 // 1) For the element inside the iframe without offsetParent, this method will return
9679 // documentElement of the parent window
9680 // 2) For the hidden or detached element
9681 // 3) For body or html element, i.e. in case of the html node - it will return itself
9682 //
9683 // but those exceptions were never presented as a real life use-cases
9684 // and might be considered as more preferable results.
9685 //
9686 // This logic, however, is not guaranteed and can change at any point in the future
9687 offsetParent: function() {
9688 return this.map( function() {
9689 var offsetParent = this.offsetParent;
9690
9691 while ( offsetParent && jQuery.css( offsetParent, "position" ) === "static" ) {
9692 offsetParent = offsetParent.offsetParent;
9693 }
9694
9695 return offsetParent || documentElement;
9696 } );
9697 }
9698} );
9699
9700// Create scrollLeft and scrollTop methods
9701jQuery.each( { scrollLeft: "pageXOffset", scrollTop: "pageYOffset" }, function( method, prop ) {
9702 var top = "pageYOffset" === prop;
9703
9704 jQuery.fn[ method ] = function( val ) {
9705 return access( this, function( elem, method, val ) {
9706 var win = getWindow( elem );
9707
9708 if ( val === undefined ) {
9709 return win ? win[ prop ] : elem[ method ];
9710 }
9711
9712 if ( win ) {
9713 win.scrollTo(
9714 !top ? val : win.pageXOffset,
9715 top ? val : win.pageYOffset
9716 );
9717
9718 } else {
9719 elem[ method ] = val;
9720 }
9721 }, method, val, arguments.length );
9722 };
9723} );
9724
9725// Support: Safari<7-8+, Chrome<37-44+
9726// Add the top/left cssHooks using jQuery.fn.position
9727// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
9728// Blink bug: https://code.google.com/p/chromium/issues/detail?id=229280
9729// getComputedStyle returns percent when specified for top/left/bottom/right;
9730// rather than make the css module depend on the offset module, just check for it here
9731jQuery.each( [ "top", "left" ], function( i, prop ) {
9732 jQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition,
9733 function( elem, computed ) {
9734 if ( computed ) {
9735 computed = curCSS( elem, prop );
9736
9737 // If curCSS returns percentage, fallback to offset
9738 return rnumnonpx.test( computed ) ?
9739 jQuery( elem ).position()[ prop ] + "px" :
9740 computed;
9741 }
9742 }
9743 );
9744} );
9745
9746
9747// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
9748jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
9749 jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name },
9750 function( defaultExtra, funcName ) {
9751
9752 // Margin is only for outerHeight, outerWidth
9753 jQuery.fn[ funcName ] = function( margin, value ) {
9754 var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ),
9755 extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" );
9756
9757 return access( this, function( elem, type, value ) {
9758 var doc;
9759
9760 if ( jQuery.isWindow( elem ) ) {
9761
9762 // As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there
9763 // isn't a whole lot we can do. See pull request at this URL for discussion:
9764 // https://github.com/jquery/jquery/pull/764
9765 return elem.document.documentElement[ "client" + name ];
9766 }
9767
9768 // Get document width or height
9769 if ( elem.nodeType === 9 ) {
9770 doc = elem.documentElement;
9771
9772 // Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height],
9773 // whichever is greatest
9774 return Math.max(
9775 elem.body[ "scroll" + name ], doc[ "scroll" + name ],
9776 elem.body[ "offset" + name ], doc[ "offset" + name ],
9777 doc[ "client" + name ]
9778 );
9779 }
9780
9781 return value === undefined ?
9782
9783 // Get width or height on the element, requesting but not forcing parseFloat
9784 jQuery.css( elem, type, extra ) :
9785
9786 // Set width or height on the element
9787 jQuery.style( elem, type, value, extra );
9788 }, type, chainable ? margin : undefined, chainable, null );
9789 };
9790 } );
9791} );
9792
9793
9794jQuery.fn.extend( {
9795
9796 bind: function( types, data, fn ) {
9797 return this.on( types, null, data, fn );
9798 },
9799 unbind: function( types, fn ) {
9800 return this.off( types, null, fn );
9801 },
9802
9803 delegate: function( selector, types, data, fn ) {
9804 return this.on( types, selector, data, fn );
9805 },
9806 undelegate: function( selector, types, fn ) {
9807
9808 // ( namespace ) or ( selector, types [, fn] )
9809 return arguments.length === 1 ?
9810 this.off( selector, "**" ) :
9811 this.off( types, selector || "**", fn );
9812 },
9813 size: function() {
9814 return this.length;
9815 }
9816} );
9817
9818jQuery.fn.andSelf = jQuery.fn.addBack;
9819
9820
9821
9822
9823// Register as a named AMD module, since jQuery can be concatenated with other
9824// files that may use define, but not via a proper concatenation script that
9825// understands anonymous AMD modules. A named AMD is safest and most robust
9826// way to register. Lowercase jquery is used because AMD module names are
9827// derived from file names, and jQuery is normally delivered in a lowercase
9828// file name. Do this after creating the global so that if an AMD module wants
9829// to call noConflict to hide this version of jQuery, it will work.
9830
9831// Note that for maximum portability, libraries that are not jQuery should
9832// declare themselves as anonymous modules, and avoid setting a global if an
9833// AMD loader is present. jQuery is a special case. For more information, see
9834// https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon
9835
9836if ( typeof define === "function" && define.amd ) {
9837 define( "jquery", [], function() {
9838 return jQuery;
9839 } );
9840}
9841
9842
9843
9844var
9845
9846 // Map over jQuery in case of overwrite
9847 _jQuery = window.jQuery,
9848
9849 // Map over the $ in case of overwrite
9850 _$ = window.$;
9851
9852jQuery.noConflict = function( deep ) {
9853 if ( window.$ === jQuery ) {
9854 window.$ = _$;
9855 }
9856
9857 if ( deep && window.jQuery === jQuery ) {
9858 window.jQuery = _jQuery;
9859 }
9860
9861 return jQuery;
9862};
9863
9864// Expose jQuery and $ identifiers, even in AMD
9865// (#7102#comment:10, https://github.com/jquery/jquery/pull/557)
9866// and CommonJS for browser emulators (#13566)
9867if ( !noGlobal ) {
9868 window.jQuery = window.$ = jQuery;
9869}
9870
9871return jQuery;
9872}));
9873 </script>
9874 <script>
9875 (function(root, factory) {
9876 if (typeof define === 'function' && define.amd) {
9877 define(['jquery'], factory);
9878 }
9879 else if (typeof module === 'object' && module.exports) {
9880 module.exports = factory(require('jquery'));
9881 }
9882 else {
9883 factory(root.jQuery);
9884 }
9885 }(this, function($) {
9886 "use strict";
9887
9888 /*
9889 * Plugin class
9890 */
9891 var jQCloud = function (element, word_array, options) {
9892 this.$element = $(element);
9893
9894 this.word_array = word_array || [];
9895 this.options = options;
9896
9897 this.sizeGenerator = null;
9898 this.colorGenerator = null;
9899
9900 // Data used internally
9901 this.data = {
9902 placed_words: [],
9903 timeouts: {},
9904 namespace: null,
9905 step: null,
9906 angle: null,
9907 aspect_ratio: null,
9908 max_weight: null,
9909 min_weight: null,
9910 sizes: [],
9911 colors: []
9912 };
9913
9914 this.initialize();
9915 };
9916
9917 jQCloud.DEFAULTS = {
9918 width: 100,
9919 height: 100,
9920 center: { x: 0.5, y: 0.5 },
9921 steps: 10,
9922 delay: null,
9923 shape: 'elliptic',
9924 classPattern: 'w{n}',
9925 encodeURI: true,
9926 removeOverflowing: true,
9927 afterCloudRender: null,
9928 autoResize: false,
9929 colors: null,
9930 fontSize: null,
9931 template: null
9932 };
9933
9934 jQCloud.prototype = {
9935 initialize: function() {
9936 // Set/Get dimensions
9937 if (this.options.width) {
9938 this.$element.width(this.options.width);
9939 }
9940 else {
9941 this.options.width = this.$element.width();
9942 }
9943 if (this.options.height) {
9944 this.$element.height(this.options.height);
9945 }
9946 else {
9947 this.options.height = this.$element.height();
9948 }
9949
9950 // Default options value
9951 this.options = $.extend(true, {}, jQCloud.DEFAULTS, this.options);
9952
9953 // Ensure delay
9954 if (this.options.delay === null) {
9955 this.options.delay = this.word_array.length > 50 ? 10 : 0;
9956 }
9957
9958 // Backward compatibility
9959 if (this.options.center.x > 1) {
9960 this.options.center.x = this.options.center.x / this.options.width;
9961 this.options.center.y = this.options.center.y / this.options.height;
9962 }
9963
9964 // Create colorGenerator function from options
9965 // Direct function
9966 if (typeof this.options.colors == 'function') {
9967 this.colorGenerator = this.options.colors;
9968 }
9969 // Array of sizes
9970 else if ($.isArray(this.options.colors)) {
9971 var cl = this.options.colors.length;
9972 if (cl > 0) {
9973 // Fill the sizes array to X items
9974 if (cl < this.options.steps) {
9975 for (var i=cl; i<this.options.steps; i++) {
9976 this.options.colors[i] = this.options.colors[cl-1];
9977 }
9978 }
9979
9980 this.colorGenerator = function(weight) {
9981 return this.options.colors[this.options.steps - weight];
9982 };
9983 }
9984 }
9985
9986 // Create sizeGenerator function from options
9987 // Direct function
9988 if (typeof this.options.fontSize == 'function') {
9989 this.sizeGenerator = this.options.fontSize;
9990 }
9991 // Object with 'from' and 'to'
9992 else if ($.isPlainObject(this.options.fontSize)) {
9993 this.sizeGenerator = function(width, height, weight) {
9994 var max = width * this.options.fontSize.from,
9995 min = width * this.options.fontSize.to;
9996 return Math.round(min + (max - min) * 1.0 / (this.options.steps-1) * (weight - 1)) + 'px';
9997 };
9998 }
9999 // Array of sizes
10000 else if ($.isArray(this.options.fontSize)) {
10001 var sl = this.options.fontSize.length;
10002 if (sl > 0) {
10003 // Fill the sizes array to X items
10004 if (sl < this.options.steps) {
10005 for (var j=sl; j<this.options.steps; j++) {
10006 this.options.fontSize[j] = this.options.fontSize[sl-1];
10007 }
10008 }
10009
10010 this.sizeGenerator = function(width, height, weight) {
10011 return this.options.fontSize[this.options.steps - weight];
10012 };
10013 }
10014 }
10015
10016 this.data.angle = Math.random() * 6.28;
10017 this.data.step = (this.options.shape === 'rectangular') ? 18.0 : 2.0;
10018 this.data.aspect_ratio = this.options.width / this.options.height;
10019 this.clearTimeouts();
10020
10021 // Namespace word ids to avoid collisions between multiple clouds
10022 this.data.namespace = (this.$element.attr('id') || Math.floor((Math.random()*1000000)).toString(36)) + '_word_';
10023
10024 this.$element.addClass('jqcloud');
10025
10026 // Container's CSS position cannot be 'static'
10027 if (this.$element.css('position') === 'static') {
10028 this.$element.css('position', 'relative');
10029 }
10030
10031 // Delay execution so that the browser can render the page before the computatively intensive word cloud drawing
10032 this.createTimeout($.proxy(this.drawWordCloud, this), 10);
10033
10034 // Attach window resize event
10035 if (this.options.autoResize) {
10036 $(window).on('resize', throttle(this.resize, 50, this));
10037 }
10038 },
10039
10040 // Helper function to keep track of timeouts so they can be destroyed
10041 createTimeout: function(callback, time) {
10042 var timeout = setTimeout($.proxy(function(){
10043 delete this.data.timeouts[timeout];
10044 callback();
10045 }, this), time);
10046 this.data.timeouts[timeout] = true;
10047 },
10048
10049 // Destroy all timeouts
10050 clearTimeouts: function() {
10051 $.each(this.data.timeouts, function(key){
10052 clearTimeout(key);
10053 });
10054 this.data.timeouts = {};
10055 },
10056
10057 // Pairwise overlap detection
10058 overlapping: function(a, b) {
10059 if (Math.abs(2.0*a.left + a.width - 2.0*b.left - b.width) < a.width + b.width) {
10060 if (Math.abs(2.0*a.top + a.height - 2.0*b.top - b.height) < a.height + b.height) {
10061 return true;
10062 }
10063 }
10064 return false;
10065 },
10066
10067 // Helper function to test if an element overlaps others
10068 hitTest: function(elem) {
10069 // Check elements for overlap one by one, stop and return false as soon as an overlap is found
10070 for(var i=0, l=this.data.placed_words.length; i<l; i++) {
10071 if (this.overlapping(elem, this.data.placed_words[i])) {
10072 return true;
10073 }
10074 }
10075 return false;
10076 },
10077
10078 // Initialize the drawing of the whole cloud
10079 drawWordCloud: function() {
10080 var i, l;
10081
10082 this.$element.children('[id^="' + this.data.namespace + '"]').remove();
10083
10084 if (this.word_array.length === 0) {
10085 return;
10086 }
10087
10088 // Make sure every weight is a number before sorting
10089 for (i=0, l=this.word_array.length; i<l; i++) {
10090 this.word_array[i].weight = parseFloat(this.word_array[i].weight, 10);
10091 }
10092
10093 // Sort word_array from the word with the highest weight to the one with the lowest
10094 this.word_array.sort(function(a, b) {
10095 return b.weight - a.weight;
10096 });
10097
10098 // Kepp trace of bounds
10099 this.data.max_weight = this.word_array[0].weight;
10100 this.data.min_weight = this.word_array[this.word_array.length - 1].weight;
10101
10102 // Generate colors
10103 this.data.colors = [];
10104 if (this.colorGenerator) {
10105 for (i=0; i<this.options.steps; i++) {
10106 this.data.colors.push(this.colorGenerator(i+1));
10107 }
10108 }
10109
10110 // Generate font sizes
10111 this.data.sizes = [];
10112 if (this.sizeGenerator) {
10113 for (i=0; i<this.options.steps; i++) {
10114 this.data.sizes.push(this.sizeGenerator(this.options.width, this.options.height, i+1));
10115 }
10116 }
10117
10118 // Iterate drawOneWord on every word, immediately or with delay
10119 if (this.options.delay > 0){
10120 this.drawOneWordDelayed();
10121 }
10122 else {
10123 for (i=0, l=this.word_array.length; i<l; i++) {
10124 this.drawOneWord(i, this.word_array[i]);
10125 }
10126
10127 if (typeof this.options.afterCloudRender === 'function') {
10128 this.options.afterCloudRender.call(this.$element);
10129 }
10130 }
10131 },
10132
10133 // Function to draw a word, by moving it in spiral until it finds a suitable empty place
10134 drawOneWord: function(index, word) {
10135 var word_id = this.data.namespace + index,
10136 word_selector = '#' + word_id,
10137
10138 // option.shape == 'elliptic'
10139 angle = this.data.angle,
10140 radius = 0.0,
10141
10142 // option.shape == 'rectangular'
10143 steps_in_direction = 0.0,
10144 quarter_turns = 0.0,
10145
10146 weight = Math.floor(this.options.steps / 2),
10147 word_span,
10148 word_size,
10149 word_style;
10150
10151 // Create word attr object
10152 word.attr = $.extend({}, word.html, { id: word_id });
10153
10154 // Linearly map the original weight to a discrete scale from 1 to 10
10155 // Only if weights are different
10156 if (this.data.max_weight != this.data.min_weight) {
10157 weight = Math.round((word.weight - this.data.min_weight) * 1.0 * (this.options.steps-1) / (this.data.max_weight - this.data.min_weight)) + 1;
10158 }
10159 word_span = $('<span>').attr(word.attr);
10160
10161 // Apply class
10162 if (this.options.classPattern) {
10163 word_span.addClass(this.options.classPattern.replace('{n}', weight));
10164 }
10165
10166 // Apply color
10167 if (this.data.colors.length) {
10168 word_span.css('color', this.data.colors[weight-1]);
10169 }
10170
10171 // Apply color from word property
10172 if (word.color) {
10173 word_span.css('color', word.color);
10174 }
10175
10176 // Apply size
10177 if (this.data.sizes.length) {
10178 word_span.css('font-size', this.data.sizes[weight-1]);
10179 }
10180
10181 //Render using template function if provided.
10182 if (this.options.template) {
10183 word_span.html(this.options.template(word));
10184 } else if (word.link) {
10185 // Append link if word.link attribute was set
10186 // If link is a string, then use it as the link href
10187 if (typeof word.link === 'string') {
10188 word.link = { href: word.link };
10189 }
10190
10191 if (this.options.encodeURI) {
10192 word.link.href = encodeURI(word.link.href).replace(/'/g, '%27');
10193 }
10194
10195 word_span.append($('<a>').attr(word.link).text(word.text));
10196 }
10197 else {
10198 word_span.text(word.text);
10199 }
10200
10201 // Bind handlers to words
10202 if (word.handlers) {
10203 word_span.on(word.handlers);
10204 }
10205
10206 this.$element.append(word_span);
10207
10208 word_size = {
10209 width: word_span.outerWidth(),
10210 height: word_span.outerHeight()
10211 };
10212 word_size.left = this.options.center.x*this.options.width - word_size.width / 2.0;
10213 word_size.top = this.options.center.y*this.options.height - word_size.height / 2.0;
10214
10215 // Save a reference to the style property, for better performance
10216 word_style = word_span[0].style;
10217 word_style.position = 'absolute';
10218 word_style.left = word_size.left + 'px';
10219 word_style.top = word_size.top + 'px';
10220
10221 while(this.hitTest(word_size)) {
10222 // option shape is 'rectangular' so move the word in a rectangular spiral
10223 if (this.options.shape === 'rectangular') {
10224 steps_in_direction++;
10225
10226 if (steps_in_direction * this.data.step > (1 + Math.floor(quarter_turns / 2.0)) * this.data.step * ((quarter_turns % 4 % 2) === 0 ? 1 : this.data.aspect_ratio)) {
10227 steps_in_direction = 0.0;
10228 quarter_turns++;
10229 }
10230
10231 switch(quarter_turns % 4) {
10232 case 1:
10233 word_size.left += this.data.step * this.data.aspect_ratio + Math.random() * 2.0;
10234 break;
10235 case 2:
10236 word_size.top -= this.data.step + Math.random() * 2.0;
10237 break;
10238 case 3:
10239 word_size.left -= this.data.step * this.data.aspect_ratio + Math.random() * 2.0;
10240 break;
10241 case 0:
10242 word_size.top += this.data.step + Math.random() * 2.0;
10243 break;
10244 }
10245 }
10246 // Default settings: elliptic spiral shape
10247 else {
10248 radius += this.data.step;
10249 angle += (index % 2 === 0 ? 1 : -1) * this.data.step;
10250
10251 word_size.left = this.options.center.x*this.options.width - (word_size.width / 2.0) + (radius*Math.cos(angle)) * this.data.aspect_ratio;
10252 word_size.top = this.options.center.y*this.options.height + radius*Math.sin(angle) - (word_size.height / 2.0);
10253 }
10254 word_style.left = word_size.left + 'px';
10255 word_style.top = word_size.top + 'px';
10256 }
10257
10258 // Don't render word if part of it would be outside the container
10259 if (this.options.removeOverflowing && (
10260 word_size.left < 0 || word_size.top < 0 ||
10261 (word_size.left + word_size.width) > this.options.width ||
10262 (word_size.top + word_size.height) > this.options.height
10263 )
10264 ) {
10265 word_span.remove();
10266 return;
10267 }
10268
10269 // Save position for further usage
10270 this.data.placed_words.push(word_size);
10271
10272 if (typeof word.afterWordRender === 'function') {
10273 word.afterWordRender.call(word_span);
10274 }
10275 },
10276
10277 // Draw one word then recall the function after a delay
10278 drawOneWordDelayed: function(index) {
10279 index = index || 0;
10280
10281 // if not visible then do not attempt to draw
10282 if (!this.$element.is(':visible')) {
10283 this.createTimeout($.proxy(function(){
10284 this.drawOneWordDelayed(index);
10285 }, this), 10);
10286
10287 return;
10288 }
10289
10290 if (index < this.word_array.length) {
10291 this.drawOneWord(index, this.word_array[index]);
10292
10293 this.createTimeout($.proxy(function(){
10294 this.drawOneWordDelayed(index + 1);
10295 }, this), this.options.delay);
10296 }
10297 else {
10298 if (typeof this.options.afterCloudRender == 'function') {
10299 this.options.afterCloudRender.call(this.$element);
10300 }
10301 }
10302 },
10303
10304 // Destroy any data and objects added by the plugin
10305 destroy: function() {
10306 this.clearTimeouts();
10307 this.$element.removeClass('jqcloud');
10308 this.$element.removeData('jqcloud');
10309 this.$element.children('[id^="' + this.data.namespace + '"]').remove();
10310 },
10311
10312 // Update the list of words
10313 update: function(word_array) {
10314 this.word_array = word_array;
10315 this.data.placed_words = [];
10316
10317 this.clearTimeouts();
10318 this.drawWordCloud();
10319 },
10320
10321 resize: function() {
10322 var new_size = {
10323 width: this.$element.width(),
10324 height: this.$element.height()
10325 };
10326
10327 if (new_size.width != this.options.width || new_size.height != this.options.height) {
10328 this.options.width = new_size.width;
10329 this.options.height = new_size.height;
10330 this.data.aspect_ratio = this.options.width / this.options.height;
10331
10332 this.update(this.word_array);
10333 }
10334 },
10335 };
10336
10337 /*
10338 * Apply throttling to a callback
10339 * @param callback {function}
10340 * @param delay {int} milliseconds
10341 * @param context {object|null}
10342 * @return {function}
10343 */
10344 function throttle(callback, delay, context) {
10345 var state = {
10346 pid: null,
10347 last: 0
10348 };
10349
10350 return function() {
10351 var elapsed = new Date().getTime() - state.last,
10352 args = arguments,
10353 that = this;
10354
10355 function exec() {
10356 state.last = new Date().getTime();
10357 return callback.apply(context || that, Array.prototype.slice.call(args));
10358 }
10359
10360 if (elapsed > delay) {
10361 return exec();
10362 }
10363 else {
10364 clearTimeout(state.pid);
10365 state.pid = setTimeout(exec, delay - elapsed);
10366 }
10367 };
10368 }
10369
10370 /*
10371 * jQuery plugin
10372 */
10373 $.fn.jQCloud = function(word_array, option) {
10374 var args = arguments;
10375
10376 return this.each(function () {
10377 var $this = $(this),
10378 data = $this.data('jqcloud');
10379
10380 if (!data && word_array === 'destroy') {
10381 // Don't even try to initialize when called with 'destroy'
10382 return;
10383 }
10384 if (!data) {
10385 var options = typeof option === 'object' ? option : {};
10386 $this.data('jqcloud', (data = new jQCloud(this, word_array, options)));
10387 }
10388 else if (typeof word_array === 'string') {
10389 data[word_array].apply(data, Array.prototype.slice.call(args, 1));
10390 }
10391 });
10392 };
10393
10394 $.fn.jQCloud.defaults = {
10395 set: function(options) {
10396 $.extend(true, jQCloud.DEFAULTS, options);
10397 },
10398 get: function(key) {
10399 var options = jQCloud.DEFAULTS;
10400 if (key) {
10401 options = options[key];
10402 }
10403 return $.extend(true, {}, options);
10404 }
10405 };
10406 }));
10407
10408 </script>
10409 <script>
10410 var words = [
10411 {text: "Lorem", weight: 13},
10412 {text: "Ipsum", weight: 10.5},
10413 {text: "Dolor", weight: 9.4},
10414 {text: "Sit", weight: 8},
10415 {text: "Amet", weight: 6.2},
10416 {text: "Consectetur", weight: 5},
10417 {text: "Adipiscing", weight: 5},
10418 /* ... */
10419 ];
10420 var words = ${stringWeights}.map(function(item){return JSON.parse(item);});
10421 $('#cloud').jQCloud(words, {
10422 autoResize: true
10423 });
10424
10425 </script>
10426 </body>
10427 </html>`;
10428 }
10429
10430}