aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rwxr-xr-xplugins/addlink_toolbar/addlink_toolbar.css4
-rwxr-xr-xplugins/addlink_toolbar/addlink_toolbar.html6
-rwxr-xr-xplugins/addlink_toolbar/addlink_toolbar.php38
-rw-r--r--plugins/archiveorg/archiveorg.html1
-rw-r--r--plugins/archiveorg/archiveorg.php25
-rw-r--r--plugins/archiveorg/internetarchive.pngbin0 -> 878 bytes
-rw-r--r--plugins/playvideos/README.md71
-rw-r--r--plugins/playvideos/jquery-1.11.2.js10346
-rw-r--r--plugins/playvideos/jquery-1.11.2.min.js4
-rw-r--r--plugins/playvideos/playvideos.html1
-rw-r--r--plugins/playvideos/playvideos.php40
-rw-r--r--plugins/playvideos/youtube_playlist.js196
-rw-r--r--plugins/qrcode/qr-1.1.3.js1215
-rw-r--r--plugins/qrcode/qr-1.1.3.min.js5
-rw-r--r--plugins/qrcode/qrcode.html5
-rw-r--r--plugins/qrcode/qrcode.php41
-rw-r--r--plugins/qrcode/qrcode.pngbin0 -> 321 bytes
-rw-r--r--plugins/qrcode/shaarli-qrcode.js56
-rw-r--r--tests/plugins/PlugQrcodeTest.php67
-rw-r--r--tests/plugins/PluginAddlinkTest.php100
-rw-r--r--tests/plugins/PluginArchiveorgTest.php48
-rw-r--r--tests/plugins/PluginPlayvideosTest.php61
22 files changed, 12330 insertions, 0 deletions
diff --git a/plugins/addlink_toolbar/addlink_toolbar.css b/plugins/addlink_toolbar/addlink_toolbar.css
new file mode 100755
index 00000000..b6a612f0
--- /dev/null
+++ b/plugins/addlink_toolbar/addlink_toolbar.css
@@ -0,0 +1,4 @@
1#addlink_toolbar {
2 display: inline;
3 margin: 0 0 0 25px;
4} \ No newline at end of file
diff --git a/plugins/addlink_toolbar/addlink_toolbar.html b/plugins/addlink_toolbar/addlink_toolbar.html
new file mode 100755
index 00000000..f38c41a0
--- /dev/null
+++ b/plugins/addlink_toolbar/addlink_toolbar.html
@@ -0,0 +1,6 @@
1<div id="addlink_toolbar">
2 <form method="GET" action="" name="addform" class="addform">
3 <input type="text" name="post" placeholder="URI">
4 <input type="submit" value="Add link" class="bigbutton">
5 </form>
6</div> \ No newline at end of file
diff --git a/plugins/addlink_toolbar/addlink_toolbar.php b/plugins/addlink_toolbar/addlink_toolbar.php
new file mode 100755
index 00000000..ba3849cf
--- /dev/null
+++ b/plugins/addlink_toolbar/addlink_toolbar.php
@@ -0,0 +1,38 @@
1<?php
2
3/**
4 * Plugin addlink_toolbar.
5 * Adds the addlink input on the linklist page.
6 */
7
8/**
9 * When linklist is displayed, add play videos to header's toolbar.
10 *
11 * @param array $data - header data.
12 *
13 * @return mixed - header data with addlink toolbar item.
14 */
15function hook_addlink_toolbar_render_header($data)
16{
17 if ($data['_PAGE_'] == Router::$PAGE_LINKLIST && $data['_LOGGEDIN_'] === true) {
18 $data['fields_toolbar'][] = file_get_contents(PluginManager::$PLUGINS_PATH . '/addlink_toolbar/addlink_toolbar.html');
19 }
20
21 return $data;
22}
23
24/**
25 * When link list is displayed, include markdown CSS.
26 *
27 * @param array $data - includes data.
28 *
29 * @return mixed - includes data with markdown CSS file added.
30 */
31function hook_addlink_toolbar_render_includes($data)
32{
33 if ($data['_PAGE_'] == Router::$PAGE_LINKLIST && $data['_LOGGEDIN_'] === true) {
34 $data['css_files'][] = PluginManager::$PLUGINS_PATH . '/addlink_toolbar/addlink_toolbar.css';
35 }
36
37 return $data;
38} \ No newline at end of file
diff --git a/plugins/archiveorg/archiveorg.html b/plugins/archiveorg/archiveorg.html
new file mode 100644
index 00000000..ce3bc6b7
--- /dev/null
+++ b/plugins/archiveorg/archiveorg.html
@@ -0,0 +1 @@
<span><a href="https://web.archive.org/web/%s"><img width="13" height="13" src="plugins/archiveorg/internetarchive.png" title="View on archive.org" /></a></span> \ No newline at end of file
diff --git a/plugins/archiveorg/archiveorg.php b/plugins/archiveorg/archiveorg.php
new file mode 100644
index 00000000..7d172584
--- /dev/null
+++ b/plugins/archiveorg/archiveorg.php
@@ -0,0 +1,25 @@
1<?php
2/**
3 * Plugin Archive.org.
4 *
5 * Add an icon in the link list for archive.org.
6 */
7
8/**
9 * Add archive.org icon to link_plugin when rendering linklist.
10 *
11 * @param mixed $data - linklist data.
12 *
13 * @return mixed - linklist data with archive.org plugin.
14 */
15function hook_archiveorg_render_linklist($data)
16{
17 $archive_html = file_get_contents(PluginManager::$PLUGINS_PATH . '/archiveorg/archiveorg.html');
18
19 foreach ($data['links'] as &$value) {
20 $archive = sprintf($archive_html, $value['url']);
21 $value['link_plugin'][] = $archive;
22 }
23
24 return $data;
25}
diff --git a/plugins/archiveorg/internetarchive.png b/plugins/archiveorg/internetarchive.png
new file mode 100644
index 00000000..ca070769
--- /dev/null
+++ b/plugins/archiveorg/internetarchive.png
Binary files differ
diff --git a/plugins/playvideos/README.md b/plugins/playvideos/README.md
new file mode 100644
index 00000000..ec1ead8d
--- /dev/null
+++ b/plugins/playvideos/README.md
@@ -0,0 +1,71 @@
1### ► Play Videos plugin for Shaarli
2This plugin adds a `► Play Videos` button to [Shaarli](https://github.com/shaarli/Shaarli)'s toolbar. Click this button to play all videos on the page in an overlay HTML5 player. Nice for continuous stream of music, documentaries, talks...
3
4This uses code from https://zaius.github.io/youtube_playlist/ and is currently only compatible with Youtube videos.
5
6![](https://cdn.mediacru.sh/D_izf0zjAtxy.png)
7
8#### Installation and setup
9Place the files in the `tpl/plugins/playvideos/` directory of your Shaarli.
10This is a default Shaarli plugin, you just have to enable it.
11
12To enable the plugin, add `playvideos` to the `TOOLBAR_PLUGINS` config option in your `index.php` or `data/options.php`. Example:
13
14 $GLOBALS['config']['TOOLBAR_PLUGINS'] = array('aplugins', 'anotherone', 'playvideos');
15
16#### Troubleshooting
17If your server has [Content Security Policy](http://content-security-policy.com/) headers enabled, this may prevent the script from loading fully. You should relax the CSP in your server settings. Example CSP rule for apache2:
18`Header set Content-Security-Policy "script-src 'self' 'unsafe-inline' https://www.youtube.com https://s.ytimg.com 'unsafe-eval'"`
19
20### License
21```
22File: youtube_playlist.js
23Copyright: (c) 2010-2014, David Kelso <david@kelso.id.au>
24License: The ISC License (http://opensource.org/licenses/ISC)
25
26Files: jquery*.js
27License: MIT License (http://opensource.org/licenses/MIT)
28Copyright: (C) jQuery Foundation and other contributors, https://jquery.com/download/
29
30-----------------------------------------------------
31
32The ISC License (http://opensource.org/licenses/ISC)
33
34Copyright (c) 2010-2014, David Kelso (david at kelso dot id dot au)
35Copyright (c) 2010-2014, nodiscc (nodiscc at gmail dot com)
36
37Permission to use, copy, modify, and/or distribute this software for any
38purpose with or without fee is hereby granted, provided that the above
39copyright notice and this permission notice appear in all copies.
40
41THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
42WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
43MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
44ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
45WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
46ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
47OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE
48
49----------------------------------------------------
50MIT LICENSE
51
52Permission is hereby granted, free of charge, to any person obtaining a copy
53of this software and associated documentation files (the "Software"), to deal
54in the Software without restriction, including without limitation the rights
55to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
56copies of the Software, and to permit persons to whom the Software is
57furnished to do so, subject to the following conditions:
58
59The above copyright notice and this permission notice shall be included in
60all copies or substantial portions of the Software.
61
62THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
63IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
64FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
65AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
66LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
67OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
68THE SOFTWARE.
69
70----------------------------------------------------
71``` \ No newline at end of file
diff --git a/plugins/playvideos/jquery-1.11.2.js b/plugins/playvideos/jquery-1.11.2.js
new file mode 100644
index 00000000..1c3aa822
--- /dev/null
+++ b/plugins/playvideos/jquery-1.11.2.js
@@ -0,0 +1,10346 @@
1/*!
2 * jQuery JavaScript Library v1.11.2
3 * http://jquery.com/
4 *
5 * Includes Sizzle.js
6 * http://sizzlejs.com/
7 *
8 * Copyright 2005, 2014 jQuery Foundation, Inc. and other contributors
9 * Released under the MIT license
10 * http://jquery.org/license
11 *
12 * Date: 2014-12-17T15:27Z
13 */
14
15(function( global, factory ) {
16
17 if ( typeof module === "object" && typeof module.exports === "object" ) {
18 // For CommonJS and CommonJS-like environments where a proper window is present,
19 // execute the factory and get jQuery
20 // For environments that do not inherently posses a window with a document
21 // (such as Node.js), expose a jQuery-making factory as module.exports
22 // This accentuates the need for the creation of a real window
23 // e.g. var jQuery = require("jquery")(window);
24 // See ticket #14549 for more info
25 module.exports = global.document ?
26 factory( global, true ) :
27 function( w ) {
28 if ( !w.document ) {
29 throw new Error( "jQuery requires a window with a document" );
30 }
31 return factory( w );
32 };
33 } else {
34 factory( global );
35 }
36
37// Pass this if window is not defined yet
38}(typeof window !== "undefined" ? window : this, function( window, noGlobal ) {
39
40// Can't do this because several apps including ASP.NET trace
41// the stack via arguments.caller.callee and Firefox dies if
42// you try to trace through "use strict" call chains. (#13335)
43// Support: Firefox 18+
44//
45
46var deletedIds = [];
47
48var slice = deletedIds.slice;
49
50var concat = deletedIds.concat;
51
52var push = deletedIds.push;
53
54var indexOf = deletedIds.indexOf;
55
56var class2type = {};
57
58var toString = class2type.toString;
59
60var hasOwn = class2type.hasOwnProperty;
61
62var support = {};
63
64
65
66var
67 version = "1.11.2",
68
69 // Define a local copy of jQuery
70 jQuery = function( selector, context ) {
71 // The jQuery object is actually just the init constructor 'enhanced'
72 // Need init if jQuery is called (just allow error to be thrown if not included)
73 return new jQuery.fn.init( selector, context );
74 },
75
76 // Support: Android<4.1, IE<9
77 // Make sure we trim BOM and NBSP
78 rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,
79
80 // Matches dashed string for camelizing
81 rmsPrefix = /^-ms-/,
82 rdashAlpha = /-([\da-z])/gi,
83
84 // Used by jQuery.camelCase as callback to replace()
85 fcamelCase = function( all, letter ) {
86 return letter.toUpperCase();
87 };
88
89jQuery.fn = jQuery.prototype = {
90 // The current version of jQuery being used
91 jquery: version,
92
93 constructor: jQuery,
94
95 // Start with an empty selector
96 selector: "",
97
98 // The default length of a jQuery object is 0
99 length: 0,
100
101 toArray: function() {
102 return slice.call( this );
103 },
104
105 // Get the Nth element in the matched element set OR
106 // Get the whole matched element set as a clean array
107 get: function( num ) {
108 return num != null ?
109
110 // Return just the one element from the set
111 ( num < 0 ? this[ num + this.length ] : this[ num ] ) :
112
113 // Return all the elements in a clean array
114 slice.call( this );
115 },
116
117 // Take an array of elements and push it onto the stack
118 // (returning the new matched element set)
119 pushStack: function( elems ) {
120
121 // Build a new jQuery matched element set
122 var ret = jQuery.merge( this.constructor(), elems );
123
124 // Add the old object onto the stack (as a reference)
125 ret.prevObject = this;
126 ret.context = this.context;
127
128 // Return the newly-formed element set
129 return ret;
130 },
131
132 // Execute a callback for every element in the matched set.
133 // (You can seed the arguments with an array of args, but this is
134 // only used internally.)
135 each: function( callback, args ) {
136 return jQuery.each( this, callback, args );
137 },
138
139 map: function( callback ) {
140 return this.pushStack( jQuery.map(this, function( elem, i ) {
141 return callback.call( elem, i, elem );
142 }));
143 },
144
145 slice: function() {
146 return this.pushStack( slice.apply( this, arguments ) );
147 },
148
149 first: function() {
150 return this.eq( 0 );
151 },
152
153 last: function() {
154 return this.eq( -1 );
155 },
156
157 eq: function( i ) {
158 var len = this.length,
159 j = +i + ( i < 0 ? len : 0 );
160 return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] );
161 },
162
163 end: function() {
164 return this.prevObject || this.constructor(null);
165 },
166
167 // For internal use only.
168 // Behaves like an Array's method, not like a jQuery method.
169 push: push,
170 sort: deletedIds.sort,
171 splice: deletedIds.splice
172};
173
174jQuery.extend = jQuery.fn.extend = function() {
175 var src, copyIsArray, copy, name, options, clone,
176 target = arguments[0] || {},
177 i = 1,
178 length = arguments.length,
179 deep = false;
180
181 // Handle a deep copy situation
182 if ( typeof target === "boolean" ) {
183 deep = target;
184
185 // skip the boolean and the target
186 target = arguments[ i ] || {};
187 i++;
188 }
189
190 // Handle case when target is a string or something (possible in deep copy)
191 if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
192 target = {};
193 }
194
195 // extend jQuery itself if only one argument is passed
196 if ( i === length ) {
197 target = this;
198 i--;
199 }
200
201 for ( ; i < length; i++ ) {
202 // Only deal with non-null/undefined values
203 if ( (options = arguments[ i ]) != null ) {
204 // Extend the base object
205 for ( name in options ) {
206 src = target[ name ];
207 copy = options[ name ];
208
209 // Prevent never-ending loop
210 if ( target === copy ) {
211 continue;
212 }
213
214 // Recurse if we're merging plain objects or arrays
215 if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
216 if ( copyIsArray ) {
217 copyIsArray = false;
218 clone = src && jQuery.isArray(src) ? src : [];
219
220 } else {
221 clone = src && jQuery.isPlainObject(src) ? src : {};
222 }
223
224 // Never move original objects, clone them
225 target[ name ] = jQuery.extend( deep, clone, copy );
226
227 // Don't bring in undefined values
228 } else if ( copy !== undefined ) {
229 target[ name ] = copy;
230 }
231 }
232 }
233 }
234
235 // Return the modified object
236 return target;
237};
238
239jQuery.extend({
240 // Unique for each copy of jQuery on the page
241 expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ),
242
243 // Assume jQuery is ready without the ready module
244 isReady: true,
245
246 error: function( msg ) {
247 throw new Error( msg );
248 },
249
250 noop: function() {},
251
252 // See test/unit/core.js for details concerning isFunction.
253 // Since version 1.3, DOM methods and functions like alert
254 // aren't supported. They return false on IE (#2968).
255 isFunction: function( obj ) {
256 return jQuery.type(obj) === "function";
257 },
258
259 isArray: Array.isArray || function( obj ) {
260 return jQuery.type(obj) === "array";
261 },
262
263 isWindow: function( obj ) {
264 /* jshint eqeqeq: false */
265 return obj != null && obj == obj.window;
266 },
267
268 isNumeric: function( obj ) {
269 // parseFloat NaNs numeric-cast false positives (null|true|false|"")
270 // ...but misinterprets leading-number strings, particularly hex literals ("0x...")
271 // subtraction forces infinities to NaN
272 // adding 1 corrects loss of precision from parseFloat (#15100)
273 return !jQuery.isArray( obj ) && (obj - parseFloat( obj ) + 1) >= 0;
274 },
275
276 isEmptyObject: function( obj ) {
277 var name;
278 for ( name in obj ) {
279 return false;
280 }
281 return true;
282 },
283
284 isPlainObject: function( obj ) {
285 var key;
286
287 // Must be an Object.
288 // Because of IE, we also have to check the presence of the constructor property.
289 // Make sure that DOM nodes and window objects don't pass through, as well
290 if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
291 return false;
292 }
293
294 try {
295 // Not own constructor property must be Object
296 if ( obj.constructor &&
297 !hasOwn.call(obj, "constructor") &&
298 !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
299 return false;
300 }
301 } catch ( e ) {
302 // IE8,9 Will throw exceptions on certain host objects #9897
303 return false;
304 }
305
306 // Support: IE<9
307 // Handle iteration over inherited properties before own properties.
308 if ( support.ownLast ) {
309 for ( key in obj ) {
310 return hasOwn.call( obj, key );
311 }
312 }
313
314 // Own properties are enumerated firstly, so to speed up,
315 // if last one is own, then all properties are own.
316 for ( key in obj ) {}
317
318 return key === undefined || hasOwn.call( obj, key );
319 },
320
321 type: function( obj ) {
322 if ( obj == null ) {
323 return obj + "";
324 }
325 return typeof obj === "object" || typeof obj === "function" ?
326 class2type[ toString.call(obj) ] || "object" :
327 typeof obj;
328 },
329
330 // Evaluates a script in a global context
331 // Workarounds based on findings by Jim Driscoll
332 // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context
333 globalEval: function( data ) {
334 if ( data && jQuery.trim( data ) ) {
335 // We use execScript on Internet Explorer
336 // We use an anonymous function so that context is window
337 // rather than jQuery in Firefox
338 ( window.execScript || function( data ) {
339 window[ "eval" ].call( window, data );
340 } )( data );
341 }
342 },
343
344 // Convert dashed to camelCase; used by the css and data modules
345 // Microsoft forgot to hump their vendor prefix (#9572)
346 camelCase: function( string ) {
347 return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
348 },
349
350 nodeName: function( elem, name ) {
351 return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
352 },
353
354 // args is for internal usage only
355 each: function( obj, callback, args ) {
356 var value,
357 i = 0,
358 length = obj.length,
359 isArray = isArraylike( obj );
360
361 if ( args ) {
362 if ( isArray ) {
363 for ( ; i < length; i++ ) {
364 value = callback.apply( obj[ i ], args );
365
366 if ( value === false ) {
367 break;
368 }
369 }
370 } else {
371 for ( i in obj ) {
372 value = callback.apply( obj[ i ], args );
373
374 if ( value === false ) {
375 break;
376 }
377 }
378 }
379
380 // A special, fast, case for the most common use of each
381 } else {
382 if ( isArray ) {
383 for ( ; i < length; i++ ) {
384 value = callback.call( obj[ i ], i, obj[ i ] );
385
386 if ( value === false ) {
387 break;
388 }
389 }
390 } else {
391 for ( i in obj ) {
392 value = callback.call( obj[ i ], i, obj[ i ] );
393
394 if ( value === false ) {
395 break;
396 }
397 }
398 }
399 }
400
401 return obj;
402 },
403
404 // Support: Android<4.1, IE<9
405 trim: function( text ) {
406 return text == null ?
407 "" :
408 ( text + "" ).replace( rtrim, "" );
409 },
410
411 // results is for internal usage only
412 makeArray: function( arr, results ) {
413 var ret = results || [];
414
415 if ( arr != null ) {
416 if ( isArraylike( Object(arr) ) ) {
417 jQuery.merge( ret,
418 typeof arr === "string" ?
419 [ arr ] : arr
420 );
421 } else {
422 push.call( ret, arr );
423 }
424 }
425
426 return ret;
427 },
428
429 inArray: function( elem, arr, i ) {
430 var len;
431
432 if ( arr ) {
433 if ( indexOf ) {
434 return indexOf.call( arr, elem, i );
435 }
436
437 len = arr.length;
438 i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;
439
440 for ( ; i < len; i++ ) {
441 // Skip accessing in sparse arrays
442 if ( i in arr && arr[ i ] === elem ) {
443 return i;
444 }
445 }
446 }
447
448 return -1;
449 },
450
451 merge: function( first, second ) {
452 var len = +second.length,
453 j = 0,
454 i = first.length;
455
456 while ( j < len ) {
457 first[ i++ ] = second[ j++ ];
458 }
459
460 // Support: IE<9
461 // Workaround casting of .length to NaN on otherwise arraylike objects (e.g., NodeLists)
462 if ( len !== len ) {
463 while ( second[j] !== undefined ) {
464 first[ i++ ] = second[ j++ ];
465 }
466 }
467
468 first.length = i;
469
470 return first;
471 },
472
473 grep: function( elems, callback, invert ) {
474 var callbackInverse,
475 matches = [],
476 i = 0,
477 length = elems.length,
478 callbackExpect = !invert;
479
480 // Go through the array, only saving the items
481 // that pass the validator function
482 for ( ; i < length; i++ ) {
483 callbackInverse = !callback( elems[ i ], i );
484 if ( callbackInverse !== callbackExpect ) {
485 matches.push( elems[ i ] );
486 }
487 }
488
489 return matches;
490 },
491
492 // arg is for internal usage only
493 map: function( elems, callback, arg ) {
494 var value,
495 i = 0,
496 length = elems.length,
497 isArray = isArraylike( elems ),
498 ret = [];
499
500 // Go through the array, translating each of the items to their new values
501 if ( isArray ) {
502 for ( ; i < length; i++ ) {
503 value = callback( elems[ i ], i, arg );
504
505 if ( value != null ) {
506 ret.push( value );
507 }
508 }
509
510 // Go through every key on the object,
511 } else {
512 for ( i in elems ) {
513 value = callback( elems[ i ], i, arg );
514
515 if ( value != null ) {
516 ret.push( value );
517 }
518 }
519 }
520
521 // Flatten any nested arrays
522 return concat.apply( [], ret );
523 },
524
525 // A global GUID counter for objects
526 guid: 1,
527
528 // Bind a function to a context, optionally partially applying any
529 // arguments.
530 proxy: function( fn, context ) {
531 var args, proxy, tmp;
532
533 if ( typeof context === "string" ) {
534 tmp = fn[ context ];
535 context = fn;
536 fn = tmp;
537 }
538
539 // Quick check to determine if target is callable, in the spec
540 // this throws a TypeError, but we will just return undefined.
541 if ( !jQuery.isFunction( fn ) ) {
542 return undefined;
543 }
544
545 // Simulated bind
546 args = slice.call( arguments, 2 );
547 proxy = function() {
548 return fn.apply( context || this, args.concat( slice.call( arguments ) ) );
549 };
550
551 // Set the guid of unique handler to the same of original handler, so it can be removed
552 proxy.guid = fn.guid = fn.guid || jQuery.guid++;
553
554 return proxy;
555 },
556
557 now: function() {
558 return +( new Date() );
559 },
560
561 // jQuery.support is not used in Core but other projects attach their
562 // properties to it so it needs to exist.
563 support: support
564});
565
566// Populate the class2type map
567jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {
568 class2type[ "[object " + name + "]" ] = name.toLowerCase();
569});
570
571function isArraylike( obj ) {
572 var length = obj.length,
573 type = jQuery.type( obj );
574
575 if ( type === "function" || jQuery.isWindow( obj ) ) {
576 return false;
577 }
578
579 if ( obj.nodeType === 1 && length ) {
580 return true;
581 }
582
583 return type === "array" || length === 0 ||
584 typeof length === "number" && length > 0 && ( length - 1 ) in obj;
585}
586var Sizzle =
587/*!
588 * Sizzle CSS Selector Engine v2.2.0-pre
589 * http://sizzlejs.com/
590 *
591 * Copyright 2008, 2014 jQuery Foundation, Inc. and other contributors
592 * Released under the MIT license
593 * http://jquery.org/license
594 *
595 * Date: 2014-12-16
596 */
597(function( window ) {
598
599var i,
600 support,
601 Expr,
602 getText,
603 isXML,
604 tokenize,
605 compile,
606 select,
607 outermostContext,
608 sortInput,
609 hasDuplicate,
610
611 // Local document vars
612 setDocument,
613 document,
614 docElem,
615 documentIsHTML,
616 rbuggyQSA,
617 rbuggyMatches,
618 matches,
619 contains,
620
621 // Instance-specific data
622 expando = "sizzle" + 1 * new Date(),
623 preferredDoc = window.document,
624 dirruns = 0,
625 done = 0,
626 classCache = createCache(),
627 tokenCache = createCache(),
628 compilerCache = createCache(),
629 sortOrder = function( a, b ) {
630 if ( a === b ) {
631 hasDuplicate = true;
632 }
633 return 0;
634 },
635
636 // General-purpose constants
637 MAX_NEGATIVE = 1 << 31,
638
639 // Instance methods
640 hasOwn = ({}).hasOwnProperty,
641 arr = [],
642 pop = arr.pop,
643 push_native = arr.push,
644 push = arr.push,
645 slice = arr.slice,
646 // Use a stripped-down indexOf as it's faster than native
647 // http://jsperf.com/thor-indexof-vs-for/5
648 indexOf = function( list, elem ) {
649 var i = 0,
650 len = list.length;
651 for ( ; i < len; i++ ) {
652 if ( list[i] === elem ) {
653 return i;
654 }
655 }
656 return -1;
657 },
658
659 booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",
660
661 // Regular expressions
662
663 // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace
664 whitespace = "[\\x20\\t\\r\\n\\f]",
665 // http://www.w3.org/TR/css3-syntax/#characters
666 characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",
667
668 // Loosely modeled on CSS identifier characters
669 // An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors
670 // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
671 identifier = characterEncoding.replace( "w", "w#" ),
672
673 // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors
674 attributes = "\\[" + whitespace + "*(" + characterEncoding + ")(?:" + whitespace +
675 // Operator (capture 2)
676 "*([*^$|!~]?=)" + whitespace +
677 // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]"
678 "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace +
679 "*\\]",
680
681 pseudos = ":(" + characterEncoding + ")(?:\\((" +
682 // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:
683 // 1. quoted (capture 3; capture 4 or capture 5)
684 "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" +
685 // 2. simple (capture 6)
686 "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" +
687 // 3. anything else (capture 2)
688 ".*" +
689 ")\\)|)",
690
691 // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
692 rwhitespace = new RegExp( whitespace + "+", "g" ),
693 rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),
694
695 rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
696 rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ),
697
698 rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ),
699
700 rpseudo = new RegExp( pseudos ),
701 ridentifier = new RegExp( "^" + identifier + "$" ),
702
703 matchExpr = {
704 "ID": new RegExp( "^#(" + characterEncoding + ")" ),
705 "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ),
706 "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ),
707 "ATTR": new RegExp( "^" + attributes ),
708 "PSEUDO": new RegExp( "^" + pseudos ),
709 "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
710 "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
711 "*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
712 "bool": new RegExp( "^(?:" + booleans + ")$", "i" ),
713 // For use in libraries implementing .is()
714 // We use this for POS matching in `select`
715 "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
716 whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
717 },
718
719 rinputs = /^(?:input|select|textarea|button)$/i,
720 rheader = /^h\d$/i,
721
722 rnative = /^[^{]+\{\s*\[native \w/,
723
724 // Easily-parseable/retrievable ID or TAG or CLASS selectors
725 rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
726
727 rsibling = /[+~]/,
728 rescape = /'|\\/g,
729
730 // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
731 runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ),
732 funescape = function( _, escaped, escapedWhitespace ) {
733 var high = "0x" + escaped - 0x10000;
734 // NaN means non-codepoint
735 // Support: Firefox<24
736 // Workaround erroneous numeric interpretation of +"0x"
737 return high !== high || escapedWhitespace ?
738 escaped :
739 high < 0 ?
740 // BMP codepoint
741 String.fromCharCode( high + 0x10000 ) :
742 // Supplemental Plane codepoint (surrogate pair)
743 String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
744 },
745
746 // Used for iframes
747 // See setDocument()
748 // Removing the function wrapper causes a "Permission Denied"
749 // error in IE
750 unloadHandler = function() {
751 setDocument();
752 };
753
754// Optimize for push.apply( _, NodeList )
755try {
756 push.apply(
757 (arr = slice.call( preferredDoc.childNodes )),
758 preferredDoc.childNodes
759 );
760 // Support: Android<4.0
761 // Detect silently failing push.apply
762 arr[ preferredDoc.childNodes.length ].nodeType;
763} catch ( e ) {
764 push = { apply: arr.length ?
765
766 // Leverage slice if possible
767 function( target, els ) {
768 push_native.apply( target, slice.call(els) );
769 } :
770
771 // Support: IE<9
772 // Otherwise append directly
773 function( target, els ) {
774 var j = target.length,
775 i = 0;
776 // Can't trust NodeList.length
777 while ( (target[j++] = els[i++]) ) {}
778 target.length = j - 1;
779 }
780 };
781}
782
783function Sizzle( selector, context, results, seed ) {
784 var match, elem, m, nodeType,
785 // QSA vars
786 i, groups, old, nid, newContext, newSelector;
787
788 if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
789 setDocument( context );
790 }
791
792 context = context || document;
793 results = results || [];
794 nodeType = context.nodeType;
795
796 if ( typeof selector !== "string" || !selector ||
797 nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {
798
799 return results;
800 }
801
802 if ( !seed && documentIsHTML ) {
803
804 // Try to shortcut find operations when possible (e.g., not under DocumentFragment)
805 if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) {
806 // Speed-up: Sizzle("#ID")
807 if ( (m = match[1]) ) {
808 if ( nodeType === 9 ) {
809 elem = context.getElementById( m );
810 // Check parentNode to catch when Blackberry 4.6 returns
811 // nodes that are no longer in the document (jQuery #6963)
812 if ( elem && elem.parentNode ) {
813 // Handle the case where IE, Opera, and Webkit return items
814 // by name instead of ID
815 if ( elem.id === m ) {
816 results.push( elem );
817 return results;
818 }
819 } else {
820 return results;
821 }
822 } else {
823 // Context is not a document
824 if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) &&
825 contains( context, elem ) && elem.id === m ) {
826 results.push( elem );
827 return results;
828 }
829 }
830
831 // Speed-up: Sizzle("TAG")
832 } else if ( match[2] ) {
833 push.apply( results, context.getElementsByTagName( selector ) );
834 return results;
835
836 // Speed-up: Sizzle(".CLASS")
837 } else if ( (m = match[3]) && support.getElementsByClassName ) {
838 push.apply( results, context.getElementsByClassName( m ) );
839 return results;
840 }
841 }
842
843 // QSA path
844 if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {
845 nid = old = expando;
846 newContext = context;
847 newSelector = nodeType !== 1 && selector;
848
849 // qSA works strangely on Element-rooted queries
850 // We can work around this by specifying an extra ID on the root
851 // and working up from there (Thanks to Andrew Dupont for the technique)
852 // IE 8 doesn't work on object elements
853 if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
854 groups = tokenize( selector );
855
856 if ( (old = context.getAttribute("id")) ) {
857 nid = old.replace( rescape, "\\$&" );
858 } else {
859 context.setAttribute( "id", nid );
860 }
861 nid = "[id='" + nid + "'] ";
862
863 i = groups.length;
864 while ( i-- ) {
865 groups[i] = nid + toSelector( groups[i] );
866 }
867 newContext = rsibling.test( selector ) && testContext( context.parentNode ) || context;
868 newSelector = groups.join(",");
869 }
870
871 if ( newSelector ) {
872 try {
873 push.apply( results,
874 newContext.querySelectorAll( newSelector )
875 );
876 return results;
877 } catch(qsaError) {
878 } finally {
879 if ( !old ) {
880 context.removeAttribute("id");
881 }
882 }
883 }
884 }
885 }
886
887 // All others
888 return select( selector.replace( rtrim, "$1" ), context, results, seed );
889}
890
891/**
892 * Create key-value caches of limited size
893 * @returns {Function(string, Object)} Returns the Object data after storing it on itself with
894 * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
895 * deleting the oldest entry
896 */
897function createCache() {
898 var keys = [];
899
900 function cache( key, value ) {
901 // Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
902 if ( keys.push( key + " " ) > Expr.cacheLength ) {
903 // Only keep the most recent entries
904 delete cache[ keys.shift() ];
905 }
906 return (cache[ key + " " ] = value);
907 }
908 return cache;
909}
910
911/**
912 * Mark a function for special use by Sizzle
913 * @param {Function} fn The function to mark
914 */
915function markFunction( fn ) {
916 fn[ expando ] = true;
917 return fn;
918}
919
920/**
921 * Support testing using an element
922 * @param {Function} fn Passed the created div and expects a boolean result
923 */
924function assert( fn ) {
925 var div = document.createElement("div");
926
927 try {
928 return !!fn( div );
929 } catch (e) {
930 return false;
931 } finally {
932 // Remove from its parent by default
933 if ( div.parentNode ) {
934 div.parentNode.removeChild( div );
935 }
936 // release memory in IE
937 div = null;
938 }
939}
940
941/**
942 * Adds the same handler for all of the specified attrs
943 * @param {String} attrs Pipe-separated list of attributes
944 * @param {Function} handler The method that will be applied
945 */
946function addHandle( attrs, handler ) {
947 var arr = attrs.split("|"),
948 i = attrs.length;
949
950 while ( i-- ) {
951 Expr.attrHandle[ arr[i] ] = handler;
952 }
953}
954
955/**
956 * Checks document order of two siblings
957 * @param {Element} a
958 * @param {Element} b
959 * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b
960 */
961function siblingCheck( a, b ) {
962 var cur = b && a,
963 diff = cur && a.nodeType === 1 && b.nodeType === 1 &&
964 ( ~b.sourceIndex || MAX_NEGATIVE ) -
965 ( ~a.sourceIndex || MAX_NEGATIVE );
966
967 // Use IE sourceIndex if available on both nodes
968 if ( diff ) {
969 return diff;
970 }
971
972 // Check if b follows a
973 if ( cur ) {
974 while ( (cur = cur.nextSibling) ) {
975 if ( cur === b ) {
976 return -1;
977 }
978 }
979 }
980
981 return a ? 1 : -1;
982}
983
984/**
985 * Returns a function to use in pseudos for input types
986 * @param {String} type
987 */
988function createInputPseudo( type ) {
989 return function( elem ) {
990 var name = elem.nodeName.toLowerCase();
991 return name === "input" && elem.type === type;
992 };
993}
994
995/**
996 * Returns a function to use in pseudos for buttons
997 * @param {String} type
998 */
999function createButtonPseudo( type ) {
1000 return function( elem ) {
1001 var name = elem.nodeName.toLowerCase();
1002 return (name === "input" || name === "button") && elem.type === type;
1003 };
1004}
1005
1006/**
1007 * Returns a function to use in pseudos for positionals
1008 * @param {Function} fn
1009 */
1010function createPositionalPseudo( fn ) {
1011 return markFunction(function( argument ) {
1012 argument = +argument;
1013 return markFunction(function( seed, matches ) {
1014 var j,
1015 matchIndexes = fn( [], seed.length, argument ),
1016 i = matchIndexes.length;
1017
1018 // Match elements found at the specified indexes
1019 while ( i-- ) {
1020 if ( seed[ (j = matchIndexes[i]) ] ) {
1021 seed[j] = !(matches[j] = seed[j]);
1022 }
1023 }
1024 });
1025 });
1026}
1027
1028/**
1029 * Checks a node for validity as a Sizzle context
1030 * @param {Element|Object=} context
1031 * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value
1032 */
1033function testContext( context ) {
1034 return context && typeof context.getElementsByTagName !== "undefined" && context;
1035}
1036
1037// Expose support vars for convenience
1038support = Sizzle.support = {};
1039
1040/**
1041 * Detects XML nodes
1042 * @param {Element|Object} elem An element or a document
1043 * @returns {Boolean} True iff elem is a non-HTML XML node
1044 */
1045isXML = Sizzle.isXML = function( elem ) {
1046 // documentElement is verified for cases where it doesn't yet exist
1047 // (such as loading iframes in IE - #4833)
1048 var documentElement = elem && (elem.ownerDocument || elem).documentElement;
1049 return documentElement ? documentElement.nodeName !== "HTML" : false;
1050};
1051
1052/**
1053 * Sets document-related variables once based on the current document
1054 * @param {Element|Object} [doc] An element or document object to use to set the document
1055 * @returns {Object} Returns the current document
1056 */
1057setDocument = Sizzle.setDocument = function( node ) {
1058 var hasCompare, parent,
1059 doc = node ? node.ownerDocument || node : preferredDoc;
1060
1061 // If no document and documentElement is available, return
1062 if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
1063 return document;
1064 }
1065
1066 // Set our document
1067 document = doc;
1068 docElem = doc.documentElement;
1069 parent = doc.defaultView;
1070
1071 // Support: IE>8
1072 // If iframe document is assigned to "document" variable and if iframe has been reloaded,
1073 // IE will throw "permission denied" error when accessing "document" variable, see jQuery #13936
1074 // IE6-8 do not support the defaultView property so parent will be undefined
1075 if ( parent && parent !== parent.top ) {
1076 // IE11 does not have attachEvent, so all must suffer
1077 if ( parent.addEventListener ) {
1078 parent.addEventListener( "unload", unloadHandler, false );
1079 } else if ( parent.attachEvent ) {
1080 parent.attachEvent( "onunload", unloadHandler );
1081 }
1082 }
1083
1084 /* Support tests
1085 ---------------------------------------------------------------------- */
1086 documentIsHTML = !isXML( doc );
1087
1088 /* Attributes
1089 ---------------------------------------------------------------------- */
1090
1091 // Support: IE<8
1092 // Verify that getAttribute really returns attributes and not properties
1093 // (excepting IE8 booleans)
1094 support.attributes = assert(function( div ) {
1095 div.className = "i";
1096 return !div.getAttribute("className");
1097 });
1098
1099 /* getElement(s)By*
1100 ---------------------------------------------------------------------- */
1101
1102 // Check if getElementsByTagName("*") returns only elements
1103 support.getElementsByTagName = assert(function( div ) {
1104 div.appendChild( doc.createComment("") );
1105 return !div.getElementsByTagName("*").length;
1106 });
1107
1108 // Support: IE<9
1109 support.getElementsByClassName = rnative.test( doc.getElementsByClassName );
1110
1111 // Support: IE<10
1112 // Check if getElementById returns elements by name
1113 // The broken getElementById methods don't pick up programatically-set names,
1114 // so use a roundabout getElementsByName test
1115 support.getById = assert(function( div ) {
1116 docElem.appendChild( div ).id = expando;
1117 return !doc.getElementsByName || !doc.getElementsByName( expando ).length;
1118 });
1119
1120 // ID find and filter
1121 if ( support.getById ) {
1122 Expr.find["ID"] = function( id, context ) {
1123 if ( typeof context.getElementById !== "undefined" && documentIsHTML ) {
1124 var m = context.getElementById( id );
1125 // Check parentNode to catch when Blackberry 4.6 returns
1126 // nodes that are no longer in the document #6963
1127 return m && m.parentNode ? [ m ] : [];
1128 }
1129 };
1130 Expr.filter["ID"] = function( id ) {
1131 var attrId = id.replace( runescape, funescape );
1132 return function( elem ) {
1133 return elem.getAttribute("id") === attrId;
1134 };
1135 };
1136 } else {
1137 // Support: IE6/7
1138 // getElementById is not reliable as a find shortcut
1139 delete Expr.find["ID"];
1140
1141 Expr.filter["ID"] = function( id ) {
1142 var attrId = id.replace( runescape, funescape );
1143 return function( elem ) {
1144 var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
1145 return node && node.value === attrId;
1146 };
1147 };
1148 }
1149
1150 // Tag
1151 Expr.find["TAG"] = support.getElementsByTagName ?
1152 function( tag, context ) {
1153 if ( typeof context.getElementsByTagName !== "undefined" ) {
1154 return context.getElementsByTagName( tag );
1155
1156 // DocumentFragment nodes don't have gEBTN
1157 } else if ( support.qsa ) {
1158 return context.querySelectorAll( tag );
1159 }
1160 } :
1161
1162 function( tag, context ) {
1163 var elem,
1164 tmp = [],
1165 i = 0,
1166 // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too
1167 results = context.getElementsByTagName( tag );
1168
1169 // Filter out possible comments
1170 if ( tag === "*" ) {
1171 while ( (elem = results[i++]) ) {
1172 if ( elem.nodeType === 1 ) {
1173 tmp.push( elem );
1174 }
1175 }
1176
1177 return tmp;
1178 }
1179 return results;
1180 };
1181
1182 // Class
1183 Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) {
1184 if ( documentIsHTML ) {
1185 return context.getElementsByClassName( className );
1186 }
1187 };
1188
1189 /* QSA/matchesSelector
1190 ---------------------------------------------------------------------- */
1191
1192 // QSA and matchesSelector support
1193
1194 // matchesSelector(:active) reports false when true (IE9/Opera 11.5)
1195 rbuggyMatches = [];
1196
1197 // qSa(:focus) reports false when true (Chrome 21)
1198 // We allow this because of a bug in IE8/9 that throws an error
1199 // whenever `document.activeElement` is accessed on an iframe
1200 // So, we allow :focus to pass through QSA all the time to avoid the IE error
1201 // See http://bugs.jquery.com/ticket/13378
1202 rbuggyQSA = [];
1203
1204 if ( (support.qsa = rnative.test( doc.querySelectorAll )) ) {
1205 // Build QSA regex
1206 // Regex strategy adopted from Diego Perini
1207 assert(function( div ) {
1208 // Select is set to empty string on purpose
1209 // This is to test IE's treatment of not explicitly
1210 // setting a boolean content attribute,
1211 // since its presence should be enough
1212 // http://bugs.jquery.com/ticket/12359
1213 docElem.appendChild( div ).innerHTML = "<a id='" + expando + "'></a>" +
1214 "<select id='" + expando + "-\f]' msallowcapture=''>" +
1215 "<option selected=''></option></select>";
1216
1217 // Support: IE8, Opera 11-12.16
1218 // Nothing should be selected when empty strings follow ^= or $= or *=
1219 // The test attribute must be unknown in Opera but "safe" for WinRT
1220 // http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section
1221 if ( div.querySelectorAll("[msallowcapture^='']").length ) {
1222 rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" );
1223 }
1224
1225 // Support: IE8
1226 // Boolean attributes and "value" are not treated correctly
1227 if ( !div.querySelectorAll("[selected]").length ) {
1228 rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" );
1229 }
1230
1231 // Support: Chrome<29, Android<4.2+, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.7+
1232 if ( !div.querySelectorAll( "[id~=" + expando + "-]" ).length ) {
1233 rbuggyQSA.push("~=");
1234 }
1235
1236 // Webkit/Opera - :checked should return selected option elements
1237 // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
1238 // IE8 throws error here and will not see later tests
1239 if ( !div.querySelectorAll(":checked").length ) {
1240 rbuggyQSA.push(":checked");
1241 }
1242
1243 // Support: Safari 8+, iOS 8+
1244 // https://bugs.webkit.org/show_bug.cgi?id=136851
1245 // In-page `selector#id sibing-combinator selector` fails
1246 if ( !div.querySelectorAll( "a#" + expando + "+*" ).length ) {
1247 rbuggyQSA.push(".#.+[+~]");
1248 }
1249 });
1250
1251 assert(function( div ) {
1252 // Support: Windows 8 Native Apps
1253 // The type and name attributes are restricted during .innerHTML assignment
1254 var input = doc.createElement("input");
1255 input.setAttribute( "type", "hidden" );
1256 div.appendChild( input ).setAttribute( "name", "D" );
1257
1258 // Support: IE8
1259 // Enforce case-sensitivity of name attribute
1260 if ( div.querySelectorAll("[name=d]").length ) {
1261 rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" );
1262 }
1263
1264 // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
1265 // IE8 throws error here and will not see later tests
1266 if ( !div.querySelectorAll(":enabled").length ) {
1267 rbuggyQSA.push( ":enabled", ":disabled" );
1268 }
1269
1270 // Opera 10-11 does not throw on post-comma invalid pseudos
1271 div.querySelectorAll("*,:x");
1272 rbuggyQSA.push(",.*:");
1273 });
1274 }
1275
1276 if ( (support.matchesSelector = rnative.test( (matches = docElem.matches ||
1277 docElem.webkitMatchesSelector ||
1278 docElem.mozMatchesSelector ||
1279 docElem.oMatchesSelector ||
1280 docElem.msMatchesSelector) )) ) {
1281
1282 assert(function( div ) {
1283 // Check to see if it's possible to do matchesSelector
1284 // on a disconnected node (IE 9)
1285 support.disconnectedMatch = matches.call( div, "div" );
1286
1287 // This should fail with an exception
1288 // Gecko does not error, returns false instead
1289 matches.call( div, "[s!='']:x" );
1290 rbuggyMatches.push( "!=", pseudos );
1291 });
1292 }
1293
1294 rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") );
1295 rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") );
1296
1297 /* Contains
1298 ---------------------------------------------------------------------- */
1299 hasCompare = rnative.test( docElem.compareDocumentPosition );
1300
1301 // Element contains another
1302 // Purposefully does not implement inclusive descendent
1303 // As in, an element does not contain itself
1304 contains = hasCompare || rnative.test( docElem.contains ) ?
1305 function( a, b ) {
1306 var adown = a.nodeType === 9 ? a.documentElement : a,
1307 bup = b && b.parentNode;
1308 return a === bup || !!( bup && bup.nodeType === 1 && (
1309 adown.contains ?
1310 adown.contains( bup ) :
1311 a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
1312 ));
1313 } :
1314 function( a, b ) {
1315 if ( b ) {
1316 while ( (b = b.parentNode) ) {
1317 if ( b === a ) {
1318 return true;
1319 }
1320 }
1321 }
1322 return false;
1323 };
1324
1325 /* Sorting
1326 ---------------------------------------------------------------------- */
1327
1328 // Document order sorting
1329 sortOrder = hasCompare ?
1330 function( a, b ) {
1331
1332 // Flag for duplicate removal
1333 if ( a === b ) {
1334 hasDuplicate = true;
1335 return 0;
1336 }
1337
1338 // Sort on method existence if only one input has compareDocumentPosition
1339 var compare = !a.compareDocumentPosition - !b.compareDocumentPosition;
1340 if ( compare ) {
1341 return compare;
1342 }
1343
1344 // Calculate position if both inputs belong to the same document
1345 compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ?
1346 a.compareDocumentPosition( b ) :
1347
1348 // Otherwise we know they are disconnected
1349 1;
1350
1351 // Disconnected nodes
1352 if ( compare & 1 ||
1353 (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {
1354
1355 // Choose the first element that is related to our preferred document
1356 if ( a === doc || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {
1357 return -1;
1358 }
1359 if ( b === doc || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) {
1360 return 1;
1361 }
1362
1363 // Maintain original order
1364 return sortInput ?
1365 ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
1366 0;
1367 }
1368
1369 return compare & 4 ? -1 : 1;
1370 } :
1371 function( a, b ) {
1372 // Exit early if the nodes are identical
1373 if ( a === b ) {
1374 hasDuplicate = true;
1375 return 0;
1376 }
1377
1378 var cur,
1379 i = 0,
1380 aup = a.parentNode,
1381 bup = b.parentNode,
1382 ap = [ a ],
1383 bp = [ b ];
1384
1385 // Parentless nodes are either documents or disconnected
1386 if ( !aup || !bup ) {
1387 return a === doc ? -1 :
1388 b === doc ? 1 :
1389 aup ? -1 :
1390 bup ? 1 :
1391 sortInput ?
1392 ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
1393 0;
1394
1395 // If the nodes are siblings, we can do a quick check
1396 } else if ( aup === bup ) {
1397 return siblingCheck( a, b );
1398 }
1399
1400 // Otherwise we need full lists of their ancestors for comparison
1401 cur = a;
1402 while ( (cur = cur.parentNode) ) {
1403 ap.unshift( cur );
1404 }
1405 cur = b;
1406 while ( (cur = cur.parentNode) ) {
1407 bp.unshift( cur );
1408 }
1409
1410 // Walk down the tree looking for a discrepancy
1411 while ( ap[i] === bp[i] ) {
1412 i++;
1413 }
1414
1415 return i ?
1416 // Do a sibling check if the nodes have a common ancestor
1417 siblingCheck( ap[i], bp[i] ) :
1418
1419 // Otherwise nodes in our document sort first
1420 ap[i] === preferredDoc ? -1 :
1421 bp[i] === preferredDoc ? 1 :
1422 0;
1423 };
1424
1425 return doc;
1426};
1427
1428Sizzle.matches = function( expr, elements ) {
1429 return Sizzle( expr, null, null, elements );
1430};
1431
1432Sizzle.matchesSelector = function( elem, expr ) {
1433 // Set document vars if needed
1434 if ( ( elem.ownerDocument || elem ) !== document ) {
1435 setDocument( elem );
1436 }
1437
1438 // Make sure that attribute selectors are quoted
1439 expr = expr.replace( rattributeQuotes, "='$1']" );
1440
1441 if ( support.matchesSelector && documentIsHTML &&
1442 ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&
1443 ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) {
1444
1445 try {
1446 var ret = matches.call( elem, expr );
1447
1448 // IE 9's matchesSelector returns false on disconnected nodes
1449 if ( ret || support.disconnectedMatch ||
1450 // As well, disconnected nodes are said to be in a document
1451 // fragment in IE 9
1452 elem.document && elem.document.nodeType !== 11 ) {
1453 return ret;
1454 }
1455 } catch (e) {}
1456 }
1457
1458 return Sizzle( expr, document, null, [ elem ] ).length > 0;
1459};
1460
1461Sizzle.contains = function( context, elem ) {
1462 // Set document vars if needed
1463 if ( ( context.ownerDocument || context ) !== document ) {
1464 setDocument( context );
1465 }
1466 return contains( context, elem );
1467};
1468
1469Sizzle.attr = function( elem, name ) {
1470 // Set document vars if needed
1471 if ( ( elem.ownerDocument || elem ) !== document ) {
1472 setDocument( elem );
1473 }
1474
1475 var fn = Expr.attrHandle[ name.toLowerCase() ],
1476 // Don't get fooled by Object.prototype properties (jQuery #13807)
1477 val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?
1478 fn( elem, name, !documentIsHTML ) :
1479 undefined;
1480
1481 return val !== undefined ?
1482 val :
1483 support.attributes || !documentIsHTML ?
1484 elem.getAttribute( name ) :
1485 (val = elem.getAttributeNode(name)) && val.specified ?
1486 val.value :
1487 null;
1488};
1489
1490Sizzle.error = function( msg ) {
1491 throw new Error( "Syntax error, unrecognized expression: " + msg );
1492};
1493
1494/**
1495 * Document sorting and removing duplicates
1496 * @param {ArrayLike} results
1497 */
1498Sizzle.uniqueSort = function( results ) {
1499 var elem,
1500 duplicates = [],
1501 j = 0,
1502 i = 0;
1503
1504 // Unless we *know* we can detect duplicates, assume their presence
1505 hasDuplicate = !support.detectDuplicates;
1506 sortInput = !support.sortStable && results.slice( 0 );
1507 results.sort( sortOrder );
1508
1509 if ( hasDuplicate ) {
1510 while ( (elem = results[i++]) ) {
1511 if ( elem === results[ i ] ) {
1512 j = duplicates.push( i );
1513 }
1514 }
1515 while ( j-- ) {
1516 results.splice( duplicates[ j ], 1 );
1517 }
1518 }
1519
1520 // Clear input after sorting to release objects
1521 // See https://github.com/jquery/sizzle/pull/225
1522 sortInput = null;
1523
1524 return results;
1525};
1526
1527/**
1528 * Utility function for retrieving the text value of an array of DOM nodes
1529 * @param {Array|Element} elem
1530 */
1531getText = Sizzle.getText = function( elem ) {
1532 var node,
1533 ret = "",
1534 i = 0,
1535 nodeType = elem.nodeType;
1536
1537 if ( !nodeType ) {
1538 // If no nodeType, this is expected to be an array
1539 while ( (node = elem[i++]) ) {
1540 // Do not traverse comment nodes
1541 ret += getText( node );
1542 }
1543 } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
1544 // Use textContent for elements
1545 // innerText usage removed for consistency of new lines (jQuery #11153)
1546 if ( typeof elem.textContent === "string" ) {
1547 return elem.textContent;
1548 } else {
1549 // Traverse its children
1550 for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
1551 ret += getText( elem );
1552 }
1553 }
1554 } else if ( nodeType === 3 || nodeType === 4 ) {
1555 return elem.nodeValue;
1556 }
1557 // Do not include comment or processing instruction nodes
1558
1559 return ret;
1560};
1561
1562Expr = Sizzle.selectors = {
1563
1564 // Can be adjusted by the user
1565 cacheLength: 50,
1566
1567 createPseudo: markFunction,
1568
1569 match: matchExpr,
1570
1571 attrHandle: {},
1572
1573 find: {},
1574
1575 relative: {
1576 ">": { dir: "parentNode", first: true },
1577 " ": { dir: "parentNode" },
1578 "+": { dir: "previousSibling", first: true },
1579 "~": { dir: "previousSibling" }
1580 },
1581
1582 preFilter: {
1583 "ATTR": function( match ) {
1584 match[1] = match[1].replace( runescape, funescape );
1585
1586 // Move the given value to match[3] whether quoted or unquoted
1587 match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape );
1588
1589 if ( match[2] === "~=" ) {
1590 match[3] = " " + match[3] + " ";
1591 }
1592
1593 return match.slice( 0, 4 );
1594 },
1595
1596 "CHILD": function( match ) {
1597 /* matches from matchExpr["CHILD"]
1598 1 type (only|nth|...)
1599 2 what (child|of-type)
1600 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
1601 4 xn-component of xn+y argument ([+-]?\d*n|)
1602 5 sign of xn-component
1603 6 x of xn-component
1604 7 sign of y-component
1605 8 y of y-component
1606 */
1607 match[1] = match[1].toLowerCase();
1608
1609 if ( match[1].slice( 0, 3 ) === "nth" ) {
1610 // nth-* requires argument
1611 if ( !match[3] ) {
1612 Sizzle.error( match[0] );
1613 }
1614
1615 // numeric x and y parameters for Expr.filter.CHILD
1616 // remember that false/true cast respectively to 0/1
1617 match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) );
1618 match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" );
1619
1620 // other types prohibit arguments
1621 } else if ( match[3] ) {
1622 Sizzle.error( match[0] );
1623 }
1624
1625 return match;
1626 },
1627
1628 "PSEUDO": function( match ) {
1629 var excess,
1630 unquoted = !match[6] && match[2];
1631
1632 if ( matchExpr["CHILD"].test( match[0] ) ) {
1633 return null;
1634 }
1635
1636 // Accept quoted arguments as-is
1637 if ( match[3] ) {
1638 match[2] = match[4] || match[5] || "";
1639
1640 // Strip excess characters from unquoted arguments
1641 } else if ( unquoted && rpseudo.test( unquoted ) &&
1642 // Get excess from tokenize (recursively)
1643 (excess = tokenize( unquoted, true )) &&
1644 // advance to the next closing parenthesis
1645 (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {
1646
1647 // excess is a negative index
1648 match[0] = match[0].slice( 0, excess );
1649 match[2] = unquoted.slice( 0, excess );
1650 }
1651
1652 // Return only captures needed by the pseudo filter method (type and argument)
1653 return match.slice( 0, 3 );
1654 }
1655 },
1656
1657 filter: {
1658
1659 "TAG": function( nodeNameSelector ) {
1660 var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();
1661 return nodeNameSelector === "*" ?
1662 function() { return true; } :
1663 function( elem ) {
1664 return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
1665 };
1666 },
1667
1668 "CLASS": function( className ) {
1669 var pattern = classCache[ className + " " ];
1670
1671 return pattern ||
1672 (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&
1673 classCache( className, function( elem ) {
1674 return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" );
1675 });
1676 },
1677
1678 "ATTR": function( name, operator, check ) {
1679 return function( elem ) {
1680 var result = Sizzle.attr( elem, name );
1681
1682 if ( result == null ) {
1683 return operator === "!=";
1684 }
1685 if ( !operator ) {
1686 return true;
1687 }
1688
1689 result += "";
1690
1691 return operator === "=" ? result === check :
1692 operator === "!=" ? result !== check :
1693 operator === "^=" ? check && result.indexOf( check ) === 0 :
1694 operator === "*=" ? check && result.indexOf( check ) > -1 :
1695 operator === "$=" ? check && result.slice( -check.length ) === check :
1696 operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 :
1697 operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
1698 false;
1699 };
1700 },
1701
1702 "CHILD": function( type, what, argument, first, last ) {
1703 var simple = type.slice( 0, 3 ) !== "nth",
1704 forward = type.slice( -4 ) !== "last",
1705 ofType = what === "of-type";
1706
1707 return first === 1 && last === 0 ?
1708
1709 // Shortcut for :nth-*(n)
1710 function( elem ) {
1711 return !!elem.parentNode;
1712 } :
1713
1714 function( elem, context, xml ) {
1715 var cache, outerCache, node, diff, nodeIndex, start,
1716 dir = simple !== forward ? "nextSibling" : "previousSibling",
1717 parent = elem.parentNode,
1718 name = ofType && elem.nodeName.toLowerCase(),
1719 useCache = !xml && !ofType;
1720
1721 if ( parent ) {
1722
1723 // :(first|last|only)-(child|of-type)
1724 if ( simple ) {
1725 while ( dir ) {
1726 node = elem;
1727 while ( (node = node[ dir ]) ) {
1728 if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) {
1729 return false;
1730 }
1731 }
1732 // Reverse direction for :only-* (if we haven't yet done so)
1733 start = dir = type === "only" && !start && "nextSibling";
1734 }
1735 return true;
1736 }
1737
1738 start = [ forward ? parent.firstChild : parent.lastChild ];
1739
1740 // non-xml :nth-child(...) stores cache data on `parent`
1741 if ( forward && useCache ) {
1742 // Seek `elem` from a previously-cached index
1743 outerCache = parent[ expando ] || (parent[ expando ] = {});
1744 cache = outerCache[ type ] || [];
1745 nodeIndex = cache[0] === dirruns && cache[1];
1746 diff = cache[0] === dirruns && cache[2];
1747 node = nodeIndex && parent.childNodes[ nodeIndex ];
1748
1749 while ( (node = ++nodeIndex && node && node[ dir ] ||
1750
1751 // Fallback to seeking `elem` from the start
1752 (diff = nodeIndex = 0) || start.pop()) ) {
1753
1754 // When found, cache indexes on `parent` and break
1755 if ( node.nodeType === 1 && ++diff && node === elem ) {
1756 outerCache[ type ] = [ dirruns, nodeIndex, diff ];
1757 break;
1758 }
1759 }
1760
1761 // Use previously-cached element index if available
1762 } else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) {
1763 diff = cache[1];
1764
1765 // xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...)
1766 } else {
1767 // Use the same loop as above to seek `elem` from the start
1768 while ( (node = ++nodeIndex && node && node[ dir ] ||
1769 (diff = nodeIndex = 0) || start.pop()) ) {
1770
1771 if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) {
1772 // Cache the index of each encountered element
1773 if ( useCache ) {
1774 (node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ];
1775 }
1776
1777 if ( node === elem ) {
1778 break;
1779 }
1780 }
1781 }
1782 }
1783
1784 // Incorporate the offset, then check against cycle size
1785 diff -= last;
1786 return diff === first || ( diff % first === 0 && diff / first >= 0 );
1787 }
1788 };
1789 },
1790
1791 "PSEUDO": function( pseudo, argument ) {
1792 // pseudo-class names are case-insensitive
1793 // http://www.w3.org/TR/selectors/#pseudo-classes
1794 // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
1795 // Remember that setFilters inherits from pseudos
1796 var args,
1797 fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
1798 Sizzle.error( "unsupported pseudo: " + pseudo );
1799
1800 // The user may use createPseudo to indicate that
1801 // arguments are needed to create the filter function
1802 // just as Sizzle does
1803 if ( fn[ expando ] ) {
1804 return fn( argument );
1805 }
1806
1807 // But maintain support for old signatures
1808 if ( fn.length > 1 ) {
1809 args = [ pseudo, pseudo, "", argument ];
1810 return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
1811 markFunction(function( seed, matches ) {
1812 var idx,
1813 matched = fn( seed, argument ),
1814 i = matched.length;
1815 while ( i-- ) {
1816 idx = indexOf( seed, matched[i] );
1817 seed[ idx ] = !( matches[ idx ] = matched[i] );
1818 }
1819 }) :
1820 function( elem ) {
1821 return fn( elem, 0, args );
1822 };
1823 }
1824
1825 return fn;
1826 }
1827 },
1828
1829 pseudos: {
1830 // Potentially complex pseudos
1831 "not": markFunction(function( selector ) {
1832 // Trim the selector passed to compile
1833 // to avoid treating leading and trailing
1834 // spaces as combinators
1835 var input = [],
1836 results = [],
1837 matcher = compile( selector.replace( rtrim, "$1" ) );
1838
1839 return matcher[ expando ] ?
1840 markFunction(function( seed, matches, context, xml ) {
1841 var elem,
1842 unmatched = matcher( seed, null, xml, [] ),
1843 i = seed.length;
1844
1845 // Match elements unmatched by `matcher`
1846 while ( i-- ) {
1847 if ( (elem = unmatched[i]) ) {
1848 seed[i] = !(matches[i] = elem);
1849 }
1850 }
1851 }) :
1852 function( elem, context, xml ) {
1853 input[0] = elem;
1854 matcher( input, null, xml, results );
1855 // Don't keep the element (issue #299)
1856 input[0] = null;
1857 return !results.pop();
1858 };
1859 }),
1860
1861 "has": markFunction(function( selector ) {
1862 return function( elem ) {
1863 return Sizzle( selector, elem ).length > 0;
1864 };
1865 }),
1866
1867 "contains": markFunction(function( text ) {
1868 text = text.replace( runescape, funescape );
1869 return function( elem ) {
1870 return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
1871 };
1872 }),
1873
1874 // "Whether an element is represented by a :lang() selector
1875 // is based solely on the element's language value
1876 // being equal to the identifier C,
1877 // or beginning with the identifier C immediately followed by "-".
1878 // The matching of C against the element's language value is performed case-insensitively.
1879 // The identifier C does not have to be a valid language name."
1880 // http://www.w3.org/TR/selectors/#lang-pseudo
1881 "lang": markFunction( function( lang ) {
1882 // lang value must be a valid identifier
1883 if ( !ridentifier.test(lang || "") ) {
1884 Sizzle.error( "unsupported lang: " + lang );
1885 }
1886 lang = lang.replace( runescape, funescape ).toLowerCase();
1887 return function( elem ) {
1888 var elemLang;
1889 do {
1890 if ( (elemLang = documentIsHTML ?
1891 elem.lang :
1892 elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) {
1893
1894 elemLang = elemLang.toLowerCase();
1895 return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
1896 }
1897 } while ( (elem = elem.parentNode) && elem.nodeType === 1 );
1898 return false;
1899 };
1900 }),
1901
1902 // Miscellaneous
1903 "target": function( elem ) {
1904 var hash = window.location && window.location.hash;
1905 return hash && hash.slice( 1 ) === elem.id;
1906 },
1907
1908 "root": function( elem ) {
1909 return elem === docElem;
1910 },
1911
1912 "focus": function( elem ) {
1913 return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
1914 },
1915
1916 // Boolean properties
1917 "enabled": function( elem ) {
1918 return elem.disabled === false;
1919 },
1920
1921 "disabled": function( elem ) {
1922 return elem.disabled === true;
1923 },
1924
1925 "checked": function( elem ) {
1926 // In CSS3, :checked should return both checked and selected elements
1927 // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
1928 var nodeName = elem.nodeName.toLowerCase();
1929 return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
1930 },
1931
1932 "selected": function( elem ) {
1933 // Accessing this property makes selected-by-default
1934 // options in Safari work properly
1935 if ( elem.parentNode ) {
1936 elem.parentNode.selectedIndex;
1937 }
1938
1939 return elem.selected === true;
1940 },
1941
1942 // Contents
1943 "empty": function( elem ) {
1944 // http://www.w3.org/TR/selectors/#empty-pseudo
1945 // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),
1946 // but not by others (comment: 8; processing instruction: 7; etc.)
1947 // nodeType < 6 works because attributes (2) do not appear as children
1948 for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
1949 if ( elem.nodeType < 6 ) {
1950 return false;
1951 }
1952 }
1953 return true;
1954 },
1955
1956 "parent": function( elem ) {
1957 return !Expr.pseudos["empty"]( elem );
1958 },
1959
1960 // Element/input types
1961 "header": function( elem ) {
1962 return rheader.test( elem.nodeName );
1963 },
1964
1965 "input": function( elem ) {
1966 return rinputs.test( elem.nodeName );
1967 },
1968
1969 "button": function( elem ) {
1970 var name = elem.nodeName.toLowerCase();
1971 return name === "input" && elem.type === "button" || name === "button";
1972 },
1973
1974 "text": function( elem ) {
1975 var attr;
1976 return elem.nodeName.toLowerCase() === "input" &&
1977 elem.type === "text" &&
1978
1979 // Support: IE<8
1980 // New HTML5 attribute values (e.g., "search") appear with elem.type === "text"
1981 ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" );
1982 },
1983
1984 // Position-in-collection
1985 "first": createPositionalPseudo(function() {
1986 return [ 0 ];
1987 }),
1988
1989 "last": createPositionalPseudo(function( matchIndexes, length ) {
1990 return [ length - 1 ];
1991 }),
1992
1993 "eq": createPositionalPseudo(function( matchIndexes, length, argument ) {
1994 return [ argument < 0 ? argument + length : argument ];
1995 }),
1996
1997 "even": createPositionalPseudo(function( matchIndexes, length ) {
1998 var i = 0;
1999 for ( ; i < length; i += 2 ) {
2000 matchIndexes.push( i );
2001 }
2002 return matchIndexes;
2003 }),
2004
2005 "odd": createPositionalPseudo(function( matchIndexes, length ) {
2006 var i = 1;
2007 for ( ; i < length; i += 2 ) {
2008 matchIndexes.push( i );
2009 }
2010 return matchIndexes;
2011 }),
2012
2013 "lt": createPositionalPseudo(function( matchIndexes, length, argument ) {
2014 var i = argument < 0 ? argument + length : argument;
2015 for ( ; --i >= 0; ) {
2016 matchIndexes.push( i );
2017 }
2018 return matchIndexes;
2019 }),
2020
2021 "gt": createPositionalPseudo(function( matchIndexes, length, argument ) {
2022 var i = argument < 0 ? argument + length : argument;
2023 for ( ; ++i < length; ) {
2024 matchIndexes.push( i );
2025 }
2026 return matchIndexes;
2027 })
2028 }
2029};
2030
2031Expr.pseudos["nth"] = Expr.pseudos["eq"];
2032
2033// Add button/input type pseudos
2034for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
2035 Expr.pseudos[ i ] = createInputPseudo( i );
2036}
2037for ( i in { submit: true, reset: true } ) {
2038 Expr.pseudos[ i ] = createButtonPseudo( i );
2039}
2040
2041// Easy API for creating new setFilters
2042function setFilters() {}
2043setFilters.prototype = Expr.filters = Expr.pseudos;
2044Expr.setFilters = new setFilters();
2045
2046tokenize = Sizzle.tokenize = function( selector, parseOnly ) {
2047 var matched, match, tokens, type,
2048 soFar, groups, preFilters,
2049 cached = tokenCache[ selector + " " ];
2050
2051 if ( cached ) {
2052 return parseOnly ? 0 : cached.slice( 0 );
2053 }
2054
2055 soFar = selector;
2056 groups = [];
2057 preFilters = Expr.preFilter;
2058
2059 while ( soFar ) {
2060
2061 // Comma and first run
2062 if ( !matched || (match = rcomma.exec( soFar )) ) {
2063 if ( match ) {
2064 // Don't consume trailing commas as valid
2065 soFar = soFar.slice( match[0].length ) || soFar;
2066 }
2067 groups.push( (tokens = []) );
2068 }
2069
2070 matched = false;
2071
2072 // Combinators
2073 if ( (match = rcombinators.exec( soFar )) ) {
2074 matched = match.shift();
2075 tokens.push({
2076 value: matched,
2077 // Cast descendant combinators to space
2078 type: match[0].replace( rtrim, " " )
2079 });
2080 soFar = soFar.slice( matched.length );
2081 }
2082
2083 // Filters
2084 for ( type in Expr.filter ) {
2085 if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
2086 (match = preFilters[ type ]( match ))) ) {
2087 matched = match.shift();
2088 tokens.push({
2089 value: matched,
2090 type: type,
2091 matches: match
2092 });
2093 soFar = soFar.slice( matched.length );
2094 }
2095 }
2096
2097 if ( !matched ) {
2098 break;
2099 }
2100 }
2101
2102 // Return the length of the invalid excess
2103 // if we're just parsing
2104 // Otherwise, throw an error or return tokens
2105 return parseOnly ?
2106 soFar.length :
2107 soFar ?
2108 Sizzle.error( selector ) :
2109 // Cache the tokens
2110 tokenCache( selector, groups ).slice( 0 );
2111};
2112
2113function toSelector( tokens ) {
2114 var i = 0,
2115 len = tokens.length,
2116 selector = "";
2117 for ( ; i < len; i++ ) {
2118 selector += tokens[i].value;
2119 }
2120 return selector;
2121}
2122
2123function addCombinator( matcher, combinator, base ) {
2124 var dir = combinator.dir,
2125 checkNonElements = base && dir === "parentNode",
2126 doneName = done++;
2127
2128 return combinator.first ?
2129 // Check against closest ancestor/preceding element
2130 function( elem, context, xml ) {
2131 while ( (elem = elem[ dir ]) ) {
2132 if ( elem.nodeType === 1 || checkNonElements ) {
2133 return matcher( elem, context, xml );
2134 }
2135 }
2136 } :
2137
2138 // Check against all ancestor/preceding elements
2139 function( elem, context, xml ) {
2140 var oldCache, outerCache,
2141 newCache = [ dirruns, doneName ];
2142
2143 // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching
2144 if ( xml ) {
2145 while ( (elem = elem[ dir ]) ) {
2146 if ( elem.nodeType === 1 || checkNonElements ) {
2147 if ( matcher( elem, context, xml ) ) {
2148 return true;
2149 }
2150 }
2151 }
2152 } else {
2153 while ( (elem = elem[ dir ]) ) {
2154 if ( elem.nodeType === 1 || checkNonElements ) {
2155 outerCache = elem[ expando ] || (elem[ expando ] = {});
2156 if ( (oldCache = outerCache[ dir ]) &&
2157 oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {
2158
2159 // Assign to newCache so results back-propagate to previous elements
2160 return (newCache[ 2 ] = oldCache[ 2 ]);
2161 } else {
2162 // Reuse newcache so results back-propagate to previous elements
2163 outerCache[ dir ] = newCache;
2164
2165 // A match means we're done; a fail means we have to keep checking
2166 if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) {
2167 return true;
2168 }
2169 }
2170 }
2171 }
2172 }
2173 };
2174}
2175
2176function elementMatcher( matchers ) {
2177 return matchers.length > 1 ?
2178 function( elem, context, xml ) {
2179 var i = matchers.length;
2180 while ( i-- ) {
2181 if ( !matchers[i]( elem, context, xml ) ) {
2182 return false;
2183 }
2184 }
2185 return true;
2186 } :
2187 matchers[0];
2188}
2189
2190function multipleContexts( selector, contexts, results ) {
2191 var i = 0,
2192 len = contexts.length;
2193 for ( ; i < len; i++ ) {
2194 Sizzle( selector, contexts[i], results );
2195 }
2196 return results;
2197}
2198
2199function condense( unmatched, map, filter, context, xml ) {
2200 var elem,
2201 newUnmatched = [],
2202 i = 0,
2203 len = unmatched.length,
2204 mapped = map != null;
2205
2206 for ( ; i < len; i++ ) {
2207 if ( (elem = unmatched[i]) ) {
2208 if ( !filter || filter( elem, context, xml ) ) {
2209 newUnmatched.push( elem );
2210 if ( mapped ) {
2211 map.push( i );
2212 }
2213 }
2214 }
2215 }
2216
2217 return newUnmatched;
2218}
2219
2220function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
2221 if ( postFilter && !postFilter[ expando ] ) {
2222 postFilter = setMatcher( postFilter );
2223 }
2224 if ( postFinder && !postFinder[ expando ] ) {
2225 postFinder = setMatcher( postFinder, postSelector );
2226 }
2227 return markFunction(function( seed, results, context, xml ) {
2228 var temp, i, elem,
2229 preMap = [],
2230 postMap = [],
2231 preexisting = results.length,
2232
2233 // Get initial elements from seed or context
2234 elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ),
2235
2236 // Prefilter to get matcher input, preserving a map for seed-results synchronization
2237 matcherIn = preFilter && ( seed || !selector ) ?
2238 condense( elems, preMap, preFilter, context, xml ) :
2239 elems,
2240
2241 matcherOut = matcher ?
2242 // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
2243 postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
2244
2245 // ...intermediate processing is necessary
2246 [] :
2247
2248 // ...otherwise use results directly
2249 results :
2250 matcherIn;
2251
2252 // Find primary matches
2253 if ( matcher ) {
2254 matcher( matcherIn, matcherOut, context, xml );
2255 }
2256
2257 // Apply postFilter
2258 if ( postFilter ) {
2259 temp = condense( matcherOut, postMap );
2260 postFilter( temp, [], context, xml );
2261
2262 // Un-match failing elements by moving them back to matcherIn
2263 i = temp.length;
2264 while ( i-- ) {
2265 if ( (elem = temp[i]) ) {
2266 matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);
2267 }
2268 }
2269 }
2270
2271 if ( seed ) {
2272 if ( postFinder || preFilter ) {
2273 if ( postFinder ) {
2274 // Get the final matcherOut by condensing this intermediate into postFinder contexts
2275 temp = [];
2276 i = matcherOut.length;
2277 while ( i-- ) {
2278 if ( (elem = matcherOut[i]) ) {
2279 // Restore matcherIn since elem is not yet a final match
2280 temp.push( (matcherIn[i] = elem) );
2281 }
2282 }
2283 postFinder( null, (matcherOut = []), temp, xml );
2284 }
2285
2286 // Move matched elements from seed to results to keep them synchronized
2287 i = matcherOut.length;
2288 while ( i-- ) {
2289 if ( (elem = matcherOut[i]) &&
2290 (temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) {
2291
2292 seed[temp] = !(results[temp] = elem);
2293 }
2294 }
2295 }
2296
2297 // Add elements to results, through postFinder if defined
2298 } else {
2299 matcherOut = condense(
2300 matcherOut === results ?
2301 matcherOut.splice( preexisting, matcherOut.length ) :
2302 matcherOut
2303 );
2304 if ( postFinder ) {
2305 postFinder( null, results, matcherOut, xml );
2306 } else {
2307 push.apply( results, matcherOut );
2308 }
2309 }
2310 });
2311}
2312
2313function matcherFromTokens( tokens ) {
2314 var checkContext, matcher, j,
2315 len = tokens.length,
2316 leadingRelative = Expr.relative[ tokens[0].type ],
2317 implicitRelative = leadingRelative || Expr.relative[" "],
2318 i = leadingRelative ? 1 : 0,
2319
2320 // The foundational matcher ensures that elements are reachable from top-level context(s)
2321 matchContext = addCombinator( function( elem ) {
2322 return elem === checkContext;
2323 }, implicitRelative, true ),
2324 matchAnyContext = addCombinator( function( elem ) {
2325 return indexOf( checkContext, elem ) > -1;
2326 }, implicitRelative, true ),
2327 matchers = [ function( elem, context, xml ) {
2328 var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
2329 (checkContext = context).nodeType ?
2330 matchContext( elem, context, xml ) :
2331 matchAnyContext( elem, context, xml ) );
2332 // Avoid hanging onto element (issue #299)
2333 checkContext = null;
2334 return ret;
2335 } ];
2336
2337 for ( ; i < len; i++ ) {
2338 if ( (matcher = Expr.relative[ tokens[i].type ]) ) {
2339 matchers = [ addCombinator(elementMatcher( matchers ), matcher) ];
2340 } else {
2341 matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );
2342
2343 // Return special upon seeing a positional matcher
2344 if ( matcher[ expando ] ) {
2345 // Find the next relative operator (if any) for proper handling
2346 j = ++i;
2347 for ( ; j < len; j++ ) {
2348 if ( Expr.relative[ tokens[j].type ] ) {
2349 break;
2350 }
2351 }
2352 return setMatcher(
2353 i > 1 && elementMatcher( matchers ),
2354 i > 1 && toSelector(
2355 // If the preceding token was a descendant combinator, insert an implicit any-element `*`
2356 tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" })
2357 ).replace( rtrim, "$1" ),
2358 matcher,
2359 i < j && matcherFromTokens( tokens.slice( i, j ) ),
2360 j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),
2361 j < len && toSelector( tokens )
2362 );
2363 }
2364 matchers.push( matcher );
2365 }
2366 }
2367
2368 return elementMatcher( matchers );
2369}
2370
2371function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
2372 var bySet = setMatchers.length > 0,
2373 byElement = elementMatchers.length > 0,
2374 superMatcher = function( seed, context, xml, results, outermost ) {
2375 var elem, j, matcher,
2376 matchedCount = 0,
2377 i = "0",
2378 unmatched = seed && [],
2379 setMatched = [],
2380 contextBackup = outermostContext,
2381 // We must always have either seed elements or outermost context
2382 elems = seed || byElement && Expr.find["TAG"]( "*", outermost ),
2383 // Use integer dirruns iff this is the outermost matcher
2384 dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1),
2385 len = elems.length;
2386
2387 if ( outermost ) {
2388 outermostContext = context !== document && context;
2389 }
2390
2391 // Add elements passing elementMatchers directly to results
2392 // Keep `i` a string if there are no elements so `matchedCount` will be "00" below
2393 // Support: IE<9, Safari
2394 // Tolerate NodeList properties (IE: "length"; Safari: <number>) matching elements by id
2395 for ( ; i !== len && (elem = elems[i]) != null; i++ ) {
2396 if ( byElement && elem ) {
2397 j = 0;
2398 while ( (matcher = elementMatchers[j++]) ) {
2399 if ( matcher( elem, context, xml ) ) {
2400 results.push( elem );
2401 break;
2402 }
2403 }
2404 if ( outermost ) {
2405 dirruns = dirrunsUnique;
2406 }
2407 }
2408
2409 // Track unmatched elements for set filters
2410 if ( bySet ) {
2411 // They will have gone through all possible matchers
2412 if ( (elem = !matcher && elem) ) {
2413 matchedCount--;
2414 }
2415
2416 // Lengthen the array for every element, matched or not
2417 if ( seed ) {
2418 unmatched.push( elem );
2419 }
2420 }
2421 }
2422
2423 // Apply set filters to unmatched elements
2424 matchedCount += i;
2425 if ( bySet && i !== matchedCount ) {
2426 j = 0;
2427 while ( (matcher = setMatchers[j++]) ) {
2428 matcher( unmatched, setMatched, context, xml );
2429 }
2430
2431 if ( seed ) {
2432 // Reintegrate element matches to eliminate the need for sorting
2433 if ( matchedCount > 0 ) {
2434 while ( i-- ) {
2435 if ( !(unmatched[i] || setMatched[i]) ) {
2436 setMatched[i] = pop.call( results );
2437 }
2438 }
2439 }
2440
2441 // Discard index placeholder values to get only actual matches
2442 setMatched = condense( setMatched );
2443 }
2444
2445 // Add matches to results
2446 push.apply( results, setMatched );
2447
2448 // Seedless set matches succeeding multiple successful matchers stipulate sorting
2449 if ( outermost && !seed && setMatched.length > 0 &&
2450 ( matchedCount + setMatchers.length ) > 1 ) {
2451
2452 Sizzle.uniqueSort( results );
2453 }
2454 }
2455
2456 // Override manipulation of globals by nested matchers
2457 if ( outermost ) {
2458 dirruns = dirrunsUnique;
2459 outermostContext = contextBackup;
2460 }
2461
2462 return unmatched;
2463 };
2464
2465 return bySet ?
2466 markFunction( superMatcher ) :
2467 superMatcher;
2468}
2469
2470compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) {
2471 var i,
2472 setMatchers = [],
2473 elementMatchers = [],
2474 cached = compilerCache[ selector + " " ];
2475
2476 if ( !cached ) {
2477 // Generate a function of recursive functions that can be used to check each element
2478 if ( !match ) {
2479 match = tokenize( selector );
2480 }
2481 i = match.length;
2482 while ( i-- ) {
2483 cached = matcherFromTokens( match[i] );
2484 if ( cached[ expando ] ) {
2485 setMatchers.push( cached );
2486 } else {
2487 elementMatchers.push( cached );
2488 }
2489 }
2490
2491 // Cache the compiled function
2492 cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );
2493
2494 // Save selector and tokenization
2495 cached.selector = selector;
2496 }
2497 return cached;
2498};
2499
2500/**
2501 * A low-level selection function that works with Sizzle's compiled
2502 * selector functions
2503 * @param {String|Function} selector A selector or a pre-compiled
2504 * selector function built with Sizzle.compile
2505 * @param {Element} context
2506 * @param {Array} [results]
2507 * @param {Array} [seed] A set of elements to match against
2508 */
2509select = Sizzle.select = function( selector, context, results, seed ) {
2510 var i, tokens, token, type, find,
2511 compiled = typeof selector === "function" && selector,
2512 match = !seed && tokenize( (selector = compiled.selector || selector) );
2513
2514 results = results || [];
2515
2516 // Try to minimize operations if there is no seed and only one group
2517 if ( match.length === 1 ) {
2518
2519 // Take a shortcut and set the context if the root selector is an ID
2520 tokens = match[0] = match[0].slice( 0 );
2521 if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&
2522 support.getById && context.nodeType === 9 && documentIsHTML &&
2523 Expr.relative[ tokens[1].type ] ) {
2524
2525 context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];
2526 if ( !context ) {
2527 return results;
2528
2529 // Precompiled matchers will still verify ancestry, so step up a level
2530 } else if ( compiled ) {
2531 context = context.parentNode;
2532 }
2533
2534 selector = selector.slice( tokens.shift().value.length );
2535 }
2536
2537 // Fetch a seed set for right-to-left matching
2538 i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length;
2539 while ( i-- ) {
2540 token = tokens[i];
2541
2542 // Abort if we hit a combinator
2543 if ( Expr.relative[ (type = token.type) ] ) {
2544 break;
2545 }
2546 if ( (find = Expr.find[ type ]) ) {
2547 // Search, expanding context for leading sibling combinators
2548 if ( (seed = find(
2549 token.matches[0].replace( runescape, funescape ),
2550 rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context
2551 )) ) {
2552
2553 // If seed is empty or no tokens remain, we can return early
2554 tokens.splice( i, 1 );
2555 selector = seed.length && toSelector( tokens );
2556 if ( !selector ) {
2557 push.apply( results, seed );
2558 return results;
2559 }
2560
2561 break;
2562 }
2563 }
2564 }
2565 }
2566
2567 // Compile and execute a filtering function if one is not provided
2568 // Provide `match` to avoid retokenization if we modified the selector above
2569 ( compiled || compile( selector, match ) )(
2570 seed,
2571 context,
2572 !documentIsHTML,
2573 results,
2574 rsibling.test( selector ) && testContext( context.parentNode ) || context
2575 );
2576 return results;
2577};
2578
2579// One-time assignments
2580
2581// Sort stability
2582support.sortStable = expando.split("").sort( sortOrder ).join("") === expando;
2583
2584// Support: Chrome 14-35+
2585// Always assume duplicates if they aren't passed to the comparison function
2586support.detectDuplicates = !!hasDuplicate;
2587
2588// Initialize against the default document
2589setDocument();
2590
2591// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)
2592// Detached nodes confoundingly follow *each other*
2593support.sortDetached = assert(function( div1 ) {
2594 // Should return 1, but returns 4 (following)
2595 return div1.compareDocumentPosition( document.createElement("div") ) & 1;
2596});
2597
2598// Support: IE<8
2599// Prevent attribute/property "interpolation"
2600// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
2601if ( !assert(function( div ) {
2602 div.innerHTML = "<a href='#'></a>";
2603 return div.firstChild.getAttribute("href") === "#" ;
2604}) ) {
2605 addHandle( "type|href|height|width", function( elem, name, isXML ) {
2606 if ( !isXML ) {
2607 return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 );
2608 }
2609 });
2610}
2611
2612// Support: IE<9
2613// Use defaultValue in place of getAttribute("value")
2614if ( !support.attributes || !assert(function( div ) {
2615 div.innerHTML = "<input/>";
2616 div.firstChild.setAttribute( "value", "" );
2617 return div.firstChild.getAttribute( "value" ) === "";
2618}) ) {
2619 addHandle( "value", function( elem, name, isXML ) {
2620 if ( !isXML && elem.nodeName.toLowerCase() === "input" ) {
2621 return elem.defaultValue;
2622 }
2623 });
2624}
2625
2626// Support: IE<9
2627// Use getAttributeNode to fetch booleans when getAttribute lies
2628if ( !assert(function( div ) {
2629 return div.getAttribute("disabled") == null;
2630}) ) {
2631 addHandle( booleans, function( elem, name, isXML ) {
2632 var val;
2633 if ( !isXML ) {
2634 return elem[ name ] === true ? name.toLowerCase() :
2635 (val = elem.getAttributeNode( name )) && val.specified ?
2636 val.value :
2637 null;
2638 }
2639 });
2640}
2641
2642return Sizzle;
2643
2644})( window );
2645
2646
2647
2648jQuery.find = Sizzle;
2649jQuery.expr = Sizzle.selectors;
2650jQuery.expr[":"] = jQuery.expr.pseudos;
2651jQuery.unique = Sizzle.uniqueSort;
2652jQuery.text = Sizzle.getText;
2653jQuery.isXMLDoc = Sizzle.isXML;
2654jQuery.contains = Sizzle.contains;
2655
2656
2657
2658var rneedsContext = jQuery.expr.match.needsContext;
2659
2660var rsingleTag = (/^<(\w+)\s*\/?>(?:<\/\1>|)$/);
2661
2662
2663
2664var risSimple = /^.[^:#\[\.,]*$/;
2665
2666// Implement the identical functionality for filter and not
2667function winnow( elements, qualifier, not ) {
2668 if ( jQuery.isFunction( qualifier ) ) {
2669 return jQuery.grep( elements, function( elem, i ) {
2670 /* jshint -W018 */
2671 return !!qualifier.call( elem, i, elem ) !== not;
2672 });
2673
2674 }
2675
2676 if ( qualifier.nodeType ) {
2677 return jQuery.grep( elements, function( elem ) {
2678 return ( elem === qualifier ) !== not;
2679 });
2680
2681 }
2682
2683 if ( typeof qualifier === "string" ) {
2684 if ( risSimple.test( qualifier ) ) {
2685 return jQuery.filter( qualifier, elements, not );
2686 }
2687
2688 qualifier = jQuery.filter( qualifier, elements );
2689 }
2690
2691 return jQuery.grep( elements, function( elem ) {
2692 return ( jQuery.inArray( elem, qualifier ) >= 0 ) !== not;
2693 });
2694}
2695
2696jQuery.filter = function( expr, elems, not ) {
2697 var elem = elems[ 0 ];
2698
2699 if ( not ) {
2700 expr = ":not(" + expr + ")";
2701 }
2702
2703 return elems.length === 1 && elem.nodeType === 1 ?
2704 jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] :
2705 jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) {
2706 return elem.nodeType === 1;
2707 }));
2708};
2709
2710jQuery.fn.extend({
2711 find: function( selector ) {
2712 var i,
2713 ret = [],
2714 self = this,
2715 len = self.length;
2716
2717 if ( typeof selector !== "string" ) {
2718 return this.pushStack( jQuery( selector ).filter(function() {
2719 for ( i = 0; i < len; i++ ) {
2720 if ( jQuery.contains( self[ i ], this ) ) {
2721 return true;
2722 }
2723 }
2724 }) );
2725 }
2726
2727 for ( i = 0; i < len; i++ ) {
2728 jQuery.find( selector, self[ i ], ret );
2729 }
2730
2731 // Needed because $( selector, context ) becomes $( context ).find( selector )
2732 ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret );
2733 ret.selector = this.selector ? this.selector + " " + selector : selector;
2734 return ret;
2735 },
2736 filter: function( selector ) {
2737 return this.pushStack( winnow(this, selector || [], false) );
2738 },
2739 not: function( selector ) {
2740 return this.pushStack( winnow(this, selector || [], true) );
2741 },
2742 is: function( selector ) {
2743 return !!winnow(
2744 this,
2745
2746 // If this is a positional/relative selector, check membership in the returned set
2747 // so $("p:first").is("p:last") won't return true for a doc with two "p".
2748 typeof selector === "string" && rneedsContext.test( selector ) ?
2749 jQuery( selector ) :
2750 selector || [],
2751 false
2752 ).length;
2753 }
2754});
2755
2756
2757// Initialize a jQuery object
2758
2759
2760// A central reference to the root jQuery(document)
2761var rootjQuery,
2762
2763 // Use the correct document accordingly with window argument (sandbox)
2764 document = window.document,
2765
2766 // A simple way to check for HTML strings
2767 // Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
2768 // Strict HTML recognition (#11290: must start with <)
2769 rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,
2770
2771 init = jQuery.fn.init = function( selector, context ) {
2772 var match, elem;
2773
2774 // HANDLE: $(""), $(null), $(undefined), $(false)
2775 if ( !selector ) {
2776 return this;
2777 }
2778
2779 // Handle HTML strings
2780 if ( typeof selector === "string" ) {
2781 if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
2782 // Assume that strings that start and end with <> are HTML and skip the regex check
2783 match = [ null, selector, null ];
2784
2785 } else {
2786 match = rquickExpr.exec( selector );
2787 }
2788
2789 // Match html or make sure no context is specified for #id
2790 if ( match && (match[1] || !context) ) {
2791
2792 // HANDLE: $(html) -> $(array)
2793 if ( match[1] ) {
2794 context = context instanceof jQuery ? context[0] : context;
2795
2796 // scripts is true for back-compat
2797 // Intentionally let the error be thrown if parseHTML is not present
2798 jQuery.merge( this, jQuery.parseHTML(
2799 match[1],
2800 context && context.nodeType ? context.ownerDocument || context : document,
2801 true
2802 ) );
2803
2804 // HANDLE: $(html, props)
2805 if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {
2806 for ( match in context ) {
2807 // Properties of context are called as methods if possible
2808 if ( jQuery.isFunction( this[ match ] ) ) {
2809 this[ match ]( context[ match ] );
2810
2811 // ...and otherwise set as attributes
2812 } else {
2813 this.attr( match, context[ match ] );
2814 }
2815 }
2816 }
2817
2818 return this;
2819
2820 // HANDLE: $(#id)
2821 } else {
2822 elem = document.getElementById( match[2] );
2823
2824 // Check parentNode to catch when Blackberry 4.6 returns
2825 // nodes that are no longer in the document #6963
2826 if ( elem && elem.parentNode ) {
2827 // Handle the case where IE and Opera return items
2828 // by name instead of ID
2829 if ( elem.id !== match[2] ) {
2830 return rootjQuery.find( selector );
2831 }
2832
2833 // Otherwise, we inject the element directly into the jQuery object
2834 this.length = 1;
2835 this[0] = elem;
2836 }
2837
2838 this.context = document;
2839 this.selector = selector;
2840 return this;
2841 }
2842
2843 // HANDLE: $(expr, $(...))
2844 } else if ( !context || context.jquery ) {
2845 return ( context || rootjQuery ).find( selector );
2846
2847 // HANDLE: $(expr, context)
2848 // (which is just equivalent to: $(context).find(expr)
2849 } else {
2850 return this.constructor( context ).find( selector );
2851 }
2852
2853 // HANDLE: $(DOMElement)
2854 } else if ( selector.nodeType ) {
2855 this.context = this[0] = selector;
2856 this.length = 1;
2857 return this;
2858
2859 // HANDLE: $(function)
2860 // Shortcut for document ready
2861 } else if ( jQuery.isFunction( selector ) ) {
2862 return typeof rootjQuery.ready !== "undefined" ?
2863 rootjQuery.ready( selector ) :
2864 // Execute immediately if ready is not present
2865 selector( jQuery );
2866 }
2867
2868 if ( selector.selector !== undefined ) {
2869 this.selector = selector.selector;
2870 this.context = selector.context;
2871 }
2872
2873 return jQuery.makeArray( selector, this );
2874 };
2875
2876// Give the init function the jQuery prototype for later instantiation
2877init.prototype = jQuery.fn;
2878
2879// Initialize central reference
2880rootjQuery = jQuery( document );
2881
2882
2883var rparentsprev = /^(?:parents|prev(?:Until|All))/,
2884 // methods guaranteed to produce a unique set when starting from a unique set
2885 guaranteedUnique = {
2886 children: true,
2887 contents: true,
2888 next: true,
2889 prev: true
2890 };
2891
2892jQuery.extend({
2893 dir: function( elem, dir, until ) {
2894 var matched = [],
2895 cur = elem[ dir ];
2896
2897 while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {
2898 if ( cur.nodeType === 1 ) {
2899 matched.push( cur );
2900 }
2901 cur = cur[dir];
2902 }
2903 return matched;
2904 },
2905
2906 sibling: function( n, elem ) {
2907 var r = [];
2908
2909 for ( ; n; n = n.nextSibling ) {
2910 if ( n.nodeType === 1 && n !== elem ) {
2911 r.push( n );
2912 }
2913 }
2914
2915 return r;
2916 }
2917});
2918
2919jQuery.fn.extend({
2920 has: function( target ) {
2921 var i,
2922 targets = jQuery( target, this ),
2923 len = targets.length;
2924
2925 return this.filter(function() {
2926 for ( i = 0; i < len; i++ ) {
2927 if ( jQuery.contains( this, targets[i] ) ) {
2928 return true;
2929 }
2930 }
2931 });
2932 },
2933
2934 closest: function( selectors, context ) {
2935 var cur,
2936 i = 0,
2937 l = this.length,
2938 matched = [],
2939 pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ?
2940 jQuery( selectors, context || this.context ) :
2941 0;
2942
2943 for ( ; i < l; i++ ) {
2944 for ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) {
2945 // Always skip document fragments
2946 if ( cur.nodeType < 11 && (pos ?
2947 pos.index(cur) > -1 :
2948
2949 // Don't pass non-elements to Sizzle
2950 cur.nodeType === 1 &&
2951 jQuery.find.matchesSelector(cur, selectors)) ) {
2952
2953 matched.push( cur );
2954 break;
2955 }
2956 }
2957 }
2958
2959 return this.pushStack( matched.length > 1 ? jQuery.unique( matched ) : matched );
2960 },
2961
2962 // Determine the position of an element within
2963 // the matched set of elements
2964 index: function( elem ) {
2965
2966 // No argument, return index in parent
2967 if ( !elem ) {
2968 return ( this[0] && this[0].parentNode ) ? this.first().prevAll().length : -1;
2969 }
2970
2971 // index in selector
2972 if ( typeof elem === "string" ) {
2973 return jQuery.inArray( this[0], jQuery( elem ) );
2974 }
2975
2976 // Locate the position of the desired element
2977 return jQuery.inArray(
2978 // If it receives a jQuery object, the first element is used
2979 elem.jquery ? elem[0] : elem, this );
2980 },
2981
2982 add: function( selector, context ) {
2983 return this.pushStack(
2984 jQuery.unique(
2985 jQuery.merge( this.get(), jQuery( selector, context ) )
2986 )
2987 );
2988 },
2989
2990 addBack: function( selector ) {
2991 return this.add( selector == null ?
2992 this.prevObject : this.prevObject.filter(selector)
2993 );
2994 }
2995});
2996
2997function sibling( cur, dir ) {
2998 do {
2999 cur = cur[ dir ];
3000 } while ( cur && cur.nodeType !== 1 );
3001
3002 return cur;
3003}
3004
3005jQuery.each({
3006 parent: function( elem ) {
3007 var parent = elem.parentNode;
3008 return parent && parent.nodeType !== 11 ? parent : null;
3009 },
3010 parents: function( elem ) {
3011 return jQuery.dir( elem, "parentNode" );
3012 },
3013 parentsUntil: function( elem, i, until ) {
3014 return jQuery.dir( elem, "parentNode", until );
3015 },
3016 next: function( elem ) {
3017 return sibling( elem, "nextSibling" );
3018 },
3019 prev: function( elem ) {
3020 return sibling( elem, "previousSibling" );
3021 },
3022 nextAll: function( elem ) {
3023 return jQuery.dir( elem, "nextSibling" );
3024 },
3025 prevAll: function( elem ) {
3026 return jQuery.dir( elem, "previousSibling" );
3027 },
3028 nextUntil: function( elem, i, until ) {
3029 return jQuery.dir( elem, "nextSibling", until );
3030 },
3031 prevUntil: function( elem, i, until ) {
3032 return jQuery.dir( elem, "previousSibling", until );
3033 },
3034 siblings: function( elem ) {
3035 return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );
3036 },
3037 children: function( elem ) {
3038 return jQuery.sibling( elem.firstChild );
3039 },
3040 contents: function( elem ) {
3041 return jQuery.nodeName( elem, "iframe" ) ?
3042 elem.contentDocument || elem.contentWindow.document :
3043 jQuery.merge( [], elem.childNodes );
3044 }
3045}, function( name, fn ) {
3046 jQuery.fn[ name ] = function( until, selector ) {
3047 var ret = jQuery.map( this, fn, until );
3048
3049 if ( name.slice( -5 ) !== "Until" ) {
3050 selector = until;
3051 }
3052
3053 if ( selector && typeof selector === "string" ) {
3054 ret = jQuery.filter( selector, ret );
3055 }
3056
3057 if ( this.length > 1 ) {
3058 // Remove duplicates
3059 if ( !guaranteedUnique[ name ] ) {
3060 ret = jQuery.unique( ret );
3061 }
3062
3063 // Reverse order for parents* and prev-derivatives
3064 if ( rparentsprev.test( name ) ) {
3065 ret = ret.reverse();
3066 }
3067 }
3068
3069 return this.pushStack( ret );
3070 };
3071});
3072var rnotwhite = (/\S+/g);
3073
3074
3075
3076// String to Object options format cache
3077var optionsCache = {};
3078
3079// Convert String-formatted options into Object-formatted ones and store in cache
3080function createOptions( options ) {
3081 var object = optionsCache[ options ] = {};
3082 jQuery.each( options.match( rnotwhite ) || [], function( _, flag ) {
3083 object[ flag ] = true;
3084 });
3085 return object;
3086}
3087
3088/*
3089 * Create a callback list using the following parameters:
3090 *
3091 * options: an optional list of space-separated options that will change how
3092 * the callback list behaves or a more traditional option object
3093 *
3094 * By default a callback list will act like an event callback list and can be
3095 * "fired" multiple times.
3096 *
3097 * Possible options:
3098 *
3099 * once: will ensure the callback list can only be fired once (like a Deferred)
3100 *
3101 * memory: will keep track of previous values and will call any callback added
3102 * after the list has been fired right away with the latest "memorized"
3103 * values (like a Deferred)
3104 *
3105 * unique: will ensure a callback can only be added once (no duplicate in the list)
3106 *
3107 * stopOnFalse: interrupt callings when a callback returns false
3108 *
3109 */
3110jQuery.Callbacks = function( options ) {
3111
3112 // Convert options from String-formatted to Object-formatted if needed
3113 // (we check in cache first)
3114 options = typeof options === "string" ?
3115 ( optionsCache[ options ] || createOptions( options ) ) :
3116 jQuery.extend( {}, options );
3117
3118 var // Flag to know if list is currently firing
3119 firing,
3120 // Last fire value (for non-forgettable lists)
3121 memory,
3122 // Flag to know if list was already fired
3123 fired,
3124 // End of the loop when firing
3125 firingLength,
3126 // Index of currently firing callback (modified by remove if needed)
3127 firingIndex,
3128 // First callback to fire (used internally by add and fireWith)
3129 firingStart,
3130 // Actual callback list
3131 list = [],
3132 // Stack of fire calls for repeatable lists
3133 stack = !options.once && [],
3134 // Fire callbacks
3135 fire = function( data ) {
3136 memory = options.memory && data;
3137 fired = true;
3138 firingIndex = firingStart || 0;
3139 firingStart = 0;
3140 firingLength = list.length;
3141 firing = true;
3142 for ( ; list && firingIndex < firingLength; firingIndex++ ) {
3143 if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {
3144 memory = false; // To prevent further calls using add
3145 break;
3146 }
3147 }
3148 firing = false;
3149 if ( list ) {
3150 if ( stack ) {
3151 if ( stack.length ) {
3152 fire( stack.shift() );
3153 }
3154 } else if ( memory ) {
3155 list = [];
3156 } else {
3157 self.disable();
3158 }
3159 }
3160 },
3161 // Actual Callbacks object
3162 self = {
3163 // Add a callback or a collection of callbacks to the list
3164 add: function() {
3165 if ( list ) {
3166 // First, we save the current length
3167 var start = list.length;
3168 (function add( args ) {
3169 jQuery.each( args, function( _, arg ) {
3170 var type = jQuery.type( arg );
3171 if ( type === "function" ) {
3172 if ( !options.unique || !self.has( arg ) ) {
3173 list.push( arg );
3174 }
3175 } else if ( arg && arg.length && type !== "string" ) {
3176 // Inspect recursively
3177 add( arg );
3178 }
3179 });
3180 })( arguments );
3181 // Do we need to add the callbacks to the
3182 // current firing batch?
3183 if ( firing ) {
3184 firingLength = list.length;
3185 // With memory, if we're not firing then
3186 // we should call right away
3187 } else if ( memory ) {
3188 firingStart = start;
3189 fire( memory );
3190 }
3191 }
3192 return this;
3193 },
3194 // Remove a callback from the list
3195 remove: function() {
3196 if ( list ) {
3197 jQuery.each( arguments, function( _, arg ) {
3198 var index;
3199 while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
3200 list.splice( index, 1 );
3201 // Handle firing indexes
3202 if ( firing ) {
3203 if ( index <= firingLength ) {
3204 firingLength--;
3205 }
3206 if ( index <= firingIndex ) {
3207 firingIndex--;
3208 }
3209 }
3210 }
3211 });
3212 }
3213 return this;
3214 },
3215 // Check if a given callback is in the list.
3216 // If no argument is given, return whether or not list has callbacks attached.
3217 has: function( fn ) {
3218 return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length );
3219 },
3220 // Remove all callbacks from the list
3221 empty: function() {
3222 list = [];
3223 firingLength = 0;
3224 return this;
3225 },
3226 // Have the list do nothing anymore
3227 disable: function() {
3228 list = stack = memory = undefined;
3229 return this;
3230 },
3231 // Is it disabled?
3232 disabled: function() {
3233 return !list;
3234 },
3235 // Lock the list in its current state
3236 lock: function() {
3237 stack = undefined;
3238 if ( !memory ) {
3239 self.disable();
3240 }
3241 return this;
3242 },
3243 // Is it locked?
3244 locked: function() {
3245 return !stack;
3246 },
3247 // Call all callbacks with the given context and arguments
3248 fireWith: function( context, args ) {
3249 if ( list && ( !fired || stack ) ) {
3250 args = args || [];
3251 args = [ context, args.slice ? args.slice() : args ];
3252 if ( firing ) {
3253 stack.push( args );
3254 } else {
3255 fire( args );
3256 }
3257 }
3258 return this;
3259 },
3260 // Call all the callbacks with the given arguments
3261 fire: function() {
3262 self.fireWith( this, arguments );
3263 return this;
3264 },
3265 // To know if the callbacks have already been called at least once
3266 fired: function() {
3267 return !!fired;
3268 }
3269 };
3270
3271 return self;
3272};
3273
3274
3275jQuery.extend({
3276
3277 Deferred: function( func ) {
3278 var tuples = [
3279 // action, add listener, listener list, final state
3280 [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ],
3281 [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ],
3282 [ "notify", "progress", jQuery.Callbacks("memory") ]
3283 ],
3284 state = "pending",
3285 promise = {
3286 state: function() {
3287 return state;
3288 },
3289 always: function() {
3290 deferred.done( arguments ).fail( arguments );
3291 return this;
3292 },
3293 then: function( /* fnDone, fnFail, fnProgress */ ) {
3294 var fns = arguments;
3295 return jQuery.Deferred(function( newDefer ) {
3296 jQuery.each( tuples, function( i, tuple ) {
3297 var fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];
3298 // deferred[ done | fail | progress ] for forwarding actions to newDefer
3299 deferred[ tuple[1] ](function() {
3300 var returned = fn && fn.apply( this, arguments );
3301 if ( returned && jQuery.isFunction( returned.promise ) ) {
3302 returned.promise()
3303 .done( newDefer.resolve )
3304 .fail( newDefer.reject )
3305 .progress( newDefer.notify );
3306 } else {
3307 newDefer[ tuple[ 0 ] + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments );
3308 }
3309 });
3310 });
3311 fns = null;
3312 }).promise();
3313 },
3314 // Get a promise for this deferred
3315 // If obj is provided, the promise aspect is added to the object
3316 promise: function( obj ) {
3317 return obj != null ? jQuery.extend( obj, promise ) : promise;
3318 }
3319 },
3320 deferred = {};
3321
3322 // Keep pipe for back-compat
3323 promise.pipe = promise.then;
3324
3325 // Add list-specific methods
3326 jQuery.each( tuples, function( i, tuple ) {
3327 var list = tuple[ 2 ],
3328 stateString = tuple[ 3 ];
3329
3330 // promise[ done | fail | progress ] = list.add
3331 promise[ tuple[1] ] = list.add;
3332
3333 // Handle state
3334 if ( stateString ) {
3335 list.add(function() {
3336 // state = [ resolved | rejected ]
3337 state = stateString;
3338
3339 // [ reject_list | resolve_list ].disable; progress_list.lock
3340 }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );
3341 }
3342
3343 // deferred[ resolve | reject | notify ]
3344 deferred[ tuple[0] ] = function() {
3345 deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments );
3346 return this;
3347 };
3348 deferred[ tuple[0] + "With" ] = list.fireWith;
3349 });
3350
3351 // Make the deferred a promise
3352 promise.promise( deferred );
3353
3354 // Call given func if any
3355 if ( func ) {
3356 func.call( deferred, deferred );
3357 }
3358
3359 // All done!
3360 return deferred;
3361 },
3362
3363 // Deferred helper
3364 when: function( subordinate /* , ..., subordinateN */ ) {
3365 var i = 0,
3366 resolveValues = slice.call( arguments ),
3367 length = resolveValues.length,
3368
3369 // the count of uncompleted subordinates
3370 remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,
3371
3372 // the master Deferred. If resolveValues consist of only a single Deferred, just use that.
3373 deferred = remaining === 1 ? subordinate : jQuery.Deferred(),
3374
3375 // Update function for both resolve and progress values
3376 updateFunc = function( i, contexts, values ) {
3377 return function( value ) {
3378 contexts[ i ] = this;
3379 values[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;
3380 if ( values === progressValues ) {
3381 deferred.notifyWith( contexts, values );
3382
3383 } else if ( !(--remaining) ) {
3384 deferred.resolveWith( contexts, values );
3385 }
3386 };
3387 },
3388
3389 progressValues, progressContexts, resolveContexts;
3390
3391 // add listeners to Deferred subordinates; treat others as resolved
3392 if ( length > 1 ) {
3393 progressValues = new Array( length );
3394 progressContexts = new Array( length );
3395 resolveContexts = new Array( length );
3396 for ( ; i < length; i++ ) {
3397 if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {
3398 resolveValues[ i ].promise()
3399 .done( updateFunc( i, resolveContexts, resolveValues ) )
3400 .fail( deferred.reject )
3401 .progress( updateFunc( i, progressContexts, progressValues ) );
3402 } else {
3403 --remaining;
3404 }
3405 }
3406 }
3407
3408 // if we're not waiting on anything, resolve the master
3409 if ( !remaining ) {
3410 deferred.resolveWith( resolveContexts, resolveValues );
3411 }
3412
3413 return deferred.promise();
3414 }
3415});
3416
3417
3418// The deferred used on DOM ready
3419var readyList;
3420
3421jQuery.fn.ready = function( fn ) {
3422 // Add the callback
3423 jQuery.ready.promise().done( fn );
3424
3425 return this;
3426};
3427
3428jQuery.extend({
3429 // Is the DOM ready to be used? Set to true once it occurs.
3430 isReady: false,
3431
3432 // A counter to track how many items to wait for before
3433 // the ready event fires. See #6781
3434 readyWait: 1,
3435
3436 // Hold (or release) the ready event
3437 holdReady: function( hold ) {
3438 if ( hold ) {
3439 jQuery.readyWait++;
3440 } else {
3441 jQuery.ready( true );
3442 }
3443 },
3444
3445 // Handle when the DOM is ready
3446 ready: function( wait ) {
3447
3448 // Abort if there are pending holds or we're already ready
3449 if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
3450 return;
3451 }
3452
3453 // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
3454 if ( !document.body ) {
3455 return setTimeout( jQuery.ready );
3456 }
3457
3458 // Remember that the DOM is ready
3459 jQuery.isReady = true;
3460
3461 // If a normal DOM Ready event fired, decrement, and wait if need be
3462 if ( wait !== true && --jQuery.readyWait > 0 ) {
3463 return;
3464 }
3465
3466 // If there are functions bound, to execute
3467 readyList.resolveWith( document, [ jQuery ] );
3468
3469 // Trigger any bound ready events
3470 if ( jQuery.fn.triggerHandler ) {
3471 jQuery( document ).triggerHandler( "ready" );
3472 jQuery( document ).off( "ready" );
3473 }
3474 }
3475});
3476
3477/**
3478 * Clean-up method for dom ready events
3479 */
3480function detach() {
3481 if ( document.addEventListener ) {
3482 document.removeEventListener( "DOMContentLoaded", completed, false );
3483 window.removeEventListener( "load", completed, false );
3484
3485 } else {
3486 document.detachEvent( "onreadystatechange", completed );
3487 window.detachEvent( "onload", completed );
3488 }
3489}
3490
3491/**
3492 * The ready event handler and self cleanup method
3493 */
3494function completed() {
3495 // readyState === "complete" is good enough for us to call the dom ready in oldIE
3496 if ( document.addEventListener || event.type === "load" || document.readyState === "complete" ) {
3497 detach();
3498 jQuery.ready();
3499 }
3500}
3501
3502jQuery.ready.promise = function( obj ) {
3503 if ( !readyList ) {
3504
3505 readyList = jQuery.Deferred();
3506
3507 // Catch cases where $(document).ready() is called after the browser event has already occurred.
3508 // we once tried to use readyState "interactive" here, but it caused issues like the one
3509 // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15
3510 if ( document.readyState === "complete" ) {
3511 // Handle it asynchronously to allow scripts the opportunity to delay ready
3512 setTimeout( jQuery.ready );
3513
3514 // Standards-based browsers support DOMContentLoaded
3515 } else if ( document.addEventListener ) {
3516 // Use the handy event callback
3517 document.addEventListener( "DOMContentLoaded", completed, false );
3518
3519 // A fallback to window.onload, that will always work
3520 window.addEventListener( "load", completed, false );
3521
3522 // If IE event model is used
3523 } else {
3524 // Ensure firing before onload, maybe late but safe also for iframes
3525 document.attachEvent( "onreadystatechange", completed );
3526
3527 // A fallback to window.onload, that will always work
3528 window.attachEvent( "onload", completed );
3529
3530 // If IE and not a frame
3531 // continually check to see if the document is ready
3532 var top = false;
3533
3534 try {
3535 top = window.frameElement == null && document.documentElement;
3536 } catch(e) {}
3537
3538 if ( top && top.doScroll ) {
3539 (function doScrollCheck() {
3540 if ( !jQuery.isReady ) {
3541
3542 try {
3543 // Use the trick by Diego Perini
3544 // http://javascript.nwbox.com/IEContentLoaded/
3545 top.doScroll("left");
3546 } catch(e) {
3547 return setTimeout( doScrollCheck, 50 );
3548 }
3549
3550 // detach all dom ready events
3551 detach();
3552
3553 // and execute any waiting functions
3554 jQuery.ready();
3555 }
3556 })();
3557 }
3558 }
3559 }
3560 return readyList.promise( obj );
3561};
3562
3563
3564var strundefined = typeof undefined;
3565
3566
3567
3568// Support: IE<9
3569// Iteration over object's inherited properties before its own
3570var i;
3571for ( i in jQuery( support ) ) {
3572 break;
3573}
3574support.ownLast = i !== "0";
3575
3576// Note: most support tests are defined in their respective modules.
3577// false until the test is run
3578support.inlineBlockNeedsLayout = false;
3579
3580// Execute ASAP in case we need to set body.style.zoom
3581jQuery(function() {
3582 // Minified: var a,b,c,d
3583 var val, div, body, container;
3584
3585 body = document.getElementsByTagName( "body" )[ 0 ];
3586 if ( !body || !body.style ) {
3587 // Return for frameset docs that don't have a body
3588 return;
3589 }
3590
3591 // Setup
3592 div = document.createElement( "div" );
3593 container = document.createElement( "div" );
3594 container.style.cssText = "position:absolute;border:0;width:0;height:0;top:0;left:-9999px";
3595 body.appendChild( container ).appendChild( div );
3596
3597 if ( typeof div.style.zoom !== strundefined ) {
3598 // Support: IE<8
3599 // Check if natively block-level elements act like inline-block
3600 // elements when setting their display to 'inline' and giving
3601 // them layout
3602 div.style.cssText = "display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1";
3603
3604 support.inlineBlockNeedsLayout = val = div.offsetWidth === 3;
3605 if ( val ) {
3606 // Prevent IE 6 from affecting layout for positioned elements #11048
3607 // Prevent IE from shrinking the body in IE 7 mode #12869
3608 // Support: IE<8
3609 body.style.zoom = 1;
3610 }
3611 }
3612
3613 body.removeChild( container );
3614});
3615
3616
3617
3618
3619(function() {
3620 var div = document.createElement( "div" );
3621
3622 // Execute the test only if not already executed in another module.
3623 if (support.deleteExpando == null) {
3624 // Support: IE<9
3625 support.deleteExpando = true;
3626 try {
3627 delete div.test;
3628 } catch( e ) {
3629 support.deleteExpando = false;
3630 }
3631 }
3632
3633 // Null elements to avoid leaks in IE.
3634 div = null;
3635})();
3636
3637
3638/**
3639 * Determines whether an object can have data
3640 */
3641jQuery.acceptData = function( elem ) {
3642 var noData = jQuery.noData[ (elem.nodeName + " ").toLowerCase() ],
3643 nodeType = +elem.nodeType || 1;
3644
3645 // Do not set data on non-element DOM nodes because it will not be cleared (#8335).
3646 return nodeType !== 1 && nodeType !== 9 ?
3647 false :
3648
3649 // Nodes accept data unless otherwise specified; rejection can be conditional
3650 !noData || noData !== true && elem.getAttribute("classid") === noData;
3651};
3652
3653
3654var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,
3655 rmultiDash = /([A-Z])/g;
3656
3657function dataAttr( elem, key, data ) {
3658 // If nothing was found internally, try to fetch any
3659 // data from the HTML5 data-* attribute
3660 if ( data === undefined && elem.nodeType === 1 ) {
3661
3662 var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();
3663
3664 data = elem.getAttribute( name );
3665
3666 if ( typeof data === "string" ) {
3667 try {
3668 data = data === "true" ? true :
3669 data === "false" ? false :
3670 data === "null" ? null :
3671 // Only convert to a number if it doesn't change the string
3672 +data + "" === data ? +data :
3673 rbrace.test( data ) ? jQuery.parseJSON( data ) :
3674 data;
3675 } catch( e ) {}
3676
3677 // Make sure we set the data so it isn't changed later
3678 jQuery.data( elem, key, data );
3679
3680 } else {
3681 data = undefined;
3682 }
3683 }
3684
3685 return data;
3686}
3687
3688// checks a cache object for emptiness
3689function isEmptyDataObject( obj ) {
3690 var name;
3691 for ( name in obj ) {
3692
3693 // if the public data object is empty, the private is still empty
3694 if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) {
3695 continue;
3696 }
3697 if ( name !== "toJSON" ) {
3698 return false;
3699 }
3700 }
3701
3702 return true;
3703}
3704
3705function internalData( elem, name, data, pvt /* Internal Use Only */ ) {
3706 if ( !jQuery.acceptData( elem ) ) {
3707 return;
3708 }
3709
3710 var ret, thisCache,
3711 internalKey = jQuery.expando,
3712
3713 // We have to handle DOM nodes and JS objects differently because IE6-7
3714 // can't GC object references properly across the DOM-JS boundary
3715 isNode = elem.nodeType,
3716
3717 // Only DOM nodes need the global jQuery cache; JS object data is
3718 // attached directly to the object so GC can occur automatically
3719 cache = isNode ? jQuery.cache : elem,
3720
3721 // Only defining an ID for JS objects if its cache already exists allows
3722 // the code to shortcut on the same path as a DOM node with no cache
3723 id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey;
3724
3725 // Avoid doing any more work than we need to when trying to get data on an
3726 // object that has no data at all
3727 if ( (!id || !cache[id] || (!pvt && !cache[id].data)) && data === undefined && typeof name === "string" ) {
3728 return;
3729 }
3730
3731 if ( !id ) {
3732 // Only DOM nodes need a new unique ID for each element since their data
3733 // ends up in the global cache
3734 if ( isNode ) {
3735 id = elem[ internalKey ] = deletedIds.pop() || jQuery.guid++;
3736 } else {
3737 id = internalKey;
3738 }
3739 }
3740
3741 if ( !cache[ id ] ) {
3742 // Avoid exposing jQuery metadata on plain JS objects when the object
3743 // is serialized using JSON.stringify
3744 cache[ id ] = isNode ? {} : { toJSON: jQuery.noop };
3745 }
3746
3747 // An object can be passed to jQuery.data instead of a key/value pair; this gets
3748 // shallow copied over onto the existing cache
3749 if ( typeof name === "object" || typeof name === "function" ) {
3750 if ( pvt ) {
3751 cache[ id ] = jQuery.extend( cache[ id ], name );
3752 } else {
3753 cache[ id ].data = jQuery.extend( cache[ id ].data, name );
3754 }
3755 }
3756
3757 thisCache = cache[ id ];
3758
3759 // jQuery data() is stored in a separate object inside the object's internal data
3760 // cache in order to avoid key collisions between internal data and user-defined
3761 // data.
3762 if ( !pvt ) {
3763 if ( !thisCache.data ) {
3764 thisCache.data = {};
3765 }
3766
3767 thisCache = thisCache.data;
3768 }
3769
3770 if ( data !== undefined ) {
3771 thisCache[ jQuery.camelCase( name ) ] = data;
3772 }
3773
3774 // Check for both converted-to-camel and non-converted data property names
3775 // If a data property was specified
3776 if ( typeof name === "string" ) {
3777
3778 // First Try to find as-is property data
3779 ret = thisCache[ name ];
3780
3781 // Test for null|undefined property data
3782 if ( ret == null ) {
3783
3784 // Try to find the camelCased property
3785 ret = thisCache[ jQuery.camelCase( name ) ];
3786 }
3787 } else {
3788 ret = thisCache;
3789 }
3790
3791 return ret;
3792}
3793
3794function internalRemoveData( elem, name, pvt ) {
3795 if ( !jQuery.acceptData( elem ) ) {
3796 return;
3797 }
3798
3799 var thisCache, i,
3800 isNode = elem.nodeType,
3801
3802 // See jQuery.data for more information
3803 cache = isNode ? jQuery.cache : elem,
3804 id = isNode ? elem[ jQuery.expando ] : jQuery.expando;
3805
3806 // If there is already no cache entry for this object, there is no
3807 // purpose in continuing
3808 if ( !cache[ id ] ) {
3809 return;
3810 }
3811
3812 if ( name ) {
3813
3814 thisCache = pvt ? cache[ id ] : cache[ id ].data;
3815
3816 if ( thisCache ) {
3817
3818 // Support array or space separated string names for data keys
3819 if ( !jQuery.isArray( name ) ) {
3820
3821 // try the string as a key before any manipulation
3822 if ( name in thisCache ) {
3823 name = [ name ];
3824 } else {
3825
3826 // split the camel cased version by spaces unless a key with the spaces exists
3827 name = jQuery.camelCase( name );
3828 if ( name in thisCache ) {
3829 name = [ name ];
3830 } else {
3831 name = name.split(" ");
3832 }
3833 }
3834 } else {
3835 // If "name" is an array of keys...
3836 // When data is initially created, via ("key", "val") signature,
3837 // keys will be converted to camelCase.
3838 // Since there is no way to tell _how_ a key was added, remove
3839 // both plain key and camelCase key. #12786
3840 // This will only penalize the array argument path.
3841 name = name.concat( jQuery.map( name, jQuery.camelCase ) );
3842 }
3843
3844 i = name.length;
3845 while ( i-- ) {
3846 delete thisCache[ name[i] ];
3847 }
3848
3849 // If there is no data left in the cache, we want to continue
3850 // and let the cache object itself get destroyed
3851 if ( pvt ? !isEmptyDataObject(thisCache) : !jQuery.isEmptyObject(thisCache) ) {
3852 return;
3853 }
3854 }
3855 }
3856
3857 // See jQuery.data for more information
3858 if ( !pvt ) {
3859 delete cache[ id ].data;
3860
3861 // Don't destroy the parent cache unless the internal data object
3862 // had been the only thing left in it
3863 if ( !isEmptyDataObject( cache[ id ] ) ) {
3864 return;
3865 }
3866 }
3867
3868 // Destroy the cache
3869 if ( isNode ) {
3870 jQuery.cleanData( [ elem ], true );
3871
3872 // Use delete when supported for expandos or `cache` is not a window per isWindow (#10080)
3873 /* jshint eqeqeq: false */
3874 } else if ( support.deleteExpando || cache != cache.window ) {
3875 /* jshint eqeqeq: true */
3876 delete cache[ id ];
3877
3878 // When all else fails, null
3879 } else {
3880 cache[ id ] = null;
3881 }
3882}
3883
3884jQuery.extend({
3885 cache: {},
3886
3887 // The following elements (space-suffixed to avoid Object.prototype collisions)
3888 // throw uncatchable exceptions if you attempt to set expando properties
3889 noData: {
3890 "applet ": true,
3891 "embed ": true,
3892 // ...but Flash objects (which have this classid) *can* handle expandos
3893 "object ": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
3894 },
3895
3896 hasData: function( elem ) {
3897 elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
3898 return !!elem && !isEmptyDataObject( elem );
3899 },
3900
3901 data: function( elem, name, data ) {
3902 return internalData( elem, name, data );
3903 },
3904
3905 removeData: function( elem, name ) {
3906 return internalRemoveData( elem, name );
3907 },
3908
3909 // For internal use only.
3910 _data: function( elem, name, data ) {
3911 return internalData( elem, name, data, true );
3912 },
3913
3914 _removeData: function( elem, name ) {
3915 return internalRemoveData( elem, name, true );
3916 }
3917});
3918
3919jQuery.fn.extend({
3920 data: function( key, value ) {
3921 var i, name, data,
3922 elem = this[0],
3923 attrs = elem && elem.attributes;
3924
3925 // Special expections of .data basically thwart jQuery.access,
3926 // so implement the relevant behavior ourselves
3927
3928 // Gets all values
3929 if ( key === undefined ) {
3930 if ( this.length ) {
3931 data = jQuery.data( elem );
3932
3933 if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) {
3934 i = attrs.length;
3935 while ( i-- ) {
3936
3937 // Support: IE11+
3938 // The attrs elements can be null (#14894)
3939 if ( attrs[ i ] ) {
3940 name = attrs[ i ].name;
3941 if ( name.indexOf( "data-" ) === 0 ) {
3942 name = jQuery.camelCase( name.slice(5) );
3943 dataAttr( elem, name, data[ name ] );
3944 }
3945 }
3946 }
3947 jQuery._data( elem, "parsedAttrs", true );
3948 }
3949 }
3950
3951 return data;
3952 }
3953
3954 // Sets multiple values
3955 if ( typeof key === "object" ) {
3956 return this.each(function() {
3957 jQuery.data( this, key );
3958 });
3959 }
3960
3961 return arguments.length > 1 ?
3962
3963 // Sets one value
3964 this.each(function() {
3965 jQuery.data( this, key, value );
3966 }) :
3967
3968 // Gets one value
3969 // Try to fetch any internally stored data first
3970 elem ? dataAttr( elem, key, jQuery.data( elem, key ) ) : undefined;
3971 },
3972
3973 removeData: function( key ) {
3974 return this.each(function() {
3975 jQuery.removeData( this, key );
3976 });
3977 }
3978});
3979
3980
3981jQuery.extend({
3982 queue: function( elem, type, data ) {
3983 var queue;
3984
3985 if ( elem ) {
3986 type = ( type || "fx" ) + "queue";
3987 queue = jQuery._data( elem, type );
3988
3989 // Speed up dequeue by getting out quickly if this is just a lookup
3990 if ( data ) {
3991 if ( !queue || jQuery.isArray(data) ) {
3992 queue = jQuery._data( elem, type, jQuery.makeArray(data) );
3993 } else {
3994 queue.push( data );
3995 }
3996 }
3997 return queue || [];
3998 }
3999 },
4000
4001 dequeue: function( elem, type ) {
4002 type = type || "fx";
4003
4004 var queue = jQuery.queue( elem, type ),
4005 startLength = queue.length,
4006 fn = queue.shift(),
4007 hooks = jQuery._queueHooks( elem, type ),
4008 next = function() {
4009 jQuery.dequeue( elem, type );
4010 };
4011
4012 // If the fx queue is dequeued, always remove the progress sentinel
4013 if ( fn === "inprogress" ) {
4014 fn = queue.shift();
4015 startLength--;
4016 }
4017
4018 if ( fn ) {
4019
4020 // Add a progress sentinel to prevent the fx queue from being
4021 // automatically dequeued
4022 if ( type === "fx" ) {
4023 queue.unshift( "inprogress" );
4024 }
4025
4026 // clear up the last queue stop function
4027 delete hooks.stop;
4028 fn.call( elem, next, hooks );
4029 }
4030
4031 if ( !startLength && hooks ) {
4032 hooks.empty.fire();
4033 }
4034 },
4035
4036 // not intended for public consumption - generates a queueHooks object, or returns the current one
4037 _queueHooks: function( elem, type ) {
4038 var key = type + "queueHooks";
4039 return jQuery._data( elem, key ) || jQuery._data( elem, key, {
4040 empty: jQuery.Callbacks("once memory").add(function() {
4041 jQuery._removeData( elem, type + "queue" );
4042 jQuery._removeData( elem, key );
4043 })
4044 });
4045 }
4046});
4047
4048jQuery.fn.extend({
4049 queue: function( type, data ) {
4050 var setter = 2;
4051
4052 if ( typeof type !== "string" ) {
4053 data = type;
4054 type = "fx";
4055 setter--;
4056 }
4057
4058 if ( arguments.length < setter ) {
4059 return jQuery.queue( this[0], type );
4060 }
4061
4062 return data === undefined ?
4063 this :
4064 this.each(function() {
4065 var queue = jQuery.queue( this, type, data );
4066
4067 // ensure a hooks for this queue
4068 jQuery._queueHooks( this, type );
4069
4070 if ( type === "fx" && queue[0] !== "inprogress" ) {
4071 jQuery.dequeue( this, type );
4072 }
4073 });
4074 },
4075 dequeue: function( type ) {
4076 return this.each(function() {
4077 jQuery.dequeue( this, type );
4078 });
4079 },
4080 clearQueue: function( type ) {
4081 return this.queue( type || "fx", [] );
4082 },
4083 // Get a promise resolved when queues of a certain type
4084 // are emptied (fx is the type by default)
4085 promise: function( type, obj ) {
4086 var tmp,
4087 count = 1,
4088 defer = jQuery.Deferred(),
4089 elements = this,
4090 i = this.length,
4091 resolve = function() {
4092 if ( !( --count ) ) {
4093 defer.resolveWith( elements, [ elements ] );
4094 }
4095 };
4096
4097 if ( typeof type !== "string" ) {
4098 obj = type;
4099 type = undefined;
4100 }
4101 type = type || "fx";
4102
4103 while ( i-- ) {
4104 tmp = jQuery._data( elements[ i ], type + "queueHooks" );
4105 if ( tmp && tmp.empty ) {
4106 count++;
4107 tmp.empty.add( resolve );
4108 }
4109 }
4110 resolve();
4111 return defer.promise( obj );
4112 }
4113});
4114var pnum = (/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/).source;
4115
4116var cssExpand = [ "Top", "Right", "Bottom", "Left" ];
4117
4118var isHidden = function( elem, el ) {
4119 // isHidden might be called from jQuery#filter function;
4120 // in that case, element will be second argument
4121 elem = el || elem;
4122 return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem );
4123 };
4124
4125
4126
4127// Multifunctional method to get and set values of a collection
4128// The value/s can optionally be executed if it's a function
4129var access = jQuery.access = function( elems, fn, key, value, chainable, emptyGet, raw ) {
4130 var i = 0,
4131 length = elems.length,
4132 bulk = key == null;
4133
4134 // Sets many values
4135 if ( jQuery.type( key ) === "object" ) {
4136 chainable = true;
4137 for ( i in key ) {
4138 jQuery.access( elems, fn, i, key[i], true, emptyGet, raw );
4139 }
4140
4141 // Sets one value
4142 } else if ( value !== undefined ) {
4143 chainable = true;
4144
4145 if ( !jQuery.isFunction( value ) ) {
4146 raw = true;
4147 }
4148
4149 if ( bulk ) {
4150 // Bulk operations run against the entire set
4151 if ( raw ) {
4152 fn.call( elems, value );
4153 fn = null;
4154
4155 // ...except when executing function values
4156 } else {
4157 bulk = fn;
4158 fn = function( elem, key, value ) {
4159 return bulk.call( jQuery( elem ), value );
4160 };
4161 }
4162 }
4163
4164 if ( fn ) {
4165 for ( ; i < length; i++ ) {
4166 fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) );
4167 }
4168 }
4169 }
4170
4171 return chainable ?
4172 elems :
4173
4174 // Gets
4175 bulk ?
4176 fn.call( elems ) :
4177 length ? fn( elems[0], key ) : emptyGet;
4178};
4179var rcheckableType = (/^(?:checkbox|radio)$/i);
4180
4181
4182
4183(function() {
4184 // Minified: var a,b,c
4185 var input = document.createElement( "input" ),
4186 div = document.createElement( "div" ),
4187 fragment = document.createDocumentFragment();
4188
4189 // Setup
4190 div.innerHTML = " <link/><table></table><a href='/a'>a</a><input type='checkbox'/>";
4191
4192 // IE strips leading whitespace when .innerHTML is used
4193 support.leadingWhitespace = div.firstChild.nodeType === 3;
4194
4195 // Make sure that tbody elements aren't automatically inserted
4196 // IE will insert them into empty tables
4197 support.tbody = !div.getElementsByTagName( "tbody" ).length;
4198
4199 // Make sure that link elements get serialized correctly by innerHTML
4200 // This requires a wrapper element in IE
4201 support.htmlSerialize = !!div.getElementsByTagName( "link" ).length;
4202
4203 // Makes sure cloning an html5 element does not cause problems
4204 // Where outerHTML is undefined, this still works
4205 support.html5Clone =
4206 document.createElement( "nav" ).cloneNode( true ).outerHTML !== "<:nav></:nav>";
4207
4208 // Check if a disconnected checkbox will retain its checked
4209 // value of true after appended to the DOM (IE6/7)
4210 input.type = "checkbox";
4211 input.checked = true;
4212 fragment.appendChild( input );
4213 support.appendChecked = input.checked;
4214
4215 // Make sure textarea (and checkbox) defaultValue is properly cloned
4216 // Support: IE6-IE11+
4217 div.innerHTML = "<textarea>x</textarea>";
4218 support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;
4219
4220 // #11217 - WebKit loses check when the name is after the checked attribute
4221 fragment.appendChild( div );
4222 div.innerHTML = "<input type='radio' checked='checked' name='t'/>";
4223
4224 // Support: Safari 5.1, iOS 5.1, Android 4.x, Android 2.3
4225 // old WebKit doesn't clone checked state correctly in fragments
4226 support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked;
4227
4228 // Support: IE<9
4229 // Opera does not clone events (and typeof div.attachEvent === undefined).
4230 // IE9-10 clones events bound via attachEvent, but they don't trigger with .click()
4231 support.noCloneEvent = true;
4232 if ( div.attachEvent ) {
4233 div.attachEvent( "onclick", function() {
4234 support.noCloneEvent = false;
4235 });
4236
4237 div.cloneNode( true ).click();
4238 }
4239
4240 // Execute the test only if not already executed in another module.
4241 if (support.deleteExpando == null) {
4242 // Support: IE<9
4243 support.deleteExpando = true;
4244 try {
4245 delete div.test;
4246 } catch( e ) {
4247 support.deleteExpando = false;
4248 }
4249 }
4250})();
4251
4252
4253(function() {
4254 var i, eventName,
4255 div = document.createElement( "div" );
4256
4257 // Support: IE<9 (lack submit/change bubble), Firefox 23+ (lack focusin event)
4258 for ( i in { submit: true, change: true, focusin: true }) {
4259 eventName = "on" + i;
4260
4261 if ( !(support[ i + "Bubbles" ] = eventName in window) ) {
4262 // Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP)
4263 div.setAttribute( eventName, "t" );
4264 support[ i + "Bubbles" ] = div.attributes[ eventName ].expando === false;
4265 }
4266 }
4267
4268 // Null elements to avoid leaks in IE.
4269 div = null;
4270})();
4271
4272
4273var rformElems = /^(?:input|select|textarea)$/i,
4274 rkeyEvent = /^key/,
4275 rmouseEvent = /^(?:mouse|pointer|contextmenu)|click/,
4276 rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
4277 rtypenamespace = /^([^.]*)(?:\.(.+)|)$/;
4278
4279function returnTrue() {
4280 return true;
4281}
4282
4283function returnFalse() {
4284 return false;
4285}
4286
4287function safeActiveElement() {
4288 try {
4289 return document.activeElement;
4290 } catch ( err ) { }
4291}
4292
4293/*
4294 * Helper functions for managing events -- not part of the public interface.
4295 * Props to Dean Edwards' addEvent library for many of the ideas.
4296 */
4297jQuery.event = {
4298
4299 global: {},
4300
4301 add: function( elem, types, handler, data, selector ) {
4302 var tmp, events, t, handleObjIn,
4303 special, eventHandle, handleObj,
4304 handlers, type, namespaces, origType,
4305 elemData = jQuery._data( elem );
4306
4307 // Don't attach events to noData or text/comment nodes (but allow plain objects)
4308 if ( !elemData ) {
4309 return;
4310 }
4311
4312 // Caller can pass in an object of custom data in lieu of the handler
4313 if ( handler.handler ) {
4314 handleObjIn = handler;
4315 handler = handleObjIn.handler;
4316 selector = handleObjIn.selector;
4317 }
4318
4319 // Make sure that the handler has a unique ID, used to find/remove it later
4320 if ( !handler.guid ) {
4321 handler.guid = jQuery.guid++;
4322 }
4323
4324 // Init the element's event structure and main handler, if this is the first
4325 if ( !(events = elemData.events) ) {
4326 events = elemData.events = {};
4327 }
4328 if ( !(eventHandle = elemData.handle) ) {
4329 eventHandle = elemData.handle = function( e ) {
4330 // Discard the second event of a jQuery.event.trigger() and
4331 // when an event is called after a page has unloaded
4332 return typeof jQuery !== strundefined && (!e || jQuery.event.triggered !== e.type) ?
4333 jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :
4334 undefined;
4335 };
4336 // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events
4337 eventHandle.elem = elem;
4338 }
4339
4340 // Handle multiple events separated by a space
4341 types = ( types || "" ).match( rnotwhite ) || [ "" ];
4342 t = types.length;
4343 while ( t-- ) {
4344 tmp = rtypenamespace.exec( types[t] ) || [];
4345 type = origType = tmp[1];
4346 namespaces = ( tmp[2] || "" ).split( "." ).sort();
4347
4348 // There *must* be a type, no attaching namespace-only handlers
4349 if ( !type ) {
4350 continue;
4351 }
4352
4353 // If event changes its type, use the special event handlers for the changed type
4354 special = jQuery.event.special[ type ] || {};
4355
4356 // If selector defined, determine special event api type, otherwise given type
4357 type = ( selector ? special.delegateType : special.bindType ) || type;
4358
4359 // Update special based on newly reset type
4360 special = jQuery.event.special[ type ] || {};
4361
4362 // handleObj is passed to all event handlers
4363 handleObj = jQuery.extend({
4364 type: type,
4365 origType: origType,
4366 data: data,
4367 handler: handler,
4368 guid: handler.guid,
4369 selector: selector,
4370 needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
4371 namespace: namespaces.join(".")
4372 }, handleObjIn );
4373
4374 // Init the event handler queue if we're the first
4375 if ( !(handlers = events[ type ]) ) {
4376 handlers = events[ type ] = [];
4377 handlers.delegateCount = 0;
4378
4379 // Only use addEventListener/attachEvent if the special events handler returns false
4380 if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
4381 // Bind the global event handler to the element
4382 if ( elem.addEventListener ) {
4383 elem.addEventListener( type, eventHandle, false );
4384
4385 } else if ( elem.attachEvent ) {
4386 elem.attachEvent( "on" + type, eventHandle );
4387 }
4388 }
4389 }
4390
4391 if ( special.add ) {
4392 special.add.call( elem, handleObj );
4393
4394 if ( !handleObj.handler.guid ) {
4395 handleObj.handler.guid = handler.guid;
4396 }
4397 }
4398
4399 // Add to the element's handler list, delegates in front
4400 if ( selector ) {
4401 handlers.splice( handlers.delegateCount++, 0, handleObj );
4402 } else {
4403 handlers.push( handleObj );
4404 }
4405
4406 // Keep track of which events have ever been used, for event optimization
4407 jQuery.event.global[ type ] = true;
4408 }
4409
4410 // Nullify elem to prevent memory leaks in IE
4411 elem = null;
4412 },
4413
4414 // Detach an event or set of events from an element
4415 remove: function( elem, types, handler, selector, mappedTypes ) {
4416 var j, handleObj, tmp,
4417 origCount, t, events,
4418 special, handlers, type,
4419 namespaces, origType,
4420 elemData = jQuery.hasData( elem ) && jQuery._data( elem );
4421
4422 if ( !elemData || !(events = elemData.events) ) {
4423 return;
4424 }
4425
4426 // Once for each type.namespace in types; type may be omitted
4427 types = ( types || "" ).match( rnotwhite ) || [ "" ];
4428 t = types.length;
4429 while ( t-- ) {
4430 tmp = rtypenamespace.exec( types[t] ) || [];
4431 type = origType = tmp[1];
4432 namespaces = ( tmp[2] || "" ).split( "." ).sort();
4433
4434 // Unbind all events (on this namespace, if provided) for the element
4435 if ( !type ) {
4436 for ( type in events ) {
4437 jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
4438 }
4439 continue;
4440 }
4441
4442 special = jQuery.event.special[ type ] || {};
4443 type = ( selector ? special.delegateType : special.bindType ) || type;
4444 handlers = events[ type ] || [];
4445 tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" );
4446
4447 // Remove matching events
4448 origCount = j = handlers.length;
4449 while ( j-- ) {
4450 handleObj = handlers[ j ];
4451
4452 if ( ( mappedTypes || origType === handleObj.origType ) &&
4453 ( !handler || handler.guid === handleObj.guid ) &&
4454 ( !tmp || tmp.test( handleObj.namespace ) ) &&
4455 ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) {
4456 handlers.splice( j, 1 );
4457
4458 if ( handleObj.selector ) {
4459 handlers.delegateCount--;
4460 }
4461 if ( special.remove ) {
4462 special.remove.call( elem, handleObj );
4463 }
4464 }
4465 }
4466
4467 // Remove generic event handler if we removed something and no more handlers exist
4468 // (avoids potential for endless recursion during removal of special event handlers)
4469 if ( origCount && !handlers.length ) {
4470 if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
4471 jQuery.removeEvent( elem, type, elemData.handle );
4472 }
4473
4474 delete events[ type ];
4475 }
4476 }
4477
4478 // Remove the expando if it's no longer used
4479 if ( jQuery.isEmptyObject( events ) ) {
4480 delete elemData.handle;
4481
4482 // removeData also checks for emptiness and clears the expando if empty
4483 // so use it instead of delete
4484 jQuery._removeData( elem, "events" );
4485 }
4486 },
4487
4488 trigger: function( event, data, elem, onlyHandlers ) {
4489 var handle, ontype, cur,
4490 bubbleType, special, tmp, i,
4491 eventPath = [ elem || document ],
4492 type = hasOwn.call( event, "type" ) ? event.type : event,
4493 namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : [];
4494
4495 cur = tmp = elem = elem || document;
4496
4497 // Don't do events on text and comment nodes
4498 if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
4499 return;
4500 }
4501
4502 // focus/blur morphs to focusin/out; ensure we're not firing them right now
4503 if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
4504 return;
4505 }
4506
4507 if ( type.indexOf(".") >= 0 ) {
4508 // Namespaced trigger; create a regexp to match event type in handle()
4509 namespaces = type.split(".");
4510 type = namespaces.shift();
4511 namespaces.sort();
4512 }
4513 ontype = type.indexOf(":") < 0 && "on" + type;
4514
4515 // Caller can pass in a jQuery.Event object, Object, or just an event type string
4516 event = event[ jQuery.expando ] ?
4517 event :
4518 new jQuery.Event( type, typeof event === "object" && event );
4519
4520 // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)
4521 event.isTrigger = onlyHandlers ? 2 : 3;
4522 event.namespace = namespaces.join(".");
4523 event.namespace_re = event.namespace ?
4524 new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) :
4525 null;
4526
4527 // Clean up the event in case it is being reused
4528 event.result = undefined;
4529 if ( !event.target ) {
4530 event.target = elem;
4531 }
4532
4533 // Clone any incoming data and prepend the event, creating the handler arg list
4534 data = data == null ?
4535 [ event ] :
4536 jQuery.makeArray( data, [ event ] );
4537
4538 // Allow special events to draw outside the lines
4539 special = jQuery.event.special[ type ] || {};
4540 if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {
4541 return;
4542 }
4543
4544 // Determine event propagation path in advance, per W3C events spec (#9951)
4545 // Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
4546 if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {
4547
4548 bubbleType = special.delegateType || type;
4549 if ( !rfocusMorph.test( bubbleType + type ) ) {
4550 cur = cur.parentNode;
4551 }
4552 for ( ; cur; cur = cur.parentNode ) {
4553 eventPath.push( cur );
4554 tmp = cur;
4555 }
4556
4557 // Only add window if we got to document (e.g., not plain obj or detached DOM)
4558 if ( tmp === (elem.ownerDocument || document) ) {
4559 eventPath.push( tmp.defaultView || tmp.parentWindow || window );
4560 }
4561 }
4562
4563 // Fire handlers on the event path
4564 i = 0;
4565 while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) {
4566
4567 event.type = i > 1 ?
4568 bubbleType :
4569 special.bindType || type;
4570
4571 // jQuery handler
4572 handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" );
4573 if ( handle ) {
4574 handle.apply( cur, data );
4575 }
4576
4577 // Native handler
4578 handle = ontype && cur[ ontype ];
4579 if ( handle && handle.apply && jQuery.acceptData( cur ) ) {
4580 event.result = handle.apply( cur, data );
4581 if ( event.result === false ) {
4582 event.preventDefault();
4583 }
4584 }
4585 }
4586 event.type = type;
4587
4588 // If nobody prevented the default action, do it now
4589 if ( !onlyHandlers && !event.isDefaultPrevented() ) {
4590
4591 if ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) &&
4592 jQuery.acceptData( elem ) ) {
4593
4594 // Call a native DOM method on the target with the same name name as the event.
4595 // Can't use an .isFunction() check here because IE6/7 fails that test.
4596 // Don't do default actions on window, that's where global variables be (#6170)
4597 if ( ontype && elem[ type ] && !jQuery.isWindow( elem ) ) {
4598
4599 // Don't re-trigger an onFOO event when we call its FOO() method
4600 tmp = elem[ ontype ];
4601
4602 if ( tmp ) {
4603 elem[ ontype ] = null;
4604 }
4605
4606 // Prevent re-triggering of the same event, since we already bubbled it above
4607 jQuery.event.triggered = type;
4608 try {
4609 elem[ type ]();
4610 } catch ( e ) {
4611 // IE<9 dies on focus/blur to hidden element (#1486,#12518)
4612 // only reproducible on winXP IE8 native, not IE9 in IE8 mode
4613 }
4614 jQuery.event.triggered = undefined;
4615
4616 if ( tmp ) {
4617 elem[ ontype ] = tmp;
4618 }
4619 }
4620 }
4621 }
4622
4623 return event.result;
4624 },
4625
4626 dispatch: function( event ) {
4627
4628 // Make a writable jQuery.Event from the native event object
4629 event = jQuery.event.fix( event );
4630
4631 var i, ret, handleObj, matched, j,
4632 handlerQueue = [],
4633 args = slice.call( arguments ),
4634 handlers = ( jQuery._data( this, "events" ) || {} )[ event.type ] || [],
4635 special = jQuery.event.special[ event.type ] || {};
4636
4637 // Use the fix-ed jQuery.Event rather than the (read-only) native event
4638 args[0] = event;
4639 event.delegateTarget = this;
4640
4641 // Call the preDispatch hook for the mapped type, and let it bail if desired
4642 if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
4643 return;
4644 }
4645
4646 // Determine handlers
4647 handlerQueue = jQuery.event.handlers.call( this, event, handlers );
4648
4649 // Run delegates first; they may want to stop propagation beneath us
4650 i = 0;
4651 while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) {
4652 event.currentTarget = matched.elem;
4653
4654 j = 0;
4655 while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) {
4656
4657 // Triggered event must either 1) have no namespace, or
4658 // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).
4659 if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) {
4660
4661 event.handleObj = handleObj;
4662 event.data = handleObj.data;
4663
4664 ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )
4665 .apply( matched.elem, args );
4666
4667 if ( ret !== undefined ) {
4668 if ( (event.result = ret) === false ) {
4669 event.preventDefault();
4670 event.stopPropagation();
4671 }
4672 }
4673 }
4674 }
4675 }
4676
4677 // Call the postDispatch hook for the mapped type
4678 if ( special.postDispatch ) {
4679 special.postDispatch.call( this, event );
4680 }
4681
4682 return event.result;
4683 },
4684
4685 handlers: function( event, handlers ) {
4686 var sel, handleObj, matches, i,
4687 handlerQueue = [],
4688 delegateCount = handlers.delegateCount,
4689 cur = event.target;
4690
4691 // Find delegate handlers
4692 // Black-hole SVG <use> instance trees (#13180)
4693 // Avoid non-left-click bubbling in Firefox (#3861)
4694 if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) {
4695
4696 /* jshint eqeqeq: false */
4697 for ( ; cur != this; cur = cur.parentNode || this ) {
4698 /* jshint eqeqeq: true */
4699
4700 // Don't check non-elements (#13208)
4701 // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)
4702 if ( cur.nodeType === 1 && (cur.disabled !== true || event.type !== "click") ) {
4703 matches = [];
4704 for ( i = 0; i < delegateCount; i++ ) {
4705 handleObj = handlers[ i ];
4706
4707 // Don't conflict with Object.prototype properties (#13203)
4708 sel = handleObj.selector + " ";
4709
4710 if ( matches[ sel ] === undefined ) {
4711 matches[ sel ] = handleObj.needsContext ?
4712 jQuery( sel, this ).index( cur ) >= 0 :
4713 jQuery.find( sel, this, null, [ cur ] ).length;
4714 }
4715 if ( matches[ sel ] ) {
4716 matches.push( handleObj );
4717 }
4718 }
4719 if ( matches.length ) {
4720 handlerQueue.push({ elem: cur, handlers: matches });
4721 }
4722 }
4723 }
4724 }
4725
4726 // Add the remaining (directly-bound) handlers
4727 if ( delegateCount < handlers.length ) {
4728 handlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) });
4729 }
4730
4731 return handlerQueue;
4732 },
4733
4734 fix: function( event ) {
4735 if ( event[ jQuery.expando ] ) {
4736 return event;
4737 }
4738
4739 // Create a writable copy of the event object and normalize some properties
4740 var i, prop, copy,
4741 type = event.type,
4742 originalEvent = event,
4743 fixHook = this.fixHooks[ type ];
4744
4745 if ( !fixHook ) {
4746 this.fixHooks[ type ] = fixHook =
4747 rmouseEvent.test( type ) ? this.mouseHooks :
4748 rkeyEvent.test( type ) ? this.keyHooks :
4749 {};
4750 }
4751 copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;
4752
4753 event = new jQuery.Event( originalEvent );
4754
4755 i = copy.length;
4756 while ( i-- ) {
4757 prop = copy[ i ];
4758 event[ prop ] = originalEvent[ prop ];
4759 }
4760
4761 // Support: IE<9
4762 // Fix target property (#1925)
4763 if ( !event.target ) {
4764 event.target = originalEvent.srcElement || document;
4765 }
4766
4767 // Support: Chrome 23+, Safari?
4768 // Target should not be a text node (#504, #13143)
4769 if ( event.target.nodeType === 3 ) {
4770 event.target = event.target.parentNode;
4771 }
4772
4773 // Support: IE<9
4774 // For mouse/key events, metaKey==false if it's undefined (#3368, #11328)
4775 event.metaKey = !!event.metaKey;
4776
4777 return fixHook.filter ? fixHook.filter( event, originalEvent ) : event;
4778 },
4779
4780 // Includes some event props shared by KeyEvent and MouseEvent
4781 props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),
4782
4783 fixHooks: {},
4784
4785 keyHooks: {
4786 props: "char charCode key keyCode".split(" "),
4787 filter: function( event, original ) {
4788
4789 // Add which for key events
4790 if ( event.which == null ) {
4791 event.which = original.charCode != null ? original.charCode : original.keyCode;
4792 }
4793
4794 return event;
4795 }
4796 },
4797
4798 mouseHooks: {
4799 props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),
4800 filter: function( event, original ) {
4801 var body, eventDoc, doc,
4802 button = original.button,
4803 fromElement = original.fromElement;
4804
4805 // Calculate pageX/Y if missing and clientX/Y available
4806 if ( event.pageX == null && original.clientX != null ) {
4807 eventDoc = event.target.ownerDocument || document;
4808 doc = eventDoc.documentElement;
4809 body = eventDoc.body;
4810
4811 event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );
4812 event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 );
4813 }
4814
4815 // Add relatedTarget, if necessary
4816 if ( !event.relatedTarget && fromElement ) {
4817 event.relatedTarget = fromElement === event.target ? original.toElement : fromElement;
4818 }
4819
4820 // Add which for click: 1 === left; 2 === middle; 3 === right
4821 // Note: button is not normalized, so don't use it
4822 if ( !event.which && button !== undefined ) {
4823 event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
4824 }
4825
4826 return event;
4827 }
4828 },
4829
4830 special: {
4831 load: {
4832 // Prevent triggered image.load events from bubbling to window.load
4833 noBubble: true
4834 },
4835 focus: {
4836 // Fire native event if possible so blur/focus sequence is correct
4837 trigger: function() {
4838 if ( this !== safeActiveElement() && this.focus ) {
4839 try {
4840 this.focus();
4841 return false;
4842 } catch ( e ) {
4843 // Support: IE<9
4844 // If we error on focus to hidden element (#1486, #12518),
4845 // let .trigger() run the handlers
4846 }
4847 }
4848 },
4849 delegateType: "focusin"
4850 },
4851 blur: {
4852 trigger: function() {
4853 if ( this === safeActiveElement() && this.blur ) {
4854 this.blur();
4855 return false;
4856 }
4857 },
4858 delegateType: "focusout"
4859 },
4860 click: {
4861 // For checkbox, fire native event so checked state will be right
4862 trigger: function() {
4863 if ( jQuery.nodeName( this, "input" ) && this.type === "checkbox" && this.click ) {
4864 this.click();
4865 return false;
4866 }
4867 },
4868
4869 // For cross-browser consistency, don't fire native .click() on links
4870 _default: function( event ) {
4871 return jQuery.nodeName( event.target, "a" );
4872 }
4873 },
4874
4875 beforeunload: {
4876 postDispatch: function( event ) {
4877
4878 // Support: Firefox 20+
4879 // Firefox doesn't alert if the returnValue field is not set.
4880 if ( event.result !== undefined && event.originalEvent ) {
4881 event.originalEvent.returnValue = event.result;
4882 }
4883 }
4884 }
4885 },
4886
4887 simulate: function( type, elem, event, bubble ) {
4888 // Piggyback on a donor event to simulate a different one.
4889 // Fake originalEvent to avoid donor's stopPropagation, but if the
4890 // simulated event prevents default then we do the same on the donor.
4891 var e = jQuery.extend(
4892 new jQuery.Event(),
4893 event,
4894 {
4895 type: type,
4896 isSimulated: true,
4897 originalEvent: {}
4898 }
4899 );
4900 if ( bubble ) {
4901 jQuery.event.trigger( e, null, elem );
4902 } else {
4903 jQuery.event.dispatch.call( elem, e );
4904 }
4905 if ( e.isDefaultPrevented() ) {
4906 event.preventDefault();
4907 }
4908 }
4909};
4910
4911jQuery.removeEvent = document.removeEventListener ?
4912 function( elem, type, handle ) {
4913 if ( elem.removeEventListener ) {
4914 elem.removeEventListener( type, handle, false );
4915 }
4916 } :
4917 function( elem, type, handle ) {
4918 var name = "on" + type;
4919
4920 if ( elem.detachEvent ) {
4921
4922 // #8545, #7054, preventing memory leaks for custom events in IE6-8
4923 // detachEvent needed property on element, by name of that event, to properly expose it to GC
4924 if ( typeof elem[ name ] === strundefined ) {
4925 elem[ name ] = null;
4926 }
4927
4928 elem.detachEvent( name, handle );
4929 }
4930 };
4931
4932jQuery.Event = function( src, props ) {
4933 // Allow instantiation without the 'new' keyword
4934 if ( !(this instanceof jQuery.Event) ) {
4935 return new jQuery.Event( src, props );
4936 }
4937
4938 // Event object
4939 if ( src && src.type ) {
4940 this.originalEvent = src;
4941 this.type = src.type;
4942
4943 // Events bubbling up the document may have been marked as prevented
4944 // by a handler lower down the tree; reflect the correct value.
4945 this.isDefaultPrevented = src.defaultPrevented ||
4946 src.defaultPrevented === undefined &&
4947 // Support: IE < 9, Android < 4.0
4948 src.returnValue === false ?
4949 returnTrue :
4950 returnFalse;
4951
4952 // Event type
4953 } else {
4954 this.type = src;
4955 }
4956
4957 // Put explicitly provided properties onto the event object
4958 if ( props ) {
4959 jQuery.extend( this, props );
4960 }
4961
4962 // Create a timestamp if incoming event doesn't have one
4963 this.timeStamp = src && src.timeStamp || jQuery.now();
4964
4965 // Mark it as fixed
4966 this[ jQuery.expando ] = true;
4967};
4968
4969// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
4970// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
4971jQuery.Event.prototype = {
4972 isDefaultPrevented: returnFalse,
4973 isPropagationStopped: returnFalse,
4974 isImmediatePropagationStopped: returnFalse,
4975
4976 preventDefault: function() {
4977 var e = this.originalEvent;
4978
4979 this.isDefaultPrevented = returnTrue;
4980 if ( !e ) {
4981 return;
4982 }
4983
4984 // If preventDefault exists, run it on the original event
4985 if ( e.preventDefault ) {
4986 e.preventDefault();
4987
4988 // Support: IE
4989 // Otherwise set the returnValue property of the original event to false
4990 } else {
4991 e.returnValue = false;
4992 }
4993 },
4994 stopPropagation: function() {
4995 var e = this.originalEvent;
4996
4997 this.isPropagationStopped = returnTrue;
4998 if ( !e ) {
4999 return;
5000 }
5001 // If stopPropagation exists, run it on the original event
5002 if ( e.stopPropagation ) {
5003 e.stopPropagation();
5004 }
5005
5006 // Support: IE
5007 // Set the cancelBubble property of the original event to true
5008 e.cancelBubble = true;
5009 },
5010 stopImmediatePropagation: function() {
5011 var e = this.originalEvent;
5012
5013 this.isImmediatePropagationStopped = returnTrue;
5014
5015 if ( e && e.stopImmediatePropagation ) {
5016 e.stopImmediatePropagation();
5017 }
5018
5019 this.stopPropagation();
5020 }
5021};
5022
5023// Create mouseenter/leave events using mouseover/out and event-time checks
5024jQuery.each({
5025 mouseenter: "mouseover",
5026 mouseleave: "mouseout",
5027 pointerenter: "pointerover",
5028 pointerleave: "pointerout"
5029}, function( orig, fix ) {
5030 jQuery.event.special[ orig ] = {
5031 delegateType: fix,
5032 bindType: fix,
5033
5034 handle: function( event ) {
5035 var ret,
5036 target = this,
5037 related = event.relatedTarget,
5038 handleObj = event.handleObj;
5039
5040 // For mousenter/leave call the handler if related is outside the target.
5041 // NB: No relatedTarget if the mouse left/entered the browser window
5042 if ( !related || (related !== target && !jQuery.contains( target, related )) ) {
5043 event.type = handleObj.origType;
5044 ret = handleObj.handler.apply( this, arguments );
5045 event.type = fix;
5046 }
5047 return ret;
5048 }
5049 };
5050});
5051
5052// IE submit delegation
5053if ( !support.submitBubbles ) {
5054
5055 jQuery.event.special.submit = {
5056 setup: function() {
5057 // Only need this for delegated form submit events
5058 if ( jQuery.nodeName( this, "form" ) ) {
5059 return false;
5060 }
5061
5062 // Lazy-add a submit handler when a descendant form may potentially be submitted
5063 jQuery.event.add( this, "click._submit keypress._submit", function( e ) {
5064 // Node name check avoids a VML-related crash in IE (#9807)
5065 var elem = e.target,
5066 form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined;
5067 if ( form && !jQuery._data( form, "submitBubbles" ) ) {
5068 jQuery.event.add( form, "submit._submit", function( event ) {
5069 event._submit_bubble = true;
5070 });
5071 jQuery._data( form, "submitBubbles", true );
5072 }
5073 });
5074 // return undefined since we don't need an event listener
5075 },
5076
5077 postDispatch: function( event ) {
5078 // If form was submitted by the user, bubble the event up the tree
5079 if ( event._submit_bubble ) {
5080 delete event._submit_bubble;
5081 if ( this.parentNode && !event.isTrigger ) {
5082 jQuery.event.simulate( "submit", this.parentNode, event, true );
5083 }
5084 }
5085 },
5086
5087 teardown: function() {
5088 // Only need this for delegated form submit events
5089 if ( jQuery.nodeName( this, "form" ) ) {
5090 return false;
5091 }
5092
5093 // Remove delegated handlers; cleanData eventually reaps submit handlers attached above
5094 jQuery.event.remove( this, "._submit" );
5095 }
5096 };
5097}
5098
5099// IE change delegation and checkbox/radio fix
5100if ( !support.changeBubbles ) {
5101
5102 jQuery.event.special.change = {
5103
5104 setup: function() {
5105
5106 if ( rformElems.test( this.nodeName ) ) {
5107 // IE doesn't fire change on a check/radio until blur; trigger it on click
5108 // after a propertychange. Eat the blur-change in special.change.handle.
5109 // This still fires onchange a second time for check/radio after blur.
5110 if ( this.type === "checkbox" || this.type === "radio" ) {
5111 jQuery.event.add( this, "propertychange._change", function( event ) {
5112 if ( event.originalEvent.propertyName === "checked" ) {
5113 this._just_changed = true;
5114 }
5115 });
5116 jQuery.event.add( this, "click._change", function( event ) {
5117 if ( this._just_changed && !event.isTrigger ) {
5118 this._just_changed = false;
5119 }
5120 // Allow triggered, simulated change events (#11500)
5121 jQuery.event.simulate( "change", this, event, true );
5122 });
5123 }
5124 return false;
5125 }
5126 // Delegated event; lazy-add a change handler on descendant inputs
5127 jQuery.event.add( this, "beforeactivate._change", function( e ) {
5128 var elem = e.target;
5129
5130 if ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, "changeBubbles" ) ) {
5131 jQuery.event.add( elem, "change._change", function( event ) {
5132 if ( this.parentNode && !event.isSimulated && !event.isTrigger ) {
5133 jQuery.event.simulate( "change", this.parentNode, event, true );
5134 }
5135 });
5136 jQuery._data( elem, "changeBubbles", true );
5137 }
5138 });
5139 },
5140
5141 handle: function( event ) {
5142 var elem = event.target;
5143
5144 // Swallow native change events from checkbox/radio, we already triggered them above
5145 if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) {
5146 return event.handleObj.handler.apply( this, arguments );
5147 }
5148 },
5149
5150 teardown: function() {
5151 jQuery.event.remove( this, "._change" );
5152
5153 return !rformElems.test( this.nodeName );
5154 }
5155 };
5156}
5157
5158// Create "bubbling" focus and blur events
5159if ( !support.focusinBubbles ) {
5160 jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
5161
5162 // Attach a single capturing handler on the document while someone wants focusin/focusout
5163 var handler = function( event ) {
5164 jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );
5165 };
5166
5167 jQuery.event.special[ fix ] = {
5168 setup: function() {
5169 var doc = this.ownerDocument || this,
5170 attaches = jQuery._data( doc, fix );
5171
5172 if ( !attaches ) {
5173 doc.addEventListener( orig, handler, true );
5174 }
5175 jQuery._data( doc, fix, ( attaches || 0 ) + 1 );
5176 },
5177 teardown: function() {
5178 var doc = this.ownerDocument || this,
5179 attaches = jQuery._data( doc, fix ) - 1;
5180
5181 if ( !attaches ) {
5182 doc.removeEventListener( orig, handler, true );
5183 jQuery._removeData( doc, fix );
5184 } else {
5185 jQuery._data( doc, fix, attaches );
5186 }
5187 }
5188 };
5189 });
5190}
5191
5192jQuery.fn.extend({
5193
5194 on: function( types, selector, data, fn, /*INTERNAL*/ one ) {
5195 var type, origFn;
5196
5197 // Types can be a map of types/handlers
5198 if ( typeof types === "object" ) {
5199 // ( types-Object, selector, data )
5200 if ( typeof selector !== "string" ) {
5201 // ( types-Object, data )
5202 data = data || selector;
5203 selector = undefined;
5204 }
5205 for ( type in types ) {
5206 this.on( type, selector, data, types[ type ], one );
5207 }
5208 return this;
5209 }
5210
5211 if ( data == null && fn == null ) {
5212 // ( types, fn )
5213 fn = selector;
5214 data = selector = undefined;
5215 } else if ( fn == null ) {
5216 if ( typeof selector === "string" ) {
5217 // ( types, selector, fn )
5218 fn = data;
5219 data = undefined;
5220 } else {
5221 // ( types, data, fn )
5222 fn = data;
5223 data = selector;
5224 selector = undefined;
5225 }
5226 }
5227 if ( fn === false ) {
5228 fn = returnFalse;
5229 } else if ( !fn ) {
5230 return this;
5231 }
5232
5233 if ( one === 1 ) {
5234 origFn = fn;
5235 fn = function( event ) {
5236 // Can use an empty set, since event contains the info
5237 jQuery().off( event );
5238 return origFn.apply( this, arguments );
5239 };
5240 // Use same guid so caller can remove using origFn
5241 fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
5242 }
5243 return this.each( function() {
5244 jQuery.event.add( this, types, fn, data, selector );
5245 });
5246 },
5247 one: function( types, selector, data, fn ) {
5248 return this.on( types, selector, data, fn, 1 );
5249 },
5250 off: function( types, selector, fn ) {
5251 var handleObj, type;
5252 if ( types && types.preventDefault && types.handleObj ) {
5253 // ( event ) dispatched jQuery.Event
5254 handleObj = types.handleObj;
5255 jQuery( types.delegateTarget ).off(
5256 handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType,
5257 handleObj.selector,
5258 handleObj.handler
5259 );
5260 return this;
5261 }
5262 if ( typeof types === "object" ) {
5263 // ( types-object [, selector] )
5264 for ( type in types ) {
5265 this.off( type, selector, types[ type ] );
5266 }
5267 return this;
5268 }
5269 if ( selector === false || typeof selector === "function" ) {
5270 // ( types [, fn] )
5271 fn = selector;
5272 selector = undefined;
5273 }
5274 if ( fn === false ) {
5275 fn = returnFalse;
5276 }
5277 return this.each(function() {
5278 jQuery.event.remove( this, types, fn, selector );
5279 });
5280 },
5281
5282 trigger: function( type, data ) {
5283 return this.each(function() {
5284 jQuery.event.trigger( type, data, this );
5285 });
5286 },
5287 triggerHandler: function( type, data ) {
5288 var elem = this[0];
5289 if ( elem ) {
5290 return jQuery.event.trigger( type, data, elem, true );
5291 }
5292 }
5293});
5294
5295
5296function createSafeFragment( document ) {
5297 var list = nodeNames.split( "|" ),
5298 safeFrag = document.createDocumentFragment();
5299
5300 if ( safeFrag.createElement ) {
5301 while ( list.length ) {
5302 safeFrag.createElement(
5303 list.pop()
5304 );
5305 }
5306 }
5307 return safeFrag;
5308}
5309
5310var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" +
5311 "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",
5312 rinlinejQuery = / jQuery\d+="(?:null|\d+)"/g,
5313 rnoshimcache = new RegExp("<(?:" + nodeNames + ")[\\s/>]", "i"),
5314 rleadingWhitespace = /^\s+/,
5315 rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,
5316 rtagName = /<([\w:]+)/,
5317 rtbody = /<tbody/i,
5318 rhtml = /<|&#?\w+;/,
5319 rnoInnerhtml = /<(?:script|style|link)/i,
5320 // checked="checked" or checked
5321 rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
5322 rscriptType = /^$|\/(?:java|ecma)script/i,
5323 rscriptTypeMasked = /^true\/(.*)/,
5324 rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,
5325
5326 // We have to close these tags to support XHTML (#13200)
5327 wrapMap = {
5328 option: [ 1, "<select multiple='multiple'>", "</select>" ],
5329 legend: [ 1, "<fieldset>", "</fieldset>" ],
5330 area: [ 1, "<map>", "</map>" ],
5331 param: [ 1, "<object>", "</object>" ],
5332 thead: [ 1, "<table>", "</table>" ],
5333 tr: [ 2, "<table><tbody>", "</tbody></table>" ],
5334 col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ],
5335 td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
5336
5337 // IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags,
5338 // unless wrapped in a div with non-breaking characters in front of it.
5339 _default: support.htmlSerialize ? [ 0, "", "" ] : [ 1, "X<div>", "</div>" ]
5340 },
5341 safeFragment = createSafeFragment( document ),
5342 fragmentDiv = safeFragment.appendChild( document.createElement("div") );
5343
5344wrapMap.optgroup = wrapMap.option;
5345wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
5346wrapMap.th = wrapMap.td;
5347
5348function getAll( context, tag ) {
5349 var elems, elem,
5350 i = 0,
5351 found = typeof context.getElementsByTagName !== strundefined ? context.getElementsByTagName( tag || "*" ) :
5352 typeof context.querySelectorAll !== strundefined ? context.querySelectorAll( tag || "*" ) :
5353 undefined;
5354
5355 if ( !found ) {
5356 for ( found = [], elems = context.childNodes || context; (elem = elems[i]) != null; i++ ) {
5357 if ( !tag || jQuery.nodeName( elem, tag ) ) {
5358 found.push( elem );
5359 } else {
5360 jQuery.merge( found, getAll( elem, tag ) );
5361 }
5362 }
5363 }
5364
5365 return tag === undefined || tag && jQuery.nodeName( context, tag ) ?
5366 jQuery.merge( [ context ], found ) :
5367 found;
5368}
5369
5370// Used in buildFragment, fixes the defaultChecked property
5371function fixDefaultChecked( elem ) {
5372 if ( rcheckableType.test( elem.type ) ) {
5373 elem.defaultChecked = elem.checked;
5374 }
5375}
5376
5377// Support: IE<8
5378// Manipulating tables requires a tbody
5379function manipulationTarget( elem, content ) {
5380 return jQuery.nodeName( elem, "table" ) &&
5381 jQuery.nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ?
5382
5383 elem.getElementsByTagName("tbody")[0] ||
5384 elem.appendChild( elem.ownerDocument.createElement("tbody") ) :
5385 elem;
5386}
5387
5388// Replace/restore the type attribute of script elements for safe DOM manipulation
5389function disableScript( elem ) {
5390 elem.type = (jQuery.find.attr( elem, "type" ) !== null) + "/" + elem.type;
5391 return elem;
5392}
5393function restoreScript( elem ) {
5394 var match = rscriptTypeMasked.exec( elem.type );
5395 if ( match ) {
5396 elem.type = match[1];
5397 } else {
5398 elem.removeAttribute("type");
5399 }
5400 return elem;
5401}
5402
5403// Mark scripts as having already been evaluated
5404function setGlobalEval( elems, refElements ) {
5405 var elem,
5406 i = 0;
5407 for ( ; (elem = elems[i]) != null; i++ ) {
5408 jQuery._data( elem, "globalEval", !refElements || jQuery._data( refElements[i], "globalEval" ) );
5409 }
5410}
5411
5412function cloneCopyEvent( src, dest ) {
5413
5414 if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {
5415 return;
5416 }
5417
5418 var type, i, l,
5419 oldData = jQuery._data( src ),
5420 curData = jQuery._data( dest, oldData ),
5421 events = oldData.events;
5422
5423 if ( events ) {
5424 delete curData.handle;
5425 curData.events = {};
5426
5427 for ( type in events ) {
5428 for ( i = 0, l = events[ type ].length; i < l; i++ ) {
5429 jQuery.event.add( dest, type, events[ type ][ i ] );
5430 }
5431 }
5432 }
5433
5434 // make the cloned public data object a copy from the original
5435 if ( curData.data ) {
5436 curData.data = jQuery.extend( {}, curData.data );
5437 }
5438}
5439
5440function fixCloneNodeIssues( src, dest ) {
5441 var nodeName, e, data;
5442
5443 // We do not need to do anything for non-Elements
5444 if ( dest.nodeType !== 1 ) {
5445 return;
5446 }
5447
5448 nodeName = dest.nodeName.toLowerCase();
5449
5450 // IE6-8 copies events bound via attachEvent when using cloneNode.
5451 if ( !support.noCloneEvent && dest[ jQuery.expando ] ) {
5452 data = jQuery._data( dest );
5453
5454 for ( e in data.events ) {
5455 jQuery.removeEvent( dest, e, data.handle );
5456 }
5457
5458 // Event data gets referenced instead of copied if the expando gets copied too
5459 dest.removeAttribute( jQuery.expando );
5460 }
5461
5462 // IE blanks contents when cloning scripts, and tries to evaluate newly-set text
5463 if ( nodeName === "script" && dest.text !== src.text ) {
5464 disableScript( dest ).text = src.text;
5465 restoreScript( dest );
5466
5467 // IE6-10 improperly clones children of object elements using classid.
5468 // IE10 throws NoModificationAllowedError if parent is null, #12132.
5469 } else if ( nodeName === "object" ) {
5470 if ( dest.parentNode ) {
5471 dest.outerHTML = src.outerHTML;
5472 }
5473
5474 // This path appears unavoidable for IE9. When cloning an object
5475 // element in IE9, the outerHTML strategy above is not sufficient.
5476 // If the src has innerHTML and the destination does not,
5477 // copy the src.innerHTML into the dest.innerHTML. #10324
5478 if ( support.html5Clone && ( src.innerHTML && !jQuery.trim(dest.innerHTML) ) ) {
5479 dest.innerHTML = src.innerHTML;
5480 }
5481
5482 } else if ( nodeName === "input" && rcheckableType.test( src.type ) ) {
5483 // IE6-8 fails to persist the checked state of a cloned checkbox
5484 // or radio button. Worse, IE6-7 fail to give the cloned element
5485 // a checked appearance if the defaultChecked value isn't also set
5486
5487 dest.defaultChecked = dest.checked = src.checked;
5488
5489 // IE6-7 get confused and end up setting the value of a cloned
5490 // checkbox/radio button to an empty string instead of "on"
5491 if ( dest.value !== src.value ) {
5492 dest.value = src.value;
5493 }
5494
5495 // IE6-8 fails to return the selected option to the default selected
5496 // state when cloning options
5497 } else if ( nodeName === "option" ) {
5498 dest.defaultSelected = dest.selected = src.defaultSelected;
5499
5500 // IE6-8 fails to set the defaultValue to the correct value when
5501 // cloning other types of input fields
5502 } else if ( nodeName === "input" || nodeName === "textarea" ) {
5503 dest.defaultValue = src.defaultValue;
5504 }
5505}
5506
5507jQuery.extend({
5508 clone: function( elem, dataAndEvents, deepDataAndEvents ) {
5509 var destElements, node, clone, i, srcElements,
5510 inPage = jQuery.contains( elem.ownerDocument, elem );
5511
5512 if ( support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( "<" + elem.nodeName + ">" ) ) {
5513 clone = elem.cloneNode( true );
5514
5515 // IE<=8 does not properly clone detached, unknown element nodes
5516 } else {
5517 fragmentDiv.innerHTML = elem.outerHTML;
5518 fragmentDiv.removeChild( clone = fragmentDiv.firstChild );
5519 }
5520
5521 if ( (!support.noCloneEvent || !support.noCloneChecked) &&
5522 (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {
5523
5524 // We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2
5525 destElements = getAll( clone );
5526 srcElements = getAll( elem );
5527
5528 // Fix all IE cloning issues
5529 for ( i = 0; (node = srcElements[i]) != null; ++i ) {
5530 // Ensure that the destination node is not null; Fixes #9587
5531 if ( destElements[i] ) {
5532 fixCloneNodeIssues( node, destElements[i] );
5533 }
5534 }
5535 }
5536
5537 // Copy the events from the original to the clone
5538 if ( dataAndEvents ) {
5539 if ( deepDataAndEvents ) {
5540 srcElements = srcElements || getAll( elem );
5541 destElements = destElements || getAll( clone );
5542
5543 for ( i = 0; (node = srcElements[i]) != null; i++ ) {
5544 cloneCopyEvent( node, destElements[i] );
5545 }
5546 } else {
5547 cloneCopyEvent( elem, clone );
5548 }
5549 }
5550
5551 // Preserve script evaluation history
5552 destElements = getAll( clone, "script" );
5553 if ( destElements.length > 0 ) {
5554 setGlobalEval( destElements, !inPage && getAll( elem, "script" ) );
5555 }
5556
5557 destElements = srcElements = node = null;
5558
5559 // Return the cloned set
5560 return clone;
5561 },
5562
5563 buildFragment: function( elems, context, scripts, selection ) {
5564 var j, elem, contains,
5565 tmp, tag, tbody, wrap,
5566 l = elems.length,
5567
5568 // Ensure a safe fragment
5569 safe = createSafeFragment( context ),
5570
5571 nodes = [],
5572 i = 0;
5573
5574 for ( ; i < l; i++ ) {
5575 elem = elems[ i ];
5576
5577 if ( elem || elem === 0 ) {
5578
5579 // Add nodes directly
5580 if ( jQuery.type( elem ) === "object" ) {
5581 jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );
5582
5583 // Convert non-html into a text node
5584 } else if ( !rhtml.test( elem ) ) {
5585 nodes.push( context.createTextNode( elem ) );
5586
5587 // Convert html into DOM nodes
5588 } else {
5589 tmp = tmp || safe.appendChild( context.createElement("div") );
5590
5591 // Deserialize a standard representation
5592 tag = (rtagName.exec( elem ) || [ "", "" ])[ 1 ].toLowerCase();
5593 wrap = wrapMap[ tag ] || wrapMap._default;
5594
5595 tmp.innerHTML = wrap[1] + elem.replace( rxhtmlTag, "<$1></$2>" ) + wrap[2];
5596
5597 // Descend through wrappers to the right content
5598 j = wrap[0];
5599 while ( j-- ) {
5600 tmp = tmp.lastChild;
5601 }
5602
5603 // Manually add leading whitespace removed by IE
5604 if ( !support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {
5605 nodes.push( context.createTextNode( rleadingWhitespace.exec( elem )[0] ) );
5606 }
5607
5608 // Remove IE's autoinserted <tbody> from table fragments
5609 if ( !support.tbody ) {
5610
5611 // String was a <table>, *may* have spurious <tbody>
5612 elem = tag === "table" && !rtbody.test( elem ) ?
5613 tmp.firstChild :
5614
5615 // String was a bare <thead> or <tfoot>
5616 wrap[1] === "<table>" && !rtbody.test( elem ) ?
5617 tmp :
5618 0;
5619
5620 j = elem && elem.childNodes.length;
5621 while ( j-- ) {
5622 if ( jQuery.nodeName( (tbody = elem.childNodes[j]), "tbody" ) && !tbody.childNodes.length ) {
5623 elem.removeChild( tbody );
5624 }
5625 }
5626 }
5627
5628 jQuery.merge( nodes, tmp.childNodes );
5629
5630 // Fix #12392 for WebKit and IE > 9
5631 tmp.textContent = "";
5632
5633 // Fix #12392 for oldIE
5634 while ( tmp.firstChild ) {
5635 tmp.removeChild( tmp.firstChild );
5636 }
5637
5638 // Remember the top-level container for proper cleanup
5639 tmp = safe.lastChild;
5640 }
5641 }
5642 }
5643
5644 // Fix #11356: Clear elements from fragment
5645 if ( tmp ) {
5646 safe.removeChild( tmp );
5647 }
5648
5649 // Reset defaultChecked for any radios and checkboxes
5650 // about to be appended to the DOM in IE 6/7 (#8060)
5651 if ( !support.appendChecked ) {
5652 jQuery.grep( getAll( nodes, "input" ), fixDefaultChecked );
5653 }
5654
5655 i = 0;
5656 while ( (elem = nodes[ i++ ]) ) {
5657
5658 // #4087 - If origin and destination elements are the same, and this is
5659 // that element, do not do anything
5660 if ( selection && jQuery.inArray( elem, selection ) !== -1 ) {
5661 continue;
5662 }
5663
5664 contains = jQuery.contains( elem.ownerDocument, elem );
5665
5666 // Append to fragment
5667 tmp = getAll( safe.appendChild( elem ), "script" );
5668
5669 // Preserve script evaluation history
5670 if ( contains ) {
5671 setGlobalEval( tmp );
5672 }
5673
5674 // Capture executables
5675 if ( scripts ) {
5676 j = 0;
5677 while ( (elem = tmp[ j++ ]) ) {
5678 if ( rscriptType.test( elem.type || "" ) ) {
5679 scripts.push( elem );
5680 }
5681 }
5682 }
5683 }
5684
5685 tmp = null;
5686
5687 return safe;
5688 },
5689
5690 cleanData: function( elems, /* internal */ acceptData ) {
5691 var elem, type, id, data,
5692 i = 0,
5693 internalKey = jQuery.expando,
5694 cache = jQuery.cache,
5695 deleteExpando = support.deleteExpando,
5696 special = jQuery.event.special;
5697
5698 for ( ; (elem = elems[i]) != null; i++ ) {
5699 if ( acceptData || jQuery.acceptData( elem ) ) {
5700
5701 id = elem[ internalKey ];
5702 data = id && cache[ id ];
5703
5704 if ( data ) {
5705 if ( data.events ) {
5706 for ( type in data.events ) {
5707 if ( special[ type ] ) {
5708 jQuery.event.remove( elem, type );
5709
5710 // This is a shortcut to avoid jQuery.event.remove's overhead
5711 } else {
5712 jQuery.removeEvent( elem, type, data.handle );
5713 }
5714 }
5715 }
5716
5717 // Remove cache only if it was not already removed by jQuery.event.remove
5718 if ( cache[ id ] ) {
5719
5720 delete cache[ id ];
5721
5722 // IE does not allow us to delete expando properties from nodes,
5723 // nor does it have a removeAttribute function on Document nodes;
5724 // we must handle all of these cases
5725 if ( deleteExpando ) {
5726 delete elem[ internalKey ];
5727
5728 } else if ( typeof elem.removeAttribute !== strundefined ) {
5729 elem.removeAttribute( internalKey );
5730
5731 } else {
5732 elem[ internalKey ] = null;
5733 }
5734
5735 deletedIds.push( id );
5736 }
5737 }
5738 }
5739 }
5740 }
5741});
5742
5743jQuery.fn.extend({
5744 text: function( value ) {
5745 return access( this, function( value ) {
5746 return value === undefined ?
5747 jQuery.text( this ) :
5748 this.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) );
5749 }, null, value, arguments.length );
5750 },
5751
5752 append: function() {
5753 return this.domManip( arguments, function( elem ) {
5754 if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
5755 var target = manipulationTarget( this, elem );
5756 target.appendChild( elem );
5757 }
5758 });
5759 },
5760
5761 prepend: function() {
5762 return this.domManip( arguments, function( elem ) {
5763 if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
5764 var target = manipulationTarget( this, elem );
5765 target.insertBefore( elem, target.firstChild );
5766 }
5767 });
5768 },
5769
5770 before: function() {
5771 return this.domManip( arguments, function( elem ) {
5772 if ( this.parentNode ) {
5773 this.parentNode.insertBefore( elem, this );
5774 }
5775 });
5776 },
5777
5778 after: function() {
5779 return this.domManip( arguments, function( elem ) {
5780 if ( this.parentNode ) {
5781 this.parentNode.insertBefore( elem, this.nextSibling );
5782 }
5783 });
5784 },
5785
5786 remove: function( selector, keepData /* Internal Use Only */ ) {
5787 var elem,
5788 elems = selector ? jQuery.filter( selector, this ) : this,
5789 i = 0;
5790
5791 for ( ; (elem = elems[i]) != null; i++ ) {
5792
5793 if ( !keepData && elem.nodeType === 1 ) {
5794 jQuery.cleanData( getAll( elem ) );
5795 }
5796
5797 if ( elem.parentNode ) {
5798 if ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) {
5799 setGlobalEval( getAll( elem, "script" ) );
5800 }
5801 elem.parentNode.removeChild( elem );
5802 }
5803 }
5804
5805 return this;
5806 },
5807
5808 empty: function() {
5809 var elem,
5810 i = 0;
5811
5812 for ( ; (elem = this[i]) != null; i++ ) {
5813 // Remove element nodes and prevent memory leaks
5814 if ( elem.nodeType === 1 ) {
5815 jQuery.cleanData( getAll( elem, false ) );
5816 }
5817
5818 // Remove any remaining nodes
5819 while ( elem.firstChild ) {
5820 elem.removeChild( elem.firstChild );
5821 }
5822
5823 // If this is a select, ensure that it displays empty (#12336)
5824 // Support: IE<9
5825 if ( elem.options && jQuery.nodeName( elem, "select" ) ) {
5826 elem.options.length = 0;
5827 }
5828 }
5829
5830 return this;
5831 },
5832
5833 clone: function( dataAndEvents, deepDataAndEvents ) {
5834 dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
5835 deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
5836
5837 return this.map(function() {
5838 return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
5839 });
5840 },
5841
5842 html: function( value ) {
5843 return access( this, function( value ) {
5844 var elem = this[ 0 ] || {},
5845 i = 0,
5846 l = this.length;
5847
5848 if ( value === undefined ) {
5849 return elem.nodeType === 1 ?
5850 elem.innerHTML.replace( rinlinejQuery, "" ) :
5851 undefined;
5852 }
5853
5854 // See if we can take a shortcut and just use innerHTML
5855 if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
5856 ( support.htmlSerialize || !rnoshimcache.test( value ) ) &&
5857 ( support.leadingWhitespace || !rleadingWhitespace.test( value ) ) &&
5858 !wrapMap[ (rtagName.exec( value ) || [ "", "" ])[ 1 ].toLowerCase() ] ) {
5859
5860 value = value.replace( rxhtmlTag, "<$1></$2>" );
5861
5862 try {
5863 for (; i < l; i++ ) {
5864 // Remove element nodes and prevent memory leaks
5865 elem = this[i] || {};
5866 if ( elem.nodeType === 1 ) {
5867 jQuery.cleanData( getAll( elem, false ) );
5868 elem.innerHTML = value;
5869 }
5870 }
5871
5872 elem = 0;
5873
5874 // If using innerHTML throws an exception, use the fallback method
5875 } catch(e) {}
5876 }
5877
5878 if ( elem ) {
5879 this.empty().append( value );
5880 }
5881 }, null, value, arguments.length );
5882 },
5883
5884 replaceWith: function() {
5885 var arg = arguments[ 0 ];
5886
5887 // Make the changes, replacing each context element with the new content
5888 this.domManip( arguments, function( elem ) {
5889 arg = this.parentNode;
5890
5891 jQuery.cleanData( getAll( this ) );
5892
5893 if ( arg ) {
5894 arg.replaceChild( elem, this );
5895 }
5896 });
5897
5898 // Force removal if there was no new content (e.g., from empty arguments)
5899 return arg && (arg.length || arg.nodeType) ? this : this.remove();
5900 },
5901
5902 detach: function( selector ) {
5903 return this.remove( selector, true );
5904 },
5905
5906 domManip: function( args, callback ) {
5907
5908 // Flatten any nested arrays
5909 args = concat.apply( [], args );
5910
5911 var first, node, hasScripts,
5912 scripts, doc, fragment,
5913 i = 0,
5914 l = this.length,
5915 set = this,
5916 iNoClone = l - 1,
5917 value = args[0],
5918 isFunction = jQuery.isFunction( value );
5919
5920 // We can't cloneNode fragments that contain checked, in WebKit
5921 if ( isFunction ||
5922 ( l > 1 && typeof value === "string" &&
5923 !support.checkClone && rchecked.test( value ) ) ) {
5924 return this.each(function( index ) {
5925 var self = set.eq( index );
5926 if ( isFunction ) {
5927 args[0] = value.call( this, index, self.html() );
5928 }
5929 self.domManip( args, callback );
5930 });
5931 }
5932
5933 if ( l ) {
5934 fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, this );
5935 first = fragment.firstChild;
5936
5937 if ( fragment.childNodes.length === 1 ) {
5938 fragment = first;
5939 }
5940
5941 if ( first ) {
5942 scripts = jQuery.map( getAll( fragment, "script" ), disableScript );
5943 hasScripts = scripts.length;
5944
5945 // Use the original fragment for the last item instead of the first because it can end up
5946 // being emptied incorrectly in certain situations (#8070).
5947 for ( ; i < l; i++ ) {
5948 node = fragment;
5949
5950 if ( i !== iNoClone ) {
5951 node = jQuery.clone( node, true, true );
5952
5953 // Keep references to cloned scripts for later restoration
5954 if ( hasScripts ) {
5955 jQuery.merge( scripts, getAll( node, "script" ) );
5956 }
5957 }
5958
5959 callback.call( this[i], node, i );
5960 }
5961
5962 if ( hasScripts ) {
5963 doc = scripts[ scripts.length - 1 ].ownerDocument;
5964
5965 // Reenable scripts
5966 jQuery.map( scripts, restoreScript );
5967
5968 // Evaluate executable scripts on first document insertion
5969 for ( i = 0; i < hasScripts; i++ ) {
5970 node = scripts[ i ];
5971 if ( rscriptType.test( node.type || "" ) &&
5972 !jQuery._data( node, "globalEval" ) && jQuery.contains( doc, node ) ) {
5973
5974 if ( node.src ) {
5975 // Optional AJAX dependency, but won't run scripts if not present
5976 if ( jQuery._evalUrl ) {
5977 jQuery._evalUrl( node.src );
5978 }
5979 } else {
5980 jQuery.globalEval( ( node.text || node.textContent || node.innerHTML || "" ).replace( rcleanScript, "" ) );
5981 }
5982 }
5983 }
5984 }
5985
5986 // Fix #11809: Avoid leaking memory
5987 fragment = first = null;
5988 }
5989 }
5990
5991 return this;
5992 }
5993});
5994
5995jQuery.each({
5996 appendTo: "append",
5997 prependTo: "prepend",
5998 insertBefore: "before",
5999 insertAfter: "after",
6000 replaceAll: "replaceWith"
6001}, function( name, original ) {
6002 jQuery.fn[ name ] = function( selector ) {
6003 var elems,
6004 i = 0,
6005 ret = [],
6006 insert = jQuery( selector ),
6007 last = insert.length - 1;
6008
6009 for ( ; i <= last; i++ ) {
6010 elems = i === last ? this : this.clone(true);
6011 jQuery( insert[i] )[ original ]( elems );
6012
6013 // Modern browsers can apply jQuery collections as arrays, but oldIE needs a .get()
6014 push.apply( ret, elems.get() );
6015 }
6016
6017 return this.pushStack( ret );
6018 };
6019});
6020
6021
6022var iframe,
6023 elemdisplay = {};
6024
6025/**
6026 * Retrieve the actual display of a element
6027 * @param {String} name nodeName of the element
6028 * @param {Object} doc Document object
6029 */
6030// Called only from within defaultDisplay
6031function actualDisplay( name, doc ) {
6032 var style,
6033 elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ),
6034
6035 // getDefaultComputedStyle might be reliably used only on attached element
6036 display = window.getDefaultComputedStyle && ( style = window.getDefaultComputedStyle( elem[ 0 ] ) ) ?
6037
6038 // Use of this method is a temporary fix (more like optmization) until something better comes along,
6039 // since it was removed from specification and supported only in FF
6040 style.display : jQuery.css( elem[ 0 ], "display" );
6041
6042 // We don't have any data stored on the element,
6043 // so use "detach" method as fast way to get rid of the element
6044 elem.detach();
6045
6046 return display;
6047}
6048
6049/**
6050 * Try to determine the default display value of an element
6051 * @param {String} nodeName
6052 */
6053function defaultDisplay( nodeName ) {
6054 var doc = document,
6055 display = elemdisplay[ nodeName ];
6056
6057 if ( !display ) {
6058 display = actualDisplay( nodeName, doc );
6059
6060 // If the simple way fails, read from inside an iframe
6061 if ( display === "none" || !display ) {
6062
6063 // Use the already-created iframe if possible
6064 iframe = (iframe || jQuery( "<iframe frameborder='0' width='0' height='0'/>" )).appendTo( doc.documentElement );
6065
6066 // Always write a new HTML skeleton so Webkit and Firefox don't choke on reuse
6067 doc = ( iframe[ 0 ].contentWindow || iframe[ 0 ].contentDocument ).document;
6068
6069 // Support: IE
6070 doc.write();
6071 doc.close();
6072
6073 display = actualDisplay( nodeName, doc );
6074 iframe.detach();
6075 }
6076
6077 // Store the correct default display
6078 elemdisplay[ nodeName ] = display;
6079 }
6080
6081 return display;
6082}
6083
6084
6085(function() {
6086 var shrinkWrapBlocksVal;
6087
6088 support.shrinkWrapBlocks = function() {
6089 if ( shrinkWrapBlocksVal != null ) {
6090 return shrinkWrapBlocksVal;
6091 }
6092
6093 // Will be changed later if needed.
6094 shrinkWrapBlocksVal = false;
6095
6096 // Minified: var b,c,d
6097 var div, body, container;
6098
6099 body = document.getElementsByTagName( "body" )[ 0 ];
6100 if ( !body || !body.style ) {
6101 // Test fired too early or in an unsupported environment, exit.
6102 return;
6103 }
6104
6105 // Setup
6106 div = document.createElement( "div" );
6107 container = document.createElement( "div" );
6108 container.style.cssText = "position:absolute;border:0;width:0;height:0;top:0;left:-9999px";
6109 body.appendChild( container ).appendChild( div );
6110
6111 // Support: IE6
6112 // Check if elements with layout shrink-wrap their children
6113 if ( typeof div.style.zoom !== strundefined ) {
6114 // Reset CSS: box-sizing; display; margin; border
6115 div.style.cssText =
6116 // Support: Firefox<29, Android 2.3
6117 // Vendor-prefix box-sizing
6118 "-webkit-box-sizing:content-box;-moz-box-sizing:content-box;" +
6119 "box-sizing:content-box;display:block;margin:0;border:0;" +
6120 "padding:1px;width:1px;zoom:1";
6121 div.appendChild( document.createElement( "div" ) ).style.width = "5px";
6122 shrinkWrapBlocksVal = div.offsetWidth !== 3;
6123 }
6124
6125 body.removeChild( container );
6126
6127 return shrinkWrapBlocksVal;
6128 };
6129
6130})();
6131var rmargin = (/^margin/);
6132
6133var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" );
6134
6135
6136
6137var getStyles, curCSS,
6138 rposition = /^(top|right|bottom|left)$/;
6139
6140if ( window.getComputedStyle ) {
6141 getStyles = function( elem ) {
6142 // Support: IE<=11+, Firefox<=30+ (#15098, #14150)
6143 // IE throws on elements created in popups
6144 // FF meanwhile throws on frame elements through "defaultView.getComputedStyle"
6145 if ( elem.ownerDocument.defaultView.opener ) {
6146 return elem.ownerDocument.defaultView.getComputedStyle( elem, null );
6147 }
6148
6149 return window.getComputedStyle( elem, null );
6150 };
6151
6152 curCSS = function( elem, name, computed ) {
6153 var width, minWidth, maxWidth, ret,
6154 style = elem.style;
6155
6156 computed = computed || getStyles( elem );
6157
6158 // getPropertyValue is only needed for .css('filter') in IE9, see #12537
6159 ret = computed ? computed.getPropertyValue( name ) || computed[ name ] : undefined;
6160
6161 if ( computed ) {
6162
6163 if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) {
6164 ret = jQuery.style( elem, name );
6165 }
6166
6167 // A tribute to the "awesome hack by Dean Edwards"
6168 // Chrome < 17 and Safari 5.0 uses "computed value" instead of "used value" for margin-right
6169 // Safari 5.1.7 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels
6170 // this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values
6171 if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) {
6172
6173 // Remember the original values
6174 width = style.width;
6175 minWidth = style.minWidth;
6176 maxWidth = style.maxWidth;
6177
6178 // Put in the new values to get a computed value out
6179 style.minWidth = style.maxWidth = style.width = ret;
6180 ret = computed.width;
6181
6182 // Revert the changed values
6183 style.width = width;
6184 style.minWidth = minWidth;
6185 style.maxWidth = maxWidth;
6186 }
6187 }
6188
6189 // Support: IE
6190 // IE returns zIndex value as an integer.
6191 return ret === undefined ?
6192 ret :
6193 ret + "";
6194 };
6195} else if ( document.documentElement.currentStyle ) {
6196 getStyles = function( elem ) {
6197 return elem.currentStyle;
6198 };
6199
6200 curCSS = function( elem, name, computed ) {
6201 var left, rs, rsLeft, ret,
6202 style = elem.style;
6203
6204 computed = computed || getStyles( elem );
6205 ret = computed ? computed[ name ] : undefined;
6206
6207 // Avoid setting ret to empty string here
6208 // so we don't default to auto
6209 if ( ret == null && style && style[ name ] ) {
6210 ret = style[ name ];
6211 }
6212
6213 // From the awesome hack by Dean Edwards
6214 // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
6215
6216 // If we're not dealing with a regular pixel number
6217 // but a number that has a weird ending, we need to convert it to pixels
6218 // but not position css attributes, as those are proportional to the parent element instead
6219 // and we can't measure the parent instead because it might trigger a "stacking dolls" problem
6220 if ( rnumnonpx.test( ret ) && !rposition.test( name ) ) {
6221
6222 // Remember the original values
6223 left = style.left;
6224 rs = elem.runtimeStyle;
6225 rsLeft = rs && rs.left;
6226
6227 // Put in the new values to get a computed value out
6228 if ( rsLeft ) {
6229 rs.left = elem.currentStyle.left;
6230 }
6231 style.left = name === "fontSize" ? "1em" : ret;
6232 ret = style.pixelLeft + "px";
6233
6234 // Revert the changed values
6235 style.left = left;
6236 if ( rsLeft ) {
6237 rs.left = rsLeft;
6238 }
6239 }
6240
6241 // Support: IE
6242 // IE returns zIndex value as an integer.
6243 return ret === undefined ?
6244 ret :
6245 ret + "" || "auto";
6246 };
6247}
6248
6249
6250
6251
6252function addGetHookIf( conditionFn, hookFn ) {
6253 // Define the hook, we'll check on the first run if it's really needed.
6254 return {
6255 get: function() {
6256 var condition = conditionFn();
6257
6258 if ( condition == null ) {
6259 // The test was not ready at this point; screw the hook this time
6260 // but check again when needed next time.
6261 return;
6262 }
6263
6264 if ( condition ) {
6265 // Hook not needed (or it's not possible to use it due to missing dependency),
6266 // remove it.
6267 // Since there are no other hooks for marginRight, remove the whole object.
6268 delete this.get;
6269 return;
6270 }
6271
6272 // Hook needed; redefine it so that the support test is not executed again.
6273
6274 return (this.get = hookFn).apply( this, arguments );
6275 }
6276 };
6277}
6278
6279
6280(function() {
6281 // Minified: var b,c,d,e,f,g, h,i
6282 var div, style, a, pixelPositionVal, boxSizingReliableVal,
6283 reliableHiddenOffsetsVal, reliableMarginRightVal;
6284
6285 // Setup
6286 div = document.createElement( "div" );
6287 div.innerHTML = " <link/><table></table><a href='/a'>a</a><input type='checkbox'/>";
6288 a = div.getElementsByTagName( "a" )[ 0 ];
6289 style = a && a.style;
6290
6291 // Finish early in limited (non-browser) environments
6292 if ( !style ) {
6293 return;
6294 }
6295
6296 style.cssText = "float:left;opacity:.5";
6297
6298 // Support: IE<9
6299 // Make sure that element opacity exists (as opposed to filter)
6300 support.opacity = style.opacity === "0.5";
6301
6302 // Verify style float existence
6303 // (IE uses styleFloat instead of cssFloat)
6304 support.cssFloat = !!style.cssFloat;
6305
6306 div.style.backgroundClip = "content-box";
6307 div.cloneNode( true ).style.backgroundClip = "";
6308 support.clearCloneStyle = div.style.backgroundClip === "content-box";
6309
6310 // Support: Firefox<29, Android 2.3
6311 // Vendor-prefix box-sizing
6312 support.boxSizing = style.boxSizing === "" || style.MozBoxSizing === "" ||
6313 style.WebkitBoxSizing === "";
6314
6315 jQuery.extend(support, {
6316 reliableHiddenOffsets: function() {
6317 if ( reliableHiddenOffsetsVal == null ) {
6318 computeStyleTests();
6319 }
6320 return reliableHiddenOffsetsVal;
6321 },
6322
6323 boxSizingReliable: function() {
6324 if ( boxSizingReliableVal == null ) {
6325 computeStyleTests();
6326 }
6327 return boxSizingReliableVal;
6328 },
6329
6330 pixelPosition: function() {
6331 if ( pixelPositionVal == null ) {
6332 computeStyleTests();
6333 }
6334 return pixelPositionVal;
6335 },
6336
6337 // Support: Android 2.3
6338 reliableMarginRight: function() {
6339 if ( reliableMarginRightVal == null ) {
6340 computeStyleTests();
6341 }
6342 return reliableMarginRightVal;
6343 }
6344 });
6345
6346 function computeStyleTests() {
6347 // Minified: var b,c,d,j
6348 var div, body, container, contents;
6349
6350 body = document.getElementsByTagName( "body" )[ 0 ];
6351 if ( !body || !body.style ) {
6352 // Test fired too early or in an unsupported environment, exit.
6353 return;
6354 }
6355
6356 // Setup
6357 div = document.createElement( "div" );
6358 container = document.createElement( "div" );
6359 container.style.cssText = "position:absolute;border:0;width:0;height:0;top:0;left:-9999px";
6360 body.appendChild( container ).appendChild( div );
6361
6362 div.style.cssText =
6363 // Support: Firefox<29, Android 2.3
6364 // Vendor-prefix box-sizing
6365 "-webkit-box-sizing:border-box;-moz-box-sizing:border-box;" +
6366 "box-sizing:border-box;display:block;margin-top:1%;top:1%;" +
6367 "border:1px;padding:1px;width:4px;position:absolute";
6368
6369 // Support: IE<9
6370 // Assume reasonable values in the absence of getComputedStyle
6371 pixelPositionVal = boxSizingReliableVal = false;
6372 reliableMarginRightVal = true;
6373
6374 // Check for getComputedStyle so that this code is not run in IE<9.
6375 if ( window.getComputedStyle ) {
6376 pixelPositionVal = ( window.getComputedStyle( div, null ) || {} ).top !== "1%";
6377 boxSizingReliableVal =
6378 ( window.getComputedStyle( div, null ) || { width: "4px" } ).width === "4px";
6379
6380 // Support: Android 2.3
6381 // Div with explicit width and no margin-right incorrectly
6382 // gets computed margin-right based on width of container (#3333)
6383 // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
6384 contents = div.appendChild( document.createElement( "div" ) );
6385
6386 // Reset CSS: box-sizing; display; margin; border; padding
6387 contents.style.cssText = div.style.cssText =
6388 // Support: Firefox<29, Android 2.3
6389 // Vendor-prefix box-sizing
6390 "-webkit-box-sizing:content-box;-moz-box-sizing:content-box;" +
6391 "box-sizing:content-box;display:block;margin:0;border:0;padding:0";
6392 contents.style.marginRight = contents.style.width = "0";
6393 div.style.width = "1px";
6394
6395 reliableMarginRightVal =
6396 !parseFloat( ( window.getComputedStyle( contents, null ) || {} ).marginRight );
6397
6398 div.removeChild( contents );
6399 }
6400
6401 // Support: IE8
6402 // Check if table cells still have offsetWidth/Height when they are set
6403 // to display:none and there are still other visible table cells in a
6404 // table row; if so, offsetWidth/Height are not reliable for use when
6405 // determining if an element has been hidden directly using
6406 // display:none (it is still safe to use offsets if a parent element is
6407 // hidden; don safety goggles and see bug #4512 for more information).
6408 div.innerHTML = "<table><tr><td></td><td>t</td></tr></table>";
6409 contents = div.getElementsByTagName( "td" );
6410 contents[ 0 ].style.cssText = "margin:0;border:0;padding:0;display:none";
6411 reliableHiddenOffsetsVal = contents[ 0 ].offsetHeight === 0;
6412 if ( reliableHiddenOffsetsVal ) {
6413 contents[ 0 ].style.display = "";
6414 contents[ 1 ].style.display = "none";
6415 reliableHiddenOffsetsVal = contents[ 0 ].offsetHeight === 0;
6416 }
6417
6418 body.removeChild( container );
6419 }
6420
6421})();
6422
6423
6424// A method for quickly swapping in/out CSS properties to get correct calculations.
6425jQuery.swap = function( elem, options, callback, args ) {
6426 var ret, name,
6427 old = {};
6428
6429 // Remember the old values, and insert the new ones
6430 for ( name in options ) {
6431 old[ name ] = elem.style[ name ];
6432 elem.style[ name ] = options[ name ];
6433 }
6434
6435 ret = callback.apply( elem, args || [] );
6436
6437 // Revert the old values
6438 for ( name in options ) {
6439 elem.style[ name ] = old[ name ];
6440 }
6441
6442 return ret;
6443};
6444
6445
6446var
6447 ralpha = /alpha\([^)]*\)/i,
6448 ropacity = /opacity\s*=\s*([^)]*)/,
6449
6450 // swappable if display is none or starts with table except "table", "table-cell", or "table-caption"
6451 // see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
6452 rdisplayswap = /^(none|table(?!-c[ea]).+)/,
6453 rnumsplit = new RegExp( "^(" + pnum + ")(.*)$", "i" ),
6454 rrelNum = new RegExp( "^([+-])=(" + pnum + ")", "i" ),
6455
6456 cssShow = { position: "absolute", visibility: "hidden", display: "block" },
6457 cssNormalTransform = {
6458 letterSpacing: "0",
6459 fontWeight: "400"
6460 },
6461
6462 cssPrefixes = [ "Webkit", "O", "Moz", "ms" ];
6463
6464
6465// return a css property mapped to a potentially vendor prefixed property
6466function vendorPropName( style, name ) {
6467
6468 // shortcut for names that are not vendor prefixed
6469 if ( name in style ) {
6470 return name;
6471 }
6472
6473 // check for vendor prefixed names
6474 var capName = name.charAt(0).toUpperCase() + name.slice(1),
6475 origName = name,
6476 i = cssPrefixes.length;
6477
6478 while ( i-- ) {
6479 name = cssPrefixes[ i ] + capName;
6480 if ( name in style ) {
6481 return name;
6482 }
6483 }
6484
6485 return origName;
6486}
6487
6488function showHide( elements, show ) {
6489 var display, elem, hidden,
6490 values = [],
6491 index = 0,
6492 length = elements.length;
6493
6494 for ( ; index < length; index++ ) {
6495 elem = elements[ index ];
6496 if ( !elem.style ) {
6497 continue;
6498 }
6499
6500 values[ index ] = jQuery._data( elem, "olddisplay" );
6501 display = elem.style.display;
6502 if ( show ) {
6503 // Reset the inline display of this element to learn if it is
6504 // being hidden by cascaded rules or not
6505 if ( !values[ index ] && display === "none" ) {
6506 elem.style.display = "";
6507 }
6508
6509 // Set elements which have been overridden with display: none
6510 // in a stylesheet to whatever the default browser style is
6511 // for such an element
6512 if ( elem.style.display === "" && isHidden( elem ) ) {
6513 values[ index ] = jQuery._data( elem, "olddisplay", defaultDisplay(elem.nodeName) );
6514 }
6515 } else {
6516 hidden = isHidden( elem );
6517
6518 if ( display && display !== "none" || !hidden ) {
6519 jQuery._data( elem, "olddisplay", hidden ? display : jQuery.css( elem, "display" ) );
6520 }
6521 }
6522 }
6523
6524 // Set the display of most of the elements in a second loop
6525 // to avoid the constant reflow
6526 for ( index = 0; index < length; index++ ) {
6527 elem = elements[ index ];
6528 if ( !elem.style ) {
6529 continue;
6530 }
6531 if ( !show || elem.style.display === "none" || elem.style.display === "" ) {
6532 elem.style.display = show ? values[ index ] || "" : "none";
6533 }
6534 }
6535
6536 return elements;
6537}
6538
6539function setPositiveNumber( elem, value, subtract ) {
6540 var matches = rnumsplit.exec( value );
6541 return matches ?
6542 // Guard against undefined "subtract", e.g., when used as in cssHooks
6543 Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) :
6544 value;
6545}
6546
6547function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {
6548 var i = extra === ( isBorderBox ? "border" : "content" ) ?
6549 // If we already have the right measurement, avoid augmentation
6550 4 :
6551 // Otherwise initialize for horizontal or vertical properties
6552 name === "width" ? 1 : 0,
6553
6554 val = 0;
6555
6556 for ( ; i < 4; i += 2 ) {
6557 // both box models exclude margin, so add it if we want it
6558 if ( extra === "margin" ) {
6559 val += jQuery.css( elem, extra + cssExpand[ i ], true, styles );
6560 }
6561
6562 if ( isBorderBox ) {
6563 // border-box includes padding, so remove it if we want content
6564 if ( extra === "content" ) {
6565 val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
6566 }
6567
6568 // at this point, extra isn't border nor margin, so remove border
6569 if ( extra !== "margin" ) {
6570 val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
6571 }
6572 } else {
6573 // at this point, extra isn't content, so add padding
6574 val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
6575
6576 // at this point, extra isn't content nor padding, so add border
6577 if ( extra !== "padding" ) {
6578 val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
6579 }
6580 }
6581 }
6582
6583 return val;
6584}
6585
6586function getWidthOrHeight( elem, name, extra ) {
6587
6588 // Start with offset property, which is equivalent to the border-box value
6589 var valueIsBorderBox = true,
6590 val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
6591 styles = getStyles( elem ),
6592 isBorderBox = support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box";
6593
6594 // some non-html elements return undefined for offsetWidth, so check for null/undefined
6595 // svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285
6596 // MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668
6597 if ( val <= 0 || val == null ) {
6598 // Fall back to computed then uncomputed css if necessary
6599 val = curCSS( elem, name, styles );
6600 if ( val < 0 || val == null ) {
6601 val = elem.style[ name ];
6602 }
6603
6604 // Computed unit is not pixels. Stop here and return.
6605 if ( rnumnonpx.test(val) ) {
6606 return val;
6607 }
6608
6609 // we need the check for style in case a browser which returns unreliable values
6610 // for getComputedStyle silently falls back to the reliable elem.style
6611 valueIsBorderBox = isBorderBox && ( support.boxSizingReliable() || val === elem.style[ name ] );
6612
6613 // Normalize "", auto, and prepare for extra
6614 val = parseFloat( val ) || 0;
6615 }
6616
6617 // use the active box-sizing model to add/subtract irrelevant styles
6618 return ( val +
6619 augmentWidthOrHeight(
6620 elem,
6621 name,
6622 extra || ( isBorderBox ? "border" : "content" ),
6623 valueIsBorderBox,
6624 styles
6625 )
6626 ) + "px";
6627}
6628
6629jQuery.extend({
6630 // Add in style property hooks for overriding the default
6631 // behavior of getting and setting a style property
6632 cssHooks: {
6633 opacity: {
6634 get: function( elem, computed ) {
6635 if ( computed ) {
6636 // We should always get a number back from opacity
6637 var ret = curCSS( elem, "opacity" );
6638 return ret === "" ? "1" : ret;
6639 }
6640 }
6641 }
6642 },
6643
6644 // Don't automatically add "px" to these possibly-unitless properties
6645 cssNumber: {
6646 "columnCount": true,
6647 "fillOpacity": true,
6648 "flexGrow": true,
6649 "flexShrink": true,
6650 "fontWeight": true,
6651 "lineHeight": true,
6652 "opacity": true,
6653 "order": true,
6654 "orphans": true,
6655 "widows": true,
6656 "zIndex": true,
6657 "zoom": true
6658 },
6659
6660 // Add in properties whose names you wish to fix before
6661 // setting or getting the value
6662 cssProps: {
6663 // normalize float css property
6664 "float": support.cssFloat ? "cssFloat" : "styleFloat"
6665 },
6666
6667 // Get and set the style property on a DOM Node
6668 style: function( elem, name, value, extra ) {
6669 // Don't set styles on text and comment nodes
6670 if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
6671 return;
6672 }
6673
6674 // Make sure that we're working with the right name
6675 var ret, type, hooks,
6676 origName = jQuery.camelCase( name ),
6677 style = elem.style;
6678
6679 name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) );
6680
6681 // gets hook for the prefixed version
6682 // followed by the unprefixed version
6683 hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
6684
6685 // Check if we're setting a value
6686 if ( value !== undefined ) {
6687 type = typeof value;
6688
6689 // convert relative number strings (+= or -=) to relative numbers. #7345
6690 if ( type === "string" && (ret = rrelNum.exec( value )) ) {
6691 value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) );
6692 // Fixes bug #9237
6693 type = "number";
6694 }
6695
6696 // Make sure that null and NaN values aren't set. See: #7116
6697 if ( value == null || value !== value ) {
6698 return;
6699 }
6700
6701 // If a number was passed in, add 'px' to the (except for certain CSS properties)
6702 if ( type === "number" && !jQuery.cssNumber[ origName ] ) {
6703 value += "px";
6704 }
6705
6706 // Fixes #8908, it can be done more correctly by specifing setters in cssHooks,
6707 // but it would mean to define eight (for every problematic property) identical functions
6708 if ( !support.clearCloneStyle && value === "" && name.indexOf("background") === 0 ) {
6709 style[ name ] = "inherit";
6710 }
6711
6712 // If a hook was provided, use that value, otherwise just set the specified value
6713 if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) {
6714
6715 // Support: IE
6716 // Swallow errors from 'invalid' CSS values (#5509)
6717 try {
6718 style[ name ] = value;
6719 } catch(e) {}
6720 }
6721
6722 } else {
6723 // If a hook was provided get the non-computed value from there
6724 if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {
6725 return ret;
6726 }
6727
6728 // Otherwise just get the value from the style object
6729 return style[ name ];
6730 }
6731 },
6732
6733 css: function( elem, name, extra, styles ) {
6734 var num, val, hooks,
6735 origName = jQuery.camelCase( name );
6736
6737 // Make sure that we're working with the right name
6738 name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) );
6739
6740 // gets hook for the prefixed version
6741 // followed by the unprefixed version
6742 hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
6743
6744 // If a hook was provided get the computed value from there
6745 if ( hooks && "get" in hooks ) {
6746 val = hooks.get( elem, true, extra );
6747 }
6748
6749 // Otherwise, if a way to get the computed value exists, use that
6750 if ( val === undefined ) {
6751 val = curCSS( elem, name, styles );
6752 }
6753
6754 //convert "normal" to computed value
6755 if ( val === "normal" && name in cssNormalTransform ) {
6756 val = cssNormalTransform[ name ];
6757 }
6758
6759 // Return, converting to number if forced or a qualifier was provided and val looks numeric
6760 if ( extra === "" || extra ) {
6761 num = parseFloat( val );
6762 return extra === true || jQuery.isNumeric( num ) ? num || 0 : val;
6763 }
6764 return val;
6765 }
6766});
6767
6768jQuery.each([ "height", "width" ], function( i, name ) {
6769 jQuery.cssHooks[ name ] = {
6770 get: function( elem, computed, extra ) {
6771 if ( computed ) {
6772 // certain elements can have dimension info if we invisibly show them
6773 // however, it must have a current display style that would benefit from this
6774 return rdisplayswap.test( jQuery.css( elem, "display" ) ) && elem.offsetWidth === 0 ?
6775 jQuery.swap( elem, cssShow, function() {
6776 return getWidthOrHeight( elem, name, extra );
6777 }) :
6778 getWidthOrHeight( elem, name, extra );
6779 }
6780 },
6781
6782 set: function( elem, value, extra ) {
6783 var styles = extra && getStyles( elem );
6784 return setPositiveNumber( elem, value, extra ?
6785 augmentWidthOrHeight(
6786 elem,
6787 name,
6788 extra,
6789 support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
6790 styles
6791 ) : 0
6792 );
6793 }
6794 };
6795});
6796
6797if ( !support.opacity ) {
6798 jQuery.cssHooks.opacity = {
6799 get: function( elem, computed ) {
6800 // IE uses filters for opacity
6801 return ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "" ) ?
6802 ( 0.01 * parseFloat( RegExp.$1 ) ) + "" :
6803 computed ? "1" : "";
6804 },
6805
6806 set: function( elem, value ) {
6807 var style = elem.style,
6808 currentStyle = elem.currentStyle,
6809 opacity = jQuery.isNumeric( value ) ? "alpha(opacity=" + value * 100 + ")" : "",
6810 filter = currentStyle && currentStyle.filter || style.filter || "";
6811
6812 // IE has trouble with opacity if it does not have layout
6813 // Force it by setting the zoom level
6814 style.zoom = 1;
6815
6816 // if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652
6817 // if value === "", then remove inline opacity #12685
6818 if ( ( value >= 1 || value === "" ) &&
6819 jQuery.trim( filter.replace( ralpha, "" ) ) === "" &&
6820 style.removeAttribute ) {
6821
6822 // Setting style.filter to null, "" & " " still leave "filter:" in the cssText
6823 // if "filter:" is present at all, clearType is disabled, we want to avoid this
6824 // style.removeAttribute is IE Only, but so apparently is this code path...
6825 style.removeAttribute( "filter" );
6826
6827 // if there is no filter style applied in a css rule or unset inline opacity, we are done
6828 if ( value === "" || currentStyle && !currentStyle.filter ) {
6829 return;
6830 }
6831 }
6832
6833 // otherwise, set new filter values
6834 style.filter = ralpha.test( filter ) ?
6835 filter.replace( ralpha, opacity ) :
6836 filter + " " + opacity;
6837 }
6838 };
6839}
6840
6841jQuery.cssHooks.marginRight = addGetHookIf( support.reliableMarginRight,
6842 function( elem, computed ) {
6843 if ( computed ) {
6844 // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
6845 // Work around by temporarily setting element display to inline-block
6846 return jQuery.swap( elem, { "display": "inline-block" },
6847 curCSS, [ elem, "marginRight" ] );
6848 }
6849 }
6850);
6851
6852// These hooks are used by animate to expand properties
6853jQuery.each({
6854 margin: "",
6855 padding: "",
6856 border: "Width"
6857}, function( prefix, suffix ) {
6858 jQuery.cssHooks[ prefix + suffix ] = {
6859 expand: function( value ) {
6860 var i = 0,
6861 expanded = {},
6862
6863 // assumes a single number if not a string
6864 parts = typeof value === "string" ? value.split(" ") : [ value ];
6865
6866 for ( ; i < 4; i++ ) {
6867 expanded[ prefix + cssExpand[ i ] + suffix ] =
6868 parts[ i ] || parts[ i - 2 ] || parts[ 0 ];
6869 }
6870
6871 return expanded;
6872 }
6873 };
6874
6875 if ( !rmargin.test( prefix ) ) {
6876 jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;
6877 }
6878});
6879
6880jQuery.fn.extend({
6881 css: function( name, value ) {
6882 return access( this, function( elem, name, value ) {
6883 var styles, len,
6884 map = {},
6885 i = 0;
6886
6887 if ( jQuery.isArray( name ) ) {
6888 styles = getStyles( elem );
6889 len = name.length;
6890
6891 for ( ; i < len; i++ ) {
6892 map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );
6893 }
6894
6895 return map;
6896 }
6897
6898 return value !== undefined ?
6899 jQuery.style( elem, name, value ) :
6900 jQuery.css( elem, name );
6901 }, name, value, arguments.length > 1 );
6902 },
6903 show: function() {
6904 return showHide( this, true );
6905 },
6906 hide: function() {
6907 return showHide( this );
6908 },
6909 toggle: function( state ) {
6910 if ( typeof state === "boolean" ) {
6911 return state ? this.show() : this.hide();
6912 }
6913
6914 return this.each(function() {
6915 if ( isHidden( this ) ) {
6916 jQuery( this ).show();
6917 } else {
6918 jQuery( this ).hide();
6919 }
6920 });
6921 }
6922});
6923
6924
6925function Tween( elem, options, prop, end, easing ) {
6926 return new Tween.prototype.init( elem, options, prop, end, easing );
6927}
6928jQuery.Tween = Tween;
6929
6930Tween.prototype = {
6931 constructor: Tween,
6932 init: function( elem, options, prop, end, easing, unit ) {
6933 this.elem = elem;
6934 this.prop = prop;
6935 this.easing = easing || "swing";
6936 this.options = options;
6937 this.start = this.now = this.cur();
6938 this.end = end;
6939 this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" );
6940 },
6941 cur: function() {
6942 var hooks = Tween.propHooks[ this.prop ];
6943
6944 return hooks && hooks.get ?
6945 hooks.get( this ) :
6946 Tween.propHooks._default.get( this );
6947 },
6948 run: function( percent ) {
6949 var eased,
6950 hooks = Tween.propHooks[ this.prop ];
6951
6952 if ( this.options.duration ) {
6953 this.pos = eased = jQuery.easing[ this.easing ](
6954 percent, this.options.duration * percent, 0, 1, this.options.duration
6955 );
6956 } else {
6957 this.pos = eased = percent;
6958 }
6959 this.now = ( this.end - this.start ) * eased + this.start;
6960
6961 if ( this.options.step ) {
6962 this.options.step.call( this.elem, this.now, this );
6963 }
6964
6965 if ( hooks && hooks.set ) {
6966 hooks.set( this );
6967 } else {
6968 Tween.propHooks._default.set( this );
6969 }
6970 return this;
6971 }
6972};
6973
6974Tween.prototype.init.prototype = Tween.prototype;
6975
6976Tween.propHooks = {
6977 _default: {
6978 get: function( tween ) {
6979 var result;
6980
6981 if ( tween.elem[ tween.prop ] != null &&
6982 (!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) {
6983 return tween.elem[ tween.prop ];
6984 }
6985
6986 // passing an empty string as a 3rd parameter to .css will automatically
6987 // attempt a parseFloat and fallback to a string if the parse fails
6988 // so, simple values such as "10px" are parsed to Float.
6989 // complex values such as "rotate(1rad)" are returned as is.
6990 result = jQuery.css( tween.elem, tween.prop, "" );
6991 // Empty strings, null, undefined and "auto" are converted to 0.
6992 return !result || result === "auto" ? 0 : result;
6993 },
6994 set: function( tween ) {
6995 // use step hook for back compat - use cssHook if its there - use .style if its
6996 // available and use plain properties where available
6997 if ( jQuery.fx.step[ tween.prop ] ) {
6998 jQuery.fx.step[ tween.prop ]( tween );
6999 } else if ( tween.elem.style && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) {
7000 jQuery.style( tween.elem, tween.prop, tween.now + tween.unit );
7001 } else {
7002 tween.elem[ tween.prop ] = tween.now;
7003 }
7004 }
7005 }
7006};
7007
7008// Support: IE <=9
7009// Panic based approach to setting things on disconnected nodes
7010
7011Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {
7012 set: function( tween ) {
7013 if ( tween.elem.nodeType && tween.elem.parentNode ) {
7014 tween.elem[ tween.prop ] = tween.now;
7015 }
7016 }
7017};
7018
7019jQuery.easing = {
7020 linear: function( p ) {
7021 return p;
7022 },
7023 swing: function( p ) {
7024 return 0.5 - Math.cos( p * Math.PI ) / 2;
7025 }
7026};
7027
7028jQuery.fx = Tween.prototype.init;
7029
7030// Back Compat <1.8 extension point
7031jQuery.fx.step = {};
7032
7033
7034
7035
7036var
7037 fxNow, timerId,
7038 rfxtypes = /^(?:toggle|show|hide)$/,
7039 rfxnum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ),
7040 rrun = /queueHooks$/,
7041 animationPrefilters = [ defaultPrefilter ],
7042 tweeners = {
7043 "*": [ function( prop, value ) {
7044 var tween = this.createTween( prop, value ),
7045 target = tween.cur(),
7046 parts = rfxnum.exec( value ),
7047 unit = parts && parts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ),
7048
7049 // Starting value computation is required for potential unit mismatches
7050 start = ( jQuery.cssNumber[ prop ] || unit !== "px" && +target ) &&
7051 rfxnum.exec( jQuery.css( tween.elem, prop ) ),
7052 scale = 1,
7053 maxIterations = 20;
7054
7055 if ( start && start[ 3 ] !== unit ) {
7056 // Trust units reported by jQuery.css
7057 unit = unit || start[ 3 ];
7058
7059 // Make sure we update the tween properties later on
7060 parts = parts || [];
7061
7062 // Iteratively approximate from a nonzero starting point
7063 start = +target || 1;
7064
7065 do {
7066 // If previous iteration zeroed out, double until we get *something*
7067 // Use a string for doubling factor so we don't accidentally see scale as unchanged below
7068 scale = scale || ".5";
7069
7070 // Adjust and apply
7071 start = start / scale;
7072 jQuery.style( tween.elem, prop, start + unit );
7073
7074 // Update scale, tolerating zero or NaN from tween.cur()
7075 // And breaking the loop if scale is unchanged or perfect, or if we've just had enough
7076 } while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations );
7077 }
7078
7079 // Update tween properties
7080 if ( parts ) {
7081 start = tween.start = +start || +target || 0;
7082 tween.unit = unit;
7083 // If a +=/-= token was provided, we're doing a relative animation
7084 tween.end = parts[ 1 ] ?
7085 start + ( parts[ 1 ] + 1 ) * parts[ 2 ] :
7086 +parts[ 2 ];
7087 }
7088
7089 return tween;
7090 } ]
7091 };
7092
7093// Animations created synchronously will run synchronously
7094function createFxNow() {
7095 setTimeout(function() {
7096 fxNow = undefined;
7097 });
7098 return ( fxNow = jQuery.now() );
7099}
7100
7101// Generate parameters to create a standard animation
7102function genFx( type, includeWidth ) {
7103 var which,
7104 attrs = { height: type },
7105 i = 0;
7106
7107 // if we include width, step value is 1 to do all cssExpand values,
7108 // if we don't include width, step value is 2 to skip over Left and Right
7109 includeWidth = includeWidth ? 1 : 0;
7110 for ( ; i < 4 ; i += 2 - includeWidth ) {
7111 which = cssExpand[ i ];
7112 attrs[ "margin" + which ] = attrs[ "padding" + which ] = type;
7113 }
7114
7115 if ( includeWidth ) {
7116 attrs.opacity = attrs.width = type;
7117 }
7118
7119 return attrs;
7120}
7121
7122function createTween( value, prop, animation ) {
7123 var tween,
7124 collection = ( tweeners[ prop ] || [] ).concat( tweeners[ "*" ] ),
7125 index = 0,
7126 length = collection.length;
7127 for ( ; index < length; index++ ) {
7128 if ( (tween = collection[ index ].call( animation, prop, value )) ) {
7129
7130 // we're done with this property
7131 return tween;
7132 }
7133 }
7134}
7135
7136function defaultPrefilter( elem, props, opts ) {
7137 /* jshint validthis: true */
7138 var prop, value, toggle, tween, hooks, oldfire, display, checkDisplay,
7139 anim = this,
7140 orig = {},
7141 style = elem.style,
7142 hidden = elem.nodeType && isHidden( elem ),
7143 dataShow = jQuery._data( elem, "fxshow" );
7144
7145 // handle queue: false promises
7146 if ( !opts.queue ) {
7147 hooks = jQuery._queueHooks( elem, "fx" );
7148 if ( hooks.unqueued == null ) {
7149 hooks.unqueued = 0;
7150 oldfire = hooks.empty.fire;
7151 hooks.empty.fire = function() {
7152 if ( !hooks.unqueued ) {
7153 oldfire();
7154 }
7155 };
7156 }
7157 hooks.unqueued++;
7158
7159 anim.always(function() {
7160 // doing this makes sure that the complete handler will be called
7161 // before this completes
7162 anim.always(function() {
7163 hooks.unqueued--;
7164 if ( !jQuery.queue( elem, "fx" ).length ) {
7165 hooks.empty.fire();
7166 }
7167 });
7168 });
7169 }
7170
7171 // height/width overflow pass
7172 if ( elem.nodeType === 1 && ( "height" in props || "width" in props ) ) {
7173 // Make sure that nothing sneaks out
7174 // Record all 3 overflow attributes because IE does not
7175 // change the overflow attribute when overflowX and
7176 // overflowY are set to the same value
7177 opts.overflow = [ style.overflow, style.overflowX, style.overflowY ];
7178
7179 // Set display property to inline-block for height/width
7180 // animations on inline elements that are having width/height animated
7181 display = jQuery.css( elem, "display" );
7182
7183 // Test default display if display is currently "none"
7184 checkDisplay = display === "none" ?
7185 jQuery._data( elem, "olddisplay" ) || defaultDisplay( elem.nodeName ) : display;
7186
7187 if ( checkDisplay === "inline" && jQuery.css( elem, "float" ) === "none" ) {
7188
7189 // inline-level elements accept inline-block;
7190 // block-level elements need to be inline with layout
7191 if ( !support.inlineBlockNeedsLayout || defaultDisplay( elem.nodeName ) === "inline" ) {
7192 style.display = "inline-block";
7193 } else {
7194 style.zoom = 1;
7195 }
7196 }
7197 }
7198
7199 if ( opts.overflow ) {
7200 style.overflow = "hidden";
7201 if ( !support.shrinkWrapBlocks() ) {
7202 anim.always(function() {
7203 style.overflow = opts.overflow[ 0 ];
7204 style.overflowX = opts.overflow[ 1 ];
7205 style.overflowY = opts.overflow[ 2 ];
7206 });
7207 }
7208 }
7209
7210 // show/hide pass
7211 for ( prop in props ) {
7212 value = props[ prop ];
7213 if ( rfxtypes.exec( value ) ) {
7214 delete props[ prop ];
7215 toggle = toggle || value === "toggle";
7216 if ( value === ( hidden ? "hide" : "show" ) ) {
7217
7218 // If there is dataShow left over from a stopped hide or show and we are going to proceed with show, we should pretend to be hidden
7219 if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) {
7220 hidden = true;
7221 } else {
7222 continue;
7223 }
7224 }
7225 orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop );
7226
7227 // Any non-fx value stops us from restoring the original display value
7228 } else {
7229 display = undefined;
7230 }
7231 }
7232
7233 if ( !jQuery.isEmptyObject( orig ) ) {
7234 if ( dataShow ) {
7235 if ( "hidden" in dataShow ) {
7236 hidden = dataShow.hidden;
7237 }
7238 } else {
7239 dataShow = jQuery._data( elem, "fxshow", {} );
7240 }
7241
7242 // store state if its toggle - enables .stop().toggle() to "reverse"
7243 if ( toggle ) {
7244 dataShow.hidden = !hidden;
7245 }
7246 if ( hidden ) {
7247 jQuery( elem ).show();
7248 } else {
7249 anim.done(function() {
7250 jQuery( elem ).hide();
7251 });
7252 }
7253 anim.done(function() {
7254 var prop;
7255 jQuery._removeData( elem, "fxshow" );
7256 for ( prop in orig ) {
7257 jQuery.style( elem, prop, orig[ prop ] );
7258 }
7259 });
7260 for ( prop in orig ) {
7261 tween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim );
7262
7263 if ( !( prop in dataShow ) ) {
7264 dataShow[ prop ] = tween.start;
7265 if ( hidden ) {
7266 tween.end = tween.start;
7267 tween.start = prop === "width" || prop === "height" ? 1 : 0;
7268 }
7269 }
7270 }
7271
7272 // If this is a noop like .hide().hide(), restore an overwritten display value
7273 } else if ( (display === "none" ? defaultDisplay( elem.nodeName ) : display) === "inline" ) {
7274 style.display = display;
7275 }
7276}
7277
7278function propFilter( props, specialEasing ) {
7279 var index, name, easing, value, hooks;
7280
7281 // camelCase, specialEasing and expand cssHook pass
7282 for ( index in props ) {
7283 name = jQuery.camelCase( index );
7284 easing = specialEasing[ name ];
7285 value = props[ index ];
7286 if ( jQuery.isArray( value ) ) {
7287 easing = value[ 1 ];
7288 value = props[ index ] = value[ 0 ];
7289 }
7290
7291 if ( index !== name ) {
7292 props[ name ] = value;
7293 delete props[ index ];
7294 }
7295
7296 hooks = jQuery.cssHooks[ name ];
7297 if ( hooks && "expand" in hooks ) {
7298 value = hooks.expand( value );
7299 delete props[ name ];
7300
7301 // not quite $.extend, this wont overwrite keys already present.
7302 // also - reusing 'index' from above because we have the correct "name"
7303 for ( index in value ) {
7304 if ( !( index in props ) ) {
7305 props[ index ] = value[ index ];
7306 specialEasing[ index ] = easing;
7307 }
7308 }
7309 } else {
7310 specialEasing[ name ] = easing;
7311 }
7312 }
7313}
7314
7315function Animation( elem, properties, options ) {
7316 var result,
7317 stopped,
7318 index = 0,
7319 length = animationPrefilters.length,
7320 deferred = jQuery.Deferred().always( function() {
7321 // don't match elem in the :animated selector
7322 delete tick.elem;
7323 }),
7324 tick = function() {
7325 if ( stopped ) {
7326 return false;
7327 }
7328 var currentTime = fxNow || createFxNow(),
7329 remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
7330 // archaic crash bug won't allow us to use 1 - ( 0.5 || 0 ) (#12497)
7331 temp = remaining / animation.duration || 0,
7332 percent = 1 - temp,
7333 index = 0,
7334 length = animation.tweens.length;
7335
7336 for ( ; index < length ; index++ ) {
7337 animation.tweens[ index ].run( percent );
7338 }
7339
7340 deferred.notifyWith( elem, [ animation, percent, remaining ]);
7341
7342 if ( percent < 1 && length ) {
7343 return remaining;
7344 } else {
7345 deferred.resolveWith( elem, [ animation ] );
7346 return false;
7347 }
7348 },
7349 animation = deferred.promise({
7350 elem: elem,
7351 props: jQuery.extend( {}, properties ),
7352 opts: jQuery.extend( true, { specialEasing: {} }, options ),
7353 originalProperties: properties,
7354 originalOptions: options,
7355 startTime: fxNow || createFxNow(),
7356 duration: options.duration,
7357 tweens: [],
7358 createTween: function( prop, end ) {
7359 var tween = jQuery.Tween( elem, animation.opts, prop, end,
7360 animation.opts.specialEasing[ prop ] || animation.opts.easing );
7361 animation.tweens.push( tween );
7362 return tween;
7363 },
7364 stop: function( gotoEnd ) {
7365 var index = 0,
7366 // if we are going to the end, we want to run all the tweens
7367 // otherwise we skip this part
7368 length = gotoEnd ? animation.tweens.length : 0;
7369 if ( stopped ) {
7370 return this;
7371 }
7372 stopped = true;
7373 for ( ; index < length ; index++ ) {
7374 animation.tweens[ index ].run( 1 );
7375 }
7376
7377 // resolve when we played the last frame
7378 // otherwise, reject
7379 if ( gotoEnd ) {
7380 deferred.resolveWith( elem, [ animation, gotoEnd ] );
7381 } else {
7382 deferred.rejectWith( elem, [ animation, gotoEnd ] );
7383 }
7384 return this;
7385 }
7386 }),
7387 props = animation.props;
7388
7389 propFilter( props, animation.opts.specialEasing );
7390
7391 for ( ; index < length ; index++ ) {
7392 result = animationPrefilters[ index ].call( animation, elem, props, animation.opts );
7393 if ( result ) {
7394 return result;
7395 }
7396 }
7397
7398 jQuery.map( props, createTween, animation );
7399
7400 if ( jQuery.isFunction( animation.opts.start ) ) {
7401 animation.opts.start.call( elem, animation );
7402 }
7403
7404 jQuery.fx.timer(
7405 jQuery.extend( tick, {
7406 elem: elem,
7407 anim: animation,
7408 queue: animation.opts.queue
7409 })
7410 );
7411
7412 // attach callbacks from options
7413 return animation.progress( animation.opts.progress )
7414 .done( animation.opts.done, animation.opts.complete )
7415 .fail( animation.opts.fail )
7416 .always( animation.opts.always );
7417}
7418
7419jQuery.Animation = jQuery.extend( Animation, {
7420 tweener: function( props, callback ) {
7421 if ( jQuery.isFunction( props ) ) {
7422 callback = props;
7423 props = [ "*" ];
7424 } else {
7425 props = props.split(" ");
7426 }
7427
7428 var prop,
7429 index = 0,
7430 length = props.length;
7431
7432 for ( ; index < length ; index++ ) {
7433 prop = props[ index ];
7434 tweeners[ prop ] = tweeners[ prop ] || [];
7435 tweeners[ prop ].unshift( callback );
7436 }
7437 },
7438
7439 prefilter: function( callback, prepend ) {
7440 if ( prepend ) {
7441 animationPrefilters.unshift( callback );
7442 } else {
7443 animationPrefilters.push( callback );
7444 }
7445 }
7446});
7447
7448jQuery.speed = function( speed, easing, fn ) {
7449 var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
7450 complete: fn || !fn && easing ||
7451 jQuery.isFunction( speed ) && speed,
7452 duration: speed,
7453 easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing
7454 };
7455
7456 opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
7457 opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;
7458
7459 // normalize opt.queue - true/undefined/null -> "fx"
7460 if ( opt.queue == null || opt.queue === true ) {
7461 opt.queue = "fx";
7462 }
7463
7464 // Queueing
7465 opt.old = opt.complete;
7466
7467 opt.complete = function() {
7468 if ( jQuery.isFunction( opt.old ) ) {
7469 opt.old.call( this );
7470 }
7471
7472 if ( opt.queue ) {
7473 jQuery.dequeue( this, opt.queue );
7474 }
7475 };
7476
7477 return opt;
7478};
7479
7480jQuery.fn.extend({
7481 fadeTo: function( speed, to, easing, callback ) {
7482
7483 // show any hidden elements after setting opacity to 0
7484 return this.filter( isHidden ).css( "opacity", 0 ).show()
7485
7486 // animate to the value specified
7487 .end().animate({ opacity: to }, speed, easing, callback );
7488 },
7489 animate: function( prop, speed, easing, callback ) {
7490 var empty = jQuery.isEmptyObject( prop ),
7491 optall = jQuery.speed( speed, easing, callback ),
7492 doAnimation = function() {
7493 // Operate on a copy of prop so per-property easing won't be lost
7494 var anim = Animation( this, jQuery.extend( {}, prop ), optall );
7495
7496 // Empty animations, or finishing resolves immediately
7497 if ( empty || jQuery._data( this, "finish" ) ) {
7498 anim.stop( true );
7499 }
7500 };
7501 doAnimation.finish = doAnimation;
7502
7503 return empty || optall.queue === false ?
7504 this.each( doAnimation ) :
7505 this.queue( optall.queue, doAnimation );
7506 },
7507 stop: function( type, clearQueue, gotoEnd ) {
7508 var stopQueue = function( hooks ) {
7509 var stop = hooks.stop;
7510 delete hooks.stop;
7511 stop( gotoEnd );
7512 };
7513
7514 if ( typeof type !== "string" ) {
7515 gotoEnd = clearQueue;
7516 clearQueue = type;
7517 type = undefined;
7518 }
7519 if ( clearQueue && type !== false ) {
7520 this.queue( type || "fx", [] );
7521 }
7522
7523 return this.each(function() {
7524 var dequeue = true,
7525 index = type != null && type + "queueHooks",
7526 timers = jQuery.timers,
7527 data = jQuery._data( this );
7528
7529 if ( index ) {
7530 if ( data[ index ] && data[ index ].stop ) {
7531 stopQueue( data[ index ] );
7532 }
7533 } else {
7534 for ( index in data ) {
7535 if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {
7536 stopQueue( data[ index ] );
7537 }
7538 }
7539 }
7540
7541 for ( index = timers.length; index--; ) {
7542 if ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {
7543 timers[ index ].anim.stop( gotoEnd );
7544 dequeue = false;
7545 timers.splice( index, 1 );
7546 }
7547 }
7548
7549 // start the next in the queue if the last step wasn't forced
7550 // timers currently will call their complete callbacks, which will dequeue
7551 // but only if they were gotoEnd
7552 if ( dequeue || !gotoEnd ) {
7553 jQuery.dequeue( this, type );
7554 }
7555 });
7556 },
7557 finish: function( type ) {
7558 if ( type !== false ) {
7559 type = type || "fx";
7560 }
7561 return this.each(function() {
7562 var index,
7563 data = jQuery._data( this ),
7564 queue = data[ type + "queue" ],
7565 hooks = data[ type + "queueHooks" ],
7566 timers = jQuery.timers,
7567 length = queue ? queue.length : 0;
7568
7569 // enable finishing flag on private data
7570 data.finish = true;
7571
7572 // empty the queue first
7573 jQuery.queue( this, type, [] );
7574
7575 if ( hooks && hooks.stop ) {
7576 hooks.stop.call( this, true );
7577 }
7578
7579 // look for any active animations, and finish them
7580 for ( index = timers.length; index--; ) {
7581 if ( timers[ index ].elem === this && timers[ index ].queue === type ) {
7582 timers[ index ].anim.stop( true );
7583 timers.splice( index, 1 );
7584 }
7585 }
7586
7587 // look for any animations in the old queue and finish them
7588 for ( index = 0; index < length; index++ ) {
7589 if ( queue[ index ] && queue[ index ].finish ) {
7590 queue[ index ].finish.call( this );
7591 }
7592 }
7593
7594 // turn off finishing flag
7595 delete data.finish;
7596 });
7597 }
7598});
7599
7600jQuery.each([ "toggle", "show", "hide" ], function( i, name ) {
7601 var cssFn = jQuery.fn[ name ];
7602 jQuery.fn[ name ] = function( speed, easing, callback ) {
7603 return speed == null || typeof speed === "boolean" ?
7604 cssFn.apply( this, arguments ) :
7605 this.animate( genFx( name, true ), speed, easing, callback );
7606 };
7607});
7608
7609// Generate shortcuts for custom animations
7610jQuery.each({
7611 slideDown: genFx("show"),
7612 slideUp: genFx("hide"),
7613 slideToggle: genFx("toggle"),
7614 fadeIn: { opacity: "show" },
7615 fadeOut: { opacity: "hide" },
7616 fadeToggle: { opacity: "toggle" }
7617}, function( name, props ) {
7618 jQuery.fn[ name ] = function( speed, easing, callback ) {
7619 return this.animate( props, speed, easing, callback );
7620 };
7621});
7622
7623jQuery.timers = [];
7624jQuery.fx.tick = function() {
7625 var timer,
7626 timers = jQuery.timers,
7627 i = 0;
7628
7629 fxNow = jQuery.now();
7630
7631 for ( ; i < timers.length; i++ ) {
7632 timer = timers[ i ];
7633 // Checks the timer has not already been removed
7634 if ( !timer() && timers[ i ] === timer ) {
7635 timers.splice( i--, 1 );
7636 }
7637 }
7638
7639 if ( !timers.length ) {
7640 jQuery.fx.stop();
7641 }
7642 fxNow = undefined;
7643};
7644
7645jQuery.fx.timer = function( timer ) {
7646 jQuery.timers.push( timer );
7647 if ( timer() ) {
7648 jQuery.fx.start();
7649 } else {
7650 jQuery.timers.pop();
7651 }
7652};
7653
7654jQuery.fx.interval = 13;
7655
7656jQuery.fx.start = function() {
7657 if ( !timerId ) {
7658 timerId = setInterval( jQuery.fx.tick, jQuery.fx.interval );
7659 }
7660};
7661
7662jQuery.fx.stop = function() {
7663 clearInterval( timerId );
7664 timerId = null;
7665};
7666
7667jQuery.fx.speeds = {
7668 slow: 600,
7669 fast: 200,
7670 // Default speed
7671 _default: 400
7672};
7673
7674
7675// Based off of the plugin by Clint Helfers, with permission.
7676// http://blindsignals.com/index.php/2009/07/jquery-delay/
7677jQuery.fn.delay = function( time, type ) {
7678 time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
7679 type = type || "fx";
7680
7681 return this.queue( type, function( next, hooks ) {
7682 var timeout = setTimeout( next, time );
7683 hooks.stop = function() {
7684 clearTimeout( timeout );
7685 };
7686 });
7687};
7688
7689
7690(function() {
7691 // Minified: var a,b,c,d,e
7692 var input, div, select, a, opt;
7693
7694 // Setup
7695 div = document.createElement( "div" );
7696 div.setAttribute( "className", "t" );
7697 div.innerHTML = " <link/><table></table><a href='/a'>a</a><input type='checkbox'/>";
7698 a = div.getElementsByTagName("a")[ 0 ];
7699
7700 // First batch of tests.
7701 select = document.createElement("select");
7702 opt = select.appendChild( document.createElement("option") );
7703 input = div.getElementsByTagName("input")[ 0 ];
7704
7705 a.style.cssText = "top:1px";
7706
7707 // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)
7708 support.getSetAttribute = div.className !== "t";
7709
7710 // Get the style information from getAttribute
7711 // (IE uses .cssText instead)
7712 support.style = /top/.test( a.getAttribute("style") );
7713
7714 // Make sure that URLs aren't manipulated
7715 // (IE normalizes it by default)
7716 support.hrefNormalized = a.getAttribute("href") === "/a";
7717
7718 // Check the default checkbox/radio value ("" on WebKit; "on" elsewhere)
7719 support.checkOn = !!input.value;
7720
7721 // Make sure that a selected-by-default option has a working selected property.
7722 // (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
7723 support.optSelected = opt.selected;
7724
7725 // Tests for enctype support on a form (#6743)
7726 support.enctype = !!document.createElement("form").enctype;
7727
7728 // Make sure that the options inside disabled selects aren't marked as disabled
7729 // (WebKit marks them as disabled)
7730 select.disabled = true;
7731 support.optDisabled = !opt.disabled;
7732
7733 // Support: IE8 only
7734 // Check if we can trust getAttribute("value")
7735 input = document.createElement( "input" );
7736 input.setAttribute( "value", "" );
7737 support.input = input.getAttribute( "value" ) === "";
7738
7739 // Check if an input maintains its value after becoming a radio
7740 input.value = "t";
7741 input.setAttribute( "type", "radio" );
7742 support.radioValue = input.value === "t";
7743})();
7744
7745
7746var rreturn = /\r/g;
7747
7748jQuery.fn.extend({
7749 val: function( value ) {
7750 var hooks, ret, isFunction,
7751 elem = this[0];
7752
7753 if ( !arguments.length ) {
7754 if ( elem ) {
7755 hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];
7756
7757 if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
7758 return ret;
7759 }
7760
7761 ret = elem.value;
7762
7763 return typeof ret === "string" ?
7764 // handle most common string cases
7765 ret.replace(rreturn, "") :
7766 // handle cases where value is null/undef or number
7767 ret == null ? "" : ret;
7768 }
7769
7770 return;
7771 }
7772
7773 isFunction = jQuery.isFunction( value );
7774
7775 return this.each(function( i ) {
7776 var val;
7777
7778 if ( this.nodeType !== 1 ) {
7779 return;
7780 }
7781
7782 if ( isFunction ) {
7783 val = value.call( this, i, jQuery( this ).val() );
7784 } else {
7785 val = value;
7786 }
7787
7788 // Treat null/undefined as ""; convert numbers to string
7789 if ( val == null ) {
7790 val = "";
7791 } else if ( typeof val === "number" ) {
7792 val += "";
7793 } else if ( jQuery.isArray( val ) ) {
7794 val = jQuery.map( val, function( value ) {
7795 return value == null ? "" : value + "";
7796 });
7797 }
7798
7799 hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
7800
7801 // If set returns undefined, fall back to normal setting
7802 if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
7803 this.value = val;
7804 }
7805 });
7806 }
7807});
7808
7809jQuery.extend({
7810 valHooks: {
7811 option: {
7812 get: function( elem ) {
7813 var val = jQuery.find.attr( elem, "value" );
7814 return val != null ?
7815 val :
7816 // Support: IE10-11+
7817 // option.text throws exceptions (#14686, #14858)
7818 jQuery.trim( jQuery.text( elem ) );
7819 }
7820 },
7821 select: {
7822 get: function( elem ) {
7823 var value, option,
7824 options = elem.options,
7825 index = elem.selectedIndex,
7826 one = elem.type === "select-one" || index < 0,
7827 values = one ? null : [],
7828 max = one ? index + 1 : options.length,
7829 i = index < 0 ?
7830 max :
7831 one ? index : 0;
7832
7833 // Loop through all the selected options
7834 for ( ; i < max; i++ ) {
7835 option = options[ i ];
7836
7837 // oldIE doesn't update selected after form reset (#2551)
7838 if ( ( option.selected || i === index ) &&
7839 // Don't return options that are disabled or in a disabled optgroup
7840 ( support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null ) &&
7841 ( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) {
7842
7843 // Get the specific value for the option
7844 value = jQuery( option ).val();
7845
7846 // We don't need an array for one selects
7847 if ( one ) {
7848 return value;
7849 }
7850
7851 // Multi-Selects return an array
7852 values.push( value );
7853 }
7854 }
7855
7856 return values;
7857 },
7858
7859 set: function( elem, value ) {
7860 var optionSet, option,
7861 options = elem.options,
7862 values = jQuery.makeArray( value ),
7863 i = options.length;
7864
7865 while ( i-- ) {
7866 option = options[ i ];
7867
7868 if ( jQuery.inArray( jQuery.valHooks.option.get( option ), values ) >= 0 ) {
7869
7870 // Support: IE6
7871 // When new option element is added to select box we need to
7872 // force reflow of newly added node in order to workaround delay
7873 // of initialization properties
7874 try {
7875 option.selected = optionSet = true;
7876
7877 } catch ( _ ) {
7878
7879 // Will be executed only in IE6
7880 option.scrollHeight;
7881 }
7882
7883 } else {
7884 option.selected = false;
7885 }
7886 }
7887
7888 // Force browsers to behave consistently when non-matching value is set
7889 if ( !optionSet ) {
7890 elem.selectedIndex = -1;
7891 }
7892
7893 return options;
7894 }
7895 }
7896 }
7897});
7898
7899// Radios and checkboxes getter/setter
7900jQuery.each([ "radio", "checkbox" ], function() {
7901 jQuery.valHooks[ this ] = {
7902 set: function( elem, value ) {
7903 if ( jQuery.isArray( value ) ) {
7904 return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );
7905 }
7906 }
7907 };
7908 if ( !support.checkOn ) {
7909 jQuery.valHooks[ this ].get = function( elem ) {
7910 // Support: Webkit
7911 // "" is returned instead of "on" if a value isn't specified
7912 return elem.getAttribute("value") === null ? "on" : elem.value;
7913 };
7914 }
7915});
7916
7917
7918
7919
7920var nodeHook, boolHook,
7921 attrHandle = jQuery.expr.attrHandle,
7922 ruseDefault = /^(?:checked|selected)$/i,
7923 getSetAttribute = support.getSetAttribute,
7924 getSetInput = support.input;
7925
7926jQuery.fn.extend({
7927 attr: function( name, value ) {
7928 return access( this, jQuery.attr, name, value, arguments.length > 1 );
7929 },
7930
7931 removeAttr: function( name ) {
7932 return this.each(function() {
7933 jQuery.removeAttr( this, name );
7934 });
7935 }
7936});
7937
7938jQuery.extend({
7939 attr: function( elem, name, value ) {
7940 var hooks, ret,
7941 nType = elem.nodeType;
7942
7943 // don't get/set attributes on text, comment and attribute nodes
7944 if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
7945 return;
7946 }
7947
7948 // Fallback to prop when attributes are not supported
7949 if ( typeof elem.getAttribute === strundefined ) {
7950 return jQuery.prop( elem, name, value );
7951 }
7952
7953 // All attributes are lowercase
7954 // Grab necessary hook if one is defined
7955 if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {
7956 name = name.toLowerCase();
7957 hooks = jQuery.attrHooks[ name ] ||
7958 ( jQuery.expr.match.bool.test( name ) ? boolHook : nodeHook );
7959 }
7960
7961 if ( value !== undefined ) {
7962
7963 if ( value === null ) {
7964 jQuery.removeAttr( elem, name );
7965
7966 } else if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
7967 return ret;
7968
7969 } else {
7970 elem.setAttribute( name, value + "" );
7971 return value;
7972 }
7973
7974 } else if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
7975 return ret;
7976
7977 } else {
7978 ret = jQuery.find.attr( elem, name );
7979
7980 // Non-existent attributes return null, we normalize to undefined
7981 return ret == null ?
7982 undefined :
7983 ret;
7984 }
7985 },
7986
7987 removeAttr: function( elem, value ) {
7988 var name, propName,
7989 i = 0,
7990 attrNames = value && value.match( rnotwhite );
7991
7992 if ( attrNames && elem.nodeType === 1 ) {
7993 while ( (name = attrNames[i++]) ) {
7994 propName = jQuery.propFix[ name ] || name;
7995
7996 // Boolean attributes get special treatment (#10870)
7997 if ( jQuery.expr.match.bool.test( name ) ) {
7998 // Set corresponding property to false
7999 if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) {
8000 elem[ propName ] = false;
8001 // Support: IE<9
8002 // Also clear defaultChecked/defaultSelected (if appropriate)
8003 } else {
8004 elem[ jQuery.camelCase( "default-" + name ) ] =
8005 elem[ propName ] = false;
8006 }
8007
8008 // See #9699 for explanation of this approach (setting first, then removal)
8009 } else {
8010 jQuery.attr( elem, name, "" );
8011 }
8012
8013 elem.removeAttribute( getSetAttribute ? name : propName );
8014 }
8015 }
8016 },
8017
8018 attrHooks: {
8019 type: {
8020 set: function( elem, value ) {
8021 if ( !support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) {
8022 // Setting the type on a radio button after the value resets the value in IE6-9
8023 // Reset value to default in case type is set after value during creation
8024 var val = elem.value;
8025 elem.setAttribute( "type", value );
8026 if ( val ) {
8027 elem.value = val;
8028 }
8029 return value;
8030 }
8031 }
8032 }
8033 }
8034});
8035
8036// Hook for boolean attributes
8037boolHook = {
8038 set: function( elem, value, name ) {
8039 if ( value === false ) {
8040 // Remove boolean attributes when set to false
8041 jQuery.removeAttr( elem, name );
8042 } else if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) {
8043 // IE<8 needs the *property* name
8044 elem.setAttribute( !getSetAttribute && jQuery.propFix[ name ] || name, name );
8045
8046 // Use defaultChecked and defaultSelected for oldIE
8047 } else {
8048 elem[ jQuery.camelCase( "default-" + name ) ] = elem[ name ] = true;
8049 }
8050
8051 return name;
8052 }
8053};
8054
8055// Retrieve booleans specially
8056jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) {
8057
8058 var getter = attrHandle[ name ] || jQuery.find.attr;
8059
8060 attrHandle[ name ] = getSetInput && getSetAttribute || !ruseDefault.test( name ) ?
8061 function( elem, name, isXML ) {
8062 var ret, handle;
8063 if ( !isXML ) {
8064 // Avoid an infinite loop by temporarily removing this function from the getter
8065 handle = attrHandle[ name ];
8066 attrHandle[ name ] = ret;
8067 ret = getter( elem, name, isXML ) != null ?
8068 name.toLowerCase() :
8069 null;
8070 attrHandle[ name ] = handle;
8071 }
8072 return ret;
8073 } :
8074 function( elem, name, isXML ) {
8075 if ( !isXML ) {
8076 return elem[ jQuery.camelCase( "default-" + name ) ] ?
8077 name.toLowerCase() :
8078 null;
8079 }
8080 };
8081});
8082
8083// fix oldIE attroperties
8084if ( !getSetInput || !getSetAttribute ) {
8085 jQuery.attrHooks.value = {
8086 set: function( elem, value, name ) {
8087 if ( jQuery.nodeName( elem, "input" ) ) {
8088 // Does not return so that setAttribute is also used
8089 elem.defaultValue = value;
8090 } else {
8091 // Use nodeHook if defined (#1954); otherwise setAttribute is fine
8092 return nodeHook && nodeHook.set( elem, value, name );
8093 }
8094 }
8095 };
8096}
8097
8098// IE6/7 do not support getting/setting some attributes with get/setAttribute
8099if ( !getSetAttribute ) {
8100
8101 // Use this for any attribute in IE6/7
8102 // This fixes almost every IE6/7 issue
8103 nodeHook = {
8104 set: function( elem, value, name ) {
8105 // Set the existing or create a new attribute node
8106 var ret = elem.getAttributeNode( name );
8107 if ( !ret ) {
8108 elem.setAttributeNode(
8109 (ret = elem.ownerDocument.createAttribute( name ))
8110 );
8111 }
8112
8113 ret.value = value += "";
8114
8115 // Break association with cloned elements by also using setAttribute (#9646)
8116 if ( name === "value" || value === elem.getAttribute( name ) ) {
8117 return value;
8118 }
8119 }
8120 };
8121
8122 // Some attributes are constructed with empty-string values when not defined
8123 attrHandle.id = attrHandle.name = attrHandle.coords =
8124 function( elem, name, isXML ) {
8125 var ret;
8126 if ( !isXML ) {
8127 return (ret = elem.getAttributeNode( name )) && ret.value !== "" ?
8128 ret.value :
8129 null;
8130 }
8131 };
8132
8133 // Fixing value retrieval on a button requires this module
8134 jQuery.valHooks.button = {
8135 get: function( elem, name ) {
8136 var ret = elem.getAttributeNode( name );
8137 if ( ret && ret.specified ) {
8138 return ret.value;
8139 }
8140 },
8141 set: nodeHook.set
8142 };
8143
8144 // Set contenteditable to false on removals(#10429)
8145 // Setting to empty string throws an error as an invalid value
8146 jQuery.attrHooks.contenteditable = {
8147 set: function( elem, value, name ) {
8148 nodeHook.set( elem, value === "" ? false : value, name );
8149 }
8150 };
8151
8152 // Set width and height to auto instead of 0 on empty string( Bug #8150 )
8153 // This is for removals
8154 jQuery.each([ "width", "height" ], function( i, name ) {
8155 jQuery.attrHooks[ name ] = {
8156 set: function( elem, value ) {
8157 if ( value === "" ) {
8158 elem.setAttribute( name, "auto" );
8159 return value;
8160 }
8161 }
8162 };
8163 });
8164}
8165
8166if ( !support.style ) {
8167 jQuery.attrHooks.style = {
8168 get: function( elem ) {
8169 // Return undefined in the case of empty string
8170 // Note: IE uppercases css property names, but if we were to .toLowerCase()
8171 // .cssText, that would destroy case senstitivity in URL's, like in "background"
8172 return elem.style.cssText || undefined;
8173 },
8174 set: function( elem, value ) {
8175 return ( elem.style.cssText = value + "" );
8176 }
8177 };
8178}
8179
8180
8181
8182
8183var rfocusable = /^(?:input|select|textarea|button|object)$/i,
8184 rclickable = /^(?:a|area)$/i;
8185
8186jQuery.fn.extend({
8187 prop: function( name, value ) {
8188 return access( this, jQuery.prop, name, value, arguments.length > 1 );
8189 },
8190
8191 removeProp: function( name ) {
8192 name = jQuery.propFix[ name ] || name;
8193 return this.each(function() {
8194 // try/catch handles cases where IE balks (such as removing a property on window)
8195 try {
8196 this[ name ] = undefined;
8197 delete this[ name ];
8198 } catch( e ) {}
8199 });
8200 }
8201});
8202
8203jQuery.extend({
8204 propFix: {
8205 "for": "htmlFor",
8206 "class": "className"
8207 },
8208
8209 prop: function( elem, name, value ) {
8210 var ret, hooks, notxml,
8211 nType = elem.nodeType;
8212
8213 // don't get/set properties on text, comment and attribute nodes
8214 if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
8215 return;
8216 }
8217
8218 notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
8219
8220 if ( notxml ) {
8221 // Fix name and attach hooks
8222 name = jQuery.propFix[ name ] || name;
8223 hooks = jQuery.propHooks[ name ];
8224 }
8225
8226 if ( value !== undefined ) {
8227 return hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ?
8228 ret :
8229 ( elem[ name ] = value );
8230
8231 } else {
8232 return hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ?
8233 ret :
8234 elem[ name ];
8235 }
8236 },
8237
8238 propHooks: {
8239 tabIndex: {
8240 get: function( elem ) {
8241 // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
8242 // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
8243 // Use proper attribute retrieval(#12072)
8244 var tabindex = jQuery.find.attr( elem, "tabindex" );
8245
8246 return tabindex ?
8247 parseInt( tabindex, 10 ) :
8248 rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
8249 0 :
8250 -1;
8251 }
8252 }
8253 }
8254});
8255
8256// Some attributes require a special call on IE
8257// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
8258if ( !support.hrefNormalized ) {
8259 // href/src property should get the full normalized URL (#10299/#12915)
8260 jQuery.each([ "href", "src" ], function( i, name ) {
8261 jQuery.propHooks[ name ] = {
8262 get: function( elem ) {
8263 return elem.getAttribute( name, 4 );
8264 }
8265 };
8266 });
8267}
8268
8269// Support: Safari, IE9+
8270// mis-reports the default selected property of an option
8271// Accessing the parent's selectedIndex property fixes it
8272if ( !support.optSelected ) {
8273 jQuery.propHooks.selected = {
8274 get: function( elem ) {
8275 var parent = elem.parentNode;
8276
8277 if ( parent ) {
8278 parent.selectedIndex;
8279
8280 // Make sure that it also works with optgroups, see #5701
8281 if ( parent.parentNode ) {
8282 parent.parentNode.selectedIndex;
8283 }
8284 }
8285 return null;
8286 }
8287 };
8288}
8289
8290jQuery.each([
8291 "tabIndex",
8292 "readOnly",
8293 "maxLength",
8294 "cellSpacing",
8295 "cellPadding",
8296 "rowSpan",
8297 "colSpan",
8298 "useMap",
8299 "frameBorder",
8300 "contentEditable"
8301], function() {
8302 jQuery.propFix[ this.toLowerCase() ] = this;
8303});
8304
8305// IE6/7 call enctype encoding
8306if ( !support.enctype ) {
8307 jQuery.propFix.enctype = "encoding";
8308}
8309
8310
8311
8312
8313var rclass = /[\t\r\n\f]/g;
8314
8315jQuery.fn.extend({
8316 addClass: function( value ) {
8317 var classes, elem, cur, clazz, j, finalValue,
8318 i = 0,
8319 len = this.length,
8320 proceed = typeof value === "string" && value;
8321
8322 if ( jQuery.isFunction( value ) ) {
8323 return this.each(function( j ) {
8324 jQuery( this ).addClass( value.call( this, j, this.className ) );
8325 });
8326 }
8327
8328 if ( proceed ) {
8329 // The disjunction here is for better compressibility (see removeClass)
8330 classes = ( value || "" ).match( rnotwhite ) || [];
8331
8332 for ( ; i < len; i++ ) {
8333 elem = this[ i ];
8334 cur = elem.nodeType === 1 && ( elem.className ?
8335 ( " " + elem.className + " " ).replace( rclass, " " ) :
8336 " "
8337 );
8338
8339 if ( cur ) {
8340 j = 0;
8341 while ( (clazz = classes[j++]) ) {
8342 if ( cur.indexOf( " " + clazz + " " ) < 0 ) {
8343 cur += clazz + " ";
8344 }
8345 }
8346
8347 // only assign if different to avoid unneeded rendering.
8348 finalValue = jQuery.trim( cur );
8349 if ( elem.className !== finalValue ) {
8350 elem.className = finalValue;
8351 }
8352 }
8353 }
8354 }
8355
8356 return this;
8357 },
8358
8359 removeClass: function( value ) {
8360 var classes, elem, cur, clazz, j, finalValue,
8361 i = 0,
8362 len = this.length,
8363 proceed = arguments.length === 0 || typeof value === "string" && value;
8364
8365 if ( jQuery.isFunction( value ) ) {
8366 return this.each(function( j ) {
8367 jQuery( this ).removeClass( value.call( this, j, this.className ) );
8368 });
8369 }
8370 if ( proceed ) {
8371 classes = ( value || "" ).match( rnotwhite ) || [];
8372
8373 for ( ; i < len; i++ ) {
8374 elem = this[ i ];
8375 // This expression is here for better compressibility (see addClass)
8376 cur = elem.nodeType === 1 && ( elem.className ?
8377 ( " " + elem.className + " " ).replace( rclass, " " ) :
8378 ""
8379 );
8380
8381 if ( cur ) {
8382 j = 0;
8383 while ( (clazz = classes[j++]) ) {
8384 // Remove *all* instances
8385 while ( cur.indexOf( " " + clazz + " " ) >= 0 ) {
8386 cur = cur.replace( " " + clazz + " ", " " );
8387 }
8388 }
8389
8390 // only assign if different to avoid unneeded rendering.
8391 finalValue = value ? jQuery.trim( cur ) : "";
8392 if ( elem.className !== finalValue ) {
8393 elem.className = finalValue;
8394 }
8395 }
8396 }
8397 }
8398
8399 return this;
8400 },
8401
8402 toggleClass: function( value, stateVal ) {
8403 var type = typeof value;
8404
8405 if ( typeof stateVal === "boolean" && type === "string" ) {
8406 return stateVal ? this.addClass( value ) : this.removeClass( value );
8407 }
8408
8409 if ( jQuery.isFunction( value ) ) {
8410 return this.each(function( i ) {
8411 jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );
8412 });
8413 }
8414
8415 return this.each(function() {
8416 if ( type === "string" ) {
8417 // toggle individual class names
8418 var className,
8419 i = 0,
8420 self = jQuery( this ),
8421 classNames = value.match( rnotwhite ) || [];
8422
8423 while ( (className = classNames[ i++ ]) ) {
8424 // check each className given, space separated list
8425 if ( self.hasClass( className ) ) {
8426 self.removeClass( className );
8427 } else {
8428 self.addClass( className );
8429 }
8430 }
8431
8432 // Toggle whole class name
8433 } else if ( type === strundefined || type === "boolean" ) {
8434 if ( this.className ) {
8435 // store className if set
8436 jQuery._data( this, "__className__", this.className );
8437 }
8438
8439 // If the element has a class name or if we're passed "false",
8440 // then remove the whole classname (if there was one, the above saved it).
8441 // Otherwise bring back whatever was previously saved (if anything),
8442 // falling back to the empty string if nothing was stored.
8443 this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || "";
8444 }
8445 });
8446 },
8447
8448 hasClass: function( selector ) {
8449 var className = " " + selector + " ",
8450 i = 0,
8451 l = this.length;
8452 for ( ; i < l; i++ ) {
8453 if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) {
8454 return true;
8455 }
8456 }
8457
8458 return false;
8459 }
8460});
8461
8462
8463
8464
8465// Return jQuery for attributes-only inclusion
8466
8467
8468jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
8469 "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
8470 "change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) {
8471
8472 // Handle event binding
8473 jQuery.fn[ name ] = function( data, fn ) {
8474 return arguments.length > 0 ?
8475 this.on( name, null, data, fn ) :
8476 this.trigger( name );
8477 };
8478});
8479
8480jQuery.fn.extend({
8481 hover: function( fnOver, fnOut ) {
8482 return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
8483 },
8484
8485 bind: function( types, data, fn ) {
8486 return this.on( types, null, data, fn );
8487 },
8488 unbind: function( types, fn ) {
8489 return this.off( types, null, fn );
8490 },
8491
8492 delegate: function( selector, types, data, fn ) {
8493 return this.on( types, selector, data, fn );
8494 },
8495 undelegate: function( selector, types, fn ) {
8496 // ( namespace ) or ( selector, types [, fn] )
8497 return arguments.length === 1 ? this.off( selector, "**" ) : this.off( types, selector || "**", fn );
8498 }
8499});
8500
8501
8502var nonce = jQuery.now();
8503
8504var rquery = (/\?/);
8505
8506
8507
8508var rvalidtokens = /(,)|(\[|{)|(}|])|"(?:[^"\\\r\n]|\\["\\\/bfnrt]|\\u[\da-fA-F]{4})*"\s*:?|true|false|null|-?(?!0\d)\d+(?:\.\d+|)(?:[eE][+-]?\d+|)/g;
8509
8510jQuery.parseJSON = function( data ) {
8511 // Attempt to parse using the native JSON parser first
8512 if ( window.JSON && window.JSON.parse ) {
8513 // Support: Android 2.3
8514 // Workaround failure to string-cast null input
8515 return window.JSON.parse( data + "" );
8516 }
8517
8518 var requireNonComma,
8519 depth = null,
8520 str = jQuery.trim( data + "" );
8521
8522 // Guard against invalid (and possibly dangerous) input by ensuring that nothing remains
8523 // after removing valid tokens
8524 return str && !jQuery.trim( str.replace( rvalidtokens, function( token, comma, open, close ) {
8525
8526 // Force termination if we see a misplaced comma
8527 if ( requireNonComma && comma ) {
8528 depth = 0;
8529 }
8530
8531 // Perform no more replacements after returning to outermost depth
8532 if ( depth === 0 ) {
8533 return token;
8534 }
8535
8536 // Commas must not follow "[", "{", or ","
8537 requireNonComma = open || comma;
8538
8539 // Determine new depth
8540 // array/object open ("[" or "{"): depth += true - false (increment)
8541 // array/object close ("]" or "}"): depth += false - true (decrement)
8542 // other cases ("," or primitive): depth += true - true (numeric cast)
8543 depth += !close - !open;
8544
8545 // Remove this token
8546 return "";
8547 }) ) ?
8548 ( Function( "return " + str ) )() :
8549 jQuery.error( "Invalid JSON: " + data );
8550};
8551
8552
8553// Cross-browser xml parsing
8554jQuery.parseXML = function( data ) {
8555 var xml, tmp;
8556 if ( !data || typeof data !== "string" ) {
8557 return null;
8558 }
8559 try {
8560 if ( window.DOMParser ) { // Standard
8561 tmp = new DOMParser();
8562 xml = tmp.parseFromString( data, "text/xml" );
8563 } else { // IE
8564 xml = new ActiveXObject( "Microsoft.XMLDOM" );
8565 xml.async = "false";
8566 xml.loadXML( data );
8567 }
8568 } catch( e ) {
8569 xml = undefined;
8570 }
8571 if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) {
8572 jQuery.error( "Invalid XML: " + data );
8573 }
8574 return xml;
8575};
8576
8577
8578var
8579 // Document location
8580 ajaxLocParts,
8581 ajaxLocation,
8582
8583 rhash = /#.*$/,
8584 rts = /([?&])_=[^&]*/,
8585 rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, // IE leaves an \r character at EOL
8586 // #7653, #8125, #8152: local protocol detection
8587 rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,
8588 rnoContent = /^(?:GET|HEAD)$/,
8589 rprotocol = /^\/\//,
8590 rurl = /^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/,
8591
8592 /* Prefilters
8593 * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
8594 * 2) These are called:
8595 * - BEFORE asking for a transport
8596 * - AFTER param serialization (s.data is a string if s.processData is true)
8597 * 3) key is the dataType
8598 * 4) the catchall symbol "*" can be used
8599 * 5) execution will start with transport dataType and THEN continue down to "*" if needed
8600 */
8601 prefilters = {},
8602
8603 /* Transports bindings
8604 * 1) key is the dataType
8605 * 2) the catchall symbol "*" can be used
8606 * 3) selection will start with transport dataType and THEN go to "*" if needed
8607 */
8608 transports = {},
8609
8610 // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
8611 allTypes = "*/".concat("*");
8612
8613// #8138, IE may throw an exception when accessing
8614// a field from window.location if document.domain has been set
8615try {
8616 ajaxLocation = location.href;
8617} catch( e ) {
8618 // Use the href attribute of an A element
8619 // since IE will modify it given document.location
8620 ajaxLocation = document.createElement( "a" );
8621 ajaxLocation.href = "";
8622 ajaxLocation = ajaxLocation.href;
8623}
8624
8625// Segment location into parts
8626ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];
8627
8628// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
8629function addToPrefiltersOrTransports( structure ) {
8630
8631 // dataTypeExpression is optional and defaults to "*"
8632 return function( dataTypeExpression, func ) {
8633
8634 if ( typeof dataTypeExpression !== "string" ) {
8635 func = dataTypeExpression;
8636 dataTypeExpression = "*";
8637 }
8638
8639 var dataType,
8640 i = 0,
8641 dataTypes = dataTypeExpression.toLowerCase().match( rnotwhite ) || [];
8642
8643 if ( jQuery.isFunction( func ) ) {
8644 // For each dataType in the dataTypeExpression
8645 while ( (dataType = dataTypes[i++]) ) {
8646 // Prepend if requested
8647 if ( dataType.charAt( 0 ) === "+" ) {
8648 dataType = dataType.slice( 1 ) || "*";
8649 (structure[ dataType ] = structure[ dataType ] || []).unshift( func );
8650
8651 // Otherwise append
8652 } else {
8653 (structure[ dataType ] = structure[ dataType ] || []).push( func );
8654 }
8655 }
8656 }
8657 };
8658}
8659
8660// Base inspection function for prefilters and transports
8661function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {
8662
8663 var inspected = {},
8664 seekingTransport = ( structure === transports );
8665
8666 function inspect( dataType ) {
8667 var selected;
8668 inspected[ dataType ] = true;
8669 jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {
8670 var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );
8671 if ( typeof dataTypeOrTransport === "string" && !seekingTransport && !inspected[ dataTypeOrTransport ] ) {
8672 options.dataTypes.unshift( dataTypeOrTransport );
8673 inspect( dataTypeOrTransport );
8674 return false;
8675 } else if ( seekingTransport ) {
8676 return !( selected = dataTypeOrTransport );
8677 }
8678 });
8679 return selected;
8680 }
8681
8682 return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" );
8683}
8684
8685// A special extend for ajax options
8686// that takes "flat" options (not to be deep extended)
8687// Fixes #9887
8688function ajaxExtend( target, src ) {
8689 var deep, key,
8690 flatOptions = jQuery.ajaxSettings.flatOptions || {};
8691
8692 for ( key in src ) {
8693 if ( src[ key ] !== undefined ) {
8694 ( flatOptions[ key ] ? target : ( deep || (deep = {}) ) )[ key ] = src[ key ];
8695 }
8696 }
8697 if ( deep ) {
8698 jQuery.extend( true, target, deep );
8699 }
8700
8701 return target;
8702}
8703
8704/* Handles responses to an ajax request:
8705 * - finds the right dataType (mediates between content-type and expected dataType)
8706 * - returns the corresponding response
8707 */
8708function ajaxHandleResponses( s, jqXHR, responses ) {
8709 var firstDataType, ct, finalDataType, type,
8710 contents = s.contents,
8711 dataTypes = s.dataTypes;
8712
8713 // Remove auto dataType and get content-type in the process
8714 while ( dataTypes[ 0 ] === "*" ) {
8715 dataTypes.shift();
8716 if ( ct === undefined ) {
8717 ct = s.mimeType || jqXHR.getResponseHeader("Content-Type");
8718 }
8719 }
8720
8721 // Check if we're dealing with a known content-type
8722 if ( ct ) {
8723 for ( type in contents ) {
8724 if ( contents[ type ] && contents[ type ].test( ct ) ) {
8725 dataTypes.unshift( type );
8726 break;
8727 }
8728 }
8729 }
8730
8731 // Check to see if we have a response for the expected dataType
8732 if ( dataTypes[ 0 ] in responses ) {
8733 finalDataType = dataTypes[ 0 ];
8734 } else {
8735 // Try convertible dataTypes
8736 for ( type in responses ) {
8737 if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) {
8738 finalDataType = type;
8739 break;
8740 }
8741 if ( !firstDataType ) {
8742 firstDataType = type;
8743 }
8744 }
8745 // Or just use first one
8746 finalDataType = finalDataType || firstDataType;
8747 }
8748
8749 // If we found a dataType
8750 // We add the dataType to the list if needed
8751 // and return the corresponding response
8752 if ( finalDataType ) {
8753 if ( finalDataType !== dataTypes[ 0 ] ) {
8754 dataTypes.unshift( finalDataType );
8755 }
8756 return responses[ finalDataType ];
8757 }
8758}
8759
8760/* Chain conversions given the request and the original response
8761 * Also sets the responseXXX fields on the jqXHR instance
8762 */
8763function ajaxConvert( s, response, jqXHR, isSuccess ) {
8764 var conv2, current, conv, tmp, prev,
8765 converters = {},
8766 // Work with a copy of dataTypes in case we need to modify it for conversion
8767 dataTypes = s.dataTypes.slice();
8768
8769 // Create converters map with lowercased keys
8770 if ( dataTypes[ 1 ] ) {
8771 for ( conv in s.converters ) {
8772 converters[ conv.toLowerCase() ] = s.converters[ conv ];
8773 }
8774 }
8775
8776 current = dataTypes.shift();
8777
8778 // Convert to each sequential dataType
8779 while ( current ) {
8780
8781 if ( s.responseFields[ current ] ) {
8782 jqXHR[ s.responseFields[ current ] ] = response;
8783 }
8784
8785 // Apply the dataFilter if provided
8786 if ( !prev && isSuccess && s.dataFilter ) {
8787 response = s.dataFilter( response, s.dataType );
8788 }
8789
8790 prev = current;
8791 current = dataTypes.shift();
8792
8793 if ( current ) {
8794
8795 // There's only work to do if current dataType is non-auto
8796 if ( current === "*" ) {
8797
8798 current = prev;
8799
8800 // Convert response if prev dataType is non-auto and differs from current
8801 } else if ( prev !== "*" && prev !== current ) {
8802
8803 // Seek a direct converter
8804 conv = converters[ prev + " " + current ] || converters[ "* " + current ];
8805
8806 // If none found, seek a pair
8807 if ( !conv ) {
8808 for ( conv2 in converters ) {
8809
8810 // If conv2 outputs current
8811 tmp = conv2.split( " " );
8812 if ( tmp[ 1 ] === current ) {
8813
8814 // If prev can be converted to accepted input
8815 conv = converters[ prev + " " + tmp[ 0 ] ] ||
8816 converters[ "* " + tmp[ 0 ] ];
8817 if ( conv ) {
8818 // Condense equivalence converters
8819 if ( conv === true ) {
8820 conv = converters[ conv2 ];
8821
8822 // Otherwise, insert the intermediate dataType
8823 } else if ( converters[ conv2 ] !== true ) {
8824 current = tmp[ 0 ];
8825 dataTypes.unshift( tmp[ 1 ] );
8826 }
8827 break;
8828 }
8829 }
8830 }
8831 }
8832
8833 // Apply converter (if not an equivalence)
8834 if ( conv !== true ) {
8835
8836 // Unless errors are allowed to bubble, catch and return them
8837 if ( conv && s[ "throws" ] ) {
8838 response = conv( response );
8839 } else {
8840 try {
8841 response = conv( response );
8842 } catch ( e ) {
8843 return { state: "parsererror", error: conv ? e : "No conversion from " + prev + " to " + current };
8844 }
8845 }
8846 }
8847 }
8848 }
8849 }
8850
8851 return { state: "success", data: response };
8852}
8853
8854jQuery.extend({
8855
8856 // Counter for holding the number of active queries
8857 active: 0,
8858
8859 // Last-Modified header cache for next request
8860 lastModified: {},
8861 etag: {},
8862
8863 ajaxSettings: {
8864 url: ajaxLocation,
8865 type: "GET",
8866 isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),
8867 global: true,
8868 processData: true,
8869 async: true,
8870 contentType: "application/x-www-form-urlencoded; charset=UTF-8",
8871 /*
8872 timeout: 0,
8873 data: null,
8874 dataType: null,
8875 username: null,
8876 password: null,
8877 cache: null,
8878 throws: false,
8879 traditional: false,
8880 headers: {},
8881 */
8882
8883 accepts: {
8884 "*": allTypes,
8885 text: "text/plain",
8886 html: "text/html",
8887 xml: "application/xml, text/xml",
8888 json: "application/json, text/javascript"
8889 },
8890
8891 contents: {
8892 xml: /xml/,
8893 html: /html/,
8894 json: /json/
8895 },
8896
8897 responseFields: {
8898 xml: "responseXML",
8899 text: "responseText",
8900 json: "responseJSON"
8901 },
8902
8903 // Data converters
8904 // Keys separate source (or catchall "*") and destination types with a single space
8905 converters: {
8906
8907 // Convert anything to text
8908 "* text": String,
8909
8910 // Text to html (true = no transformation)
8911 "text html": true,
8912
8913 // Evaluate text as a json expression
8914 "text json": jQuery.parseJSON,
8915
8916 // Parse text as xml
8917 "text xml": jQuery.parseXML
8918 },
8919
8920 // For options that shouldn't be deep extended:
8921 // you can add your own custom options here if
8922 // and when you create one that shouldn't be
8923 // deep extended (see ajaxExtend)
8924 flatOptions: {
8925 url: true,
8926 context: true
8927 }
8928 },
8929
8930 // Creates a full fledged settings object into target
8931 // with both ajaxSettings and settings fields.
8932 // If target is omitted, writes into ajaxSettings.
8933 ajaxSetup: function( target, settings ) {
8934 return settings ?
8935
8936 // Building a settings object
8937 ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :
8938
8939 // Extending ajaxSettings
8940 ajaxExtend( jQuery.ajaxSettings, target );
8941 },
8942
8943 ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
8944 ajaxTransport: addToPrefiltersOrTransports( transports ),
8945
8946 // Main method
8947 ajax: function( url, options ) {
8948
8949 // If url is an object, simulate pre-1.5 signature
8950 if ( typeof url === "object" ) {
8951 options = url;
8952 url = undefined;
8953 }
8954
8955 // Force options to be an object
8956 options = options || {};
8957
8958 var // Cross-domain detection vars
8959 parts,
8960 // Loop variable
8961 i,
8962 // URL without anti-cache param
8963 cacheURL,
8964 // Response headers as string
8965 responseHeadersString,
8966 // timeout handle
8967 timeoutTimer,
8968
8969 // To know if global events are to be dispatched
8970 fireGlobals,
8971
8972 transport,
8973 // Response headers
8974 responseHeaders,
8975 // Create the final options object
8976 s = jQuery.ajaxSetup( {}, options ),
8977 // Callbacks context
8978 callbackContext = s.context || s,
8979 // Context for global events is callbackContext if it is a DOM node or jQuery collection
8980 globalEventContext = s.context && ( callbackContext.nodeType || callbackContext.jquery ) ?
8981 jQuery( callbackContext ) :
8982 jQuery.event,
8983 // Deferreds
8984 deferred = jQuery.Deferred(),
8985 completeDeferred = jQuery.Callbacks("once memory"),
8986 // Status-dependent callbacks
8987 statusCode = s.statusCode || {},
8988 // Headers (they are sent all at once)
8989 requestHeaders = {},
8990 requestHeadersNames = {},
8991 // The jqXHR state
8992 state = 0,
8993 // Default abort message
8994 strAbort = "canceled",
8995 // Fake xhr
8996 jqXHR = {
8997 readyState: 0,
8998
8999 // Builds headers hashtable if needed
9000 getResponseHeader: function( key ) {
9001 var match;
9002 if ( state === 2 ) {
9003 if ( !responseHeaders ) {
9004 responseHeaders = {};
9005 while ( (match = rheaders.exec( responseHeadersString )) ) {
9006 responseHeaders[ match[1].toLowerCase() ] = match[ 2 ];
9007 }
9008 }
9009 match = responseHeaders[ key.toLowerCase() ];
9010 }
9011 return match == null ? null : match;
9012 },
9013
9014 // Raw string
9015 getAllResponseHeaders: function() {
9016 return state === 2 ? responseHeadersString : null;
9017 },
9018
9019 // Caches the header
9020 setRequestHeader: function( name, value ) {
9021 var lname = name.toLowerCase();
9022 if ( !state ) {
9023 name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;
9024 requestHeaders[ name ] = value;
9025 }
9026 return this;
9027 },
9028
9029 // Overrides response content-type header
9030 overrideMimeType: function( type ) {
9031 if ( !state ) {
9032 s.mimeType = type;
9033 }
9034 return this;
9035 },
9036
9037 // Status-dependent callbacks
9038 statusCode: function( map ) {
9039 var code;
9040 if ( map ) {
9041 if ( state < 2 ) {
9042 for ( code in map ) {
9043 // Lazy-add the new callback in a way that preserves old ones
9044 statusCode[ code ] = [ statusCode[ code ], map[ code ] ];
9045 }
9046 } else {
9047 // Execute the appropriate callbacks
9048 jqXHR.always( map[ jqXHR.status ] );
9049 }
9050 }
9051 return this;
9052 },
9053
9054 // Cancel the request
9055 abort: function( statusText ) {
9056 var finalText = statusText || strAbort;
9057 if ( transport ) {
9058 transport.abort( finalText );
9059 }
9060 done( 0, finalText );
9061 return this;
9062 }
9063 };
9064
9065 // Attach deferreds
9066 deferred.promise( jqXHR ).complete = completeDeferred.add;
9067 jqXHR.success = jqXHR.done;
9068 jqXHR.error = jqXHR.fail;
9069
9070 // Remove hash character (#7531: and string promotion)
9071 // Add protocol if not provided (#5866: IE7 issue with protocol-less urls)
9072 // Handle falsy url in the settings object (#10093: consistency with old signature)
9073 // We also use the url parameter if available
9074 s.url = ( ( url || s.url || ajaxLocation ) + "" ).replace( rhash, "" ).replace( rprotocol, ajaxLocParts[ 1 ] + "//" );
9075
9076 // Alias method option to type as per ticket #12004
9077 s.type = options.method || options.type || s.method || s.type;
9078
9079 // Extract dataTypes list
9080 s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().match( rnotwhite ) || [ "" ];
9081
9082 // A cross-domain request is in order when we have a protocol:host:port mismatch
9083 if ( s.crossDomain == null ) {
9084 parts = rurl.exec( s.url.toLowerCase() );
9085 s.crossDomain = !!( parts &&
9086 ( parts[ 1 ] !== ajaxLocParts[ 1 ] || parts[ 2 ] !== ajaxLocParts[ 2 ] ||
9087 ( parts[ 3 ] || ( parts[ 1 ] === "http:" ? "80" : "443" ) ) !==
9088 ( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? "80" : "443" ) ) )
9089 );
9090 }
9091
9092 // Convert data if not already a string
9093 if ( s.data && s.processData && typeof s.data !== "string" ) {
9094 s.data = jQuery.param( s.data, s.traditional );
9095 }
9096
9097 // Apply prefilters
9098 inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
9099
9100 // If request was aborted inside a prefilter, stop there
9101 if ( state === 2 ) {
9102 return jqXHR;
9103 }
9104
9105 // We can fire global events as of now if asked to
9106 // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118)
9107 fireGlobals = jQuery.event && s.global;
9108
9109 // Watch for a new set of requests
9110 if ( fireGlobals && jQuery.active++ === 0 ) {
9111 jQuery.event.trigger("ajaxStart");
9112 }
9113
9114 // Uppercase the type
9115 s.type = s.type.toUpperCase();
9116
9117 // Determine if request has content
9118 s.hasContent = !rnoContent.test( s.type );
9119
9120 // Save the URL in case we're toying with the If-Modified-Since
9121 // and/or If-None-Match header later on
9122 cacheURL = s.url;
9123
9124 // More options handling for requests with no content
9125 if ( !s.hasContent ) {
9126
9127 // If data is available, append data to url
9128 if ( s.data ) {
9129 cacheURL = ( s.url += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data );
9130 // #9682: remove data so that it's not used in an eventual retry
9131 delete s.data;
9132 }
9133
9134 // Add anti-cache in url if needed
9135 if ( s.cache === false ) {
9136 s.url = rts.test( cacheURL ) ?
9137
9138 // If there is already a '_' parameter, set its value
9139 cacheURL.replace( rts, "$1_=" + nonce++ ) :
9140
9141 // Otherwise add one to the end
9142 cacheURL + ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + nonce++;
9143 }
9144 }
9145
9146 // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
9147 if ( s.ifModified ) {
9148 if ( jQuery.lastModified[ cacheURL ] ) {
9149 jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] );
9150 }
9151 if ( jQuery.etag[ cacheURL ] ) {
9152 jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] );
9153 }
9154 }
9155
9156 // Set the correct header, if data is being sent
9157 if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
9158 jqXHR.setRequestHeader( "Content-Type", s.contentType );
9159 }
9160
9161 // Set the Accepts header for the server, depending on the dataType
9162 jqXHR.setRequestHeader(
9163 "Accept",
9164 s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?
9165 s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
9166 s.accepts[ "*" ]
9167 );
9168
9169 // Check for headers option
9170 for ( i in s.headers ) {
9171 jqXHR.setRequestHeader( i, s.headers[ i ] );
9172 }
9173
9174 // Allow custom headers/mimetypes and early abort
9175 if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {
9176 // Abort if not done already and return
9177 return jqXHR.abort();
9178 }
9179
9180 // aborting is no longer a cancellation
9181 strAbort = "abort";
9182
9183 // Install callbacks on deferreds
9184 for ( i in { success: 1, error: 1, complete: 1 } ) {
9185 jqXHR[ i ]( s[ i ] );
9186 }
9187
9188 // Get transport
9189 transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
9190
9191 // If no transport, we auto-abort
9192 if ( !transport ) {
9193 done( -1, "No Transport" );
9194 } else {
9195 jqXHR.readyState = 1;
9196
9197 // Send global event
9198 if ( fireGlobals ) {
9199 globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
9200 }
9201 // Timeout
9202 if ( s.async && s.timeout > 0 ) {
9203 timeoutTimer = setTimeout(function() {
9204 jqXHR.abort("timeout");
9205 }, s.timeout );
9206 }
9207
9208 try {
9209 state = 1;
9210 transport.send( requestHeaders, done );
9211 } catch ( e ) {
9212 // Propagate exception as error if not done
9213 if ( state < 2 ) {
9214 done( -1, e );
9215 // Simply rethrow otherwise
9216 } else {
9217 throw e;
9218 }
9219 }
9220 }
9221
9222 // Callback for when everything is done
9223 function done( status, nativeStatusText, responses, headers ) {
9224 var isSuccess, success, error, response, modified,
9225 statusText = nativeStatusText;
9226
9227 // Called once
9228 if ( state === 2 ) {
9229 return;
9230 }
9231
9232 // State is "done" now
9233 state = 2;
9234
9235 // Clear timeout if it exists
9236 if ( timeoutTimer ) {
9237 clearTimeout( timeoutTimer );
9238 }
9239
9240 // Dereference transport for early garbage collection
9241 // (no matter how long the jqXHR object will be used)
9242 transport = undefined;
9243
9244 // Cache response headers
9245 responseHeadersString = headers || "";
9246
9247 // Set readyState
9248 jqXHR.readyState = status > 0 ? 4 : 0;
9249
9250 // Determine if successful
9251 isSuccess = status >= 200 && status < 300 || status === 304;
9252
9253 // Get response data
9254 if ( responses ) {
9255 response = ajaxHandleResponses( s, jqXHR, responses );
9256 }
9257
9258 // Convert no matter what (that way responseXXX fields are always set)
9259 response = ajaxConvert( s, response, jqXHR, isSuccess );
9260
9261 // If successful, handle type chaining
9262 if ( isSuccess ) {
9263
9264 // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
9265 if ( s.ifModified ) {
9266 modified = jqXHR.getResponseHeader("Last-Modified");
9267 if ( modified ) {
9268 jQuery.lastModified[ cacheURL ] = modified;
9269 }
9270 modified = jqXHR.getResponseHeader("etag");
9271 if ( modified ) {
9272 jQuery.etag[ cacheURL ] = modified;
9273 }
9274 }
9275
9276 // if no content
9277 if ( status === 204 || s.type === "HEAD" ) {
9278 statusText = "nocontent";
9279
9280 // if not modified
9281 } else if ( status === 304 ) {
9282 statusText = "notmodified";
9283
9284 // If we have data, let's convert it
9285 } else {
9286 statusText = response.state;
9287 success = response.data;
9288 error = response.error;
9289 isSuccess = !error;
9290 }
9291 } else {
9292 // We extract error from statusText
9293 // then normalize statusText and status for non-aborts
9294 error = statusText;
9295 if ( status || !statusText ) {
9296 statusText = "error";
9297 if ( status < 0 ) {
9298 status = 0;
9299 }
9300 }
9301 }
9302
9303 // Set data for the fake xhr object
9304 jqXHR.status = status;
9305 jqXHR.statusText = ( nativeStatusText || statusText ) + "";
9306
9307 // Success/Error
9308 if ( isSuccess ) {
9309 deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
9310 } else {
9311 deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
9312 }
9313
9314 // Status-dependent callbacks
9315 jqXHR.statusCode( statusCode );
9316 statusCode = undefined;
9317
9318 if ( fireGlobals ) {
9319 globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError",
9320 [ jqXHR, s, isSuccess ? success : error ] );
9321 }
9322
9323 // Complete
9324 completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );
9325
9326 if ( fireGlobals ) {
9327 globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
9328 // Handle the global AJAX counter
9329 if ( !( --jQuery.active ) ) {
9330 jQuery.event.trigger("ajaxStop");
9331 }
9332 }
9333 }
9334
9335 return jqXHR;
9336 },
9337
9338 getJSON: function( url, data, callback ) {
9339 return jQuery.get( url, data, callback, "json" );
9340 },
9341
9342 getScript: function( url, callback ) {
9343 return jQuery.get( url, undefined, callback, "script" );
9344 }
9345});
9346
9347jQuery.each( [ "get", "post" ], function( i, method ) {
9348 jQuery[ method ] = function( url, data, callback, type ) {
9349 // shift arguments if data argument was omitted
9350 if ( jQuery.isFunction( data ) ) {
9351 type = type || callback;
9352 callback = data;
9353 data = undefined;
9354 }
9355
9356 return jQuery.ajax({
9357 url: url,
9358 type: method,
9359 dataType: type,
9360 data: data,
9361 success: callback
9362 });
9363 };
9364});
9365
9366
9367jQuery._evalUrl = function( url ) {
9368 return jQuery.ajax({
9369 url: url,
9370 type: "GET",
9371 dataType: "script",
9372 async: false,
9373 global: false,
9374 "throws": true
9375 });
9376};
9377
9378
9379jQuery.fn.extend({
9380 wrapAll: function( html ) {
9381 if ( jQuery.isFunction( html ) ) {
9382 return this.each(function(i) {
9383 jQuery(this).wrapAll( html.call(this, i) );
9384 });
9385 }
9386
9387 if ( this[0] ) {
9388 // The elements to wrap the target around
9389 var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);
9390
9391 if ( this[0].parentNode ) {
9392 wrap.insertBefore( this[0] );
9393 }
9394
9395 wrap.map(function() {
9396 var elem = this;
9397
9398 while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {
9399 elem = elem.firstChild;
9400 }
9401
9402 return elem;
9403 }).append( this );
9404 }
9405
9406 return this;
9407 },
9408
9409 wrapInner: function( html ) {
9410 if ( jQuery.isFunction( html ) ) {
9411 return this.each(function(i) {
9412 jQuery(this).wrapInner( html.call(this, i) );
9413 });
9414 }
9415
9416 return this.each(function() {
9417 var self = jQuery( this ),
9418 contents = self.contents();
9419
9420 if ( contents.length ) {
9421 contents.wrapAll( html );
9422
9423 } else {
9424 self.append( html );
9425 }
9426 });
9427 },
9428
9429 wrap: function( html ) {
9430 var isFunction = jQuery.isFunction( html );
9431
9432 return this.each(function(i) {
9433 jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );
9434 });
9435 },
9436
9437 unwrap: function() {
9438 return this.parent().each(function() {
9439 if ( !jQuery.nodeName( this, "body" ) ) {
9440 jQuery( this ).replaceWith( this.childNodes );
9441 }
9442 }).end();
9443 }
9444});
9445
9446
9447jQuery.expr.filters.hidden = function( elem ) {
9448 // Support: Opera <= 12.12
9449 // Opera reports offsetWidths and offsetHeights less than zero on some elements
9450 return elem.offsetWidth <= 0 && elem.offsetHeight <= 0 ||
9451 (!support.reliableHiddenOffsets() &&
9452 ((elem.style && elem.style.display) || jQuery.css( elem, "display" )) === "none");
9453};
9454
9455jQuery.expr.filters.visible = function( elem ) {
9456 return !jQuery.expr.filters.hidden( elem );
9457};
9458
9459
9460
9461
9462var r20 = /%20/g,
9463 rbracket = /\[\]$/,
9464 rCRLF = /\r?\n/g,
9465 rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,
9466 rsubmittable = /^(?:input|select|textarea|keygen)/i;
9467
9468function buildParams( prefix, obj, traditional, add ) {
9469 var name;
9470
9471 if ( jQuery.isArray( obj ) ) {
9472 // Serialize array item.
9473 jQuery.each( obj, function( i, v ) {
9474 if ( traditional || rbracket.test( prefix ) ) {
9475 // Treat each array item as a scalar.
9476 add( prefix, v );
9477
9478 } else {
9479 // Item is non-scalar (array or object), encode its numeric index.
9480 buildParams( prefix + "[" + ( typeof v === "object" ? i : "" ) + "]", v, traditional, add );
9481 }
9482 });
9483
9484 } else if ( !traditional && jQuery.type( obj ) === "object" ) {
9485 // Serialize object item.
9486 for ( name in obj ) {
9487 buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
9488 }
9489
9490 } else {
9491 // Serialize scalar item.
9492 add( prefix, obj );
9493 }
9494}
9495
9496// Serialize an array of form elements or a set of
9497// key/values into a query string
9498jQuery.param = function( a, traditional ) {
9499 var prefix,
9500 s = [],
9501 add = function( key, value ) {
9502 // If value is a function, invoke it and return its value
9503 value = jQuery.isFunction( value ) ? value() : ( value == null ? "" : value );
9504 s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
9505 };
9506
9507 // Set traditional to true for jQuery <= 1.3.2 behavior.
9508 if ( traditional === undefined ) {
9509 traditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;
9510 }
9511
9512 // If an array was passed in, assume that it is an array of form elements.
9513 if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
9514 // Serialize the form elements
9515 jQuery.each( a, function() {
9516 add( this.name, this.value );
9517 });
9518
9519 } else {
9520 // If traditional, encode the "old" way (the way 1.3.2 or older
9521 // did it), otherwise encode params recursively.
9522 for ( prefix in a ) {
9523 buildParams( prefix, a[ prefix ], traditional, add );
9524 }
9525 }
9526
9527 // Return the resulting serialization
9528 return s.join( "&" ).replace( r20, "+" );
9529};
9530
9531jQuery.fn.extend({
9532 serialize: function() {
9533 return jQuery.param( this.serializeArray() );
9534 },
9535 serializeArray: function() {
9536 return this.map(function() {
9537 // Can add propHook for "elements" to filter or add form elements
9538 var elements = jQuery.prop( this, "elements" );
9539 return elements ? jQuery.makeArray( elements ) : this;
9540 })
9541 .filter(function() {
9542 var type = this.type;
9543 // Use .is(":disabled") so that fieldset[disabled] works
9544 return this.name && !jQuery( this ).is( ":disabled" ) &&
9545 rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&
9546 ( this.checked || !rcheckableType.test( type ) );
9547 })
9548 .map(function( i, elem ) {
9549 var val = jQuery( this ).val();
9550
9551 return val == null ?
9552 null :
9553 jQuery.isArray( val ) ?
9554 jQuery.map( val, function( val ) {
9555 return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
9556 }) :
9557 { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
9558 }).get();
9559 }
9560});
9561
9562
9563// Create the request object
9564// (This is still attached to ajaxSettings for backward compatibility)
9565jQuery.ajaxSettings.xhr = window.ActiveXObject !== undefined ?
9566 // Support: IE6+
9567 function() {
9568
9569 // XHR cannot access local files, always use ActiveX for that case
9570 return !this.isLocal &&
9571
9572 // Support: IE7-8
9573 // oldIE XHR does not support non-RFC2616 methods (#13240)
9574 // See http://msdn.microsoft.com/en-us/library/ie/ms536648(v=vs.85).aspx
9575 // and http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9
9576 // Although this check for six methods instead of eight
9577 // since IE also does not support "trace" and "connect"
9578 /^(get|post|head|put|delete|options)$/i.test( this.type ) &&
9579
9580 createStandardXHR() || createActiveXHR();
9581 } :
9582 // For all other browsers, use the standard XMLHttpRequest object
9583 createStandardXHR;
9584
9585var xhrId = 0,
9586 xhrCallbacks = {},
9587 xhrSupported = jQuery.ajaxSettings.xhr();
9588
9589// Support: IE<10
9590// Open requests must be manually aborted on unload (#5280)
9591// See https://support.microsoft.com/kb/2856746 for more info
9592if ( window.attachEvent ) {
9593 window.attachEvent( "onunload", function() {
9594 for ( var key in xhrCallbacks ) {
9595 xhrCallbacks[ key ]( undefined, true );
9596 }
9597 });
9598}
9599
9600// Determine support properties
9601support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported );
9602xhrSupported = support.ajax = !!xhrSupported;
9603
9604// Create transport if the browser can provide an xhr
9605if ( xhrSupported ) {
9606
9607 jQuery.ajaxTransport(function( options ) {
9608 // Cross domain only allowed if supported through XMLHttpRequest
9609 if ( !options.crossDomain || support.cors ) {
9610
9611 var callback;
9612
9613 return {
9614 send: function( headers, complete ) {
9615 var i,
9616 xhr = options.xhr(),
9617 id = ++xhrId;
9618
9619 // Open the socket
9620 xhr.open( options.type, options.url, options.async, options.username, options.password );
9621
9622 // Apply custom fields if provided
9623 if ( options.xhrFields ) {
9624 for ( i in options.xhrFields ) {
9625 xhr[ i ] = options.xhrFields[ i ];
9626 }
9627 }
9628
9629 // Override mime type if needed
9630 if ( options.mimeType && xhr.overrideMimeType ) {
9631 xhr.overrideMimeType( options.mimeType );
9632 }
9633
9634 // X-Requested-With header
9635 // For cross-domain requests, seeing as conditions for a preflight are
9636 // akin to a jigsaw puzzle, we simply never set it to be sure.
9637 // (it can always be set on a per-request basis or even using ajaxSetup)
9638 // For same-domain requests, won't change header if already provided.
9639 if ( !options.crossDomain && !headers["X-Requested-With"] ) {
9640 headers["X-Requested-With"] = "XMLHttpRequest";
9641 }
9642
9643 // Set headers
9644 for ( i in headers ) {
9645 // Support: IE<9
9646 // IE's ActiveXObject throws a 'Type Mismatch' exception when setting
9647 // request header to a null-value.
9648 //
9649 // To keep consistent with other XHR implementations, cast the value
9650 // to string and ignore `undefined`.
9651 if ( headers[ i ] !== undefined ) {
9652 xhr.setRequestHeader( i, headers[ i ] + "" );
9653 }
9654 }
9655
9656 // Do send the request
9657 // This may raise an exception which is actually
9658 // handled in jQuery.ajax (so no try/catch here)
9659 xhr.send( ( options.hasContent && options.data ) || null );
9660
9661 // Listener
9662 callback = function( _, isAbort ) {
9663 var status, statusText, responses;
9664
9665 // Was never called and is aborted or complete
9666 if ( callback && ( isAbort || xhr.readyState === 4 ) ) {
9667 // Clean up
9668 delete xhrCallbacks[ id ];
9669 callback = undefined;
9670 xhr.onreadystatechange = jQuery.noop;
9671
9672 // Abort manually if needed
9673 if ( isAbort ) {
9674 if ( xhr.readyState !== 4 ) {
9675 xhr.abort();
9676 }
9677 } else {
9678 responses = {};
9679 status = xhr.status;
9680
9681 // Support: IE<10
9682 // Accessing binary-data responseText throws an exception
9683 // (#11426)
9684 if ( typeof xhr.responseText === "string" ) {
9685 responses.text = xhr.responseText;
9686 }
9687
9688 // Firefox throws an exception when accessing
9689 // statusText for faulty cross-domain requests
9690 try {
9691 statusText = xhr.statusText;
9692 } catch( e ) {
9693 // We normalize with Webkit giving an empty statusText
9694 statusText = "";
9695 }
9696
9697 // Filter status for non standard behaviors
9698
9699 // If the request is local and we have data: assume a success
9700 // (success with no data won't get notified, that's the best we
9701 // can do given current implementations)
9702 if ( !status && options.isLocal && !options.crossDomain ) {
9703 status = responses.text ? 200 : 404;
9704 // IE - #1450: sometimes returns 1223 when it should be 204
9705 } else if ( status === 1223 ) {
9706 status = 204;
9707 }
9708 }
9709 }
9710
9711 // Call complete if needed
9712 if ( responses ) {
9713 complete( status, statusText, responses, xhr.getAllResponseHeaders() );
9714 }
9715 };
9716
9717 if ( !options.async ) {
9718 // if we're in sync mode we fire the callback
9719 callback();
9720 } else if ( xhr.readyState === 4 ) {
9721 // (IE6 & IE7) if it's in cache and has been
9722 // retrieved directly we need to fire the callback
9723 setTimeout( callback );
9724 } else {
9725 // Add to the list of active xhr callbacks
9726 xhr.onreadystatechange = xhrCallbacks[ id ] = callback;
9727 }
9728 },
9729
9730 abort: function() {
9731 if ( callback ) {
9732 callback( undefined, true );
9733 }
9734 }
9735 };
9736 }
9737 });
9738}
9739
9740// Functions to create xhrs
9741function createStandardXHR() {
9742 try {
9743 return new window.XMLHttpRequest();
9744 } catch( e ) {}
9745}
9746
9747function createActiveXHR() {
9748 try {
9749 return new window.ActiveXObject( "Microsoft.XMLHTTP" );
9750 } catch( e ) {}
9751}
9752
9753
9754
9755
9756// Install script dataType
9757jQuery.ajaxSetup({
9758 accepts: {
9759 script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
9760 },
9761 contents: {
9762 script: /(?:java|ecma)script/
9763 },
9764 converters: {
9765 "text script": function( text ) {
9766 jQuery.globalEval( text );
9767 return text;
9768 }
9769 }
9770});
9771
9772// Handle cache's special case and global
9773jQuery.ajaxPrefilter( "script", function( s ) {
9774 if ( s.cache === undefined ) {
9775 s.cache = false;
9776 }
9777 if ( s.crossDomain ) {
9778 s.type = "GET";
9779 s.global = false;
9780 }
9781});
9782
9783// Bind script tag hack transport
9784jQuery.ajaxTransport( "script", function(s) {
9785
9786 // This transport only deals with cross domain requests
9787 if ( s.crossDomain ) {
9788
9789 var script,
9790 head = document.head || jQuery("head")[0] || document.documentElement;
9791
9792 return {
9793
9794 send: function( _, callback ) {
9795
9796 script = document.createElement("script");
9797
9798 script.async = true;
9799
9800 if ( s.scriptCharset ) {
9801 script.charset = s.scriptCharset;
9802 }
9803
9804 script.src = s.url;
9805
9806 // Attach handlers for all browsers
9807 script.onload = script.onreadystatechange = function( _, isAbort ) {
9808
9809 if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {
9810
9811 // Handle memory leak in IE
9812 script.onload = script.onreadystatechange = null;
9813
9814 // Remove the script
9815 if ( script.parentNode ) {
9816 script.parentNode.removeChild( script );
9817 }
9818
9819 // Dereference the script
9820 script = null;
9821
9822 // Callback if not abort
9823 if ( !isAbort ) {
9824 callback( 200, "success" );
9825 }
9826 }
9827 };
9828
9829 // Circumvent IE6 bugs with base elements (#2709 and #4378) by prepending
9830 // Use native DOM manipulation to avoid our domManip AJAX trickery
9831 head.insertBefore( script, head.firstChild );
9832 },
9833
9834 abort: function() {
9835 if ( script ) {
9836 script.onload( undefined, true );
9837 }
9838 }
9839 };
9840 }
9841});
9842
9843
9844
9845
9846var oldCallbacks = [],
9847 rjsonp = /(=)\?(?=&|$)|\?\?/;
9848
9849// Default jsonp settings
9850jQuery.ajaxSetup({
9851 jsonp: "callback",
9852 jsonpCallback: function() {
9853 var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce++ ) );
9854 this[ callback ] = true;
9855 return callback;
9856 }
9857});
9858
9859// Detect, normalize options and install callbacks for jsonp requests
9860jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
9861
9862 var callbackName, overwritten, responseContainer,
9863 jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?
9864 "url" :
9865 typeof s.data === "string" && !( s.contentType || "" ).indexOf("application/x-www-form-urlencoded") && rjsonp.test( s.data ) && "data"
9866 );
9867
9868 // Handle iff the expected data type is "jsonp" or we have a parameter to set
9869 if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) {
9870
9871 // Get callback name, remembering preexisting value associated with it
9872 callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ?
9873 s.jsonpCallback() :
9874 s.jsonpCallback;
9875
9876 // Insert callback into url or form data
9877 if ( jsonProp ) {
9878 s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName );
9879 } else if ( s.jsonp !== false ) {
9880 s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName;
9881 }
9882
9883 // Use data converter to retrieve json after script execution
9884 s.converters["script json"] = function() {
9885 if ( !responseContainer ) {
9886 jQuery.error( callbackName + " was not called" );
9887 }
9888 return responseContainer[ 0 ];
9889 };
9890
9891 // force json dataType
9892 s.dataTypes[ 0 ] = "json";
9893
9894 // Install callback
9895 overwritten = window[ callbackName ];
9896 window[ callbackName ] = function() {
9897 responseContainer = arguments;
9898 };
9899
9900 // Clean-up function (fires after converters)
9901 jqXHR.always(function() {
9902 // Restore preexisting value
9903 window[ callbackName ] = overwritten;
9904
9905 // Save back as free
9906 if ( s[ callbackName ] ) {
9907 // make sure that re-using the options doesn't screw things around
9908 s.jsonpCallback = originalSettings.jsonpCallback;
9909
9910 // save the callback name for future use
9911 oldCallbacks.push( callbackName );
9912 }
9913
9914 // Call if it was a function and we have a response
9915 if ( responseContainer && jQuery.isFunction( overwritten ) ) {
9916 overwritten( responseContainer[ 0 ] );
9917 }
9918
9919 responseContainer = overwritten = undefined;
9920 });
9921
9922 // Delegate to script
9923 return "script";
9924 }
9925});
9926
9927
9928
9929
9930// data: string of html
9931// context (optional): If specified, the fragment will be created in this context, defaults to document
9932// keepScripts (optional): If true, will include scripts passed in the html string
9933jQuery.parseHTML = function( data, context, keepScripts ) {
9934 if ( !data || typeof data !== "string" ) {
9935 return null;
9936 }
9937 if ( typeof context === "boolean" ) {
9938 keepScripts = context;
9939 context = false;
9940 }
9941 context = context || document;
9942
9943 var parsed = rsingleTag.exec( data ),
9944 scripts = !keepScripts && [];
9945
9946 // Single tag
9947 if ( parsed ) {
9948 return [ context.createElement( parsed[1] ) ];
9949 }
9950
9951 parsed = jQuery.buildFragment( [ data ], context, scripts );
9952
9953 if ( scripts && scripts.length ) {
9954 jQuery( scripts ).remove();
9955 }
9956
9957 return jQuery.merge( [], parsed.childNodes );
9958};
9959
9960
9961// Keep a copy of the old load method
9962var _load = jQuery.fn.load;
9963
9964/**
9965 * Load a url into a page
9966 */
9967jQuery.fn.load = function( url, params, callback ) {
9968 if ( typeof url !== "string" && _load ) {
9969 return _load.apply( this, arguments );
9970 }
9971
9972 var selector, response, type,
9973 self = this,
9974 off = url.indexOf(" ");
9975
9976 if ( off >= 0 ) {
9977 selector = jQuery.trim( url.slice( off, url.length ) );
9978 url = url.slice( 0, off );
9979 }
9980
9981 // If it's a function
9982 if ( jQuery.isFunction( params ) ) {
9983
9984 // We assume that it's the callback
9985 callback = params;
9986 params = undefined;
9987
9988 // Otherwise, build a param string
9989 } else if ( params && typeof params === "object" ) {
9990 type = "POST";
9991 }
9992
9993 // If we have elements to modify, make the request
9994 if ( self.length > 0 ) {
9995 jQuery.ajax({
9996 url: url,
9997
9998 // if "type" variable is undefined, then "GET" method will be used
9999 type: type,
10000 dataType: "html",
10001 data: params
10002 }).done(function( responseText ) {
10003
10004 // Save response for use in complete callback
10005 response = arguments;
10006
10007 self.html( selector ?
10008
10009 // If a selector was specified, locate the right elements in a dummy div
10010 // Exclude scripts to avoid IE 'Permission Denied' errors
10011 jQuery("<div>").append( jQuery.parseHTML( responseText ) ).find( selector ) :
10012
10013 // Otherwise use the full result
10014 responseText );
10015
10016 }).complete( callback && function( jqXHR, status ) {
10017 self.each( callback, response || [ jqXHR.responseText, status, jqXHR ] );
10018 });
10019 }
10020
10021 return this;
10022};
10023
10024
10025
10026
10027// Attach a bunch of functions for handling common AJAX events
10028jQuery.each( [ "ajaxStart", "ajaxStop", "ajaxComplete", "ajaxError", "ajaxSuccess", "ajaxSend" ], function( i, type ) {
10029 jQuery.fn[ type ] = function( fn ) {
10030 return this.on( type, fn );
10031 };
10032});
10033
10034
10035
10036
10037jQuery.expr.filters.animated = function( elem ) {
10038 return jQuery.grep(jQuery.timers, function( fn ) {
10039 return elem === fn.elem;
10040 }).length;
10041};
10042
10043
10044
10045
10046
10047var docElem = window.document.documentElement;
10048
10049/**
10050 * Gets a window from an element
10051 */
10052function getWindow( elem ) {
10053 return jQuery.isWindow( elem ) ?
10054 elem :
10055 elem.nodeType === 9 ?
10056 elem.defaultView || elem.parentWindow :
10057 false;
10058}
10059
10060jQuery.offset = {
10061 setOffset: function( elem, options, i ) {
10062 var curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition,
10063 position = jQuery.css( elem, "position" ),
10064 curElem = jQuery( elem ),
10065 props = {};
10066
10067 // set position first, in-case top/left are set even on static elem
10068 if ( position === "static" ) {
10069 elem.style.position = "relative";
10070 }
10071
10072 curOffset = curElem.offset();
10073 curCSSTop = jQuery.css( elem, "top" );
10074 curCSSLeft = jQuery.css( elem, "left" );
10075 calculatePosition = ( position === "absolute" || position === "fixed" ) &&
10076 jQuery.inArray("auto", [ curCSSTop, curCSSLeft ] ) > -1;
10077
10078 // need to be able to calculate position if either top or left is auto and position is either absolute or fixed
10079 if ( calculatePosition ) {
10080 curPosition = curElem.position();
10081 curTop = curPosition.top;
10082 curLeft = curPosition.left;
10083 } else {
10084 curTop = parseFloat( curCSSTop ) || 0;
10085 curLeft = parseFloat( curCSSLeft ) || 0;
10086 }
10087
10088 if ( jQuery.isFunction( options ) ) {
10089 options = options.call( elem, i, curOffset );
10090 }
10091
10092 if ( options.top != null ) {
10093 props.top = ( options.top - curOffset.top ) + curTop;
10094 }
10095 if ( options.left != null ) {
10096 props.left = ( options.left - curOffset.left ) + curLeft;
10097 }
10098
10099 if ( "using" in options ) {
10100 options.using.call( elem, props );
10101 } else {
10102 curElem.css( props );
10103 }
10104 }
10105};
10106
10107jQuery.fn.extend({
10108 offset: function( options ) {
10109 if ( arguments.length ) {
10110 return options === undefined ?
10111 this :
10112 this.each(function( i ) {
10113 jQuery.offset.setOffset( this, options, i );
10114 });
10115 }
10116
10117 var docElem, win,
10118 box = { top: 0, left: 0 },
10119 elem = this[ 0 ],
10120 doc = elem && elem.ownerDocument;
10121
10122 if ( !doc ) {
10123 return;
10124 }
10125
10126 docElem = doc.documentElement;
10127
10128 // Make sure it's not a disconnected DOM node
10129 if ( !jQuery.contains( docElem, elem ) ) {
10130 return box;
10131 }
10132
10133 // If we don't have gBCR, just use 0,0 rather than error
10134 // BlackBerry 5, iOS 3 (original iPhone)
10135 if ( typeof elem.getBoundingClientRect !== strundefined ) {
10136 box = elem.getBoundingClientRect();
10137 }
10138 win = getWindow( doc );
10139 return {
10140 top: box.top + ( win.pageYOffset || docElem.scrollTop ) - ( docElem.clientTop || 0 ),
10141 left: box.left + ( win.pageXOffset || docElem.scrollLeft ) - ( docElem.clientLeft || 0 )
10142 };
10143 },
10144
10145 position: function() {
10146 if ( !this[ 0 ] ) {
10147 return;
10148 }
10149
10150 var offsetParent, offset,
10151 parentOffset = { top: 0, left: 0 },
10152 elem = this[ 0 ];
10153
10154 // fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is its only offset parent
10155 if ( jQuery.css( elem, "position" ) === "fixed" ) {
10156 // we assume that getBoundingClientRect is available when computed position is fixed
10157 offset = elem.getBoundingClientRect();
10158 } else {
10159 // Get *real* offsetParent
10160 offsetParent = this.offsetParent();
10161
10162 // Get correct offsets
10163 offset = this.offset();
10164 if ( !jQuery.nodeName( offsetParent[ 0 ], "html" ) ) {
10165 parentOffset = offsetParent.offset();
10166 }
10167
10168 // Add offsetParent borders
10169 parentOffset.top += jQuery.css( offsetParent[ 0 ], "borderTopWidth", true );
10170 parentOffset.left += jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true );
10171 }
10172
10173 // Subtract parent offsets and element margins
10174 // note: when an element has margin: auto the offsetLeft and marginLeft
10175 // are the same in Safari causing offset.left to incorrectly be 0
10176 return {
10177 top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ),
10178 left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true)
10179 };
10180 },
10181
10182 offsetParent: function() {
10183 return this.map(function() {
10184 var offsetParent = this.offsetParent || docElem;
10185
10186 while ( offsetParent && ( !jQuery.nodeName( offsetParent, "html" ) && jQuery.css( offsetParent, "position" ) === "static" ) ) {
10187 offsetParent = offsetParent.offsetParent;
10188 }
10189 return offsetParent || docElem;
10190 });
10191 }
10192});
10193
10194// Create scrollLeft and scrollTop methods
10195jQuery.each( { scrollLeft: "pageXOffset", scrollTop: "pageYOffset" }, function( method, prop ) {
10196 var top = /Y/.test( prop );
10197
10198 jQuery.fn[ method ] = function( val ) {
10199 return access( this, function( elem, method, val ) {
10200 var win = getWindow( elem );
10201
10202 if ( val === undefined ) {
10203 return win ? (prop in win) ? win[ prop ] :
10204 win.document.documentElement[ method ] :
10205 elem[ method ];
10206 }
10207
10208 if ( win ) {
10209 win.scrollTo(
10210 !top ? val : jQuery( win ).scrollLeft(),
10211 top ? val : jQuery( win ).scrollTop()
10212 );
10213
10214 } else {
10215 elem[ method ] = val;
10216 }
10217 }, method, val, arguments.length, null );
10218 };
10219});
10220
10221// Add the top/left cssHooks using jQuery.fn.position
10222// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
10223// getComputedStyle returns percent when specified for top/left/bottom/right
10224// rather than make the css module depend on the offset module, we just check for it here
10225jQuery.each( [ "top", "left" ], function( i, prop ) {
10226 jQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition,
10227 function( elem, computed ) {
10228 if ( computed ) {
10229 computed = curCSS( elem, prop );
10230 // if curCSS returns percentage, fallback to offset
10231 return rnumnonpx.test( computed ) ?
10232 jQuery( elem ).position()[ prop ] + "px" :
10233 computed;
10234 }
10235 }
10236 );
10237});
10238
10239
10240// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
10241jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
10242 jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name }, function( defaultExtra, funcName ) {
10243 // margin is only for outerHeight, outerWidth
10244 jQuery.fn[ funcName ] = function( margin, value ) {
10245 var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ),
10246 extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" );
10247
10248 return access( this, function( elem, type, value ) {
10249 var doc;
10250
10251 if ( jQuery.isWindow( elem ) ) {
10252 // As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there
10253 // isn't a whole lot we can do. See pull request at this URL for discussion:
10254 // https://github.com/jquery/jquery/pull/764
10255 return elem.document.documentElement[ "client" + name ];
10256 }
10257
10258 // Get document width or height
10259 if ( elem.nodeType === 9 ) {
10260 doc = elem.documentElement;
10261
10262 // Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height], whichever is greatest
10263 // unfortunately, this causes bug #3838 in IE6/8 only, but there is currently no good, small way to fix it.
10264 return Math.max(
10265 elem.body[ "scroll" + name ], doc[ "scroll" + name ],
10266 elem.body[ "offset" + name ], doc[ "offset" + name ],
10267 doc[ "client" + name ]
10268 );
10269 }
10270
10271 return value === undefined ?
10272 // Get width or height on the element, requesting but not forcing parseFloat
10273 jQuery.css( elem, type, extra ) :
10274
10275 // Set width or height on the element
10276 jQuery.style( elem, type, value, extra );
10277 }, type, chainable ? margin : undefined, chainable, null );
10278 };
10279 });
10280});
10281
10282
10283// The number of elements contained in the matched element set
10284jQuery.fn.size = function() {
10285 return this.length;
10286};
10287
10288jQuery.fn.andSelf = jQuery.fn.addBack;
10289
10290
10291
10292
10293// Register as a named AMD module, since jQuery can be concatenated with other
10294// files that may use define, but not via a proper concatenation script that
10295// understands anonymous AMD modules. A named AMD is safest and most robust
10296// way to register. Lowercase jquery is used because AMD module names are
10297// derived from file names, and jQuery is normally delivered in a lowercase
10298// file name. Do this after creating the global so that if an AMD module wants
10299// to call noConflict to hide this version of jQuery, it will work.
10300
10301// Note that for maximum portability, libraries that are not jQuery should
10302// declare themselves as anonymous modules, and avoid setting a global if an
10303// AMD loader is present. jQuery is a special case. For more information, see
10304// https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon
10305
10306if ( typeof define === "function" && define.amd ) {
10307 define( "jquery", [], function() {
10308 return jQuery;
10309 });
10310}
10311
10312
10313
10314
10315var
10316 // Map over jQuery in case of overwrite
10317 _jQuery = window.jQuery,
10318
10319 // Map over the $ in case of overwrite
10320 _$ = window.$;
10321
10322jQuery.noConflict = function( deep ) {
10323 if ( window.$ === jQuery ) {
10324 window.$ = _$;
10325 }
10326
10327 if ( deep && window.jQuery === jQuery ) {
10328 window.jQuery = _jQuery;
10329 }
10330
10331 return jQuery;
10332};
10333
10334// Expose jQuery and $ identifiers, even in
10335// AMD (#7102#comment:10, https://github.com/jquery/jquery/pull/557)
10336// and CommonJS for browser emulators (#13566)
10337if ( typeof noGlobal === strundefined ) {
10338 window.jQuery = window.$ = jQuery;
10339}
10340
10341
10342
10343
10344return jQuery;
10345
10346}));
diff --git a/plugins/playvideos/jquery-1.11.2.min.js b/plugins/playvideos/jquery-1.11.2.min.js
new file mode 100644
index 00000000..e6a051d0
--- /dev/null
+++ b/plugins/playvideos/jquery-1.11.2.min.js
@@ -0,0 +1,4 @@
1/*! jQuery v1.11.2 | (c) 2005, 2014 jQuery Foundation, Inc. | jquery.org/license */
2!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k={},l="1.11.2",m=function(a,b){return new m.fn.init(a,b)},n=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,o=/^-ms-/,p=/-([\da-z])/gi,q=function(a,b){return b.toUpperCase()};m.fn=m.prototype={jquery:l,constructor:m,selector:"",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=m.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return m.each(this,a,b)},map:function(a){return this.pushStack(m.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},m.extend=m.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||m.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(e=arguments[h]))for(d in e)a=g[d],c=e[d],g!==c&&(j&&c&&(m.isPlainObject(c)||(b=m.isArray(c)))?(b?(b=!1,f=a&&m.isArray(a)?a:[]):f=a&&m.isPlainObject(a)?a:{},g[d]=m.extend(j,f,c)):void 0!==c&&(g[d]=c));return g},m.extend({expando:"jQuery"+(l+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===m.type(a)},isArray:Array.isArray||function(a){return"array"===m.type(a)},isWindow:function(a){return null!=a&&a==a.window},isNumeric:function(a){return!m.isArray(a)&&a-parseFloat(a)+1>=0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},isPlainObject:function(a){var b;if(!a||"object"!==m.type(a)||a.nodeType||m.isWindow(a))return!1;try{if(a.constructor&&!j.call(a,"constructor")&&!j.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}if(k.ownLast)for(b in a)return j.call(a,b);for(b in a);return void 0===b||j.call(a,b)},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(b){b&&m.trim(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(o,"ms-").replace(p,q)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=r(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(n,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(r(Object(a))?m.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){var d;if(b){if(g)return g.call(b,a,c);for(d=b.length,c=c?0>c?Math.max(0,d+c):c:0;d>c;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,b){var c=+b.length,d=0,e=a.length;while(c>d)a[e++]=b[d++];if(c!==c)while(void 0!==b[d])a[e++]=b[d++];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=r(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(f=a[b],b=a,a=f),m.isFunction(a)?(c=d.call(arguments,2),e=function(){return a.apply(b||this,c.concat(d.call(arguments)))},e.guid=a.guid=a.guid||m.guid++,e):void 0},now:function(){return+new Date},support:k}),m.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function r(a){var b=a.length,c=m.type(a);return"function"===c||m.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var s=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=hb(),z=hb(),A=hb(),B=function(a,b){return a===b&&(l=!0),0},C=1<<31,D={}.hasOwnProperty,E=[],F=E.pop,G=E.push,H=E.push,I=E.slice,J=function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},K="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",L="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",N=M.replace("w","w#"),O="\\["+L+"*("+M+")(?:"+L+"*([*^$|!~]?=)"+L+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+N+"))|)"+L+"*\\]",P=":("+M+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+O+")*)|.*)\\)|)",Q=new RegExp(L+"+","g"),R=new RegExp("^"+L+"+|((?:^|[^\\\\])(?:\\\\.)*)"+L+"+$","g"),S=new RegExp("^"+L+"*,"+L+"*"),T=new RegExp("^"+L+"*([>+~]|"+L+")"+L+"*"),U=new RegExp("="+L+"*([^\\]'\"]*?)"+L+"*\\]","g"),V=new RegExp(P),W=new RegExp("^"+N+"$"),X={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),TAG:new RegExp("^("+M.replace("w","w*")+")"),ATTR:new RegExp("^"+O),PSEUDO:new RegExp("^"+P),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+L+"*(even|odd|(([+-]|)(\\d*)n|)"+L+"*(?:([+-]|)"+L+"*(\\d+)|))"+L+"*\\)|)","i"),bool:new RegExp("^(?:"+K+")$","i"),needsContext:new RegExp("^"+L+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+L+"*((?:-\\d)?\\d*)"+L+"*\\)|)(?=[^-]|$)","i")},Y=/^(?:input|select|textarea|button)$/i,Z=/^h\d$/i,$=/^[^{]+\{\s*\[native \w/,_=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ab=/[+~]/,bb=/'|\\/g,cb=new RegExp("\\\\([\\da-f]{1,6}"+L+"?|("+L+")|.)","ig"),db=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},eb=function(){m()};try{H.apply(E=I.call(v.childNodes),v.childNodes),E[v.childNodes.length].nodeType}catch(fb){H={apply:E.length?function(a,b){G.apply(a,I.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function gb(a,b,d,e){var f,h,j,k,l,o,r,s,w,x;if((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,d=d||[],k=b.nodeType,"string"!=typeof a||!a||1!==k&&9!==k&&11!==k)return d;if(!e&&p){if(11!==k&&(f=_.exec(a)))if(j=f[1]){if(9===k){if(h=b.getElementById(j),!h||!h.parentNode)return d;if(h.id===j)return d.push(h),d}else if(b.ownerDocument&&(h=b.ownerDocument.getElementById(j))&&t(b,h)&&h.id===j)return d.push(h),d}else{if(f[2])return H.apply(d,b.getElementsByTagName(a)),d;if((j=f[3])&&c.getElementsByClassName)return H.apply(d,b.getElementsByClassName(j)),d}if(c.qsa&&(!q||!q.test(a))){if(s=r=u,w=b,x=1!==k&&a,1===k&&"object"!==b.nodeName.toLowerCase()){o=g(a),(r=b.getAttribute("id"))?s=r.replace(bb,"\\$&"):b.setAttribute("id",s),s="[id='"+s+"'] ",l=o.length;while(l--)o[l]=s+rb(o[l]);w=ab.test(a)&&pb(b.parentNode)||b,x=o.join(",")}if(x)try{return H.apply(d,w.querySelectorAll(x)),d}catch(y){}finally{r||b.removeAttribute("id")}}}return i(a.replace(R,"$1"),b,d,e)}function hb(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ib(a){return a[u]=!0,a}function jb(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function kb(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function lb(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||C)-(~a.sourceIndex||C);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function mb(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function nb(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function ob(a){return ib(function(b){return b=+b,ib(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function pb(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=gb.support={},f=gb.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=gb.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=g.documentElement,e=g.defaultView,e&&e!==e.top&&(e.addEventListener?e.addEventListener("unload",eb,!1):e.attachEvent&&e.attachEvent("onunload",eb)),p=!f(g),c.attributes=jb(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=jb(function(a){return a.appendChild(g.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=$.test(g.getElementsByClassName),c.getById=jb(function(a){return o.appendChild(a).id=u,!g.getElementsByName||!g.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=$.test(g.querySelectorAll))&&(jb(function(a){o.appendChild(a).innerHTML="<a id='"+u+"'></a><select id='"+u+"-\f]' msallowcapture=''><option selected=''></option></select>",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+L+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+L+"*(?:value|"+K+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),jb(function(a){var b=g.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+L+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=$.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&jb(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",P)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=$.test(o.compareDocumentPosition),t=b||$.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===g||a.ownerDocument===v&&t(v,a)?-1:b===g||b.ownerDocument===v&&t(v,b)?1:k?J(k,a)-J(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,h=[a],i=[b];if(!e||!f)return a===g?-1:b===g?1:e?-1:f?1:k?J(k,a)-J(k,b):0;if(e===f)return lb(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)i.unshift(c);while(h[d]===i[d])d++;return d?lb(h[d],i[d]):h[d]===v?-1:i[d]===v?1:0},g):n},gb.matches=function(a,b){return gb(a,null,null,b)},gb.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(U,"='$1']"),!(!c.matchesSelector||!p||r&&r.test(b)||q&&q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return gb(b,n,null,[a]).length>0},gb.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},gb.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&D.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},gb.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},gb.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=gb.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=gb.selectors={cacheLength:50,createPseudo:ib,match:X,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(cb,db),a[3]=(a[3]||a[4]||a[5]||"").replace(cb,db),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||gb.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&gb.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return X.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&V.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(cb,db).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+L+")"+a+"("+L+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=gb.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(Q," ")+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){k=q[u]||(q[u]={}),j=k[a]||[],n=j[0]===w&&j[1],m=j[0]===w&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[w,n,m];break}}else if(s&&(j=(b[u]||(b[u]={}))[a])&&j[0]===w)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(s&&((l[u]||(l[u]={}))[a]=[w,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||gb.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ib(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=J(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ib(function(a){var b=[],c=[],d=h(a.replace(R,"$1"));return d[u]?ib(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ib(function(a){return function(b){return gb(a,b).length>0}}),contains:ib(function(a){return a=a.replace(cb,db),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ib(function(a){return W.test(a||"")||gb.error("unsupported lang: "+a),a=a.replace(cb,db).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Z.test(a.nodeName)},input:function(a){return Y.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:ob(function(){return[0]}),last:ob(function(a,b){return[b-1]}),eq:ob(function(a,b,c){return[0>c?c+b:c]}),even:ob(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:ob(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:ob(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:ob(function(a,b,c){for(var d=0>c?c+b:c;++d<b;)a.push(d);return a})}},d.pseudos.nth=d.pseudos.eq;for(b in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})d.pseudos[b]=mb(b);for(b in{submit:!0,reset:!0})d.pseudos[b]=nb(b);function qb(){}qb.prototype=d.filters=d.pseudos,d.setFilters=new qb,g=gb.tokenize=function(a,b){var c,e,f,g,h,i,j,k=z[a+" "];if(k)return b?0:k.slice(0);h=a,i=[],j=d.preFilter;while(h){(!c||(e=S.exec(h)))&&(e&&(h=h.slice(e[0].length)||h),i.push(f=[])),c=!1,(e=T.exec(h))&&(c=e.shift(),f.push({value:c,type:e[0].replace(R," ")}),h=h.slice(c.length));for(g in d.filter)!(e=X[g].exec(h))||j[g]&&!(e=j[g](e))||(c=e.shift(),f.push({value:c,type:g,matches:e}),h=h.slice(c.length));if(!c)break}return b?h.length:h?gb.error(a):z(a,i).slice(0)};function rb(a){for(var b=0,c=a.length,d="";c>b;b++)d+=a[b].value;return d}function sb(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[u]||(b[u]={}),(h=i[d])&&h[0]===w&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function tb(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function ub(a,b,c){for(var d=0,e=b.length;e>d;d++)gb(a,b[d],c);return c}function vb(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function wb(a,b,c,d,e,f){return d&&!d[u]&&(d=wb(d)),e&&!e[u]&&(e=wb(e,f)),ib(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||ub(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:vb(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=vb(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?J(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=vb(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):H.apply(g,r)})}function xb(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=sb(function(a){return a===b},h,!0),l=sb(function(a){return J(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];f>i;i++)if(c=d.relative[a[i].type])m=[sb(tb(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return wb(i>1&&tb(m),i>1&&rb(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(R,"$1"),c,e>i&&xb(a.slice(i,e)),f>e&&xb(a=a.slice(e)),f>e&&rb(a))}m.push(c)}return tb(m)}function yb(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,m,o,p=0,q="0",r=f&&[],s=[],t=j,u=f||e&&d.find.TAG("*",k),v=w+=null==t?1:Math.random()||.1,x=u.length;for(k&&(j=g!==n&&g);q!==x&&null!=(l=u[q]);q++){if(e&&l){m=0;while(o=a[m++])if(o(l,g,h)){i.push(l);break}k&&(w=v)}c&&((l=!o&&l)&&p--,f&&r.push(l))}if(p+=q,c&&q!==p){m=0;while(o=b[m++])o(r,s,g,h);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=F.call(i));s=vb(s)}H.apply(i,s),k&&!f&&s.length>0&&p+b.length>1&&gb.uniqueSort(i)}return k&&(w=v,j=t),r};return c?ib(f):f}return h=gb.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=xb(b[c]),f[u]?d.push(f):e.push(f);f=A(a,yb(e,d)),f.selector=a}return f},i=gb.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(cb,db),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=X.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(cb,db),ab.test(j[0].type)&&pb(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&rb(j),!a)return H.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,ab.test(a)&&pb(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=jb(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),jb(function(a){return a.innerHTML="<a href='#'></a>","#"===a.firstChild.getAttribute("href")})||kb("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&jb(function(a){return a.innerHTML="<input/>",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||kb("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),jb(function(a){return null==a.getAttribute("disabled")})||kb(K,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),gb}(a);m.find=s,m.expr=s.selectors,m.expr[":"]=m.expr.pseudos,m.unique=s.uniqueSort,m.text=s.getText,m.isXMLDoc=s.isXML,m.contains=s.contains;var t=m.expr.match.needsContext,u=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,v=/^.[^:#\[\.,]*$/;function w(a,b,c){if(m.isFunction(b))return m.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return m.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(v.test(b))return m.filter(b,a,c);b=m.filter(b,a)}return m.grep(a,function(a){return m.inArray(a,b)>=0!==c})}m.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?m.find.matchesSelector(d,a)?[d]:[]:m.find.matches(a,m.grep(b,function(a){return 1===a.nodeType}))},m.fn.extend({find:function(a){var b,c=[],d=this,e=d.length;if("string"!=typeof a)return this.pushStack(m(a).filter(function(){for(b=0;e>b;b++)if(m.contains(d[b],this))return!0}));for(b=0;e>b;b++)m.find(a,d[b],c);return c=this.pushStack(e>1?m.unique(c):c),c.selector=this.selector?this.selector+" "+a:a,c},filter:function(a){return this.pushStack(w(this,a||[],!1))},not:function(a){return this.pushStack(w(this,a||[],!0))},is:function(a){return!!w(this,"string"==typeof a&&t.test(a)?m(a):a||[],!1).length}});var x,y=a.document,z=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,A=m.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a.charAt(0)&&">"===a.charAt(a.length-1)&&a.length>=3?[null,a,null]:z.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||x).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof m?b[0]:b,m.merge(this,m.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:y,!0)),u.test(c[1])&&m.isPlainObject(b))for(c in b)m.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}if(d=y.getElementById(c[2]),d&&d.parentNode){if(d.id!==c[2])return x.find(a);this.length=1,this[0]=d}return this.context=y,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):m.isFunction(a)?"undefined"!=typeof x.ready?x.ready(a):a(m):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),m.makeArray(a,this))};A.prototype=m.fn,x=m(y);var B=/^(?:parents|prev(?:Until|All))/,C={children:!0,contents:!0,next:!0,prev:!0};m.extend({dir:function(a,b,c){var d=[],e=a[b];while(e&&9!==e.nodeType&&(void 0===c||1!==e.nodeType||!m(e).is(c)))1===e.nodeType&&d.push(e),e=e[b];return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),m.fn.extend({has:function(a){var b,c=m(a,this),d=c.length;return this.filter(function(){for(b=0;d>b;b++)if(m.contains(this,c[b]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=t.test(a)||"string"!=typeof a?m(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&m.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?m.unique(f):f)},index:function(a){return a?"string"==typeof a?m.inArray(this[0],m(a)):m.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(m.unique(m.merge(this.get(),m(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function D(a,b){do a=a[b];while(a&&1!==a.nodeType);return a}m.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return m.dir(a,"parentNode")},parentsUntil:function(a,b,c){return m.dir(a,"parentNode",c)},next:function(a){return D(a,"nextSibling")},prev:function(a){return D(a,"previousSibling")},nextAll:function(a){return m.dir(a,"nextSibling")},prevAll:function(a){return m.dir(a,"previousSibling")},nextUntil:function(a,b,c){return m.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return m.dir(a,"previousSibling",c)},siblings:function(a){return m.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return m.sibling(a.firstChild)},contents:function(a){return m.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:m.merge([],a.childNodes)}},function(a,b){m.fn[a]=function(c,d){var e=m.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=m.filter(d,e)),this.length>1&&(C[a]||(e=m.unique(e)),B.test(a)&&(e=e.reverse())),this.pushStack(e)}});var E=/\S+/g,F={};function G(a){var b=F[a]={};return m.each(a.match(E)||[],function(a,c){b[c]=!0}),b}m.Callbacks=function(a){a="string"==typeof a?F[a]||G(a):m.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(c=a.memory&&l,d=!0,f=g||0,g=0,e=h.length,b=!0;h&&e>f;f++)if(h[f].apply(l[0],l[1])===!1&&a.stopOnFalse){c=!1;break}b=!1,h&&(i?i.length&&j(i.shift()):c?h=[]:k.disable())},k={add:function(){if(h){var d=h.length;!function f(b){m.each(b,function(b,c){var d=m.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&f(c)})}(arguments),b?e=h.length:c&&(g=d,j(c))}return this},remove:function(){return h&&m.each(arguments,function(a,c){var d;while((d=m.inArray(c,h,d))>-1)h.splice(d,1),b&&(e>=d&&e--,f>=d&&f--)}),this},has:function(a){return a?m.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],e=0,this},disable:function(){return h=i=c=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,c||k.disable(),this},locked:function(){return!i},fireWith:function(a,c){return!h||d&&!i||(c=c||[],c=[a,c.slice?c.slice():c],b?i.push(c):j(c)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!d}};return k},m.extend({Deferred:function(a){var b=[["resolve","done",m.Callbacks("once memory"),"resolved"],["reject","fail",m.Callbacks("once memory"),"rejected"],["notify","progress",m.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return m.Deferred(function(c){m.each(b,function(b,f){var g=m.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&m.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?m.extend(a,d):d}},e={};return d.pipe=d.then,m.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&m.isFunction(a.promise)?e:0,g=1===f?a:m.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&m.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var H;m.fn.ready=function(a){return m.ready.promise().done(a),this},m.extend({isReady:!1,readyWait:1,holdReady:function(a){a?m.readyWait++:m.ready(!0)},ready:function(a){if(a===!0?!--m.readyWait:!m.isReady){if(!y.body)return setTimeout(m.ready);m.isReady=!0,a!==!0&&--m.readyWait>0||(H.resolveWith(y,[m]),m.fn.triggerHandler&&(m(y).triggerHandler("ready"),m(y).off("ready")))}}});function I(){y.addEventListener?(y.removeEventListener("DOMContentLoaded",J,!1),a.removeEventListener("load",J,!1)):(y.detachEvent("onreadystatechange",J),a.detachEvent("onload",J))}function J(){(y.addEventListener||"load"===event.type||"complete"===y.readyState)&&(I(),m.ready())}m.ready.promise=function(b){if(!H)if(H=m.Deferred(),"complete"===y.readyState)setTimeout(m.ready);else if(y.addEventListener)y.addEventListener("DOMContentLoaded",J,!1),a.addEventListener("load",J,!1);else{y.attachEvent("onreadystatechange",J),a.attachEvent("onload",J);var c=!1;try{c=null==a.frameElement&&y.documentElement}catch(d){}c&&c.doScroll&&!function e(){if(!m.isReady){try{c.doScroll("left")}catch(a){return setTimeout(e,50)}I(),m.ready()}}()}return H.promise(b)};var K="undefined",L;for(L in m(k))break;k.ownLast="0"!==L,k.inlineBlockNeedsLayout=!1,m(function(){var a,b,c,d;c=y.getElementsByTagName("body")[0],c&&c.style&&(b=y.createElement("div"),d=y.createElement("div"),d.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(d).appendChild(b),typeof b.style.zoom!==K&&(b.style.cssText="display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1",k.inlineBlockNeedsLayout=a=3===b.offsetWidth,a&&(c.style.zoom=1)),c.removeChild(d))}),function(){var a=y.createElement("div");if(null==k.deleteExpando){k.deleteExpando=!0;try{delete a.test}catch(b){k.deleteExpando=!1}}a=null}(),m.acceptData=function(a){var b=m.noData[(a.nodeName+" ").toLowerCase()],c=+a.nodeType||1;return 1!==c&&9!==c?!1:!b||b!==!0&&a.getAttribute("classid")===b};var M=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,N=/([A-Z])/g;function O(a,b,c){if(void 0===c&&1===a.nodeType){var d="data-"+b.replace(N,"-$1").toLowerCase();if(c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:M.test(c)?m.parseJSON(c):c}catch(e){}m.data(a,b,c)}else c=void 0}return c}function P(a){var b;for(b in a)if(("data"!==b||!m.isEmptyObject(a[b]))&&"toJSON"!==b)return!1;
3return!0}function Q(a,b,d,e){if(m.acceptData(a)){var f,g,h=m.expando,i=a.nodeType,j=i?m.cache:a,k=i?a[h]:a[h]&&h;if(k&&j[k]&&(e||j[k].data)||void 0!==d||"string"!=typeof b)return k||(k=i?a[h]=c.pop()||m.guid++:h),j[k]||(j[k]=i?{}:{toJSON:m.noop}),("object"==typeof b||"function"==typeof b)&&(e?j[k]=m.extend(j[k],b):j[k].data=m.extend(j[k].data,b)),g=j[k],e||(g.data||(g.data={}),g=g.data),void 0!==d&&(g[m.camelCase(b)]=d),"string"==typeof b?(f=g[b],null==f&&(f=g[m.camelCase(b)])):f=g,f}}function R(a,b,c){if(m.acceptData(a)){var d,e,f=a.nodeType,g=f?m.cache:a,h=f?a[m.expando]:m.expando;if(g[h]){if(b&&(d=c?g[h]:g[h].data)){m.isArray(b)?b=b.concat(m.map(b,m.camelCase)):b in d?b=[b]:(b=m.camelCase(b),b=b in d?[b]:b.split(" ")),e=b.length;while(e--)delete d[b[e]];if(c?!P(d):!m.isEmptyObject(d))return}(c||(delete g[h].data,P(g[h])))&&(f?m.cleanData([a],!0):k.deleteExpando||g!=g.window?delete g[h]:g[h]=null)}}}m.extend({cache:{},noData:{"applet ":!0,"embed ":!0,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(a){return a=a.nodeType?m.cache[a[m.expando]]:a[m.expando],!!a&&!P(a)},data:function(a,b,c){return Q(a,b,c)},removeData:function(a,b){return R(a,b)},_data:function(a,b,c){return Q(a,b,c,!0)},_removeData:function(a,b){return R(a,b,!0)}}),m.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=m.data(f),1===f.nodeType&&!m._data(f,"parsedAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=m.camelCase(d.slice(5)),O(f,d,e[d])));m._data(f,"parsedAttrs",!0)}return e}return"object"==typeof a?this.each(function(){m.data(this,a)}):arguments.length>1?this.each(function(){m.data(this,a,b)}):f?O(f,a,m.data(f,a)):void 0},removeData:function(a){return this.each(function(){m.removeData(this,a)})}}),m.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=m._data(a,b),c&&(!d||m.isArray(c)?d=m._data(a,b,m.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=m.queue(a,b),d=c.length,e=c.shift(),f=m._queueHooks(a,b),g=function(){m.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return m._data(a,c)||m._data(a,c,{empty:m.Callbacks("once memory").add(function(){m._removeData(a,b+"queue"),m._removeData(a,c)})})}}),m.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length<c?m.queue(this[0],a):void 0===b?this:this.each(function(){var c=m.queue(this,a,b);m._queueHooks(this,a),"fx"===a&&"inprogress"!==c[0]&&m.dequeue(this,a)})},dequeue:function(a){return this.each(function(){m.dequeue(this,a)})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,b){var c,d=1,e=m.Deferred(),f=this,g=this.length,h=function(){--d||e.resolveWith(f,[f])};"string"!=typeof a&&(b=a,a=void 0),a=a||"fx";while(g--)c=m._data(f[g],a+"queueHooks"),c&&c.empty&&(d++,c.empty.add(h));return h(),e.promise(b)}});var S=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,T=["Top","Right","Bottom","Left"],U=function(a,b){return a=b||a,"none"===m.css(a,"display")||!m.contains(a.ownerDocument,a)},V=m.access=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===m.type(c)){e=!0;for(h in c)m.access(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,m.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(m(a),c)})),b))for(;i>h;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},W=/^(?:checkbox|radio)$/i;!function(){var a=y.createElement("input"),b=y.createElement("div"),c=y.createDocumentFragment();if(b.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",k.leadingWhitespace=3===b.firstChild.nodeType,k.tbody=!b.getElementsByTagName("tbody").length,k.htmlSerialize=!!b.getElementsByTagName("link").length,k.html5Clone="<:nav></:nav>"!==y.createElement("nav").cloneNode(!0).outerHTML,a.type="checkbox",a.checked=!0,c.appendChild(a),k.appendChecked=a.checked,b.innerHTML="<textarea>x</textarea>",k.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue,c.appendChild(b),b.innerHTML="<input type='radio' checked='checked' name='t'/>",k.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,k.noCloneEvent=!0,b.attachEvent&&(b.attachEvent("onclick",function(){k.noCloneEvent=!1}),b.cloneNode(!0).click()),null==k.deleteExpando){k.deleteExpando=!0;try{delete b.test}catch(d){k.deleteExpando=!1}}}(),function(){var b,c,d=y.createElement("div");for(b in{submit:!0,change:!0,focusin:!0})c="on"+b,(k[b+"Bubbles"]=c in a)||(d.setAttribute(c,"t"),k[b+"Bubbles"]=d.attributes[c].expando===!1);d=null}();var X=/^(?:input|select|textarea)$/i,Y=/^key/,Z=/^(?:mouse|pointer|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=/^([^.]*)(?:\.(.+)|)$/;function ab(){return!0}function bb(){return!1}function cb(){try{return y.activeElement}catch(a){}}m.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m._data(a);if(r){c.handler&&(i=c,c=i.handler,e=i.selector),c.guid||(c.guid=m.guid++),(g=r.events)||(g=r.events={}),(k=r.handle)||(k=r.handle=function(a){return typeof m===K||a&&m.event.triggered===a.type?void 0:m.event.dispatch.apply(k.elem,arguments)},k.elem=a),b=(b||"").match(E)||[""],h=b.length;while(h--)f=_.exec(b[h])||[],o=q=f[1],p=(f[2]||"").split(".").sort(),o&&(j=m.event.special[o]||{},o=(e?j.delegateType:j.bindType)||o,j=m.event.special[o]||{},l=m.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&m.expr.match.needsContext.test(e),namespace:p.join(".")},i),(n=g[o])||(n=g[o]=[],n.delegateCount=0,j.setup&&j.setup.call(a,d,p,k)!==!1||(a.addEventListener?a.addEventListener(o,k,!1):a.attachEvent&&a.attachEvent("on"+o,k))),j.add&&(j.add.call(a,l),l.handler.guid||(l.handler.guid=c.guid)),e?n.splice(n.delegateCount++,0,l):n.push(l),m.event.global[o]=!0);a=null}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m.hasData(a)&&m._data(a);if(r&&(k=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)if(h=_.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=m.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,n=k[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),i=f=n.length;while(f--)g=n[f],!e&&q!==g.origType||c&&c.guid!==g.guid||h&&!h.test(g.namespace)||d&&d!==g.selector&&("**"!==d||!g.selector)||(n.splice(f,1),g.selector&&n.delegateCount--,l.remove&&l.remove.call(a,g));i&&!n.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||m.removeEvent(a,o,r.handle),delete k[o])}else for(o in k)m.event.remove(a,o+b[j],c,d,!0);m.isEmptyObject(k)&&(delete r.handle,m._removeData(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,l,n,o=[d||y],p=j.call(b,"type")?b.type:b,q=j.call(b,"namespace")?b.namespace.split("."):[];if(h=l=d=d||y,3!==d.nodeType&&8!==d.nodeType&&!$.test(p+m.event.triggered)&&(p.indexOf(".")>=0&&(q=p.split("."),p=q.shift(),q.sort()),g=p.indexOf(":")<0&&"on"+p,b=b[m.expando]?b:new m.Event(p,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=q.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+q.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:m.makeArray(c,[b]),k=m.event.special[p]||{},e||!k.trigger||k.trigger.apply(d,c)!==!1)){if(!e&&!k.noBubble&&!m.isWindow(d)){for(i=k.delegateType||p,$.test(i+p)||(h=h.parentNode);h;h=h.parentNode)o.push(h),l=h;l===(d.ownerDocument||y)&&o.push(l.defaultView||l.parentWindow||a)}n=0;while((h=o[n++])&&!b.isPropagationStopped())b.type=n>1?i:k.bindType||p,f=(m._data(h,"events")||{})[b.type]&&m._data(h,"handle"),f&&f.apply(h,c),f=g&&h[g],f&&f.apply&&m.acceptData(h)&&(b.result=f.apply(h,c),b.result===!1&&b.preventDefault());if(b.type=p,!e&&!b.isDefaultPrevented()&&(!k._default||k._default.apply(o.pop(),c)===!1)&&m.acceptData(d)&&g&&d[p]&&!m.isWindow(d)){l=d[g],l&&(d[g]=null),m.event.triggered=p;try{d[p]()}catch(r){}m.event.triggered=void 0,l&&(d[g]=l)}return b.result}},dispatch:function(a){a=m.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(m._data(this,"events")||{})[a.type]||[],k=m.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=m.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,g=0;while((e=f.handlers[g++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(e.namespace))&&(a.handleObj=e,a.data=e.data,c=((m.event.special[e.origType]||{}).handle||e.handler).apply(f.elem,i),void 0!==c&&(a.result=c)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!=this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(e=[],f=0;h>f;f++)d=b[f],c=d.selector+" ",void 0===e[c]&&(e[c]=d.needsContext?m(c,this).index(i)>=0:m.find(c,this,null,[i]).length),e[c]&&e.push(d);e.length&&g.push({elem:i,handlers:e})}return h<b.length&&g.push({elem:this,handlers:b.slice(h)}),g},fix:function(a){if(a[m.expando])return a;var b,c,d,e=a.type,f=a,g=this.fixHooks[e];g||(this.fixHooks[e]=g=Z.test(e)?this.mouseHooks:Y.test(e)?this.keyHooks:{}),d=g.props?this.props.concat(g.props):this.props,a=new m.Event(f),b=d.length;while(b--)c=d[b],a[c]=f[c];return a.target||(a.target=f.srcElement||y),3===a.target.nodeType&&(a.target=a.target.parentNode),a.metaKey=!!a.metaKey,g.filter?g.filter(a,f):a},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){return null==a.which&&(a.which=null!=b.charCode?b.charCode:b.keyCode),a}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,b){var c,d,e,f=b.button,g=b.fromElement;return null==a.pageX&&null!=b.clientX&&(d=a.target.ownerDocument||y,e=d.documentElement,c=d.body,a.pageX=b.clientX+(e&&e.scrollLeft||c&&c.scrollLeft||0)-(e&&e.clientLeft||c&&c.clientLeft||0),a.pageY=b.clientY+(e&&e.scrollTop||c&&c.scrollTop||0)-(e&&e.clientTop||c&&c.clientTop||0)),!a.relatedTarget&&g&&(a.relatedTarget=g===a.target?b.toElement:g),a.which||void 0===f||(a.which=1&f?1:2&f?3:4&f?2:0),a}},special:{load:{noBubble:!0},focus:{trigger:function(){if(this!==cb()&&this.focus)try{return this.focus(),!1}catch(a){}},delegateType:"focusin"},blur:{trigger:function(){return this===cb()&&this.blur?(this.blur(),!1):void 0},delegateType:"focusout"},click:{trigger:function(){return m.nodeName(this,"input")&&"checkbox"===this.type&&this.click?(this.click(),!1):void 0},_default:function(a){return m.nodeName(a.target,"a")}},beforeunload:{postDispatch:function(a){void 0!==a.result&&a.originalEvent&&(a.originalEvent.returnValue=a.result)}}},simulate:function(a,b,c,d){var e=m.extend(new m.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?m.event.trigger(e,null,b):m.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},m.removeEvent=y.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){var d="on"+b;a.detachEvent&&(typeof a[d]===K&&(a[d]=null),a.detachEvent(d,c))},m.Event=function(a,b){return this instanceof m.Event?(a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||void 0===a.defaultPrevented&&a.returnValue===!1?ab:bb):this.type=a,b&&m.extend(this,b),this.timeStamp=a&&a.timeStamp||m.now(),void(this[m.expando]=!0)):new m.Event(a,b)},m.Event.prototype={isDefaultPrevented:bb,isPropagationStopped:bb,isImmediatePropagationStopped:bb,preventDefault:function(){var a=this.originalEvent;this.isDefaultPrevented=ab,a&&(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){var a=this.originalEvent;this.isPropagationStopped=ab,a&&(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){var a=this.originalEvent;this.isImmediatePropagationStopped=ab,a&&a.stopImmediatePropagation&&a.stopImmediatePropagation(),this.stopPropagation()}},m.each({mouseenter:"mouseover",mouseleave:"mouseout",pointerenter:"pointerover",pointerleave:"pointerout"},function(a,b){m.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c,d=this,e=a.relatedTarget,f=a.handleObj;return(!e||e!==d&&!m.contains(d,e))&&(a.type=f.origType,c=f.handler.apply(this,arguments),a.type=b),c}}}),k.submitBubbles||(m.event.special.submit={setup:function(){return m.nodeName(this,"form")?!1:void m.event.add(this,"click._submit keypress._submit",function(a){var b=a.target,c=m.nodeName(b,"input")||m.nodeName(b,"button")?b.form:void 0;c&&!m._data(c,"submitBubbles")&&(m.event.add(c,"submit._submit",function(a){a._submit_bubble=!0}),m._data(c,"submitBubbles",!0))})},postDispatch:function(a){a._submit_bubble&&(delete a._submit_bubble,this.parentNode&&!a.isTrigger&&m.event.simulate("submit",this.parentNode,a,!0))},teardown:function(){return m.nodeName(this,"form")?!1:void m.event.remove(this,"._submit")}}),k.changeBubbles||(m.event.special.change={setup:function(){return X.test(this.nodeName)?(("checkbox"===this.type||"radio"===this.type)&&(m.event.add(this,"propertychange._change",function(a){"checked"===a.originalEvent.propertyName&&(this._just_changed=!0)}),m.event.add(this,"click._change",function(a){this._just_changed&&!a.isTrigger&&(this._just_changed=!1),m.event.simulate("change",this,a,!0)})),!1):void m.event.add(this,"beforeactivate._change",function(a){var b=a.target;X.test(b.nodeName)&&!m._data(b,"changeBubbles")&&(m.event.add(b,"change._change",function(a){!this.parentNode||a.isSimulated||a.isTrigger||m.event.simulate("change",this.parentNode,a,!0)}),m._data(b,"changeBubbles",!0))})},handle:function(a){var b=a.target;return this!==b||a.isSimulated||a.isTrigger||"radio"!==b.type&&"checkbox"!==b.type?a.handleObj.handler.apply(this,arguments):void 0},teardown:function(){return m.event.remove(this,"._change"),!X.test(this.nodeName)}}),k.focusinBubbles||m.each({focus:"focusin",blur:"focusout"},function(a,b){var c=function(a){m.event.simulate(b,a.target,m.event.fix(a),!0)};m.event.special[b]={setup:function(){var d=this.ownerDocument||this,e=m._data(d,b);e||d.addEventListener(a,c,!0),m._data(d,b,(e||0)+1)},teardown:function(){var d=this.ownerDocument||this,e=m._data(d,b)-1;e?m._data(d,b,e):(d.removeEventListener(a,c,!0),m._removeData(d,b))}}}),m.fn.extend({on:function(a,b,c,d,e){var f,g;if("object"==typeof a){"string"!=typeof b&&(c=c||b,b=void 0);for(f in a)this.on(f,b,c,a[f],e);return this}if(null==c&&null==d?(d=b,c=b=void 0):null==d&&("string"==typeof b?(d=c,c=void 0):(d=c,c=b,b=void 0)),d===!1)d=bb;else if(!d)return this;return 1===e&&(g=d,d=function(a){return m().off(a),g.apply(this,arguments)},d.guid=g.guid||(g.guid=m.guid++)),this.each(function(){m.event.add(this,a,d,c,b)})},one:function(a,b,c,d){return this.on(a,b,c,d,1)},off:function(a,b,c){var d,e;if(a&&a.preventDefault&&a.handleObj)return d=a.handleObj,m(a.delegateTarget).off(d.namespace?d.origType+"."+d.namespace:d.origType,d.selector,d.handler),this;if("object"==typeof a){for(e in a)this.off(e,b,a[e]);return this}return(b===!1||"function"==typeof b)&&(c=b,b=void 0),c===!1&&(c=bb),this.each(function(){m.event.remove(this,a,c,b)})},trigger:function(a,b){return this.each(function(){m.event.trigger(a,b,this)})},triggerHandler:function(a,b){var c=this[0];return c?m.event.trigger(a,b,c,!0):void 0}});function db(a){var b=eb.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}var eb="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",fb=/ jQuery\d+="(?:null|\d+)"/g,gb=new RegExp("<(?:"+eb+")[\\s/>]","i"),hb=/^\s+/,ib=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,jb=/<([\w:]+)/,kb=/<tbody/i,lb=/<|&#?\w+;/,mb=/<(?:script|style|link)/i,nb=/checked\s*(?:[^=]|=\s*.checked.)/i,ob=/^$|\/(?:java|ecma)script/i,pb=/^true\/(.*)/,qb=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,rb={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],area:[1,"<map>","</map>"],param:[1,"<object>","</object>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:k.htmlSerialize?[0,"",""]:[1,"X<div>","</div>"]},sb=db(y),tb=sb.appendChild(y.createElement("div"));rb.optgroup=rb.option,rb.tbody=rb.tfoot=rb.colgroup=rb.caption=rb.thead,rb.th=rb.td;function ub(a,b){var c,d,e=0,f=typeof a.getElementsByTagName!==K?a.getElementsByTagName(b||"*"):typeof a.querySelectorAll!==K?a.querySelectorAll(b||"*"):void 0;if(!f)for(f=[],c=a.childNodes||a;null!=(d=c[e]);e++)!b||m.nodeName(d,b)?f.push(d):m.merge(f,ub(d,b));return void 0===b||b&&m.nodeName(a,b)?m.merge([a],f):f}function vb(a){W.test(a.type)&&(a.defaultChecked=a.checked)}function wb(a,b){return m.nodeName(a,"table")&&m.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function xb(a){return a.type=(null!==m.find.attr(a,"type"))+"/"+a.type,a}function yb(a){var b=pb.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function zb(a,b){for(var c,d=0;null!=(c=a[d]);d++)m._data(c,"globalEval",!b||m._data(b[d],"globalEval"))}function Ab(a,b){if(1===b.nodeType&&m.hasData(a)){var c,d,e,f=m._data(a),g=m._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;e>d;d++)m.event.add(b,c,h[c][d])}g.data&&(g.data=m.extend({},g.data))}}function Bb(a,b){var c,d,e;if(1===b.nodeType){if(c=b.nodeName.toLowerCase(),!k.noCloneEvent&&b[m.expando]){e=m._data(b);for(d in e.events)m.removeEvent(b,d,e.handle);b.removeAttribute(m.expando)}"script"===c&&b.text!==a.text?(xb(b).text=a.text,yb(b)):"object"===c?(b.parentNode&&(b.outerHTML=a.outerHTML),k.html5Clone&&a.innerHTML&&!m.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):"input"===c&&W.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):"option"===c?b.defaultSelected=b.selected=a.defaultSelected:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}}m.extend({clone:function(a,b,c){var d,e,f,g,h,i=m.contains(a.ownerDocument,a);if(k.html5Clone||m.isXMLDoc(a)||!gb.test("<"+a.nodeName+">")?f=a.cloneNode(!0):(tb.innerHTML=a.outerHTML,tb.removeChild(f=tb.firstChild)),!(k.noCloneEvent&&k.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||m.isXMLDoc(a)))for(d=ub(f),h=ub(a),g=0;null!=(e=h[g]);++g)d[g]&&Bb(e,d[g]);if(b)if(c)for(h=h||ub(a),d=d||ub(f),g=0;null!=(e=h[g]);g++)Ab(e,d[g]);else Ab(a,f);return d=ub(f,"script"),d.length>0&&zb(d,!i&&ub(a,"script")),d=h=e=null,f},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,l,n=a.length,o=db(b),p=[],q=0;n>q;q++)if(f=a[q],f||0===f)if("object"===m.type(f))m.merge(p,f.nodeType?[f]:f);else if(lb.test(f)){h=h||o.appendChild(b.createElement("div")),i=(jb.exec(f)||["",""])[1].toLowerCase(),l=rb[i]||rb._default,h.innerHTML=l[1]+f.replace(ib,"<$1></$2>")+l[2],e=l[0];while(e--)h=h.lastChild;if(!k.leadingWhitespace&&hb.test(f)&&p.push(b.createTextNode(hb.exec(f)[0])),!k.tbody){f="table"!==i||kb.test(f)?"<table>"!==l[1]||kb.test(f)?0:h:h.firstChild,e=f&&f.childNodes.length;while(e--)m.nodeName(j=f.childNodes[e],"tbody")&&!j.childNodes.length&&f.removeChild(j)}m.merge(p,h.childNodes),h.textContent="";while(h.firstChild)h.removeChild(h.firstChild);h=o.lastChild}else p.push(b.createTextNode(f));h&&o.removeChild(h),k.appendChecked||m.grep(ub(p,"input"),vb),q=0;while(f=p[q++])if((!d||-1===m.inArray(f,d))&&(g=m.contains(f.ownerDocument,f),h=ub(o.appendChild(f),"script"),g&&zb(h),c)){e=0;while(f=h[e++])ob.test(f.type||"")&&c.push(f)}return h=null,o},cleanData:function(a,b){for(var d,e,f,g,h=0,i=m.expando,j=m.cache,l=k.deleteExpando,n=m.event.special;null!=(d=a[h]);h++)if((b||m.acceptData(d))&&(f=d[i],g=f&&j[f])){if(g.events)for(e in g.events)n[e]?m.event.remove(d,e):m.removeEvent(d,e,g.handle);j[f]&&(delete j[f],l?delete d[i]:typeof d.removeAttribute!==K?d.removeAttribute(i):d[i]=null,c.push(f))}}}),m.fn.extend({text:function(a){return V(this,function(a){return void 0===a?m.text(this):this.empty().append((this[0]&&this[0].ownerDocument||y).createTextNode(a))},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=wb(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=wb(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?m.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||m.cleanData(ub(c)),c.parentNode&&(b&&m.contains(c.ownerDocument,c)&&zb(ub(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++){1===a.nodeType&&m.cleanData(ub(a,!1));while(a.firstChild)a.removeChild(a.firstChild);a.options&&m.nodeName(a,"select")&&(a.options.length=0)}return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return m.clone(this,a,b)})},html:function(a){return V(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a)return 1===b.nodeType?b.innerHTML.replace(fb,""):void 0;if(!("string"!=typeof a||mb.test(a)||!k.htmlSerialize&&gb.test(a)||!k.leadingWhitespace&&hb.test(a)||rb[(jb.exec(a)||["",""])[1].toLowerCase()])){a=a.replace(ib,"<$1></$2>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(m.cleanData(ub(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,m.cleanData(ub(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,l=this.length,n=this,o=l-1,p=a[0],q=m.isFunction(p);if(q||l>1&&"string"==typeof p&&!k.checkClone&&nb.test(p))return this.each(function(c){var d=n.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(l&&(i=m.buildFragment(a,this[0].ownerDocument,!1,this),c=i.firstChild,1===i.childNodes.length&&(i=c),c)){for(g=m.map(ub(i,"script"),xb),f=g.length;l>j;j++)d=i,j!==o&&(d=m.clone(d,!0,!0),f&&m.merge(g,ub(d,"script"))),b.call(this[j],d,j);if(f)for(h=g[g.length-1].ownerDocument,m.map(g,yb),j=0;f>j;j++)d=g[j],ob.test(d.type||"")&&!m._data(d,"globalEval")&&m.contains(h,d)&&(d.src?m._evalUrl&&m._evalUrl(d.src):m.globalEval((d.text||d.textContent||d.innerHTML||"").replace(qb,"")));i=c=null}return this}}),m.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){m.fn[a]=function(a){for(var c,d=0,e=[],g=m(a),h=g.length-1;h>=d;d++)c=d===h?this:this.clone(!0),m(g[d])[b](c),f.apply(e,c.get());return this.pushStack(e)}});var Cb,Db={};function Eb(b,c){var d,e=m(c.createElement(b)).appendTo(c.body),f=a.getDefaultComputedStyle&&(d=a.getDefaultComputedStyle(e[0]))?d.display:m.css(e[0],"display");return e.detach(),f}function Fb(a){var b=y,c=Db[a];return c||(c=Eb(a,b),"none"!==c&&c||(Cb=(Cb||m("<iframe frameborder='0' width='0' height='0'/>")).appendTo(b.documentElement),b=(Cb[0].contentWindow||Cb[0].contentDocument).document,b.write(),b.close(),c=Eb(a,b),Cb.detach()),Db[a]=c),c}!function(){var a;k.shrinkWrapBlocks=function(){if(null!=a)return a;a=!1;var b,c,d;return c=y.getElementsByTagName("body")[0],c&&c.style?(b=y.createElement("div"),d=y.createElement("div"),d.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(d).appendChild(b),typeof b.style.zoom!==K&&(b.style.cssText="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:1px;width:1px;zoom:1",b.appendChild(y.createElement("div")).style.width="5px",a=3!==b.offsetWidth),c.removeChild(d),a):void 0}}();var Gb=/^margin/,Hb=new RegExp("^("+S+")(?!px)[a-z%]+$","i"),Ib,Jb,Kb=/^(top|right|bottom|left)$/;a.getComputedStyle?(Ib=function(b){return b.ownerDocument.defaultView.opener?b.ownerDocument.defaultView.getComputedStyle(b,null):a.getComputedStyle(b,null)},Jb=function(a,b,c){var d,e,f,g,h=a.style;return c=c||Ib(a),g=c?c.getPropertyValue(b)||c[b]:void 0,c&&(""!==g||m.contains(a.ownerDocument,a)||(g=m.style(a,b)),Hb.test(g)&&Gb.test(b)&&(d=h.width,e=h.minWidth,f=h.maxWidth,h.minWidth=h.maxWidth=h.width=g,g=c.width,h.width=d,h.minWidth=e,h.maxWidth=f)),void 0===g?g:g+""}):y.documentElement.currentStyle&&(Ib=function(a){return a.currentStyle},Jb=function(a,b,c){var d,e,f,g,h=a.style;return c=c||Ib(a),g=c?c[b]:void 0,null==g&&h&&h[b]&&(g=h[b]),Hb.test(g)&&!Kb.test(b)&&(d=h.left,e=a.runtimeStyle,f=e&&e.left,f&&(e.left=a.currentStyle.left),h.left="fontSize"===b?"1em":g,g=h.pixelLeft+"px",h.left=d,f&&(e.left=f)),void 0===g?g:g+""||"auto"});function Lb(a,b){return{get:function(){var c=a();if(null!=c)return c?void delete this.get:(this.get=b).apply(this,arguments)}}}!function(){var b,c,d,e,f,g,h;if(b=y.createElement("div"),b.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",d=b.getElementsByTagName("a")[0],c=d&&d.style){c.cssText="float:left;opacity:.5",k.opacity="0.5"===c.opacity,k.cssFloat=!!c.cssFloat,b.style.backgroundClip="content-box",b.cloneNode(!0).style.backgroundClip="",k.clearCloneStyle="content-box"===b.style.backgroundClip,k.boxSizing=""===c.boxSizing||""===c.MozBoxSizing||""===c.WebkitBoxSizing,m.extend(k,{reliableHiddenOffsets:function(){return null==g&&i(),g},boxSizingReliable:function(){return null==f&&i(),f},pixelPosition:function(){return null==e&&i(),e},reliableMarginRight:function(){return null==h&&i(),h}});function i(){var b,c,d,i;c=y.getElementsByTagName("body")[0],c&&c.style&&(b=y.createElement("div"),d=y.createElement("div"),d.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(d).appendChild(b),b.style.cssText="-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;display:block;margin-top:1%;top:1%;border:1px;padding:1px;width:4px;position:absolute",e=f=!1,h=!0,a.getComputedStyle&&(e="1%"!==(a.getComputedStyle(b,null)||{}).top,f="4px"===(a.getComputedStyle(b,null)||{width:"4px"}).width,i=b.appendChild(y.createElement("div")),i.style.cssText=b.style.cssText="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:0",i.style.marginRight=i.style.width="0",b.style.width="1px",h=!parseFloat((a.getComputedStyle(i,null)||{}).marginRight),b.removeChild(i)),b.innerHTML="<table><tr><td></td><td>t</td></tr></table>",i=b.getElementsByTagName("td"),i[0].style.cssText="margin:0;border:0;padding:0;display:none",g=0===i[0].offsetHeight,g&&(i[0].style.display="",i[1].style.display="none",g=0===i[0].offsetHeight),c.removeChild(d))}}}(),m.swap=function(a,b,c,d){var e,f,g={};for(f in b)g[f]=a.style[f],a.style[f]=b[f];e=c.apply(a,d||[]);for(f in b)a.style[f]=g[f];return e};var Mb=/alpha\([^)]*\)/i,Nb=/opacity\s*=\s*([^)]*)/,Ob=/^(none|table(?!-c[ea]).+)/,Pb=new RegExp("^("+S+")(.*)$","i"),Qb=new RegExp("^([+-])=("+S+")","i"),Rb={position:"absolute",visibility:"hidden",display:"block"},Sb={letterSpacing:"0",fontWeight:"400"},Tb=["Webkit","O","Moz","ms"];function Ub(a,b){if(b in a)return b;var c=b.charAt(0).toUpperCase()+b.slice(1),d=b,e=Tb.length;while(e--)if(b=Tb[e]+c,b in a)return b;return d}function Vb(a,b){for(var c,d,e,f=[],g=0,h=a.length;h>g;g++)d=a[g],d.style&&(f[g]=m._data(d,"olddisplay"),c=d.style.display,b?(f[g]||"none"!==c||(d.style.display=""),""===d.style.display&&U(d)&&(f[g]=m._data(d,"olddisplay",Fb(d.nodeName)))):(e=U(d),(c&&"none"!==c||!e)&&m._data(d,"olddisplay",e?c:m.css(d,"display"))));for(g=0;h>g;g++)d=a[g],d.style&&(b&&"none"!==d.style.display&&""!==d.style.display||(d.style.display=b?f[g]||"":"none"));return a}function Wb(a,b,c){var d=Pb.exec(b);return d?Math.max(0,d[1]-(c||0))+(d[2]||"px"):b}function Xb(a,b,c,d,e){for(var f=c===(d?"border":"content")?4:"width"===b?1:0,g=0;4>f;f+=2)"margin"===c&&(g+=m.css(a,c+T[f],!0,e)),d?("content"===c&&(g-=m.css(a,"padding"+T[f],!0,e)),"margin"!==c&&(g-=m.css(a,"border"+T[f]+"Width",!0,e))):(g+=m.css(a,"padding"+T[f],!0,e),"padding"!==c&&(g+=m.css(a,"border"+T[f]+"Width",!0,e)));return g}function Yb(a,b,c){var d=!0,e="width"===b?a.offsetWidth:a.offsetHeight,f=Ib(a),g=k.boxSizing&&"border-box"===m.css(a,"boxSizing",!1,f);if(0>=e||null==e){if(e=Jb(a,b,f),(0>e||null==e)&&(e=a.style[b]),Hb.test(e))return e;d=g&&(k.boxSizingReliable()||e===a.style[b]),e=parseFloat(e)||0}return e+Xb(a,b,c||(g?"border":"content"),d,f)+"px"}m.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=Jb(a,"opacity");return""===c?"1":c}}}},cssNumber:{columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":k.cssFloat?"cssFloat":"styleFloat"},style:function(a,b,c,d){if(a&&3!==a.nodeType&&8!==a.nodeType&&a.style){var e,f,g,h=m.camelCase(b),i=a.style;if(b=m.cssProps[h]||(m.cssProps[h]=Ub(i,h)),g=m.cssHooks[b]||m.cssHooks[h],void 0===c)return g&&"get"in g&&void 0!==(e=g.get(a,!1,d))?e:i[b];if(f=typeof c,"string"===f&&(e=Qb.exec(c))&&(c=(e[1]+1)*e[2]+parseFloat(m.css(a,b)),f="number"),null!=c&&c===c&&("number"!==f||m.cssNumber[h]||(c+="px"),k.clearCloneStyle||""!==c||0!==b.indexOf("background")||(i[b]="inherit"),!(g&&"set"in g&&void 0===(c=g.set(a,c,d)))))try{i[b]=c}catch(j){}}},css:function(a,b,c,d){var e,f,g,h=m.camelCase(b);return b=m.cssProps[h]||(m.cssProps[h]=Ub(a.style,h)),g=m.cssHooks[b]||m.cssHooks[h],g&&"get"in g&&(f=g.get(a,!0,c)),void 0===f&&(f=Jb(a,b,d)),"normal"===f&&b in Sb&&(f=Sb[b]),""===c||c?(e=parseFloat(f),c===!0||m.isNumeric(e)?e||0:f):f}}),m.each(["height","width"],function(a,b){m.cssHooks[b]={get:function(a,c,d){return c?Ob.test(m.css(a,"display"))&&0===a.offsetWidth?m.swap(a,Rb,function(){return Yb(a,b,d)}):Yb(a,b,d):void 0},set:function(a,c,d){var e=d&&Ib(a);return Wb(a,c,d?Xb(a,b,d,k.boxSizing&&"border-box"===m.css(a,"boxSizing",!1,e),e):0)}}}),k.opacity||(m.cssHooks.opacity={get:function(a,b){return Nb.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=m.isNumeric(b)?"alpha(opacity="+100*b+")":"",f=d&&d.filter||c.filter||"";c.zoom=1,(b>=1||""===b)&&""===m.trim(f.replace(Mb,""))&&c.removeAttribute&&(c.removeAttribute("filter"),""===b||d&&!d.filter)||(c.filter=Mb.test(f)?f.replace(Mb,e):f+" "+e)}}),m.cssHooks.marginRight=Lb(k.reliableMarginRight,function(a,b){return b?m.swap(a,{display:"inline-block"},Jb,[a,"marginRight"]):void 0}),m.each({margin:"",padding:"",border:"Width"},function(a,b){m.cssHooks[a+b]={expand:function(c){for(var d=0,e={},f="string"==typeof c?c.split(" "):[c];4>d;d++)e[a+T[d]+b]=f[d]||f[d-2]||f[0];return e}},Gb.test(a)||(m.cssHooks[a+b].set=Wb)}),m.fn.extend({css:function(a,b){return V(this,function(a,b,c){var d,e,f={},g=0;if(m.isArray(b)){for(d=Ib(a),e=b.length;e>g;g++)f[b[g]]=m.css(a,b[g],!1,d);return f}return void 0!==c?m.style(a,b,c):m.css(a,b)},a,b,arguments.length>1)},show:function(){return Vb(this,!0)},hide:function(){return Vb(this)},toggle:function(a){return"boolean"==typeof a?a?this.show():this.hide():this.each(function(){U(this)?m(this).show():m(this).hide()})}});function Zb(a,b,c,d,e){return new Zb.prototype.init(a,b,c,d,e)
4}m.Tween=Zb,Zb.prototype={constructor:Zb,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||"swing",this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(m.cssNumber[c]?"":"px")},cur:function(){var a=Zb.propHooks[this.prop];return a&&a.get?a.get(this):Zb.propHooks._default.get(this)},run:function(a){var b,c=Zb.propHooks[this.prop];return this.pos=b=this.options.duration?m.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):Zb.propHooks._default.set(this),this}},Zb.prototype.init.prototype=Zb.prototype,Zb.propHooks={_default:{get:function(a){var b;return null==a.elem[a.prop]||a.elem.style&&null!=a.elem.style[a.prop]?(b=m.css(a.elem,a.prop,""),b&&"auto"!==b?b:0):a.elem[a.prop]},set:function(a){m.fx.step[a.prop]?m.fx.step[a.prop](a):a.elem.style&&(null!=a.elem.style[m.cssProps[a.prop]]||m.cssHooks[a.prop])?m.style(a.elem,a.prop,a.now+a.unit):a.elem[a.prop]=a.now}}},Zb.propHooks.scrollTop=Zb.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},m.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2}},m.fx=Zb.prototype.init,m.fx.step={};var $b,_b,ac=/^(?:toggle|show|hide)$/,bc=new RegExp("^(?:([+-])=|)("+S+")([a-z%]*)$","i"),cc=/queueHooks$/,dc=[ic],ec={"*":[function(a,b){var c=this.createTween(a,b),d=c.cur(),e=bc.exec(b),f=e&&e[3]||(m.cssNumber[a]?"":"px"),g=(m.cssNumber[a]||"px"!==f&&+d)&&bc.exec(m.css(c.elem,a)),h=1,i=20;if(g&&g[3]!==f){f=f||g[3],e=e||[],g=+d||1;do h=h||".5",g/=h,m.style(c.elem,a,g+f);while(h!==(h=c.cur()/d)&&1!==h&&--i)}return e&&(g=c.start=+g||+d||0,c.unit=f,c.end=e[1]?g+(e[1]+1)*e[2]:+e[2]),c}]};function fc(){return setTimeout(function(){$b=void 0}),$b=m.now()}function gc(a,b){var c,d={height:a},e=0;for(b=b?1:0;4>e;e+=2-b)c=T[e],d["margin"+c]=d["padding"+c]=a;return b&&(d.opacity=d.width=a),d}function hc(a,b,c){for(var d,e=(ec[b]||[]).concat(ec["*"]),f=0,g=e.length;g>f;f++)if(d=e[f].call(c,b,a))return d}function ic(a,b,c){var d,e,f,g,h,i,j,l,n=this,o={},p=a.style,q=a.nodeType&&U(a),r=m._data(a,"fxshow");c.queue||(h=m._queueHooks(a,"fx"),null==h.unqueued&&(h.unqueued=0,i=h.empty.fire,h.empty.fire=function(){h.unqueued||i()}),h.unqueued++,n.always(function(){n.always(function(){h.unqueued--,m.queue(a,"fx").length||h.empty.fire()})})),1===a.nodeType&&("height"in b||"width"in b)&&(c.overflow=[p.overflow,p.overflowX,p.overflowY],j=m.css(a,"display"),l="none"===j?m._data(a,"olddisplay")||Fb(a.nodeName):j,"inline"===l&&"none"===m.css(a,"float")&&(k.inlineBlockNeedsLayout&&"inline"!==Fb(a.nodeName)?p.zoom=1:p.display="inline-block")),c.overflow&&(p.overflow="hidden",k.shrinkWrapBlocks()||n.always(function(){p.overflow=c.overflow[0],p.overflowX=c.overflow[1],p.overflowY=c.overflow[2]}));for(d in b)if(e=b[d],ac.exec(e)){if(delete b[d],f=f||"toggle"===e,e===(q?"hide":"show")){if("show"!==e||!r||void 0===r[d])continue;q=!0}o[d]=r&&r[d]||m.style(a,d)}else j=void 0;if(m.isEmptyObject(o))"inline"===("none"===j?Fb(a.nodeName):j)&&(p.display=j);else{r?"hidden"in r&&(q=r.hidden):r=m._data(a,"fxshow",{}),f&&(r.hidden=!q),q?m(a).show():n.done(function(){m(a).hide()}),n.done(function(){var b;m._removeData(a,"fxshow");for(b in o)m.style(a,b,o[b])});for(d in o)g=hc(q?r[d]:0,d,n),d in r||(r[d]=g.start,q&&(g.end=g.start,g.start="width"===d||"height"===d?1:0))}}function jc(a,b){var c,d,e,f,g;for(c in a)if(d=m.camelCase(c),e=b[d],f=a[c],m.isArray(f)&&(e=f[1],f=a[c]=f[0]),c!==d&&(a[d]=f,delete a[c]),g=m.cssHooks[d],g&&"expand"in g){f=g.expand(f),delete a[d];for(c in f)c in a||(a[c]=f[c],b[c]=e)}else b[d]=e}function kc(a,b,c){var d,e,f=0,g=dc.length,h=m.Deferred().always(function(){delete i.elem}),i=function(){if(e)return!1;for(var b=$b||fc(),c=Math.max(0,j.startTime+j.duration-b),d=c/j.duration||0,f=1-d,g=0,i=j.tweens.length;i>g;g++)j.tweens[g].run(f);return h.notifyWith(a,[j,f,c]),1>f&&i?c:(h.resolveWith(a,[j]),!1)},j=h.promise({elem:a,props:m.extend({},b),opts:m.extend(!0,{specialEasing:{}},c),originalProperties:b,originalOptions:c,startTime:$b||fc(),duration:c.duration,tweens:[],createTween:function(b,c){var d=m.Tween(a,j.opts,b,c,j.opts.specialEasing[b]||j.opts.easing);return j.tweens.push(d),d},stop:function(b){var c=0,d=b?j.tweens.length:0;if(e)return this;for(e=!0;d>c;c++)j.tweens[c].run(1);return b?h.resolveWith(a,[j,b]):h.rejectWith(a,[j,b]),this}}),k=j.props;for(jc(k,j.opts.specialEasing);g>f;f++)if(d=dc[f].call(j,a,k,j.opts))return d;return m.map(k,hc,j),m.isFunction(j.opts.start)&&j.opts.start.call(a,j),m.fx.timer(m.extend(i,{elem:a,anim:j,queue:j.opts.queue})),j.progress(j.opts.progress).done(j.opts.done,j.opts.complete).fail(j.opts.fail).always(j.opts.always)}m.Animation=m.extend(kc,{tweener:function(a,b){m.isFunction(a)?(b=a,a=["*"]):a=a.split(" ");for(var c,d=0,e=a.length;e>d;d++)c=a[d],ec[c]=ec[c]||[],ec[c].unshift(b)},prefilter:function(a,b){b?dc.unshift(a):dc.push(a)}}),m.speed=function(a,b,c){var d=a&&"object"==typeof a?m.extend({},a):{complete:c||!c&&b||m.isFunction(a)&&a,duration:a,easing:c&&b||b&&!m.isFunction(b)&&b};return d.duration=m.fx.off?0:"number"==typeof d.duration?d.duration:d.duration in m.fx.speeds?m.fx.speeds[d.duration]:m.fx.speeds._default,(null==d.queue||d.queue===!0)&&(d.queue="fx"),d.old=d.complete,d.complete=function(){m.isFunction(d.old)&&d.old.call(this),d.queue&&m.dequeue(this,d.queue)},d},m.fn.extend({fadeTo:function(a,b,c,d){return this.filter(U).css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=m.isEmptyObject(a),f=m.speed(b,c,d),g=function(){var b=kc(this,m.extend({},a),f);(e||m._data(this,"finish"))&&b.stop(!0)};return g.finish=g,e||f.queue===!1?this.each(g):this.queue(f.queue,g)},stop:function(a,b,c){var d=function(a){var b=a.stop;delete a.stop,b(c)};return"string"!=typeof a&&(c=b,b=a,a=void 0),b&&a!==!1&&this.queue(a||"fx",[]),this.each(function(){var b=!0,e=null!=a&&a+"queueHooks",f=m.timers,g=m._data(this);if(e)g[e]&&g[e].stop&&d(g[e]);else for(e in g)g[e]&&g[e].stop&&cc.test(e)&&d(g[e]);for(e=f.length;e--;)f[e].elem!==this||null!=a&&f[e].queue!==a||(f[e].anim.stop(c),b=!1,f.splice(e,1));(b||!c)&&m.dequeue(this,a)})},finish:function(a){return a!==!1&&(a=a||"fx"),this.each(function(){var b,c=m._data(this),d=c[a+"queue"],e=c[a+"queueHooks"],f=m.timers,g=d?d.length:0;for(c.finish=!0,m.queue(this,a,[]),e&&e.stop&&e.stop.call(this,!0),b=f.length;b--;)f[b].elem===this&&f[b].queue===a&&(f[b].anim.stop(!0),f.splice(b,1));for(b=0;g>b;b++)d[b]&&d[b].finish&&d[b].finish.call(this);delete c.finish})}}),m.each(["toggle","show","hide"],function(a,b){var c=m.fn[b];m.fn[b]=function(a,d,e){return null==a||"boolean"==typeof a?c.apply(this,arguments):this.animate(gc(b,!0),a,d,e)}}),m.each({slideDown:gc("show"),slideUp:gc("hide"),slideToggle:gc("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){m.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),m.timers=[],m.fx.tick=function(){var a,b=m.timers,c=0;for($b=m.now();c<b.length;c++)a=b[c],a()||b[c]!==a||b.splice(c--,1);b.length||m.fx.stop(),$b=void 0},m.fx.timer=function(a){m.timers.push(a),a()?m.fx.start():m.timers.pop()},m.fx.interval=13,m.fx.start=function(){_b||(_b=setInterval(m.fx.tick,m.fx.interval))},m.fx.stop=function(){clearInterval(_b),_b=null},m.fx.speeds={slow:600,fast:200,_default:400},m.fn.delay=function(a,b){return a=m.fx?m.fx.speeds[a]||a:a,b=b||"fx",this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},function(){var a,b,c,d,e;b=y.createElement("div"),b.setAttribute("className","t"),b.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",d=b.getElementsByTagName("a")[0],c=y.createElement("select"),e=c.appendChild(y.createElement("option")),a=b.getElementsByTagName("input")[0],d.style.cssText="top:1px",k.getSetAttribute="t"!==b.className,k.style=/top/.test(d.getAttribute("style")),k.hrefNormalized="/a"===d.getAttribute("href"),k.checkOn=!!a.value,k.optSelected=e.selected,k.enctype=!!y.createElement("form").enctype,c.disabled=!0,k.optDisabled=!e.disabled,a=y.createElement("input"),a.setAttribute("value",""),k.input=""===a.getAttribute("value"),a.value="t",a.setAttribute("type","radio"),k.radioValue="t"===a.value}();var lc=/\r/g;m.fn.extend({val:function(a){var b,c,d,e=this[0];{if(arguments.length)return d=m.isFunction(a),this.each(function(c){var e;1===this.nodeType&&(e=d?a.call(this,c,m(this).val()):a,null==e?e="":"number"==typeof e?e+="":m.isArray(e)&&(e=m.map(e,function(a){return null==a?"":a+""})),b=m.valHooks[this.type]||m.valHooks[this.nodeName.toLowerCase()],b&&"set"in b&&void 0!==b.set(this,e,"value")||(this.value=e))});if(e)return b=m.valHooks[e.type]||m.valHooks[e.nodeName.toLowerCase()],b&&"get"in b&&void 0!==(c=b.get(e,"value"))?c:(c=e.value,"string"==typeof c?c.replace(lc,""):null==c?"":c)}}}),m.extend({valHooks:{option:{get:function(a){var b=m.find.attr(a,"value");return null!=b?b:m.trim(m.text(a))}},select:{get:function(a){for(var b,c,d=a.options,e=a.selectedIndex,f="select-one"===a.type||0>e,g=f?null:[],h=f?e+1:d.length,i=0>e?h:f?e:0;h>i;i++)if(c=d[i],!(!c.selected&&i!==e||(k.optDisabled?c.disabled:null!==c.getAttribute("disabled"))||c.parentNode.disabled&&m.nodeName(c.parentNode,"optgroup"))){if(b=m(c).val(),f)return b;g.push(b)}return g},set:function(a,b){var c,d,e=a.options,f=m.makeArray(b),g=e.length;while(g--)if(d=e[g],m.inArray(m.valHooks.option.get(d),f)>=0)try{d.selected=c=!0}catch(h){d.scrollHeight}else d.selected=!1;return c||(a.selectedIndex=-1),e}}}}),m.each(["radio","checkbox"],function(){m.valHooks[this]={set:function(a,b){return m.isArray(b)?a.checked=m.inArray(m(a).val(),b)>=0:void 0}},k.checkOn||(m.valHooks[this].get=function(a){return null===a.getAttribute("value")?"on":a.value})});var mc,nc,oc=m.expr.attrHandle,pc=/^(?:checked|selected)$/i,qc=k.getSetAttribute,rc=k.input;m.fn.extend({attr:function(a,b){return V(this,m.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){m.removeAttr(this,a)})}}),m.extend({attr:function(a,b,c){var d,e,f=a.nodeType;if(a&&3!==f&&8!==f&&2!==f)return typeof a.getAttribute===K?m.prop(a,b,c):(1===f&&m.isXMLDoc(a)||(b=b.toLowerCase(),d=m.attrHooks[b]||(m.expr.match.bool.test(b)?nc:mc)),void 0===c?d&&"get"in d&&null!==(e=d.get(a,b))?e:(e=m.find.attr(a,b),null==e?void 0:e):null!==c?d&&"set"in d&&void 0!==(e=d.set(a,c,b))?e:(a.setAttribute(b,c+""),c):void m.removeAttr(a,b))},removeAttr:function(a,b){var c,d,e=0,f=b&&b.match(E);if(f&&1===a.nodeType)while(c=f[e++])d=m.propFix[c]||c,m.expr.match.bool.test(c)?rc&&qc||!pc.test(c)?a[d]=!1:a[m.camelCase("default-"+c)]=a[d]=!1:m.attr(a,c,""),a.removeAttribute(qc?c:d)},attrHooks:{type:{set:function(a,b){if(!k.radioValue&&"radio"===b&&m.nodeName(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}}}}),nc={set:function(a,b,c){return b===!1?m.removeAttr(a,c):rc&&qc||!pc.test(c)?a.setAttribute(!qc&&m.propFix[c]||c,c):a[m.camelCase("default-"+c)]=a[c]=!0,c}},m.each(m.expr.match.bool.source.match(/\w+/g),function(a,b){var c=oc[b]||m.find.attr;oc[b]=rc&&qc||!pc.test(b)?function(a,b,d){var e,f;return d||(f=oc[b],oc[b]=e,e=null!=c(a,b,d)?b.toLowerCase():null,oc[b]=f),e}:function(a,b,c){return c?void 0:a[m.camelCase("default-"+b)]?b.toLowerCase():null}}),rc&&qc||(m.attrHooks.value={set:function(a,b,c){return m.nodeName(a,"input")?void(a.defaultValue=b):mc&&mc.set(a,b,c)}}),qc||(mc={set:function(a,b,c){var d=a.getAttributeNode(c);return d||a.setAttributeNode(d=a.ownerDocument.createAttribute(c)),d.value=b+="","value"===c||b===a.getAttribute(c)?b:void 0}},oc.id=oc.name=oc.coords=function(a,b,c){var d;return c?void 0:(d=a.getAttributeNode(b))&&""!==d.value?d.value:null},m.valHooks.button={get:function(a,b){var c=a.getAttributeNode(b);return c&&c.specified?c.value:void 0},set:mc.set},m.attrHooks.contenteditable={set:function(a,b,c){mc.set(a,""===b?!1:b,c)}},m.each(["width","height"],function(a,b){m.attrHooks[b]={set:function(a,c){return""===c?(a.setAttribute(b,"auto"),c):void 0}}})),k.style||(m.attrHooks.style={get:function(a){return a.style.cssText||void 0},set:function(a,b){return a.style.cssText=b+""}});var sc=/^(?:input|select|textarea|button|object)$/i,tc=/^(?:a|area)$/i;m.fn.extend({prop:function(a,b){return V(this,m.prop,a,b,arguments.length>1)},removeProp:function(a){return a=m.propFix[a]||a,this.each(function(){try{this[a]=void 0,delete this[a]}catch(b){}})}}),m.extend({propFix:{"for":"htmlFor","class":"className"},prop:function(a,b,c){var d,e,f,g=a.nodeType;if(a&&3!==g&&8!==g&&2!==g)return f=1!==g||!m.isXMLDoc(a),f&&(b=m.propFix[b]||b,e=m.propHooks[b]),void 0!==c?e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:a[b]=c:e&&"get"in e&&null!==(d=e.get(a,b))?d:a[b]},propHooks:{tabIndex:{get:function(a){var b=m.find.attr(a,"tabindex");return b?parseInt(b,10):sc.test(a.nodeName)||tc.test(a.nodeName)&&a.href?0:-1}}}}),k.hrefNormalized||m.each(["href","src"],function(a,b){m.propHooks[b]={get:function(a){return a.getAttribute(b,4)}}}),k.optSelected||(m.propHooks.selected={get:function(a){var b=a.parentNode;return b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex),null}}),m.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){m.propFix[this.toLowerCase()]=this}),k.enctype||(m.propFix.enctype="encoding");var uc=/[\t\r\n\f]/g;m.fn.extend({addClass:function(a){var b,c,d,e,f,g,h=0,i=this.length,j="string"==typeof a&&a;if(m.isFunction(a))return this.each(function(b){m(this).addClass(a.call(this,b,this.className))});if(j)for(b=(a||"").match(E)||[];i>h;h++)if(c=this[h],d=1===c.nodeType&&(c.className?(" "+c.className+" ").replace(uc," "):" ")){f=0;while(e=b[f++])d.indexOf(" "+e+" ")<0&&(d+=e+" ");g=m.trim(d),c.className!==g&&(c.className=g)}return this},removeClass:function(a){var b,c,d,e,f,g,h=0,i=this.length,j=0===arguments.length||"string"==typeof a&&a;if(m.isFunction(a))return this.each(function(b){m(this).removeClass(a.call(this,b,this.className))});if(j)for(b=(a||"").match(E)||[];i>h;h++)if(c=this[h],d=1===c.nodeType&&(c.className?(" "+c.className+" ").replace(uc," "):"")){f=0;while(e=b[f++])while(d.indexOf(" "+e+" ")>=0)d=d.replace(" "+e+" "," ");g=a?m.trim(d):"",c.className!==g&&(c.className=g)}return this},toggleClass:function(a,b){var c=typeof a;return"boolean"==typeof b&&"string"===c?b?this.addClass(a):this.removeClass(a):this.each(m.isFunction(a)?function(c){m(this).toggleClass(a.call(this,c,this.className,b),b)}:function(){if("string"===c){var b,d=0,e=m(this),f=a.match(E)||[];while(b=f[d++])e.hasClass(b)?e.removeClass(b):e.addClass(b)}else(c===K||"boolean"===c)&&(this.className&&m._data(this,"__className__",this.className),this.className=this.className||a===!1?"":m._data(this,"__className__")||"")})},hasClass:function(a){for(var b=" "+a+" ",c=0,d=this.length;d>c;c++)if(1===this[c].nodeType&&(" "+this[c].className+" ").replace(uc," ").indexOf(b)>=0)return!0;return!1}}),m.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){m.fn[b]=function(a,c){return arguments.length>0?this.on(b,null,a,c):this.trigger(b)}}),m.fn.extend({hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return 1===arguments.length?this.off(a,"**"):this.off(b,a||"**",c)}});var vc=m.now(),wc=/\?/,xc=/(,)|(\[|{)|(}|])|"(?:[^"\\\r\n]|\\["\\\/bfnrt]|\\u[\da-fA-F]{4})*"\s*:?|true|false|null|-?(?!0\d)\d+(?:\.\d+|)(?:[eE][+-]?\d+|)/g;m.parseJSON=function(b){if(a.JSON&&a.JSON.parse)return a.JSON.parse(b+"");var c,d=null,e=m.trim(b+"");return e&&!m.trim(e.replace(xc,function(a,b,e,f){return c&&b&&(d=0),0===d?a:(c=e||b,d+=!f-!e,"")}))?Function("return "+e)():m.error("Invalid JSON: "+b)},m.parseXML=function(b){var c,d;if(!b||"string"!=typeof b)return null;try{a.DOMParser?(d=new DOMParser,c=d.parseFromString(b,"text/xml")):(c=new ActiveXObject("Microsoft.XMLDOM"),c.async="false",c.loadXML(b))}catch(e){c=void 0}return c&&c.documentElement&&!c.getElementsByTagName("parsererror").length||m.error("Invalid XML: "+b),c};var yc,zc,Ac=/#.*$/,Bc=/([?&])_=[^&]*/,Cc=/^(.*?):[ \t]*([^\r\n]*)\r?$/gm,Dc=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Ec=/^(?:GET|HEAD)$/,Fc=/^\/\//,Gc=/^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/,Hc={},Ic={},Jc="*/".concat("*");try{zc=location.href}catch(Kc){zc=y.createElement("a"),zc.href="",zc=zc.href}yc=Gc.exec(zc.toLowerCase())||[];function Lc(a){return function(b,c){"string"!=typeof b&&(c=b,b="*");var d,e=0,f=b.toLowerCase().match(E)||[];if(m.isFunction(c))while(d=f[e++])"+"===d.charAt(0)?(d=d.slice(1)||"*",(a[d]=a[d]||[]).unshift(c)):(a[d]=a[d]||[]).push(c)}}function Mc(a,b,c,d){var e={},f=a===Ic;function g(h){var i;return e[h]=!0,m.each(a[h]||[],function(a,h){var j=h(b,c,d);return"string"!=typeof j||f||e[j]?f?!(i=j):void 0:(b.dataTypes.unshift(j),g(j),!1)}),i}return g(b.dataTypes[0])||!e["*"]&&g("*")}function Nc(a,b){var c,d,e=m.ajaxSettings.flatOptions||{};for(d in b)void 0!==b[d]&&((e[d]?a:c||(c={}))[d]=b[d]);return c&&m.extend(!0,a,c),a}function Oc(a,b,c){var d,e,f,g,h=a.contents,i=a.dataTypes;while("*"===i[0])i.shift(),void 0===e&&(e=a.mimeType||b.getResponseHeader("Content-Type"));if(e)for(g in h)if(h[g]&&h[g].test(e)){i.unshift(g);break}if(i[0]in c)f=i[0];else{for(g in c){if(!i[0]||a.converters[g+" "+i[0]]){f=g;break}d||(d=g)}f=f||d}return f?(f!==i[0]&&i.unshift(f),c[f]):void 0}function Pc(a,b,c,d){var e,f,g,h,i,j={},k=a.dataTypes.slice();if(k[1])for(g in a.converters)j[g.toLowerCase()]=a.converters[g];f=k.shift();while(f)if(a.responseFields[f]&&(c[a.responseFields[f]]=b),!i&&d&&a.dataFilter&&(b=a.dataFilter(b,a.dataType)),i=f,f=k.shift())if("*"===f)f=i;else if("*"!==i&&i!==f){if(g=j[i+" "+f]||j["* "+f],!g)for(e in j)if(h=e.split(" "),h[1]===f&&(g=j[i+" "+h[0]]||j["* "+h[0]])){g===!0?g=j[e]:j[e]!==!0&&(f=h[0],k.unshift(h[1]));break}if(g!==!0)if(g&&a["throws"])b=g(b);else try{b=g(b)}catch(l){return{state:"parsererror",error:g?l:"No conversion from "+i+" to "+f}}}return{state:"success",data:b}}m.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:zc,type:"GET",isLocal:Dc.test(yc[1]),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Jc,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":m.parseJSON,"text xml":m.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(a,b){return b?Nc(Nc(a,m.ajaxSettings),b):Nc(m.ajaxSettings,a)},ajaxPrefilter:Lc(Hc),ajaxTransport:Lc(Ic),ajax:function(a,b){"object"==typeof a&&(b=a,a=void 0),b=b||{};var c,d,e,f,g,h,i,j,k=m.ajaxSetup({},b),l=k.context||k,n=k.context&&(l.nodeType||l.jquery)?m(l):m.event,o=m.Deferred(),p=m.Callbacks("once memory"),q=k.statusCode||{},r={},s={},t=0,u="canceled",v={readyState:0,getResponseHeader:function(a){var b;if(2===t){if(!j){j={};while(b=Cc.exec(f))j[b[1].toLowerCase()]=b[2]}b=j[a.toLowerCase()]}return null==b?null:b},getAllResponseHeaders:function(){return 2===t?f:null},setRequestHeader:function(a,b){var c=a.toLowerCase();return t||(a=s[c]=s[c]||a,r[a]=b),this},overrideMimeType:function(a){return t||(k.mimeType=a),this},statusCode:function(a){var b;if(a)if(2>t)for(b in a)q[b]=[q[b],a[b]];else v.always(a[v.status]);return this},abort:function(a){var b=a||u;return i&&i.abort(b),x(0,b),this}};if(o.promise(v).complete=p.add,v.success=v.done,v.error=v.fail,k.url=((a||k.url||zc)+"").replace(Ac,"").replace(Fc,yc[1]+"//"),k.type=b.method||b.type||k.method||k.type,k.dataTypes=m.trim(k.dataType||"*").toLowerCase().match(E)||[""],null==k.crossDomain&&(c=Gc.exec(k.url.toLowerCase()),k.crossDomain=!(!c||c[1]===yc[1]&&c[2]===yc[2]&&(c[3]||("http:"===c[1]?"80":"443"))===(yc[3]||("http:"===yc[1]?"80":"443")))),k.data&&k.processData&&"string"!=typeof k.data&&(k.data=m.param(k.data,k.traditional)),Mc(Hc,k,b,v),2===t)return v;h=m.event&&k.global,h&&0===m.active++&&m.event.trigger("ajaxStart"),k.type=k.type.toUpperCase(),k.hasContent=!Ec.test(k.type),e=k.url,k.hasContent||(k.data&&(e=k.url+=(wc.test(e)?"&":"?")+k.data,delete k.data),k.cache===!1&&(k.url=Bc.test(e)?e.replace(Bc,"$1_="+vc++):e+(wc.test(e)?"&":"?")+"_="+vc++)),k.ifModified&&(m.lastModified[e]&&v.setRequestHeader("If-Modified-Since",m.lastModified[e]),m.etag[e]&&v.setRequestHeader("If-None-Match",m.etag[e])),(k.data&&k.hasContent&&k.contentType!==!1||b.contentType)&&v.setRequestHeader("Content-Type",k.contentType),v.setRequestHeader("Accept",k.dataTypes[0]&&k.accepts[k.dataTypes[0]]?k.accepts[k.dataTypes[0]]+("*"!==k.dataTypes[0]?", "+Jc+"; q=0.01":""):k.accepts["*"]);for(d in k.headers)v.setRequestHeader(d,k.headers[d]);if(k.beforeSend&&(k.beforeSend.call(l,v,k)===!1||2===t))return v.abort();u="abort";for(d in{success:1,error:1,complete:1})v[d](k[d]);if(i=Mc(Ic,k,b,v)){v.readyState=1,h&&n.trigger("ajaxSend",[v,k]),k.async&&k.timeout>0&&(g=setTimeout(function(){v.abort("timeout")},k.timeout));try{t=1,i.send(r,x)}catch(w){if(!(2>t))throw w;x(-1,w)}}else x(-1,"No Transport");function x(a,b,c,d){var j,r,s,u,w,x=b;2!==t&&(t=2,g&&clearTimeout(g),i=void 0,f=d||"",v.readyState=a>0?4:0,j=a>=200&&300>a||304===a,c&&(u=Oc(k,v,c)),u=Pc(k,u,v,j),j?(k.ifModified&&(w=v.getResponseHeader("Last-Modified"),w&&(m.lastModified[e]=w),w=v.getResponseHeader("etag"),w&&(m.etag[e]=w)),204===a||"HEAD"===k.type?x="nocontent":304===a?x="notmodified":(x=u.state,r=u.data,s=u.error,j=!s)):(s=x,(a||!x)&&(x="error",0>a&&(a=0))),v.status=a,v.statusText=(b||x)+"",j?o.resolveWith(l,[r,x,v]):o.rejectWith(l,[v,x,s]),v.statusCode(q),q=void 0,h&&n.trigger(j?"ajaxSuccess":"ajaxError",[v,k,j?r:s]),p.fireWith(l,[v,x]),h&&(n.trigger("ajaxComplete",[v,k]),--m.active||m.event.trigger("ajaxStop")))}return v},getJSON:function(a,b,c){return m.get(a,b,c,"json")},getScript:function(a,b){return m.get(a,void 0,b,"script")}}),m.each(["get","post"],function(a,b){m[b]=function(a,c,d,e){return m.isFunction(c)&&(e=e||d,d=c,c=void 0),m.ajax({url:a,type:b,dataType:e,data:c,success:d})}}),m._evalUrl=function(a){return m.ajax({url:a,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0})},m.fn.extend({wrapAll:function(a){if(m.isFunction(a))return this.each(function(b){m(this).wrapAll(a.call(this,b))});if(this[0]){var b=m(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&1===a.firstChild.nodeType)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){return this.each(m.isFunction(a)?function(b){m(this).wrapInner(a.call(this,b))}:function(){var b=m(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=m.isFunction(a);return this.each(function(c){m(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){m.nodeName(this,"body")||m(this).replaceWith(this.childNodes)}).end()}}),m.expr.filters.hidden=function(a){return a.offsetWidth<=0&&a.offsetHeight<=0||!k.reliableHiddenOffsets()&&"none"===(a.style&&a.style.display||m.css(a,"display"))},m.expr.filters.visible=function(a){return!m.expr.filters.hidden(a)};var Qc=/%20/g,Rc=/\[\]$/,Sc=/\r?\n/g,Tc=/^(?:submit|button|image|reset|file)$/i,Uc=/^(?:input|select|textarea|keygen)/i;function Vc(a,b,c,d){var e;if(m.isArray(b))m.each(b,function(b,e){c||Rc.test(a)?d(a,e):Vc(a+"["+("object"==typeof e?b:"")+"]",e,c,d)});else if(c||"object"!==m.type(b))d(a,b);else for(e in b)Vc(a+"["+e+"]",b[e],c,d)}m.param=function(a,b){var c,d=[],e=function(a,b){b=m.isFunction(b)?b():null==b?"":b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};if(void 0===b&&(b=m.ajaxSettings&&m.ajaxSettings.traditional),m.isArray(a)||a.jquery&&!m.isPlainObject(a))m.each(a,function(){e(this.name,this.value)});else for(c in a)Vc(c,a[c],b,e);return d.join("&").replace(Qc,"+")},m.fn.extend({serialize:function(){return m.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var a=m.prop(this,"elements");return a?m.makeArray(a):this}).filter(function(){var a=this.type;return this.name&&!m(this).is(":disabled")&&Uc.test(this.nodeName)&&!Tc.test(a)&&(this.checked||!W.test(a))}).map(function(a,b){var c=m(this).val();return null==c?null:m.isArray(c)?m.map(c,function(a){return{name:b.name,value:a.replace(Sc,"\r\n")}}):{name:b.name,value:c.replace(Sc,"\r\n")}}).get()}}),m.ajaxSettings.xhr=void 0!==a.ActiveXObject?function(){return!this.isLocal&&/^(get|post|head|put|delete|options)$/i.test(this.type)&&Zc()||$c()}:Zc;var Wc=0,Xc={},Yc=m.ajaxSettings.xhr();a.attachEvent&&a.attachEvent("onunload",function(){for(var a in Xc)Xc[a](void 0,!0)}),k.cors=!!Yc&&"withCredentials"in Yc,Yc=k.ajax=!!Yc,Yc&&m.ajaxTransport(function(a){if(!a.crossDomain||k.cors){var b;return{send:function(c,d){var e,f=a.xhr(),g=++Wc;if(f.open(a.type,a.url,a.async,a.username,a.password),a.xhrFields)for(e in a.xhrFields)f[e]=a.xhrFields[e];a.mimeType&&f.overrideMimeType&&f.overrideMimeType(a.mimeType),a.crossDomain||c["X-Requested-With"]||(c["X-Requested-With"]="XMLHttpRequest");for(e in c)void 0!==c[e]&&f.setRequestHeader(e,c[e]+"");f.send(a.hasContent&&a.data||null),b=function(c,e){var h,i,j;if(b&&(e||4===f.readyState))if(delete Xc[g],b=void 0,f.onreadystatechange=m.noop,e)4!==f.readyState&&f.abort();else{j={},h=f.status,"string"==typeof f.responseText&&(j.text=f.responseText);try{i=f.statusText}catch(k){i=""}h||!a.isLocal||a.crossDomain?1223===h&&(h=204):h=j.text?200:404}j&&d(h,i,j,f.getAllResponseHeaders())},a.async?4===f.readyState?setTimeout(b):f.onreadystatechange=Xc[g]=b:b()},abort:function(){b&&b(void 0,!0)}}}});function Zc(){try{return new a.XMLHttpRequest}catch(b){}}function $c(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}m.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/(?:java|ecma)script/},converters:{"text script":function(a){return m.globalEval(a),a}}}),m.ajaxPrefilter("script",function(a){void 0===a.cache&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),m.ajaxTransport("script",function(a){if(a.crossDomain){var b,c=y.head||m("head")[0]||y.documentElement;return{send:function(d,e){b=y.createElement("script"),b.async=!0,a.scriptCharset&&(b.charset=a.scriptCharset),b.src=a.url,b.onload=b.onreadystatechange=function(a,c){(c||!b.readyState||/loaded|complete/.test(b.readyState))&&(b.onload=b.onreadystatechange=null,b.parentNode&&b.parentNode.removeChild(b),b=null,c||e(200,"success"))},c.insertBefore(b,c.firstChild)},abort:function(){b&&b.onload(void 0,!0)}}}});var _c=[],ad=/(=)\?(?=&|$)|\?\?/;m.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=_c.pop()||m.expando+"_"+vc++;return this[a]=!0,a}}),m.ajaxPrefilter("json jsonp",function(b,c,d){var e,f,g,h=b.jsonp!==!1&&(ad.test(b.url)?"url":"string"==typeof b.data&&!(b.contentType||"").indexOf("application/x-www-form-urlencoded")&&ad.test(b.data)&&"data");return h||"jsonp"===b.dataTypes[0]?(e=b.jsonpCallback=m.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,h?b[h]=b[h].replace(ad,"$1"+e):b.jsonp!==!1&&(b.url+=(wc.test(b.url)?"&":"?")+b.jsonp+"="+e),b.converters["script json"]=function(){return g||m.error(e+" was not called"),g[0]},b.dataTypes[0]="json",f=a[e],a[e]=function(){g=arguments},d.always(function(){a[e]=f,b[e]&&(b.jsonpCallback=c.jsonpCallback,_c.push(e)),g&&m.isFunction(f)&&f(g[0]),g=f=void 0}),"script"):void 0}),m.parseHTML=function(a,b,c){if(!a||"string"!=typeof a)return null;"boolean"==typeof b&&(c=b,b=!1),b=b||y;var d=u.exec(a),e=!c&&[];return d?[b.createElement(d[1])]:(d=m.buildFragment([a],b,e),e&&e.length&&m(e).remove(),m.merge([],d.childNodes))};var bd=m.fn.load;m.fn.load=function(a,b,c){if("string"!=typeof a&&bd)return bd.apply(this,arguments);var d,e,f,g=this,h=a.indexOf(" ");return h>=0&&(d=m.trim(a.slice(h,a.length)),a=a.slice(0,h)),m.isFunction(b)?(c=b,b=void 0):b&&"object"==typeof b&&(f="POST"),g.length>0&&m.ajax({url:a,type:f,dataType:"html",data:b}).done(function(a){e=arguments,g.html(d?m("<div>").append(m.parseHTML(a)).find(d):a)}).complete(c&&function(a,b){g.each(c,e||[a.responseText,b,a])}),this},m.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(a,b){m.fn[b]=function(a){return this.on(b,a)}}),m.expr.filters.animated=function(a){return m.grep(m.timers,function(b){return a===b.elem}).length};var cd=a.document.documentElement;function dd(a){return m.isWindow(a)?a:9===a.nodeType?a.defaultView||a.parentWindow:!1}m.offset={setOffset:function(a,b,c){var d,e,f,g,h,i,j,k=m.css(a,"position"),l=m(a),n={};"static"===k&&(a.style.position="relative"),h=l.offset(),f=m.css(a,"top"),i=m.css(a,"left"),j=("absolute"===k||"fixed"===k)&&m.inArray("auto",[f,i])>-1,j?(d=l.position(),g=d.top,e=d.left):(g=parseFloat(f)||0,e=parseFloat(i)||0),m.isFunction(b)&&(b=b.call(a,c,h)),null!=b.top&&(n.top=b.top-h.top+g),null!=b.left&&(n.left=b.left-h.left+e),"using"in b?b.using.call(a,n):l.css(n)}},m.fn.extend({offset:function(a){if(arguments.length)return void 0===a?this:this.each(function(b){m.offset.setOffset(this,a,b)});var b,c,d={top:0,left:0},e=this[0],f=e&&e.ownerDocument;if(f)return b=f.documentElement,m.contains(b,e)?(typeof e.getBoundingClientRect!==K&&(d=e.getBoundingClientRect()),c=dd(f),{top:d.top+(c.pageYOffset||b.scrollTop)-(b.clientTop||0),left:d.left+(c.pageXOffset||b.scrollLeft)-(b.clientLeft||0)}):d},position:function(){if(this[0]){var a,b,c={top:0,left:0},d=this[0];return"fixed"===m.css(d,"position")?b=d.getBoundingClientRect():(a=this.offsetParent(),b=this.offset(),m.nodeName(a[0],"html")||(c=a.offset()),c.top+=m.css(a[0],"borderTopWidth",!0),c.left+=m.css(a[0],"borderLeftWidth",!0)),{top:b.top-c.top-m.css(d,"marginTop",!0),left:b.left-c.left-m.css(d,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||cd;while(a&&!m.nodeName(a,"html")&&"static"===m.css(a,"position"))a=a.offsetParent;return a||cd})}}),m.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,b){var c=/Y/.test(b);m.fn[a]=function(d){return V(this,function(a,d,e){var f=dd(a);return void 0===e?f?b in f?f[b]:f.document.documentElement[d]:a[d]:void(f?f.scrollTo(c?m(f).scrollLeft():e,c?e:m(f).scrollTop()):a[d]=e)},a,d,arguments.length,null)}}),m.each(["top","left"],function(a,b){m.cssHooks[b]=Lb(k.pixelPosition,function(a,c){return c?(c=Jb(a,b),Hb.test(c)?m(a).position()[b]+"px":c):void 0})}),m.each({Height:"height",Width:"width"},function(a,b){m.each({padding:"inner"+a,content:b,"":"outer"+a},function(c,d){m.fn[d]=function(d,e){var f=arguments.length&&(c||"boolean"!=typeof d),g=c||(d===!0||e===!0?"margin":"border");return V(this,function(b,c,d){var e;return m.isWindow(b)?b.document.documentElement["client"+a]:9===b.nodeType?(e=b.documentElement,Math.max(b.body["scroll"+a],e["scroll"+a],b.body["offset"+a],e["offset"+a],e["client"+a])):void 0===d?m.css(b,c,g):m.style(b,c,d,g)},b,f?d:void 0,f,null)}})}),m.fn.size=function(){return this.length},m.fn.andSelf=m.fn.addBack,"function"==typeof define&&define.amd&&define("jquery",[],function(){return m});var ed=a.jQuery,fd=a.$;return m.noConflict=function(b){return a.$===m&&(a.$=fd),b&&a.jQuery===m&&(a.jQuery=ed),m},typeof b===K&&(a.jQuery=a.$=m),m});
diff --git a/plugins/playvideos/playvideos.html b/plugins/playvideos/playvideos.html
new file mode 100644
index 00000000..fda3d54f
--- /dev/null
+++ b/plugins/playvideos/playvideos.html
@@ -0,0 +1 @@
<a href="#" id="playvideos">► Play Videos</a> \ No newline at end of file
diff --git a/plugins/playvideos/playvideos.php b/plugins/playvideos/playvideos.php
new file mode 100644
index 00000000..0a80aa58
--- /dev/null
+++ b/plugins/playvideos/playvideos.php
@@ -0,0 +1,40 @@
1<?php
2/**
3 * Plugin PlayVideos
4 *
5 * Add a button in the toolbar allowing to watch all videos.
6 * Note: this plugin adds jQuery.
7 */
8
9/**
10 * When linklist is displayed, add play videos to header's toolbar.
11 *
12 * @param array $data - header data.
13 *
14 * @return mixed - header data with playvideos toolbar item.
15 */
16function hook_playvideos_render_header($data)
17{
18 if ($data['_PAGE_'] == Router::$PAGE_LINKLIST) {
19 $data['buttons_toolbar'][] = file_get_contents(PluginManager::$PLUGINS_PATH . '/playvideos/playvideos.html');
20 }
21
22 return $data;
23}
24
25/**
26 * When linklist is displayed, include playvideos JS files.
27 *
28 * @param array $data - footer data.
29 *
30 * @return mixed - footer data with playvideos JS files added.
31 */
32function hook_playvideos_render_footer($data)
33{
34 if ($data['_PAGE_'] == Router::$PAGE_LINKLIST) {
35 $data['js_files'][] = PluginManager::$PLUGINS_PATH . '/playvideos/jquery-1.11.2.min.js';
36 $data['js_files'][] = PluginManager::$PLUGINS_PATH . '/playvideos/youtube_playlist.js';
37 }
38
39 return $data;
40} \ No newline at end of file
diff --git a/plugins/playvideos/youtube_playlist.js b/plugins/playvideos/youtube_playlist.js
new file mode 100644
index 00000000..be8d63af
--- /dev/null
+++ b/plugins/playvideos/youtube_playlist.js
@@ -0,0 +1,196 @@
1var run_playideos = (function () {
2 var e, n, t, o, r, i = [].indexOf || function (e) {
3 for (var n = 0, t = this.length; n < t; n++) {
4 if (n in this && this[n] === e) return n
5 }
6 return -1
7 };
8 if (!window.console) {
9 window.console = {
10 log: function () {}
11 }
12 }
13 n = {
14 shadow: {
15 "background-color": "black",
16 position: "fixed",
17 left: 0,
18 top: 0,
19 width: "100%",
20 height: "100%",
21 "z-index": 1e3,
22 opacity: .8
23 },
24 player_box: {
25 position: "fixed",
26 left: "50%",
27 top: "50%",
28 width: 640,
29 height: 480,
30 "margin-left": -320,
31 "margin-top": -240,
32 "z-index": 1001
33 },
34 prev_button: {
35 "float": "left"
36 },
37 next_button: {
38 "float": "right"
39 }
40 };
41 t = function (e, n) {
42 var t, o, r;
43 r = document.createElement("script");
44 r.src = e;
45 o = document.getElementsByTagName("head")[0];
46 t = false;
47 r.onload = r.onreadystatechange = function () {
48 var e, i;
49 e = !this.readyState || (i = this.readyState) === "loaded" || i === "complete";
50 if (!t && e) {
51 t = true;
52 n();
53 r.onload = r.onreadystatechange = null;
54 return o.removeChild(r)
55 }
56 };
57 return o.appendChild(r)
58 };
59 e = function (e) {
60 var t, o, r, a, u, l, d, c, f, p, s, y, h, g, v, m, w;
61 e.getScript("//www.youtube.com/iframe_api");
62 d = [];
63 w = new RegExp("https?://(www.)?youtube.com/");
64 e('a[href^="http"]').each(function () {
65 var n;
66 if (!e(this).attr("href").match(w)) {
67 return
68 }
69 n = this.href.replace(/^.*v=/, "").replace(/\&.*$/, "");
70 if (i.call(d, n) < 0) {
71 return d.push(n)
72 }
73 });
74 console.log("video ids", d);
75 c = 0;
76 y = null;
77 g = "playlist_player";
78 f = function () {
79 console.log("Playing", c, d[c]);
80 return y.loadVideoById(d[c])
81 };
82 p = function () {
83 c++;
84 if (c >= d.length) {
85 c -= d.length
86 }
87 return f()
88 };
89 s = function () {
90 c--;
91 if (c < 0) {
92 c += d.length
93 }
94 return f()
95 };
96 l = function () {
97 e("#shadow, #player_box").remove();
98 return e(document).unbind("keyup.player")
99 };
100 e(document).bind("keyup.player", function (e) {
101 if (e.keyCode === 27) {
102 l()
103 }
104 if (e.keyCode === 39) {
105 p()
106 }
107 if (e.keyCode === 37) {
108 return s()
109 }
110 });
111 u = e("<div />", {
112 id: "shadow",
113 css: n.shadow,
114 click: l
115 });
116 r = e("<div />", {
117 id: "player_box",
118 css: n.player_box
119 });
120 o = e("<div />", {
121 id: g
122 });
123 a = e("<a />", {
124 href: "javascript:;",
125 text: "previous",
126 css: n.prev_button,
127 click: s
128 });
129 t = e("<a />", {
130 href: "javascript:;",
131 text: "next",
132 css: n.next_button,
133 click: p
134 });
135 r.append(o).append(a).append(t);
136 e("body").append(u).append(r);
137 v = function (e) {
138 console.log("player ready");
139 return e.target.playVideo()
140 };
141 h = function (e) {
142 var n, t;
143 n = {
144 2: "invalid video id",
145 5: "video not supported in html5",
146 100: "video removed or private",
147 101: "video not embedable",
148 150: "video not embedable"
149 };
150 t = n[e.data] || "unknown error";
151 console.log("Error", t);
152 d.splice(c, 1);
153 if (c >= d.length) {
154 c = 0
155 }
156 return f()
157 };
158 m = function (e) {
159 if (e.data === YT.PlayerState.ENDED) {
160 return p()
161 }
162 };
163 return window.onYouTubeIframeAPIReady = function () {
164 return y = new YT.Player(g, {
165 height: "390",
166 width: "640",
167 videoId: d[0],
168 events: {
169 onReady: v,
170 onError: h,
171 onStateChange: m
172 }
173 })
174 }
175 };
176 o = false;
177 if (typeof jQuery !== "undefined" && jQuery !== null && jQuery.fn && jQuery.fn.jquery) {
178 r = jQuery.fn.jquery.split(".");
179 if (r.length === 3 && parseInt(r[1]) > 3) {
180 console.log("using in page jquery version", jQuery.fn.jquery);
181 e(jQuery);
182 o = true
183 }
184 }
185 if (!o) {
186 t("plugins/playvideos/jquery-1.11.2.min.js", function () {
187 return e(jQuery.noConflict(true))
188 })
189 }
190});
191
192var input = document.querySelector('#playvideos');
193input.addEventListener('click', function()
194{
195 run_playideos();
196});
diff --git a/plugins/qrcode/qr-1.1.3.js b/plugins/qrcode/qr-1.1.3.js
new file mode 100644
index 00000000..4f127e6e
--- /dev/null
+++ b/plugins/qrcode/qr-1.1.3.js
@@ -0,0 +1,1215 @@
1// [qr.js](http://neocotic.com/qr.js)
2// (c) 2014 Alasdair Mercer
3// Licensed under the GPL Version 3 license.
4// Based on [jsqrencode](http://code.google.com/p/jsqrencode/)
5// (c) 2010 tz@execpc.com
6// Licensed under the GPL Version 3 license.
7// For all details and documentation:
8// <http://neocotic.com/qr.js>
9
10(function (root) {
11
12 'use strict';
13
14 // Private constants
15 // -----------------
16
17 // Alignment pattern.
18 var ALIGNMENT_DELTA = [
19 0, 11, 15, 19, 23, 27, 31,
20 16, 18, 20, 22, 24, 26, 28, 20, 22, 24, 24, 26, 28, 28, 22, 24, 24,
21 26, 26, 28, 28, 24, 24, 26, 26, 26, 28, 28, 24, 26, 26, 26, 28, 28
22 ];
23 // Default MIME type.
24 var DEFAULT_MIME = 'image/png';
25 // MIME used to initiate a browser download prompt when `qr.save` is called.
26 var DOWNLOAD_MIME = 'image/octet-stream';
27 // There are four elements per version. The first two indicate the number of blocks, then the
28 // data width, and finally the ECC width.
29 var ECC_BLOCKS = [
30 1, 0, 19, 7, 1, 0, 16, 10, 1, 0, 13, 13, 1, 0, 9, 17,
31 1, 0, 34, 10, 1, 0, 28, 16, 1, 0, 22, 22, 1, 0, 16, 28,
32 1, 0, 55, 15, 1, 0, 44, 26, 2, 0, 17, 18, 2, 0, 13, 22,
33 1, 0, 80, 20, 2, 0, 32, 18, 2, 0, 24, 26, 4, 0, 9, 16,
34 1, 0, 108, 26, 2, 0, 43, 24, 2, 2, 15, 18, 2, 2, 11, 22,
35 2, 0, 68, 18, 4, 0, 27, 16, 4, 0, 19, 24, 4, 0, 15, 28,
36 2, 0, 78, 20, 4, 0, 31, 18, 2, 4, 14, 18, 4, 1, 13, 26,
37 2, 0, 97, 24, 2, 2, 38, 22, 4, 2, 18, 22, 4, 2, 14, 26,
38 2, 0, 116, 30, 3, 2, 36, 22, 4, 4, 16, 20, 4, 4, 12, 24,
39 2, 2, 68, 18, 4, 1, 43, 26, 6, 2, 19, 24, 6, 2, 15, 28,
40 4, 0, 81, 20, 1, 4, 50, 30, 4, 4, 22, 28, 3, 8, 12, 24,
41 2, 2, 92, 24, 6, 2, 36, 22, 4, 6, 20, 26, 7, 4, 14, 28,
42 4, 0, 107, 26, 8, 1, 37, 22, 8, 4, 20, 24, 12, 4, 11, 22,
43 3, 1, 115, 30, 4, 5, 40, 24, 11, 5, 16, 20, 11, 5, 12, 24,
44 5, 1, 87, 22, 5, 5, 41, 24, 5, 7, 24, 30, 11, 7, 12, 24,
45 5, 1, 98, 24, 7, 3, 45, 28, 15, 2, 19, 24, 3, 13, 15, 30,
46 1, 5, 107, 28, 10, 1, 46, 28, 1, 15, 22, 28, 2, 17, 14, 28,
47 5, 1, 120, 30, 9, 4, 43, 26, 17, 1, 22, 28, 2, 19, 14, 28,
48 3, 4, 113, 28, 3, 11, 44, 26, 17, 4, 21, 26, 9, 16, 13, 26,
49 3, 5, 107, 28, 3, 13, 41, 26, 15, 5, 24, 30, 15, 10, 15, 28,
50 4, 4, 116, 28, 17, 0, 42, 26, 17, 6, 22, 28, 19, 6, 16, 30,
51 2, 7, 111, 28, 17, 0, 46, 28, 7, 16, 24, 30, 34, 0, 13, 24,
52 4, 5, 121, 30, 4, 14, 47, 28, 11, 14, 24, 30, 16, 14, 15, 30,
53 6, 4, 117, 30, 6, 14, 45, 28, 11, 16, 24, 30, 30, 2, 16, 30,
54 8, 4, 106, 26, 8, 13, 47, 28, 7, 22, 24, 30, 22, 13, 15, 30,
55 10, 2, 114, 28, 19, 4, 46, 28, 28, 6, 22, 28, 33, 4, 16, 30,
56 8, 4, 122, 30, 22, 3, 45, 28, 8, 26, 23, 30, 12, 28, 15, 30,
57 3, 10, 117, 30, 3, 23, 45, 28, 4, 31, 24, 30, 11, 31, 15, 30,
58 7, 7, 116, 30, 21, 7, 45, 28, 1, 37, 23, 30, 19, 26, 15, 30,
59 5, 10, 115, 30, 19, 10, 47, 28, 15, 25, 24, 30, 23, 25, 15, 30,
60 13, 3, 115, 30, 2, 29, 46, 28, 42, 1, 24, 30, 23, 28, 15, 30,
61 17, 0, 115, 30, 10, 23, 46, 28, 10, 35, 24, 30, 19, 35, 15, 30,
62 17, 1, 115, 30, 14, 21, 46, 28, 29, 19, 24, 30, 11, 46, 15, 30,
63 13, 6, 115, 30, 14, 23, 46, 28, 44, 7, 24, 30, 59, 1, 16, 30,
64 12, 7, 121, 30, 12, 26, 47, 28, 39, 14, 24, 30, 22, 41, 15, 30,
65 6, 14, 121, 30, 6, 34, 47, 28, 46, 10, 24, 30, 2, 64, 15, 30,
66 17, 4, 122, 30, 29, 14, 46, 28, 49, 10, 24, 30, 24, 46, 15, 30,
67 4, 18, 122, 30, 13, 32, 46, 28, 48, 14, 24, 30, 42, 32, 15, 30,
68 20, 4, 117, 30, 40, 7, 47, 28, 43, 22, 24, 30, 10, 67, 15, 30,
69 19, 6, 118, 30, 18, 31, 47, 28, 34, 34, 24, 30, 20, 61, 15, 30
70 ];
71 // Map of human-readable ECC levels.
72 var ECC_LEVELS = {
73 L: 1,
74 M: 2,
75 Q: 3,
76 H: 4
77 };
78 // Final format bits with mask (level << 3 | mask).
79 var FINAL_FORMAT = [
80 0x77c4, 0x72f3, 0x7daa, 0x789d, 0x662f, 0x6318, 0x6c41, 0x6976, /* L */
81 0x5412, 0x5125, 0x5e7c, 0x5b4b, 0x45f9, 0x40ce, 0x4f97, 0x4aa0, /* M */
82 0x355f, 0x3068, 0x3f31, 0x3a06, 0x24b4, 0x2183, 0x2eda, 0x2bed, /* Q */
83 0x1689, 0x13be, 0x1ce7, 0x19d0, 0x0762, 0x0255, 0x0d0c, 0x083b /* H */
84 ];
85 // Galois field exponent table.
86 var GALOIS_EXPONENT = [
87 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1d, 0x3a, 0x74, 0xe8, 0xcd, 0x87, 0x13, 0x26,
88 0x4c, 0x98, 0x2d, 0x5a, 0xb4, 0x75, 0xea, 0xc9, 0x8f, 0x03, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0,
89 0x9d, 0x27, 0x4e, 0x9c, 0x25, 0x4a, 0x94, 0x35, 0x6a, 0xd4, 0xb5, 0x77, 0xee, 0xc1, 0x9f, 0x23,
90 0x46, 0x8c, 0x05, 0x0a, 0x14, 0x28, 0x50, 0xa0, 0x5d, 0xba, 0x69, 0xd2, 0xb9, 0x6f, 0xde, 0xa1,
91 0x5f, 0xbe, 0x61, 0xc2, 0x99, 0x2f, 0x5e, 0xbc, 0x65, 0xca, 0x89, 0x0f, 0x1e, 0x3c, 0x78, 0xf0,
92 0xfd, 0xe7, 0xd3, 0xbb, 0x6b, 0xd6, 0xb1, 0x7f, 0xfe, 0xe1, 0xdf, 0xa3, 0x5b, 0xb6, 0x71, 0xe2,
93 0xd9, 0xaf, 0x43, 0x86, 0x11, 0x22, 0x44, 0x88, 0x0d, 0x1a, 0x34, 0x68, 0xd0, 0xbd, 0x67, 0xce,
94 0x81, 0x1f, 0x3e, 0x7c, 0xf8, 0xed, 0xc7, 0x93, 0x3b, 0x76, 0xec, 0xc5, 0x97, 0x33, 0x66, 0xcc,
95 0x85, 0x17, 0x2e, 0x5c, 0xb8, 0x6d, 0xda, 0xa9, 0x4f, 0x9e, 0x21, 0x42, 0x84, 0x15, 0x2a, 0x54,
96 0xa8, 0x4d, 0x9a, 0x29, 0x52, 0xa4, 0x55, 0xaa, 0x49, 0x92, 0x39, 0x72, 0xe4, 0xd5, 0xb7, 0x73,
97 0xe6, 0xd1, 0xbf, 0x63, 0xc6, 0x91, 0x3f, 0x7e, 0xfc, 0xe5, 0xd7, 0xb3, 0x7b, 0xf6, 0xf1, 0xff,
98 0xe3, 0xdb, 0xab, 0x4b, 0x96, 0x31, 0x62, 0xc4, 0x95, 0x37, 0x6e, 0xdc, 0xa5, 0x57, 0xae, 0x41,
99 0x82, 0x19, 0x32, 0x64, 0xc8, 0x8d, 0x07, 0x0e, 0x1c, 0x38, 0x70, 0xe0, 0xdd, 0xa7, 0x53, 0xa6,
100 0x51, 0xa2, 0x59, 0xb2, 0x79, 0xf2, 0xf9, 0xef, 0xc3, 0x9b, 0x2b, 0x56, 0xac, 0x45, 0x8a, 0x09,
101 0x12, 0x24, 0x48, 0x90, 0x3d, 0x7a, 0xf4, 0xf5, 0xf7, 0xf3, 0xfb, 0xeb, 0xcb, 0x8b, 0x0b, 0x16,
102 0x2c, 0x58, 0xb0, 0x7d, 0xfa, 0xe9, 0xcf, 0x83, 0x1b, 0x36, 0x6c, 0xd8, 0xad, 0x47, 0x8e, 0x00
103 ];
104 // Galois field log table.
105 var GALOIS_LOG = [
106 0xff, 0x00, 0x01, 0x19, 0x02, 0x32, 0x1a, 0xc6, 0x03, 0xdf, 0x33, 0xee, 0x1b, 0x68, 0xc7, 0x4b,
107 0x04, 0x64, 0xe0, 0x0e, 0x34, 0x8d, 0xef, 0x81, 0x1c, 0xc1, 0x69, 0xf8, 0xc8, 0x08, 0x4c, 0x71,
108 0x05, 0x8a, 0x65, 0x2f, 0xe1, 0x24, 0x0f, 0x21, 0x35, 0x93, 0x8e, 0xda, 0xf0, 0x12, 0x82, 0x45,
109 0x1d, 0xb5, 0xc2, 0x7d, 0x6a, 0x27, 0xf9, 0xb9, 0xc9, 0x9a, 0x09, 0x78, 0x4d, 0xe4, 0x72, 0xa6,
110 0x06, 0xbf, 0x8b, 0x62, 0x66, 0xdd, 0x30, 0xfd, 0xe2, 0x98, 0x25, 0xb3, 0x10, 0x91, 0x22, 0x88,
111 0x36, 0xd0, 0x94, 0xce, 0x8f, 0x96, 0xdb, 0xbd, 0xf1, 0xd2, 0x13, 0x5c, 0x83, 0x38, 0x46, 0x40,
112 0x1e, 0x42, 0xb6, 0xa3, 0xc3, 0x48, 0x7e, 0x6e, 0x6b, 0x3a, 0x28, 0x54, 0xfa, 0x85, 0xba, 0x3d,
113 0xca, 0x5e, 0x9b, 0x9f, 0x0a, 0x15, 0x79, 0x2b, 0x4e, 0xd4, 0xe5, 0xac, 0x73, 0xf3, 0xa7, 0x57,
114 0x07, 0x70, 0xc0, 0xf7, 0x8c, 0x80, 0x63, 0x0d, 0x67, 0x4a, 0xde, 0xed, 0x31, 0xc5, 0xfe, 0x18,
115 0xe3, 0xa5, 0x99, 0x77, 0x26, 0xb8, 0xb4, 0x7c, 0x11, 0x44, 0x92, 0xd9, 0x23, 0x20, 0x89, 0x2e,
116 0x37, 0x3f, 0xd1, 0x5b, 0x95, 0xbc, 0xcf, 0xcd, 0x90, 0x87, 0x97, 0xb2, 0xdc, 0xfc, 0xbe, 0x61,
117 0xf2, 0x56, 0xd3, 0xab, 0x14, 0x2a, 0x5d, 0x9e, 0x84, 0x3c, 0x39, 0x53, 0x47, 0x6d, 0x41, 0xa2,
118 0x1f, 0x2d, 0x43, 0xd8, 0xb7, 0x7b, 0xa4, 0x76, 0xc4, 0x17, 0x49, 0xec, 0x7f, 0x0c, 0x6f, 0xf6,
119 0x6c, 0xa1, 0x3b, 0x52, 0x29, 0x9d, 0x55, 0xaa, 0xfb, 0x60, 0x86, 0xb1, 0xbb, 0xcc, 0x3e, 0x5a,
120 0xcb, 0x59, 0x5f, 0xb0, 0x9c, 0xa9, 0xa0, 0x51, 0x0b, 0xf5, 0x16, 0xeb, 0x7a, 0x75, 0x2c, 0xd7,
121 0x4f, 0xae, 0xd5, 0xe9, 0xe6, 0xe7, 0xad, 0xe8, 0x74, 0xd6, 0xf4, 0xea, 0xa8, 0x50, 0x58, 0xaf
122 ];
123 // *Badness* coefficients.
124 var N1 = 3;
125 var N2 = 3;
126 var N3 = 40;
127 var N4 = 10;
128 // Version pattern.
129 var VERSION_BLOCK = [
130 0xc94, 0x5bc, 0xa99, 0x4d3, 0xbf6, 0x762, 0x847, 0x60d, 0x928, 0xb78, 0x45d, 0xa17, 0x532,
131 0x9a6, 0x683, 0x8c9, 0x7ec, 0xec4, 0x1e1, 0xfab, 0x08e, 0xc1a, 0x33f, 0xd75, 0x250, 0x9d5,
132 0x6f0, 0x8ba, 0x79f, 0xb0b, 0x42e, 0xa64, 0x541, 0xc69
133 ];
134 // Mode for node.js file system file writes.
135 var WRITE_MODE = parseInt('0666', 8);
136
137 // Private variables
138 // -----------------
139
140 // Run lengths for badness.
141 var badBuffer = [];
142 // Constructor for `canvas` elements in the node.js environment.
143 var Canvas;
144 // Data block.
145 var dataBlock;
146 // ECC data blocks and tables.
147 var eccBlock, neccBlock1, neccBlock2;
148 // ECC buffer.
149 var eccBuffer = [];
150 // ECC level (defaults to **L**).
151 var eccLevel = 1;
152 // Image buffer.
153 var frameBuffer = [];
154 // Fixed part of the image.
155 var frameMask = [];
156 // File system within the node.js environment.
157 var fs;
158 // Constructor for `img` elements in the node.js environment.
159 var Image;
160 // Indicates whether or not this script is running in node.js.
161 var inNode = false;
162 // Generator polynomial.
163 var polynomial = [];
164 // Save the previous value of the `qr` variable.
165 var previousQr = root.qr;
166 // Data input buffer.
167 var stringBuffer = [];
168 // Version for the data.
169 var version;
170 // Data width is based on `version`.
171 var width;
172
173 // Private functions
174 // -----------------
175
176 // Create a new canvas using `document.createElement` unless script is running in node.js, in
177 // which case the `canvas` module is used.
178 function createCanvas() {
179 return inNode ? new Canvas() : root.document.createElement('canvas');
180 }
181
182 // Create a new image using `document.createElement` unless script is running in node.js, in
183 // which case the `canvas` module is used.
184 function createImage() {
185 return inNode ? new Image() : root.document.createElement('img');
186 }
187
188 // Force the canvas image to be downloaded in the browser.
189 // Optionally, a `callback` function can be specified which will be called upon completed. Since
190 // this is not an asynchronous operation, this is merely convenient and helps simplify the
191 // calling code.
192 function download(cvs, data, callback) {
193 var mime = data.mime || DEFAULT_MIME;
194
195 root.location.href = cvs.toDataURL(mime).replace(mime, DOWNLOAD_MIME);
196
197 if (typeof callback === 'function') callback();
198 }
199
200 // Normalize the `data` that is provided to the main API.
201 function normalizeData(data) {
202 if (typeof data === 'string') data = { value: data };
203 return data || {};
204 }
205
206 // Override the `qr` API methods that require HTML5 canvas support to throw a relevant error.
207 function overrideAPI(qr) {
208 var methods = [ 'canvas', 'image', 'save', 'saveSync', 'toDataURL' ];
209 var i;
210
211 function overrideMethod(name) {
212 qr[name] = function () {
213 throw new Error(name + ' requires HTML5 canvas element support');
214 };
215 }
216
217 for (i = 0; i < methods.length; i++) {
218 overrideMethod(methods[i]);
219 }
220 }
221
222 // Asynchronously write the data of the rendered canvas to a given file path.
223 function writeFile(cvs, data, callback) {
224 if (typeof data.path !== 'string') {
225 return callback(new TypeError('Invalid path type: ' + typeof data.path));
226 }
227
228 var fd, buff;
229
230 // Write the buffer to the open file stream once both prerequisites are met.
231 function writeBuffer() {
232 fs.write(fd, buff, 0, buff.length, 0, function (error) {
233 fs.close(fd);
234
235 callback(error);
236 });
237 }
238
239 // Create a buffer of the canvas' data.
240 cvs.toBuffer(function (error, _buff) {
241 if (error) return callback(error);
242
243 buff = _buff;
244 if (fd) {
245 writeBuffer();
246 }
247 });
248
249 // Open a stream for the file to be written.
250 fs.open(data.path, 'w', WRITE_MODE, function (error, _fd) {
251 if (error) return callback(error);
252
253 fd = _fd;
254 if (buff) {
255 writeBuffer();
256 }
257 });
258 }
259
260 // Write the data of the rendered canvas to a given file path.
261 function writeFileSync(cvs, data) {
262 if (typeof data.path !== 'string') {
263 throw new TypeError('Invalid path type: ' + typeof data.path);
264 }
265
266 var buff = cvs.toBuffer();
267 var fd = fs.openSync(data.path, 'w', WRITE_MODE);
268
269 try {
270 fs.writeSync(fd, buff, 0, buff.length, 0);
271 } finally {
272 fs.closeSync(fd);
273 }
274 }
275
276 // Set bit to indicate cell in frame is immutable (symmetric around diagonal).
277 function setMask(x, y) {
278 var bit;
279
280 if (x > y) {
281 bit = x;
282 x = y;
283 y = bit;
284 }
285
286 bit = y;
287 bit *= y;
288 bit += y;
289 bit >>= 1;
290 bit += x;
291
292 frameMask[bit] = 1;
293 }
294
295 // Enter alignment pattern. Foreground colour to frame, background to mask. Frame will be merged
296 // with mask later.
297 function addAlignment(x, y) {
298 var i;
299
300 frameBuffer[x + width * y] = 1;
301
302 for (i = -2; i < 2; i++) {
303 frameBuffer[(x + i) + width * (y - 2)] = 1;
304 frameBuffer[(x - 2) + width * (y + i + 1)] = 1;
305 frameBuffer[(x + 2) + width * (y + i)] = 1;
306 frameBuffer[(x + i + 1) + width * (y + 2)] = 1;
307 }
308
309 for (i = 0; i < 2; i++) {
310 setMask(x - 1, y + i);
311 setMask(x + 1, y - i);
312 setMask(x - i, y - 1);
313 setMask(x + i, y + 1);
314 }
315 }
316
317 // Exponentiation mod N.
318 function modN(x) {
319 while (x >= 255) {
320 x -= 255;
321 x = (x >> 8) + (x & 255);
322 }
323
324 return x;
325 }
326
327 // Calculate and append `ecc` data to the `data` block. If block is in the string buffer the
328 // indices to buffers are used.
329 function appendData(data, dataLength, ecc, eccLength) {
330 var bit, i, j;
331
332 for (i = 0; i < eccLength; i++) {
333 stringBuffer[ecc + i] = 0;
334 }
335
336 for (i = 0; i < dataLength; i++) {
337 bit = GALOIS_LOG[stringBuffer[data + i] ^ stringBuffer[ecc]];
338
339 if (bit !== 255) {
340 for (j = 1; j < eccLength; j++) {
341 stringBuffer[ecc + j - 1] = stringBuffer[ecc + j] ^
342 GALOIS_EXPONENT[modN(bit + polynomial[eccLength - j])];
343 }
344 } else {
345 for (j = ecc; j < ecc + eccLength; j++) {
346 stringBuffer[j] = stringBuffer[j + 1];
347 }
348 }
349
350 stringBuffer[ecc + eccLength - 1] = bit === 255 ? 0 :
351 GALOIS_EXPONENT[modN(bit + polynomial[0])];
352 }
353 }
354
355 // Check mask since symmetricals use half.
356 function isMasked(x, y) {
357 var bit;
358
359 if (x > y) {
360 bit = x;
361 x = y;
362 y = bit;
363 }
364
365 bit = y;
366 bit += y * y;
367 bit >>= 1;
368 bit += x;
369
370 return frameMask[bit] === 1;
371 }
372
373 // Apply the selected mask out of the 8 options.
374 function applyMask(mask) {
375 var x, y, r3x, r3y;
376
377 switch (mask) {
378 case 0:
379 for (y = 0; y < width; y++) {
380 for (x = 0; x < width; x++) {
381 if (!((x + y) & 1) && !isMasked(x, y)) {
382 frameBuffer[x + y * width] ^= 1;
383 }
384 }
385 }
386
387 break;
388 case 1:
389 for (y = 0; y < width; y++) {
390 for (x = 0; x < width; x++) {
391 if (!(y & 1) && !isMasked(x, y)) {
392 frameBuffer[x + y * width] ^= 1;
393 }
394 }
395 }
396
397 break;
398 case 2:
399 for (y = 0; y < width; y++) {
400 for (r3x = 0, x = 0; x < width; x++, r3x++) {
401 if (r3x === 3) r3x = 0;
402
403 if (!r3x && !isMasked(x, y)) {
404 frameBuffer[x + y * width] ^= 1;
405 }
406 }
407 }
408
409 break;
410 case 3:
411 for (r3y = 0, y = 0; y < width; y++, r3y++) {
412 if (r3y === 3) r3y = 0;
413
414 for (r3x = r3y, x = 0; x < width; x++, r3x++) {
415 if (r3x === 3) r3x = 0;
416
417 if (!r3x && !isMasked(x, y)) {
418 frameBuffer[x + y * width] ^= 1;
419 }
420 }
421 }
422
423 break;
424 case 4:
425 for (y = 0; y < width; y++) {
426 for (r3x = 0, r3y = ((y >> 1) & 1), x = 0; x < width; x++, r3x++) {
427 if (r3x === 3) {
428 r3x = 0;
429 r3y = !r3y;
430 }
431
432 if (!r3y && !isMasked(x, y)) {
433 frameBuffer[x + y * width] ^= 1;
434 }
435 }
436 }
437
438 break;
439 case 5:
440 for (r3y = 0, y = 0; y < width; y++, r3y++) {
441 if (r3y === 3) r3y = 0;
442
443 for (r3x = 0, x = 0; x < width; x++, r3x++) {
444 if (r3x === 3) r3x = 0;
445
446 if (!((x & y & 1) + !(!r3x | !r3y)) && !isMasked(x, y)) {
447 frameBuffer[x + y * width] ^= 1;
448 }
449 }
450 }
451
452 break;
453 case 6:
454 for (r3y = 0, y = 0; y < width; y++, r3y++) {
455 if (r3y === 3) r3y = 0;
456
457 for (r3x = 0, x = 0; x < width; x++, r3x++) {
458 if (r3x === 3) r3x = 0;
459
460 if (!(((x & y & 1) + (r3x && (r3x === r3y))) & 1) && !isMasked(x, y)) {
461 frameBuffer[x + y * width] ^= 1;
462 }
463 }
464 }
465
466 break;
467 case 7:
468 for (r3y = 0, y = 0; y < width; y++, r3y++) {
469 if (r3y === 3) r3y = 0;
470
471 for (r3x = 0, x = 0; x < width; x++, r3x++) {
472 if (r3x === 3) r3x = 0;
473
474 if (!(((r3x && (r3x === r3y)) + ((x + y) & 1)) & 1) && !isMasked(x, y)) {
475 frameBuffer[x + y * width] ^= 1;
476 }
477 }
478 }
479
480 break;
481 }
482 }
483
484 // Using the table for the length of each run, calculate the amount of bad image. Long runs or
485 // those that look like finders are called twice; once for X and Y.
486 function getBadRuns(length) {
487 var badRuns = 0;
488 var i;
489
490 for (i = 0; i <= length; i++) {
491 if (badBuffer[i] >= 5) {
492 badRuns += N1 + badBuffer[i] - 5;
493 }
494 }
495
496 // FBFFFBF as in finder.
497 for (i = 3; i < length - 1; i += 2) {
498 if (badBuffer[i - 2] === badBuffer[i + 2] &&
499 badBuffer[i + 2] === badBuffer[i - 1] &&
500 badBuffer[i - 1] === badBuffer[i + 1] &&
501 badBuffer[i - 1] * 3 === badBuffer[i] &&
502 // Background around the foreground pattern? Not part of the specs.
503 (badBuffer[i - 3] === 0 || i + 3 > length ||
504 badBuffer[i - 3] * 3 >= badBuffer[i] * 4 ||
505 badBuffer[i + 3] * 3 >= badBuffer[i] * 4)) {
506 badRuns += N3;
507 }
508 }
509
510 return badRuns;
511 }
512
513 // Calculate how bad the masked image is (e.g. blocks, imbalance, runs, or finders).
514 function checkBadness() {
515 var b, b1, bad, big, bw, count, h, x, y;
516 bad = bw = count = 0;
517
518 // Blocks of same colour.
519 for (y = 0; y < width - 1; y++) {
520 for (x = 0; x < width - 1; x++) {
521 // All foreground colour.
522 if ((frameBuffer[x + width * y] &&
523 frameBuffer[(x + 1) + width * y] &&
524 frameBuffer[x + width * (y + 1)] &&
525 frameBuffer[(x + 1) + width * (y + 1)]) ||
526 // All background colour.
527 !(frameBuffer[x + width * y] ||
528 frameBuffer[(x + 1) + width * y] ||
529 frameBuffer[x + width * (y + 1)] ||
530 frameBuffer[(x + 1) + width * (y + 1)])) {
531 bad += N2;
532 }
533 }
534 }
535
536 // X runs.
537 for (y = 0; y < width; y++) {
538 badBuffer[0] = 0;
539
540 for (h = b = x = 0; x < width; x++) {
541 if ((b1 = frameBuffer[x + width * y]) === b) {
542 badBuffer[h]++;
543 } else {
544 badBuffer[++h] = 1;
545 }
546
547 b = b1;
548 bw += b ? 1 : -1;
549 }
550
551 bad += getBadRuns(h);
552 }
553
554 if (bw < 0) bw = -bw;
555
556 big = bw;
557 big += big << 2;
558 big <<= 1;
559
560 while (big > width * width) {
561 big -= width * width;
562 count++;
563 }
564
565 bad += count * N4;
566
567 // Y runs.
568 for (x = 0; x < width; x++) {
569 badBuffer[0] = 0;
570
571 for (h = b = y = 0; y < width; y++) {
572 if ((b1 = frameBuffer[x + width * y]) === b) {
573 badBuffer[h]++;
574 } else {
575 badBuffer[++h] = 1;
576 }
577
578 b = b1;
579 }
580
581 bad += getBadRuns(h);
582 }
583
584 return bad;
585 }
586
587 // Generate the encoded QR image for the string provided.
588 function generateFrame(str) {
589 var i, j, k, m, t, v, x, y;
590
591 // Find the smallest version that fits the string.
592 t = str.length;
593
594 version = 0;
595
596 do {
597 version++;
598
599 k = (eccLevel - 1) * 4 + (version - 1) * 16;
600
601 neccBlock1 = ECC_BLOCKS[k++];
602 neccBlock2 = ECC_BLOCKS[k++];
603 dataBlock = ECC_BLOCKS[k++];
604 eccBlock = ECC_BLOCKS[k];
605
606 k = dataBlock * (neccBlock1 + neccBlock2) + neccBlock2 - 3 + (version <= 9);
607
608 if (t <= k) break;
609 } while (version < 40);
610
611 // FIXME: Ensure that it fits insted of being truncated.
612 width = 17 + 4 * version;
613
614 // Allocate, clear and setup data structures.
615 v = dataBlock + (dataBlock + eccBlock) * (neccBlock1 + neccBlock2) + neccBlock2;
616
617 for (t = 0; t < v; t++) {
618 eccBuffer[t] = 0;
619 }
620
621 stringBuffer = str.slice(0);
622
623 for (t = 0; t < width * width; t++) {
624 frameBuffer[t] = 0;
625 }
626
627 for (t = 0; t < (width * (width + 1) + 1) / 2; t++) {
628 frameMask[t] = 0;
629 }
630
631 // Insert finders: Foreground colour to frame and background to mask.
632 for (t = 0; t < 3; t++) {
633 k = y = 0;
634
635 if (t === 1) k = (width - 7);
636 if (t === 2) y = (width - 7);
637
638 frameBuffer[(y + 3) + width * (k + 3)] = 1;
639
640 for (x = 0; x < 6; x++) {
641 frameBuffer[(y + x) + width * k] = 1;
642 frameBuffer[y + width * (k + x + 1)] = 1;
643 frameBuffer[(y + 6) + width * (k + x)] = 1;
644 frameBuffer[(y + x + 1) + width * (k + 6)] = 1;
645 }
646
647 for (x = 1; x < 5; x++) {
648 setMask(y + x, k + 1);
649 setMask(y + 1, k + x + 1);
650 setMask(y + 5, k + x);
651 setMask(y + x + 1, k + 5);
652 }
653
654 for (x = 2; x < 4; x++) {
655 frameBuffer[(y + x) + width * (k + 2)] = 1;
656 frameBuffer[(y + 2) + width * (k + x + 1)] = 1;
657 frameBuffer[(y + 4) + width * (k + x)] = 1;
658 frameBuffer[(y + x + 1) + width * (k + 4)] = 1;
659 }
660 }
661
662 // Alignment blocks.
663 if (version > 1) {
664 t = ALIGNMENT_DELTA[version];
665 y = width - 7;
666
667 for (;;) {
668 x = width - 7;
669
670 while (x > t - 3) {
671 addAlignment(x, y);
672
673 if (x < t) break;
674
675 x -= t;
676 }
677
678 if (y <= t + 9) break;
679
680 y -= t;
681
682 addAlignment(6, y);
683 addAlignment(y, 6);
684 }
685 }
686
687 // Single foreground cell.
688 frameBuffer[8 + width * (width - 8)] = 1;
689
690 // Timing gap (mask only).
691 for (y = 0; y < 7; y++) {
692 setMask(7, y);
693 setMask(width - 8, y);
694 setMask(7, y + width - 7);
695 }
696
697 for (x = 0; x < 8; x++) {
698 setMask(x, 7);
699 setMask(x + width - 8, 7);
700 setMask(x, width - 8);
701 }
702
703 // Reserve mask, format area.
704 for (x = 0; x < 9; x++) {
705 setMask(x, 8);
706 }
707
708 for (x = 0; x < 8; x++) {
709 setMask(x + width - 8, 8);
710 setMask(8, x);
711 }
712
713 for (y = 0; y < 7; y++) {
714 setMask(8, y + width - 7);
715 }
716
717 // Timing row/column.
718 for (x = 0; x < width - 14; x++) {
719 if (x & 1) {
720 setMask(8 + x, 6);
721 setMask(6, 8 + x);
722 } else {
723 frameBuffer[(8 + x) + width * 6] = 1;
724 frameBuffer[6 + width * (8 + x)] = 1;
725 }
726 }
727
728 // Version block.
729 if (version > 6) {
730 t = VERSION_BLOCK[version - 7];
731 k = 17;
732
733 for (x = 0; x < 6; x++) {
734 for (y = 0; y < 3; y++, k--) {
735 if (1 & (k > 11 ? version >> (k - 12) : t >> k)) {
736 frameBuffer[(5 - x) + width * (2 - y + width - 11)] = 1;
737 frameBuffer[(2 - y + width - 11) + width * (5 - x)] = 1;
738 } else {
739 setMask(5 - x, 2 - y + width - 11);
740 setMask(2 - y + width - 11, 5 - x);
741 }
742 }
743 }
744 }
745
746 // Sync mask bits. Only set above for background cells, so now add the foreground.
747 for (y = 0; y < width; y++) {
748 for (x = 0; x <= y; x++) {
749 if (frameBuffer[x + width * y]) {
750 setMask(x, y);
751 }
752 }
753 }
754
755 // Convert string to bit stream. 8-bit data to QR-coded 8-bit data (numeric, alphanum, or kanji
756 // not supported).
757 v = stringBuffer.length;
758
759 // String to array.
760 for (i = 0; i < v; i++) {
761 eccBuffer[i] = stringBuffer.charCodeAt(i);
762 }
763
764 stringBuffer = eccBuffer.slice(0);
765
766 // Calculate max string length.
767 x = dataBlock * (neccBlock1 + neccBlock2) + neccBlock2;
768
769 if (v >= x - 2) {
770 v = x - 2;
771
772 if (version > 9) v--;
773 }
774
775 // Shift and re-pack to insert length prefix.
776 i = v;
777
778 if (version > 9) {
779 stringBuffer[i + 2] = 0;
780 stringBuffer[i + 3] = 0;
781
782 while (i--) {
783 t = stringBuffer[i];
784
785 stringBuffer[i + 3] |= 255 & (t << 4);
786 stringBuffer[i + 2] = t >> 4;
787 }
788
789 stringBuffer[2] |= 255 & (v << 4);
790 stringBuffer[1] = v >> 4;
791 stringBuffer[0] = 0x40 | (v >> 12);
792 } else {
793 stringBuffer[i + 1] = 0;
794 stringBuffer[i + 2] = 0;
795
796 while (i--) {
797 t = stringBuffer[i];
798
799 stringBuffer[i + 2] |= 255 & (t << 4);
800 stringBuffer[i + 1] = t >> 4;
801 }
802
803 stringBuffer[1] |= 255 & (v << 4);
804 stringBuffer[0] = 0x40 | (v >> 4);
805 }
806
807 // Fill to end with pad pattern.
808 i = v + 3 - (version < 10);
809
810 while (i < x) {
811 stringBuffer[i++] = 0xec;
812 stringBuffer[i++] = 0x11;
813 }
814
815 // Calculate generator polynomial.
816 polynomial[0] = 1;
817
818 for (i = 0; i < eccBlock; i++) {
819 polynomial[i + 1] = 1;
820
821 for (j = i; j > 0; j--) {
822 polynomial[j] = polynomial[j] ? polynomial[j - 1] ^
823 GALOIS_EXPONENT[modN(GALOIS_LOG[polynomial[j]] + i)] : polynomial[j - 1];
824 }
825
826 polynomial[0] = GALOIS_EXPONENT[modN(GALOIS_LOG[polynomial[0]] + i)];
827 }
828
829 // Use logs for generator polynomial to save calculation step.
830 for (i = 0; i <= eccBlock; i++) {
831 polynomial[i] = GALOIS_LOG[polynomial[i]];
832 }
833
834 // Append ECC to data buffer.
835 k = x;
836 y = 0;
837
838 for (i = 0; i < neccBlock1; i++) {
839 appendData(y, dataBlock, k, eccBlock);
840
841 y += dataBlock;
842 k += eccBlock;
843 }
844
845 for (i = 0; i < neccBlock2; i++) {
846 appendData(y, dataBlock + 1, k, eccBlock);
847
848 y += dataBlock + 1;
849 k += eccBlock;
850 }
851
852 // Interleave blocks.
853 y = 0;
854
855 for (i = 0; i < dataBlock; i++) {
856 for (j = 0; j < neccBlock1; j++) {
857 eccBuffer[y++] = stringBuffer[i + j * dataBlock];
858 }
859
860 for (j = 0; j < neccBlock2; j++) {
861 eccBuffer[y++] = stringBuffer[(neccBlock1 * dataBlock) + i + (j * (dataBlock + 1))];
862 }
863 }
864
865 for (j = 0; j < neccBlock2; j++) {
866 eccBuffer[y++] = stringBuffer[(neccBlock1 * dataBlock) + i + (j * (dataBlock + 1))];
867 }
868
869 for (i = 0; i < eccBlock; i++) {
870 for (j = 0; j < neccBlock1 + neccBlock2; j++) {
871 eccBuffer[y++] = stringBuffer[x + i + j * eccBlock];
872 }
873 }
874
875 stringBuffer = eccBuffer;
876
877 // Pack bits into frame avoiding masked area.
878 x = y = width - 1;
879 k = v = 1;
880
881 // inteleaved data and ECC codes.
882 m = (dataBlock + eccBlock) * (neccBlock1 + neccBlock2) + neccBlock2;
883
884 for (i = 0; i < m; i++) {
885 t = stringBuffer[i];
886
887 for (j = 0; j < 8; j++, t <<= 1) {
888 if (0x80 & t) {
889 frameBuffer[x + width * y] = 1;
890 }
891
892 // Find next fill position.
893 do {
894 if (v) {
895 x--;
896 } else {
897 x++;
898
899 if (k) {
900 if (y !== 0) {
901 y--;
902 } else {
903 x -= 2;
904 k = !k;
905
906 if (x === 6) {
907 x--;
908 y = 9;
909 }
910 }
911 } else {
912 if (y !== width - 1) {
913 y++;
914 } else {
915 x -= 2;
916 k = !k;
917
918 if (x === 6) {
919 x--;
920 y -= 8;
921 }
922 }
923 }
924 }
925
926 v = !v;
927 } while (isMasked(x, y));
928 }
929 }
930
931 // Save pre-mask copy of frame.
932 stringBuffer = frameBuffer.slice(0);
933
934 t = 0;
935 y = 30000;
936
937 // Using `for` instead of `while` since in original Arduino code if an early mask was *good
938 // enough* it wouldn't try for a better one since they get more complex and take longer.
939 for (k = 0; k < 8; k++) {
940 // Returns foreground-background imbalance.
941 applyMask(k);
942
943 x = checkBadness();
944
945 // Is current mask better than previous best?
946 if (x < y) {
947 y = x;
948 t = k;
949 }
950
951 // Don't increment `i` to a void redoing mask.
952 if (t === 7) break;
953
954 // Reset for next pass.
955 frameBuffer = stringBuffer.slice(0);
956 }
957
958 // Redo best mask as none were *good enough* (i.e. last wasn't `t`).
959 if (t !== k) {
960 applyMask(t);
961 }
962
963 // Add in final mask/ECC level bytes.
964 y = FINAL_FORMAT[t + ((eccLevel - 1) << 3)];
965
966 // Low byte.
967 for (k = 0; k < 8; k++, y >>= 1) {
968 if (y & 1) {
969 frameBuffer[(width - 1 - k) + width * 8] = 1;
970
971 if (k < 6) {
972 frameBuffer[8 + width * k] = 1;
973 } else {
974 frameBuffer[8 + width * (k + 1)] = 1;
975 }
976 }
977 }
978
979 // High byte.
980 for (k = 0; k < 7; k++, y >>= 1) {
981 if (y & 1) {
982 frameBuffer[8 + width * (width - 7 + k)] = 1;
983
984 if (k) {
985 frameBuffer[(6 - k) + width * 8] = 1;
986 } else {
987 frameBuffer[7 + width * 8] = 1;
988 }
989 }
990 }
991
992 // Finally, return the image data.
993 return frameBuffer;
994 }
995
996 // qr.js setup
997 // -----------
998
999 // Build the publicly exposed API.
1000 var qr = {
1001
1002 // Constants
1003 // ---------
1004
1005 // Current version of `qr`.
1006 VERSION: '1.1.3',
1007
1008 // QR functions
1009 // ------------
1010
1011 // Generate the QR code using the data provided and render it on to a `<canvas>` element.
1012 // If no `<canvas>` element is specified in the argument provided a new one will be created and
1013 // used.
1014 // ECC (error correction capacity) determines how many intential errors are contained in the QR
1015 // code.
1016 canvas: function(data) {
1017 data = normalizeData(data);
1018
1019 // Module size of the generated QR code (i.e. 1-10).
1020 var size = data.size >= 1 && data.size <= 10 ? data.size : 4;
1021 // Actual size of the QR code symbol and is scaled to 25 pixels (e.g. 1 = 25px, 3 = 75px).
1022 size *= 25;
1023
1024 // `<canvas>` element used to render the QR code.
1025 var cvs = data.canvas || createCanvas();
1026 // Retreive the 2D context of the canvas.
1027 var c2d = cvs.getContext('2d');
1028 // Ensure the canvas has the correct dimensions.
1029 c2d.canvas.width = size;
1030 c2d.canvas.height = size;
1031 // Fill the canvas with the correct background colour.
1032 c2d.fillStyle = data.background || '#fff';
1033 c2d.fillRect(0, 0, size, size);
1034
1035 // Determine the ECC level to be applied.
1036 eccLevel = ECC_LEVELS[(data.level && data.level.toUpperCase()) || 'L'];
1037
1038 // Generate the image frame for the given `value`.
1039 var frame = generateFrame(data.value || '');
1040
1041 c2d.lineWidth = 1;
1042
1043 // Determine the *pixel* size.
1044 var px = size;
1045 px /= width;
1046 px = Math.floor(px);
1047
1048 // Draw the QR code.
1049 c2d.clearRect(0, 0, size, size);
1050 c2d.fillStyle = data.background || '#fff';
1051 c2d.fillRect(0, 0, px * (width + 8), px * (width + 8));
1052 c2d.fillStyle = data.foreground || '#000';
1053
1054 var i, j;
1055
1056 for (i = 0; i < width; i++) {
1057 for (j = 0; j < width; j++) {
1058 if (frame[j * width + i]) {
1059 c2d.fillRect(px * i, px * j, px, px);
1060 }
1061 }
1062 }
1063
1064 return cvs;
1065 },
1066
1067 // Generate the QR code using the data provided and render it on to a `<img>` element.
1068 // If no `<img>` element is specified in the argument provided a new one will be created and
1069 // used.
1070 // ECC (error correction capacity) determines how many intential errors are contained in the QR
1071 // code.
1072 image: function(data) {
1073 data = normalizeData(data);
1074
1075 // `<canvas>` element only which the QR code is rendered.
1076 var cvs = this.canvas(data);
1077 // `<img>` element used to display the QR code.
1078 var img = data.image || createImage();
1079
1080 // Apply the QR code to `img`.
1081 img.src = cvs.toDataURL(data.mime || DEFAULT_MIME);
1082 img.height = cvs.height;
1083 img.width = cvs.width;
1084
1085 return img;
1086 },
1087
1088 // Generate the QR code using the data provided and render it on to a `<canvas>` element and
1089 // save it as an image file.
1090 // If no `<canvas>` element is specified in the argument provided a new one will be created and
1091 // used.
1092 // ECC (error correction capacity) determines how many intential errors are contained in the QR
1093 // code.
1094 // If called in a browser the `path` property/argument is ignored and will simply prompt the
1095 // user to choose a location and file name. However, if called within node.js the file will be
1096 // saved to specified path.
1097 // A `callback` function must be provided which will be called once the saving process has
1098 // started. If an error occurs it will be passed as the first argument to this function,
1099 // otherwise this argument will be `null`.
1100 save: function(data, path, callback) {
1101 data = normalizeData(data);
1102
1103 switch (typeof path) {
1104 case 'function':
1105 callback = path;
1106 path = null;
1107 break;
1108 case 'string':
1109 data.path = path;
1110 break;
1111 }
1112
1113 // Callback function is required.
1114 if (typeof callback !== 'function') {
1115 throw new TypeError('Invalid callback type: ' + typeof callback);
1116 }
1117
1118 var completed = false;
1119 // `<canvas>` element only which the QR code is rendered.
1120 var cvs = this.canvas(data);
1121
1122 // Simple function to try and ensure that the `callback` function is only called once.
1123 function done(error) {
1124 if (!completed) {
1125 completed = true;
1126
1127 callback(error);
1128 }
1129 }
1130
1131 if (inNode) {
1132 writeFile(cvs, data, done);
1133 } else {
1134 download(cvs, data, done);
1135 }
1136 },
1137
1138 // Generate the QR code using the data provided and render it on to a `<canvas>` element and
1139 // save it as an image file.
1140 // If no `<canvas>` element is specified in the argument provided a new one will be created and
1141 // used.
1142 // ECC (error correction capacity) determines how many intential errors are contained in the QR
1143 // code.
1144 // If called in a browser the `path` property/argument is ignored and will simply prompt the
1145 // user to choose a location and file name. However, if called within node.js the file will be
1146 // saved to specified path.
1147 saveSync: function(data, path) {
1148 data = normalizeData(data);
1149
1150 if (typeof path === 'string') data.path = path;
1151
1152 // `<canvas>` element only which the QR code is rendered.
1153 var cvs = this.canvas(data);
1154
1155 if (inNode) {
1156 writeFileSync(cvs, data);
1157 } else {
1158 download(cvs, data);
1159 }
1160 },
1161
1162 // Generate the QR code using the data provided and render it on to a `<canvas>` element before
1163 // returning its data URI.
1164 // If no `<canvas>` element is specified in the argument provided a new one will be created and
1165 // used.
1166 // ECC (error correction capacity) determines how many intential errors are contained in the QR
1167 // code.
1168 toDataURL: function(data) {
1169 data = normalizeData(data);
1170
1171 return this.canvas(data).toDataURL(data.mime || DEFAULT_MIME);
1172 },
1173
1174 // Utility functions
1175 // -----------------
1176
1177 // Run qr.js in *noConflict* mode, returning the `qr` variable to its previous owner.
1178 // Returns a reference to `qr`.
1179 noConflict: function() {
1180 root.qr = previousQr;
1181 return this;
1182 }
1183
1184 };
1185
1186 // Support
1187 // -------
1188
1189 // Export `qr` for node.js and CommonJS.
1190 if (typeof exports !== 'undefined') {
1191 inNode = true;
1192
1193 if (typeof module !== 'undefined' && module.exports) {
1194 exports = module.exports = qr;
1195 }
1196 exports.qr = qr;
1197
1198 // Import required node.js modules.
1199 Canvas = require('canvas');
1200 Image = Canvas.Image;
1201 fs = require('fs');
1202 } else if (typeof define === 'function' && define.amd) {
1203 define(function () {
1204 return qr;
1205 });
1206 } else {
1207 // In non-HTML5 browser so strip base functionality.
1208 if (!root.HTMLCanvasElement) {
1209 overrideAPI(qr);
1210 }
1211
1212 root.qr = qr;
1213 }
1214
1215})(this);
diff --git a/plugins/qrcode/qr-1.1.3.min.js b/plugins/qrcode/qr-1.1.3.min.js
new file mode 100644
index 00000000..19d704e1
--- /dev/null
+++ b/plugins/qrcode/qr-1.1.3.min.js
@@ -0,0 +1,5 @@
1/*! qr-js v1.1.3 | (c) 2014 Alasdair Mercer | GPL v3 License
2jsqrencode | (c) 2010 tz@execpc.com | GPL v3 License
3*/
4!function(a){"use strict";function b(){return T?new r:a.document.createElement("canvas")}function c(){return T?new x:a.document.createElement("img")}function d(b,c,d){var e=c.mime||B;a.location.href=b.toDataURL(e).replace(e,C),"function"==typeof d&&d()}function e(a){return"string"==typeof a&&(a={value:a}),a||{}}function f(a){function b(b){a[b]=function(){throw new Error(b+" requires HTML5 canvas element support")}}var c,d=["canvas","image","save","saveSync","toDataURL"];for(c=0;c<d.length;c++)b(d[c])}function g(a,b,c){function d(){w.write(e,f,0,f.length,0,function(a){w.close(e),c(a)})}if("string"!=typeof b.path)return c(new TypeError("Invalid path type: "+typeof b.path));var e,f;a.toBuffer(function(a,b){return a?c(a):(f=b,void(e&&d()))}),w.open(b.path,"w",N,function(a,b){return a?c(a):(e=b,void(f&&d()))})}function h(a,b){if("string"!=typeof b.path)throw new TypeError("Invalid path type: "+typeof b.path);var c=a.toBuffer(),d=w.openSync(b.path,"w",N);try{w.writeSync(d,c,0,c.length,0)}finally{w.closeSync(d)}}function i(a,b){var c;a>b&&(c=a,a=b,b=c),c=b,c*=b,c+=b,c>>=1,c+=a,S[c]=1}function j(a,b){var c;for(R[a+z*b]=1,c=-2;2>c;c++)R[a+c+z*(b-2)]=1,R[a-2+z*(b+c+1)]=1,R[a+2+z*(b+c)]=1,R[a+c+1+z*(b+2)]=1;for(c=0;2>c;c++)i(a-1,b+c),i(a+1,b-c),i(a-c,b-1),i(a+c,b+1)}function k(a){for(;a>=255;)a-=255,a=(a>>8)+(255&a);return a}function l(a,b,c,d){var e,f,g;for(f=0;d>f;f++)W[c+f]=0;for(f=0;b>f;f++){if(e=H[W[a+f]^W[c]],255!==e)for(g=1;d>g;g++)W[c+g-1]=W[c+g]^G[k(e+U[d-g])];else for(g=c;c+d>g;g++)W[g]=W[g+1];W[c+d-1]=255===e?0:G[k(e+U[0])]}}function m(a,b){var c;return a>b&&(c=a,a=b,b=c),c=b,c+=b*b,c>>=1,c+=a,1===S[c]}function n(a){var b,c,d,e;switch(a){case 0:for(c=0;z>c;c++)for(b=0;z>b;b++)b+c&1||m(b,c)||(R[b+c*z]^=1);break;case 1:for(c=0;z>c;c++)for(b=0;z>b;b++)1&c||m(b,c)||(R[b+c*z]^=1);break;case 2:for(c=0;z>c;c++)for(d=0,b=0;z>b;b++,d++)3===d&&(d=0),d||m(b,c)||(R[b+c*z]^=1);break;case 3:for(e=0,c=0;z>c;c++,e++)for(3===e&&(e=0),d=e,b=0;z>b;b++,d++)3===d&&(d=0),d||m(b,c)||(R[b+c*z]^=1);break;case 4:for(c=0;z>c;c++)for(d=0,e=c>>1&1,b=0;z>b;b++,d++)3===d&&(d=0,e=!e),e||m(b,c)||(R[b+c*z]^=1);break;case 5:for(e=0,c=0;z>c;c++,e++)for(3===e&&(e=0),d=0,b=0;z>b;b++,d++)3===d&&(d=0),(b&c&1)+!(!d|!e)||m(b,c)||(R[b+c*z]^=1);break;case 6:for(e=0,c=0;z>c;c++,e++)for(3===e&&(e=0),d=0,b=0;z>b;b++,d++)3===d&&(d=0),(b&c&1)+(d&&d===e)&1||m(b,c)||(R[b+c*z]^=1);break;case 7:for(e=0,c=0;z>c;c++,e++)for(3===e&&(e=0),d=0,b=0;z>b;b++,d++)3===d&&(d=0),(d&&d===e)+(b+c&1)&1||m(b,c)||(R[b+c*z]^=1)}}function o(a){var b,c=0;for(b=0;a>=b;b++)O[b]>=5&&(c+=I+O[b]-5);for(b=3;a-1>b;b+=2)O[b-2]===O[b+2]&&O[b+2]===O[b-1]&&O[b-1]===O[b+1]&&3*O[b-1]===O[b]&&(0===O[b-3]||b+3>a||3*O[b-3]>=4*O[b]||3*O[b+3]>=4*O[b])&&(c+=K);return c}function p(){var a,b,c,d,e,f,g,h,i;for(c=e=f=0,i=0;z-1>i;i++)for(h=0;z-1>h;h++)(R[h+z*i]&&R[h+1+z*i]&&R[h+z*(i+1)]&&R[h+1+z*(i+1)]||!(R[h+z*i]||R[h+1+z*i]||R[h+z*(i+1)]||R[h+1+z*(i+1)]))&&(c+=J);for(i=0;z>i;i++){for(O[0]=0,g=a=h=0;z>h;h++)(b=R[h+z*i])===a?O[g]++:O[++g]=1,a=b,e+=a?1:-1;c+=o(g)}for(0>e&&(e=-e),d=e,d+=d<<2,d<<=1;d>z*z;)d-=z*z,f++;for(c+=f*L,h=0;z>h;h++){for(O[0]=0,g=a=i=0;z>i;i++)(b=R[h+z*i])===a?O[g]++:O[++g]=1,a=b;c+=o(g)}return c}function q(a){var b,c,d,e,f,g,h,o;f=a.length,y=0;do if(y++,d=4*(Q-1)+16*(y-1),u=D[d++],v=D[d++],s=D[d++],t=D[d],d=s*(u+v)+v-3+(9>=y),d>=f)break;while(40>y);for(z=17+4*y,g=s+(s+t)*(u+v)+v,f=0;g>f;f++)P[f]=0;for(W=a.slice(0),f=0;z*z>f;f++)R[f]=0;for(f=0;(z*(z+1)+1)/2>f;f++)S[f]=0;for(f=0;3>f;f++){for(d=o=0,1===f&&(d=z-7),2===f&&(o=z-7),R[o+3+z*(d+3)]=1,h=0;6>h;h++)R[o+h+z*d]=1,R[o+z*(d+h+1)]=1,R[o+6+z*(d+h)]=1,R[o+h+1+z*(d+6)]=1;for(h=1;5>h;h++)i(o+h,d+1),i(o+1,d+h+1),i(o+5,d+h),i(o+h+1,d+5);for(h=2;4>h;h++)R[o+h+z*(d+2)]=1,R[o+2+z*(d+h+1)]=1,R[o+4+z*(d+h)]=1,R[o+h+1+z*(d+4)]=1}if(y>1)for(f=A[y],o=z-7;;){for(h=z-7;h>f-3&&(j(h,o),!(f>h));)h-=f;if(f+9>=o)break;o-=f,j(6,o),j(o,6)}for(R[8+z*(z-8)]=1,o=0;7>o;o++)i(7,o),i(z-8,o),i(7,o+z-7);for(h=0;8>h;h++)i(h,7),i(h+z-8,7),i(h,z-8);for(h=0;9>h;h++)i(h,8);for(h=0;8>h;h++)i(h+z-8,8),i(8,h);for(o=0;7>o;o++)i(8,o+z-7);for(h=0;z-14>h;h++)1&h?(i(8+h,6),i(6,8+h)):(R[8+h+6*z]=1,R[6+z*(8+h)]=1);if(y>6)for(f=M[y-7],d=17,h=0;6>h;h++)for(o=0;3>o;o++,d--)1&(d>11?y>>d-12:f>>d)?(R[5-h+z*(2-o+z-11)]=1,R[2-o+z-11+z*(5-h)]=1):(i(5-h,2-o+z-11),i(2-o+z-11,5-h));for(o=0;z>o;o++)for(h=0;o>=h;h++)R[h+z*o]&&i(h,o);for(g=W.length,b=0;g>b;b++)P[b]=W.charCodeAt(b);if(W=P.slice(0),h=s*(u+v)+v,g>=h-2&&(g=h-2,y>9&&g--),b=g,y>9){for(W[b+2]=0,W[b+3]=0;b--;)f=W[b],W[b+3]|=255&f<<4,W[b+2]=f>>4;W[2]|=255&g<<4,W[1]=g>>4,W[0]=64|g>>12}else{for(W[b+1]=0,W[b+2]=0;b--;)f=W[b],W[b+2]|=255&f<<4,W[b+1]=f>>4;W[1]|=255&g<<4,W[0]=64|g>>4}for(b=g+3-(10>y);h>b;)W[b++]=236,W[b++]=17;for(U[0]=1,b=0;t>b;b++){for(U[b+1]=1,c=b;c>0;c--)U[c]=U[c]?U[c-1]^G[k(H[U[c]]+b)]:U[c-1];U[0]=G[k(H[U[0]]+b)]}for(b=0;t>=b;b++)U[b]=H[U[b]];for(d=h,o=0,b=0;u>b;b++)l(o,s,d,t),o+=s,d+=t;for(b=0;v>b;b++)l(o,s+1,d,t),o+=s+1,d+=t;for(o=0,b=0;s>b;b++){for(c=0;u>c;c++)P[o++]=W[b+c*s];for(c=0;v>c;c++)P[o++]=W[u*s+b+c*(s+1)]}for(c=0;v>c;c++)P[o++]=W[u*s+b+c*(s+1)];for(b=0;t>b;b++)for(c=0;u+v>c;c++)P[o++]=W[h+b+c*t];for(W=P,h=o=z-1,d=g=1,e=(s+t)*(u+v)+v,b=0;e>b;b++)for(f=W[b],c=0;8>c;c++,f<<=1){128&f&&(R[h+z*o]=1);do g?h--:(h++,d?0!==o?o--:(h-=2,d=!d,6===h&&(h--,o=9)):o!==z-1?o++:(h-=2,d=!d,6===h&&(h--,o-=8))),g=!g;while(m(h,o))}for(W=R.slice(0),f=0,o=3e4,d=0;8>d&&(n(d),h=p(),o>h&&(o=h,f=d),7!==f);d++)R=W.slice(0);for(f!==d&&n(f),o=F[f+(Q-1<<3)],d=0;8>d;d++,o>>=1)1&o&&(R[z-1-d+8*z]=1,6>d?R[8+z*d]=1:R[8+z*(d+1)]=1);for(d=0;7>d;d++,o>>=1)1&o&&(R[8+z*(z-7+d)]=1,d?R[6-d+8*z]=1:R[7+8*z]=1);return R}var r,s,t,u,v,w,x,y,z,A=[0,11,15,19,23,27,31,16,18,20,22,24,26,28,20,22,24,24,26,28,28,22,24,24,26,26,28,28,24,24,26,26,26,28,28,24,26,26,26,28,28],B="image/png",C="image/octet-stream",D=[1,0,19,7,1,0,16,10,1,0,13,13,1,0,9,17,1,0,34,10,1,0,28,16,1,0,22,22,1,0,16,28,1,0,55,15,1,0,44,26,2,0,17,18,2,0,13,22,1,0,80,20,2,0,32,18,2,0,24,26,4,0,9,16,1,0,108,26,2,0,43,24,2,2,15,18,2,2,11,22,2,0,68,18,4,0,27,16,4,0,19,24,4,0,15,28,2,0,78,20,4,0,31,18,2,4,14,18,4,1,13,26,2,0,97,24,2,2,38,22,4,2,18,22,4,2,14,26,2,0,116,30,3,2,36,22,4,4,16,20,4,4,12,24,2,2,68,18,4,1,43,26,6,2,19,24,6,2,15,28,4,0,81,20,1,4,50,30,4,4,22,28,3,8,12,24,2,2,92,24,6,2,36,22,4,6,20,26,7,4,14,28,4,0,107,26,8,1,37,22,8,4,20,24,12,4,11,22,3,1,115,30,4,5,40,24,11,5,16,20,11,5,12,24,5,1,87,22,5,5,41,24,5,7,24,30,11,7,12,24,5,1,98,24,7,3,45,28,15,2,19,24,3,13,15,30,1,5,107,28,10,1,46,28,1,15,22,28,2,17,14,28,5,1,120,30,9,4,43,26,17,1,22,28,2,19,14,28,3,4,113,28,3,11,44,26,17,4,21,26,9,16,13,26,3,5,107,28,3,13,41,26,15,5,24,30,15,10,15,28,4,4,116,28,17,0,42,26,17,6,22,28,19,6,16,30,2,7,111,28,17,0,46,28,7,16,24,30,34,0,13,24,4,5,121,30,4,14,47,28,11,14,24,30,16,14,15,30,6,4,117,30,6,14,45,28,11,16,24,30,30,2,16,30,8,4,106,26,8,13,47,28,7,22,24,30,22,13,15,30,10,2,114,28,19,4,46,28,28,6,22,28,33,4,16,30,8,4,122,30,22,3,45,28,8,26,23,30,12,28,15,30,3,10,117,30,3,23,45,28,4,31,24,30,11,31,15,30,7,7,116,30,21,7,45,28,1,37,23,30,19,26,15,30,5,10,115,30,19,10,47,28,15,25,24,30,23,25,15,30,13,3,115,30,2,29,46,28,42,1,24,30,23,28,15,30,17,0,115,30,10,23,46,28,10,35,24,30,19,35,15,30,17,1,115,30,14,21,46,28,29,19,24,30,11,46,15,30,13,6,115,30,14,23,46,28,44,7,24,30,59,1,16,30,12,7,121,30,12,26,47,28,39,14,24,30,22,41,15,30,6,14,121,30,6,34,47,28,46,10,24,30,2,64,15,30,17,4,122,30,29,14,46,28,49,10,24,30,24,46,15,30,4,18,122,30,13,32,46,28,48,14,24,30,42,32,15,30,20,4,117,30,40,7,47,28,43,22,24,30,10,67,15,30,19,6,118,30,18,31,47,28,34,34,24,30,20,61,15,30],E={L:1,M:2,Q:3,H:4},F=[30660,29427,32170,30877,26159,25368,27713,26998,21522,20773,24188,23371,17913,16590,20375,19104,13663,12392,16177,14854,9396,8579,11994,11245,5769,5054,7399,6608,1890,597,3340,2107],G=[1,2,4,8,16,32,64,128,29,58,116,232,205,135,19,38,76,152,45,90,180,117,234,201,143,3,6,12,24,48,96,192,157,39,78,156,37,74,148,53,106,212,181,119,238,193,159,35,70,140,5,10,20,40,80,160,93,186,105,210,185,111,222,161,95,190,97,194,153,47,94,188,101,202,137,15,30,60,120,240,253,231,211,187,107,214,177,127,254,225,223,163,91,182,113,226,217,175,67,134,17,34,68,136,13,26,52,104,208,189,103,206,129,31,62,124,248,237,199,147,59,118,236,197,151,51,102,204,133,23,46,92,184,109,218,169,79,158,33,66,132,21,42,84,168,77,154,41,82,164,85,170,73,146,57,114,228,213,183,115,230,209,191,99,198,145,63,126,252,229,215,179,123,246,241,255,227,219,171,75,150,49,98,196,149,55,110,220,165,87,174,65,130,25,50,100,200,141,7,14,28,56,112,224,221,167,83,166,81,162,89,178,121,242,249,239,195,155,43,86,172,69,138,9,18,36,72,144,61,122,244,245,247,243,251,235,203,139,11,22,44,88,176,125,250,233,207,131,27,54,108,216,173,71,142,0],H=[255,0,1,25,2,50,26,198,3,223,51,238,27,104,199,75,4,100,224,14,52,141,239,129,28,193,105,248,200,8,76,113,5,138,101,47,225,36,15,33,53,147,142,218,240,18,130,69,29,181,194,125,106,39,249,185,201,154,9,120,77,228,114,166,6,191,139,98,102,221,48,253,226,152,37,179,16,145,34,136,54,208,148,206,143,150,219,189,241,210,19,92,131,56,70,64,30,66,182,163,195,72,126,110,107,58,40,84,250,133,186,61,202,94,155,159,10,21,121,43,78,212,229,172,115,243,167,87,7,112,192,247,140,128,99,13,103,74,222,237,49,197,254,24,227,165,153,119,38,184,180,124,17,68,146,217,35,32,137,46,55,63,209,91,149,188,207,205,144,135,151,178,220,252,190,97,242,86,211,171,20,42,93,158,132,60,57,83,71,109,65,162,31,45,67,216,183,123,164,118,196,23,73,236,127,12,111,246,108,161,59,82,41,157,85,170,251,96,134,177,187,204,62,90,203,89,95,176,156,169,160,81,11,245,22,235,122,117,44,215,79,174,213,233,230,231,173,232,116,214,244,234,168,80,88,175],I=3,J=3,K=40,L=10,M=[3220,1468,2713,1235,3062,1890,2119,1549,2344,2936,1117,2583,1330,2470,1667,2249,2028,3780,481,4011,142,3098,831,3445,592,2517,1776,2234,1951,2827,1070,2660,1345,3177],N=parseInt("0666",8),O=[],P=[],Q=1,R=[],S=[],T=!1,U=[],V=a.qr,W=[],X={VERSION:"1.1.3",canvas:function(a){a=e(a);var c=a.size>=1&&a.size<=10?a.size:4;c*=25;var d=a.canvas||b(),f=d.getContext("2d");f.canvas.width=c,f.canvas.height=c,f.fillStyle=a.background||"#fff",f.fillRect(0,0,c,c),Q=E[a.level&&a.level.toUpperCase()||"L"];var g=q(a.value||"");f.lineWidth=1;var h=c;h/=z,h=Math.floor(h),f.clearRect(0,0,c,c),f.fillStyle=a.background||"#fff",f.fillRect(0,0,h*(z+8),h*(z+8)),f.fillStyle=a.foreground||"#000";var i,j;for(i=0;z>i;i++)for(j=0;z>j;j++)g[j*z+i]&&f.fillRect(h*i,h*j,h,h);return d},image:function(a){a=e(a);var b=this.canvas(a),d=a.image||c();return d.src=b.toDataURL(a.mime||B),d.height=b.height,d.width=b.width,d},save:function(a,b,c){function f(a){h||(h=!0,c(a))}switch(a=e(a),typeof b){case"function":c=b,b=null;break;case"string":a.path=b}if("function"!=typeof c)throw new TypeError("Invalid callback type: "+typeof c);var h=!1,i=this.canvas(a);T?g(i,a,f):d(i,a,f)},saveSync:function(a,b){a=e(a),"string"==typeof b&&(a.path=b);var c=this.canvas(a);T?h(c,a):d(c,a)},toDataURL:function(a){return a=e(a),this.canvas(a).toDataURL(a.mime||B)},noConflict:function(){return a.qr=V,this}};"undefined"!=typeof exports?(T=!0,"undefined"!=typeof module&&module.exports&&(exports=module.exports=X),exports.qr=X,r=require("canvas"),x=r.Image,w=require("fs")):"function"==typeof define&&define.amd?define(function(){return X}):(a.HTMLCanvasElement||f(X),a.qr=X)}(this);
5//# sourceMappingURL=qr.min.map \ No newline at end of file
diff --git a/plugins/qrcode/qrcode.html b/plugins/qrcode/qrcode.html
new file mode 100644
index 00000000..ffdaf3b8
--- /dev/null
+++ b/plugins/qrcode/qrcode.html
@@ -0,0 +1,5 @@
1<div class="linkqrcode">
2 <a href="http://qrfree.kaywa.com/?l=1&amp;s=8&amp;d=%s" onclick="showQrCode(this); return false;" class="qrcode" data-permalink="%s">
3 <img src="%s/qrcode/qrcode.png" width="13" height="13" title="QR-Code">
4 </a>
5</div>
diff --git a/plugins/qrcode/qrcode.php b/plugins/qrcode/qrcode.php
new file mode 100644
index 00000000..1080c964
--- /dev/null
+++ b/plugins/qrcode/qrcode.php
@@ -0,0 +1,41 @@
1<?php
2/**
3 * Plugin qrcode
4 * Add QRCode containing URL for each links.
5 * Display a QRCode icon in link list.
6 */
7
8/**
9 * Add qrcode icon to link_plugin when rendering linklist.
10 *
11 * @param array $data - linklist data.
12 *
13 * @return mixed - linklist data with qrcode plugin.
14 */
15function hook_qrcode_render_linklist($data)
16{
17 $qrcode_html = file_get_contents(PluginManager::$PLUGINS_PATH . '/qrcode/qrcode.html');
18
19 foreach ($data['links'] as &$value) {
20 $qrcode = sprintf($qrcode_html, $value['url'], $value['url'], PluginManager::$PLUGINS_PATH);
21 $value['link_plugin'][] = $qrcode;
22 }
23
24 return $data;
25}
26
27/**
28 * When linklist is displayed, include qrcode JS files.
29 *
30 * @param array $data - footer data.
31 *
32 * @return mixed - footer data with qrcode JS files added.
33 */
34function hook_qrcode_render_footer($data)
35{
36 if ($data['_PAGE_'] == Router::$PAGE_LINKLIST) {
37 $data['js_files'][] = PluginManager::$PLUGINS_PATH . '/qrcode/shaarli-qrcode.js';
38 }
39
40 return $data;
41}
diff --git a/plugins/qrcode/qrcode.png b/plugins/qrcode/qrcode.png
new file mode 100644
index 00000000..c2cfa476
--- /dev/null
+++ b/plugins/qrcode/qrcode.png
Binary files differ
diff --git a/plugins/qrcode/shaarli-qrcode.js b/plugins/qrcode/shaarli-qrcode.js
new file mode 100644
index 00000000..0a8de21d
--- /dev/null
+++ b/plugins/qrcode/shaarli-qrcode.js
@@ -0,0 +1,56 @@
1// Show the QR-Code of a permalink (when the QR-Code icon is clicked).
2function showQrCode(caller,loading)
3{
4 // Dynamic javascript lib loading: We only load qr.js if the QR code icon is clicked:
5 if (typeof(qr) == 'undefined') // Load qr.js only if not present.
6 {
7 if (!loading) // If javascript lib is still loading, do not append script to body.
8 {
9 var element = document.createElement("script");
10 element.src = "plugins/qrcode/qr-1.1.3.min.js";
11 document.body.appendChild(element);
12 }
13 setTimeout(function() { showQrCode(caller,true);}, 200); // Retry in 200 milliseconds.
14 return false;
15 }
16
17 // Remove previous qrcode if present.
18 removeQrcode();
19
20 // Build the div which contains the QR-Code:
21 var element = document.createElement('div');
22 element.id="permalinkQrcode";
23
24 // Make QR-Code div commit sepuku when clicked:
25 if ( element.attachEvent ){
26 element.attachEvent('onclick', 'this.parentNode.removeChild(this);' );
27
28 } else {
29 // Damn IE
30 element.setAttribute('onclick', 'this.parentNode.removeChild(this);' );
31 }
32
33 // Build the QR-Code:
34 var image = qr.image({size: 8,value: caller.dataset.permalink});
35 if (image)
36 {
37 element.appendChild(image);
38 element.innerHTML += "<br>Click to close";
39 caller.parentNode.appendChild(element);
40 }
41 else
42 {
43 element.innerHTML = "Your browser does not seem to be HTML5 compatible.";
44 }
45 return false;
46}
47
48// Remove any displayed QR-Code
49function removeQrcode()
50{
51 var elem = document.getElementById("permalinkQrcode");
52 if (elem) {
53 elem.parentNode.removeChild(elem);
54 }
55 return false;
56} \ No newline at end of file
diff --git a/tests/plugins/PlugQrcodeTest.php b/tests/plugins/PlugQrcodeTest.php
new file mode 100644
index 00000000..86dc7f29
--- /dev/null
+++ b/tests/plugins/PlugQrcodeTest.php
@@ -0,0 +1,67 @@
1<?php
2
3/**
4 * PlugQrcodeTest.php
5 */
6
7require_once 'plugins/qrcode/qrcode.php';
8require_once 'application/Router.php';
9
10/**
11 * Class PlugQrcodeTest
12 * Unit test for the QR-Code plugin
13 */
14class PlugQrcodeTest extends PHPUnit_Framework_TestCase
15{
16 /**
17 * Reset plugin path
18 */
19 function setUp() {
20 PluginManager::$PLUGINS_PATH = 'plugins';
21 }
22
23 /**
24 * Test render_linklist hook.
25 */
26 function testQrcodeLinklist()
27 {
28 $str = 'http://randomstr.com/test';
29 $data = array(
30 'title' => $str,
31 'links' => array(
32 array(
33 'url' => $str,
34 )
35 )
36 );
37
38 $data = hook_qrcode_render_linklist($data);
39 $link = $data['links'][0];
40 // data shouldn't be altered
41 $this->assertEquals($str, $data['title']);
42 $this->assertEquals($str, $link['url']);
43
44 // plugin data
45 $this->assertEquals(1, count($link['link_plugin']));
46 $this->assertNotFalse(strpos($link['link_plugin'][0], $str));
47 }
48
49 /**
50 * Test render_footer hook.
51 */
52 function testQrcodeFooter()
53 {
54 $str = 'stuff';
55 $data = array($str => $str);
56 $data['_PAGE_'] = Router::$PAGE_LINKLIST;
57
58 $data = hook_qrcode_render_footer($data);
59 $this->assertEquals($str, $data[$str]);
60 $this->assertEquals(1, count($data['js_files']));
61
62 $data = array($str => $str);
63 $data['_PAGE_'] = $str;
64 $this->assertEquals($str, $data[$str]);
65 $this->assertArrayNotHasKey('js_files', $data);
66 }
67}
diff --git a/tests/plugins/PluginAddlinkTest.php b/tests/plugins/PluginAddlinkTest.php
new file mode 100644
index 00000000..a2f25bec
--- /dev/null
+++ b/tests/plugins/PluginAddlinkTest.php
@@ -0,0 +1,100 @@
1<?php
2
3/**
4 * PluginPlayvideosTest.php
5 */
6
7require_once 'plugins/addlink_toolbar/addlink_toolbar.php';
8require_once 'application/Router.php';
9
10/**
11 * Class PluginAddlinkTest
12 * Unit test for the Addlink toolbar plugin
13 */
14class PluginAddlinkTest extends PHPUnit_Framework_TestCase
15{
16 /**
17 * Reset plugin path.
18 */
19 function setUp()
20 {
21 PluginManager::$PLUGINS_PATH = 'plugins';
22 }
23
24 /**
25 * Test render_header hook while logged in.
26 */
27 function testAddlinkHeaderLoggedIn()
28 {
29 $str = 'stuff';
30 $data = array($str => $str);
31 $data['_PAGE_'] = Router::$PAGE_LINKLIST;
32 $data['_LOGGEDIN_'] = true;
33
34 $data = hook_addlink_toolbar_render_header($data);
35 $this->assertEquals($str, $data[$str]);
36 $this->assertEquals(1, count($data['fields_toolbar']));
37
38 $data = array($str => $str);
39 $data['_PAGE_'] = $str;
40 $data['_LOGGEDIN_'] = true;
41 $data = hook_addlink_toolbar_render_header($data);
42 $this->assertEquals($str, $data[$str]);
43 $this->assertArrayNotHasKey('fields_toolbar', $data);
44 }
45
46 /**
47 * Test render_header hook while logged out.
48 */
49 function testAddlinkHeaderLoggedOut()
50 {
51 $str = 'stuff';
52 $data = array($str => $str);
53 $data['_PAGE_'] = Router::$PAGE_LINKLIST;
54 $data['_LOGGEDIN_'] = false;
55
56 $data = hook_addlink_toolbar_render_header($data);
57 $this->assertEquals($str, $data[$str]);
58 $this->assertArrayNotHasKey('fields_toolbar', $data);
59 }
60
61 /**
62 * Test render_includes hook while logged in.
63 */
64 function testAddlinkIncludesLoggedIn()
65 {
66 $str = 'stuff';
67 $data = array($str => $str);
68 $data['_PAGE_'] = Router::$PAGE_LINKLIST;
69 $data['_LOGGEDIN_'] = true;
70
71 $data = hook_addlink_toolbar_render_includes($data);
72 $this->assertEquals($str, $data[$str]);
73 $this->assertEquals(1, count($data['css_files']));
74
75 $str = 'stuff';
76 $data = array($str => $str);
77 $data['_PAGE_'] = $str;
78 $data['_LOGGEDIN_'] = true;
79
80 $data = hook_addlink_toolbar_render_includes($data);
81 $this->assertEquals($str, $data[$str]);
82 $this->assertArrayNotHasKey('css_files', $data);
83 }
84
85 /**
86 * Test render_includes hook.
87 * Should not affect css files while logged out.
88 */
89 function testAddlinkIncludesLoggedOut()
90 {
91 $str = 'stuff';
92 $data = array($str => $str);
93 $data['_PAGE_'] = Router::$PAGE_LINKLIST;
94 $data['_LOGGEDIN_'] = false;
95
96 $data = hook_addlink_toolbar_render_includes($data);
97 $this->assertEquals($str, $data[$str]);
98 $this->assertArrayNotHasKey('css_files', $data);
99 }
100}
diff --git a/tests/plugins/PluginArchiveorgTest.php b/tests/plugins/PluginArchiveorgTest.php
new file mode 100644
index 00000000..dbc52bc8
--- /dev/null
+++ b/tests/plugins/PluginArchiveorgTest.php
@@ -0,0 +1,48 @@
1<?php
2
3/**
4 * PluginArchiveorgTest.php
5 */
6
7require_once 'plugins/archiveorg/archiveorg.php';
8
9/**
10 * Class PlugQrcodeTest
11 * Unit test for the QR-Code plugin
12 */
13class PluginArchiveorgTest extends PHPUnit_Framework_TestCase
14{
15 /**
16 * Reset plugin path
17 */
18 function setUp()
19 {
20 PluginManager::$PLUGINS_PATH = 'plugins';
21 }
22
23 /**
24 * Test render_linklist hook.
25 */
26 function testArchiveorgLinklist()
27 {
28 $str = 'http://randomstr.com/test';
29 $data = array(
30 'title' => $str,
31 'links' => array(
32 array(
33 'url' => $str,
34 )
35 )
36 );
37
38 $data = hook_archiveorg_render_linklist($data);
39 $link = $data['links'][0];
40 // data shouldn't be altered
41 $this->assertEquals($str, $data['title']);
42 $this->assertEquals($str, $link['url']);
43
44 // plugin data
45 $this->assertEquals(1, count($link['link_plugin']));
46 $this->assertNotFalse(strpos($link['link_plugin'][0], $str));
47 }
48}
diff --git a/tests/plugins/PluginPlayvideosTest.php b/tests/plugins/PluginPlayvideosTest.php
new file mode 100644
index 00000000..be1ef774
--- /dev/null
+++ b/tests/plugins/PluginPlayvideosTest.php
@@ -0,0 +1,61 @@
1<?php
2
3/**
4 * PluginPlayvideosTest.php
5 */
6
7require_once 'plugins/playvideos/playvideos.php';
8require_once 'application/Router.php';
9
10/**
11 * Class PluginPlayvideosTest
12 * Unit test for the PlayVideos plugin
13 */
14class PluginPlayvideosTest extends PHPUnit_Framework_TestCase
15{
16 /**
17 * Reset plugin path
18 */
19 function setUp()
20 {
21 PluginManager::$PLUGINS_PATH = 'plugins';
22 }
23
24 /**
25 * Test render_linklist hook.
26 */
27 function testPlayvideosHeader()
28 {
29 $str = 'stuff';
30 $data = array($str => $str);
31 $data['_PAGE_'] = Router::$PAGE_LINKLIST;
32
33 $data = hook_playvideos_render_header($data);
34 $this->assertEquals($str, $data[$str]);
35 $this->assertEquals(1, count($data['buttons_toolbar']));
36
37 $data = array($str => $str);
38 $data['_PAGE_'] = $str;
39 $this->assertEquals($str, $data[$str]);
40 $this->assertArrayNotHasKey('buttons_toolbar', $data);
41 }
42
43 /**
44 * Test render_footer hook.
45 */
46 function testPlayvideosFooter()
47 {
48 $str = 'stuff';
49 $data = array($str => $str);
50 $data['_PAGE_'] = Router::$PAGE_LINKLIST;
51
52 $data = hook_playvideos_render_footer($data);
53 $this->assertEquals($str, $data[$str]);
54 $this->assertEquals(2, count($data['js_files']));
55
56 $data = array($str => $str);
57 $data['_PAGE_'] = $str;
58 $this->assertEquals($str, $data[$str]);
59 $this->assertArrayNotHasKey('js_files', $data);
60 }
61}