##// END OF EJS Templates
remove old external.js...
MinRK -
Show More
@@ -1,15 +0,0
1 We use minified versions of JQuery / jQueryUI and google-code-prettify in the Notebook.
2
3 Some package managers require full versions alongside minified,
4 and they can be dropped in here as necessary.
5
6 origins of our minified js:
7 prettify: http://google-code-prettify.googlecode.com/files/prettify-small-1-Jun-2011.tar.bz2
8 jQuery-1.7.1: http://code.jquery.com/jquery-1.7.1.min.js
9 jQueryUI menubar branch checkpoint: (generated by ant build from the source tree)
10
11 And their unminified counterparts:
12 prettify: http://google-code-prettify.googlecode.com/files/prettify-1-Jun-2011.tar.bz2
13 jQuery-1.7.1: http://code.jquery.com/jquery-1.7.1.js
14 jQueryUI version we ship: https://github.com/jquery/jquery-ui/tarball/ba8f147e4d69948aff4e956333098fb9360e3865
15 and the menubar branch in general: https://github.com/jquery/jquery-ui/tree/menubar
This diff has been collapsed as it changes many lines, (9266 lines changed) Show them Hide them
@@ -1,9266 +0,0
1 /*!
2 * jQuery JavaScript Library v1.7.1
3 * http://jquery.com/
4 *
5 * Copyright 2011, John Resig
6 * Dual licensed under the MIT or GPL Version 2 licenses.
7 * http://jquery.org/license
8 *
9 * Includes Sizzle.js
10 * http://sizzlejs.com/
11 * Copyright 2011, The Dojo Foundation
12 * Released under the MIT, BSD, and GPL Licenses.
13 *
14 * Date: Mon Nov 21 21:11:03 2011 -0500
15 */
16 (function( window, undefined ) {
17
18 // Use the correct document accordingly with window argument (sandbox)
19 var document = window.document,
20 navigator = window.navigator,
21 location = window.location;
22 var jQuery = (function() {
23
24 // Define a local copy of jQuery
25 var jQuery = function( selector, context ) {
26 // The jQuery object is actually just the init constructor 'enhanced'
27 return new jQuery.fn.init( selector, context, rootjQuery );
28 },
29
30 // Map over jQuery in case of overwrite
31 _jQuery = window.jQuery,
32
33 // Map over the $ in case of overwrite
34 _$ = window.$,
35
36 // A central reference to the root jQuery(document)
37 rootjQuery,
38
39 // A simple way to check for HTML strings or ID strings
40 // Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
41 quickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,
42
43 // Check if a string has a non-whitespace character in it
44 rnotwhite = /\S/,
45
46 // Used for trimming whitespace
47 trimLeft = /^\s+/,
48 trimRight = /\s+$/,
49
50 // Match a standalone tag
51 rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/,
52
53 // JSON RegExp
54 rvalidchars = /^[\],:{}\s]*$/,
55 rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,
56 rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,
57 rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g,
58
59 // Useragent RegExp
60 rwebkit = /(webkit)[ \/]([\w.]+)/,
61 ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/,
62 rmsie = /(msie) ([\w.]+)/,
63 rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/,
64
65 // Matches dashed string for camelizing
66 rdashAlpha = /-([a-z]|[0-9])/ig,
67 rmsPrefix = /^-ms-/,
68
69 // Used by jQuery.camelCase as callback to replace()
70 fcamelCase = function( all, letter ) {
71 return ( letter + "" ).toUpperCase();
72 },
73
74 // Keep a UserAgent string for use with jQuery.browser
75 userAgent = navigator.userAgent,
76
77 // For matching the engine and version of the browser
78 browserMatch,
79
80 // The deferred used on DOM ready
81 readyList,
82
83 // The ready event handler
84 DOMContentLoaded,
85
86 // Save a reference to some core methods
87 toString = Object.prototype.toString,
88 hasOwn = Object.prototype.hasOwnProperty,
89 push = Array.prototype.push,
90 slice = Array.prototype.slice,
91 trim = String.prototype.trim,
92 indexOf = Array.prototype.indexOf,
93
94 // [[Class]] -> type pairs
95 class2type = {};
96
97 jQuery.fn = jQuery.prototype = {
98 constructor: jQuery,
99 init: function( selector, context, rootjQuery ) {
100 var match, elem, ret, doc;
101
102 // Handle $(""), $(null), or $(undefined)
103 if ( !selector ) {
104 return this;
105 }
106
107 // Handle $(DOMElement)
108 if ( selector.nodeType ) {
109 this.context = this[0] = selector;
110 this.length = 1;
111 return this;
112 }
113
114 // The body element only exists once, optimize finding it
115 if ( selector === "body" && !context && document.body ) {
116 this.context = document;
117 this[0] = document.body;
118 this.selector = selector;
119 this.length = 1;
120 return this;
121 }
122
123 // Handle HTML strings
124 if ( typeof selector === "string" ) {
125 // Are we dealing with HTML string or an ID?
126 if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
127 // Assume that strings that start and end with <> are HTML and skip the regex check
128 match = [ null, selector, null ];
129
130 } else {
131 match = quickExpr.exec( selector );
132 }
133
134 // Verify a match, and that no context was specified for #id
135 if ( match && (match[1] || !context) ) {
136
137 // HANDLE: $(html) -> $(array)
138 if ( match[1] ) {
139 context = context instanceof jQuery ? context[0] : context;
140 doc = ( context ? context.ownerDocument || context : document );
141
142 // If a single string is passed in and it's a single tag
143 // just do a createElement and skip the rest
144 ret = rsingleTag.exec( selector );
145
146 if ( ret ) {
147 if ( jQuery.isPlainObject( context ) ) {
148 selector = [ document.createElement( ret[1] ) ];
149 jQuery.fn.attr.call( selector, context, true );
150
151 } else {
152 selector = [ doc.createElement( ret[1] ) ];
153 }
154
155 } else {
156 ret = jQuery.buildFragment( [ match[1] ], [ doc ] );
157 selector = ( ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment ).childNodes;
158 }
159
160 return jQuery.merge( this, selector );
161
162 // HANDLE: $("#id")
163 } else {
164 elem = document.getElementById( match[2] );
165
166 // Check parentNode to catch when Blackberry 4.6 returns
167 // nodes that are no longer in the document #6963
168 if ( elem && elem.parentNode ) {
169 // Handle the case where IE and Opera return items
170 // by name instead of ID
171 if ( elem.id !== match[2] ) {
172 return rootjQuery.find( selector );
173 }
174
175 // Otherwise, we inject the element directly into the jQuery object
176 this.length = 1;
177 this[0] = elem;
178 }
179
180 this.context = document;
181 this.selector = selector;
182 return this;
183 }
184
185 // HANDLE: $(expr, $(...))
186 } else if ( !context || context.jquery ) {
187 return ( context || rootjQuery ).find( selector );
188
189 // HANDLE: $(expr, context)
190 // (which is just equivalent to: $(context).find(expr)
191 } else {
192 return this.constructor( context ).find( selector );
193 }
194
195 // HANDLE: $(function)
196 // Shortcut for document ready
197 } else if ( jQuery.isFunction( selector ) ) {
198 return rootjQuery.ready( selector );
199 }
200
201 if ( selector.selector !== undefined ) {
202 this.selector = selector.selector;
203 this.context = selector.context;
204 }
205
206 return jQuery.makeArray( selector, this );
207 },
208
209 // Start with an empty selector
210 selector: "",
211
212 // The current version of jQuery being used
213 jquery: "1.7.1",
214
215 // The default length of a jQuery object is 0
216 length: 0,
217
218 // The number of elements contained in the matched element set
219 size: function() {
220 return this.length;
221 },
222
223 toArray: function() {
224 return slice.call( this, 0 );
225 },
226
227 // Get the Nth element in the matched element set OR
228 // Get the whole matched element set as a clean array
229 get: function( num ) {
230 return num == null ?
231
232 // Return a 'clean' array
233 this.toArray() :
234
235 // Return just the object
236 ( num < 0 ? this[ this.length + num ] : this[ num ] );
237 },
238
239 // Take an array of elements and push it onto the stack
240 // (returning the new matched element set)
241 pushStack: function( elems, name, selector ) {
242 // Build a new jQuery matched element set
243 var ret = this.constructor();
244
245 if ( jQuery.isArray( elems ) ) {
246 push.apply( ret, elems );
247
248 } else {
249 jQuery.merge( ret, elems );
250 }
251
252 // Add the old object onto the stack (as a reference)
253 ret.prevObject = this;
254
255 ret.context = this.context;
256
257 if ( name === "find" ) {
258 ret.selector = this.selector + ( this.selector ? " " : "" ) + selector;
259 } else if ( name ) {
260 ret.selector = this.selector + "." + name + "(" + selector + ")";
261 }
262
263 // Return the newly-formed element set
264 return ret;
265 },
266
267 // Execute a callback for every element in the matched set.
268 // (You can seed the arguments with an array of args, but this is
269 // only used internally.)
270 each: function( callback, args ) {
271 return jQuery.each( this, callback, args );
272 },
273
274 ready: function( fn ) {
275 // Attach the listeners
276 jQuery.bindReady();
277
278 // Add the callback
279 readyList.add( fn );
280
281 return this;
282 },
283
284 eq: function( i ) {
285 i = +i;
286 return i === -1 ?
287 this.slice( i ) :
288 this.slice( i, i + 1 );
289 },
290
291 first: function() {
292 return this.eq( 0 );
293 },
294
295 last: function() {
296 return this.eq( -1 );
297 },
298
299 slice: function() {
300 return this.pushStack( slice.apply( this, arguments ),
301 "slice", slice.call(arguments).join(",") );
302 },
303
304 map: function( callback ) {
305 return this.pushStack( jQuery.map(this, function( elem, i ) {
306 return callback.call( elem, i, elem );
307 }));
308 },
309
310 end: function() {
311 return this.prevObject || this.constructor(null);
312 },
313
314 // For internal use only.
315 // Behaves like an Array's method, not like a jQuery method.
316 push: push,
317 sort: [].sort,
318 splice: [].splice
319 };
320
321 // Give the init function the jQuery prototype for later instantiation
322 jQuery.fn.init.prototype = jQuery.fn;
323
324 jQuery.extend = jQuery.fn.extend = function() {
325 var options, name, src, copy, copyIsArray, clone,
326 target = arguments[0] || {},
327 i = 1,
328 length = arguments.length,
329 deep = false;
330
331 // Handle a deep copy situation
332 if ( typeof target === "boolean" ) {
333 deep = target;
334 target = arguments[1] || {};
335 // skip the boolean and the target
336 i = 2;
337 }
338
339 // Handle case when target is a string or something (possible in deep copy)
340 if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
341 target = {};
342 }
343
344 // extend jQuery itself if only one argument is passed
345 if ( length === i ) {
346 target = this;
347 --i;
348 }
349
350 for ( ; i < length; i++ ) {
351 // Only deal with non-null/undefined values
352 if ( (options = arguments[ i ]) != null ) {
353 // Extend the base object
354 for ( name in options ) {
355 src = target[ name ];
356 copy = options[ name ];
357
358 // Prevent never-ending loop
359 if ( target === copy ) {
360 continue;
361 }
362
363 // Recurse if we're merging plain objects or arrays
364 if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
365 if ( copyIsArray ) {
366 copyIsArray = false;
367 clone = src && jQuery.isArray(src) ? src : [];
368
369 } else {
370 clone = src && jQuery.isPlainObject(src) ? src : {};
371 }
372
373 // Never move original objects, clone them
374 target[ name ] = jQuery.extend( deep, clone, copy );
375
376 // Don't bring in undefined values
377 } else if ( copy !== undefined ) {
378 target[ name ] = copy;
379 }
380 }
381 }
382 }
383
384 // Return the modified object
385 return target;
386 };
387
388 jQuery.extend({
389 noConflict: function( deep ) {
390 if ( window.$ === jQuery ) {
391 window.$ = _$;
392 }
393
394 if ( deep && window.jQuery === jQuery ) {
395 window.jQuery = _jQuery;
396 }
397
398 return jQuery;
399 },
400
401 // Is the DOM ready to be used? Set to true once it occurs.
402 isReady: false,
403
404 // A counter to track how many items to wait for before
405 // the ready event fires. See #6781
406 readyWait: 1,
407
408 // Hold (or release) the ready event
409 holdReady: function( hold ) {
410 if ( hold ) {
411 jQuery.readyWait++;
412 } else {
413 jQuery.ready( true );
414 }
415 },
416
417 // Handle when the DOM is ready
418 ready: function( wait ) {
419 // Either a released hold or an DOMready/load event and not yet ready
420 if ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) {
421 // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
422 if ( !document.body ) {
423 return setTimeout( jQuery.ready, 1 );
424 }
425
426 // Remember that the DOM is ready
427 jQuery.isReady = true;
428
429 // If a normal DOM Ready event fired, decrement, and wait if need be
430 if ( wait !== true && --jQuery.readyWait > 0 ) {
431 return;
432 }
433
434 // If there are functions bound, to execute
435 readyList.fireWith( document, [ jQuery ] );
436
437 // Trigger any bound ready events
438 if ( jQuery.fn.trigger ) {
439 jQuery( document ).trigger( "ready" ).off( "ready" );
440 }
441 }
442 },
443
444 bindReady: function() {
445 if ( readyList ) {
446 return;
447 }
448
449 readyList = jQuery.Callbacks( "once memory" );
450
451 // Catch cases where $(document).ready() is called after the
452 // browser event has already occurred.
453 if ( document.readyState === "complete" ) {
454 // Handle it asynchronously to allow scripts the opportunity to delay ready
455 return setTimeout( jQuery.ready, 1 );
456 }
457
458 // Mozilla, Opera and webkit nightlies currently support this event
459 if ( document.addEventListener ) {
460 // Use the handy event callback
461 document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
462
463 // A fallback to window.onload, that will always work
464 window.addEventListener( "load", jQuery.ready, false );
465
466 // If IE event model is used
467 } else if ( document.attachEvent ) {
468 // ensure firing before onload,
469 // maybe late but safe also for iframes
470 document.attachEvent( "onreadystatechange", DOMContentLoaded );
471
472 // A fallback to window.onload, that will always work
473 window.attachEvent( "onload", jQuery.ready );
474
475 // If IE and not a frame
476 // continually check to see if the document is ready
477 var toplevel = false;
478
479 try {
480 toplevel = window.frameElement == null;
481 } catch(e) {}
482
483 if ( document.documentElement.doScroll && toplevel ) {
484 doScrollCheck();
485 }
486 }
487 },
488
489 // See test/unit/core.js for details concerning isFunction.
490 // Since version 1.3, DOM methods and functions like alert
491 // aren't supported. They return false on IE (#2968).
492 isFunction: function( obj ) {
493 return jQuery.type(obj) === "function";
494 },
495
496 isArray: Array.isArray || function( obj ) {
497 return jQuery.type(obj) === "array";
498 },
499
500 // A crude way of determining if an object is a window
501 isWindow: function( obj ) {
502 return obj && typeof obj === "object" && "setInterval" in obj;
503 },
504
505 isNumeric: function( obj ) {
506 return !isNaN( parseFloat(obj) ) && isFinite( obj );
507 },
508
509 type: function( obj ) {
510 return obj == null ?
511 String( obj ) :
512 class2type[ toString.call(obj) ] || "object";
513 },
514
515 isPlainObject: function( obj ) {
516 // Must be an Object.
517 // Because of IE, we also have to check the presence of the constructor property.
518 // Make sure that DOM nodes and window objects don't pass through, as well
519 if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
520 return false;
521 }
522
523 try {
524 // Not own constructor property must be Object
525 if ( obj.constructor &&
526 !hasOwn.call(obj, "constructor") &&
527 !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
528 return false;
529 }
530 } catch ( e ) {
531 // IE8,9 Will throw exceptions on certain host objects #9897
532 return false;
533 }
534
535 // Own properties are enumerated firstly, so to speed up,
536 // if last one is own, then all properties are own.
537
538 var key;
539 for ( key in obj ) {}
540
541 return key === undefined || hasOwn.call( obj, key );
542 },
543
544 isEmptyObject: function( obj ) {
545 for ( var name in obj ) {
546 return false;
547 }
548 return true;
549 },
550
551 error: function( msg ) {
552 throw new Error( msg );
553 },
554
555 parseJSON: function( data ) {
556 if ( typeof data !== "string" || !data ) {
557 return null;
558 }
559
560 // Make sure leading/trailing whitespace is removed (IE can't handle it)
561 data = jQuery.trim( data );
562
563 // Attempt to parse using the native JSON parser first
564 if ( window.JSON && window.JSON.parse ) {
565 return window.JSON.parse( data );
566 }
567
568 // Make sure the incoming data is actual JSON
569 // Logic borrowed from http://json.org/json2.js
570 if ( rvalidchars.test( data.replace( rvalidescape, "@" )
571 .replace( rvalidtokens, "]" )
572 .replace( rvalidbraces, "")) ) {
573
574 return ( new Function( "return " + data ) )();
575
576 }
577 jQuery.error( "Invalid JSON: " + data );
578 },
579
580 // Cross-browser xml parsing
581 parseXML: function( data ) {
582 var xml, tmp;
583 try {
584 if ( window.DOMParser ) { // Standard
585 tmp = new DOMParser();
586 xml = tmp.parseFromString( data , "text/xml" );
587 } else { // IE
588 xml = new ActiveXObject( "Microsoft.XMLDOM" );
589 xml.async = "false";
590 xml.loadXML( data );
591 }
592 } catch( e ) {
593 xml = undefined;
594 }
595 if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) {
596 jQuery.error( "Invalid XML: " + data );
597 }
598 return xml;
599 },
600
601 noop: function() {},
602
603 // Evaluates a script in a global context
604 // Workarounds based on findings by Jim Driscoll
605 // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context
606 globalEval: function( data ) {
607 if ( data && rnotwhite.test( data ) ) {
608 // We use execScript on Internet Explorer
609 // We use an anonymous function so that context is window
610 // rather than jQuery in Firefox
611 ( window.execScript || function( data ) {
612 window[ "eval" ].call( window, data );
613 } )( data );
614 }
615 },
616
617 // Convert dashed to camelCase; used by the css and data modules
618 // Microsoft forgot to hump their vendor prefix (#9572)
619 camelCase: function( string ) {
620 return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
621 },
622
623 nodeName: function( elem, name ) {
624 return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();
625 },
626
627 // args is for internal usage only
628 each: function( object, callback, args ) {
629 var name, i = 0,
630 length = object.length,
631 isObj = length === undefined || jQuery.isFunction( object );
632
633 if ( args ) {
634 if ( isObj ) {
635 for ( name in object ) {
636 if ( callback.apply( object[ name ], args ) === false ) {
637 break;
638 }
639 }
640 } else {
641 for ( ; i < length; ) {
642 if ( callback.apply( object[ i++ ], args ) === false ) {
643 break;
644 }
645 }
646 }
647
648 // A special, fast, case for the most common use of each
649 } else {
650 if ( isObj ) {
651 for ( name in object ) {
652 if ( callback.call( object[ name ], name, object[ name ] ) === false ) {
653 break;
654 }
655 }
656 } else {
657 for ( ; i < length; ) {
658 if ( callback.call( object[ i ], i, object[ i++ ] ) === false ) {
659 break;
660 }
661 }
662 }
663 }
664
665 return object;
666 },
667
668 // Use native String.trim function wherever possible
669 trim: trim ?
670 function( text ) {
671 return text == null ?
672 "" :
673 trim.call( text );
674 } :
675
676 // Otherwise use our own trimming functionality
677 function( text ) {
678 return text == null ?
679 "" :
680 text.toString().replace( trimLeft, "" ).replace( trimRight, "" );
681 },
682
683 // results is for internal usage only
684 makeArray: function( array, results ) {
685 var ret = results || [];
686
687 if ( array != null ) {
688 // The window, strings (and functions) also have 'length'
689 // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930
690 var type = jQuery.type( array );
691
692 if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) {
693 push.call( ret, array );
694 } else {
695 jQuery.merge( ret, array );
696 }
697 }
698
699 return ret;
700 },
701
702 inArray: function( elem, array, i ) {
703 var len;
704
705 if ( array ) {
706 if ( indexOf ) {
707 return indexOf.call( array, elem, i );
708 }
709
710 len = array.length;
711 i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;
712
713 for ( ; i < len; i++ ) {
714 // Skip accessing in sparse arrays
715 if ( i in array && array[ i ] === elem ) {
716 return i;
717 }
718 }
719 }
720
721 return -1;
722 },
723
724 merge: function( first, second ) {
725 var i = first.length,
726 j = 0;
727
728 if ( typeof second.length === "number" ) {
729 for ( var l = second.length; j < l; j++ ) {
730 first[ i++ ] = second[ j ];
731 }
732
733 } else {
734 while ( second[j] !== undefined ) {
735 first[ i++ ] = second[ j++ ];
736 }
737 }
738
739 first.length = i;
740
741 return first;
742 },
743
744 grep: function( elems, callback, inv ) {
745 var ret = [], retVal;
746 inv = !!inv;
747
748 // Go through the array, only saving the items
749 // that pass the validator function
750 for ( var i = 0, length = elems.length; i < length; i++ ) {
751 retVal = !!callback( elems[ i ], i );
752 if ( inv !== retVal ) {
753 ret.push( elems[ i ] );
754 }
755 }
756
757 return ret;
758 },
759
760 // arg is for internal usage only
761 map: function( elems, callback, arg ) {
762 var value, key, ret = [],
763 i = 0,
764 length = elems.length,
765 // jquery objects are treated as arrays
766 isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ;
767
768 // Go through the array, translating each of the items to their
769 if ( isArray ) {
770 for ( ; i < length; i++ ) {
771 value = callback( elems[ i ], i, arg );
772
773 if ( value != null ) {
774 ret[ ret.length ] = value;
775 }
776 }
777
778 // Go through every key on the object,
779 } else {
780 for ( key in elems ) {
781 value = callback( elems[ key ], key, arg );
782
783 if ( value != null ) {
784 ret[ ret.length ] = value;
785 }
786 }
787 }
788
789 // Flatten any nested arrays
790 return ret.concat.apply( [], ret );
791 },
792
793 // A global GUID counter for objects
794 guid: 1,
795
796 // Bind a function to a context, optionally partially applying any
797 // arguments.
798 proxy: function( fn, context ) {
799 if ( typeof context === "string" ) {
800 var tmp = fn[ context ];
801 context = fn;
802 fn = tmp;
803 }
804
805 // Quick check to determine if target is callable, in the spec
806 // this throws a TypeError, but we will just return undefined.
807 if ( !jQuery.isFunction( fn ) ) {
808 return undefined;
809 }
810
811 // Simulated bind
812 var args = slice.call( arguments, 2 ),
813 proxy = function() {
814 return fn.apply( context, args.concat( slice.call( arguments ) ) );
815 };
816
817 // Set the guid of unique handler to the same of original handler, so it can be removed
818 proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++;
819
820 return proxy;
821 },
822
823 // Mutifunctional method to get and set values to a collection
824 // The value/s can optionally be executed if it's a function
825 access: function( elems, key, value, exec, fn, pass ) {
826 var length = elems.length;
827
828 // Setting many attributes
829 if ( typeof key === "object" ) {
830 for ( var k in key ) {
831 jQuery.access( elems, k, key[k], exec, fn, value );
832 }
833 return elems;
834 }
835
836 // Setting one attribute
837 if ( value !== undefined ) {
838 // Optionally, function values get executed if exec is true
839 exec = !pass && exec && jQuery.isFunction(value);
840
841 for ( var i = 0; i < length; i++ ) {
842 fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );
843 }
844
845 return elems;
846 }
847
848 // Getting an attribute
849 return length ? fn( elems[0], key ) : undefined;
850 },
851
852 now: function() {
853 return ( new Date() ).getTime();
854 },
855
856 // Use of jQuery.browser is frowned upon.
857 // More details: http://docs.jquery.com/Utilities/jQuery.browser
858 uaMatch: function( ua ) {
859 ua = ua.toLowerCase();
860
861 var match = rwebkit.exec( ua ) ||
862 ropera.exec( ua ) ||
863 rmsie.exec( ua ) ||
864 ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) ||
865 [];
866
867 return { browser: match[1] || "", version: match[2] || "0" };
868 },
869
870 sub: function() {
871 function jQuerySub( selector, context ) {
872 return new jQuerySub.fn.init( selector, context );
873 }
874 jQuery.extend( true, jQuerySub, this );
875 jQuerySub.superclass = this;
876 jQuerySub.fn = jQuerySub.prototype = this();
877 jQuerySub.fn.constructor = jQuerySub;
878 jQuerySub.sub = this.sub;
879 jQuerySub.fn.init = function init( selector, context ) {
880 if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) {
881 context = jQuerySub( context );
882 }
883
884 return jQuery.fn.init.call( this, selector, context, rootjQuerySub );
885 };
886 jQuerySub.fn.init.prototype = jQuerySub.fn;
887 var rootjQuerySub = jQuerySub(document);
888 return jQuerySub;
889 },
890
891 browser: {}
892 });
893
894 // Populate the class2type map
895 jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) {
896 class2type[ "[object " + name + "]" ] = name.toLowerCase();
897 });
898
899 browserMatch = jQuery.uaMatch( userAgent );
900 if ( browserMatch.browser ) {
901 jQuery.browser[ browserMatch.browser ] = true;
902 jQuery.browser.version = browserMatch.version;
903 }
904
905 // Deprecated, use jQuery.browser.webkit instead
906 if ( jQuery.browser.webkit ) {
907 jQuery.browser.safari = true;
908 }
909
910 // IE doesn't match non-breaking spaces with \s
911 if ( rnotwhite.test( "\xA0" ) ) {
912 trimLeft = /^[\s\xA0]+/;
913 trimRight = /[\s\xA0]+$/;
914 }
915
916 // All jQuery objects should point back to these
917 rootjQuery = jQuery(document);
918
919 // Cleanup functions for the document ready method
920 if ( document.addEventListener ) {
921 DOMContentLoaded = function() {
922 document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
923 jQuery.ready();
924 };
925
926 } else if ( document.attachEvent ) {
927 DOMContentLoaded = function() {
928 // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
929 if ( document.readyState === "complete" ) {
930 document.detachEvent( "onreadystatechange", DOMContentLoaded );
931 jQuery.ready();
932 }
933 };
934 }
935
936 // The DOM ready check for Internet Explorer
937 function doScrollCheck() {
938 if ( jQuery.isReady ) {
939 return;
940 }
941
942 try {
943 // If IE is used, use the trick by Diego Perini
944 // http://javascript.nwbox.com/IEContentLoaded/
945 document.documentElement.doScroll("left");
946 } catch(e) {
947 setTimeout( doScrollCheck, 1 );
948 return;
949 }
950
951 // and execute any waiting functions
952 jQuery.ready();
953 }
954
955 return jQuery;
956
957 })();
958
959
960 // String to Object flags format cache
961 var flagsCache = {};
962
963 // Convert String-formatted flags into Object-formatted ones and store in cache
964 function createFlags( flags ) {
965 var object = flagsCache[ flags ] = {},
966 i, length;
967 flags = flags.split( /\s+/ );
968 for ( i = 0, length = flags.length; i < length; i++ ) {
969 object[ flags[i] ] = true;
970 }
971 return object;
972 }
973
974 /*
975 * Create a callback list using the following parameters:
976 *
977 * flags: an optional list of space-separated flags that will change how
978 * the callback list behaves
979 *
980 * By default a callback list will act like an event callback list and can be
981 * "fired" multiple times.
982 *
983 * Possible flags:
984 *
985 * once: will ensure the callback list can only be fired once (like a Deferred)
986 *
987 * memory: will keep track of previous values and will call any callback added
988 * after the list has been fired right away with the latest "memorized"
989 * values (like a Deferred)
990 *
991 * unique: will ensure a callback can only be added once (no duplicate in the list)
992 *
993 * stopOnFalse: interrupt callings when a callback returns false
994 *
995 */
996 jQuery.Callbacks = function( flags ) {
997
998 // Convert flags from String-formatted to Object-formatted
999 // (we check in cache first)
1000 flags = flags ? ( flagsCache[ flags ] || createFlags( flags ) ) : {};
1001
1002 var // Actual callback list
1003 list = [],
1004 // Stack of fire calls for repeatable lists
1005 stack = [],
1006 // Last fire value (for non-forgettable lists)
1007 memory,
1008 // Flag to know if list is currently firing
1009 firing,
1010 // First callback to fire (used internally by add and fireWith)
1011 firingStart,
1012 // End of the loop when firing
1013 firingLength,
1014 // Index of currently firing callback (modified by remove if needed)
1015 firingIndex,
1016 // Add one or several callbacks to the list
1017 add = function( args ) {
1018 var i,
1019 length,
1020 elem,
1021 type,
1022 actual;
1023 for ( i = 0, length = args.length; i < length; i++ ) {
1024 elem = args[ i ];
1025 type = jQuery.type( elem );
1026 if ( type === "array" ) {
1027 // Inspect recursively
1028 add( elem );
1029 } else if ( type === "function" ) {
1030 // Add if not in unique mode and callback is not in
1031 if ( !flags.unique || !self.has( elem ) ) {
1032 list.push( elem );
1033 }
1034 }
1035 }
1036 },
1037 // Fire callbacks
1038 fire = function( context, args ) {
1039 args = args || [];
1040 memory = !flags.memory || [ context, args ];
1041 firing = true;
1042 firingIndex = firingStart || 0;
1043 firingStart = 0;
1044 firingLength = list.length;
1045 for ( ; list && firingIndex < firingLength; firingIndex++ ) {
1046 if ( list[ firingIndex ].apply( context, args ) === false && flags.stopOnFalse ) {
1047 memory = true; // Mark as halted
1048 break;
1049 }
1050 }
1051 firing = false;
1052 if ( list ) {
1053 if ( !flags.once ) {
1054 if ( stack && stack.length ) {
1055 memory = stack.shift();
1056 self.fireWith( memory[ 0 ], memory[ 1 ] );
1057 }
1058 } else if ( memory === true ) {
1059 self.disable();
1060 } else {
1061 list = [];
1062 }
1063 }
1064 },
1065 // Actual Callbacks object
1066 self = {
1067 // Add a callback or a collection of callbacks to the list
1068 add: function() {
1069 if ( list ) {
1070 var length = list.length;
1071 add( arguments );
1072 // Do we need to add the callbacks to the
1073 // current firing batch?
1074 if ( firing ) {
1075 firingLength = list.length;
1076 // With memory, if we're not firing then
1077 // we should call right away, unless previous
1078 // firing was halted (stopOnFalse)
1079 } else if ( memory && memory !== true ) {
1080 firingStart = length;
1081 fire( memory[ 0 ], memory[ 1 ] );
1082 }
1083 }
1084 return this;
1085 },
1086 // Remove a callback from the list
1087 remove: function() {
1088 if ( list ) {
1089 var args = arguments,
1090 argIndex = 0,
1091 argLength = args.length;
1092 for ( ; argIndex < argLength ; argIndex++ ) {
1093 for ( var i = 0; i < list.length; i++ ) {
1094 if ( args[ argIndex ] === list[ i ] ) {
1095 // Handle firingIndex and firingLength
1096 if ( firing ) {
1097 if ( i <= firingLength ) {
1098 firingLength--;
1099 if ( i <= firingIndex ) {
1100 firingIndex--;
1101 }
1102 }
1103 }
1104 // Remove the element
1105 list.splice( i--, 1 );
1106 // If we have some unicity property then
1107 // we only need to do this once
1108 if ( flags.unique ) {
1109 break;
1110 }
1111 }
1112 }
1113 }
1114 }
1115 return this;
1116 },
1117 // Control if a given callback is in the list
1118 has: function( fn ) {
1119 if ( list ) {
1120 var i = 0,
1121 length = list.length;
1122 for ( ; i < length; i++ ) {
1123 if ( fn === list[ i ] ) {
1124 return true;
1125 }
1126 }
1127 }
1128 return false;
1129 },
1130 // Remove all callbacks from the list
1131 empty: function() {
1132 list = [];
1133 return this;
1134 },
1135 // Have the list do nothing anymore
1136 disable: function() {
1137 list = stack = memory = undefined;
1138 return this;
1139 },
1140 // Is it disabled?
1141 disabled: function() {
1142 return !list;
1143 },
1144 // Lock the list in its current state
1145 lock: function() {
1146 stack = undefined;
1147 if ( !memory || memory === true ) {
1148 self.disable();
1149 }
1150 return this;
1151 },
1152 // Is it locked?
1153 locked: function() {
1154 return !stack;
1155 },
1156 // Call all callbacks with the given context and arguments
1157 fireWith: function( context, args ) {
1158 if ( stack ) {
1159 if ( firing ) {
1160 if ( !flags.once ) {
1161 stack.push( [ context, args ] );
1162 }
1163 } else if ( !( flags.once && memory ) ) {
1164 fire( context, args );
1165 }
1166 }
1167 return this;
1168 },
1169 // Call all the callbacks with the given arguments
1170 fire: function() {
1171 self.fireWith( this, arguments );
1172 return this;
1173 },
1174 // To know if the callbacks have already been called at least once
1175 fired: function() {
1176 return !!memory;
1177 }
1178 };
1179
1180 return self;
1181 };
1182
1183
1184
1185
1186 var // Static reference to slice
1187 sliceDeferred = [].slice;
1188
1189 jQuery.extend({
1190
1191 Deferred: function( func ) {
1192 var doneList = jQuery.Callbacks( "once memory" ),
1193 failList = jQuery.Callbacks( "once memory" ),
1194 progressList = jQuery.Callbacks( "memory" ),
1195 state = "pending",
1196 lists = {
1197 resolve: doneList,
1198 reject: failList,
1199 notify: progressList
1200 },
1201 promise = {
1202 done: doneList.add,
1203 fail: failList.add,
1204 progress: progressList.add,
1205
1206 state: function() {
1207 return state;
1208 },
1209
1210 // Deprecated
1211 isResolved: doneList.fired,
1212 isRejected: failList.fired,
1213
1214 then: function( doneCallbacks, failCallbacks, progressCallbacks ) {
1215 deferred.done( doneCallbacks ).fail( failCallbacks ).progress( progressCallbacks );
1216 return this;
1217 },
1218 always: function() {
1219 deferred.done.apply( deferred, arguments ).fail.apply( deferred, arguments );
1220 return this;
1221 },
1222 pipe: function( fnDone, fnFail, fnProgress ) {
1223 return jQuery.Deferred(function( newDefer ) {
1224 jQuery.each( {
1225 done: [ fnDone, "resolve" ],
1226 fail: [ fnFail, "reject" ],
1227 progress: [ fnProgress, "notify" ]
1228 }, function( handler, data ) {
1229 var fn = data[ 0 ],
1230 action = data[ 1 ],
1231 returned;
1232 if ( jQuery.isFunction( fn ) ) {
1233 deferred[ handler ](function() {
1234 returned = fn.apply( this, arguments );
1235 if ( returned && jQuery.isFunction( returned.promise ) ) {
1236 returned.promise().then( newDefer.resolve, newDefer.reject, newDefer.notify );
1237 } else {
1238 newDefer[ action + "With" ]( this === deferred ? newDefer : this, [ returned ] );
1239 }
1240 });
1241 } else {
1242 deferred[ handler ]( newDefer[ action ] );
1243 }
1244 });
1245 }).promise();
1246 },
1247 // Get a promise for this deferred
1248 // If obj is provided, the promise aspect is added to the object
1249 promise: function( obj ) {
1250 if ( obj == null ) {
1251 obj = promise;
1252 } else {
1253 for ( var key in promise ) {
1254 obj[ key ] = promise[ key ];
1255 }
1256 }
1257 return obj;
1258 }
1259 },
1260 deferred = promise.promise({}),
1261 key;
1262
1263 for ( key in lists ) {
1264 deferred[ key ] = lists[ key ].fire;
1265 deferred[ key + "With" ] = lists[ key ].fireWith;
1266 }
1267
1268 // Handle state
1269 deferred.done( function() {
1270 state = "resolved";
1271 }, failList.disable, progressList.lock ).fail( function() {
1272 state = "rejected";
1273 }, doneList.disable, progressList.lock );
1274
1275 // Call given func if any
1276 if ( func ) {
1277 func.call( deferred, deferred );
1278 }
1279
1280 // All done!
1281 return deferred;
1282 },
1283
1284 // Deferred helper
1285 when: function( firstParam ) {
1286 var args = sliceDeferred.call( arguments, 0 ),
1287 i = 0,
1288 length = args.length,
1289 pValues = new Array( length ),
1290 count = length,
1291 pCount = length,
1292 deferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ?
1293 firstParam :
1294 jQuery.Deferred(),
1295 promise = deferred.promise();
1296 function resolveFunc( i ) {
1297 return function( value ) {
1298 args[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;
1299 if ( !( --count ) ) {
1300 deferred.resolveWith( deferred, args );
1301 }
1302 };
1303 }
1304 function progressFunc( i ) {
1305 return function( value ) {
1306 pValues[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;
1307 deferred.notifyWith( promise, pValues );
1308 };
1309 }
1310 if ( length > 1 ) {
1311 for ( ; i < length; i++ ) {
1312 if ( args[ i ] && args[ i ].promise && jQuery.isFunction( args[ i ].promise ) ) {
1313 args[ i ].promise().then( resolveFunc(i), deferred.reject, progressFunc(i) );
1314 } else {
1315 --count;
1316 }
1317 }
1318 if ( !count ) {
1319 deferred.resolveWith( deferred, args );
1320 }
1321 } else if ( deferred !== firstParam ) {
1322 deferred.resolveWith( deferred, length ? [ firstParam ] : [] );
1323 }
1324 return promise;
1325 }
1326 });
1327
1328
1329
1330
1331 jQuery.support = (function() {
1332
1333 var support,
1334 all,
1335 a,
1336 select,
1337 opt,
1338 input,
1339 marginDiv,
1340 fragment,
1341 tds,
1342 events,
1343 eventName,
1344 i,
1345 isSupported,
1346 div = document.createElement( "div" ),
1347 documentElement = document.documentElement;
1348
1349 // Preliminary tests
1350 div.setAttribute("className", "t");
1351 div.innerHTML = " <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>";
1352
1353 all = div.getElementsByTagName( "*" );
1354 a = div.getElementsByTagName( "a" )[ 0 ];
1355
1356 // Can't get basic test support
1357 if ( !all || !all.length || !a ) {
1358 return {};
1359 }
1360
1361 // First batch of supports tests
1362 select = document.createElement( "select" );
1363 opt = select.appendChild( document.createElement("option") );
1364 input = div.getElementsByTagName( "input" )[ 0 ];
1365
1366 support = {
1367 // IE strips leading whitespace when .innerHTML is used
1368 leadingWhitespace: ( div.firstChild.nodeType === 3 ),
1369
1370 // Make sure that tbody elements aren't automatically inserted
1371 // IE will insert them into empty tables
1372 tbody: !div.getElementsByTagName("tbody").length,
1373
1374 // Make sure that link elements get serialized correctly by innerHTML
1375 // This requires a wrapper element in IE
1376 htmlSerialize: !!div.getElementsByTagName("link").length,
1377
1378 // Get the style information from getAttribute
1379 // (IE uses .cssText instead)
1380 style: /top/.test( a.getAttribute("style") ),
1381
1382 // Make sure that URLs aren't manipulated
1383 // (IE normalizes it by default)
1384 hrefNormalized: ( a.getAttribute("href") === "/a" ),
1385
1386 // Make sure that element opacity exists
1387 // (IE uses filter instead)
1388 // Use a regex to work around a WebKit issue. See #5145
1389 opacity: /^0.55/.test( a.style.opacity ),
1390
1391 // Verify style float existence
1392 // (IE uses styleFloat instead of cssFloat)
1393 cssFloat: !!a.style.cssFloat,
1394
1395 // Make sure that if no value is specified for a checkbox
1396 // that it defaults to "on".
1397 // (WebKit defaults to "" instead)
1398 checkOn: ( input.value === "on" ),
1399
1400 // Make sure that a selected-by-default option has a working selected property.
1401 // (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
1402 optSelected: opt.selected,
1403
1404 // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)
1405 getSetAttribute: div.className !== "t",
1406
1407 // Tests for enctype support on a form(#6743)
1408 enctype: !!document.createElement("form").enctype,
1409
1410 // Makes sure cloning an html5 element does not cause problems
1411 // Where outerHTML is undefined, this still works
1412 html5Clone: document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav></:nav>",
1413
1414 // Will be defined later
1415 submitBubbles: true,
1416 changeBubbles: true,
1417 focusinBubbles: false,
1418 deleteExpando: true,
1419 noCloneEvent: true,
1420 inlineBlockNeedsLayout: false,
1421 shrinkWrapBlocks: false,
1422 reliableMarginRight: true
1423 };
1424
1425 // Make sure checked status is properly cloned
1426 input.checked = true;
1427 support.noCloneChecked = input.cloneNode( true ).checked;
1428
1429 // Make sure that the options inside disabled selects aren't marked as disabled
1430 // (WebKit marks them as disabled)
1431 select.disabled = true;
1432 support.optDisabled = !opt.disabled;
1433
1434 // Test to see if it's possible to delete an expando from an element
1435 // Fails in Internet Explorer
1436 try {
1437 delete div.test;
1438 } catch( e ) {
1439 support.deleteExpando = false;
1440 }
1441
1442 if ( !div.addEventListener && div.attachEvent && div.fireEvent ) {
1443 div.attachEvent( "onclick", function() {
1444 // Cloning a node shouldn't copy over any
1445 // bound event handlers (IE does this)
1446 support.noCloneEvent = false;
1447 });
1448 div.cloneNode( true ).fireEvent( "onclick" );
1449 }
1450
1451 // Check if a radio maintains its value
1452 // after being appended to the DOM
1453 input = document.createElement("input");
1454 input.value = "t";
1455 input.setAttribute("type", "radio");
1456 support.radioValue = input.value === "t";
1457
1458 input.setAttribute("checked", "checked");
1459 div.appendChild( input );
1460 fragment = document.createDocumentFragment();
1461 fragment.appendChild( div.lastChild );
1462
1463 // WebKit doesn't clone checked state correctly in fragments
1464 support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;
1465
1466 // Check if a disconnected checkbox will retain its checked
1467 // value of true after appended to the DOM (IE6/7)
1468 support.appendChecked = input.checked;
1469
1470 fragment.removeChild( input );
1471 fragment.appendChild( div );
1472
1473 div.innerHTML = "";
1474
1475 // Check if div with explicit width and no margin-right incorrectly
1476 // gets computed margin-right based on width of container. For more
1477 // info see bug #3333
1478 // Fails in WebKit before Feb 2011 nightlies
1479 // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
1480 if ( window.getComputedStyle ) {
1481 marginDiv = document.createElement( "div" );
1482 marginDiv.style.width = "0";
1483 marginDiv.style.marginRight = "0";
1484 div.style.width = "2px";
1485 div.appendChild( marginDiv );
1486 support.reliableMarginRight =
1487 ( parseInt( ( window.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0;
1488 }
1489
1490 // Technique from Juriy Zaytsev
1491 // http://perfectionkills.com/detecting-event-support-without-browser-sniffing/
1492 // We only care about the case where non-standard event systems
1493 // are used, namely in IE. Short-circuiting here helps us to
1494 // avoid an eval call (in setAttribute) which can cause CSP
1495 // to go haywire. See: https://developer.mozilla.org/en/Security/CSP
1496 if ( div.attachEvent ) {
1497 for( i in {
1498 submit: 1,
1499 change: 1,
1500 focusin: 1
1501 }) {
1502 eventName = "on" + i;
1503 isSupported = ( eventName in div );
1504 if ( !isSupported ) {
1505 div.setAttribute( eventName, "return;" );
1506 isSupported = ( typeof div[ eventName ] === "function" );
1507 }
1508 support[ i + "Bubbles" ] = isSupported;
1509 }
1510 }
1511
1512 fragment.removeChild( div );
1513
1514 // Null elements to avoid leaks in IE
1515 fragment = select = opt = marginDiv = div = input = null;
1516
1517 // Run tests that need a body at doc ready
1518 jQuery(function() {
1519 var container, outer, inner, table, td, offsetSupport,
1520 conMarginTop, ptlm, vb, style, html,
1521 body = document.getElementsByTagName("body")[0];
1522
1523 if ( !body ) {
1524 // Return for frameset docs that don't have a body
1525 return;
1526 }
1527
1528 conMarginTop = 1;
1529 ptlm = "position:absolute;top:0;left:0;width:1px;height:1px;margin:0;";
1530 vb = "visibility:hidden;border:0;";
1531 style = "style='" + ptlm + "border:5px solid #000;padding:0;'";
1532 html = "<div " + style + "><div></div></div>" +
1533 "<table " + style + " cellpadding='0' cellspacing='0'>" +
1534 "<tr><td></td></tr></table>";
1535
1536 container = document.createElement("div");
1537 container.style.cssText = vb + "width:0;height:0;position:static;top:0;margin-top:" + conMarginTop + "px";
1538 body.insertBefore( container, body.firstChild );
1539
1540 // Construct the test element
1541 div = document.createElement("div");
1542 container.appendChild( div );
1543
1544 // Check if table cells still have offsetWidth/Height when they are set
1545 // to display:none and there are still other visible table cells in a
1546 // table row; if so, offsetWidth/Height are not reliable for use when
1547 // determining if an element has been hidden directly using
1548 // display:none (it is still safe to use offsets if a parent element is
1549 // hidden; don safety goggles and see bug #4512 for more information).
1550 // (only IE 8 fails this test)
1551 div.innerHTML = "<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>";
1552 tds = div.getElementsByTagName( "td" );
1553 isSupported = ( tds[ 0 ].offsetHeight === 0 );
1554
1555 tds[ 0 ].style.display = "";
1556 tds[ 1 ].style.display = "none";
1557
1558 // Check if empty table cells still have offsetWidth/Height
1559 // (IE <= 8 fail this test)
1560 support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );
1561
1562 // Figure out if the W3C box model works as expected
1563 div.innerHTML = "";
1564 div.style.width = div.style.paddingLeft = "1px";
1565 jQuery.boxModel = support.boxModel = div.offsetWidth === 2;
1566
1567 if ( typeof div.style.zoom !== "undefined" ) {
1568 // Check if natively block-level elements act like inline-block
1569 // elements when setting their display to 'inline' and giving
1570 // them layout
1571 // (IE < 8 does this)
1572 div.style.display = "inline";
1573 div.style.zoom = 1;
1574 support.inlineBlockNeedsLayout = ( div.offsetWidth === 2 );
1575
1576 // Check if elements with layout shrink-wrap their children
1577 // (IE 6 does this)
1578 div.style.display = "";
1579 div.innerHTML = "<div style='width:4px;'></div>";
1580 support.shrinkWrapBlocks = ( div.offsetWidth !== 2 );
1581 }
1582
1583 div.style.cssText = ptlm + vb;
1584 div.innerHTML = html;
1585
1586 outer = div.firstChild;
1587 inner = outer.firstChild;
1588 td = outer.nextSibling.firstChild.firstChild;
1589
1590 offsetSupport = {
1591 doesNotAddBorder: ( inner.offsetTop !== 5 ),
1592 doesAddBorderForTableAndCells: ( td.offsetTop === 5 )
1593 };
1594
1595 inner.style.position = "fixed";
1596 inner.style.top = "20px";
1597
1598 // safari subtracts parent border width here which is 5px
1599 offsetSupport.fixedPosition = ( inner.offsetTop === 20 || inner.offsetTop === 15 );
1600 inner.style.position = inner.style.top = "";
1601
1602 outer.style.overflow = "hidden";
1603 outer.style.position = "relative";
1604
1605 offsetSupport.subtractsBorderForOverflowNotVisible = ( inner.offsetTop === -5 );
1606 offsetSupport.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== conMarginTop );
1607
1608 body.removeChild( container );
1609 div = container = null;
1610
1611 jQuery.extend( support, offsetSupport );
1612 });
1613
1614 return support;
1615 })();
1616
1617
1618
1619
1620 var rbrace = /^(?:\{.*\}|\[.*\])$/,
1621 rmultiDash = /([A-Z])/g;
1622
1623 jQuery.extend({
1624 cache: {},
1625
1626 // Please use with caution
1627 uuid: 0,
1628
1629 // Unique for each copy of jQuery on the page
1630 // Non-digits removed to match rinlinejQuery
1631 expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ),
1632
1633 // The following elements throw uncatchable exceptions if you
1634 // attempt to add expando properties to them.
1635 noData: {
1636 "embed": true,
1637 // Ban all objects except for Flash (which handle expandos)
1638 "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",
1639 "applet": true
1640 },
1641
1642 hasData: function( elem ) {
1643 elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
1644 return !!elem && !isEmptyDataObject( elem );
1645 },
1646
1647 data: function( elem, name, data, pvt /* Internal Use Only */ ) {
1648 if ( !jQuery.acceptData( elem ) ) {
1649 return;
1650 }
1651
1652 var privateCache, thisCache, ret,
1653 internalKey = jQuery.expando,
1654 getByName = typeof name === "string",
1655
1656 // We have to handle DOM nodes and JS objects differently because IE6-7
1657 // can't GC object references properly across the DOM-JS boundary
1658 isNode = elem.nodeType,
1659
1660 // Only DOM nodes need the global jQuery cache; JS object data is
1661 // attached directly to the object so GC can occur automatically
1662 cache = isNode ? jQuery.cache : elem,
1663
1664 // Only defining an ID for JS objects if its cache already exists allows
1665 // the code to shortcut on the same path as a DOM node with no cache
1666 id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey,
1667 isEvents = name === "events";
1668
1669 // Avoid doing any more work than we need to when trying to get data on an
1670 // object that has no data at all
1671 if ( (!id || !cache[id] || (!isEvents && !pvt && !cache[id].data)) && getByName && data === undefined ) {
1672 return;
1673 }
1674
1675 if ( !id ) {
1676 // Only DOM nodes need a new unique ID for each element since their data
1677 // ends up in the global cache
1678 if ( isNode ) {
1679 elem[ internalKey ] = id = ++jQuery.uuid;
1680 } else {
1681 id = internalKey;
1682 }
1683 }
1684
1685 if ( !cache[ id ] ) {
1686 cache[ id ] = {};
1687
1688 // Avoids exposing jQuery metadata on plain JS objects when the object
1689 // is serialized using JSON.stringify
1690 if ( !isNode ) {
1691 cache[ id ].toJSON = jQuery.noop;
1692 }
1693 }
1694
1695 // An object can be passed to jQuery.data instead of a key/value pair; this gets
1696 // shallow copied over onto the existing cache
1697 if ( typeof name === "object" || typeof name === "function" ) {
1698 if ( pvt ) {
1699 cache[ id ] = jQuery.extend( cache[ id ], name );
1700 } else {
1701 cache[ id ].data = jQuery.extend( cache[ id ].data, name );
1702 }
1703 }
1704
1705 privateCache = thisCache = cache[ id ];
1706
1707 // jQuery data() is stored in a separate object inside the object's internal data
1708 // cache in order to avoid key collisions between internal data and user-defined
1709 // data.
1710 if ( !pvt ) {
1711 if ( !thisCache.data ) {
1712 thisCache.data = {};
1713 }
1714
1715 thisCache = thisCache.data;
1716 }
1717
1718 if ( data !== undefined ) {
1719 thisCache[ jQuery.camelCase( name ) ] = data;
1720 }
1721
1722 // Users should not attempt to inspect the internal events object using jQuery.data,
1723 // it is undocumented and subject to change. But does anyone listen? No.
1724 if ( isEvents && !thisCache[ name ] ) {
1725 return privateCache.events;
1726 }
1727
1728 // Check for both converted-to-camel and non-converted data property names
1729 // If a data property was specified
1730 if ( getByName ) {
1731
1732 // First Try to find as-is property data
1733 ret = thisCache[ name ];
1734
1735 // Test for null|undefined property data
1736 if ( ret == null ) {
1737
1738 // Try to find the camelCased property
1739 ret = thisCache[ jQuery.camelCase( name ) ];
1740 }
1741 } else {
1742 ret = thisCache;
1743 }
1744
1745 return ret;
1746 },
1747
1748 removeData: function( elem, name, pvt /* Internal Use Only */ ) {
1749 if ( !jQuery.acceptData( elem ) ) {
1750 return;
1751 }
1752
1753 var thisCache, i, l,
1754
1755 // Reference to internal data cache key
1756 internalKey = jQuery.expando,
1757
1758 isNode = elem.nodeType,
1759
1760 // See jQuery.data for more information
1761 cache = isNode ? jQuery.cache : elem,
1762
1763 // See jQuery.data for more information
1764 id = isNode ? elem[ internalKey ] : internalKey;
1765
1766 // If there is already no cache entry for this object, there is no
1767 // purpose in continuing
1768 if ( !cache[ id ] ) {
1769 return;
1770 }
1771
1772 if ( name ) {
1773
1774 thisCache = pvt ? cache[ id ] : cache[ id ].data;
1775
1776 if ( thisCache ) {
1777
1778 // Support array or space separated string names for data keys
1779 if ( !jQuery.isArray( name ) ) {
1780
1781 // try the string as a key before any manipulation
1782 if ( name in thisCache ) {
1783 name = [ name ];
1784 } else {
1785
1786 // split the camel cased version by spaces unless a key with the spaces exists
1787 name = jQuery.camelCase( name );
1788 if ( name in thisCache ) {
1789 name = [ name ];
1790 } else {
1791 name = name.split( " " );
1792 }
1793 }
1794 }
1795
1796 for ( i = 0, l = name.length; i < l; i++ ) {
1797 delete thisCache[ name[i] ];
1798 }
1799
1800 // If there is no data left in the cache, we want to continue
1801 // and let the cache object itself get destroyed
1802 if ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) {
1803 return;
1804 }
1805 }
1806 }
1807
1808 // See jQuery.data for more information
1809 if ( !pvt ) {
1810 delete cache[ id ].data;
1811
1812 // Don't destroy the parent cache unless the internal data object
1813 // had been the only thing left in it
1814 if ( !isEmptyDataObject(cache[ id ]) ) {
1815 return;
1816 }
1817 }
1818
1819 // Browsers that fail expando deletion also refuse to delete expandos on
1820 // the window, but it will allow it on all other JS objects; other browsers
1821 // don't care
1822 // Ensure that `cache` is not a window object #10080
1823 if ( jQuery.support.deleteExpando || !cache.setInterval ) {
1824 delete cache[ id ];
1825 } else {
1826 cache[ id ] = null;
1827 }
1828
1829 // We destroyed the cache and need to eliminate the expando on the node to avoid
1830 // false lookups in the cache for entries that no longer exist
1831 if ( isNode ) {
1832 // IE does not allow us to delete expando properties from nodes,
1833 // nor does it have a removeAttribute function on Document nodes;
1834 // we must handle all of these cases
1835 if ( jQuery.support.deleteExpando ) {
1836 delete elem[ internalKey ];
1837 } else if ( elem.removeAttribute ) {
1838 elem.removeAttribute( internalKey );
1839 } else {
1840 elem[ internalKey ] = null;
1841 }
1842 }
1843 },
1844
1845 // For internal use only.
1846 _data: function( elem, name, data ) {
1847 return jQuery.data( elem, name, data, true );
1848 },
1849
1850 // A method for determining if a DOM node can handle the data expando
1851 acceptData: function( elem ) {
1852 if ( elem.nodeName ) {
1853 var match = jQuery.noData[ elem.nodeName.toLowerCase() ];
1854
1855 if ( match ) {
1856 return !(match === true || elem.getAttribute("classid") !== match);
1857 }
1858 }
1859
1860 return true;
1861 }
1862 });
1863
1864 jQuery.fn.extend({
1865 data: function( key, value ) {
1866 var parts, attr, name,
1867 data = null;
1868
1869 if ( typeof key === "undefined" ) {
1870 if ( this.length ) {
1871 data = jQuery.data( this[0] );
1872
1873 if ( this[0].nodeType === 1 && !jQuery._data( this[0], "parsedAttrs" ) ) {
1874 attr = this[0].attributes;
1875 for ( var i = 0, l = attr.length; i < l; i++ ) {
1876 name = attr[i].name;
1877
1878 if ( name.indexOf( "data-" ) === 0 ) {
1879 name = jQuery.camelCase( name.substring(5) );
1880
1881 dataAttr( this[0], name, data[ name ] );
1882 }
1883 }
1884 jQuery._data( this[0], "parsedAttrs", true );
1885 }
1886 }
1887
1888 return data;
1889
1890 } else if ( typeof key === "object" ) {
1891 return this.each(function() {
1892 jQuery.data( this, key );
1893 });
1894 }
1895
1896 parts = key.split(".");
1897 parts[1] = parts[1] ? "." + parts[1] : "";
1898
1899 if ( value === undefined ) {
1900 data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);
1901
1902 // Try to fetch any internally stored data first
1903 if ( data === undefined && this.length ) {
1904 data = jQuery.data( this[0], key );
1905 data = dataAttr( this[0], key, data );
1906 }
1907
1908 return data === undefined && parts[1] ?
1909 this.data( parts[0] ) :
1910 data;
1911
1912 } else {
1913 return this.each(function() {
1914 var self = jQuery( this ),
1915 args = [ parts[0], value ];
1916
1917 self.triggerHandler( "setData" + parts[1] + "!", args );
1918 jQuery.data( this, key, value );
1919 self.triggerHandler( "changeData" + parts[1] + "!", args );
1920 });
1921 }
1922 },
1923
1924 removeData: function( key ) {
1925 return this.each(function() {
1926 jQuery.removeData( this, key );
1927 });
1928 }
1929 });
1930
1931 function dataAttr( elem, key, data ) {
1932 // If nothing was found internally, try to fetch any
1933 // data from the HTML5 data-* attribute
1934 if ( data === undefined && elem.nodeType === 1 ) {
1935
1936 var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();
1937
1938 data = elem.getAttribute( name );
1939
1940 if ( typeof data === "string" ) {
1941 try {
1942 data = data === "true" ? true :
1943 data === "false" ? false :
1944 data === "null" ? null :
1945 jQuery.isNumeric( data ) ? parseFloat( data ) :
1946 rbrace.test( data ) ? jQuery.parseJSON( data ) :
1947 data;
1948 } catch( e ) {}
1949
1950 // Make sure we set the data so it isn't changed later
1951 jQuery.data( elem, key, data );
1952
1953 } else {
1954 data = undefined;
1955 }
1956 }
1957
1958 return data;
1959 }
1960
1961 // checks a cache object for emptiness
1962 function isEmptyDataObject( obj ) {
1963 for ( var name in obj ) {
1964
1965 // if the public data object is empty, the private is still empty
1966 if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) {
1967 continue;
1968 }
1969 if ( name !== "toJSON" ) {
1970 return false;
1971 }
1972 }
1973
1974 return true;
1975 }
1976
1977
1978
1979
1980 function handleQueueMarkDefer( elem, type, src ) {
1981 var deferDataKey = type + "defer",
1982 queueDataKey = type + "queue",
1983 markDataKey = type + "mark",
1984 defer = jQuery._data( elem, deferDataKey );
1985 if ( defer &&
1986 ( src === "queue" || !jQuery._data(elem, queueDataKey) ) &&
1987 ( src === "mark" || !jQuery._data(elem, markDataKey) ) ) {
1988 // Give room for hard-coded callbacks to fire first
1989 // and eventually mark/queue something else on the element
1990 setTimeout( function() {
1991 if ( !jQuery._data( elem, queueDataKey ) &&
1992 !jQuery._data( elem, markDataKey ) ) {
1993 jQuery.removeData( elem, deferDataKey, true );
1994 defer.fire();
1995 }
1996 }, 0 );
1997 }
1998 }
1999
2000 jQuery.extend({
2001
2002 _mark: function( elem, type ) {
2003 if ( elem ) {
2004 type = ( type || "fx" ) + "mark";
2005 jQuery._data( elem, type, (jQuery._data( elem, type ) || 0) + 1 );
2006 }
2007 },
2008
2009 _unmark: function( force, elem, type ) {
2010 if ( force !== true ) {
2011 type = elem;
2012 elem = force;
2013 force = false;
2014 }
2015 if ( elem ) {
2016 type = type || "fx";
2017 var key = type + "mark",
2018 count = force ? 0 : ( (jQuery._data( elem, key ) || 1) - 1 );
2019 if ( count ) {
2020 jQuery._data( elem, key, count );
2021 } else {
2022 jQuery.removeData( elem, key, true );
2023 handleQueueMarkDefer( elem, type, "mark" );
2024 }
2025 }
2026 },
2027
2028 queue: function( elem, type, data ) {
2029 var q;
2030 if ( elem ) {
2031 type = ( type || "fx" ) + "queue";
2032 q = jQuery._data( elem, type );
2033
2034 // Speed up dequeue by getting out quickly if this is just a lookup
2035 if ( data ) {
2036 if ( !q || jQuery.isArray(data) ) {
2037 q = jQuery._data( elem, type, jQuery.makeArray(data) );
2038 } else {
2039 q.push( data );
2040 }
2041 }
2042 return q || [];
2043 }
2044 },
2045
2046 dequeue: function( elem, type ) {
2047 type = type || "fx";
2048
2049 var queue = jQuery.queue( elem, type ),
2050 fn = queue.shift(),
2051 hooks = {};
2052
2053 // If the fx queue is dequeued, always remove the progress sentinel
2054 if ( fn === "inprogress" ) {
2055 fn = queue.shift();
2056 }
2057
2058 if ( fn ) {
2059 // Add a progress sentinel to prevent the fx queue from being
2060 // automatically dequeued
2061 if ( type === "fx" ) {
2062 queue.unshift( "inprogress" );
2063 }
2064
2065 jQuery._data( elem, type + ".run", hooks );
2066 fn.call( elem, function() {
2067 jQuery.dequeue( elem, type );
2068 }, hooks );
2069 }
2070
2071 if ( !queue.length ) {
2072 jQuery.removeData( elem, type + "queue " + type + ".run", true );
2073 handleQueueMarkDefer( elem, type, "queue" );
2074 }
2075 }
2076 });
2077
2078 jQuery.fn.extend({
2079 queue: function( type, data ) {
2080 if ( typeof type !== "string" ) {
2081 data = type;
2082 type = "fx";
2083 }
2084
2085 if ( data === undefined ) {
2086 return jQuery.queue( this[0], type );
2087 }
2088 return this.each(function() {
2089 var queue = jQuery.queue( this, type, data );
2090
2091 if ( type === "fx" && queue[0] !== "inprogress" ) {
2092 jQuery.dequeue( this, type );
2093 }
2094 });
2095 },
2096 dequeue: function( type ) {
2097 return this.each(function() {
2098 jQuery.dequeue( this, type );
2099 });
2100 },
2101 // Based off of the plugin by Clint Helfers, with permission.
2102 // http://blindsignals.com/index.php/2009/07/jquery-delay/
2103 delay: function( time, type ) {
2104 time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
2105 type = type || "fx";
2106
2107 return this.queue( type, function( next, hooks ) {
2108 var timeout = setTimeout( next, time );
2109 hooks.stop = function() {
2110 clearTimeout( timeout );
2111 };
2112 });
2113 },
2114 clearQueue: function( type ) {
2115 return this.queue( type || "fx", [] );
2116 },
2117 // Get a promise resolved when queues of a certain type
2118 // are emptied (fx is the type by default)
2119 promise: function( type, object ) {
2120 if ( typeof type !== "string" ) {
2121 object = type;
2122 type = undefined;
2123 }
2124 type = type || "fx";
2125 var defer = jQuery.Deferred(),
2126 elements = this,
2127 i = elements.length,
2128 count = 1,
2129 deferDataKey = type + "defer",
2130 queueDataKey = type + "queue",
2131 markDataKey = type + "mark",
2132 tmp;
2133 function resolve() {
2134 if ( !( --count ) ) {
2135 defer.resolveWith( elements, [ elements ] );
2136 }
2137 }
2138 while( i-- ) {
2139 if (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) ||
2140 ( jQuery.data( elements[ i ], queueDataKey, undefined, true ) ||
2141 jQuery.data( elements[ i ], markDataKey, undefined, true ) ) &&
2142 jQuery.data( elements[ i ], deferDataKey, jQuery.Callbacks( "once memory" ), true ) )) {
2143 count++;
2144 tmp.add( resolve );
2145 }
2146 }
2147 resolve();
2148 return defer.promise();
2149 }
2150 });
2151
2152
2153
2154
2155 var rclass = /[\n\t\r]/g,
2156 rspace = /\s+/,
2157 rreturn = /\r/g,
2158 rtype = /^(?:button|input)$/i,
2159 rfocusable = /^(?:button|input|object|select|textarea)$/i,
2160 rclickable = /^a(?:rea)?$/i,
2161 rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,
2162 getSetAttribute = jQuery.support.getSetAttribute,
2163 nodeHook, boolHook, fixSpecified;
2164
2165 jQuery.fn.extend({
2166 attr: function( name, value ) {
2167 return jQuery.access( this, name, value, true, jQuery.attr );
2168 },
2169
2170 removeAttr: function( name ) {
2171 return this.each(function() {
2172 jQuery.removeAttr( this, name );
2173 });
2174 },
2175
2176 prop: function( name, value ) {
2177 return jQuery.access( this, name, value, true, jQuery.prop );
2178 },
2179
2180 removeProp: function( name ) {
2181 name = jQuery.propFix[ name ] || name;
2182 return this.each(function() {
2183 // try/catch handles cases where IE balks (such as removing a property on window)
2184 try {
2185 this[ name ] = undefined;
2186 delete this[ name ];
2187 } catch( e ) {}
2188 });
2189 },
2190
2191 addClass: function( value ) {
2192 var classNames, i, l, elem,
2193 setClass, c, cl;
2194
2195 if ( jQuery.isFunction( value ) ) {
2196 return this.each(function( j ) {
2197 jQuery( this ).addClass( value.call(this, j, this.className) );
2198 });
2199 }
2200
2201 if ( value && typeof value === "string" ) {
2202 classNames = value.split( rspace );
2203
2204 for ( i = 0, l = this.length; i < l; i++ ) {
2205 elem = this[ i ];
2206
2207 if ( elem.nodeType === 1 ) {
2208 if ( !elem.className && classNames.length === 1 ) {
2209 elem.className = value;
2210
2211 } else {
2212 setClass = " " + elem.className + " ";
2213
2214 for ( c = 0, cl = classNames.length; c < cl; c++ ) {
2215 if ( !~setClass.indexOf( " " + classNames[ c ] + " " ) ) {
2216 setClass += classNames[ c ] + " ";
2217 }
2218 }
2219 elem.className = jQuery.trim( setClass );
2220 }
2221 }
2222 }
2223 }
2224
2225 return this;
2226 },
2227
2228 removeClass: function( value ) {
2229 var classNames, i, l, elem, className, c, cl;
2230
2231 if ( jQuery.isFunction( value ) ) {
2232 return this.each(function( j ) {
2233 jQuery( this ).removeClass( value.call(this, j, this.className) );
2234 });
2235 }
2236
2237 if ( (value && typeof value === "string") || value === undefined ) {
2238 classNames = ( value || "" ).split( rspace );
2239
2240 for ( i = 0, l = this.length; i < l; i++ ) {
2241 elem = this[ i ];
2242
2243 if ( elem.nodeType === 1 && elem.className ) {
2244 if ( value ) {
2245 className = (" " + elem.className + " ").replace( rclass, " " );
2246 for ( c = 0, cl = classNames.length; c < cl; c++ ) {
2247 className = className.replace(" " + classNames[ c ] + " ", " ");
2248 }
2249 elem.className = jQuery.trim( className );
2250
2251 } else {
2252 elem.className = "";
2253 }
2254 }
2255 }
2256 }
2257
2258 return this;
2259 },
2260
2261 toggleClass: function( value, stateVal ) {
2262 var type = typeof value,
2263 isBool = typeof stateVal === "boolean";
2264
2265 if ( jQuery.isFunction( value ) ) {
2266 return this.each(function( i ) {
2267 jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );
2268 });
2269 }
2270
2271 return this.each(function() {
2272 if ( type === "string" ) {
2273 // toggle individual class names
2274 var className,
2275 i = 0,
2276 self = jQuery( this ),
2277 state = stateVal,
2278 classNames = value.split( rspace );
2279
2280 while ( (className = classNames[ i++ ]) ) {
2281 // check each className given, space seperated list
2282 state = isBool ? state : !self.hasClass( className );
2283 self[ state ? "addClass" : "removeClass" ]( className );
2284 }
2285
2286 } else if ( type === "undefined" || type === "boolean" ) {
2287 if ( this.className ) {
2288 // store className if set
2289 jQuery._data( this, "__className__", this.className );
2290 }
2291
2292 // toggle whole className
2293 this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || "";
2294 }
2295 });
2296 },
2297
2298 hasClass: function( selector ) {
2299 var className = " " + selector + " ",
2300 i = 0,
2301 l = this.length;
2302 for ( ; i < l; i++ ) {
2303 if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) {
2304 return true;
2305 }
2306 }
2307
2308 return false;
2309 },
2310
2311 val: function( value ) {
2312 var hooks, ret, isFunction,
2313 elem = this[0];
2314
2315 if ( !arguments.length ) {
2316 if ( elem ) {
2317 hooks = jQuery.valHooks[ elem.nodeName.toLowerCase() ] || jQuery.valHooks[ elem.type ];
2318
2319 if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
2320 return ret;
2321 }
2322
2323 ret = elem.value;
2324
2325 return typeof ret === "string" ?
2326 // handle most common string cases
2327 ret.replace(rreturn, "") :
2328 // handle cases where value is null/undef or number
2329 ret == null ? "" : ret;
2330 }
2331
2332 return;
2333 }
2334
2335 isFunction = jQuery.isFunction( value );
2336
2337 return this.each(function( i ) {
2338 var self = jQuery(this), val;
2339
2340 if ( this.nodeType !== 1 ) {
2341 return;
2342 }
2343
2344 if ( isFunction ) {
2345 val = value.call( this, i, self.val() );
2346 } else {
2347 val = value;
2348 }
2349
2350 // Treat null/undefined as ""; convert numbers to string
2351 if ( val == null ) {
2352 val = "";
2353 } else if ( typeof val === "number" ) {
2354 val += "";
2355 } else if ( jQuery.isArray( val ) ) {
2356 val = jQuery.map(val, function ( value ) {
2357 return value == null ? "" : value + "";
2358 });
2359 }
2360
2361 hooks = jQuery.valHooks[ this.nodeName.toLowerCase() ] || jQuery.valHooks[ this.type ];
2362
2363 // If set returns undefined, fall back to normal setting
2364 if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
2365 this.value = val;
2366 }
2367 });
2368 }
2369 });
2370
2371 jQuery.extend({
2372 valHooks: {
2373 option: {
2374 get: function( elem ) {
2375 // attributes.value is undefined in Blackberry 4.7 but
2376 // uses .value. See #6932
2377 var val = elem.attributes.value;
2378 return !val || val.specified ? elem.value : elem.text;
2379 }
2380 },
2381 select: {
2382 get: function( elem ) {
2383 var value, i, max, option,
2384 index = elem.selectedIndex,
2385 values = [],
2386 options = elem.options,
2387 one = elem.type === "select-one";
2388
2389 // Nothing was selected
2390 if ( index < 0 ) {
2391 return null;
2392 }
2393
2394 // Loop through all the selected options
2395 i = one ? index : 0;
2396 max = one ? index + 1 : options.length;
2397 for ( ; i < max; i++ ) {
2398 option = options[ i ];
2399
2400 // Don't return options that are disabled or in a disabled optgroup
2401 if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) &&
2402 (!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) {
2403
2404 // Get the specific value for the option
2405 value = jQuery( option ).val();
2406
2407 // We don't need an array for one selects
2408 if ( one ) {
2409 return value;
2410 }
2411
2412 // Multi-Selects return an array
2413 values.push( value );
2414 }
2415 }
2416
2417 // Fixes Bug #2551 -- select.val() broken in IE after form.reset()
2418 if ( one && !values.length && options.length ) {
2419 return jQuery( options[ index ] ).val();
2420 }
2421
2422 return values;
2423 },
2424
2425 set: function( elem, value ) {
2426 var values = jQuery.makeArray( value );
2427
2428 jQuery(elem).find("option").each(function() {
2429 this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;
2430 });
2431
2432 if ( !values.length ) {
2433 elem.selectedIndex = -1;
2434 }
2435 return values;
2436 }
2437 }
2438 },
2439
2440 attrFn: {
2441 val: true,
2442 css: true,
2443 html: true,
2444 text: true,
2445 data: true,
2446 width: true,
2447 height: true,
2448 offset: true
2449 },
2450
2451 attr: function( elem, name, value, pass ) {
2452 var ret, hooks, notxml,
2453 nType = elem.nodeType;
2454
2455 // don't get/set attributes on text, comment and attribute nodes
2456 if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
2457 return;
2458 }
2459
2460 if ( pass && name in jQuery.attrFn ) {
2461 return jQuery( elem )[ name ]( value );
2462 }
2463
2464 // Fallback to prop when attributes are not supported
2465 if ( typeof elem.getAttribute === "undefined" ) {
2466 return jQuery.prop( elem, name, value );
2467 }
2468
2469 notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
2470
2471 // All attributes are lowercase
2472 // Grab necessary hook if one is defined
2473 if ( notxml ) {
2474 name = name.toLowerCase();
2475 hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook );
2476 }
2477
2478 if ( value !== undefined ) {
2479
2480 if ( value === null ) {
2481 jQuery.removeAttr( elem, name );
2482 return;
2483
2484 } else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) {
2485 return ret;
2486
2487 } else {
2488 elem.setAttribute( name, "" + value );
2489 return value;
2490 }
2491
2492 } else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) {
2493 return ret;
2494
2495 } else {
2496
2497 ret = elem.getAttribute( name );
2498
2499 // Non-existent attributes return null, we normalize to undefined
2500 return ret === null ?
2501 undefined :
2502 ret;
2503 }
2504 },
2505
2506 removeAttr: function( elem, value ) {
2507 var propName, attrNames, name, l,
2508 i = 0;
2509
2510 if ( value && elem.nodeType === 1 ) {
2511 attrNames = value.toLowerCase().split( rspace );
2512 l = attrNames.length;
2513
2514 for ( ; i < l; i++ ) {
2515 name = attrNames[ i ];
2516
2517 if ( name ) {
2518 propName = jQuery.propFix[ name ] || name;
2519
2520 // See #9699 for explanation of this approach (setting first, then removal)
2521 jQuery.attr( elem, name, "" );
2522 elem.removeAttribute( getSetAttribute ? name : propName );
2523
2524 // Set corresponding property to false for boolean attributes
2525 if ( rboolean.test( name ) && propName in elem ) {
2526 elem[ propName ] = false;
2527 }
2528 }
2529 }
2530 }
2531 },
2532
2533 attrHooks: {
2534 type: {
2535 set: function( elem, value ) {
2536 // We can't allow the type property to be changed (since it causes problems in IE)
2537 if ( rtype.test( elem.nodeName ) && elem.parentNode ) {
2538 jQuery.error( "type property can't be changed" );
2539 } else if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) {
2540 // Setting the type on a radio button after the value resets the value in IE6-9
2541 // Reset value to it's default in case type is set after value
2542 // This is for element creation
2543 var val = elem.value;
2544 elem.setAttribute( "type", value );
2545 if ( val ) {
2546 elem.value = val;
2547 }
2548 return value;
2549 }
2550 }
2551 },
2552 // Use the value property for back compat
2553 // Use the nodeHook for button elements in IE6/7 (#1954)
2554 value: {
2555 get: function( elem, name ) {
2556 if ( nodeHook && jQuery.nodeName( elem, "button" ) ) {
2557 return nodeHook.get( elem, name );
2558 }
2559 return name in elem ?
2560 elem.value :
2561 null;
2562 },
2563 set: function( elem, value, name ) {
2564 if ( nodeHook && jQuery.nodeName( elem, "button" ) ) {
2565 return nodeHook.set( elem, value, name );
2566 }
2567 // Does not return so that setAttribute is also used
2568 elem.value = value;
2569 }
2570 }
2571 },
2572
2573 propFix: {
2574 tabindex: "tabIndex",
2575 readonly: "readOnly",
2576 "for": "htmlFor",
2577 "class": "className",
2578 maxlength: "maxLength",
2579 cellspacing: "cellSpacing",
2580 cellpadding: "cellPadding",
2581 rowspan: "rowSpan",
2582 colspan: "colSpan",
2583 usemap: "useMap",
2584 frameborder: "frameBorder",
2585 contenteditable: "contentEditable"
2586 },
2587
2588 prop: function( elem, name, value ) {
2589 var ret, hooks, notxml,
2590 nType = elem.nodeType;
2591
2592 // don't get/set properties on text, comment and attribute nodes
2593 if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
2594 return;
2595 }
2596
2597 notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
2598
2599 if ( notxml ) {
2600 // Fix name and attach hooks
2601 name = jQuery.propFix[ name ] || name;
2602 hooks = jQuery.propHooks[ name ];
2603 }
2604
2605 if ( value !== undefined ) {
2606 if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
2607 return ret;
2608
2609 } else {
2610 return ( elem[ name ] = value );
2611 }
2612
2613 } else {
2614 if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
2615 return ret;
2616
2617 } else {
2618 return elem[ name ];
2619 }
2620 }
2621 },
2622
2623 propHooks: {
2624 tabIndex: {
2625 get: function( elem ) {
2626 // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
2627 // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
2628 var attributeNode = elem.getAttributeNode("tabindex");
2629
2630 return attributeNode && attributeNode.specified ?
2631 parseInt( attributeNode.value, 10 ) :
2632 rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
2633 0 :
2634 undefined;
2635 }
2636 }
2637 }
2638 });
2639
2640 // Add the tabIndex propHook to attrHooks for back-compat (different case is intentional)
2641 jQuery.attrHooks.tabindex = jQuery.propHooks.tabIndex;
2642
2643 // Hook for boolean attributes
2644 boolHook = {
2645 get: function( elem, name ) {
2646 // Align boolean attributes with corresponding properties
2647 // Fall back to attribute presence where some booleans are not supported
2648 var attrNode,
2649 property = jQuery.prop( elem, name );
2650 return property === true || typeof property !== "boolean" && ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ?
2651 name.toLowerCase() :
2652 undefined;
2653 },
2654 set: function( elem, value, name ) {
2655 var propName;
2656 if ( value === false ) {
2657 // Remove boolean attributes when set to false
2658 jQuery.removeAttr( elem, name );
2659 } else {
2660 // value is true since we know at this point it's type boolean and not false
2661 // Set boolean attributes to the same name and set the DOM property
2662 propName = jQuery.propFix[ name ] || name;
2663 if ( propName in elem ) {
2664 // Only set the IDL specifically if it already exists on the element
2665 elem[ propName ] = true;
2666 }
2667
2668 elem.setAttribute( name, name.toLowerCase() );
2669 }
2670 return name;
2671 }
2672 };
2673
2674 // IE6/7 do not support getting/setting some attributes with get/setAttribute
2675 if ( !getSetAttribute ) {
2676
2677 fixSpecified = {
2678 name: true,
2679 id: true
2680 };
2681
2682 // Use this for any attribute in IE6/7
2683 // This fixes almost every IE6/7 issue
2684 nodeHook = jQuery.valHooks.button = {
2685 get: function( elem, name ) {
2686 var ret;
2687 ret = elem.getAttributeNode( name );
2688 return ret && ( fixSpecified[ name ] ? ret.nodeValue !== "" : ret.specified ) ?
2689 ret.nodeValue :
2690 undefined;
2691 },
2692 set: function( elem, value, name ) {
2693 // Set the existing or create a new attribute node
2694 var ret = elem.getAttributeNode( name );
2695 if ( !ret ) {
2696 ret = document.createAttribute( name );
2697 elem.setAttributeNode( ret );
2698 }
2699 return ( ret.nodeValue = value + "" );
2700 }
2701 };
2702
2703 // Apply the nodeHook to tabindex
2704 jQuery.attrHooks.tabindex.set = nodeHook.set;
2705
2706 // Set width and height to auto instead of 0 on empty string( Bug #8150 )
2707 // This is for removals
2708 jQuery.each([ "width", "height" ], function( i, name ) {
2709 jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
2710 set: function( elem, value ) {
2711 if ( value === "" ) {
2712 elem.setAttribute( name, "auto" );
2713 return value;
2714 }
2715 }
2716 });
2717 });
2718
2719 // Set contenteditable to false on removals(#10429)
2720 // Setting to empty string throws an error as an invalid value
2721 jQuery.attrHooks.contenteditable = {
2722 get: nodeHook.get,
2723 set: function( elem, value, name ) {
2724 if ( value === "" ) {
2725 value = "false";
2726 }
2727 nodeHook.set( elem, value, name );
2728 }
2729 };
2730 }
2731
2732
2733 // Some attributes require a special call on IE
2734 if ( !jQuery.support.hrefNormalized ) {
2735 jQuery.each([ "href", "src", "width", "height" ], function( i, name ) {
2736 jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
2737 get: function( elem ) {
2738 var ret = elem.getAttribute( name, 2 );
2739 return ret === null ? undefined : ret;
2740 }
2741 });
2742 });
2743 }
2744
2745 if ( !jQuery.support.style ) {
2746 jQuery.attrHooks.style = {
2747 get: function( elem ) {
2748 // Return undefined in the case of empty string
2749 // Normalize to lowercase since IE uppercases css property names
2750 return elem.style.cssText.toLowerCase() || undefined;
2751 },
2752 set: function( elem, value ) {
2753 return ( elem.style.cssText = "" + value );
2754 }
2755 };
2756 }
2757
2758 // Safari mis-reports the default selected property of an option
2759 // Accessing the parent's selectedIndex property fixes it
2760 if ( !jQuery.support.optSelected ) {
2761 jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, {
2762 get: function( elem ) {
2763 var parent = elem.parentNode;
2764
2765 if ( parent ) {
2766 parent.selectedIndex;
2767
2768 // Make sure that it also works with optgroups, see #5701
2769 if ( parent.parentNode ) {
2770 parent.parentNode.selectedIndex;
2771 }
2772 }
2773 return null;
2774 }
2775 });
2776 }
2777
2778 // IE6/7 call enctype encoding
2779 if ( !jQuery.support.enctype ) {
2780 jQuery.propFix.enctype = "encoding";
2781 }
2782
2783 // Radios and checkboxes getter/setter
2784 if ( !jQuery.support.checkOn ) {
2785 jQuery.each([ "radio", "checkbox" ], function() {
2786 jQuery.valHooks[ this ] = {
2787 get: function( elem ) {
2788 // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified
2789 return elem.getAttribute("value") === null ? "on" : elem.value;
2790 }
2791 };
2792 });
2793 }
2794 jQuery.each([ "radio", "checkbox" ], function() {
2795 jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], {
2796 set: function( elem, value ) {
2797 if ( jQuery.isArray( value ) ) {
2798 return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );
2799 }
2800 }
2801 });
2802 });
2803
2804
2805
2806
2807 var rformElems = /^(?:textarea|input|select)$/i,
2808 rtypenamespace = /^([^\.]*)?(?:\.(.+))?$/,
2809 rhoverHack = /\bhover(\.\S+)?\b/,
2810 rkeyEvent = /^key/,
2811 rmouseEvent = /^(?:mouse|contextmenu)|click/,
2812 rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
2813 rquickIs = /^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,
2814 quickParse = function( selector ) {
2815 var quick = rquickIs.exec( selector );
2816 if ( quick ) {
2817 // 0 1 2 3
2818 // [ _, tag, id, class ]
2819 quick[1] = ( quick[1] || "" ).toLowerCase();
2820 quick[3] = quick[3] && new RegExp( "(?:^|\\s)" + quick[3] + "(?:\\s|$)" );
2821 }
2822 return quick;
2823 },
2824 quickIs = function( elem, m ) {
2825 var attrs = elem.attributes || {};
2826 return (
2827 (!m[1] || elem.nodeName.toLowerCase() === m[1]) &&
2828 (!m[2] || (attrs.id || {}).value === m[2]) &&
2829 (!m[3] || m[3].test( (attrs[ "class" ] || {}).value ))
2830 );
2831 },
2832 hoverHack = function( events ) {
2833 return jQuery.event.special.hover ? events : events.replace( rhoverHack, "mouseenter$1 mouseleave$1" );
2834 };
2835
2836 /*
2837 * Helper functions for managing events -- not part of the public interface.
2838 * Props to Dean Edwards' addEvent library for many of the ideas.
2839 */
2840 jQuery.event = {
2841
2842 add: function( elem, types, handler, data, selector ) {
2843
2844 var elemData, eventHandle, events,
2845 t, tns, type, namespaces, handleObj,
2846 handleObjIn, quick, handlers, special;
2847
2848 // Don't attach events to noData or text/comment nodes (allow plain objects tho)
2849 if ( elem.nodeType === 3 || elem.nodeType === 8 || !types || !handler || !(elemData = jQuery._data( elem )) ) {
2850 return;
2851 }
2852
2853 // Caller can pass in an object of custom data in lieu of the handler
2854 if ( handler.handler ) {
2855 handleObjIn = handler;
2856 handler = handleObjIn.handler;
2857 }
2858
2859 // Make sure that the handler has a unique ID, used to find/remove it later
2860 if ( !handler.guid ) {
2861 handler.guid = jQuery.guid++;
2862 }
2863
2864 // Init the element's event structure and main handler, if this is the first
2865 events = elemData.events;
2866 if ( !events ) {
2867 elemData.events = events = {};
2868 }
2869 eventHandle = elemData.handle;
2870 if ( !eventHandle ) {
2871 elemData.handle = eventHandle = function( e ) {
2872 // Discard the second event of a jQuery.event.trigger() and
2873 // when an event is called after a page has unloaded
2874 return typeof jQuery !== "undefined" && (!e || jQuery.event.triggered !== e.type) ?
2875 jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :
2876 undefined;
2877 };
2878 // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events
2879 eventHandle.elem = elem;
2880 }
2881
2882 // Handle multiple events separated by a space
2883 // jQuery(...).bind("mouseover mouseout", fn);
2884 types = jQuery.trim( hoverHack(types) ).split( " " );
2885 for ( t = 0; t < types.length; t++ ) {
2886
2887 tns = rtypenamespace.exec( types[t] ) || [];
2888 type = tns[1];
2889 namespaces = ( tns[2] || "" ).split( "." ).sort();
2890
2891 // If event changes its type, use the special event handlers for the changed type
2892 special = jQuery.event.special[ type ] || {};
2893
2894 // If selector defined, determine special event api type, otherwise given type
2895 type = ( selector ? special.delegateType : special.bindType ) || type;
2896
2897 // Update special based on newly reset type
2898 special = jQuery.event.special[ type ] || {};
2899
2900 // handleObj is passed to all event handlers
2901 handleObj = jQuery.extend({
2902 type: type,
2903 origType: tns[1],
2904 data: data,
2905 handler: handler,
2906 guid: handler.guid,
2907 selector: selector,
2908 quick: quickParse( selector ),
2909 namespace: namespaces.join(".")
2910 }, handleObjIn );
2911
2912 // Init the event handler queue if we're the first
2913 handlers = events[ type ];
2914 if ( !handlers ) {
2915 handlers = events[ type ] = [];
2916 handlers.delegateCount = 0;
2917
2918 // Only use addEventListener/attachEvent if the special events handler returns false
2919 if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
2920 // Bind the global event handler to the element
2921 if ( elem.addEventListener ) {
2922 elem.addEventListener( type, eventHandle, false );
2923
2924 } else if ( elem.attachEvent ) {
2925 elem.attachEvent( "on" + type, eventHandle );
2926 }
2927 }
2928 }
2929
2930 if ( special.add ) {
2931 special.add.call( elem, handleObj );
2932
2933 if ( !handleObj.handler.guid ) {
2934 handleObj.handler.guid = handler.guid;
2935 }
2936 }
2937
2938 // Add to the element's handler list, delegates in front
2939 if ( selector ) {
2940 handlers.splice( handlers.delegateCount++, 0, handleObj );
2941 } else {
2942 handlers.push( handleObj );
2943 }
2944
2945 // Keep track of which events have ever been used, for event optimization
2946 jQuery.event.global[ type ] = true;
2947 }
2948
2949 // Nullify elem to prevent memory leaks in IE
2950 elem = null;
2951 },
2952
2953 global: {},
2954
2955 // Detach an event or set of events from an element
2956 remove: function( elem, types, handler, selector, mappedTypes ) {
2957
2958 var elemData = jQuery.hasData( elem ) && jQuery._data( elem ),
2959 t, tns, type, origType, namespaces, origCount,
2960 j, events, special, handle, eventType, handleObj;
2961
2962 if ( !elemData || !(events = elemData.events) ) {
2963 return;
2964 }
2965
2966 // Once for each type.namespace in types; type may be omitted
2967 types = jQuery.trim( hoverHack( types || "" ) ).split(" ");
2968 for ( t = 0; t < types.length; t++ ) {
2969 tns = rtypenamespace.exec( types[t] ) || [];
2970 type = origType = tns[1];
2971 namespaces = tns[2];
2972
2973 // Unbind all events (on this namespace, if provided) for the element
2974 if ( !type ) {
2975 for ( type in events ) {
2976 jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
2977 }
2978 continue;
2979 }
2980
2981 special = jQuery.event.special[ type ] || {};
2982 type = ( selector? special.delegateType : special.bindType ) || type;
2983 eventType = events[ type ] || [];
2984 origCount = eventType.length;
2985 namespaces = namespaces ? new RegExp("(^|\\.)" + namespaces.split(".").sort().join("\\.(?:.*\\.)?") + "(\\.|$)") : null;
2986
2987 // Remove matching events
2988 for ( j = 0; j < eventType.length; j++ ) {
2989 handleObj = eventType[ j ];
2990
2991 if ( ( mappedTypes || origType === handleObj.origType ) &&
2992 ( !handler || handler.guid === handleObj.guid ) &&
2993 ( !namespaces || namespaces.test( handleObj.namespace ) ) &&
2994 ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) {
2995 eventType.splice( j--, 1 );
2996
2997 if ( handleObj.selector ) {
2998 eventType.delegateCount--;
2999 }
3000 if ( special.remove ) {
3001 special.remove.call( elem, handleObj );
3002 }
3003 }
3004 }
3005
3006 // Remove generic event handler if we removed something and no more handlers exist
3007 // (avoids potential for endless recursion during removal of special event handlers)
3008 if ( eventType.length === 0 && origCount !== eventType.length ) {
3009 if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {
3010 jQuery.removeEvent( elem, type, elemData.handle );
3011 }
3012
3013 delete events[ type ];
3014 }
3015 }
3016
3017 // Remove the expando if it's no longer used
3018 if ( jQuery.isEmptyObject( events ) ) {
3019 handle = elemData.handle;
3020 if ( handle ) {
3021 handle.elem = null;
3022 }
3023
3024 // removeData also checks for emptiness and clears the expando if empty
3025 // so use it instead of delete
3026 jQuery.removeData( elem, [ "events", "handle" ], true );
3027 }
3028 },
3029
3030 // Events that are safe to short-circuit if no handlers are attached.
3031 // Native DOM events should not be added, they may have inline handlers.
3032 customEvent: {
3033 "getData": true,
3034 "setData": true,
3035 "changeData": true
3036 },
3037
3038 trigger: function( event, data, elem, onlyHandlers ) {
3039 // Don't do events on text and comment nodes
3040 if ( elem && (elem.nodeType === 3 || elem.nodeType === 8) ) {
3041 return;
3042 }
3043
3044 // Event object or event type
3045 var type = event.type || event,
3046 namespaces = [],
3047 cache, exclusive, i, cur, old, ontype, special, handle, eventPath, bubbleType;
3048
3049 // focus/blur morphs to focusin/out; ensure we're not firing them right now
3050 if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
3051 return;
3052 }
3053
3054 if ( type.indexOf( "!" ) >= 0 ) {
3055 // Exclusive events trigger only for the exact event (no namespaces)
3056 type = type.slice(0, -1);
3057 exclusive = true;
3058 }
3059
3060 if ( type.indexOf( "." ) >= 0 ) {
3061 // Namespaced trigger; create a regexp to match event type in handle()
3062 namespaces = type.split(".");
3063 type = namespaces.shift();
3064 namespaces.sort();
3065 }
3066
3067 if ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) {
3068 // No jQuery handlers for this event type, and it can't have inline handlers
3069 return;
3070 }
3071
3072 // Caller can pass in an Event, Object, or just an event type string
3073 event = typeof event === "object" ?
3074 // jQuery.Event object
3075 event[ jQuery.expando ] ? event :
3076 // Object literal
3077 new jQuery.Event( type, event ) :
3078 // Just the event type (string)
3079 new jQuery.Event( type );
3080
3081 event.type = type;
3082 event.isTrigger = true;
3083 event.exclusive = exclusive;
3084 event.namespace = namespaces.join( "." );
3085 event.namespace_re = event.namespace? new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.)?") + "(\\.|$)") : null;
3086 ontype = type.indexOf( ":" ) < 0 ? "on" + type : "";
3087
3088 // Handle a global trigger
3089 if ( !elem ) {
3090
3091 // TODO: Stop taunting the data cache; remove global events and always attach to document
3092 cache = jQuery.cache;
3093 for ( i in cache ) {
3094 if ( cache[ i ].events && cache[ i ].events[ type ] ) {
3095 jQuery.event.trigger( event, data, cache[ i ].handle.elem, true );
3096 }
3097 }
3098 return;
3099 }
3100
3101 // Clean up the event in case it is being reused
3102 event.result = undefined;
3103 if ( !event.target ) {
3104 event.target = elem;
3105 }
3106
3107 // Clone any incoming data and prepend the event, creating the handler arg list
3108 data = data != null ? jQuery.makeArray( data ) : [];
3109 data.unshift( event );
3110
3111 // Allow special events to draw outside the lines
3112 special = jQuery.event.special[ type ] || {};
3113 if ( special.trigger && special.trigger.apply( elem, data ) === false ) {
3114 return;
3115 }
3116
3117 // Determine event propagation path in advance, per W3C events spec (#9951)
3118 // Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
3119 eventPath = [[ elem, special.bindType || type ]];
3120 if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {
3121
3122 bubbleType = special.delegateType || type;
3123 cur = rfocusMorph.test( bubbleType + type ) ? elem : elem.parentNode;
3124 old = null;
3125 for ( ; cur; cur = cur.parentNode ) {
3126 eventPath.push([ cur, bubbleType ]);
3127 old = cur;
3128 }
3129
3130 // Only add window if we got to document (e.g., not plain obj or detached DOM)
3131 if ( old && old === elem.ownerDocument ) {
3132 eventPath.push([ old.defaultView || old.parentWindow || window, bubbleType ]);
3133 }
3134 }
3135
3136 // Fire handlers on the event path
3137 for ( i = 0; i < eventPath.length && !event.isPropagationStopped(); i++ ) {
3138
3139 cur = eventPath[i][0];
3140 event.type = eventPath[i][1];
3141
3142 handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" );
3143 if ( handle ) {
3144 handle.apply( cur, data );
3145 }
3146 // Note that this is a bare JS function and not a jQuery handler
3147 handle = ontype && cur[ ontype ];
3148 if ( handle && jQuery.acceptData( cur ) && handle.apply( cur, data ) === false ) {
3149 event.preventDefault();
3150 }
3151 }
3152 event.type = type;
3153
3154 // If nobody prevented the default action, do it now
3155 if ( !onlyHandlers && !event.isDefaultPrevented() ) {
3156
3157 if ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) &&
3158 !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) {
3159
3160 // Call a native DOM method on the target with the same name name as the event.
3161 // Can't use an .isFunction() check here because IE6/7 fails that test.
3162 // Don't do default actions on window, that's where global variables be (#6170)
3163 // IE<9 dies on focus/blur to hidden element (#1486)
3164 if ( ontype && elem[ type ] && ((type !== "focus" && type !== "blur") || event.target.offsetWidth !== 0) && !jQuery.isWindow( elem ) ) {
3165
3166 // Don't re-trigger an onFOO event when we call its FOO() method
3167 old = elem[ ontype ];
3168
3169 if ( old ) {
3170 elem[ ontype ] = null;
3171 }
3172
3173 // Prevent re-triggering of the same event, since we already bubbled it above
3174 jQuery.event.triggered = type;
3175 elem[ type ]();
3176 jQuery.event.triggered = undefined;
3177
3178 if ( old ) {
3179 elem[ ontype ] = old;
3180 }
3181 }
3182 }
3183 }
3184
3185 return event.result;
3186 },
3187
3188 dispatch: function( event ) {
3189
3190 // Make a writable jQuery.Event from the native event object
3191 event = jQuery.event.fix( event || window.event );
3192
3193 var handlers = ( (jQuery._data( this, "events" ) || {} )[ event.type ] || []),
3194 delegateCount = handlers.delegateCount,
3195 args = [].slice.call( arguments, 0 ),
3196 run_all = !event.exclusive && !event.namespace,
3197 handlerQueue = [],
3198 i, j, cur, jqcur, ret, selMatch, matched, matches, handleObj, sel, related;
3199
3200 // Use the fix-ed jQuery.Event rather than the (read-only) native event
3201 args[0] = event;
3202 event.delegateTarget = this;
3203
3204 // Determine handlers that should run if there are delegated events
3205 // Avoid disabled elements in IE (#6911) and non-left-click bubbling in Firefox (#3861)
3206 if ( delegateCount && !event.target.disabled && !(event.button && event.type === "click") ) {
3207
3208 // Pregenerate a single jQuery object for reuse with .is()
3209 jqcur = jQuery(this);
3210 jqcur.context = this.ownerDocument || this;
3211
3212 for ( cur = event.target; cur != this; cur = cur.parentNode || this ) {
3213 selMatch = {};
3214 matches = [];
3215 jqcur[0] = cur;
3216 for ( i = 0; i < delegateCount; i++ ) {
3217 handleObj = handlers[ i ];
3218 sel = handleObj.selector;
3219
3220 if ( selMatch[ sel ] === undefined ) {
3221 selMatch[ sel ] = (
3222 handleObj.quick ? quickIs( cur, handleObj.quick ) : jqcur.is( sel )
3223 );
3224 }
3225 if ( selMatch[ sel ] ) {
3226 matches.push( handleObj );
3227 }
3228 }
3229 if ( matches.length ) {
3230 handlerQueue.push({ elem: cur, matches: matches });
3231 }
3232 }
3233 }
3234
3235 // Add the remaining (directly-bound) handlers
3236 if ( handlers.length > delegateCount ) {
3237 handlerQueue.push({ elem: this, matches: handlers.slice( delegateCount ) });
3238 }
3239
3240 // Run delegates first; they may want to stop propagation beneath us
3241 for ( i = 0; i < handlerQueue.length && !event.isPropagationStopped(); i++ ) {
3242 matched = handlerQueue[ i ];
3243 event.currentTarget = matched.elem;
3244
3245 for ( j = 0; j < matched.matches.length && !event.isImmediatePropagationStopped(); j++ ) {
3246 handleObj = matched.matches[ j ];
3247
3248 // Triggered event must either 1) be non-exclusive and have no namespace, or
3249 // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).
3250 if ( run_all || (!event.namespace && !handleObj.namespace) || event.namespace_re && event.namespace_re.test( handleObj.namespace ) ) {
3251
3252 event.data = handleObj.data;
3253 event.handleObj = handleObj;
3254
3255 ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )
3256 .apply( matched.elem, args );
3257
3258 if ( ret !== undefined ) {
3259 event.result = ret;
3260 if ( ret === false ) {
3261 event.preventDefault();
3262 event.stopPropagation();
3263 }
3264 }
3265 }
3266 }
3267 }
3268
3269 return event.result;
3270 },
3271
3272 // Includes some event props shared by KeyEvent and MouseEvent
3273 // *** attrChange attrName relatedNode srcElement are not normalized, non-W3C, deprecated, will be removed in 1.8 ***
3274 props: "attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),
3275
3276 fixHooks: {},
3277
3278 keyHooks: {
3279 props: "char charCode key keyCode".split(" "),
3280 filter: function( event, original ) {
3281
3282 // Add which for key events
3283 if ( event.which == null ) {
3284 event.which = original.charCode != null ? original.charCode : original.keyCode;
3285 }
3286
3287 return event;
3288 }
3289 },
3290
3291 mouseHooks: {
3292 props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),
3293 filter: function( event, original ) {
3294 var eventDoc, doc, body,
3295 button = original.button,
3296 fromElement = original.fromElement;
3297
3298 // Calculate pageX/Y if missing and clientX/Y available
3299 if ( event.pageX == null && original.clientX != null ) {
3300 eventDoc = event.target.ownerDocument || document;
3301 doc = eventDoc.documentElement;
3302 body = eventDoc.body;
3303
3304 event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );
3305 event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 );
3306 }
3307
3308 // Add relatedTarget, if necessary
3309 if ( !event.relatedTarget && fromElement ) {
3310 event.relatedTarget = fromElement === event.target ? original.toElement : fromElement;
3311 }
3312
3313 // Add which for click: 1 === left; 2 === middle; 3 === right
3314 // Note: button is not normalized, so don't use it
3315 if ( !event.which && button !== undefined ) {
3316 event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
3317 }
3318
3319 return event;
3320 }
3321 },
3322
3323 fix: function( event ) {
3324 if ( event[ jQuery.expando ] ) {
3325 return event;
3326 }
3327
3328 // Create a writable copy of the event object and normalize some properties
3329 var i, prop,
3330 originalEvent = event,
3331 fixHook = jQuery.event.fixHooks[ event.type ] || {},
3332 copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;
3333
3334 event = jQuery.Event( originalEvent );
3335
3336 for ( i = copy.length; i; ) {
3337 prop = copy[ --i ];
3338 event[ prop ] = originalEvent[ prop ];
3339 }
3340
3341 // Fix target property, if necessary (#1925, IE 6/7/8 & Safari2)
3342 if ( !event.target ) {
3343 event.target = originalEvent.srcElement || document;
3344 }
3345
3346 // Target should not be a text node (#504, Safari)
3347 if ( event.target.nodeType === 3 ) {
3348 event.target = event.target.parentNode;
3349 }
3350
3351 // For mouse/key events; add metaKey if it's not there (#3368, IE6/7/8)
3352 if ( event.metaKey === undefined ) {
3353 event.metaKey = event.ctrlKey;
3354 }
3355
3356 return fixHook.filter? fixHook.filter( event, originalEvent ) : event;
3357 },
3358
3359 special: {
3360 ready: {
3361 // Make sure the ready event is setup
3362 setup: jQuery.bindReady
3363 },
3364
3365 load: {
3366 // Prevent triggered image.load events from bubbling to window.load
3367 noBubble: true
3368 },
3369
3370 focus: {
3371 delegateType: "focusin"
3372 },
3373 blur: {
3374 delegateType: "focusout"
3375 },
3376
3377 beforeunload: {
3378 setup: function( data, namespaces, eventHandle ) {
3379 // We only want to do this special case on windows
3380 if ( jQuery.isWindow( this ) ) {
3381 this.onbeforeunload = eventHandle;
3382 }
3383 },
3384
3385 teardown: function( namespaces, eventHandle ) {
3386 if ( this.onbeforeunload === eventHandle ) {
3387 this.onbeforeunload = null;
3388 }
3389 }
3390 }
3391 },
3392
3393 simulate: function( type, elem, event, bubble ) {
3394 // Piggyback on a donor event to simulate a different one.
3395 // Fake originalEvent to avoid donor's stopPropagation, but if the
3396 // simulated event prevents default then we do the same on the donor.
3397 var e = jQuery.extend(
3398 new jQuery.Event(),
3399 event,
3400 { type: type,
3401 isSimulated: true,
3402 originalEvent: {}
3403 }
3404 );
3405 if ( bubble ) {
3406 jQuery.event.trigger( e, null, elem );
3407 } else {
3408 jQuery.event.dispatch.call( elem, e );
3409 }
3410 if ( e.isDefaultPrevented() ) {
3411 event.preventDefault();
3412 }
3413 }
3414 };
3415
3416 // Some plugins are using, but it's undocumented/deprecated and will be removed.
3417 // The 1.7 special event interface should provide all the hooks needed now.
3418 jQuery.event.handle = jQuery.event.dispatch;
3419
3420 jQuery.removeEvent = document.removeEventListener ?
3421 function( elem, type, handle ) {
3422 if ( elem.removeEventListener ) {
3423 elem.removeEventListener( type, handle, false );
3424 }
3425 } :
3426 function( elem, type, handle ) {
3427 if ( elem.detachEvent ) {
3428 elem.detachEvent( "on" + type, handle );
3429 }
3430 };
3431
3432 jQuery.Event = function( src, props ) {
3433 // Allow instantiation without the 'new' keyword
3434 if ( !(this instanceof jQuery.Event) ) {
3435 return new jQuery.Event( src, props );
3436 }
3437
3438 // Event object
3439 if ( src && src.type ) {
3440 this.originalEvent = src;
3441 this.type = src.type;
3442
3443 // Events bubbling up the document may have been marked as prevented
3444 // by a handler lower down the tree; reflect the correct value.
3445 this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false ||
3446 src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse;
3447
3448 // Event type
3449 } else {
3450 this.type = src;
3451 }
3452
3453 // Put explicitly provided properties onto the event object
3454 if ( props ) {
3455 jQuery.extend( this, props );
3456 }
3457
3458 // Create a timestamp if incoming event doesn't have one
3459 this.timeStamp = src && src.timeStamp || jQuery.now();
3460
3461 // Mark it as fixed
3462 this[ jQuery.expando ] = true;
3463 };
3464
3465 function returnFalse() {
3466 return false;
3467 }
3468 function returnTrue() {
3469 return true;
3470 }
3471
3472 // jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
3473 // http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
3474 jQuery.Event.prototype = {
3475 preventDefault: function() {
3476 this.isDefaultPrevented = returnTrue;
3477
3478 var e = this.originalEvent;
3479 if ( !e ) {
3480 return;
3481 }
3482
3483 // if preventDefault exists run it on the original event
3484 if ( e.preventDefault ) {
3485 e.preventDefault();
3486
3487 // otherwise set the returnValue property of the original event to false (IE)
3488 } else {
3489 e.returnValue = false;
3490 }
3491 },
3492 stopPropagation: function() {
3493 this.isPropagationStopped = returnTrue;
3494
3495 var e = this.originalEvent;
3496 if ( !e ) {
3497 return;
3498 }
3499 // if stopPropagation exists run it on the original event
3500 if ( e.stopPropagation ) {
3501 e.stopPropagation();
3502 }
3503 // otherwise set the cancelBubble property of the original event to true (IE)
3504 e.cancelBubble = true;
3505 },
3506 stopImmediatePropagation: function() {
3507 this.isImmediatePropagationStopped = returnTrue;
3508 this.stopPropagation();
3509 },
3510 isDefaultPrevented: returnFalse,
3511 isPropagationStopped: returnFalse,
3512 isImmediatePropagationStopped: returnFalse
3513 };
3514
3515 // Create mouseenter/leave events using mouseover/out and event-time checks
3516 jQuery.each({
3517 mouseenter: "mouseover",
3518 mouseleave: "mouseout"
3519 }, function( orig, fix ) {
3520 jQuery.event.special[ orig ] = {
3521 delegateType: fix,
3522 bindType: fix,
3523
3524 handle: function( event ) {
3525 var target = this,
3526 related = event.relatedTarget,
3527 handleObj = event.handleObj,
3528 selector = handleObj.selector,
3529 ret;
3530
3531 // For mousenter/leave call the handler if related is outside the target.
3532 // NB: No relatedTarget if the mouse left/entered the browser window
3533 if ( !related || (related !== target && !jQuery.contains( target, related )) ) {
3534 event.type = handleObj.origType;
3535 ret = handleObj.handler.apply( this, arguments );
3536 event.type = fix;
3537 }
3538 return ret;
3539 }
3540 };
3541 });
3542
3543 // IE submit delegation
3544 if ( !jQuery.support.submitBubbles ) {
3545
3546 jQuery.event.special.submit = {
3547 setup: function() {
3548 // Only need this for delegated form submit events
3549 if ( jQuery.nodeName( this, "form" ) ) {
3550 return false;
3551 }
3552
3553 // Lazy-add a submit handler when a descendant form may potentially be submitted
3554 jQuery.event.add( this, "click._submit keypress._submit", function( e ) {
3555 // Node name check avoids a VML-related crash in IE (#9807)
3556 var elem = e.target,
3557 form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined;
3558 if ( form && !form._submit_attached ) {
3559 jQuery.event.add( form, "submit._submit", function( event ) {
3560 // If form was submitted by the user, bubble the event up the tree
3561 if ( this.parentNode && !event.isTrigger ) {
3562 jQuery.event.simulate( "submit", this.parentNode, event, true );
3563 }
3564 });
3565 form._submit_attached = true;
3566 }
3567 });
3568 // return undefined since we don't need an event listener
3569 },
3570
3571 teardown: function() {
3572 // Only need this for delegated form submit events
3573 if ( jQuery.nodeName( this, "form" ) ) {
3574 return false;
3575 }
3576
3577 // Remove delegated handlers; cleanData eventually reaps submit handlers attached above
3578 jQuery.event.remove( this, "._submit" );
3579 }
3580 };
3581 }
3582
3583 // IE change delegation and checkbox/radio fix
3584 if ( !jQuery.support.changeBubbles ) {
3585
3586 jQuery.event.special.change = {
3587
3588 setup: function() {
3589
3590 if ( rformElems.test( this.nodeName ) ) {
3591 // IE doesn't fire change on a check/radio until blur; trigger it on click
3592 // after a propertychange. Eat the blur-change in special.change.handle.
3593 // This still fires onchange a second time for check/radio after blur.
3594 if ( this.type === "checkbox" || this.type === "radio" ) {
3595 jQuery.event.add( this, "propertychange._change", function( event ) {
3596 if ( event.originalEvent.propertyName === "checked" ) {
3597 this._just_changed = true;
3598 }
3599 });
3600 jQuery.event.add( this, "click._change", function( event ) {
3601 if ( this._just_changed && !event.isTrigger ) {
3602 this._just_changed = false;
3603 jQuery.event.simulate( "change", this, event, true );
3604 }
3605 });
3606 }
3607 return false;
3608 }
3609 // Delegated event; lazy-add a change handler on descendant inputs
3610 jQuery.event.add( this, "beforeactivate._change", function( e ) {
3611 var elem = e.target;
3612
3613 if ( rformElems.test( elem.nodeName ) && !elem._change_attached ) {
3614 jQuery.event.add( elem, "change._change", function( event ) {
3615 if ( this.parentNode && !event.isSimulated && !event.isTrigger ) {
3616 jQuery.event.simulate( "change", this.parentNode, event, true );
3617 }
3618 });
3619 elem._change_attached = true;
3620 }
3621 });
3622 },
3623
3624 handle: function( event ) {
3625 var elem = event.target;
3626
3627 // Swallow native change events from checkbox/radio, we already triggered them above
3628 if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) {
3629 return event.handleObj.handler.apply( this, arguments );
3630 }
3631 },
3632
3633 teardown: function() {
3634 jQuery.event.remove( this, "._change" );
3635
3636 return rformElems.test( this.nodeName );
3637 }
3638 };
3639 }
3640
3641 // Create "bubbling" focus and blur events
3642 if ( !jQuery.support.focusinBubbles ) {
3643 jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
3644
3645 // Attach a single capturing handler while someone wants focusin/focusout
3646 var attaches = 0,
3647 handler = function( event ) {
3648 jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );
3649 };
3650
3651 jQuery.event.special[ fix ] = {
3652 setup: function() {
3653 if ( attaches++ === 0 ) {
3654 document.addEventListener( orig, handler, true );
3655 }
3656 },
3657 teardown: function() {
3658 if ( --attaches === 0 ) {
3659 document.removeEventListener( orig, handler, true );
3660 }
3661 }
3662 };
3663 });
3664 }
3665
3666 jQuery.fn.extend({
3667
3668 on: function( types, selector, data, fn, /*INTERNAL*/ one ) {
3669 var origFn, type;
3670
3671 // Types can be a map of types/handlers
3672 if ( typeof types === "object" ) {
3673 // ( types-Object, selector, data )
3674 if ( typeof selector !== "string" ) {
3675 // ( types-Object, data )
3676 data = selector;
3677 selector = undefined;
3678 }
3679 for ( type in types ) {
3680 this.on( type, selector, data, types[ type ], one );
3681 }
3682 return this;
3683 }
3684
3685 if ( data == null && fn == null ) {
3686 // ( types, fn )
3687 fn = selector;
3688 data = selector = undefined;
3689 } else if ( fn == null ) {
3690 if ( typeof selector === "string" ) {
3691 // ( types, selector, fn )
3692 fn = data;
3693 data = undefined;
3694 } else {
3695 // ( types, data, fn )
3696 fn = data;
3697 data = selector;
3698 selector = undefined;
3699 }
3700 }
3701 if ( fn === false ) {
3702 fn = returnFalse;
3703 } else if ( !fn ) {
3704 return this;
3705 }
3706
3707 if ( one === 1 ) {
3708 origFn = fn;
3709 fn = function( event ) {
3710 // Can use an empty set, since event contains the info
3711 jQuery().off( event );
3712 return origFn.apply( this, arguments );
3713 };
3714 // Use same guid so caller can remove using origFn
3715 fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
3716 }
3717 return this.each( function() {
3718 jQuery.event.add( this, types, fn, data, selector );
3719 });
3720 },
3721 one: function( types, selector, data, fn ) {
3722 return this.on.call( this, types, selector, data, fn, 1 );
3723 },
3724 off: function( types, selector, fn ) {
3725 if ( types && types.preventDefault && types.handleObj ) {
3726 // ( event ) dispatched jQuery.Event
3727 var handleObj = types.handleObj;
3728 jQuery( types.delegateTarget ).off(
3729 handleObj.namespace? handleObj.type + "." + handleObj.namespace : handleObj.type,
3730 handleObj.selector,
3731 handleObj.handler
3732 );
3733 return this;
3734 }
3735 if ( typeof types === "object" ) {
3736 // ( types-object [, selector] )
3737 for ( var type in types ) {
3738 this.off( type, selector, types[ type ] );
3739 }
3740 return this;
3741 }
3742 if ( selector === false || typeof selector === "function" ) {
3743 // ( types [, fn] )
3744 fn = selector;
3745 selector = undefined;
3746 }
3747 if ( fn === false ) {
3748 fn = returnFalse;
3749 }
3750 return this.each(function() {
3751 jQuery.event.remove( this, types, fn, selector );
3752 });
3753 },
3754
3755 bind: function( types, data, fn ) {
3756 return this.on( types, null, data, fn );
3757 },
3758 unbind: function( types, fn ) {
3759 return this.off( types, null, fn );
3760 },
3761
3762 live: function( types, data, fn ) {
3763 jQuery( this.context ).on( types, this.selector, data, fn );
3764 return this;
3765 },
3766 die: function( types, fn ) {
3767 jQuery( this.context ).off( types, this.selector || "**", fn );
3768 return this;
3769 },
3770
3771 delegate: function( selector, types, data, fn ) {
3772 return this.on( types, selector, data, fn );
3773 },
3774 undelegate: function( selector, types, fn ) {
3775 // ( namespace ) or ( selector, types [, fn] )
3776 return arguments.length == 1? this.off( selector, "**" ) : this.off( types, selector, fn );
3777 },
3778
3779 trigger: function( type, data ) {
3780 return this.each(function() {
3781 jQuery.event.trigger( type, data, this );
3782 });
3783 },
3784 triggerHandler: function( type, data ) {
3785 if ( this[0] ) {
3786 return jQuery.event.trigger( type, data, this[0], true );
3787 }
3788 },
3789
3790 toggle: function( fn ) {
3791 // Save reference to arguments for access in closure
3792 var args = arguments,
3793 guid = fn.guid || jQuery.guid++,
3794 i = 0,
3795 toggler = function( event ) {
3796 // Figure out which function to execute
3797 var lastToggle = ( jQuery._data( this, "lastToggle" + fn.guid ) || 0 ) % i;
3798 jQuery._data( this, "lastToggle" + fn.guid, lastToggle + 1 );
3799
3800 // Make sure that clicks stop
3801 event.preventDefault();
3802
3803 // and execute the function
3804 return args[ lastToggle ].apply( this, arguments ) || false;
3805 };
3806
3807 // link all the functions, so any of them can unbind this click handler
3808 toggler.guid = guid;
3809 while ( i < args.length ) {
3810 args[ i++ ].guid = guid;
3811 }
3812
3813 return this.click( toggler );
3814 },
3815
3816 hover: function( fnOver, fnOut ) {
3817 return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
3818 }
3819 });
3820
3821 jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
3822 "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
3823 "change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) {
3824
3825 // Handle event binding
3826 jQuery.fn[ name ] = function( data, fn ) {
3827 if ( fn == null ) {
3828 fn = data;
3829 data = null;
3830 }
3831
3832 return arguments.length > 0 ?
3833 this.on( name, null, data, fn ) :
3834 this.trigger( name );
3835 };
3836
3837 if ( jQuery.attrFn ) {
3838 jQuery.attrFn[ name ] = true;
3839 }
3840
3841 if ( rkeyEvent.test( name ) ) {
3842 jQuery.event.fixHooks[ name ] = jQuery.event.keyHooks;
3843 }
3844
3845 if ( rmouseEvent.test( name ) ) {
3846 jQuery.event.fixHooks[ name ] = jQuery.event.mouseHooks;
3847 }
3848 });
3849
3850
3851
3852 /*!
3853 * Sizzle CSS Selector Engine
3854 * Copyright 2011, The Dojo Foundation
3855 * Released under the MIT, BSD, and GPL Licenses.
3856 * More information: http://sizzlejs.com/
3857 */
3858 (function(){
3859
3860 var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
3861 expando = "sizcache" + (Math.random() + '').replace('.', ''),
3862 done = 0,
3863 toString = Object.prototype.toString,
3864 hasDuplicate = false,
3865 baseHasDuplicate = true,
3866 rBackslash = /\\/g,
3867 rReturn = /\r\n/g,
3868 rNonWord = /\W/;
3869
3870 // Here we check if the JavaScript engine is using some sort of
3871 // optimization where it does not always call our comparision
3872 // function. If that is the case, discard the hasDuplicate value.
3873 // Thus far that includes Google Chrome.
3874 [0, 0].sort(function() {
3875 baseHasDuplicate = false;
3876 return 0;
3877 });
3878
3879 var Sizzle = function( selector, context, results, seed ) {
3880 results = results || [];
3881 context = context || document;
3882
3883 var origContext = context;
3884
3885 if ( context.nodeType !== 1 && context.nodeType !== 9 ) {
3886 return [];
3887 }
3888
3889 if ( !selector || typeof selector !== "string" ) {
3890 return results;
3891 }
3892
3893 var m, set, checkSet, extra, ret, cur, pop, i,
3894 prune = true,
3895 contextXML = Sizzle.isXML( context ),
3896 parts = [],
3897 soFar = selector;
3898
3899 // Reset the position of the chunker regexp (start from head)
3900 do {
3901 chunker.exec( "" );
3902 m = chunker.exec( soFar );
3903
3904 if ( m ) {
3905 soFar = m[3];
3906
3907 parts.push( m[1] );
3908
3909 if ( m[2] ) {
3910 extra = m[3];
3911 break;
3912 }
3913 }
3914 } while ( m );
3915
3916 if ( parts.length > 1 && origPOS.exec( selector ) ) {
3917
3918 if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {
3919 set = posProcess( parts[0] + parts[1], context, seed );
3920
3921 } else {
3922 set = Expr.relative[ parts[0] ] ?
3923 [ context ] :
3924 Sizzle( parts.shift(), context );
3925
3926 while ( parts.length ) {
3927 selector = parts.shift();
3928
3929 if ( Expr.relative[ selector ] ) {
3930 selector += parts.shift();
3931 }
3932
3933 set = posProcess( selector, set, seed );
3934 }
3935 }
3936
3937 } else {
3938 // Take a shortcut and set the context if the root selector is an ID
3939 // (but not if it'll be faster if the inner selector is an ID)
3940 if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML &&
3941 Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {
3942
3943 ret = Sizzle.find( parts.shift(), context, contextXML );
3944 context = ret.expr ?
3945 Sizzle.filter( ret.expr, ret.set )[0] :
3946 ret.set[0];
3947 }
3948
3949 if ( context ) {
3950 ret = seed ?
3951 { expr: parts.pop(), set: makeArray(seed) } :
3952 Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML );
3953
3954 set = ret.expr ?
3955 Sizzle.filter( ret.expr, ret.set ) :
3956 ret.set;
3957
3958 if ( parts.length > 0 ) {
3959 checkSet = makeArray( set );
3960
3961 } else {
3962 prune = false;
3963 }
3964
3965 while ( parts.length ) {
3966 cur = parts.pop();
3967 pop = cur;
3968
3969 if ( !Expr.relative[ cur ] ) {
3970 cur = "";
3971 } else {
3972 pop = parts.pop();
3973 }
3974
3975 if ( pop == null ) {
3976 pop = context;
3977 }
3978
3979 Expr.relative[ cur ]( checkSet, pop, contextXML );
3980 }
3981
3982 } else {
3983 checkSet = parts = [];
3984 }
3985 }
3986
3987 if ( !checkSet ) {
3988 checkSet = set;
3989 }
3990
3991 if ( !checkSet ) {
3992 Sizzle.error( cur || selector );
3993 }
3994
3995 if ( toString.call(checkSet) === "[object Array]" ) {
3996 if ( !prune ) {
3997 results.push.apply( results, checkSet );
3998
3999 } else if ( context && context.nodeType === 1 ) {
4000 for ( i = 0; checkSet[i] != null; i++ ) {
4001 if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) {
4002 results.push( set[i] );
4003 }
4004 }
4005
4006 } else {
4007 for ( i = 0; checkSet[i] != null; i++ ) {
4008 if ( checkSet[i] && checkSet[i].nodeType === 1 ) {
4009 results.push( set[i] );
4010 }
4011 }
4012 }
4013
4014 } else {
4015 makeArray( checkSet, results );
4016 }
4017
4018 if ( extra ) {
4019 Sizzle( extra, origContext, results, seed );
4020 Sizzle.uniqueSort( results );
4021 }
4022
4023 return results;
4024 };
4025
4026 Sizzle.uniqueSort = function( results ) {
4027 if ( sortOrder ) {
4028 hasDuplicate = baseHasDuplicate;
4029 results.sort( sortOrder );
4030
4031 if ( hasDuplicate ) {
4032 for ( var i = 1; i < results.length; i++ ) {
4033 if ( results[i] === results[ i - 1 ] ) {
4034 results.splice( i--, 1 );
4035 }
4036 }
4037 }
4038 }
4039
4040 return results;
4041 };
4042
4043 Sizzle.matches = function( expr, set ) {
4044 return Sizzle( expr, null, null, set );
4045 };
4046
4047 Sizzle.matchesSelector = function( node, expr ) {
4048 return Sizzle( expr, null, null, [node] ).length > 0;
4049 };
4050
4051 Sizzle.find = function( expr, context, isXML ) {
4052 var set, i, len, match, type, left;
4053
4054 if ( !expr ) {
4055 return [];
4056 }
4057
4058 for ( i = 0, len = Expr.order.length; i < len; i++ ) {
4059 type = Expr.order[i];
4060
4061 if ( (match = Expr.leftMatch[ type ].exec( expr )) ) {
4062 left = match[1];
4063 match.splice( 1, 1 );
4064
4065 if ( left.substr( left.length - 1 ) !== "\\" ) {
4066 match[1] = (match[1] || "").replace( rBackslash, "" );
4067 set = Expr.find[ type ]( match, context, isXML );
4068
4069 if ( set != null ) {
4070 expr = expr.replace( Expr.match[ type ], "" );
4071 break;
4072 }
4073 }
4074 }
4075 }
4076
4077 if ( !set ) {
4078 set = typeof context.getElementsByTagName !== "undefined" ?
4079 context.getElementsByTagName( "*" ) :
4080 [];
4081 }
4082
4083 return { set: set, expr: expr };
4084 };
4085
4086 Sizzle.filter = function( expr, set, inplace, not ) {
4087 var match, anyFound,
4088 type, found, item, filter, left,
4089 i, pass,
4090 old = expr,
4091 result = [],
4092 curLoop = set,
4093 isXMLFilter = set && set[0] && Sizzle.isXML( set[0] );
4094
4095 while ( expr && set.length ) {
4096 for ( type in Expr.filter ) {
4097 if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) {
4098 filter = Expr.filter[ type ];
4099 left = match[1];
4100
4101 anyFound = false;
4102
4103 match.splice(1,1);
4104
4105 if ( left.substr( left.length - 1 ) === "\\" ) {
4106 continue;
4107 }
4108
4109 if ( curLoop === result ) {
4110 result = [];
4111 }
4112
4113 if ( Expr.preFilter[ type ] ) {
4114 match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );
4115
4116 if ( !match ) {
4117 anyFound = found = true;
4118
4119 } else if ( match === true ) {
4120 continue;
4121 }
4122 }
4123
4124 if ( match ) {
4125 for ( i = 0; (item = curLoop[i]) != null; i++ ) {
4126 if ( item ) {
4127 found = filter( item, match, i, curLoop );
4128 pass = not ^ found;
4129
4130 if ( inplace && found != null ) {
4131 if ( pass ) {
4132 anyFound = true;
4133
4134 } else {
4135 curLoop[i] = false;
4136 }
4137
4138 } else if ( pass ) {
4139 result.push( item );
4140 anyFound = true;
4141 }
4142 }
4143 }
4144 }
4145
4146 if ( found !== undefined ) {
4147 if ( !inplace ) {
4148 curLoop = result;
4149 }
4150
4151 expr = expr.replace( Expr.match[ type ], "" );
4152
4153 if ( !anyFound ) {
4154 return [];
4155 }
4156
4157 break;
4158 }
4159 }
4160 }
4161
4162 // Improper expression
4163 if ( expr === old ) {
4164 if ( anyFound == null ) {
4165 Sizzle.error( expr );
4166
4167 } else {
4168 break;
4169 }
4170 }
4171
4172 old = expr;
4173 }
4174
4175 return curLoop;
4176 };
4177
4178 Sizzle.error = function( msg ) {
4179 throw new Error( "Syntax error, unrecognized expression: " + msg );
4180 };
4181
4182 /**
4183 * Utility function for retreiving the text value of an array of DOM nodes
4184 * @param {Array|Element} elem
4185 */
4186 var getText = Sizzle.getText = function( elem ) {
4187 var i, node,
4188 nodeType = elem.nodeType,
4189 ret = "";
4190
4191 if ( nodeType ) {
4192 if ( nodeType === 1 || nodeType === 9 ) {
4193 // Use textContent || innerText for elements
4194 if ( typeof elem.textContent === 'string' ) {
4195 return elem.textContent;
4196 } else if ( typeof elem.innerText === 'string' ) {
4197 // Replace IE's carriage returns
4198 return elem.innerText.replace( rReturn, '' );
4199 } else {
4200 // Traverse it's children
4201 for ( elem = elem.firstChild; elem; elem = elem.nextSibling) {
4202 ret += getText( elem );
4203 }
4204 }
4205 } else if ( nodeType === 3 || nodeType === 4 ) {
4206 return elem.nodeValue;
4207 }
4208 } else {
4209
4210 // If no nodeType, this is expected to be an array
4211 for ( i = 0; (node = elem[i]); i++ ) {
4212 // Do not traverse comment nodes
4213 if ( node.nodeType !== 8 ) {
4214 ret += getText( node );
4215 }
4216 }
4217 }
4218 return ret;
4219 };
4220
4221 var Expr = Sizzle.selectors = {
4222 order: [ "ID", "NAME", "TAG" ],
4223
4224 match: {
4225 ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,
4226 CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,
4227 NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,
4228 ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,
4229 TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,
4230 CHILD: /:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/,
4231 POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,
4232 PSEUDO: /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/
4233 },
4234
4235 leftMatch: {},
4236
4237 attrMap: {
4238 "class": "className",
4239 "for": "htmlFor"
4240 },
4241
4242 attrHandle: {
4243 href: function( elem ) {
4244 return elem.getAttribute( "href" );
4245 },
4246 type: function( elem ) {
4247 return elem.getAttribute( "type" );
4248 }
4249 },
4250
4251 relative: {
4252 "+": function(checkSet, part){
4253 var isPartStr = typeof part === "string",
4254 isTag = isPartStr && !rNonWord.test( part ),
4255 isPartStrNotTag = isPartStr && !isTag;
4256
4257 if ( isTag ) {
4258 part = part.toLowerCase();
4259 }
4260
4261 for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {
4262 if ( (elem = checkSet[i]) ) {
4263 while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}
4264
4265 checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ?
4266 elem || false :
4267 elem === part;
4268 }
4269 }
4270
4271 if ( isPartStrNotTag ) {
4272 Sizzle.filter( part, checkSet, true );
4273 }
4274 },
4275
4276 ">": function( checkSet, part ) {
4277 var elem,
4278 isPartStr = typeof part === "string",
4279 i = 0,
4280 l = checkSet.length;
4281
4282 if ( isPartStr && !rNonWord.test( part ) ) {
4283 part = part.toLowerCase();
4284
4285 for ( ; i < l; i++ ) {
4286 elem = checkSet[i];
4287
4288 if ( elem ) {
4289 var parent = elem.parentNode;
4290 checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false;
4291 }
4292 }
4293
4294 } else {
4295 for ( ; i < l; i++ ) {
4296 elem = checkSet[i];
4297
4298 if ( elem ) {
4299 checkSet[i] = isPartStr ?
4300 elem.parentNode :
4301 elem.parentNode === part;
4302 }
4303 }
4304
4305 if ( isPartStr ) {
4306 Sizzle.filter( part, checkSet, true );
4307 }
4308 }
4309 },
4310
4311 "": function(checkSet, part, isXML){
4312 var nodeCheck,
4313 doneName = done++,
4314 checkFn = dirCheck;
4315
4316 if ( typeof part === "string" && !rNonWord.test( part ) ) {
4317 part = part.toLowerCase();
4318 nodeCheck = part;
4319 checkFn = dirNodeCheck;
4320 }
4321
4322 checkFn( "parentNode", part, doneName, checkSet, nodeCheck, isXML );
4323 },
4324
4325 "~": function( checkSet, part, isXML ) {
4326 var nodeCheck,
4327 doneName = done++,
4328 checkFn = dirCheck;
4329
4330 if ( typeof part === "string" && !rNonWord.test( part ) ) {
4331 part = part.toLowerCase();
4332 nodeCheck = part;
4333 checkFn = dirNodeCheck;
4334 }
4335
4336 checkFn( "previousSibling", part, doneName, checkSet, nodeCheck, isXML );
4337 }
4338 },
4339
4340 find: {
4341 ID: function( match, context, isXML ) {
4342 if ( typeof context.getElementById !== "undefined" && !isXML ) {
4343 var m = context.getElementById(match[1]);
4344 // Check parentNode to catch when Blackberry 4.6 returns
4345 // nodes that are no longer in the document #6963
4346 return m && m.parentNode ? [m] : [];
4347 }
4348 },
4349
4350 NAME: function( match, context ) {
4351 if ( typeof context.getElementsByName !== "undefined" ) {
4352 var ret = [],
4353 results = context.getElementsByName( match[1] );
4354
4355 for ( var i = 0, l = results.length; i < l; i++ ) {
4356 if ( results[i].getAttribute("name") === match[1] ) {
4357 ret.push( results[i] );
4358 }
4359 }
4360
4361 return ret.length === 0 ? null : ret;
4362 }
4363 },
4364
4365 TAG: function( match, context ) {
4366 if ( typeof context.getElementsByTagName !== "undefined" ) {
4367 return context.getElementsByTagName( match[1] );
4368 }
4369 }
4370 },
4371 preFilter: {
4372 CLASS: function( match, curLoop, inplace, result, not, isXML ) {
4373 match = " " + match[1].replace( rBackslash, "" ) + " ";
4374
4375 if ( isXML ) {
4376 return match;
4377 }
4378
4379 for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {
4380 if ( elem ) {
4381 if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n\r]/g, " ").indexOf(match) >= 0) ) {
4382 if ( !inplace ) {
4383 result.push( elem );
4384 }
4385
4386 } else if ( inplace ) {
4387 curLoop[i] = false;
4388 }
4389 }
4390 }
4391
4392 return false;
4393 },
4394
4395 ID: function( match ) {
4396 return match[1].replace( rBackslash, "" );
4397 },
4398
4399 TAG: function( match, curLoop ) {
4400 return match[1].replace( rBackslash, "" ).toLowerCase();
4401 },
4402
4403 CHILD: function( match ) {
4404 if ( match[1] === "nth" ) {
4405 if ( !match[2] ) {
4406 Sizzle.error( match[0] );
4407 }
4408
4409 match[2] = match[2].replace(/^\+|\s*/g, '');
4410
4411 // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
4412 var test = /(-?)(\d*)(?:n([+\-]?\d*))?/.exec(
4413 match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" ||
4414 !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]);
4415
4416 // calculate the numbers (first)n+(last) including if they are negative
4417 match[2] = (test[1] + (test[2] || 1)) - 0;
4418 match[3] = test[3] - 0;
4419 }
4420 else if ( match[2] ) {
4421 Sizzle.error( match[0] );
4422 }
4423
4424 // TODO: Move to normal caching system
4425 match[0] = done++;
4426
4427 return match;
4428 },
4429
4430 ATTR: function( match, curLoop, inplace, result, not, isXML ) {
4431 var name = match[1] = match[1].replace( rBackslash, "" );
4432
4433 if ( !isXML && Expr.attrMap[name] ) {
4434 match[1] = Expr.attrMap[name];
4435 }
4436
4437 // Handle if an un-quoted value was used
4438 match[4] = ( match[4] || match[5] || "" ).replace( rBackslash, "" );
4439
4440 if ( match[2] === "~=" ) {
4441 match[4] = " " + match[4] + " ";
4442 }
4443
4444 return match;
4445 },
4446
4447 PSEUDO: function( match, curLoop, inplace, result, not ) {
4448 if ( match[1] === "not" ) {
4449 // If we're dealing with a complex expression, or a simple one
4450 if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) {
4451 match[3] = Sizzle(match[3], null, null, curLoop);
4452
4453 } else {
4454 var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);
4455
4456 if ( !inplace ) {
4457 result.push.apply( result, ret );
4458 }
4459
4460 return false;
4461 }
4462
4463 } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {
4464 return true;
4465 }
4466
4467 return match;
4468 },
4469
4470 POS: function( match ) {
4471 match.unshift( true );
4472
4473 return match;
4474 }
4475 },
4476
4477 filters: {
4478 enabled: function( elem ) {
4479 return elem.disabled === false && elem.type !== "hidden";
4480 },
4481
4482 disabled: function( elem ) {
4483 return elem.disabled === true;
4484 },
4485
4486 checked: function( elem ) {
4487 return elem.checked === true;
4488 },
4489
4490 selected: function( elem ) {
4491 // Accessing this property makes selected-by-default
4492 // options in Safari work properly
4493 if ( elem.parentNode ) {
4494 elem.parentNode.selectedIndex;
4495 }
4496
4497 return elem.selected === true;
4498 },
4499
4500 parent: function( elem ) {
4501 return !!elem.firstChild;
4502 },
4503
4504 empty: function( elem ) {
4505 return !elem.firstChild;
4506 },
4507
4508 has: function( elem, i, match ) {
4509 return !!Sizzle( match[3], elem ).length;
4510 },
4511
4512 header: function( elem ) {
4513 return (/h\d/i).test( elem.nodeName );
4514 },
4515
4516 text: function( elem ) {
4517 var attr = elem.getAttribute( "type" ), type = elem.type;
4518 // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc)
4519 // use getAttribute instead to test this case
4520 return elem.nodeName.toLowerCase() === "input" && "text" === type && ( attr === type || attr === null );
4521 },
4522
4523 radio: function( elem ) {
4524 return elem.nodeName.toLowerCase() === "input" && "radio" === elem.type;
4525 },
4526
4527 checkbox: function( elem ) {
4528 return elem.nodeName.toLowerCase() === "input" && "checkbox" === elem.type;
4529 },
4530
4531 file: function( elem ) {
4532 return elem.nodeName.toLowerCase() === "input" && "file" === elem.type;
4533 },
4534
4535 password: function( elem ) {
4536 return elem.nodeName.toLowerCase() === "input" && "password" === elem.type;
4537 },
4538
4539 submit: function( elem ) {
4540 var name = elem.nodeName.toLowerCase();
4541 return (name === "input" || name === "button") && "submit" === elem.type;
4542 },
4543
4544 image: function( elem ) {
4545 return elem.nodeName.toLowerCase() === "input" && "image" === elem.type;
4546 },
4547
4548 reset: function( elem ) {
4549 var name = elem.nodeName.toLowerCase();
4550 return (name === "input" || name === "button") && "reset" === elem.type;
4551 },
4552
4553 button: function( elem ) {
4554 var name = elem.nodeName.toLowerCase();
4555 return name === "input" && "button" === elem.type || name === "button";
4556 },
4557
4558 input: function( elem ) {
4559 return (/input|select|textarea|button/i).test( elem.nodeName );
4560 },
4561
4562 focus: function( elem ) {
4563 return elem === elem.ownerDocument.activeElement;
4564 }
4565 },
4566 setFilters: {
4567 first: function( elem, i ) {
4568 return i === 0;
4569 },
4570
4571 last: function( elem, i, match, array ) {
4572 return i === array.length - 1;
4573 },
4574
4575 even: function( elem, i ) {
4576 return i % 2 === 0;
4577 },
4578
4579 odd: function( elem, i ) {
4580 return i % 2 === 1;
4581 },
4582
4583 lt: function( elem, i, match ) {
4584 return i < match[3] - 0;
4585 },
4586
4587 gt: function( elem, i, match ) {
4588 return i > match[3] - 0;
4589 },
4590
4591 nth: function( elem, i, match ) {
4592 return match[3] - 0 === i;
4593 },
4594
4595 eq: function( elem, i, match ) {
4596 return match[3] - 0 === i;
4597 }
4598 },
4599 filter: {
4600 PSEUDO: function( elem, match, i, array ) {
4601 var name = match[1],
4602 filter = Expr.filters[ name ];
4603
4604 if ( filter ) {
4605 return filter( elem, i, match, array );
4606
4607 } else if ( name === "contains" ) {
4608 return (elem.textContent || elem.innerText || getText([ elem ]) || "").indexOf(match[3]) >= 0;
4609
4610 } else if ( name === "not" ) {
4611 var not = match[3];
4612
4613 for ( var j = 0, l = not.length; j < l; j++ ) {
4614 if ( not[j] === elem ) {
4615 return false;
4616 }
4617 }
4618
4619 return true;
4620
4621 } else {
4622 Sizzle.error( name );
4623 }
4624 },
4625
4626 CHILD: function( elem, match ) {
4627 var first, last,
4628 doneName, parent, cache,
4629 count, diff,
4630 type = match[1],
4631 node = elem;
4632
4633 switch ( type ) {
4634 case "only":
4635 case "first":
4636 while ( (node = node.previousSibling) ) {
4637 if ( node.nodeType === 1 ) {
4638 return false;
4639 }
4640 }
4641
4642 if ( type === "first" ) {
4643 return true;
4644 }
4645
4646 node = elem;
4647
4648 case "last":
4649 while ( (node = node.nextSibling) ) {
4650 if ( node.nodeType === 1 ) {
4651 return false;
4652 }
4653 }
4654
4655 return true;
4656
4657 case "nth":
4658 first = match[2];
4659 last = match[3];
4660
4661 if ( first === 1 && last === 0 ) {
4662 return true;
4663 }
4664
4665 doneName = match[0];
4666 parent = elem.parentNode;
4667
4668 if ( parent && (parent[ expando ] !== doneName || !elem.nodeIndex) ) {
4669 count = 0;
4670
4671 for ( node = parent.firstChild; node; node = node.nextSibling ) {
4672 if ( node.nodeType === 1 ) {
4673 node.nodeIndex = ++count;
4674 }
4675 }
4676
4677 parent[ expando ] = doneName;
4678 }
4679
4680 diff = elem.nodeIndex - last;
4681
4682 if ( first === 0 ) {
4683 return diff === 0;
4684
4685 } else {
4686 return ( diff % first === 0 && diff / first >= 0 );
4687 }
4688 }
4689 },
4690
4691 ID: function( elem, match ) {
4692 return elem.nodeType === 1 && elem.getAttribute("id") === match;
4693 },
4694
4695 TAG: function( elem, match ) {
4696 return (match === "*" && elem.nodeType === 1) || !!elem.nodeName && elem.nodeName.toLowerCase() === match;
4697 },
4698
4699 CLASS: function( elem, match ) {
4700 return (" " + (elem.className || elem.getAttribute("class")) + " ")
4701 .indexOf( match ) > -1;
4702 },
4703
4704 ATTR: function( elem, match ) {
4705 var name = match[1],
4706 result = Sizzle.attr ?
4707 Sizzle.attr( elem, name ) :
4708 Expr.attrHandle[ name ] ?
4709 Expr.attrHandle[ name ]( elem ) :
4710 elem[ name ] != null ?
4711 elem[ name ] :
4712 elem.getAttribute( name ),
4713 value = result + "",
4714 type = match[2],
4715 check = match[4];
4716
4717 return result == null ?
4718 type === "!=" :
4719 !type && Sizzle.attr ?
4720 result != null :
4721 type === "=" ?
4722 value === check :
4723 type === "*=" ?
4724 value.indexOf(check) >= 0 :
4725 type === "~=" ?
4726 (" " + value + " ").indexOf(check) >= 0 :
4727 !check ?
4728 value && result !== false :
4729 type === "!=" ?
4730 value !== check :
4731 type === "^=" ?
4732 value.indexOf(check) === 0 :
4733 type === "$=" ?
4734 value.substr(value.length - check.length) === check :
4735 type === "|=" ?
4736 value === check || value.substr(0, check.length + 1) === check + "-" :
4737 false;
4738 },
4739
4740 POS: function( elem, match, i, array ) {
4741 var name = match[2],
4742 filter = Expr.setFilters[ name ];
4743
4744 if ( filter ) {
4745 return filter( elem, i, match, array );
4746 }
4747 }
4748 }
4749 };
4750
4751 var origPOS = Expr.match.POS,
4752 fescape = function(all, num){
4753 return "\\" + (num - 0 + 1);
4754 };
4755
4756 for ( var type in Expr.match ) {
4757 Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) );
4758 Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) );
4759 }
4760
4761 var makeArray = function( array, results ) {
4762 array = Array.prototype.slice.call( array, 0 );
4763
4764 if ( results ) {
4765 results.push.apply( results, array );
4766 return results;
4767 }
4768
4769 return array;
4770 };
4771
4772 // Perform a simple check to determine if the browser is capable of
4773 // converting a NodeList to an array using builtin methods.
4774 // Also verifies that the returned array holds DOM nodes
4775 // (which is not the case in the Blackberry browser)
4776 try {
4777 Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType;
4778
4779 // Provide a fallback method if it does not work
4780 } catch( e ) {
4781 makeArray = function( array, results ) {
4782 var i = 0,
4783 ret = results || [];
4784
4785 if ( toString.call(array) === "[object Array]" ) {
4786 Array.prototype.push.apply( ret, array );
4787
4788 } else {
4789 if ( typeof array.length === "number" ) {
4790 for ( var l = array.length; i < l; i++ ) {
4791 ret.push( array[i] );
4792 }
4793
4794 } else {
4795 for ( ; array[i]; i++ ) {
4796 ret.push( array[i] );
4797 }
4798 }
4799 }
4800
4801 return ret;
4802 };
4803 }
4804
4805 var sortOrder, siblingCheck;
4806
4807 if ( document.documentElement.compareDocumentPosition ) {
4808 sortOrder = function( a, b ) {
4809 if ( a === b ) {
4810 hasDuplicate = true;
4811 return 0;
4812 }
4813
4814 if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) {
4815 return a.compareDocumentPosition ? -1 : 1;
4816 }
4817
4818 return a.compareDocumentPosition(b) & 4 ? -1 : 1;
4819 };
4820
4821 } else {
4822 sortOrder = function( a, b ) {
4823 // The nodes are identical, we can exit early
4824 if ( a === b ) {
4825 hasDuplicate = true;
4826 return 0;
4827
4828 // Fallback to using sourceIndex (in IE) if it's available on both nodes
4829 } else if ( a.sourceIndex && b.sourceIndex ) {
4830 return a.sourceIndex - b.sourceIndex;
4831 }
4832
4833 var al, bl,
4834 ap = [],
4835 bp = [],
4836 aup = a.parentNode,
4837 bup = b.parentNode,
4838 cur = aup;
4839
4840 // If the nodes are siblings (or identical) we can do a quick check
4841 if ( aup === bup ) {
4842 return siblingCheck( a, b );
4843
4844 // If no parents were found then the nodes are disconnected
4845 } else if ( !aup ) {
4846 return -1;
4847
4848 } else if ( !bup ) {
4849 return 1;
4850 }
4851
4852 // Otherwise they're somewhere else in the tree so we need
4853 // to build up a full list of the parentNodes for comparison
4854 while ( cur ) {
4855 ap.unshift( cur );
4856 cur = cur.parentNode;
4857 }
4858
4859 cur = bup;
4860
4861 while ( cur ) {
4862 bp.unshift( cur );
4863 cur = cur.parentNode;
4864 }
4865
4866 al = ap.length;
4867 bl = bp.length;
4868
4869 // Start walking down the tree looking for a discrepancy
4870 for ( var i = 0; i < al && i < bl; i++ ) {
4871 if ( ap[i] !== bp[i] ) {
4872 return siblingCheck( ap[i], bp[i] );
4873 }
4874 }
4875
4876 // We ended someplace up the tree so do a sibling check
4877 return i === al ?
4878 siblingCheck( a, bp[i], -1 ) :
4879 siblingCheck( ap[i], b, 1 );
4880 };
4881
4882 siblingCheck = function( a, b, ret ) {
4883 if ( a === b ) {
4884 return ret;
4885 }
4886
4887 var cur = a.nextSibling;
4888
4889 while ( cur ) {
4890 if ( cur === b ) {
4891 return -1;
4892 }
4893
4894 cur = cur.nextSibling;
4895 }
4896
4897 return 1;
4898 };
4899 }
4900
4901 // Check to see if the browser returns elements by name when
4902 // querying by getElementById (and provide a workaround)
4903 (function(){
4904 // We're going to inject a fake input element with a specified name
4905 var form = document.createElement("div"),
4906 id = "script" + (new Date()).getTime(),
4907 root = document.documentElement;
4908
4909 form.innerHTML = "<a name='" + id + "'/>";
4910
4911 // Inject it into the root element, check its status, and remove it quickly
4912 root.insertBefore( form, root.firstChild );
4913
4914 // The workaround has to do additional checks after a getElementById
4915 // Which slows things down for other browsers (hence the branching)
4916 if ( document.getElementById( id ) ) {
4917 Expr.find.ID = function( match, context, isXML ) {
4918 if ( typeof context.getElementById !== "undefined" && !isXML ) {
4919 var m = context.getElementById(match[1]);
4920
4921 return m ?
4922 m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ?
4923 [m] :
4924 undefined :
4925 [];
4926 }
4927 };
4928
4929 Expr.filter.ID = function( elem, match ) {
4930 var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
4931
4932 return elem.nodeType === 1 && node && node.nodeValue === match;
4933 };
4934 }
4935
4936 root.removeChild( form );
4937
4938 // release memory in IE
4939 root = form = null;
4940 })();
4941
4942 (function(){
4943 // Check to see if the browser returns only elements
4944 // when doing getElementsByTagName("*")
4945
4946 // Create a fake element
4947 var div = document.createElement("div");
4948 div.appendChild( document.createComment("") );
4949
4950 // Make sure no comments are found
4951 if ( div.getElementsByTagName("*").length > 0 ) {
4952 Expr.find.TAG = function( match, context ) {
4953 var results = context.getElementsByTagName( match[1] );
4954
4955 // Filter out possible comments
4956 if ( match[1] === "*" ) {
4957 var tmp = [];
4958
4959 for ( var i = 0; results[i]; i++ ) {
4960 if ( results[i].nodeType === 1 ) {
4961 tmp.push( results[i] );
4962 }
4963 }
4964
4965 results = tmp;
4966 }
4967
4968 return results;
4969 };
4970 }
4971
4972 // Check to see if an attribute returns normalized href attributes
4973 div.innerHTML = "<a href='#'></a>";
4974
4975 if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" &&
4976 div.firstChild.getAttribute("href") !== "#" ) {
4977
4978 Expr.attrHandle.href = function( elem ) {
4979 return elem.getAttribute( "href", 2 );
4980 };
4981 }
4982
4983 // release memory in IE
4984 div = null;
4985 })();
4986
4987 if ( document.querySelectorAll ) {
4988 (function(){
4989 var oldSizzle = Sizzle,
4990 div = document.createElement("div"),
4991 id = "__sizzle__";
4992
4993 div.innerHTML = "<p class='TEST'></p>";
4994
4995 // Safari can't handle uppercase or unicode characters when
4996 // in quirks mode.
4997 if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) {
4998 return;
4999 }
5000
5001 Sizzle = function( query, context, extra, seed ) {
5002 context = context || document;
5003
5004 // Only use querySelectorAll on non-XML documents
5005 // (ID selectors don't work in non-HTML documents)
5006 if ( !seed && !Sizzle.isXML(context) ) {
5007 // See if we find a selector to speed up
5008 var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec( query );
5009
5010 if ( match && (context.nodeType === 1 || context.nodeType === 9) ) {
5011 // Speed-up: Sizzle("TAG")
5012 if ( match[1] ) {
5013 return makeArray( context.getElementsByTagName( query ), extra );
5014
5015 // Speed-up: Sizzle(".CLASS")
5016 } else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) {
5017 return makeArray( context.getElementsByClassName( match[2] ), extra );
5018 }
5019 }
5020
5021 if ( context.nodeType === 9 ) {
5022 // Speed-up: Sizzle("body")
5023 // The body element only exists once, optimize finding it
5024 if ( query === "body" && context.body ) {
5025 return makeArray( [ context.body ], extra );
5026
5027 // Speed-up: Sizzle("#ID")
5028 } else if ( match && match[3] ) {
5029 var elem = context.getElementById( match[3] );
5030
5031 // Check parentNode to catch when Blackberry 4.6 returns
5032 // nodes that are no longer in the document #6963
5033 if ( elem && elem.parentNode ) {
5034 // Handle the case where IE and Opera return items
5035 // by name instead of ID
5036 if ( elem.id === match[3] ) {
5037 return makeArray( [ elem ], extra );
5038 }
5039
5040 } else {
5041 return makeArray( [], extra );
5042 }
5043 }
5044
5045 try {
5046 return makeArray( context.querySelectorAll(query), extra );
5047 } catch(qsaError) {}
5048
5049 // qSA works strangely on Element-rooted queries
5050 // We can work around this by specifying an extra ID on the root
5051 // and working up from there (Thanks to Andrew Dupont for the technique)
5052 // IE 8 doesn't work on object elements
5053 } else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
5054 var oldContext = context,
5055 old = context.getAttribute( "id" ),
5056 nid = old || id,
5057 hasParent = context.parentNode,
5058 relativeHierarchySelector = /^\s*[+~]/.test( query );
5059
5060 if ( !old ) {
5061 context.setAttribute( "id", nid );
5062 } else {
5063 nid = nid.replace( /'/g, "\\$&" );
5064 }
5065 if ( relativeHierarchySelector && hasParent ) {
5066 context = context.parentNode;
5067 }
5068
5069 try {
5070 if ( !relativeHierarchySelector || hasParent ) {
5071 return makeArray( context.querySelectorAll( "[id='" + nid + "'] " + query ), extra );
5072 }
5073
5074 } catch(pseudoError) {
5075 } finally {
5076 if ( !old ) {
5077 oldContext.removeAttribute( "id" );
5078 }
5079 }
5080 }
5081 }
5082
5083 return oldSizzle(query, context, extra, seed);
5084 };
5085
5086 for ( var prop in oldSizzle ) {
5087 Sizzle[ prop ] = oldSizzle[ prop ];
5088 }
5089
5090 // release memory in IE
5091 div = null;
5092 })();
5093 }
5094
5095 (function(){
5096 var html = document.documentElement,
5097 matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector;
5098
5099 if ( matches ) {
5100 // Check to see if it's possible to do matchesSelector
5101 // on a disconnected node (IE 9 fails this)
5102 var disconnectedMatch = !matches.call( document.createElement( "div" ), "div" ),
5103 pseudoWorks = false;
5104
5105 try {
5106 // This should fail with an exception
5107 // Gecko does not error, returns false instead
5108 matches.call( document.documentElement, "[test!='']:sizzle" );
5109
5110 } catch( pseudoError ) {
5111 pseudoWorks = true;
5112 }
5113
5114 Sizzle.matchesSelector = function( node, expr ) {
5115 // Make sure that attribute selectors are quoted
5116 expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']");
5117
5118 if ( !Sizzle.isXML( node ) ) {
5119 try {
5120 if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) {
5121 var ret = matches.call( node, expr );
5122
5123 // IE 9's matchesSelector returns false on disconnected nodes
5124 if ( ret || !disconnectedMatch ||
5125 // As well, disconnected nodes are said to be in a document
5126 // fragment in IE 9, so check for that
5127 node.document && node.document.nodeType !== 11 ) {
5128 return ret;
5129 }
5130 }
5131 } catch(e) {}
5132 }
5133
5134 return Sizzle(expr, null, null, [node]).length > 0;
5135 };
5136 }
5137 })();
5138
5139 (function(){
5140 var div = document.createElement("div");
5141
5142 div.innerHTML = "<div class='test e'></div><div class='test'></div>";
5143
5144 // Opera can't find a second classname (in 9.6)
5145 // Also, make sure that getElementsByClassName actually exists
5146 if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) {
5147 return;
5148 }
5149
5150 // Safari caches class attributes, doesn't catch changes (in 3.2)
5151 div.lastChild.className = "e";
5152
5153 if ( div.getElementsByClassName("e").length === 1 ) {
5154 return;
5155 }
5156
5157 Expr.order.splice(1, 0, "CLASS");
5158 Expr.find.CLASS = function( match, context, isXML ) {
5159 if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) {
5160 return context.getElementsByClassName(match[1]);
5161 }
5162 };
5163
5164 // release memory in IE
5165 div = null;
5166 })();
5167
5168 function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
5169 for ( var i = 0, l = checkSet.length; i < l; i++ ) {
5170 var elem = checkSet[i];
5171
5172 if ( elem ) {
5173 var match = false;
5174
5175 elem = elem[dir];
5176
5177 while ( elem ) {
5178 if ( elem[ expando ] === doneName ) {
5179 match = checkSet[elem.sizset];
5180 break;
5181 }
5182
5183 if ( elem.nodeType === 1 && !isXML ){
5184 elem[ expando ] = doneName;
5185 elem.sizset = i;
5186 }
5187
5188 if ( elem.nodeName.toLowerCase() === cur ) {
5189 match = elem;
5190 break;
5191 }
5192
5193 elem = elem[dir];
5194 }
5195
5196 checkSet[i] = match;
5197 }
5198 }
5199 }
5200
5201 function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
5202 for ( var i = 0, l = checkSet.length; i < l; i++ ) {
5203 var elem = checkSet[i];
5204
5205 if ( elem ) {
5206 var match = false;
5207
5208 elem = elem[dir];
5209
5210 while ( elem ) {
5211 if ( elem[ expando ] === doneName ) {
5212 match = checkSet[elem.sizset];
5213 break;
5214 }
5215
5216 if ( elem.nodeType === 1 ) {
5217 if ( !isXML ) {
5218 elem[ expando ] = doneName;
5219 elem.sizset = i;
5220 }
5221
5222 if ( typeof cur !== "string" ) {
5223 if ( elem === cur ) {
5224 match = true;
5225 break;
5226 }
5227
5228 } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {
5229 match = elem;
5230 break;
5231 }
5232 }
5233
5234 elem = elem[dir];
5235 }
5236
5237 checkSet[i] = match;
5238 }
5239 }
5240 }
5241
5242 if ( document.documentElement.contains ) {
5243 Sizzle.contains = function( a, b ) {
5244 return a !== b && (a.contains ? a.contains(b) : true);
5245 };
5246
5247 } else if ( document.documentElement.compareDocumentPosition ) {
5248 Sizzle.contains = function( a, b ) {
5249 return !!(a.compareDocumentPosition(b) & 16);
5250 };
5251
5252 } else {
5253 Sizzle.contains = function() {
5254 return false;
5255 };
5256 }
5257
5258 Sizzle.isXML = function( elem ) {
5259 // documentElement is verified for cases where it doesn't yet exist
5260 // (such as loading iframes in IE - #4833)
5261 var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement;
5262
5263 return documentElement ? documentElement.nodeName !== "HTML" : false;
5264 };
5265
5266 var posProcess = function( selector, context, seed ) {
5267 var match,
5268 tmpSet = [],
5269 later = "",
5270 root = context.nodeType ? [context] : context;
5271
5272 // Position selectors must be done after the filter
5273 // And so must :not(positional) so we move all PSEUDOs to the end
5274 while ( (match = Expr.match.PSEUDO.exec( selector )) ) {
5275 later += match[0];
5276 selector = selector.replace( Expr.match.PSEUDO, "" );
5277 }
5278
5279 selector = Expr.relative[selector] ? selector + "*" : selector;
5280
5281 for ( var i = 0, l = root.length; i < l; i++ ) {
5282 Sizzle( selector, root[i], tmpSet, seed );
5283 }
5284
5285 return Sizzle.filter( later, tmpSet );
5286 };
5287
5288 // EXPOSE
5289 // Override sizzle attribute retrieval
5290 Sizzle.attr = jQuery.attr;
5291 Sizzle.selectors.attrMap = {};
5292 jQuery.find = Sizzle;
5293 jQuery.expr = Sizzle.selectors;
5294 jQuery.expr[":"] = jQuery.expr.filters;
5295 jQuery.unique = Sizzle.uniqueSort;
5296 jQuery.text = Sizzle.getText;
5297 jQuery.isXMLDoc = Sizzle.isXML;
5298 jQuery.contains = Sizzle.contains;
5299
5300
5301 })();
5302
5303
5304 var runtil = /Until$/,
5305 rparentsprev = /^(?:parents|prevUntil|prevAll)/,
5306 // Note: This RegExp should be improved, or likely pulled from Sizzle
5307 rmultiselector = /,/,
5308 isSimple = /^.[^:#\[\.,]*$/,
5309 slice = Array.prototype.slice,
5310 POS = jQuery.expr.match.POS,
5311 // methods guaranteed to produce a unique set when starting from a unique set
5312 guaranteedUnique = {
5313 children: true,
5314 contents: true,
5315 next: true,
5316 prev: true
5317 };
5318
5319 jQuery.fn.extend({
5320 find: function( selector ) {
5321 var self = this,
5322 i, l;
5323
5324 if ( typeof selector !== "string" ) {
5325 return jQuery( selector ).filter(function() {
5326 for ( i = 0, l = self.length; i < l; i++ ) {
5327 if ( jQuery.contains( self[ i ], this ) ) {
5328 return true;
5329 }
5330 }
5331 });
5332 }
5333
5334 var ret = this.pushStack( "", "find", selector ),
5335 length, n, r;
5336
5337 for ( i = 0, l = this.length; i < l; i++ ) {
5338 length = ret.length;
5339 jQuery.find( selector, this[i], ret );
5340
5341 if ( i > 0 ) {
5342 // Make sure that the results are unique
5343 for ( n = length; n < ret.length; n++ ) {
5344 for ( r = 0; r < length; r++ ) {
5345 if ( ret[r] === ret[n] ) {
5346 ret.splice(n--, 1);
5347 break;
5348 }
5349 }
5350 }
5351 }
5352 }
5353
5354 return ret;
5355 },
5356
5357 has: function( target ) {
5358 var targets = jQuery( target );
5359 return this.filter(function() {
5360 for ( var i = 0, l = targets.length; i < l; i++ ) {
5361 if ( jQuery.contains( this, targets[i] ) ) {
5362 return true;
5363 }
5364 }
5365 });
5366 },
5367
5368 not: function( selector ) {
5369 return this.pushStack( winnow(this, selector, false), "not", selector);
5370 },
5371
5372 filter: function( selector ) {
5373 return this.pushStack( winnow(this, selector, true), "filter", selector );
5374 },
5375
5376 is: function( selector ) {
5377 return !!selector && (
5378 typeof selector === "string" ?
5379 // If this is a positional selector, check membership in the returned set
5380 // so $("p:first").is("p:last") won't return true for a doc with two "p".
5381 POS.test( selector ) ?
5382 jQuery( selector, this.context ).index( this[0] ) >= 0 :
5383 jQuery.filter( selector, this ).length > 0 :
5384 this.filter( selector ).length > 0 );
5385 },
5386
5387 closest: function( selectors, context ) {
5388 var ret = [], i, l, cur = this[0];
5389
5390 // Array (deprecated as of jQuery 1.7)
5391 if ( jQuery.isArray( selectors ) ) {
5392 var level = 1;
5393
5394 while ( cur && cur.ownerDocument && cur !== context ) {
5395 for ( i = 0; i < selectors.length; i++ ) {
5396
5397 if ( jQuery( cur ).is( selectors[ i ] ) ) {
5398 ret.push({ selector: selectors[ i ], elem: cur, level: level });
5399 }
5400 }
5401
5402 cur = cur.parentNode;
5403 level++;
5404 }
5405
5406 return ret;
5407 }
5408
5409 // String
5410 var pos = POS.test( selectors ) || typeof selectors !== "string" ?
5411 jQuery( selectors, context || this.context ) :
5412 0;
5413
5414 for ( i = 0, l = this.length; i < l; i++ ) {
5415 cur = this[i];
5416
5417 while ( cur ) {
5418 if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) {
5419 ret.push( cur );
5420 break;
5421
5422 } else {
5423 cur = cur.parentNode;
5424 if ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) {
5425 break;
5426 }
5427 }
5428 }
5429 }
5430
5431 ret = ret.length > 1 ? jQuery.unique( ret ) : ret;
5432
5433 return this.pushStack( ret, "closest", selectors );
5434 },
5435
5436 // Determine the position of an element within
5437 // the matched set of elements
5438 index: function( elem ) {
5439
5440 // No argument, return index in parent
5441 if ( !elem ) {
5442 return ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1;
5443 }
5444
5445 // index in selector
5446 if ( typeof elem === "string" ) {
5447 return jQuery.inArray( this[0], jQuery( elem ) );
5448 }
5449
5450 // Locate the position of the desired element
5451 return jQuery.inArray(
5452 // If it receives a jQuery object, the first element is used
5453 elem.jquery ? elem[0] : elem, this );
5454 },
5455
5456 add: function( selector, context ) {
5457 var set = typeof selector === "string" ?
5458 jQuery( selector, context ) :
5459 jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ),
5460 all = jQuery.merge( this.get(), set );
5461
5462 return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ?
5463 all :
5464 jQuery.unique( all ) );
5465 },
5466
5467 andSelf: function() {
5468 return this.add( this.prevObject );
5469 }
5470 });
5471
5472 // A painfully simple check to see if an element is disconnected
5473 // from a document (should be improved, where feasible).
5474 function isDisconnected( node ) {
5475 return !node || !node.parentNode || node.parentNode.nodeType === 11;
5476 }
5477
5478 jQuery.each({
5479 parent: function( elem ) {
5480 var parent = elem.parentNode;
5481 return parent && parent.nodeType !== 11 ? parent : null;
5482 },
5483 parents: function( elem ) {
5484 return jQuery.dir( elem, "parentNode" );
5485 },
5486 parentsUntil: function( elem, i, until ) {
5487 return jQuery.dir( elem, "parentNode", until );
5488 },
5489 next: function( elem ) {
5490 return jQuery.nth( elem, 2, "nextSibling" );
5491 },
5492 prev: function( elem ) {
5493 return jQuery.nth( elem, 2, "previousSibling" );
5494 },
5495 nextAll: function( elem ) {
5496 return jQuery.dir( elem, "nextSibling" );
5497 },
5498 prevAll: function( elem ) {
5499 return jQuery.dir( elem, "previousSibling" );
5500 },
5501 nextUntil: function( elem, i, until ) {
5502 return jQuery.dir( elem, "nextSibling", until );
5503 },
5504 prevUntil: function( elem, i, until ) {
5505 return jQuery.dir( elem, "previousSibling", until );
5506 },
5507 siblings: function( elem ) {
5508 return jQuery.sibling( elem.parentNode.firstChild, elem );
5509 },
5510 children: function( elem ) {
5511 return jQuery.sibling( elem.firstChild );
5512 },
5513 contents: function( elem ) {
5514 return jQuery.nodeName( elem, "iframe" ) ?
5515 elem.contentDocument || elem.contentWindow.document :
5516 jQuery.makeArray( elem.childNodes );
5517 }
5518 }, function( name, fn ) {
5519 jQuery.fn[ name ] = function( until, selector ) {
5520 var ret = jQuery.map( this, fn, until );
5521
5522 if ( !runtil.test( name ) ) {
5523 selector = until;
5524 }
5525
5526 if ( selector && typeof selector === "string" ) {
5527 ret = jQuery.filter( selector, ret );
5528 }
5529
5530 ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret;
5531
5532 if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) {
5533 ret = ret.reverse();
5534 }
5535
5536 return this.pushStack( ret, name, slice.call( arguments ).join(",") );
5537 };
5538 });
5539
5540 jQuery.extend({
5541 filter: function( expr, elems, not ) {
5542 if ( not ) {
5543 expr = ":not(" + expr + ")";
5544 }
5545
5546 return elems.length === 1 ?
5547 jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :
5548 jQuery.find.matches(expr, elems);
5549 },
5550
5551 dir: function( elem, dir, until ) {
5552 var matched = [],
5553 cur = elem[ dir ];
5554
5555 while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {
5556 if ( cur.nodeType === 1 ) {
5557 matched.push( cur );
5558 }
5559 cur = cur[dir];
5560 }
5561 return matched;
5562 },
5563
5564 nth: function( cur, result, dir, elem ) {
5565 result = result || 1;
5566 var num = 0;
5567
5568 for ( ; cur; cur = cur[dir] ) {
5569 if ( cur.nodeType === 1 && ++num === result ) {
5570 break;
5571 }
5572 }
5573
5574 return cur;
5575 },
5576
5577 sibling: function( n, elem ) {
5578 var r = [];
5579
5580 for ( ; n; n = n.nextSibling ) {
5581 if ( n.nodeType === 1 && n !== elem ) {
5582 r.push( n );
5583 }
5584 }
5585
5586 return r;
5587 }
5588 });
5589
5590 // Implement the identical functionality for filter and not
5591 function winnow( elements, qualifier, keep ) {
5592
5593 // Can't pass null or undefined to indexOf in Firefox 4
5594 // Set to 0 to skip string check
5595 qualifier = qualifier || 0;
5596
5597 if ( jQuery.isFunction( qualifier ) ) {
5598 return jQuery.grep(elements, function( elem, i ) {
5599 var retVal = !!qualifier.call( elem, i, elem );
5600 return retVal === keep;
5601 });
5602
5603 } else if ( qualifier.nodeType ) {
5604 return jQuery.grep(elements, function( elem, i ) {
5605 return ( elem === qualifier ) === keep;
5606 });
5607
5608 } else if ( typeof qualifier === "string" ) {
5609 var filtered = jQuery.grep(elements, function( elem ) {
5610 return elem.nodeType === 1;
5611 });
5612
5613 if ( isSimple.test( qualifier ) ) {
5614 return jQuery.filter(qualifier, filtered, !keep);
5615 } else {
5616 qualifier = jQuery.filter( qualifier, filtered );
5617 }
5618 }
5619
5620 return jQuery.grep(elements, function( elem, i ) {
5621 return ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep;
5622 });
5623 }
5624
5625
5626
5627
5628 function createSafeFragment( document ) {
5629 var list = nodeNames.split( "|" ),
5630 safeFrag = document.createDocumentFragment();
5631
5632 if ( safeFrag.createElement ) {
5633 while ( list.length ) {
5634 safeFrag.createElement(
5635 list.pop()
5636 );
5637 }
5638 }
5639 return safeFrag;
5640 }
5641
5642 var nodeNames = "abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|footer|" +
5643 "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",
5644 rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g,
5645 rleadingWhitespace = /^\s+/,
5646 rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,
5647 rtagName = /<([\w:]+)/,
5648 rtbody = /<tbody/i,
5649 rhtml = /<|&#?\w+;/,
5650 rnoInnerhtml = /<(?:script|style)/i,
5651 rnocache = /<(?:script|object|embed|option|style)/i,
5652 rnoshimcache = new RegExp("<(?:" + nodeNames + ")", "i"),
5653 // checked="checked" or checked
5654 rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
5655 rscriptType = /\/(java|ecma)script/i,
5656 rcleanScript = /^\s*<!(?:\[CDATA\[|\-\-)/,
5657 wrapMap = {
5658 option: [ 1, "<select multiple='multiple'>", "</select>" ],
5659 legend: [ 1, "<fieldset>", "</fieldset>" ],
5660 thead: [ 1, "<table>", "</table>" ],
5661 tr: [ 2, "<table><tbody>", "</tbody></table>" ],
5662 td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
5663 col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ],
5664 area: [ 1, "<map>", "</map>" ],
5665 _default: [ 0, "", "" ]
5666 },
5667 safeFragment = createSafeFragment( document );
5668
5669 wrapMap.optgroup = wrapMap.option;
5670 wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
5671 wrapMap.th = wrapMap.td;
5672
5673 // IE can't serialize <link> and <script> tags normally
5674 if ( !jQuery.support.htmlSerialize ) {
5675 wrapMap._default = [ 1, "div<div>", "</div>" ];
5676 }
5677
5678 jQuery.fn.extend({
5679 text: function( text ) {
5680 if ( jQuery.isFunction(text) ) {
5681 return this.each(function(i) {
5682 var self = jQuery( this );
5683
5684 self.text( text.call(this, i, self.text()) );
5685 });
5686 }
5687
5688 if ( typeof text !== "object" && text !== undefined ) {
5689 return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );
5690 }
5691
5692 return jQuery.text( this );
5693 },
5694
5695 wrapAll: function( html ) {
5696 if ( jQuery.isFunction( html ) ) {
5697 return this.each(function(i) {
5698 jQuery(this).wrapAll( html.call(this, i) );
5699 });
5700 }
5701
5702 if ( this[0] ) {
5703 // The elements to wrap the target around
5704 var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);
5705
5706 if ( this[0].parentNode ) {
5707 wrap.insertBefore( this[0] );
5708 }
5709
5710 wrap.map(function() {
5711 var elem = this;
5712
5713 while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {
5714 elem = elem.firstChild;
5715 }
5716
5717 return elem;
5718 }).append( this );
5719 }
5720
5721 return this;
5722 },
5723
5724 wrapInner: function( html ) {
5725 if ( jQuery.isFunction( html ) ) {
5726 return this.each(function(i) {
5727 jQuery(this).wrapInner( html.call(this, i) );
5728 });
5729 }
5730
5731 return this.each(function() {
5732 var self = jQuery( this ),
5733 contents = self.contents();
5734
5735 if ( contents.length ) {
5736 contents.wrapAll( html );
5737
5738 } else {
5739 self.append( html );
5740 }
5741 });
5742 },
5743
5744 wrap: function( html ) {
5745 var isFunction = jQuery.isFunction( html );
5746
5747 return this.each(function(i) {
5748 jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );
5749 });
5750 },
5751
5752 unwrap: function() {
5753 return this.parent().each(function() {
5754 if ( !jQuery.nodeName( this, "body" ) ) {
5755 jQuery( this ).replaceWith( this.childNodes );
5756 }
5757 }).end();
5758 },
5759
5760 append: function() {
5761 return this.domManip(arguments, true, function( elem ) {
5762 if ( this.nodeType === 1 ) {
5763 this.appendChild( elem );
5764 }
5765 });
5766 },
5767
5768 prepend: function() {
5769 return this.domManip(arguments, true, function( elem ) {
5770 if ( this.nodeType === 1 ) {
5771 this.insertBefore( elem, this.firstChild );
5772 }
5773 });
5774 },
5775
5776 before: function() {
5777 if ( this[0] && this[0].parentNode ) {
5778 return this.domManip(arguments, false, function( elem ) {
5779 this.parentNode.insertBefore( elem, this );
5780 });
5781 } else if ( arguments.length ) {
5782 var set = jQuery.clean( arguments );
5783 set.push.apply( set, this.toArray() );
5784 return this.pushStack( set, "before", arguments );
5785 }
5786 },
5787
5788 after: function() {
5789 if ( this[0] && this[0].parentNode ) {
5790 return this.domManip(arguments, false, function( elem ) {
5791 this.parentNode.insertBefore( elem, this.nextSibling );
5792 });
5793 } else if ( arguments.length ) {
5794 var set = this.pushStack( this, "after", arguments );
5795 set.push.apply( set, jQuery.clean(arguments) );
5796 return set;
5797 }
5798 },
5799
5800 // keepData is for internal use only--do not document
5801 remove: function( selector, keepData ) {
5802 for ( var i = 0, elem; (elem = this[i]) != null; i++ ) {
5803 if ( !selector || jQuery.filter( selector, [ elem ] ).length ) {
5804 if ( !keepData && elem.nodeType === 1 ) {
5805 jQuery.cleanData( elem.getElementsByTagName("*") );
5806 jQuery.cleanData( [ elem ] );
5807 }
5808
5809 if ( elem.parentNode ) {
5810 elem.parentNode.removeChild( elem );
5811 }
5812 }
5813 }
5814
5815 return this;
5816 },
5817
5818 empty: function() {
5819 for ( var i = 0, elem; (elem = this[i]) != null; i++ ) {
5820 // Remove element nodes and prevent memory leaks
5821 if ( elem.nodeType === 1 ) {
5822 jQuery.cleanData( elem.getElementsByTagName("*") );
5823 }
5824
5825 // Remove any remaining nodes
5826 while ( elem.firstChild ) {
5827 elem.removeChild( elem.firstChild );
5828 }
5829 }
5830
5831 return this;
5832 },
5833
5834 clone: function( dataAndEvents, deepDataAndEvents ) {
5835 dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
5836 deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
5837
5838 return this.map( function () {
5839 return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
5840 });
5841 },
5842
5843 html: function( value ) {
5844 if ( value === undefined ) {
5845 return this[0] && this[0].nodeType === 1 ?
5846 this[0].innerHTML.replace(rinlinejQuery, "") :
5847 null;
5848
5849 // See if we can take a shortcut and just use innerHTML
5850 } else if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
5851 (jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value )) &&
5852 !wrapMap[ (rtagName.exec( value ) || ["", ""])[1].toLowerCase() ] ) {
5853
5854 value = value.replace(rxhtmlTag, "<$1></$2>");
5855
5856 try {
5857 for ( var i = 0, l = this.length; i < l; i++ ) {
5858 // Remove element nodes and prevent memory leaks
5859 if ( this[i].nodeType === 1 ) {
5860 jQuery.cleanData( this[i].getElementsByTagName("*") );
5861 this[i].innerHTML = value;
5862 }
5863 }
5864
5865 // If using innerHTML throws an exception, use the fallback method
5866 } catch(e) {
5867 this.empty().append( value );
5868 }
5869
5870 } else if ( jQuery.isFunction( value ) ) {
5871 this.each(function(i){
5872 var self = jQuery( this );
5873
5874 self.html( value.call(this, i, self.html()) );
5875 });
5876
5877 } else {
5878 this.empty().append( value );
5879 }
5880
5881 return this;
5882 },
5883
5884 replaceWith: function( value ) {
5885 if ( this[0] && this[0].parentNode ) {
5886 // Make sure that the elements are removed from the DOM before they are inserted
5887 // this can help fix replacing a parent with child elements
5888 if ( jQuery.isFunction( value ) ) {
5889 return this.each(function(i) {
5890 var self = jQuery(this), old = self.html();
5891 self.replaceWith( value.call( this, i, old ) );
5892 });
5893 }
5894
5895 if ( typeof value !== "string" ) {
5896 value = jQuery( value ).detach();
5897 }
5898
5899 return this.each(function() {
5900 var next = this.nextSibling,
5901 parent = this.parentNode;
5902
5903 jQuery( this ).remove();
5904
5905 if ( next ) {
5906 jQuery(next).before( value );
5907 } else {
5908 jQuery(parent).append( value );
5909 }
5910 });
5911 } else {
5912 return this.length ?
5913 this.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), "replaceWith", value ) :
5914 this;
5915 }
5916 },
5917
5918 detach: function( selector ) {
5919 return this.remove( selector, true );
5920 },
5921
5922 domManip: function( args, table, callback ) {
5923 var results, first, fragment, parent,
5924 value = args[0],
5925 scripts = [];
5926
5927 // We can't cloneNode fragments that contain checked, in WebKit
5928 if ( !jQuery.support.checkClone && arguments.length === 3 && typeof value === "string" && rchecked.test( value ) ) {
5929 return this.each(function() {
5930 jQuery(this).domManip( args, table, callback, true );
5931 });
5932 }
5933
5934 if ( jQuery.isFunction(value) ) {
5935 return this.each(function(i) {
5936 var self = jQuery(this);
5937 args[0] = value.call(this, i, table ? self.html() : undefined);
5938 self.domManip( args, table, callback );
5939 });
5940 }
5941
5942 if ( this[0] ) {
5943 parent = value && value.parentNode;
5944
5945 // If we're in a fragment, just use that instead of building a new one
5946 if ( jQuery.support.parentNode && parent && parent.nodeType === 11 && parent.childNodes.length === this.length ) {
5947 results = { fragment: parent };
5948
5949 } else {
5950 results = jQuery.buildFragment( args, this, scripts );
5951 }
5952
5953 fragment = results.fragment;
5954
5955 if ( fragment.childNodes.length === 1 ) {
5956 first = fragment = fragment.firstChild;
5957 } else {
5958 first = fragment.firstChild;
5959 }
5960
5961 if ( first ) {
5962 table = table && jQuery.nodeName( first, "tr" );
5963
5964 for ( var i = 0, l = this.length, lastIndex = l - 1; i < l; i++ ) {
5965 callback.call(
5966 table ?
5967 root(this[i], first) :
5968 this[i],
5969 // Make sure that we do not leak memory by inadvertently discarding
5970 // the original fragment (which might have attached data) instead of
5971 // using it; in addition, use the original fragment object for the last
5972 // item instead of first because it can end up being emptied incorrectly
5973 // in certain situations (Bug #8070).
5974 // Fragments from the fragment cache must always be cloned and never used
5975 // in place.
5976 results.cacheable || ( l > 1 && i < lastIndex ) ?
5977 jQuery.clone( fragment, true, true ) :
5978 fragment
5979 );
5980 }
5981 }
5982
5983 if ( scripts.length ) {
5984 jQuery.each( scripts, evalScript );
5985 }
5986 }
5987
5988 return this;
5989 }
5990 });
5991
5992 function root( elem, cur ) {
5993 return jQuery.nodeName(elem, "table") ?
5994 (elem.getElementsByTagName("tbody")[0] ||
5995 elem.appendChild(elem.ownerDocument.createElement("tbody"))) :
5996 elem;
5997 }
5998
5999 function cloneCopyEvent( src, dest ) {
6000
6001 if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {
6002 return;
6003 }
6004
6005 var type, i, l,
6006 oldData = jQuery._data( src ),
6007 curData = jQuery._data( dest, oldData ),
6008 events = oldData.events;
6009
6010 if ( events ) {
6011 delete curData.handle;
6012 curData.events = {};
6013
6014 for ( type in events ) {
6015 for ( i = 0, l = events[ type ].length; i < l; i++ ) {
6016 jQuery.event.add( dest, type + ( events[ type ][ i ].namespace ? "." : "" ) + events[ type ][ i ].namespace, events[ type ][ i ], events[ type ][ i ].data );
6017 }
6018 }
6019 }
6020
6021 // make the cloned public data object a copy from the original
6022 if ( curData.data ) {
6023 curData.data = jQuery.extend( {}, curData.data );
6024 }
6025 }
6026
6027 function cloneFixAttributes( src, dest ) {
6028 var nodeName;
6029
6030 // We do not need to do anything for non-Elements
6031 if ( dest.nodeType !== 1 ) {
6032 return;
6033 }
6034
6035 // clearAttributes removes the attributes, which we don't want,
6036 // but also removes the attachEvent events, which we *do* want
6037 if ( dest.clearAttributes ) {
6038 dest.clearAttributes();
6039 }
6040
6041 // mergeAttributes, in contrast, only merges back on the
6042 // original attributes, not the events
6043 if ( dest.mergeAttributes ) {
6044 dest.mergeAttributes( src );
6045 }
6046
6047 nodeName = dest.nodeName.toLowerCase();
6048
6049 // IE6-8 fail to clone children inside object elements that use
6050 // the proprietary classid attribute value (rather than the type
6051 // attribute) to identify the type of content to display
6052 if ( nodeName === "object" ) {
6053 dest.outerHTML = src.outerHTML;
6054
6055 } else if ( nodeName === "input" && (src.type === "checkbox" || src.type === "radio") ) {
6056 // IE6-8 fails to persist the checked state of a cloned checkbox
6057 // or radio button. Worse, IE6-7 fail to give the cloned element
6058 // a checked appearance if the defaultChecked value isn't also set
6059 if ( src.checked ) {
6060 dest.defaultChecked = dest.checked = src.checked;
6061 }
6062
6063 // IE6-7 get confused and end up setting the value of a cloned
6064 // checkbox/radio button to an empty string instead of "on"
6065 if ( dest.value !== src.value ) {
6066 dest.value = src.value;
6067 }
6068
6069 // IE6-8 fails to return the selected option to the default selected
6070 // state when cloning options
6071 } else if ( nodeName === "option" ) {
6072 dest.selected = src.defaultSelected;
6073
6074 // IE6-8 fails to set the defaultValue to the correct value when
6075 // cloning other types of input fields
6076 } else if ( nodeName === "input" || nodeName === "textarea" ) {
6077 dest.defaultValue = src.defaultValue;
6078 }
6079
6080 // Event data gets referenced instead of copied if the expando
6081 // gets copied too
6082 dest.removeAttribute( jQuery.expando );
6083 }
6084
6085 jQuery.buildFragment = function( args, nodes, scripts ) {
6086 var fragment, cacheable, cacheresults, doc,
6087 first = args[ 0 ];
6088
6089 // nodes may contain either an explicit document object,
6090 // a jQuery collection or context object.
6091 // If nodes[0] contains a valid object to assign to doc
6092 if ( nodes && nodes[0] ) {
6093 doc = nodes[0].ownerDocument || nodes[0];
6094 }
6095
6096 // Ensure that an attr object doesn't incorrectly stand in as a document object
6097 // Chrome and Firefox seem to allow this to occur and will throw exception
6098 // Fixes #8950
6099 if ( !doc.createDocumentFragment ) {
6100 doc = document;
6101 }
6102
6103 // Only cache "small" (1/2 KB) HTML strings that are associated with the main document
6104 // Cloning options loses the selected state, so don't cache them
6105 // IE 6 doesn't like it when you put <object> or <embed> elements in a fragment
6106 // Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache
6107 // Lastly, IE6,7,8 will not correctly reuse cached fragments that were created from unknown elems #10501
6108 if ( args.length === 1 && typeof first === "string" && first.length < 512 && doc === document &&
6109 first.charAt(0) === "<" && !rnocache.test( first ) &&
6110 (jQuery.support.checkClone || !rchecked.test( first )) &&
6111 (jQuery.support.html5Clone || !rnoshimcache.test( first )) ) {
6112
6113 cacheable = true;
6114
6115 cacheresults = jQuery.fragments[ first ];
6116 if ( cacheresults && cacheresults !== 1 ) {
6117 fragment = cacheresults;
6118 }
6119 }
6120
6121 if ( !fragment ) {
6122 fragment = doc.createDocumentFragment();
6123 jQuery.clean( args, doc, fragment, scripts );
6124 }
6125
6126 if ( cacheable ) {
6127 jQuery.fragments[ first ] = cacheresults ? fragment : 1;
6128 }
6129
6130 return { fragment: fragment, cacheable: cacheable };
6131 };
6132
6133 jQuery.fragments = {};
6134
6135 jQuery.each({
6136 appendTo: "append",
6137 prependTo: "prepend",
6138 insertBefore: "before",
6139 insertAfter: "after",
6140 replaceAll: "replaceWith"
6141 }, function( name, original ) {
6142 jQuery.fn[ name ] = function( selector ) {
6143 var ret = [],
6144 insert = jQuery( selector ),
6145 parent = this.length === 1 && this[0].parentNode;
6146
6147 if ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) {
6148 insert[ original ]( this[0] );
6149 return this;
6150
6151 } else {
6152 for ( var i = 0, l = insert.length; i < l; i++ ) {
6153 var elems = ( i > 0 ? this.clone(true) : this ).get();
6154 jQuery( insert[i] )[ original ]( elems );
6155 ret = ret.concat( elems );
6156 }
6157
6158 return this.pushStack( ret, name, insert.selector );
6159 }
6160 };
6161 });
6162
6163 function getAll( elem ) {
6164 if ( typeof elem.getElementsByTagName !== "undefined" ) {
6165 return elem.getElementsByTagName( "*" );
6166
6167 } else if ( typeof elem.querySelectorAll !== "undefined" ) {
6168 return elem.querySelectorAll( "*" );
6169
6170 } else {
6171 return [];
6172 }
6173 }
6174
6175 // Used in clean, fixes the defaultChecked property
6176 function fixDefaultChecked( elem ) {
6177 if ( elem.type === "checkbox" || elem.type === "radio" ) {
6178 elem.defaultChecked = elem.checked;
6179 }
6180 }
6181 // Finds all inputs and passes them to fixDefaultChecked
6182 function findInputs( elem ) {
6183 var nodeName = ( elem.nodeName || "" ).toLowerCase();
6184 if ( nodeName === "input" ) {
6185 fixDefaultChecked( elem );
6186 // Skip scripts, get other children
6187 } else if ( nodeName !== "script" && typeof elem.getElementsByTagName !== "undefined" ) {
6188 jQuery.grep( elem.getElementsByTagName("input"), fixDefaultChecked );
6189 }
6190 }
6191
6192 // Derived From: http://www.iecss.com/shimprove/javascript/shimprove.1-0-1.js
6193 function shimCloneNode( elem ) {
6194 var div = document.createElement( "div" );
6195 safeFragment.appendChild( div );
6196
6197 div.innerHTML = elem.outerHTML;
6198 return div.firstChild;
6199 }
6200
6201 jQuery.extend({
6202 clone: function( elem, dataAndEvents, deepDataAndEvents ) {
6203 var srcElements,
6204 destElements,
6205 i,
6206 // IE<=8 does not properly clone detached, unknown element nodes
6207 clone = jQuery.support.html5Clone || !rnoshimcache.test( "<" + elem.nodeName ) ?
6208 elem.cloneNode( true ) :
6209 shimCloneNode( elem );
6210
6211 if ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) &&
6212 (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {
6213 // IE copies events bound via attachEvent when using cloneNode.
6214 // Calling detachEvent on the clone will also remove the events
6215 // from the original. In order to get around this, we use some
6216 // proprietary methods to clear the events. Thanks to MooTools
6217 // guys for this hotness.
6218
6219 cloneFixAttributes( elem, clone );
6220
6221 // Using Sizzle here is crazy slow, so we use getElementsByTagName instead
6222 srcElements = getAll( elem );
6223 destElements = getAll( clone );
6224
6225 // Weird iteration because IE will replace the length property
6226 // with an element if you are cloning the body and one of the
6227 // elements on the page has a name or id of "length"
6228 for ( i = 0; srcElements[i]; ++i ) {
6229 // Ensure that the destination node is not null; Fixes #9587
6230 if ( destElements[i] ) {
6231 cloneFixAttributes( srcElements[i], destElements[i] );
6232 }
6233 }
6234 }
6235
6236 // Copy the events from the original to the clone
6237 if ( dataAndEvents ) {
6238 cloneCopyEvent( elem, clone );
6239
6240 if ( deepDataAndEvents ) {
6241 srcElements = getAll( elem );
6242 destElements = getAll( clone );
6243
6244 for ( i = 0; srcElements[i]; ++i ) {
6245 cloneCopyEvent( srcElements[i], destElements[i] );
6246 }
6247 }
6248 }
6249
6250 srcElements = destElements = null;
6251
6252 // Return the cloned set
6253 return clone;
6254 },
6255
6256 clean: function( elems, context, fragment, scripts ) {
6257 var checkScriptType;
6258
6259 context = context || document;
6260
6261 // !context.createElement fails in IE with an error but returns typeof 'object'
6262 if ( typeof context.createElement === "undefined" ) {
6263 context = context.ownerDocument || context[0] && context[0].ownerDocument || document;
6264 }
6265
6266 var ret = [], j;
6267
6268 for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
6269 if ( typeof elem === "number" ) {
6270 elem += "";
6271 }
6272
6273 if ( !elem ) {
6274 continue;
6275 }
6276
6277 // Convert html string into DOM nodes
6278 if ( typeof elem === "string" ) {
6279 if ( !rhtml.test( elem ) ) {
6280 elem = context.createTextNode( elem );
6281 } else {
6282 // Fix "XHTML"-style tags in all browsers
6283 elem = elem.replace(rxhtmlTag, "<$1></$2>");
6284
6285 // Trim whitespace, otherwise indexOf won't work as expected
6286 var tag = ( rtagName.exec( elem ) || ["", ""] )[1].toLowerCase(),
6287 wrap = wrapMap[ tag ] || wrapMap._default,
6288 depth = wrap[0],
6289 div = context.createElement("div");
6290
6291 // Append wrapper element to unknown element safe doc fragment
6292 if ( context === document ) {
6293 // Use the fragment we've already created for this document
6294 safeFragment.appendChild( div );
6295 } else {
6296 // Use a fragment created with the owner document
6297 createSafeFragment( context ).appendChild( div );
6298 }
6299
6300 // Go to html and back, then peel off extra wrappers
6301 div.innerHTML = wrap[1] + elem + wrap[2];
6302
6303 // Move to the right depth
6304 while ( depth-- ) {
6305 div = div.lastChild;
6306 }
6307
6308 // Remove IE's autoinserted <tbody> from table fragments
6309 if ( !jQuery.support.tbody ) {
6310
6311 // String was a <table>, *may* have spurious <tbody>
6312 var hasBody = rtbody.test(elem),
6313 tbody = tag === "table" && !hasBody ?
6314 div.firstChild && div.firstChild.childNodes :
6315
6316 // String was a bare <thead> or <tfoot>
6317 wrap[1] === "<table>" && !hasBody ?
6318 div.childNodes :
6319 [];
6320
6321 for ( j = tbody.length - 1; j >= 0 ; --j ) {
6322 if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length ) {
6323 tbody[ j ].parentNode.removeChild( tbody[ j ] );
6324 }
6325 }
6326 }
6327
6328 // IE completely kills leading whitespace when innerHTML is used
6329 if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {
6330 div.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild );
6331 }
6332
6333 elem = div.childNodes;
6334 }
6335 }
6336
6337 // Resets defaultChecked for any radios and checkboxes
6338 // about to be appended to the DOM in IE 6/7 (#8060)
6339 var len;
6340 if ( !jQuery.support.appendChecked ) {
6341 if ( elem[0] && typeof (len = elem.length) === "number" ) {
6342 for ( j = 0; j < len; j++ ) {
6343 findInputs( elem[j] );
6344 }
6345 } else {
6346 findInputs( elem );
6347 }
6348 }
6349
6350 if ( elem.nodeType ) {
6351 ret.push( elem );
6352 } else {
6353 ret = jQuery.merge( ret, elem );
6354 }
6355 }
6356
6357 if ( fragment ) {
6358 checkScriptType = function( elem ) {
6359 return !elem.type || rscriptType.test( elem.type );
6360 };
6361 for ( i = 0; ret[i]; i++ ) {
6362 if ( scripts && jQuery.nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) {
6363 scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] );
6364
6365 } else {
6366 if ( ret[i].nodeType === 1 ) {
6367 var jsTags = jQuery.grep( ret[i].getElementsByTagName( "script" ), checkScriptType );
6368
6369 ret.splice.apply( ret, [i + 1, 0].concat( jsTags ) );
6370 }
6371 fragment.appendChild( ret[i] );
6372 }
6373 }
6374 }
6375
6376 return ret;
6377 },
6378
6379 cleanData: function( elems ) {
6380 var data, id,
6381 cache = jQuery.cache,
6382 special = jQuery.event.special,
6383 deleteExpando = jQuery.support.deleteExpando;
6384
6385 for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
6386 if ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) {
6387 continue;
6388 }
6389
6390 id = elem[ jQuery.expando ];
6391
6392 if ( id ) {
6393 data = cache[ id ];
6394
6395 if ( data && data.events ) {
6396 for ( var type in data.events ) {
6397 if ( special[ type ] ) {
6398 jQuery.event.remove( elem, type );
6399
6400 // This is a shortcut to avoid jQuery.event.remove's overhead
6401 } else {
6402 jQuery.removeEvent( elem, type, data.handle );
6403 }
6404 }
6405
6406 // Null the DOM reference to avoid IE6/7/8 leak (#7054)
6407 if ( data.handle ) {
6408 data.handle.elem = null;
6409 }
6410 }
6411
6412 if ( deleteExpando ) {
6413 delete elem[ jQuery.expando ];
6414
6415 } else if ( elem.removeAttribute ) {
6416 elem.removeAttribute( jQuery.expando );
6417 }
6418
6419 delete cache[ id ];
6420 }
6421 }
6422 }
6423 });
6424
6425 function evalScript( i, elem ) {
6426 if ( elem.src ) {
6427 jQuery.ajax({
6428 url: elem.src,
6429 async: false,
6430 dataType: "script"
6431 });
6432 } else {
6433 jQuery.globalEval( ( elem.text || elem.textContent || elem.innerHTML || "" ).replace( rcleanScript, "/*$0*/" ) );
6434 }
6435
6436 if ( elem.parentNode ) {
6437 elem.parentNode.removeChild( elem );
6438 }
6439 }
6440
6441
6442
6443
6444 var ralpha = /alpha\([^)]*\)/i,
6445 ropacity = /opacity=([^)]*)/,
6446 // fixed for IE9, see #8346
6447 rupper = /([A-Z]|^ms)/g,
6448 rnumpx = /^-?\d+(?:px)?$/i,
6449 rnum = /^-?\d/,
6450 rrelNum = /^([\-+])=([\-+.\de]+)/,
6451
6452 cssShow = { position: "absolute", visibility: "hidden", display: "block" },
6453 cssWidth = [ "Left", "Right" ],
6454 cssHeight = [ "Top", "Bottom" ],
6455 curCSS,
6456
6457 getComputedStyle,
6458 currentStyle;
6459
6460 jQuery.fn.css = function( name, value ) {
6461 // Setting 'undefined' is a no-op
6462 if ( arguments.length === 2 && value === undefined ) {
6463 return this;
6464 }
6465
6466 return jQuery.access( this, name, value, true, function( elem, name, value ) {
6467 return value !== undefined ?
6468 jQuery.style( elem, name, value ) :
6469 jQuery.css( elem, name );
6470 });
6471 };
6472
6473 jQuery.extend({
6474 // Add in style property hooks for overriding the default
6475 // behavior of getting and setting a style property
6476 cssHooks: {
6477 opacity: {
6478 get: function( elem, computed ) {
6479 if ( computed ) {
6480 // We should always get a number back from opacity
6481 var ret = curCSS( elem, "opacity", "opacity" );
6482 return ret === "" ? "1" : ret;
6483
6484 } else {
6485 return elem.style.opacity;
6486 }
6487 }
6488 }
6489 },
6490
6491 // Exclude the following css properties to add px
6492 cssNumber: {
6493 "fillOpacity": true,
6494 "fontWeight": true,
6495 "lineHeight": true,
6496 "opacity": true,
6497 "orphans": true,
6498 "widows": true,
6499 "zIndex": true,
6500 "zoom": true
6501 },
6502
6503 // Add in properties whose names you wish to fix before
6504 // setting or getting the value
6505 cssProps: {
6506 // normalize float css property
6507 "float": jQuery.support.cssFloat ? "cssFloat" : "styleFloat"
6508 },
6509
6510 // Get and set the style property on a DOM Node
6511 style: function( elem, name, value, extra ) {
6512 // Don't set styles on text and comment nodes
6513 if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
6514 return;
6515 }
6516
6517 // Make sure that we're working with the right name
6518 var ret, type, origName = jQuery.camelCase( name ),
6519 style = elem.style, hooks = jQuery.cssHooks[ origName ];
6520
6521 name = jQuery.cssProps[ origName ] || origName;
6522
6523 // Check if we're setting a value
6524 if ( value !== undefined ) {
6525 type = typeof value;
6526
6527 // convert relative number strings (+= or -=) to relative numbers. #7345
6528 if ( type === "string" && (ret = rrelNum.exec( value )) ) {
6529 value = ( +( ret[1] + 1) * +ret[2] ) + parseFloat( jQuery.css( elem, name ) );
6530 // Fixes bug #9237
6531 type = "number";
6532 }
6533
6534 // Make sure that NaN and null values aren't set. See: #7116
6535 if ( value == null || type === "number" && isNaN( value ) ) {
6536 return;
6537 }
6538
6539 // If a number was passed in, add 'px' to the (except for certain CSS properties)
6540 if ( type === "number" && !jQuery.cssNumber[ origName ] ) {
6541 value += "px";
6542 }
6543
6544 // If a hook was provided, use that value, otherwise just set the specified value
6545 if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value )) !== undefined ) {
6546 // Wrapped to prevent IE from throwing errors when 'invalid' values are provided
6547 // Fixes bug #5509
6548 try {
6549 style[ name ] = value;
6550 } catch(e) {}
6551 }
6552
6553 } else {
6554 // If a hook was provided get the non-computed value from there
6555 if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {
6556 return ret;
6557 }
6558
6559 // Otherwise just get the value from the style object
6560 return style[ name ];
6561 }
6562 },
6563
6564 css: function( elem, name, extra ) {
6565 var ret, hooks;
6566
6567 // Make sure that we're working with the right name
6568 name = jQuery.camelCase( name );
6569 hooks = jQuery.cssHooks[ name ];
6570 name = jQuery.cssProps[ name ] || name;
6571
6572 // cssFloat needs a special treatment
6573 if ( name === "cssFloat" ) {
6574 name = "float";
6575 }
6576
6577 // If a hook was provided get the computed value from there
6578 if ( hooks && "get" in hooks && (ret = hooks.get( elem, true, extra )) !== undefined ) {
6579 return ret;
6580
6581 // Otherwise, if a way to get the computed value exists, use that
6582 } else if ( curCSS ) {
6583 return curCSS( elem, name );
6584 }
6585 },
6586
6587 // A method for quickly swapping in/out CSS properties to get correct calculations
6588 swap: function( elem, options, callback ) {
6589 var old = {};
6590
6591 // Remember the old values, and insert the new ones
6592 for ( var name in options ) {
6593 old[ name ] = elem.style[ name ];
6594 elem.style[ name ] = options[ name ];
6595 }
6596
6597 callback.call( elem );
6598
6599 // Revert the old values
6600 for ( name in options ) {
6601 elem.style[ name ] = old[ name ];
6602 }
6603 }
6604 });
6605
6606 // DEPRECATED, Use jQuery.css() instead
6607 jQuery.curCSS = jQuery.css;
6608
6609 jQuery.each(["height", "width"], function( i, name ) {
6610 jQuery.cssHooks[ name ] = {
6611 get: function( elem, computed, extra ) {
6612 var val;
6613
6614 if ( computed ) {
6615 if ( elem.offsetWidth !== 0 ) {
6616 return getWH( elem, name, extra );
6617 } else {
6618 jQuery.swap( elem, cssShow, function() {
6619 val = getWH( elem, name, extra );
6620 });
6621 }
6622
6623 return val;
6624 }
6625 },
6626
6627 set: function( elem, value ) {
6628 if ( rnumpx.test( value ) ) {
6629 // ignore negative width and height values #1599
6630 value = parseFloat( value );
6631
6632 if ( value >= 0 ) {
6633 return value + "px";
6634 }
6635
6636 } else {
6637 return value;
6638 }
6639 }
6640 };
6641 });
6642
6643 if ( !jQuery.support.opacity ) {
6644 jQuery.cssHooks.opacity = {
6645 get: function( elem, computed ) {
6646 // IE uses filters for opacity
6647 return ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "" ) ?
6648 ( parseFloat( RegExp.$1 ) / 100 ) + "" :
6649 computed ? "1" : "";
6650 },
6651
6652 set: function( elem, value ) {
6653 var style = elem.style,
6654 currentStyle = elem.currentStyle,
6655 opacity = jQuery.isNumeric( value ) ? "alpha(opacity=" + value * 100 + ")" : "",
6656 filter = currentStyle && currentStyle.filter || style.filter || "";
6657
6658 // IE has trouble with opacity if it does not have layout
6659 // Force it by setting the zoom level
6660 style.zoom = 1;
6661
6662 // if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652
6663 if ( value >= 1 && jQuery.trim( filter.replace( ralpha, "" ) ) === "" ) {
6664
6665 // Setting style.filter to null, "" & " " still leave "filter:" in the cssText
6666 // if "filter:" is present at all, clearType is disabled, we want to avoid this
6667 // style.removeAttribute is IE Only, but so apparently is this code path...
6668 style.removeAttribute( "filter" );
6669
6670 // if there there is no filter style applied in a css rule, we are done
6671 if ( currentStyle && !currentStyle.filter ) {
6672 return;
6673 }
6674 }
6675
6676 // otherwise, set new filter values
6677 style.filter = ralpha.test( filter ) ?
6678 filter.replace( ralpha, opacity ) :
6679 filter + " " + opacity;
6680 }
6681 };
6682 }
6683
6684 jQuery(function() {
6685 // This hook cannot be added until DOM ready because the support test
6686 // for it is not run until after DOM ready
6687 if ( !jQuery.support.reliableMarginRight ) {
6688 jQuery.cssHooks.marginRight = {
6689 get: function( elem, computed ) {
6690 // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
6691 // Work around by temporarily setting element display to inline-block
6692 var ret;
6693 jQuery.swap( elem, { "display": "inline-block" }, function() {
6694 if ( computed ) {
6695 ret = curCSS( elem, "margin-right", "marginRight" );
6696 } else {
6697 ret = elem.style.marginRight;
6698 }
6699 });
6700 return ret;
6701 }
6702 };
6703 }
6704 });
6705
6706 if ( document.defaultView && document.defaultView.getComputedStyle ) {
6707 getComputedStyle = function( elem, name ) {
6708 var ret, defaultView, computedStyle;
6709
6710 name = name.replace( rupper, "-$1" ).toLowerCase();
6711
6712 if ( (defaultView = elem.ownerDocument.defaultView) &&
6713 (computedStyle = defaultView.getComputedStyle( elem, null )) ) {
6714 ret = computedStyle.getPropertyValue( name );
6715 if ( ret === "" && !jQuery.contains( elem.ownerDocument.documentElement, elem ) ) {
6716 ret = jQuery.style( elem, name );
6717 }
6718 }
6719
6720 return ret;
6721 };
6722 }
6723
6724 if ( document.documentElement.currentStyle ) {
6725 currentStyle = function( elem, name ) {
6726 var left, rsLeft, uncomputed,
6727 ret = elem.currentStyle && elem.currentStyle[ name ],
6728 style = elem.style;
6729
6730 // Avoid setting ret to empty string here
6731 // so we don't default to auto
6732 if ( ret === null && style && (uncomputed = style[ name ]) ) {
6733 ret = uncomputed;
6734 }
6735
6736 // From the awesome hack by Dean Edwards
6737 // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
6738
6739 // If we're not dealing with a regular pixel number
6740 // but a number that has a weird ending, we need to convert it to pixels
6741 if ( !rnumpx.test( ret ) && rnum.test( ret ) ) {
6742
6743 // Remember the original values
6744 left = style.left;
6745 rsLeft = elem.runtimeStyle && elem.runtimeStyle.left;
6746
6747 // Put in the new values to get a computed value out
6748 if ( rsLeft ) {
6749 elem.runtimeStyle.left = elem.currentStyle.left;
6750 }
6751 style.left = name === "fontSize" ? "1em" : ( ret || 0 );
6752 ret = style.pixelLeft + "px";
6753
6754 // Revert the changed values
6755 style.left = left;
6756 if ( rsLeft ) {
6757 elem.runtimeStyle.left = rsLeft;
6758 }
6759 }
6760
6761 return ret === "" ? "auto" : ret;
6762 };
6763 }
6764
6765 curCSS = getComputedStyle || currentStyle;
6766
6767 function getWH( elem, name, extra ) {
6768
6769 // Start with offset property
6770 var val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
6771 which = name === "width" ? cssWidth : cssHeight,
6772 i = 0,
6773 len = which.length;
6774
6775 if ( val > 0 ) {
6776 if ( extra !== "border" ) {
6777 for ( ; i < len; i++ ) {
6778 if ( !extra ) {
6779 val -= parseFloat( jQuery.css( elem, "padding" + which[ i ] ) ) || 0;
6780 }
6781 if ( extra === "margin" ) {
6782 val += parseFloat( jQuery.css( elem, extra + which[ i ] ) ) || 0;
6783 } else {
6784 val -= parseFloat( jQuery.css( elem, "border" + which[ i ] + "Width" ) ) || 0;
6785 }
6786 }
6787 }
6788
6789 return val + "px";
6790 }
6791
6792 // Fall back to computed then uncomputed css if necessary
6793 val = curCSS( elem, name, name );
6794 if ( val < 0 || val == null ) {
6795 val = elem.style[ name ] || 0;
6796 }
6797 // Normalize "", auto, and prepare for extra
6798 val = parseFloat( val ) || 0;
6799
6800 // Add padding, border, margin
6801 if ( extra ) {
6802 for ( ; i < len; i++ ) {
6803 val += parseFloat( jQuery.css( elem, "padding" + which[ i ] ) ) || 0;
6804 if ( extra !== "padding" ) {
6805 val += parseFloat( jQuery.css( elem, "border" + which[ i ] + "Width" ) ) || 0;
6806 }
6807 if ( extra === "margin" ) {
6808 val += parseFloat( jQuery.css( elem, extra + which[ i ] ) ) || 0;
6809 }
6810 }
6811 }
6812
6813 return val + "px";
6814 }
6815
6816 if ( jQuery.expr && jQuery.expr.filters ) {
6817 jQuery.expr.filters.hidden = function( elem ) {
6818 var width = elem.offsetWidth,
6819 height = elem.offsetHeight;
6820
6821 return ( width === 0 && height === 0 ) || (!jQuery.support.reliableHiddenOffsets && ((elem.style && elem.style.display) || jQuery.css( elem, "display" )) === "none");
6822 };
6823
6824 jQuery.expr.filters.visible = function( elem ) {
6825 return !jQuery.expr.filters.hidden( elem );
6826 };
6827 }
6828
6829
6830
6831
6832 var r20 = /%20/g,
6833 rbracket = /\[\]$/,
6834 rCRLF = /\r?\n/g,
6835 rhash = /#.*$/,
6836 rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, // IE leaves an \r character at EOL
6837 rinput = /^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,
6838 // #7653, #8125, #8152: local protocol detection
6839 rlocalProtocol = /^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,
6840 rnoContent = /^(?:GET|HEAD)$/,
6841 rprotocol = /^\/\//,
6842 rquery = /\?/,
6843 rscript = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,
6844 rselectTextarea = /^(?:select|textarea)/i,
6845 rspacesAjax = /\s+/,
6846 rts = /([?&])_=[^&]*/,
6847 rurl = /^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,
6848
6849 // Keep a copy of the old load method
6850 _load = jQuery.fn.load,
6851
6852 /* Prefilters
6853 * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
6854 * 2) These are called:
6855 * - BEFORE asking for a transport
6856 * - AFTER param serialization (s.data is a string if s.processData is true)
6857 * 3) key is the dataType
6858 * 4) the catchall symbol "*" can be used
6859 * 5) execution will start with transport dataType and THEN continue down to "*" if needed
6860 */
6861 prefilters = {},
6862
6863 /* Transports bindings
6864 * 1) key is the dataType
6865 * 2) the catchall symbol "*" can be used
6866 * 3) selection will start with transport dataType and THEN go to "*" if needed
6867 */
6868 transports = {},
6869
6870 // Document location
6871 ajaxLocation,
6872
6873 // Document location segments
6874 ajaxLocParts,
6875
6876 // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
6877 allTypes = ["*/"] + ["*"];
6878
6879 // #8138, IE may throw an exception when accessing
6880 // a field from window.location if document.domain has been set
6881 try {
6882 ajaxLocation = location.href;
6883 } catch( e ) {
6884 // Use the href attribute of an A element
6885 // since IE will modify it given document.location
6886 ajaxLocation = document.createElement( "a" );
6887 ajaxLocation.href = "";
6888 ajaxLocation = ajaxLocation.href;
6889 }
6890
6891 // Segment location into parts
6892 ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];
6893
6894 // Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
6895 function addToPrefiltersOrTransports( structure ) {
6896
6897 // dataTypeExpression is optional and defaults to "*"
6898 return function( dataTypeExpression, func ) {
6899
6900 if ( typeof dataTypeExpression !== "string" ) {
6901 func = dataTypeExpression;
6902 dataTypeExpression = "*";
6903 }
6904
6905 if ( jQuery.isFunction( func ) ) {
6906 var dataTypes = dataTypeExpression.toLowerCase().split( rspacesAjax ),
6907 i = 0,
6908 length = dataTypes.length,
6909 dataType,
6910 list,
6911 placeBefore;
6912
6913 // For each dataType in the dataTypeExpression
6914 for ( ; i < length; i++ ) {
6915 dataType = dataTypes[ i ];
6916 // We control if we're asked to add before
6917 // any existing element
6918 placeBefore = /^\+/.test( dataType );
6919 if ( placeBefore ) {
6920 dataType = dataType.substr( 1 ) || "*";
6921 }
6922 list = structure[ dataType ] = structure[ dataType ] || [];
6923 // then we add to the structure accordingly
6924 list[ placeBefore ? "unshift" : "push" ]( func );
6925 }
6926 }
6927 };
6928 }
6929
6930 // Base inspection function for prefilters and transports
6931 function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR,
6932 dataType /* internal */, inspected /* internal */ ) {
6933
6934 dataType = dataType || options.dataTypes[ 0 ];
6935 inspected = inspected || {};
6936
6937 inspected[ dataType ] = true;
6938
6939 var list = structure[ dataType ],
6940 i = 0,
6941 length = list ? list.length : 0,
6942 executeOnly = ( structure === prefilters ),
6943 selection;
6944
6945 for ( ; i < length && ( executeOnly || !selection ); i++ ) {
6946 selection = list[ i ]( options, originalOptions, jqXHR );
6947 // If we got redirected to another dataType
6948 // we try there if executing only and not done already
6949 if ( typeof selection === "string" ) {
6950 if ( !executeOnly || inspected[ selection ] ) {
6951 selection = undefined;
6952 } else {
6953 options.dataTypes.unshift( selection );
6954 selection = inspectPrefiltersOrTransports(
6955 structure, options, originalOptions, jqXHR, selection, inspected );
6956 }
6957 }
6958 }
6959 // If we're only executing or nothing was selected
6960 // we try the catchall dataType if not done already
6961 if ( ( executeOnly || !selection ) && !inspected[ "*" ] ) {
6962 selection = inspectPrefiltersOrTransports(
6963 structure, options, originalOptions, jqXHR, "*", inspected );
6964 }
6965 // unnecessary when only executing (prefilters)
6966 // but it'll be ignored by the caller in that case
6967 return selection;
6968 }
6969
6970 // A special extend for ajax options
6971 // that takes "flat" options (not to be deep extended)
6972 // Fixes #9887
6973 function ajaxExtend( target, src ) {
6974 var key, deep,
6975 flatOptions = jQuery.ajaxSettings.flatOptions || {};
6976 for ( key in src ) {
6977 if ( src[ key ] !== undefined ) {
6978 ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ];
6979 }
6980 }
6981 if ( deep ) {
6982 jQuery.extend( true, target, deep );
6983 }
6984 }
6985
6986 jQuery.fn.extend({
6987 load: function( url, params, callback ) {
6988 if ( typeof url !== "string" && _load ) {
6989 return _load.apply( this, arguments );
6990
6991 // Don't do a request if no elements are being requested
6992 } else if ( !this.length ) {
6993 return this;
6994 }
6995
6996 var off = url.indexOf( " " );
6997 if ( off >= 0 ) {
6998 var selector = url.slice( off, url.length );
6999 url = url.slice( 0, off );
7000 }
7001
7002 // Default to a GET request
7003 var type = "GET";
7004
7005 // If the second parameter was provided
7006 if ( params ) {
7007 // If it's a function
7008 if ( jQuery.isFunction( params ) ) {
7009 // We assume that it's the callback
7010 callback = params;
7011 params = undefined;
7012
7013 // Otherwise, build a param string
7014 } else if ( typeof params === "object" ) {
7015 params = jQuery.param( params, jQuery.ajaxSettings.traditional );
7016 type = "POST";
7017 }
7018 }
7019
7020 var self = this;
7021
7022 // Request the remote document
7023 jQuery.ajax({
7024 url: url,
7025 type: type,
7026 dataType: "html",
7027 data: params,
7028 // Complete callback (responseText is used internally)
7029 complete: function( jqXHR, status, responseText ) {
7030 // Store the response as specified by the jqXHR object
7031 responseText = jqXHR.responseText;
7032 // If successful, inject the HTML into all the matched elements
7033 if ( jqXHR.isResolved() ) {
7034 // #4825: Get the actual response in case
7035 // a dataFilter is present in ajaxSettings
7036 jqXHR.done(function( r ) {
7037 responseText = r;
7038 });
7039 // See if a selector was specified
7040 self.html( selector ?
7041 // Create a dummy div to hold the results
7042 jQuery("<div>")
7043 // inject the contents of the document in, removing the scripts
7044 // to avoid any 'Permission Denied' errors in IE
7045 .append(responseText.replace(rscript, ""))
7046
7047 // Locate the specified elements
7048 .find(selector) :
7049
7050 // If not, just inject the full result
7051 responseText );
7052 }
7053
7054 if ( callback ) {
7055 self.each( callback, [ responseText, status, jqXHR ] );
7056 }
7057 }
7058 });
7059
7060 return this;
7061 },
7062
7063 serialize: function() {
7064 return jQuery.param( this.serializeArray() );
7065 },
7066
7067 serializeArray: function() {
7068 return this.map(function(){
7069 return this.elements ? jQuery.makeArray( this.elements ) : this;
7070 })
7071 .filter(function(){
7072 return this.name && !this.disabled &&
7073 ( this.checked || rselectTextarea.test( this.nodeName ) ||
7074 rinput.test( this.type ) );
7075 })
7076 .map(function( i, elem ){
7077 var val = jQuery( this ).val();
7078
7079 return val == null ?
7080 null :
7081 jQuery.isArray( val ) ?
7082 jQuery.map( val, function( val, i ){
7083 return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
7084 }) :
7085 { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
7086 }).get();
7087 }
7088 });
7089
7090 // Attach a bunch of functions for handling common AJAX events
7091 jQuery.each( "ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split( " " ), function( i, o ){
7092 jQuery.fn[ o ] = function( f ){
7093 return this.on( o, f );
7094 };
7095 });
7096
7097 jQuery.each( [ "get", "post" ], function( i, method ) {
7098 jQuery[ method ] = function( url, data, callback, type ) {
7099 // shift arguments if data argument was omitted
7100 if ( jQuery.isFunction( data ) ) {
7101 type = type || callback;
7102 callback = data;
7103 data = undefined;
7104 }
7105
7106 return jQuery.ajax({
7107 type: method,
7108 url: url,
7109 data: data,
7110 success: callback,
7111 dataType: type
7112 });
7113 };
7114 });
7115
7116 jQuery.extend({
7117
7118 getScript: function( url, callback ) {
7119 return jQuery.get( url, undefined, callback, "script" );
7120 },
7121
7122 getJSON: function( url, data, callback ) {
7123 return jQuery.get( url, data, callback, "json" );
7124 },
7125
7126 // Creates a full fledged settings object into target
7127 // with both ajaxSettings and settings fields.
7128 // If target is omitted, writes into ajaxSettings.
7129 ajaxSetup: function( target, settings ) {
7130 if ( settings ) {
7131 // Building a settings object
7132 ajaxExtend( target, jQuery.ajaxSettings );
7133 } else {
7134 // Extending ajaxSettings
7135 settings = target;
7136 target = jQuery.ajaxSettings;
7137 }
7138 ajaxExtend( target, settings );
7139 return target;
7140 },
7141
7142 ajaxSettings: {
7143 url: ajaxLocation,
7144 isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),
7145 global: true,
7146 type: "GET",
7147 contentType: "application/x-www-form-urlencoded",
7148 processData: true,
7149 async: true,
7150 /*
7151 timeout: 0,
7152 data: null,
7153 dataType: null,
7154 username: null,
7155 password: null,
7156 cache: null,
7157 traditional: false,
7158 headers: {},
7159 */
7160
7161 accepts: {
7162 xml: "application/xml, text/xml",
7163 html: "text/html",
7164 text: "text/plain",
7165 json: "application/json, text/javascript",
7166 "*": allTypes
7167 },
7168
7169 contents: {
7170 xml: /xml/,
7171 html: /html/,
7172 json: /json/
7173 },
7174
7175 responseFields: {
7176 xml: "responseXML",
7177 text: "responseText"
7178 },
7179
7180 // List of data converters
7181 // 1) key format is "source_type destination_type" (a single space in-between)
7182 // 2) the catchall symbol "*" can be used for source_type
7183 converters: {
7184
7185 // Convert anything to text
7186 "* text": window.String,
7187
7188 // Text to html (true = no transformation)
7189 "text html": true,
7190
7191 // Evaluate text as a json expression
7192 "text json": jQuery.parseJSON,
7193
7194 // Parse text as xml
7195 "text xml": jQuery.parseXML
7196 },
7197
7198 // For options that shouldn't be deep extended:
7199 // you can add your own custom options here if
7200 // and when you create one that shouldn't be
7201 // deep extended (see ajaxExtend)
7202 flatOptions: {
7203 context: true,
7204 url: true
7205 }
7206 },
7207
7208 ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
7209 ajaxTransport: addToPrefiltersOrTransports( transports ),
7210
7211 // Main method
7212 ajax: function( url, options ) {
7213
7214 // If url is an object, simulate pre-1.5 signature
7215 if ( typeof url === "object" ) {
7216 options = url;
7217 url = undefined;
7218 }
7219
7220 // Force options to be an object
7221 options = options || {};
7222
7223 var // Create the final options object
7224 s = jQuery.ajaxSetup( {}, options ),
7225 // Callbacks context
7226 callbackContext = s.context || s,
7227 // Context for global events
7228 // It's the callbackContext if one was provided in the options
7229 // and if it's a DOM node or a jQuery collection
7230 globalEventContext = callbackContext !== s &&
7231 ( callbackContext.nodeType || callbackContext instanceof jQuery ) ?
7232 jQuery( callbackContext ) : jQuery.event,
7233 // Deferreds
7234 deferred = jQuery.Deferred(),
7235 completeDeferred = jQuery.Callbacks( "once memory" ),
7236 // Status-dependent callbacks
7237 statusCode = s.statusCode || {},
7238 // ifModified key
7239 ifModifiedKey,
7240 // Headers (they are sent all at once)
7241 requestHeaders = {},
7242 requestHeadersNames = {},
7243 // Response headers
7244 responseHeadersString,
7245 responseHeaders,
7246 // transport
7247 transport,
7248 // timeout handle
7249 timeoutTimer,
7250 // Cross-domain detection vars
7251 parts,
7252 // The jqXHR state
7253 state = 0,
7254 // To know if global events are to be dispatched
7255 fireGlobals,
7256 // Loop variable
7257 i,
7258 // Fake xhr
7259 jqXHR = {
7260
7261 readyState: 0,
7262
7263 // Caches the header
7264 setRequestHeader: function( name, value ) {
7265 if ( !state ) {
7266 var lname = name.toLowerCase();
7267 name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;
7268 requestHeaders[ name ] = value;
7269 }
7270 return this;
7271 },
7272
7273 // Raw string
7274 getAllResponseHeaders: function() {
7275 return state === 2 ? responseHeadersString : null;
7276 },
7277
7278 // Builds headers hashtable if needed
7279 getResponseHeader: function( key ) {
7280 var match;
7281 if ( state === 2 ) {
7282 if ( !responseHeaders ) {
7283 responseHeaders = {};
7284 while( ( match = rheaders.exec( responseHeadersString ) ) ) {
7285 responseHeaders[ match[1].toLowerCase() ] = match[ 2 ];
7286 }
7287 }
7288 match = responseHeaders[ key.toLowerCase() ];
7289 }
7290 return match === undefined ? null : match;
7291 },
7292
7293 // Overrides response content-type header
7294 overrideMimeType: function( type ) {
7295 if ( !state ) {
7296 s.mimeType = type;
7297 }
7298 return this;
7299 },
7300
7301 // Cancel the request
7302 abort: function( statusText ) {
7303 statusText = statusText || "abort";
7304 if ( transport ) {
7305 transport.abort( statusText );
7306 }
7307 done( 0, statusText );
7308 return this;
7309 }
7310 };
7311
7312 // Callback for when everything is done
7313 // It is defined here because jslint complains if it is declared
7314 // at the end of the function (which would be more logical and readable)
7315 function done( status, nativeStatusText, responses, headers ) {
7316
7317 // Called once
7318 if ( state === 2 ) {
7319 return;
7320 }
7321
7322 // State is "done" now
7323 state = 2;
7324
7325 // Clear timeout if it exists
7326 if ( timeoutTimer ) {
7327 clearTimeout( timeoutTimer );
7328 }
7329
7330 // Dereference transport for early garbage collection
7331 // (no matter how long the jqXHR object will be used)
7332 transport = undefined;
7333
7334 // Cache response headers
7335 responseHeadersString = headers || "";
7336
7337 // Set readyState
7338 jqXHR.readyState = status > 0 ? 4 : 0;
7339
7340 var isSuccess,
7341 success,
7342 error,
7343 statusText = nativeStatusText,
7344 response = responses ? ajaxHandleResponses( s, jqXHR, responses ) : undefined,
7345 lastModified,
7346 etag;
7347
7348 // If successful, handle type chaining
7349 if ( status >= 200 && status < 300 || status === 304 ) {
7350
7351 // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
7352 if ( s.ifModified ) {
7353
7354 if ( ( lastModified = jqXHR.getResponseHeader( "Last-Modified" ) ) ) {
7355 jQuery.lastModified[ ifModifiedKey ] = lastModified;
7356 }
7357 if ( ( etag = jqXHR.getResponseHeader( "Etag" ) ) ) {
7358 jQuery.etag[ ifModifiedKey ] = etag;
7359 }
7360 }
7361
7362 // If not modified
7363 if ( status === 304 ) {
7364
7365 statusText = "notmodified";
7366 isSuccess = true;
7367
7368 // If we have data
7369 } else {
7370
7371 try {
7372 success = ajaxConvert( s, response );
7373 statusText = "success";
7374 isSuccess = true;
7375 } catch(e) {
7376 // We have a parsererror
7377 statusText = "parsererror";
7378 error = e;
7379 }
7380 }
7381 } else {
7382 // We extract error from statusText
7383 // then normalize statusText and status for non-aborts
7384 error = statusText;
7385 if ( !statusText || status ) {
7386 statusText = "error";
7387 if ( status < 0 ) {
7388 status = 0;
7389 }
7390 }
7391 }
7392
7393 // Set data for the fake xhr object
7394 jqXHR.status = status;
7395 jqXHR.statusText = "" + ( nativeStatusText || statusText );
7396
7397 // Success/Error
7398 if ( isSuccess ) {
7399 deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
7400 } else {
7401 deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
7402 }
7403
7404 // Status-dependent callbacks
7405 jqXHR.statusCode( statusCode );
7406 statusCode = undefined;
7407
7408 if ( fireGlobals ) {
7409 globalEventContext.trigger( "ajax" + ( isSuccess ? "Success" : "Error" ),
7410 [ jqXHR, s, isSuccess ? success : error ] );
7411 }
7412
7413 // Complete
7414 completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );
7415
7416 if ( fireGlobals ) {
7417 globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
7418 // Handle the global AJAX counter
7419 if ( !( --jQuery.active ) ) {
7420 jQuery.event.trigger( "ajaxStop" );
7421 }
7422 }
7423 }
7424
7425 // Attach deferreds
7426 deferred.promise( jqXHR );
7427 jqXHR.success = jqXHR.done;
7428 jqXHR.error = jqXHR.fail;
7429 jqXHR.complete = completeDeferred.add;
7430
7431 // Status-dependent callbacks
7432 jqXHR.statusCode = function( map ) {
7433 if ( map ) {
7434 var tmp;
7435 if ( state < 2 ) {
7436 for ( tmp in map ) {
7437 statusCode[ tmp ] = [ statusCode[tmp], map[tmp] ];
7438 }
7439 } else {
7440 tmp = map[ jqXHR.status ];
7441 jqXHR.then( tmp, tmp );
7442 }
7443 }
7444 return this;
7445 };
7446
7447 // Remove hash character (#7531: and string promotion)
7448 // Add protocol if not provided (#5866: IE7 issue with protocol-less urls)
7449 // We also use the url parameter if available
7450 s.url = ( ( url || s.url ) + "" ).replace( rhash, "" ).replace( rprotocol, ajaxLocParts[ 1 ] + "//" );
7451
7452 // Extract dataTypes list
7453 s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().split( rspacesAjax );
7454
7455 // Determine if a cross-domain request is in order
7456 if ( s.crossDomain == null ) {
7457 parts = rurl.exec( s.url.toLowerCase() );
7458 s.crossDomain = !!( parts &&
7459 ( parts[ 1 ] != ajaxLocParts[ 1 ] || parts[ 2 ] != ajaxLocParts[ 2 ] ||
7460 ( parts[ 3 ] || ( parts[ 1 ] === "http:" ? 80 : 443 ) ) !=
7461 ( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? 80 : 443 ) ) )
7462 );
7463 }
7464
7465 // Convert data if not already a string
7466 if ( s.data && s.processData && typeof s.data !== "string" ) {
7467 s.data = jQuery.param( s.data, s.traditional );
7468 }
7469
7470 // Apply prefilters
7471 inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
7472
7473 // If request was aborted inside a prefiler, stop there
7474 if ( state === 2 ) {
7475 return false;
7476 }
7477
7478 // We can fire global events as of now if asked to
7479 fireGlobals = s.global;
7480
7481 // Uppercase the type
7482 s.type = s.type.toUpperCase();
7483
7484 // Determine if request has content
7485 s.hasContent = !rnoContent.test( s.type );
7486
7487 // Watch for a new set of requests
7488 if ( fireGlobals && jQuery.active++ === 0 ) {
7489 jQuery.event.trigger( "ajaxStart" );
7490 }
7491
7492 // More options handling for requests with no content
7493 if ( !s.hasContent ) {
7494
7495 // If data is available, append data to url
7496 if ( s.data ) {
7497 s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.data;
7498 // #9682: remove data so that it's not used in an eventual retry
7499 delete s.data;
7500 }
7501
7502 // Get ifModifiedKey before adding the anti-cache parameter
7503 ifModifiedKey = s.url;
7504
7505 // Add anti-cache in url if needed
7506 if ( s.cache === false ) {
7507
7508 var ts = jQuery.now(),
7509 // try replacing _= if it is there
7510 ret = s.url.replace( rts, "$1_=" + ts );
7511
7512 // if nothing was replaced, add timestamp to the end
7513 s.url = ret + ( ( ret === s.url ) ? ( rquery.test( s.url ) ? "&" : "?" ) + "_=" + ts : "" );
7514 }
7515 }
7516
7517 // Set the correct header, if data is being sent
7518 if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
7519 jqXHR.setRequestHeader( "Content-Type", s.contentType );
7520 }
7521
7522 // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
7523 if ( s.ifModified ) {
7524 ifModifiedKey = ifModifiedKey || s.url;
7525 if ( jQuery.lastModified[ ifModifiedKey ] ) {
7526 jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ ifModifiedKey ] );
7527 }
7528 if ( jQuery.etag[ ifModifiedKey ] ) {
7529 jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ ifModifiedKey ] );
7530 }
7531 }
7532
7533 // Set the Accepts header for the server, depending on the dataType
7534 jqXHR.setRequestHeader(
7535 "Accept",
7536 s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?
7537 s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
7538 s.accepts[ "*" ]
7539 );
7540
7541 // Check for headers option
7542 for ( i in s.headers ) {
7543 jqXHR.setRequestHeader( i, s.headers[ i ] );
7544 }
7545
7546 // Allow custom headers/mimetypes and early abort
7547 if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {
7548 // Abort if not done already
7549 jqXHR.abort();
7550 return false;
7551
7552 }
7553
7554 // Install callbacks on deferreds
7555 for ( i in { success: 1, error: 1, complete: 1 } ) {
7556 jqXHR[ i ]( s[ i ] );
7557 }
7558
7559 // Get transport
7560 transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
7561
7562 // If no transport, we auto-abort
7563 if ( !transport ) {
7564 done( -1, "No Transport" );
7565 } else {
7566 jqXHR.readyState = 1;
7567 // Send global event
7568 if ( fireGlobals ) {
7569 globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
7570 }
7571 // Timeout
7572 if ( s.async && s.timeout > 0 ) {
7573 timeoutTimer = setTimeout( function(){
7574 jqXHR.abort( "timeout" );
7575 }, s.timeout );
7576 }
7577
7578 try {
7579 state = 1;
7580 transport.send( requestHeaders, done );
7581 } catch (e) {
7582 // Propagate exception as error if not done
7583 if ( state < 2 ) {
7584 done( -1, e );
7585 // Simply rethrow otherwise
7586 } else {
7587 throw e;
7588 }
7589 }
7590 }
7591
7592 return jqXHR;
7593 },
7594
7595 // Serialize an array of form elements or a set of
7596 // key/values into a query string
7597 param: function( a, traditional ) {
7598 var s = [],
7599 add = function( key, value ) {
7600 // If value is a function, invoke it and return its value
7601 value = jQuery.isFunction( value ) ? value() : value;
7602 s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
7603 };
7604
7605 // Set traditional to true for jQuery <= 1.3.2 behavior.
7606 if ( traditional === undefined ) {
7607 traditional = jQuery.ajaxSettings.traditional;
7608 }
7609
7610 // If an array was passed in, assume that it is an array of form elements.
7611 if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
7612 // Serialize the form elements
7613 jQuery.each( a, function() {
7614 add( this.name, this.value );
7615 });
7616
7617 } else {
7618 // If traditional, encode the "old" way (the way 1.3.2 or older
7619 // did it), otherwise encode params recursively.
7620 for ( var prefix in a ) {
7621 buildParams( prefix, a[ prefix ], traditional, add );
7622 }
7623 }
7624
7625 // Return the resulting serialization
7626 return s.join( "&" ).replace( r20, "+" );
7627 }
7628 });
7629
7630 function buildParams( prefix, obj, traditional, add ) {
7631 if ( jQuery.isArray( obj ) ) {
7632 // Serialize array item.
7633 jQuery.each( obj, function( i, v ) {
7634 if ( traditional || rbracket.test( prefix ) ) {
7635 // Treat each array item as a scalar.
7636 add( prefix, v );
7637
7638 } else {
7639 // If array item is non-scalar (array or object), encode its
7640 // numeric index to resolve deserialization ambiguity issues.
7641 // Note that rack (as of 1.0.0) can't currently deserialize
7642 // nested arrays properly, and attempting to do so may cause
7643 // a server error. Possible fixes are to modify rack's
7644 // deserialization algorithm or to provide an option or flag
7645 // to force array serialization to be shallow.
7646 buildParams( prefix + "[" + ( typeof v === "object" || jQuery.isArray(v) ? i : "" ) + "]", v, traditional, add );
7647 }
7648 });
7649
7650 } else if ( !traditional && obj != null && typeof obj === "object" ) {
7651 // Serialize object item.
7652 for ( var name in obj ) {
7653 buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
7654 }
7655
7656 } else {
7657 // Serialize scalar item.
7658 add( prefix, obj );
7659 }
7660 }
7661
7662 // This is still on the jQuery object... for now
7663 // Want to move this to jQuery.ajax some day
7664 jQuery.extend({
7665
7666 // Counter for holding the number of active queries
7667 active: 0,
7668
7669 // Last-Modified header cache for next request
7670 lastModified: {},
7671 etag: {}
7672
7673 });
7674
7675 /* Handles responses to an ajax request:
7676 * - sets all responseXXX fields accordingly
7677 * - finds the right dataType (mediates between content-type and expected dataType)
7678 * - returns the corresponding response
7679 */
7680 function ajaxHandleResponses( s, jqXHR, responses ) {
7681
7682 var contents = s.contents,
7683 dataTypes = s.dataTypes,
7684 responseFields = s.responseFields,
7685 ct,
7686 type,
7687 finalDataType,
7688 firstDataType;
7689
7690 // Fill responseXXX fields
7691 for ( type in responseFields ) {
7692 if ( type in responses ) {
7693 jqXHR[ responseFields[type] ] = responses[ type ];
7694 }
7695 }
7696
7697 // Remove auto dataType and get content-type in the process
7698 while( dataTypes[ 0 ] === "*" ) {
7699 dataTypes.shift();
7700 if ( ct === undefined ) {
7701 ct = s.mimeType || jqXHR.getResponseHeader( "content-type" );
7702 }
7703 }
7704
7705 // Check if we're dealing with a known content-type
7706 if ( ct ) {
7707 for ( type in contents ) {
7708 if ( contents[ type ] && contents[ type ].test( ct ) ) {
7709 dataTypes.unshift( type );
7710 break;
7711 }
7712 }
7713 }
7714
7715 // Check to see if we have a response for the expected dataType
7716 if ( dataTypes[ 0 ] in responses ) {
7717 finalDataType = dataTypes[ 0 ];
7718 } else {
7719 // Try convertible dataTypes
7720 for ( type in responses ) {
7721 if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) {
7722 finalDataType = type;
7723 break;
7724 }
7725 if ( !firstDataType ) {
7726 firstDataType = type;
7727 }
7728 }
7729 // Or just use first one
7730 finalDataType = finalDataType || firstDataType;
7731 }
7732
7733 // If we found a dataType
7734 // We add the dataType to the list if needed
7735 // and return the corresponding response
7736 if ( finalDataType ) {
7737 if ( finalDataType !== dataTypes[ 0 ] ) {
7738 dataTypes.unshift( finalDataType );
7739 }
7740 return responses[ finalDataType ];
7741 }
7742 }
7743
7744 // Chain conversions given the request and the original response
7745 function ajaxConvert( s, response ) {
7746
7747 // Apply the dataFilter if provided
7748 if ( s.dataFilter ) {
7749 response = s.dataFilter( response, s.dataType );
7750 }
7751
7752 var dataTypes = s.dataTypes,
7753 converters = {},
7754 i,
7755 key,
7756 length = dataTypes.length,
7757 tmp,
7758 // Current and previous dataTypes
7759 current = dataTypes[ 0 ],
7760 prev,
7761 // Conversion expression
7762 conversion,
7763 // Conversion function
7764 conv,
7765 // Conversion functions (transitive conversion)
7766 conv1,
7767 conv2;
7768
7769 // For each dataType in the chain
7770 for ( i = 1; i < length; i++ ) {
7771
7772 // Create converters map
7773 // with lowercased keys
7774 if ( i === 1 ) {
7775 for ( key in s.converters ) {
7776 if ( typeof key === "string" ) {
7777 converters[ key.toLowerCase() ] = s.converters[ key ];
7778 }
7779 }
7780 }
7781
7782 // Get the dataTypes
7783 prev = current;
7784 current = dataTypes[ i ];
7785
7786 // If current is auto dataType, update it to prev
7787 if ( current === "*" ) {
7788 current = prev;
7789 // If no auto and dataTypes are actually different
7790 } else if ( prev !== "*" && prev !== current ) {
7791
7792 // Get the converter
7793 conversion = prev + " " + current;
7794 conv = converters[ conversion ] || converters[ "* " + current ];
7795
7796 // If there is no direct converter, search transitively
7797 if ( !conv ) {
7798 conv2 = undefined;
7799 for ( conv1 in converters ) {
7800 tmp = conv1.split( " " );
7801 if ( tmp[ 0 ] === prev || tmp[ 0 ] === "*" ) {
7802 conv2 = converters[ tmp[1] + " " + current ];
7803 if ( conv2 ) {
7804 conv1 = converters[ conv1 ];
7805 if ( conv1 === true ) {
7806 conv = conv2;
7807 } else if ( conv2 === true ) {
7808 conv = conv1;
7809 }
7810 break;
7811 }
7812 }
7813 }
7814 }
7815 // If we found no converter, dispatch an error
7816 if ( !( conv || conv2 ) ) {
7817 jQuery.error( "No conversion from " + conversion.replace(" "," to ") );
7818 }
7819 // If found converter is not an equivalence
7820 if ( conv !== true ) {
7821 // Convert with 1 or 2 converters accordingly
7822 response = conv ? conv( response ) : conv2( conv1(response) );
7823 }
7824 }
7825 }
7826 return response;
7827 }
7828
7829
7830
7831
7832 var jsc = jQuery.now(),
7833 jsre = /(\=)\?(&|$)|\?\?/i;
7834
7835 // Default jsonp settings
7836 jQuery.ajaxSetup({
7837 jsonp: "callback",
7838 jsonpCallback: function() {
7839 return jQuery.expando + "_" + ( jsc++ );
7840 }
7841 });
7842
7843 // Detect, normalize options and install callbacks for jsonp requests
7844 jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
7845
7846 var inspectData = s.contentType === "application/x-www-form-urlencoded" &&
7847 ( typeof s.data === "string" );
7848
7849 if ( s.dataTypes[ 0 ] === "jsonp" ||
7850 s.jsonp !== false && ( jsre.test( s.url ) ||
7851 inspectData && jsre.test( s.data ) ) ) {
7852
7853 var responseContainer,
7854 jsonpCallback = s.jsonpCallback =
7855 jQuery.isFunction( s.jsonpCallback ) ? s.jsonpCallback() : s.jsonpCallback,
7856 previous = window[ jsonpCallback ],
7857 url = s.url,
7858 data = s.data,
7859 replace = "$1" + jsonpCallback + "$2";
7860
7861 if ( s.jsonp !== false ) {
7862 url = url.replace( jsre, replace );
7863 if ( s.url === url ) {
7864 if ( inspectData ) {
7865 data = data.replace( jsre, replace );
7866 }
7867 if ( s.data === data ) {
7868 // Add callback manually
7869 url += (/\?/.test( url ) ? "&" : "?") + s.jsonp + "=" + jsonpCallback;
7870 }
7871 }
7872 }
7873
7874 s.url = url;
7875 s.data = data;
7876
7877 // Install callback
7878 window[ jsonpCallback ] = function( response ) {
7879 responseContainer = [ response ];
7880 };
7881
7882 // Clean-up function
7883 jqXHR.always(function() {
7884 // Set callback back to previous value
7885 window[ jsonpCallback ] = previous;
7886 // Call if it was a function and we have a response
7887 if ( responseContainer && jQuery.isFunction( previous ) ) {
7888 window[ jsonpCallback ]( responseContainer[ 0 ] );
7889 }
7890 });
7891
7892 // Use data converter to retrieve json after script execution
7893 s.converters["script json"] = function() {
7894 if ( !responseContainer ) {
7895 jQuery.error( jsonpCallback + " was not called" );
7896 }
7897 return responseContainer[ 0 ];
7898 };
7899
7900 // force json dataType
7901 s.dataTypes[ 0 ] = "json";
7902
7903 // Delegate to script
7904 return "script";
7905 }
7906 });
7907
7908
7909
7910
7911 // Install script dataType
7912 jQuery.ajaxSetup({
7913 accepts: {
7914 script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
7915 },
7916 contents: {
7917 script: /javascript|ecmascript/
7918 },
7919 converters: {
7920 "text script": function( text ) {
7921 jQuery.globalEval( text );
7922 return text;
7923 }
7924 }
7925 });
7926
7927 // Handle cache's special case and global
7928 jQuery.ajaxPrefilter( "script", function( s ) {
7929 if ( s.cache === undefined ) {
7930 s.cache = false;
7931 }
7932 if ( s.crossDomain ) {
7933 s.type = "GET";
7934 s.global = false;
7935 }
7936 });
7937
7938 // Bind script tag hack transport
7939 jQuery.ajaxTransport( "script", function(s) {
7940
7941 // This transport only deals with cross domain requests
7942 if ( s.crossDomain ) {
7943
7944 var script,
7945 head = document.head || document.getElementsByTagName( "head" )[0] || document.documentElement;
7946
7947 return {
7948
7949 send: function( _, callback ) {
7950
7951 script = document.createElement( "script" );
7952
7953 script.async = "async";
7954
7955 if ( s.scriptCharset ) {
7956 script.charset = s.scriptCharset;
7957 }
7958
7959 script.src = s.url;
7960
7961 // Attach handlers for all browsers
7962 script.onload = script.onreadystatechange = function( _, isAbort ) {
7963
7964 if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {
7965
7966 // Handle memory leak in IE
7967 script.onload = script.onreadystatechange = null;
7968
7969 // Remove the script
7970 if ( head && script.parentNode ) {
7971 head.removeChild( script );
7972 }
7973
7974 // Dereference the script
7975 script = undefined;
7976
7977 // Callback if not abort
7978 if ( !isAbort ) {
7979 callback( 200, "success" );
7980 }
7981 }
7982 };
7983 // Use insertBefore instead of appendChild to circumvent an IE6 bug.
7984 // This arises when a base node is used (#2709 and #4378).
7985 head.insertBefore( script, head.firstChild );
7986 },
7987
7988 abort: function() {
7989 if ( script ) {
7990 script.onload( 0, 1 );
7991 }
7992 }
7993 };
7994 }
7995 });
7996
7997
7998
7999
8000 var // #5280: Internet Explorer will keep connections alive if we don't abort on unload
8001 xhrOnUnloadAbort = window.ActiveXObject ? function() {
8002 // Abort all pending requests
8003 for ( var key in xhrCallbacks ) {
8004 xhrCallbacks[ key ]( 0, 1 );
8005 }
8006 } : false,
8007 xhrId = 0,
8008 xhrCallbacks;
8009
8010 // Functions to create xhrs
8011 function createStandardXHR() {
8012 try {
8013 return new window.XMLHttpRequest();
8014 } catch( e ) {}
8015 }
8016
8017 function createActiveXHR() {
8018 try {
8019 return new window.ActiveXObject( "Microsoft.XMLHTTP" );
8020 } catch( e ) {}
8021 }
8022
8023 // Create the request object
8024 // (This is still attached to ajaxSettings for backward compatibility)
8025 jQuery.ajaxSettings.xhr = window.ActiveXObject ?
8026 /* Microsoft failed to properly
8027 * implement the XMLHttpRequest in IE7 (can't request local files),
8028 * so we use the ActiveXObject when it is available
8029 * Additionally XMLHttpRequest can be disabled in IE7/IE8 so
8030 * we need a fallback.
8031 */
8032 function() {
8033 return !this.isLocal && createStandardXHR() || createActiveXHR();
8034 } :
8035 // For all other browsers, use the standard XMLHttpRequest object
8036 createStandardXHR;
8037
8038 // Determine support properties
8039 (function( xhr ) {
8040 jQuery.extend( jQuery.support, {
8041 ajax: !!xhr,
8042 cors: !!xhr && ( "withCredentials" in xhr )
8043 });
8044 })( jQuery.ajaxSettings.xhr() );
8045
8046 // Create transport if the browser can provide an xhr
8047 if ( jQuery.support.ajax ) {
8048
8049 jQuery.ajaxTransport(function( s ) {
8050 // Cross domain only allowed if supported through XMLHttpRequest
8051 if ( !s.crossDomain || jQuery.support.cors ) {
8052
8053 var callback;
8054
8055 return {
8056 send: function( headers, complete ) {
8057
8058 // Get a new xhr
8059 var xhr = s.xhr(),
8060 handle,
8061 i;
8062
8063 // Open the socket
8064 // Passing null username, generates a login popup on Opera (#2865)
8065 if ( s.username ) {
8066 xhr.open( s.type, s.url, s.async, s.username, s.password );
8067 } else {
8068 xhr.open( s.type, s.url, s.async );
8069 }
8070
8071 // Apply custom fields if provided
8072 if ( s.xhrFields ) {
8073 for ( i in s.xhrFields ) {
8074 xhr[ i ] = s.xhrFields[ i ];
8075 }
8076 }
8077
8078 // Override mime type if needed
8079 if ( s.mimeType && xhr.overrideMimeType ) {
8080 xhr.overrideMimeType( s.mimeType );
8081 }
8082
8083 // X-Requested-With header
8084 // For cross-domain requests, seeing as conditions for a preflight are
8085 // akin to a jigsaw puzzle, we simply never set it to be sure.
8086 // (it can always be set on a per-request basis or even using ajaxSetup)
8087 // For same-domain requests, won't change header if already provided.
8088 if ( !s.crossDomain && !headers["X-Requested-With"] ) {
8089 headers[ "X-Requested-With" ] = "XMLHttpRequest";
8090 }
8091
8092 // Need an extra try/catch for cross domain requests in Firefox 3
8093 try {
8094 for ( i in headers ) {
8095 xhr.setRequestHeader( i, headers[ i ] );
8096 }
8097 } catch( _ ) {}
8098
8099 // Do send the request
8100 // This may raise an exception which is actually
8101 // handled in jQuery.ajax (so no try/catch here)
8102 xhr.send( ( s.hasContent && s.data ) || null );
8103
8104 // Listener
8105 callback = function( _, isAbort ) {
8106
8107 var status,
8108 statusText,
8109 responseHeaders,
8110 responses,
8111 xml;
8112
8113 // Firefox throws exceptions when accessing properties
8114 // of an xhr when a network error occured
8115 // http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE)
8116 try {
8117
8118 // Was never called and is aborted or complete
8119 if ( callback && ( isAbort || xhr.readyState === 4 ) ) {
8120
8121 // Only called once
8122 callback = undefined;
8123
8124 // Do not keep as active anymore
8125 if ( handle ) {
8126 xhr.onreadystatechange = jQuery.noop;
8127 if ( xhrOnUnloadAbort ) {
8128 delete xhrCallbacks[ handle ];
8129 }
8130 }
8131
8132 // If it's an abort
8133 if ( isAbort ) {
8134 // Abort it manually if needed
8135 if ( xhr.readyState !== 4 ) {
8136 xhr.abort();
8137 }
8138 } else {
8139 status = xhr.status;
8140 responseHeaders = xhr.getAllResponseHeaders();
8141 responses = {};
8142 xml = xhr.responseXML;
8143
8144 // Construct response list
8145 if ( xml && xml.documentElement /* #4958 */ ) {
8146 responses.xml = xml;
8147 }
8148 responses.text = xhr.responseText;
8149
8150 // Firefox throws an exception when accessing
8151 // statusText for faulty cross-domain requests
8152 try {
8153 statusText = xhr.statusText;
8154 } catch( e ) {
8155 // We normalize with Webkit giving an empty statusText
8156 statusText = "";
8157 }
8158
8159 // Filter status for non standard behaviors
8160
8161 // If the request is local and we have data: assume a success
8162 // (success with no data won't get notified, that's the best we
8163 // can do given current implementations)
8164 if ( !status && s.isLocal && !s.crossDomain ) {
8165 status = responses.text ? 200 : 404;
8166 // IE - #1450: sometimes returns 1223 when it should be 204
8167 } else if ( status === 1223 ) {
8168 status = 204;
8169 }
8170 }
8171 }
8172 } catch( firefoxAccessException ) {
8173 if ( !isAbort ) {
8174 complete( -1, firefoxAccessException );
8175 }
8176 }
8177
8178 // Call complete if needed
8179 if ( responses ) {
8180 complete( status, statusText, responses, responseHeaders );
8181 }
8182 };
8183
8184 // if we're in sync mode or it's in cache
8185 // and has been retrieved directly (IE6 & IE7)
8186 // we need to manually fire the callback
8187 if ( !s.async || xhr.readyState === 4 ) {
8188 callback();
8189 } else {
8190 handle = ++xhrId;
8191 if ( xhrOnUnloadAbort ) {
8192 // Create the active xhrs callbacks list if needed
8193 // and attach the unload handler
8194 if ( !xhrCallbacks ) {
8195 xhrCallbacks = {};
8196 jQuery( window ).unload( xhrOnUnloadAbort );
8197 }
8198 // Add to list of active xhrs callbacks
8199 xhrCallbacks[ handle ] = callback;
8200 }
8201 xhr.onreadystatechange = callback;
8202 }
8203 },
8204
8205 abort: function() {
8206 if ( callback ) {
8207 callback(0,1);
8208 }
8209 }
8210 };
8211 }
8212 });
8213 }
8214
8215
8216
8217
8218 var elemdisplay = {},
8219 iframe, iframeDoc,
8220 rfxtypes = /^(?:toggle|show|hide)$/,
8221 rfxnum = /^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,
8222 timerId,
8223 fxAttrs = [
8224 // height animations
8225 [ "height", "marginTop", "marginBottom", "paddingTop", "paddingBottom" ],
8226 // width animations
8227 [ "width", "marginLeft", "marginRight", "paddingLeft", "paddingRight" ],
8228 // opacity animations
8229 [ "opacity" ]
8230 ],
8231 fxNow;
8232
8233 jQuery.fn.extend({
8234 show: function( speed, easing, callback ) {
8235 var elem, display;
8236
8237 if ( speed || speed === 0 ) {
8238 return this.animate( genFx("show", 3), speed, easing, callback );
8239
8240 } else {
8241 for ( var i = 0, j = this.length; i < j; i++ ) {
8242 elem = this[ i ];
8243
8244 if ( elem.style ) {
8245 display = elem.style.display;
8246
8247 // Reset the inline display of this element to learn if it is
8248 // being hidden by cascaded rules or not
8249 if ( !jQuery._data(elem, "olddisplay") && display === "none" ) {
8250 display = elem.style.display = "";
8251 }
8252
8253 // Set elements which have been overridden with display: none
8254 // in a stylesheet to whatever the default browser style is
8255 // for such an element
8256 if ( display === "" && jQuery.css(elem, "display") === "none" ) {
8257 jQuery._data( elem, "olddisplay", defaultDisplay(elem.nodeName) );
8258 }
8259 }
8260 }
8261
8262 // Set the display of most of the elements in a second loop
8263 // to avoid the constant reflow
8264 for ( i = 0; i < j; i++ ) {
8265 elem = this[ i ];
8266
8267 if ( elem.style ) {
8268 display = elem.style.display;
8269
8270 if ( display === "" || display === "none" ) {
8271 elem.style.display = jQuery._data( elem, "olddisplay" ) || "";
8272 }
8273 }
8274 }
8275
8276 return this;
8277 }
8278 },
8279
8280 hide: function( speed, easing, callback ) {
8281 if ( speed || speed === 0 ) {
8282 return this.animate( genFx("hide", 3), speed, easing, callback);
8283
8284 } else {
8285 var elem, display,
8286 i = 0,
8287 j = this.length;
8288
8289 for ( ; i < j; i++ ) {
8290 elem = this[i];
8291 if ( elem.style ) {
8292 display = jQuery.css( elem, "display" );
8293
8294 if ( display !== "none" && !jQuery._data( elem, "olddisplay" ) ) {
8295 jQuery._data( elem, "olddisplay", display );
8296 }
8297 }
8298 }
8299
8300 // Set the display of the elements in a second loop
8301 // to avoid the constant reflow
8302 for ( i = 0; i < j; i++ ) {
8303 if ( this[i].style ) {
8304 this[i].style.display = "none";
8305 }
8306 }
8307
8308 return this;
8309 }
8310 },
8311
8312 // Save the old toggle function
8313 _toggle: jQuery.fn.toggle,
8314
8315 toggle: function( fn, fn2, callback ) {
8316 var bool = typeof fn === "boolean";
8317
8318 if ( jQuery.isFunction(fn) && jQuery.isFunction(fn2) ) {
8319 this._toggle.apply( this, arguments );
8320
8321 } else if ( fn == null || bool ) {
8322 this.each(function() {
8323 var state = bool ? fn : jQuery(this).is(":hidden");
8324 jQuery(this)[ state ? "show" : "hide" ]();
8325 });
8326
8327 } else {
8328 this.animate(genFx("toggle", 3), fn, fn2, callback);
8329 }
8330
8331 return this;
8332 },
8333
8334 fadeTo: function( speed, to, easing, callback ) {
8335 return this.filter(":hidden").css("opacity", 0).show().end()
8336 .animate({opacity: to}, speed, easing, callback);
8337 },
8338
8339 animate: function( prop, speed, easing, callback ) {
8340 var optall = jQuery.speed( speed, easing, callback );
8341
8342 if ( jQuery.isEmptyObject( prop ) ) {
8343 return this.each( optall.complete, [ false ] );
8344 }
8345
8346 // Do not change referenced properties as per-property easing will be lost
8347 prop = jQuery.extend( {}, prop );
8348
8349 function doAnimation() {
8350 // XXX 'this' does not always have a nodeName when running the
8351 // test suite
8352
8353 if ( optall.queue === false ) {
8354 jQuery._mark( this );
8355 }
8356
8357 var opt = jQuery.extend( {}, optall ),
8358 isElement = this.nodeType === 1,
8359 hidden = isElement && jQuery(this).is(":hidden"),
8360 name, val, p, e,
8361 parts, start, end, unit,
8362 method;
8363
8364 // will store per property easing and be used to determine when an animation is complete
8365 opt.animatedProperties = {};
8366
8367 for ( p in prop ) {
8368
8369 // property name normalization
8370 name = jQuery.camelCase( p );
8371 if ( p !== name ) {
8372 prop[ name ] = prop[ p ];
8373 delete prop[ p ];
8374 }
8375
8376 val = prop[ name ];
8377
8378 // easing resolution: per property > opt.specialEasing > opt.easing > 'swing' (default)
8379 if ( jQuery.isArray( val ) ) {
8380 opt.animatedProperties[ name ] = val[ 1 ];
8381 val = prop[ name ] = val[ 0 ];
8382 } else {
8383 opt.animatedProperties[ name ] = opt.specialEasing && opt.specialEasing[ name ] || opt.easing || 'swing';
8384 }
8385
8386 if ( val === "hide" && hidden || val === "show" && !hidden ) {
8387 return opt.complete.call( this );
8388 }
8389
8390 if ( isElement && ( name === "height" || name === "width" ) ) {
8391 // Make sure that nothing sneaks out
8392 // Record all 3 overflow attributes because IE does not
8393 // change the overflow attribute when overflowX and
8394 // overflowY are set to the same value
8395 opt.overflow = [ this.style.overflow, this.style.overflowX, this.style.overflowY ];
8396
8397 // Set display property to inline-block for height/width
8398 // animations on inline elements that are having width/height animated
8399 if ( jQuery.css( this, "display" ) === "inline" &&
8400 jQuery.css( this, "float" ) === "none" ) {
8401
8402 // inline-level elements accept inline-block;
8403 // block-level elements need to be inline with layout
8404 if ( !jQuery.support.inlineBlockNeedsLayout || defaultDisplay( this.nodeName ) === "inline" ) {
8405 this.style.display = "inline-block";
8406
8407 } else {
8408 this.style.zoom = 1;
8409 }
8410 }
8411 }
8412 }
8413
8414 if ( opt.overflow != null ) {
8415 this.style.overflow = "hidden";
8416 }
8417
8418 for ( p in prop ) {
8419 e = new jQuery.fx( this, opt, p );
8420 val = prop[ p ];
8421
8422 if ( rfxtypes.test( val ) ) {
8423
8424 // Tracks whether to show or hide based on private
8425 // data attached to the element
8426 method = jQuery._data( this, "toggle" + p ) || ( val === "toggle" ? hidden ? "show" : "hide" : 0 );
8427 if ( method ) {
8428 jQuery._data( this, "toggle" + p, method === "show" ? "hide" : "show" );
8429 e[ method ]();
8430 } else {
8431 e[ val ]();
8432 }
8433
8434 } else {
8435 parts = rfxnum.exec( val );
8436 start = e.cur();
8437
8438 if ( parts ) {
8439 end = parseFloat( parts[2] );
8440 unit = parts[3] || ( jQuery.cssNumber[ p ] ? "" : "px" );
8441
8442 // We need to compute starting value
8443 if ( unit !== "px" ) {
8444 jQuery.style( this, p, (end || 1) + unit);
8445 start = ( (end || 1) / e.cur() ) * start;
8446 jQuery.style( this, p, start + unit);
8447 }
8448
8449 // If a +=/-= token was provided, we're doing a relative animation
8450 if ( parts[1] ) {
8451 end = ( (parts[ 1 ] === "-=" ? -1 : 1) * end ) + start;
8452 }
8453
8454 e.custom( start, end, unit );
8455
8456 } else {
8457 e.custom( start, val, "" );
8458 }
8459 }
8460 }
8461
8462 // For JS strict compliance
8463 return true;
8464 }
8465
8466 return optall.queue === false ?
8467 this.each( doAnimation ) :
8468 this.queue( optall.queue, doAnimation );
8469 },
8470
8471 stop: function( type, clearQueue, gotoEnd ) {
8472 if ( typeof type !== "string" ) {
8473 gotoEnd = clearQueue;
8474 clearQueue = type;
8475 type = undefined;
8476 }
8477 if ( clearQueue && type !== false ) {
8478 this.queue( type || "fx", [] );
8479 }
8480
8481 return this.each(function() {
8482 var index,
8483 hadTimers = false,
8484 timers = jQuery.timers,
8485 data = jQuery._data( this );
8486
8487 // clear marker counters if we know they won't be
8488 if ( !gotoEnd ) {
8489 jQuery._unmark( true, this );
8490 }
8491
8492 function stopQueue( elem, data, index ) {
8493 var hooks = data[ index ];
8494 jQuery.removeData( elem, index, true );
8495 hooks.stop( gotoEnd );
8496 }
8497
8498 if ( type == null ) {
8499 for ( index in data ) {
8500 if ( data[ index ] && data[ index ].stop && index.indexOf(".run") === index.length - 4 ) {
8501 stopQueue( this, data, index );
8502 }
8503 }
8504 } else if ( data[ index = type + ".run" ] && data[ index ].stop ){
8505 stopQueue( this, data, index );
8506 }
8507
8508 for ( index = timers.length; index--; ) {
8509 if ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {
8510 if ( gotoEnd ) {
8511
8512 // force the next step to be the last
8513 timers[ index ]( true );
8514 } else {
8515 timers[ index ].saveState();
8516 }
8517 hadTimers = true;
8518 timers.splice( index, 1 );
8519 }
8520 }
8521
8522 // start the next in the queue if the last step wasn't forced
8523 // timers currently will call their complete callbacks, which will dequeue
8524 // but only if they were gotoEnd
8525 if ( !( gotoEnd && hadTimers ) ) {
8526 jQuery.dequeue( this, type );
8527 }
8528 });
8529 }
8530
8531 });
8532
8533 // Animations created synchronously will run synchronously
8534 function createFxNow() {
8535 setTimeout( clearFxNow, 0 );
8536 return ( fxNow = jQuery.now() );
8537 }
8538
8539 function clearFxNow() {
8540 fxNow = undefined;
8541 }
8542
8543 // Generate parameters to create a standard animation
8544 function genFx( type, num ) {
8545 var obj = {};
8546
8547 jQuery.each( fxAttrs.concat.apply([], fxAttrs.slice( 0, num )), function() {
8548 obj[ this ] = type;
8549 });
8550
8551 return obj;
8552 }
8553
8554 // Generate shortcuts for custom animations
8555 jQuery.each({
8556 slideDown: genFx( "show", 1 ),
8557 slideUp: genFx( "hide", 1 ),
8558 slideToggle: genFx( "toggle", 1 ),
8559 fadeIn: { opacity: "show" },
8560 fadeOut: { opacity: "hide" },
8561 fadeToggle: { opacity: "toggle" }
8562 }, function( name, props ) {
8563 jQuery.fn[ name ] = function( speed, easing, callback ) {
8564 return this.animate( props, speed, easing, callback );
8565 };
8566 });
8567
8568 jQuery.extend({
8569 speed: function( speed, easing, fn ) {
8570 var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
8571 complete: fn || !fn && easing ||
8572 jQuery.isFunction( speed ) && speed,
8573 duration: speed,
8574 easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing
8575 };
8576
8577 opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
8578 opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;
8579
8580 // normalize opt.queue - true/undefined/null -> "fx"
8581 if ( opt.queue == null || opt.queue === true ) {
8582 opt.queue = "fx";
8583 }
8584
8585 // Queueing
8586 opt.old = opt.complete;
8587
8588 opt.complete = function( noUnmark ) {
8589 if ( jQuery.isFunction( opt.old ) ) {
8590 opt.old.call( this );
8591 }
8592
8593 if ( opt.queue ) {
8594 jQuery.dequeue( this, opt.queue );
8595 } else if ( noUnmark !== false ) {
8596 jQuery._unmark( this );
8597 }
8598 };
8599
8600 return opt;
8601 },
8602
8603 easing: {
8604 linear: function( p, n, firstNum, diff ) {
8605 return firstNum + diff * p;
8606 },
8607 swing: function( p, n, firstNum, diff ) {
8608 return ( ( -Math.cos( p*Math.PI ) / 2 ) + 0.5 ) * diff + firstNum;
8609 }
8610 },
8611
8612 timers: [],
8613
8614 fx: function( elem, options, prop ) {
8615 this.options = options;
8616 this.elem = elem;
8617 this.prop = prop;
8618
8619 options.orig = options.orig || {};
8620 }
8621
8622 });
8623
8624 jQuery.fx.prototype = {
8625 // Simple function for setting a style value
8626 update: function() {
8627 if ( this.options.step ) {
8628 this.options.step.call( this.elem, this.now, this );
8629 }
8630
8631 ( jQuery.fx.step[ this.prop ] || jQuery.fx.step._default )( this );
8632 },
8633
8634 // Get the current size
8635 cur: function() {
8636 if ( this.elem[ this.prop ] != null && (!this.elem.style || this.elem.style[ this.prop ] == null) ) {
8637 return this.elem[ this.prop ];
8638 }
8639
8640 var parsed,
8641 r = jQuery.css( this.elem, this.prop );
8642 // Empty strings, null, undefined and "auto" are converted to 0,
8643 // complex values such as "rotate(1rad)" are returned as is,
8644 // simple values such as "10px" are parsed to Float.
8645 return isNaN( parsed = parseFloat( r ) ) ? !r || r === "auto" ? 0 : r : parsed;
8646 },
8647
8648 // Start an animation from one number to another
8649 custom: function( from, to, unit ) {
8650 var self = this,
8651 fx = jQuery.fx;
8652
8653 this.startTime = fxNow || createFxNow();
8654 this.end = to;
8655 this.now = this.start = from;
8656 this.pos = this.state = 0;
8657 this.unit = unit || this.unit || ( jQuery.cssNumber[ this.prop ] ? "" : "px" );
8658
8659 function t( gotoEnd ) {
8660 return self.step( gotoEnd );
8661 }
8662
8663 t.queue = this.options.queue;
8664 t.elem = this.elem;
8665 t.saveState = function() {
8666 if ( self.options.hide && jQuery._data( self.elem, "fxshow" + self.prop ) === undefined ) {
8667 jQuery._data( self.elem, "fxshow" + self.prop, self.start );
8668 }
8669 };
8670
8671 if ( t() && jQuery.timers.push(t) && !timerId ) {
8672 timerId = setInterval( fx.tick, fx.interval );
8673 }
8674 },
8675
8676 // Simple 'show' function
8677 show: function() {
8678 var dataShow = jQuery._data( this.elem, "fxshow" + this.prop );
8679
8680 // Remember where we started, so that we can go back to it later
8681 this.options.orig[ this.prop ] = dataShow || jQuery.style( this.elem, this.prop );
8682 this.options.show = true;
8683
8684 // Begin the animation
8685 // Make sure that we start at a small width/height to avoid any flash of content
8686 if ( dataShow !== undefined ) {
8687 // This show is picking up where a previous hide or show left off
8688 this.custom( this.cur(), dataShow );
8689 } else {
8690 this.custom( this.prop === "width" || this.prop === "height" ? 1 : 0, this.cur() );
8691 }
8692
8693 // Start by showing the element
8694 jQuery( this.elem ).show();
8695 },
8696
8697 // Simple 'hide' function
8698 hide: function() {
8699 // Remember where we started, so that we can go back to it later
8700 this.options.orig[ this.prop ] = jQuery._data( this.elem, "fxshow" + this.prop ) || jQuery.style( this.elem, this.prop );
8701 this.options.hide = true;
8702
8703 // Begin the animation
8704 this.custom( this.cur(), 0 );
8705 },
8706
8707 // Each step of an animation
8708 step: function( gotoEnd ) {
8709 var p, n, complete,
8710 t = fxNow || createFxNow(),
8711 done = true,
8712 elem = this.elem,
8713 options = this.options;
8714
8715 if ( gotoEnd || t >= options.duration + this.startTime ) {
8716 this.now = this.end;
8717 this.pos = this.state = 1;
8718 this.update();
8719
8720 options.animatedProperties[ this.prop ] = true;
8721
8722 for ( p in options.animatedProperties ) {
8723 if ( options.animatedProperties[ p ] !== true ) {
8724 done = false;
8725 }
8726 }
8727
8728 if ( done ) {
8729 // Reset the overflow
8730 if ( options.overflow != null && !jQuery.support.shrinkWrapBlocks ) {
8731
8732 jQuery.each( [ "", "X", "Y" ], function( index, value ) {
8733 elem.style[ "overflow" + value ] = options.overflow[ index ];
8734 });
8735 }
8736
8737 // Hide the element if the "hide" operation was done
8738 if ( options.hide ) {
8739 jQuery( elem ).hide();
8740 }
8741
8742 // Reset the properties, if the item has been hidden or shown
8743 if ( options.hide || options.show ) {
8744 for ( p in options.animatedProperties ) {
8745 jQuery.style( elem, p, options.orig[ p ] );
8746 jQuery.removeData( elem, "fxshow" + p, true );
8747 // Toggle data is no longer needed
8748 jQuery.removeData( elem, "toggle" + p, true );
8749 }
8750 }
8751
8752 // Execute the complete function
8753 // in the event that the complete function throws an exception
8754 // we must ensure it won't be called twice. #5684
8755
8756 complete = options.complete;
8757 if ( complete ) {
8758
8759 options.complete = false;
8760 complete.call( elem );
8761 }
8762 }
8763
8764 return false;
8765
8766 } else {
8767 // classical easing cannot be used with an Infinity duration
8768 if ( options.duration == Infinity ) {
8769 this.now = t;
8770 } else {
8771 n = t - this.startTime;
8772 this.state = n / options.duration;
8773
8774 // Perform the easing function, defaults to swing
8775 this.pos = jQuery.easing[ options.animatedProperties[this.prop] ]( this.state, n, 0, 1, options.duration );
8776 this.now = this.start + ( (this.end - this.start) * this.pos );
8777 }
8778 // Perform the next step of the animation
8779 this.update();
8780 }
8781
8782 return true;
8783 }
8784 };
8785
8786 jQuery.extend( jQuery.fx, {
8787 tick: function() {
8788 var timer,
8789 timers = jQuery.timers,
8790 i = 0;
8791
8792 for ( ; i < timers.length; i++ ) {
8793 timer = timers[ i ];
8794 // Checks the timer has not already been removed
8795 if ( !timer() && timers[ i ] === timer ) {
8796 timers.splice( i--, 1 );
8797 }
8798 }
8799
8800 if ( !timers.length ) {
8801 jQuery.fx.stop();
8802 }
8803 },
8804
8805 interval: 13,
8806
8807 stop: function() {
8808 clearInterval( timerId );
8809 timerId = null;
8810 },
8811
8812 speeds: {
8813 slow: 600,
8814 fast: 200,
8815 // Default speed
8816 _default: 400
8817 },
8818
8819 step: {
8820 opacity: function( fx ) {
8821 jQuery.style( fx.elem, "opacity", fx.now );
8822 },
8823
8824 _default: function( fx ) {
8825 if ( fx.elem.style && fx.elem.style[ fx.prop ] != null ) {
8826 fx.elem.style[ fx.prop ] = fx.now + fx.unit;
8827 } else {
8828 fx.elem[ fx.prop ] = fx.now;
8829 }
8830 }
8831 }
8832 });
8833
8834 // Adds width/height step functions
8835 // Do not set anything below 0
8836 jQuery.each([ "width", "height" ], function( i, prop ) {
8837 jQuery.fx.step[ prop ] = function( fx ) {
8838 jQuery.style( fx.elem, prop, Math.max(0, fx.now) + fx.unit );
8839 };
8840 });
8841
8842 if ( jQuery.expr && jQuery.expr.filters ) {
8843 jQuery.expr.filters.animated = function( elem ) {
8844 return jQuery.grep(jQuery.timers, function( fn ) {
8845 return elem === fn.elem;
8846 }).length;
8847 };
8848 }
8849
8850 // Try to restore the default display value of an element
8851 function defaultDisplay( nodeName ) {
8852
8853 if ( !elemdisplay[ nodeName ] ) {
8854
8855 var body = document.body,
8856 elem = jQuery( "<" + nodeName + ">" ).appendTo( body ),
8857 display = elem.css( "display" );
8858 elem.remove();
8859
8860 // If the simple way fails,
8861 // get element's real default display by attaching it to a temp iframe
8862 if ( display === "none" || display === "" ) {
8863 // No iframe to use yet, so create it
8864 if ( !iframe ) {
8865 iframe = document.createElement( "iframe" );
8866 iframe.frameBorder = iframe.width = iframe.height = 0;
8867 }
8868
8869 body.appendChild( iframe );
8870
8871 // Create a cacheable copy of the iframe document on first call.
8872 // IE and Opera will allow us to reuse the iframeDoc without re-writing the fake HTML
8873 // document to it; WebKit & Firefox won't allow reusing the iframe document.
8874 if ( !iframeDoc || !iframe.createElement ) {
8875 iframeDoc = ( iframe.contentWindow || iframe.contentDocument ).document;
8876 iframeDoc.write( ( document.compatMode === "CSS1Compat" ? "<!doctype html>" : "" ) + "<html><body>" );
8877 iframeDoc.close();
8878 }
8879
8880 elem = iframeDoc.createElement( nodeName );
8881
8882 iframeDoc.body.appendChild( elem );
8883
8884 display = jQuery.css( elem, "display" );
8885 body.removeChild( iframe );
8886 }
8887
8888 // Store the correct default display
8889 elemdisplay[ nodeName ] = display;
8890 }
8891
8892 return elemdisplay[ nodeName ];
8893 }
8894
8895
8896
8897
8898 var rtable = /^t(?:able|d|h)$/i,
8899 rroot = /^(?:body|html)$/i;
8900
8901 if ( "getBoundingClientRect" in document.documentElement ) {
8902 jQuery.fn.offset = function( options ) {
8903 var elem = this[0], box;
8904
8905 if ( options ) {
8906 return this.each(function( i ) {
8907 jQuery.offset.setOffset( this, options, i );
8908 });
8909 }
8910
8911 if ( !elem || !elem.ownerDocument ) {
8912 return null;
8913 }
8914
8915 if ( elem === elem.ownerDocument.body ) {
8916 return jQuery.offset.bodyOffset( elem );
8917 }
8918
8919 try {
8920 box = elem.getBoundingClientRect();
8921 } catch(e) {}
8922
8923 var doc = elem.ownerDocument,
8924 docElem = doc.documentElement;
8925
8926 // Make sure we're not dealing with a disconnected DOM node
8927 if ( !box || !jQuery.contains( docElem, elem ) ) {
8928 return box ? { top: box.top, left: box.left } : { top: 0, left: 0 };
8929 }
8930
8931 var body = doc.body,
8932 win = getWindow(doc),
8933 clientTop = docElem.clientTop || body.clientTop || 0,
8934 clientLeft = docElem.clientLeft || body.clientLeft || 0,
8935 scrollTop = win.pageYOffset || jQuery.support.boxModel && docElem.scrollTop || body.scrollTop,
8936 scrollLeft = win.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.scrollLeft,
8937 top = box.top + scrollTop - clientTop,
8938 left = box.left + scrollLeft - clientLeft;
8939
8940 return { top: top, left: left };
8941 };
8942
8943 } else {
8944 jQuery.fn.offset = function( options ) {
8945 var elem = this[0];
8946
8947 if ( options ) {
8948 return this.each(function( i ) {
8949 jQuery.offset.setOffset( this, options, i );
8950 });
8951 }
8952
8953 if ( !elem || !elem.ownerDocument ) {
8954 return null;
8955 }
8956
8957 if ( elem === elem.ownerDocument.body ) {
8958 return jQuery.offset.bodyOffset( elem );
8959 }
8960
8961 var computedStyle,
8962 offsetParent = elem.offsetParent,
8963 prevOffsetParent = elem,
8964 doc = elem.ownerDocument,
8965 docElem = doc.documentElement,
8966 body = doc.body,
8967 defaultView = doc.defaultView,
8968 prevComputedStyle = defaultView ? defaultView.getComputedStyle( elem, null ) : elem.currentStyle,
8969 top = elem.offsetTop,
8970 left = elem.offsetLeft;
8971
8972 while ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) {
8973 if ( jQuery.support.fixedPosition && prevComputedStyle.position === "fixed" ) {
8974 break;
8975 }
8976
8977 computedStyle = defaultView ? defaultView.getComputedStyle(elem, null) : elem.currentStyle;
8978 top -= elem.scrollTop;
8979 left -= elem.scrollLeft;
8980
8981 if ( elem === offsetParent ) {
8982 top += elem.offsetTop;
8983 left += elem.offsetLeft;
8984
8985 if ( jQuery.support.doesNotAddBorder && !(jQuery.support.doesAddBorderForTableAndCells && rtable.test(elem.nodeName)) ) {
8986 top += parseFloat( computedStyle.borderTopWidth ) || 0;
8987 left += parseFloat( computedStyle.borderLeftWidth ) || 0;
8988 }
8989
8990 prevOffsetParent = offsetParent;
8991 offsetParent = elem.offsetParent;
8992 }
8993
8994 if ( jQuery.support.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== "visible" ) {
8995 top += parseFloat( computedStyle.borderTopWidth ) || 0;
8996 left += parseFloat( computedStyle.borderLeftWidth ) || 0;
8997 }
8998
8999 prevComputedStyle = computedStyle;
9000 }
9001
9002 if ( prevComputedStyle.position === "relative" || prevComputedStyle.position === "static" ) {
9003 top += body.offsetTop;
9004 left += body.offsetLeft;
9005 }
9006
9007 if ( jQuery.support.fixedPosition && prevComputedStyle.position === "fixed" ) {
9008 top += Math.max( docElem.scrollTop, body.scrollTop );
9009 left += Math.max( docElem.scrollLeft, body.scrollLeft );
9010 }
9011
9012 return { top: top, left: left };
9013 };
9014 }
9015
9016 jQuery.offset = {
9017
9018 bodyOffset: function( body ) {
9019 var top = body.offsetTop,
9020 left = body.offsetLeft;
9021
9022 if ( jQuery.support.doesNotIncludeMarginInBodyOffset ) {
9023 top += parseFloat( jQuery.css(body, "marginTop") ) || 0;
9024 left += parseFloat( jQuery.css(body, "marginLeft") ) || 0;
9025 }
9026
9027 return { top: top, left: left };
9028 },
9029
9030 setOffset: function( elem, options, i ) {
9031 var position = jQuery.css( elem, "position" );
9032
9033 // set position first, in-case top/left are set even on static elem
9034 if ( position === "static" ) {
9035 elem.style.position = "relative";
9036 }
9037
9038 var curElem = jQuery( elem ),
9039 curOffset = curElem.offset(),
9040 curCSSTop = jQuery.css( elem, "top" ),
9041 curCSSLeft = jQuery.css( elem, "left" ),
9042 calculatePosition = ( position === "absolute" || position === "fixed" ) && jQuery.inArray("auto", [curCSSTop, curCSSLeft]) > -1,
9043 props = {}, curPosition = {}, curTop, curLeft;
9044
9045 // need to be able to calculate position if either top or left is auto and position is either absolute or fixed
9046 if ( calculatePosition ) {
9047 curPosition = curElem.position();
9048 curTop = curPosition.top;
9049 curLeft = curPosition.left;
9050 } else {
9051 curTop = parseFloat( curCSSTop ) || 0;
9052 curLeft = parseFloat( curCSSLeft ) || 0;
9053 }
9054
9055 if ( jQuery.isFunction( options ) ) {
9056 options = options.call( elem, i, curOffset );
9057 }
9058
9059 if ( options.top != null ) {
9060 props.top = ( options.top - curOffset.top ) + curTop;
9061 }
9062 if ( options.left != null ) {
9063 props.left = ( options.left - curOffset.left ) + curLeft;
9064 }
9065
9066 if ( "using" in options ) {
9067 options.using.call( elem, props );
9068 } else {
9069 curElem.css( props );
9070 }
9071 }
9072 };
9073
9074
9075 jQuery.fn.extend({
9076
9077 position: function() {
9078 if ( !this[0] ) {
9079 return null;
9080 }
9081
9082 var elem = this[0],
9083
9084 // Get *real* offsetParent
9085 offsetParent = this.offsetParent(),
9086
9087 // Get correct offsets
9088 offset = this.offset(),
9089 parentOffset = rroot.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset();
9090
9091 // Subtract element margins
9092 // note: when an element has margin: auto the offsetLeft and marginLeft
9093 // are the same in Safari causing offset.left to incorrectly be 0
9094 offset.top -= parseFloat( jQuery.css(elem, "marginTop") ) || 0;
9095 offset.left -= parseFloat( jQuery.css(elem, "marginLeft") ) || 0;
9096
9097 // Add offsetParent borders
9098 parentOffset.top += parseFloat( jQuery.css(offsetParent[0], "borderTopWidth") ) || 0;
9099 parentOffset.left += parseFloat( jQuery.css(offsetParent[0], "borderLeftWidth") ) || 0;
9100
9101 // Subtract the two offsets
9102 return {
9103 top: offset.top - parentOffset.top,
9104 left: offset.left - parentOffset.left
9105 };
9106 },
9107
9108 offsetParent: function() {
9109 return this.map(function() {
9110 var offsetParent = this.offsetParent || document.body;
9111 while ( offsetParent && (!rroot.test(offsetParent.nodeName) && jQuery.css(offsetParent, "position") === "static") ) {
9112 offsetParent = offsetParent.offsetParent;
9113 }
9114 return offsetParent;
9115 });
9116 }
9117 });
9118
9119
9120 // Create scrollLeft and scrollTop methods
9121 jQuery.each( ["Left", "Top"], function( i, name ) {
9122 var method = "scroll" + name;
9123
9124 jQuery.fn[ method ] = function( val ) {
9125 var elem, win;
9126
9127 if ( val === undefined ) {
9128 elem = this[ 0 ];
9129
9130 if ( !elem ) {
9131 return null;
9132 }
9133
9134 win = getWindow( elem );
9135
9136 // Return the scroll offset
9137 return win ? ("pageXOffset" in win) ? win[ i ? "pageYOffset" : "pageXOffset" ] :
9138 jQuery.support.boxModel && win.document.documentElement[ method ] ||
9139 win.document.body[ method ] :
9140 elem[ method ];
9141 }
9142
9143 // Set the scroll offset
9144 return this.each(function() {
9145 win = getWindow( this );
9146
9147 if ( win ) {
9148 win.scrollTo(
9149 !i ? val : jQuery( win ).scrollLeft(),
9150 i ? val : jQuery( win ).scrollTop()
9151 );
9152
9153 } else {
9154 this[ method ] = val;
9155 }
9156 });
9157 };
9158 });
9159
9160 function getWindow( elem ) {
9161 return jQuery.isWindow( elem ) ?
9162 elem :
9163 elem.nodeType === 9 ?
9164 elem.defaultView || elem.parentWindow :
9165 false;
9166 }
9167
9168
9169
9170
9171 // Create width, height, innerHeight, innerWidth, outerHeight and outerWidth methods
9172 jQuery.each([ "Height", "Width" ], function( i, name ) {
9173
9174 var type = name.toLowerCase();
9175
9176 // innerHeight and innerWidth
9177 jQuery.fn[ "inner" + name ] = function() {
9178 var elem = this[0];
9179 return elem ?
9180 elem.style ?
9181 parseFloat( jQuery.css( elem, type, "padding" ) ) :
9182 this[ type ]() :
9183 null;
9184 };
9185
9186 // outerHeight and outerWidth
9187 jQuery.fn[ "outer" + name ] = function( margin ) {
9188 var elem = this[0];
9189 return elem ?
9190 elem.style ?
9191 parseFloat( jQuery.css( elem, type, margin ? "margin" : "border" ) ) :
9192 this[ type ]() :
9193 null;
9194 };
9195
9196 jQuery.fn[ type ] = function( size ) {
9197 // Get window width or height
9198 var elem = this[0];
9199 if ( !elem ) {
9200 return size == null ? null : this;
9201 }
9202
9203 if ( jQuery.isFunction( size ) ) {
9204 return this.each(function( i ) {
9205 var self = jQuery( this );
9206 self[ type ]( size.call( this, i, self[ type ]() ) );
9207 });
9208 }
9209
9210 if ( jQuery.isWindow( elem ) ) {
9211 // Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode
9212 // 3rd condition allows Nokia support, as it supports the docElem prop but not CSS1Compat
9213 var docElemProp = elem.document.documentElement[ "client" + name ],
9214 body = elem.document.body;
9215 return elem.document.compatMode === "CSS1Compat" && docElemProp ||
9216 body && body[ "client" + name ] || docElemProp;
9217
9218 // Get document width or height
9219 } else if ( elem.nodeType === 9 ) {
9220 // Either scroll[Width/Height] or offset[Width/Height], whichever is greater
9221 return Math.max(
9222 elem.documentElement["client" + name],
9223 elem.body["scroll" + name], elem.documentElement["scroll" + name],
9224 elem.body["offset" + name], elem.documentElement["offset" + name]
9225 );
9226
9227 // Get or set width or height on the element
9228 } else if ( size === undefined ) {
9229 var orig = jQuery.css( elem, type ),
9230 ret = parseFloat( orig );
9231
9232 return jQuery.isNumeric( ret ) ? ret : orig;
9233
9234 // Set the width or height on the element (default to pixels if value is unitless)
9235 } else {
9236 return this.css( type, typeof size === "string" ? size : size + "px" );
9237 }
9238 };
9239
9240 });
9241
9242
9243
9244
9245 // Expose jQuery to the global object
9246 window.jQuery = window.$ = jQuery;
9247
9248 // Expose jQuery as an AMD module, but only for AMD loaders that
9249 // understand the issues with loading multiple versions of jQuery
9250 // in a page that all might call define(). The loader will indicate
9251 // they have special allowances for multiple jQuery versions by
9252 // specifying define.amd.jQuery = true. Register as a named module,
9253 // since jQuery can be concatenated with other files that may use define,
9254 // but not use a proper concatenation script that understands anonymous
9255 // AMD modules. A named AMD is safest and most robust way to register.
9256 // Lowercase jquery is used because AMD module names are derived from
9257 // file names, and jQuery is normally delivered in a lowercase file name.
9258 // Do this after creating the global so that if an AMD module wants to call
9259 // noConflict to hide this version of jQuery, it will work.
9260 if ( typeof define === "function" && define.amd && define.amd.jQuery ) {
9261 define( "jquery", [], function () { return jQuery; } );
9262 }
9263
9264
9265
9266 })( window );
This diff has been collapsed as it changes many lines, (609 lines changed) Show them Hide them
@@ -1,609 +0,0
1 /*
2 * jQuery UI CSS Framework @VERSION
3 *
4 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
5 * Dual licensed under the MIT or GPL Version 2 licenses.
6 * http://jquery.org/license
7 *
8 * http://docs.jquery.com/UI/Theming/API
9 */
10
11 /* Layout helpers
12 ----------------------------------*/
13 .ui-helper-hidden { display: none; }
14 .ui-helper-hidden-accessible { position: absolute !important; clip: rect(1px 1px 1px 1px); clip: rect(1px,1px,1px,1px); }
15 .ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
16 .ui-helper-clearfix:before, .ui-helper-clearfix:after { content: ""; display: table; }
17 .ui-helper-clearfix:after { clear: both; }
18 .ui-helper-clearfix { zoom: 1; }
19 .ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
20
21
22 /* Interaction Cues
23 ----------------------------------*/
24 .ui-state-disabled { cursor: default !important; }
25
26
27 /* Icons
28 ----------------------------------*/
29
30 /* states and images */
31 .ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
32
33
34 /* Misc visuals
35 ----------------------------------*/
36
37 /* Overlays */
38 .ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
39 /*
40 * jQuery UI Accordion @VERSION
41 *
42 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
43 * Dual licensed under the MIT or GPL Version 2 licenses.
44 * http://jquery.org/license
45 *
46 * http://docs.jquery.com/UI/Accordion#theming
47 */
48 /* IE/Win - Fix animation bug - #4615 */
49 .ui-accordion { width: 100%; }
50 .ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; }
51 .ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; }
52 .ui-accordion .ui-accordion-heading { display: block; font-size: 1em; padding: .5em .5em .5em .7em; }
53 .ui-accordion-icons .ui-accordion-heading { padding-left: 2.2em; }
54 .ui-accordion .ui-accordion-header .ui-accordion-header-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; }
55 .ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; zoom: 1; }
56 .ui-accordion .ui-accordion-content-active { display: block; }
57 /*
58 * jQuery UI Autocomplete @VERSION
59 *
60 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
61 * Dual licensed under the MIT or GPL Version 2 licenses.
62 * http://jquery.org/license
63 *
64 * http://docs.jquery.com/UI/Autocomplete#theming
65 */
66 .ui-autocomplete { position: absolute; cursor: default; }
67
68 /* workarounds */
69 * html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */
70 /*
71 * jQuery UI Button @VERSION
72 *
73 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
74 * Dual licensed under the MIT or GPL Version 2 licenses.
75 * http://jquery.org/license
76 *
77 * http://docs.jquery.com/UI/Button#theming
78 */
79 .ui-button { display: inline-block; position: relative; padding: 0; margin-right: .1em; text-decoration: none !important; cursor: pointer; text-align: center; zoom: 1; overflow: hidden; *overflow: visible; } /* the overflow property removes extra width in IE */
80 .ui-button-icon-only { width: 2.2em; } /* to make room for the icon, a width needs to be set here */
81 button.ui-button-icon-only { width: 2.4em; } /* button elements seem to need a little more width */
82 .ui-button-icons-only { width: 3.4em; }
83 button.ui-button-icons-only { width: 3.7em; }
84
85 /*button text element */
86 .ui-button .ui-button-text { display: block; line-height: 1.4; }
87 .ui-button-text-only .ui-button-text { padding: .4em 1em; }
88 .ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text { padding: .4em; text-indent: -9999999px; }
89 .ui-button-text-icon-primary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 1em .4em 2.1em; }
90 .ui-button-text-icon-secondary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 2.1em .4em 1em; }
91 .ui-button-text-icons .ui-button-text { padding-left: 2.1em; padding-right: 2.1em; }
92 /* no icon support for input elements, provide padding by default */
93 input.ui-button { padding: .4em 1em; }
94
95 /*button icon element(s) */
96 .ui-button-icon-only .ui-icon, .ui-button-text-icon-primary .ui-icon, .ui-button-text-icon-secondary .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon { position: absolute; top: 50%; margin-top: -8px; }
97 .ui-button-icon-only .ui-icon { left: 50%; margin-left: -8px; }
98 .ui-button-text-icon-primary .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { left: .5em; }
99 .ui-button-text-icon-secondary .ui-button-icon-secondary, .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
100 .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
101
102 /*button sets*/
103 .ui-buttonset { margin-right: 7px; }
104 .ui-buttonset .ui-button { margin-left: 0; margin-right: -.3em; }
105
106 /* workarounds */
107 button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra padding in Firefox */
108 /*
109 * jQuery UI Datepicker @VERSION
110 *
111 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
112 * Dual licensed under the MIT or GPL Version 2 licenses.
113 * http://jquery.org/license
114 *
115 * http://docs.jquery.com/UI/Datepicker#theming
116 */
117 .ui-datepicker { width: 17em; padding: .2em .2em 0; display: none; }
118 .ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; }
119 .ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; }
120 .ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; }
121 .ui-datepicker .ui-datepicker-prev { left:2px; }
122 .ui-datepicker .ui-datepicker-next { right:2px; }
123 .ui-datepicker .ui-datepicker-prev-hover { left:1px; }
124 .ui-datepicker .ui-datepicker-next-hover { right:1px; }
125 .ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; }
126 .ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; }
127 .ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; }
128 .ui-datepicker select.ui-datepicker-month-year {width: 100%;}
129 .ui-datepicker select.ui-datepicker-month,
130 .ui-datepicker select.ui-datepicker-year { width: 49%;}
131 .ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }
132 .ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; }
133 .ui-datepicker td { border: 0; padding: 1px; }
134 .ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }
135 .ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; }
136 .ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
137 .ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }
138
139 /* with multiple calendars */
140 .ui-datepicker.ui-datepicker-multi { width:auto; }
141 .ui-datepicker-multi .ui-datepicker-group { float:left; }
142 .ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; }
143 .ui-datepicker-multi-2 .ui-datepicker-group { width:50%; }
144 .ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; }
145 .ui-datepicker-multi-4 .ui-datepicker-group { width:25%; }
146 .ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; }
147 .ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; }
148 .ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; }
149 .ui-datepicker-row-break { clear:both; width:100%; font-size:0em; }
150
151 /* RTL support */
152 .ui-datepicker-rtl { direction: rtl; }
153 .ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; }
154 .ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; }
155 .ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; }
156 .ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; }
157 .ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; }
158 .ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; }
159 .ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; }
160 .ui-datepicker-rtl .ui-datepicker-group { float:right; }
161 .ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
162 .ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
163
164 /* IE6 IFRAME FIX (taken from datepicker 1.5.3 */
165 .ui-datepicker-cover {
166 display: none; /*sorry for IE5*/
167 display/**/: block; /*sorry for IE5*/
168 position: absolute; /*must have*/
169 z-index: -1; /*must have*/
170 filter: mask(); /*must have*/
171 top: -4px; /*must have*/
172 left: -4px; /*must have*/
173 width: 200px; /*must have*/
174 height: 200px; /*must have*/
175 }/*
176 * jQuery UI Dialog @VERSION
177 *
178 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
179 * Dual licensed under the MIT or GPL Version 2 licenses.
180 * http://jquery.org/license
181 *
182 * http://docs.jquery.com/UI/Dialog#theming
183 */
184 .ui-dialog { position: absolute; padding: .2em; width: 300px; overflow: hidden; }
185 .ui-dialog .ui-dialog-titlebar { padding: .4em 1em; position: relative; }
186 .ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .1em 0; }
187 .ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; }
188 .ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; }
189 .ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; }
190 .ui-dialog .ui-dialog-content { position: relative; border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; }
191 .ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; }
192 .ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { float: right; }
193 .ui-dialog .ui-dialog-buttonpane button { margin: .5em .4em .5em 0; cursor: pointer; }
194 .ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; }
195 .ui-draggable .ui-dialog-titlebar { cursor: move; }
196 /*
197 * jQuery UI Menu @VERSION
198 *
199 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
200 * Dual licensed under the MIT or GPL Version 2 licenses.
201 * http://jquery.org/license
202 *
203 * http://docs.jquery.com/UI/Menu#theming
204 */
205 .ui-menu { list-style:none; padding: 2px; margin: 0; display:block; outline: none; }
206 .ui-menu .ui-menu { margin-top: -3px; position: absolute; }
207 .ui-menu .ui-menu-item { margin: 0; padding: 0; zoom: 1; width: 100%; }
208 .ui-menu .ui-menu-item a { text-decoration: none; display: block; padding: 2px .4em; line-height: 1.5; zoom: 1; font-weight: normal; }
209 .ui-menu .ui-menu-item a.ui-state-focus,
210 .ui-menu .ui-menu-item a.ui-state-active { font-weight: normal; margin: -1px; }
211
212 .ui-menu .ui-state-disabled { font-weight: normal; padding: .0em .4em; margin: .4em 0 .2em; line-height: 1.5; }
213
214 /* icon support */
215 .ui-menu-icons { position: relative; }
216 .ui-menu-icons .ui-menu-item a { position: relative; padding-left: 2em; }
217
218 /* left-aligned */
219 .ui-menu .ui-icon { position: absolute; top: .2em; left: .2em; }
220
221 /* right-aligned */
222 .ui-menu .ui-menu-icon { position: static; float: right; }
223 /*
224 * jQuery UI Menubar @VERSION
225 *
226 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
227 * Dual licensed under the MIT or GPL Version 2 licenses.
228 * http://jquery.org/license
229 */
230 .ui-menubar { list-style: none; margin: 0; padding-left: 0; }
231
232 .ui-menubar-item { float: left; }
233
234 .ui-menubar .ui-button { float: left; font-weight: normal; border-top-width: 0 !important; border-bottom-width: 0 !important; margin: 0; outline: none; }
235 .ui-menubar .ui-menubar-link { border-right: 1px dashed transparent; border-left: 1px dashed transparent; }
236
237 .ui-menubar .ui-menu { width: 200px; position: absolute; z-index: 9999; font-weight: normal; }
238 /*
239 * jQuery UI Progressbar @VERSION
240 *
241 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
242 * Dual licensed under the MIT or GPL Version 2 licenses.
243 * http://jquery.org/license
244 *
245 * http://docs.jquery.com/UI/Progressbar#theming
246 */
247 .ui-progressbar { height:2em; text-align: left; overflow: hidden; }
248 .ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }/*
249 * jQuery UI Resizable @VERSION
250 *
251 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
252 * Dual licensed under the MIT or GPL Version 2 licenses.
253 * http://jquery.org/license
254 *
255 * http://docs.jquery.com/UI/Resizable#theming
256 */
257 .ui-resizable { position: relative;}
258 .ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block; }
259 .ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; }
260 .ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; }
261 .ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; }
262 .ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; }
263 .ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; }
264 .ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; }
265 .ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; }
266 .ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; }
267 .ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/*
268 * jQuery UI Selectable @VERSION
269 *
270 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
271 * Dual licensed under the MIT or GPL Version 2 licenses.
272 * http://jquery.org/license
273 *
274 * http://docs.jquery.com/UI/Selectable#theming
275 */
276 .ui-selectable-helper { position: absolute; z-index: 100; border:1px dotted black; }
277 /*
278 * jQuery UI Slider @VERSION
279 *
280 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
281 * Dual licensed under the MIT or GPL Version 2 licenses.
282 * http://jquery.org/license
283 *
284 * http://docs.jquery.com/UI/Slider#theming
285 */
286 .ui-slider { position: relative; text-align: left; }
287 .ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; }
288 .ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; }
289
290 .ui-slider-horizontal { height: .8em; }
291 .ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; }
292 .ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; }
293 .ui-slider-horizontal .ui-slider-range-min { left: 0; }
294 .ui-slider-horizontal .ui-slider-range-max { right: 0; }
295
296 .ui-slider-vertical { width: .8em; height: 100px; }
297 .ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; }
298 .ui-slider-vertical .ui-slider-range { left: 0; width: 100%; }
299 .ui-slider-vertical .ui-slider-range-min { bottom: 0; }
300 .ui-slider-vertical .ui-slider-range-max { top: 0; }/*
301 * jQuery UI Spinner @VERSION
302 *
303 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
304 * Dual licensed under the MIT or GPL Version 2 licenses.
305 * http://jquery.org/license
306 *
307 * http://docs.jquery.com/UI/Spinner#theming
308 */
309 .ui-spinner { position:relative; display: inline-block; overflow: hidden; padding: 0; vertical-align: middle; }
310 .ui-spinner-input { border: none; background: none; padding: 0; margin: .2em 0; vertical-align: middle; margin-left: .4em; margin-right: 22px; }
311 .ui-spinner-button { width: 16px; height: 50%; font-size: .5em; padding: 0; margin: 0; z-index: 100; text-align: center; vertical-align: middle; position: absolute; cursor: default; display: block; overflow: hidden; right: 0; }
312 .ui-spinner a.ui-spinner-button { border-top: none; border-bottom: none; border-right: none; } /* more specificity required here to overide default borders */
313 .ui-spinner .ui-icon { position: absolute; margin-top: -8px; top: 50%; left: 0; } /* vertical centre icon */
314 .ui-spinner-up { top: 0; }
315 .ui-spinner-down { bottom: 0; }
316
317 /* TR overrides */
318 span.ui-spinner { background: none; }
319 .ui-spinner .ui-icon-triangle-1-s {
320 /* need to fix icons sprite */
321 background-position:-65px -16px;
322 }
323 /*
324 * jQuery UI Tabs @VERSION
325 *
326 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
327 * Dual licensed under the MIT or GPL Version 2 licenses.
328 * http://jquery.org/license
329 *
330 * http://docs.jquery.com/UI/Tabs#theming
331 */
332 .ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
333 .ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; }
334 .ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 0; margin: 1px .2em 0 0; border-bottom: 0 !important; padding: 0; white-space: nowrap; }
335 .ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 1em; text-decoration: none; }
336 .ui-tabs .ui-tabs-nav li.ui-tabs-active { margin-bottom: -1px; padding-bottom: 1px; }
337 .ui-tabs .ui-tabs-nav li.ui-tabs-active a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-tabs-loading a { cursor: text; }
338 .ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
339 .ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 1em 1.4em; background: none; }
340 /*
341 * jQuery UI Tooltip @VERSION
342 *
343 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
344 * Dual licensed under the MIT or GPL Version 2 licenses.
345 * http://jquery.org/license
346 *
347 * http://docs.jquery.com/UI/Tooltip#theming
348 */
349 .ui-tooltip {
350 padding:8px;
351 position:absolute;
352 z-index:9999;
353 -o-box-shadow: 0 0 5px #aaa;
354 -moz-box-shadow: 0 0 5px #aaa;
355 -webkit-box-shadow: 0 0 5px #aaa;
356 box-shadow: 0 0 5px #aaa;
357 }
358 /* Fades and background-images don't work well together in IE6, drop the image */
359 * html .ui-tooltip {
360 background-image: none;
361 }
362 body .ui-tooltip { border-width:2px; }
363 /*
364 * jQuery UI CSS Framework @VERSION
365 *
366 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
367 * Dual licensed under the MIT or GPL Version 2 licenses.
368 * http://jquery.org/license
369 *
370 * http://docs.jquery.com/UI/Theming/API
371 *
372 * To view and modify this theme, visit http://jqueryui.com/themeroller/
373 */
374
375
376 /* Component containers
377 ----------------------------------*/
378 .ui-widget { font-family: Verdana,Arial,sans-serif/*{ffDefault}*/; font-size: 1.1em/*{fsDefault}*/; }
379 .ui-widget .ui-widget { font-size: 1em; }
380 .ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Verdana,Arial,sans-serif/*{ffDefault}*/; font-size: 1em; }
381 .ui-widget-content { border: 1px solid #aaaaaa/*{borderColorContent}*/; background: #ffffff/*{bgColorContent}*/ url(images/ui-bg_flat_75_ffffff_40x100.png)/*{bgImgUrlContent}*/ 50%/*{bgContentXPos}*/ 50%/*{bgContentYPos}*/ repeat-x/*{bgContentRepeat}*/; color: #222222/*{fcContent}*/; }
382 .ui-widget-content a { color: #222222/*{fcContent}*/; }
383 .ui-widget-header { border: 1px solid #aaaaaa/*{borderColorHeader}*/; background: #cccccc/*{bgColorHeader}*/ url(images/ui-bg_highlight-soft_75_cccccc_1x100.png)/*{bgImgUrlHeader}*/ 50%/*{bgHeaderXPos}*/ 50%/*{bgHeaderYPos}*/ repeat-x/*{bgHeaderRepeat}*/; color: #222222/*{fcHeader}*/; font-weight: bold; }
384 .ui-widget-header a { color: #222222/*{fcHeader}*/; }
385
386 /* Interaction states
387 ----------------------------------*/
388 .ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #d3d3d3/*{borderColorDefault}*/; background: #e6e6e6/*{bgColorDefault}*/ url(images/ui-bg_glass_75_e6e6e6_1x400.png)/*{bgImgUrlDefault}*/ 50%/*{bgDefaultXPos}*/ 50%/*{bgDefaultYPos}*/ repeat-x/*{bgDefaultRepeat}*/; font-weight: normal/*{fwDefault}*/; color: #555555/*{fcDefault}*/; }
389 .ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #555555/*{fcDefault}*/; text-decoration: none; }
390 .ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #999999/*{borderColorHover}*/; background: #dadada/*{bgColorHover}*/ url(images/ui-bg_glass_75_dadada_1x400.png)/*{bgImgUrlHover}*/ 50%/*{bgHoverXPos}*/ 50%/*{bgHoverYPos}*/ repeat-x/*{bgHoverRepeat}*/; font-weight: normal/*{fwDefault}*/; color: #212121/*{fcHover}*/; }
391 .ui-state-hover a, .ui-state-hover a:hover { color: #212121/*{fcHover}*/; text-decoration: none; }
392 .ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #aaaaaa/*{borderColorActive}*/; background: #ffffff/*{bgColorActive}*/ url(images/ui-bg_glass_65_ffffff_1x400.png)/*{bgImgUrlActive}*/ 50%/*{bgActiveXPos}*/ 50%/*{bgActiveYPos}*/ repeat-x/*{bgActiveRepeat}*/; font-weight: normal/*{fwDefault}*/; color: #212121/*{fcActive}*/; }
393 .ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #212121/*{fcActive}*/; text-decoration: none; }
394 .ui-widget :active { outline: none; }
395
396 /* Interaction Cues
397 ----------------------------------*/
398 .ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #fcefa1/*{borderColorHighlight}*/; background: #fbf9ee/*{bgColorHighlight}*/ url(images/ui-bg_glass_55_fbf9ee_1x400.png)/*{bgImgUrlHighlight}*/ 50%/*{bgHighlightXPos}*/ 50%/*{bgHighlightYPos}*/ repeat-x/*{bgHighlightRepeat}*/; color: #363636/*{fcHighlight}*/; }
399 .ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636/*{fcHighlight}*/; }
400 .ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a/*{borderColorError}*/; background: #fef1ec/*{bgColorError}*/ url(images/ui-bg_glass_95_fef1ec_1x400.png)/*{bgImgUrlError}*/ 50%/*{bgErrorXPos}*/ 50%/*{bgErrorYPos}*/ repeat-x/*{bgErrorRepeat}*/; color: #cd0a0a/*{fcError}*/; }
401 .ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #cd0a0a/*{fcError}*/; }
402 .ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #cd0a0a/*{fcError}*/; }
403 .ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; }
404 .ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
405 .ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
406
407 /* Icons
408 ----------------------------------*/
409
410 /* states and images */
411 .ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png)/*{iconsContent}*/; }
412 .ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png)/*{iconsContent}*/; }
413 .ui-widget-header .ui-icon {background-image: url(images/ui-icons_222222_256x240.png)/*{iconsHeader}*/; }
414 .ui-state-default .ui-icon { background-image: url(images/ui-icons_888888_256x240.png)/*{iconsDefault}*/; }
415 .ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_454545_256x240.png)/*{iconsHover}*/; }
416 .ui-state-active .ui-icon {background-image: url(images/ui-icons_454545_256x240.png)/*{iconsActive}*/; }
417 .ui-state-highlight .ui-icon {background-image: url(images/ui-icons_2e83ff_256x240.png)/*{iconsHighlight}*/; }
418 .ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cd0a0a_256x240.png)/*{iconsError}*/; }
419
420 /* positioning */
421 .ui-icon-carat-1-n { background-position: 0 0; }
422 .ui-icon-carat-1-ne { background-position: -16px 0; }
423 .ui-icon-carat-1-e { background-position: -32px 0; }
424 .ui-icon-carat-1-se { background-position: -48px 0; }
425 .ui-icon-carat-1-s { background-position: -64px 0; }
426 .ui-icon-carat-1-sw { background-position: -80px 0; }
427 .ui-icon-carat-1-w { background-position: -96px 0; }
428 .ui-icon-carat-1-nw { background-position: -112px 0; }
429 .ui-icon-carat-2-n-s { background-position: -128px 0; }
430 .ui-icon-carat-2-e-w { background-position: -144px 0; }
431 .ui-icon-triangle-1-n { background-position: 0 -16px; }
432 .ui-icon-triangle-1-ne { background-position: -16px -16px; }
433 .ui-icon-triangle-1-e { background-position: -32px -16px; }
434 .ui-icon-triangle-1-se { background-position: -48px -16px; }
435 .ui-icon-triangle-1-s { background-position: -64px -16px; }
436 .ui-icon-triangle-1-sw { background-position: -80px -16px; }
437 .ui-icon-triangle-1-w { background-position: -96px -16px; }
438 .ui-icon-triangle-1-nw { background-position: -112px -16px; }
439 .ui-icon-triangle-2-n-s { background-position: -128px -16px; }
440 .ui-icon-triangle-2-e-w { background-position: -144px -16px; }
441 .ui-icon-arrow-1-n { background-position: 0 -32px; }
442 .ui-icon-arrow-1-ne { background-position: -16px -32px; }
443 .ui-icon-arrow-1-e { background-position: -32px -32px; }
444 .ui-icon-arrow-1-se { background-position: -48px -32px; }
445 .ui-icon-arrow-1-s { background-position: -64px -32px; }
446 .ui-icon-arrow-1-sw { background-position: -80px -32px; }
447 .ui-icon-arrow-1-w { background-position: -96px -32px; }
448 .ui-icon-arrow-1-nw { background-position: -112px -32px; }
449 .ui-icon-arrow-2-n-s { background-position: -128px -32px; }
450 .ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
451 .ui-icon-arrow-2-e-w { background-position: -160px -32px; }
452 .ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
453 .ui-icon-arrowstop-1-n { background-position: -192px -32px; }
454 .ui-icon-arrowstop-1-e { background-position: -208px -32px; }
455 .ui-icon-arrowstop-1-s { background-position: -224px -32px; }
456 .ui-icon-arrowstop-1-w { background-position: -240px -32px; }
457 .ui-icon-arrowthick-1-n { background-position: 0 -48px; }
458 .ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
459 .ui-icon-arrowthick-1-e { background-position: -32px -48px; }
460 .ui-icon-arrowthick-1-se { background-position: -48px -48px; }
461 .ui-icon-arrowthick-1-s { background-position: -64px -48px; }
462 .ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
463 .ui-icon-arrowthick-1-w { background-position: -96px -48px; }
464 .ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
465 .ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
466 .ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
467 .ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
468 .ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
469 .ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
470 .ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
471 .ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
472 .ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
473 .ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
474 .ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
475 .ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
476 .ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
477 .ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
478 .ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
479 .ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
480 .ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
481 .ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
482 .ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
483 .ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
484 .ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
485 .ui-icon-arrow-4 { background-position: 0 -80px; }
486 .ui-icon-arrow-4-diag { background-position: -16px -80px; }
487 .ui-icon-extlink { background-position: -32px -80px; }
488 .ui-icon-newwin { background-position: -48px -80px; }
489 .ui-icon-refresh { background-position: -64px -80px; }
490 .ui-icon-shuffle { background-position: -80px -80px; }
491 .ui-icon-transfer-e-w { background-position: -96px -80px; }
492 .ui-icon-transferthick-e-w { background-position: -112px -80px; }
493 .ui-icon-folder-collapsed { background-position: 0 -96px; }
494 .ui-icon-folder-open { background-position: -16px -96px; }
495 .ui-icon-document { background-position: -32px -96px; }
496 .ui-icon-document-b { background-position: -48px -96px; }
497 .ui-icon-note { background-position: -64px -96px; }
498 .ui-icon-mail-closed { background-position: -80px -96px; }
499 .ui-icon-mail-open { background-position: -96px -96px; }
500 .ui-icon-suitcase { background-position: -112px -96px; }
501 .ui-icon-comment { background-position: -128px -96px; }
502 .ui-icon-person { background-position: -144px -96px; }
503 .ui-icon-print { background-position: -160px -96px; }
504 .ui-icon-trash { background-position: -176px -96px; }
505 .ui-icon-locked { background-position: -192px -96px; }
506 .ui-icon-unlocked { background-position: -208px -96px; }
507 .ui-icon-bookmark { background-position: -224px -96px; }
508 .ui-icon-tag { background-position: -240px -96px; }
509 .ui-icon-home { background-position: 0 -112px; }
510 .ui-icon-flag { background-position: -16px -112px; }
511 .ui-icon-calendar { background-position: -32px -112px; }
512 .ui-icon-cart { background-position: -48px -112px; }
513 .ui-icon-pencil { background-position: -64px -112px; }
514 .ui-icon-clock { background-position: -80px -112px; }
515 .ui-icon-disk { background-position: -96px -112px; }
516 .ui-icon-calculator { background-position: -112px -112px; }
517 .ui-icon-zoomin { background-position: -128px -112px; }
518 .ui-icon-zoomout { background-position: -144px -112px; }
519 .ui-icon-search { background-position: -160px -112px; }
520 .ui-icon-wrench { background-position: -176px -112px; }
521 .ui-icon-gear { background-position: -192px -112px; }
522 .ui-icon-heart { background-position: -208px -112px; }
523 .ui-icon-star { background-position: -224px -112px; }
524 .ui-icon-link { background-position: -240px -112px; }
525 .ui-icon-cancel { background-position: 0 -128px; }
526 .ui-icon-plus { background-position: -16px -128px; }
527 .ui-icon-plusthick { background-position: -32px -128px; }
528 .ui-icon-minus { background-position: -48px -128px; }
529 .ui-icon-minusthick { background-position: -64px -128px; }
530 .ui-icon-close { background-position: -80px -128px; }
531 .ui-icon-closethick { background-position: -96px -128px; }
532 .ui-icon-key { background-position: -112px -128px; }
533 .ui-icon-lightbulb { background-position: -128px -128px; }
534 .ui-icon-scissors { background-position: -144px -128px; }
535 .ui-icon-clipboard { background-position: -160px -128px; }
536 .ui-icon-copy { background-position: -176px -128px; }
537 .ui-icon-contact { background-position: -192px -128px; }
538 .ui-icon-image { background-position: -208px -128px; }
539 .ui-icon-video { background-position: -224px -128px; }
540 .ui-icon-script { background-position: -240px -128px; }
541 .ui-icon-alert { background-position: 0 -144px; }
542 .ui-icon-info { background-position: -16px -144px; }
543 .ui-icon-notice { background-position: -32px -144px; }
544 .ui-icon-help { background-position: -48px -144px; }
545 .ui-icon-check { background-position: -64px -144px; }
546 .ui-icon-bullet { background-position: -80px -144px; }
547 .ui-icon-radio-on { background-position: -96px -144px; }
548 .ui-icon-radio-off { background-position: -112px -144px; }
549 .ui-icon-pin-w { background-position: -128px -144px; }
550 .ui-icon-pin-s { background-position: -144px -144px; }
551 .ui-icon-play { background-position: 0 -160px; }
552 .ui-icon-pause { background-position: -16px -160px; }
553 .ui-icon-seek-next { background-position: -32px -160px; }
554 .ui-icon-seek-prev { background-position: -48px -160px; }
555 .ui-icon-seek-end { background-position: -64px -160px; }
556 .ui-icon-seek-start { background-position: -80px -160px; }
557 /* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
558 .ui-icon-seek-first { background-position: -80px -160px; }
559 .ui-icon-stop { background-position: -96px -160px; }
560 .ui-icon-eject { background-position: -112px -160px; }
561 .ui-icon-volume-off { background-position: -128px -160px; }
562 .ui-icon-volume-on { background-position: -144px -160px; }
563 .ui-icon-power { background-position: 0 -176px; }
564 .ui-icon-signal-diag { background-position: -16px -176px; }
565 .ui-icon-signal { background-position: -32px -176px; }
566 .ui-icon-battery-0 { background-position: -48px -176px; }
567 .ui-icon-battery-1 { background-position: -64px -176px; }
568 .ui-icon-battery-2 { background-position: -80px -176px; }
569 .ui-icon-battery-3 { background-position: -96px -176px; }
570 .ui-icon-circle-plus { background-position: 0 -192px; }
571 .ui-icon-circle-minus { background-position: -16px -192px; }
572 .ui-icon-circle-close { background-position: -32px -192px; }
573 .ui-icon-circle-triangle-e { background-position: -48px -192px; }
574 .ui-icon-circle-triangle-s { background-position: -64px -192px; }
575 .ui-icon-circle-triangle-w { background-position: -80px -192px; }
576 .ui-icon-circle-triangle-n { background-position: -96px -192px; }
577 .ui-icon-circle-arrow-e { background-position: -112px -192px; }
578 .ui-icon-circle-arrow-s { background-position: -128px -192px; }
579 .ui-icon-circle-arrow-w { background-position: -144px -192px; }
580 .ui-icon-circle-arrow-n { background-position: -160px -192px; }
581 .ui-icon-circle-zoomin { background-position: -176px -192px; }
582 .ui-icon-circle-zoomout { background-position: -192px -192px; }
583 .ui-icon-circle-check { background-position: -208px -192px; }
584 .ui-icon-circlesmall-plus { background-position: 0 -208px; }
585 .ui-icon-circlesmall-minus { background-position: -16px -208px; }
586 .ui-icon-circlesmall-close { background-position: -32px -208px; }
587 .ui-icon-squaresmall-plus { background-position: -48px -208px; }
588 .ui-icon-squaresmall-minus { background-position: -64px -208px; }
589 .ui-icon-squaresmall-close { background-position: -80px -208px; }
590 .ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
591 .ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
592 .ui-icon-grip-solid-vertical { background-position: -32px -224px; }
593 .ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
594 .ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
595 .ui-icon-grip-diagonal-se { background-position: -80px -224px; }
596
597
598 /* Misc visuals
599 ----------------------------------*/
600
601 /* Corner radius */
602 .ui-corner-all, .ui-corner-top, .ui-corner-left, .ui-corner-tl { -moz-border-radius-topleft: 4px/*{cornerRadius}*/; -webkit-border-top-left-radius: 4px/*{cornerRadius}*/; -khtml-border-top-left-radius: 4px/*{cornerRadius}*/; border-top-left-radius: 4px/*{cornerRadius}*/; }
603 .ui-corner-all, .ui-corner-top, .ui-corner-right, .ui-corner-tr { -moz-border-radius-topright: 4px/*{cornerRadius}*/; -webkit-border-top-right-radius: 4px/*{cornerRadius}*/; -khtml-border-top-right-radius: 4px/*{cornerRadius}*/; border-top-right-radius: 4px/*{cornerRadius}*/; }
604 .ui-corner-all, .ui-corner-bottom, .ui-corner-left, .ui-corner-bl { -moz-border-radius-bottomleft: 4px/*{cornerRadius}*/; -webkit-border-bottom-left-radius: 4px/*{cornerRadius}*/; -khtml-border-bottom-left-radius: 4px/*{cornerRadius}*/; border-bottom-left-radius: 4px/*{cornerRadius}*/; }
605 .ui-corner-all, .ui-corner-bottom, .ui-corner-right, .ui-corner-br { -moz-border-radius-bottomright: 4px/*{cornerRadius}*/; -webkit-border-bottom-right-radius: 4px/*{cornerRadius}*/; -khtml-border-bottom-right-radius: 4px/*{cornerRadius}*/; border-bottom-right-radius: 4px/*{cornerRadius}*/; }
606
607 /* Overlays */
608 .ui-widget-overlay { background: #aaaaaa/*{bgColorOverlay}*/ url(images/ui-bg_flat_0_aaaaaa_40x100.png)/*{bgImgUrlOverlay}*/ 50%/*{bgOverlayXPos}*/ 50%/*{bgOverlayYPos}*/ repeat-x/*{bgOverlayRepeat}*/; opacity: .3;filter:Alpha(Opacity=30)/*{opacityOverlay}*/; }
609 .ui-widget-shadow { margin: -8px/*{offsetTopShadow}*/ 0 0 -8px/*{offsetLeftShadow}*/; padding: 8px/*{thicknessShadow}*/; background: #aaaaaa/*{bgColorShadow}*/ url(images/ui-bg_flat_0_aaaaaa_40x100.png)/*{bgImgUrlShadow}*/ 50%/*{bgShadowXPos}*/ 50%/*{bgShadowYPos}*/ repeat-x/*{bgShadowRepeat}*/; opacity: .3;filter:Alpha(Opacity=30)/*{opacityShadow}*/; -moz-border-radius: 8px/*{cornerRadiusShadow}*/; -khtml-border-radius: 8px/*{cornerRadiusShadow}*/; -webkit-border-radius: 8px/*{cornerRadiusShadow}*/; border-radius: 8px/*{cornerRadiusShadow}*/; } No newline at end of file
This diff has been collapsed as it changes many lines, (14537 lines changed) Show them Hide them
@@ -1,14537 +0,0
1 /*!
2 * jQuery UI @VERSION
3 *
4 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
5 * Dual licensed under the MIT or GPL Version 2 licenses.
6 * http://jquery.org/license
7 *
8 * http://docs.jquery.com/UI
9 */
10 (function( $, undefined ) {
11
12 // prevent duplicate loading
13 // this is only a problem because we proxy existing functions
14 // and we don't want to double proxy them
15 $.ui = $.ui || {};
16 if ( $.ui.version ) {
17 return;
18 }
19
20 $.extend( $.ui, {
21 version: "@VERSION",
22
23 keyCode: {
24 ALT: 18,
25 BACKSPACE: 8,
26 CAPS_LOCK: 20,
27 COMMA: 188,
28 COMMAND: 91,
29 COMMAND_LEFT: 91, // COMMAND
30 COMMAND_RIGHT: 93,
31 CONTROL: 17,
32 DELETE: 46,
33 DOWN: 40,
34 END: 35,
35 ENTER: 13,
36 ESCAPE: 27,
37 HOME: 36,
38 INSERT: 45,
39 LEFT: 37,
40 MENU: 93, // COMMAND_RIGHT
41 NUMPAD_ADD: 107,
42 NUMPAD_DECIMAL: 110,
43 NUMPAD_DIVIDE: 111,
44 NUMPAD_ENTER: 108,
45 NUMPAD_MULTIPLY: 106,
46 NUMPAD_SUBTRACT: 109,
47 PAGE_DOWN: 34,
48 PAGE_UP: 33,
49 PERIOD: 190,
50 RIGHT: 39,
51 SHIFT: 16,
52 SPACE: 32,
53 TAB: 9,
54 UP: 38,
55 WINDOWS: 91 // COMMAND
56 }
57 });
58
59 // plugins
60 $.fn.extend({
61 _focus: $.fn.focus,
62 focus: function( delay, fn ) {
63 return typeof delay === "number" ?
64 this.each(function() {
65 var elem = this;
66 setTimeout(function() {
67 $( elem ).focus();
68 if ( fn ) {
69 fn.call( elem );
70 }
71 }, delay );
72 }) :
73 this._focus.apply( this, arguments );
74 },
75
76 scrollParent: function() {
77 var scrollParent;
78 if (($.browser.msie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) {
79 scrollParent = this.parents().filter(function() {
80 return (/(relative|absolute|fixed)/).test($.curCSS(this,'position',1)) && (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
81 }).eq(0);
82 } else {
83 scrollParent = this.parents().filter(function() {
84 return (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
85 }).eq(0);
86 }
87
88 return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent;
89 },
90
91 zIndex: function( zIndex ) {
92 if ( zIndex !== undefined ) {
93 return this.css( "zIndex", zIndex );
94 }
95
96 if ( this.length ) {
97 var elem = $( this[ 0 ] ), position, value;
98 while ( elem.length && elem[ 0 ] !== document ) {
99 // Ignore z-index if position is set to a value where z-index is ignored by the browser
100 // This makes behavior of this function consistent across browsers
101 // WebKit always returns auto if the element is positioned
102 position = elem.css( "position" );
103 if ( position === "absolute" || position === "relative" || position === "fixed" ) {
104 // IE returns 0 when zIndex is not specified
105 // other browsers return a string
106 // we ignore the case of nested elements with an explicit value of 0
107 // <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
108 value = parseInt( elem.css( "zIndex" ), 10 );
109 if ( !isNaN( value ) && value !== 0 ) {
110 return value;
111 }
112 }
113 elem = elem.parent();
114 }
115 }
116
117 return 0;
118 },
119
120 disableSelection: function() {
121 return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) +
122 ".ui-disableSelection", function( event ) {
123 event.preventDefault();
124 });
125 },
126
127 enableSelection: function() {
128 return this.unbind( ".ui-disableSelection" );
129 }
130 });
131
132 $.each( [ "Width", "Height" ], function( i, name ) {
133 var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
134 type = name.toLowerCase(),
135 orig = {
136 innerWidth: $.fn.innerWidth,
137 innerHeight: $.fn.innerHeight,
138 outerWidth: $.fn.outerWidth,
139 outerHeight: $.fn.outerHeight
140 };
141
142 function reduce( elem, size, border, margin ) {
143 $.each( side, function() {
144 size -= parseFloat( $.curCSS( elem, "padding" + this, true ) ) || 0;
145 if ( border ) {
146 size -= parseFloat( $.curCSS( elem, "border" + this + "Width", true ) ) || 0;
147 }
148 if ( margin ) {
149 size -= parseFloat( $.curCSS( elem, "margin" + this, true ) ) || 0;
150 }
151 });
152 return size;
153 }
154
155 $.fn[ "inner" + name ] = function( size ) {
156 if ( size === undefined ) {
157 return orig[ "inner" + name ].call( this );
158 }
159
160 return this.each(function() {
161 $( this ).css( type, reduce( this, size ) + "px" );
162 });
163 };
164
165 $.fn[ "outer" + name] = function( size, margin ) {
166 if ( typeof size !== "number" ) {
167 return orig[ "outer" + name ].call( this, size );
168 }
169
170 return this.each(function() {
171 $( this).css( type, reduce( this, size, true, margin ) + "px" );
172 });
173 };
174 });
175
176 // selectors
177 function focusable( element, isTabIndexNotNaN ) {
178 var nodeName = element.nodeName.toLowerCase();
179 if ( "area" === nodeName ) {
180 var map = element.parentNode,
181 mapName = map.name,
182 img;
183 if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
184 return false;
185 }
186 img = $( "img[usemap=#" + mapName + "]" )[0];
187 return !!img && visible( img );
188 }
189 return ( /input|select|textarea|button|object/.test( nodeName )
190 ? !element.disabled
191 : "a" == nodeName
192 ? element.href || isTabIndexNotNaN
193 : isTabIndexNotNaN)
194 // the element and all of its ancestors must be visible
195 && visible( element );
196 }
197
198 function visible( element ) {
199 return !$( element ).parents().andSelf().filter(function() {
200 return $.curCSS( this, "visibility" ) === "hidden" ||
201 $.expr.filters.hidden( this );
202 }).length;
203 }
204
205 $.extend( $.expr[ ":" ], {
206 data: function( elem, i, match ) {
207 return !!$.data( elem, match[ 3 ] );
208 },
209
210 focusable: function( element ) {
211 return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) );
212 },
213
214 tabbable: function( element ) {
215 var tabIndex = $.attr( element, "tabindex" ),
216 isTabIndexNaN = isNaN( tabIndex );
217 return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN );
218 }
219 });
220
221 // support
222 $(function() {
223 var body = document.body,
224 div = body.appendChild( div = document.createElement( "div" ) );
225
226 $.extend( div.style, {
227 minHeight: "100px",
228 height: "auto",
229 padding: 0,
230 borderWidth: 0
231 });
232
233 $.support.minHeight = div.offsetHeight === 100;
234 $.support.selectstart = "onselectstart" in div;
235
236 // set display to none to avoid a layout bug in IE
237 // http://dev.jquery.com/ticket/4014
238 body.removeChild( div ).style.display = "none";
239 });
240
241
242
243
244
245 // deprecated
246 $.extend( $.ui, {
247 // $.ui.plugin is deprecated. Use the proxy pattern instead.
248 plugin: {
249 add: function( module, option, set ) {
250 var proto = $.ui[ module ].prototype;
251 for ( var i in set ) {
252 proto.plugins[ i ] = proto.plugins[ i ] || [];
253 proto.plugins[ i ].push( [ option, set[ i ] ] );
254 }
255 },
256 call: function( instance, name, args ) {
257 var set = instance.plugins[ name ];
258 if ( !set || !instance.element[ 0 ].parentNode || instance.element[ 0 ].parentNode.nodeType === 11 ) {
259 return;
260 }
261
262 for ( var i = 0; i < set.length; i++ ) {
263 if ( instance.options[ set[ i ][ 0 ] ] ) {
264 set[ i ][ 1 ].apply( instance.element, args );
265 }
266 }
267 }
268 },
269
270 contains: $.contains,
271
272 // only used by resizable
273 hasScroll: function( el, a ) {
274
275 //If overflow is hidden, the element might have extra content, but the user wants to hide it
276 if ( $( el ).css( "overflow" ) === "hidden") {
277 return false;
278 }
279
280 var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
281 has = false;
282
283 if ( el[ scroll ] > 0 ) {
284 return true;
285 }
286
287 // TODO: determine which cases actually cause this to happen
288 // if the element doesn't have the scroll set, see if it's possible to
289 // set the scroll
290 el[ scroll ] = 1;
291 has = ( el[ scroll ] > 0 );
292 el[ scroll ] = 0;
293 return has;
294 },
295
296 // these are odd functions, fix the API or move into individual plugins
297 isOverAxis: function( x, reference, size ) {
298 //Determines when x coordinate is over "b" element axis
299 return ( x > reference ) && ( x < ( reference + size ) );
300 },
301 isOver: function( y, x, top, left, height, width ) {
302 //Determines when x, y coordinates is over "b" element
303 return $.ui.isOverAxis( y, top, height ) && $.ui.isOverAxis( x, left, width );
304 }
305 });
306
307 })( jQuery );
308 /*!
309 * jQuery UI Widget @VERSION
310 *
311 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
312 * Dual licensed under the MIT or GPL Version 2 licenses.
313 * http://jquery.org/license
314 *
315 * http://docs.jquery.com/UI/Widget
316 */
317 (function( $, undefined ) {
318
319 var slice = Array.prototype.slice;
320
321 var _cleanData = $.cleanData;
322 $.cleanData = function( elems ) {
323 for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
324 try {
325 $( elem ).triggerHandler( "remove" );
326 // http://bugs.jquery.com/ticket/8235
327 } catch( e ) {}
328 }
329 _cleanData( elems );
330 };
331
332 $.widget = function( name, base, prototype ) {
333 var namespace = name.split( "." )[ 0 ],
334 fullName;
335 name = name.split( "." )[ 1 ];
336 fullName = namespace + "-" + name;
337
338 if ( !prototype ) {
339 prototype = base;
340 base = $.Widget;
341 }
342
343 // create selector for plugin
344 $.expr[ ":" ][ fullName ] = function( elem ) {
345 return !!$.data( elem, name );
346 };
347
348 $[ namespace ] = $[ namespace ] || {};
349 // create the constructor using $.extend() so we can carry over any
350 // static properties stored on the existing constructor (if there is one)
351 $[ namespace ][ name ] = $.extend( function( options, element ) {
352 // allow instantiation without "new" keyword
353 if ( !this._createWidget ) {
354 return new $[ namespace ][ name ]( options, element );
355 }
356
357 // allow instantiation without initializing for simple inheritance
358 // must use "new" keyword (the code above always passes args)
359 if ( arguments.length ) {
360 this._createWidget( options, element );
361 }
362 }, $[ namespace ][ name ], { version: prototype.version } );
363
364 var basePrototype = new base();
365 // we need to make the options hash a property directly on the new instance
366 // otherwise we'll modify the options hash on the prototype that we're
367 // inheriting from
368 basePrototype.options = $.widget.extend( {}, basePrototype.options );
369 $.each( prototype, function( prop, value ) {
370 if ( $.isFunction( value ) ) {
371 prototype[ prop ] = (function() {
372 var _super = function() {
373 return base.prototype[ prop ].apply( this, arguments );
374 };
375 var _superApply = function( args ) {
376 return base.prototype[ prop ].apply( this, args );
377 };
378 return function() {
379 var __super = this._super,
380 __superApply = this._superApply,
381 returnValue;
382
383 this._super = _super;
384 this._superApply = _superApply;
385
386 returnValue = value.apply( this, arguments );
387
388 this._super = __super;
389 this._superApply = __superApply;
390
391 return returnValue;
392 };
393 }());
394 }
395 });
396 $[ namespace ][ name ].prototype = $.widget.extend( basePrototype, {
397 namespace: namespace,
398 widgetName: name,
399 widgetEventPrefix: name,
400 widgetBaseClass: fullName
401 }, prototype );
402
403 $.widget.bridge( name, $[ namespace ][ name ] );
404 };
405
406 $.widget.extend = function( target ) {
407 var input = slice.call( arguments, 1 ),
408 inputIndex = 0,
409 inputLength = input.length,
410 key,
411 value;
412 for ( ; inputIndex < inputLength; inputIndex++ ) {
413 for ( key in input[ inputIndex ] ) {
414 value = input[ inputIndex ][ key ];
415 if (input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) {
416 target[ key ] = $.isPlainObject( value ) ? $.widget.extend( {}, target[ key ], value ) : value;
417 }
418 }
419 }
420 return target;
421 };
422
423 $.widget.bridge = function( name, object ) {
424 $.fn[ name ] = function( options ) {
425 var isMethodCall = typeof options === "string",
426 args = slice.call( arguments, 1 ),
427 returnValue = this;
428
429 // allow multiple hashes to be passed on init
430 options = !isMethodCall && args.length ?
431 $.widget.extend.apply( null, [ options ].concat(args) ) :
432 options;
433
434 if ( isMethodCall ) {
435 this.each(function() {
436 var instance = $.data( this, name );
437 if ( !instance ) {
438 return $.error( "cannot call methods on " + name + " prior to initialization; " +
439 "attempted to call method '" + options + "'" );
440 }
441 if ( !$.isFunction( instance[options] ) || options.charAt( 0 ) === "_" ) {
442 return $.error( "no such method '" + options + "' for " + name + " widget instance" );
443 }
444 var methodValue = instance[ options ].apply( instance, args );
445 if ( methodValue !== instance && methodValue !== undefined ) {
446 returnValue = methodValue && methodValue.jquery ?
447 returnValue.pushStack( methodValue.get() ) :
448 methodValue;
449 return false;
450 }
451 });
452 } else {
453 this.each(function() {
454 var instance = $.data( this, name );
455 if ( instance ) {
456 instance.option( options || {} )._init();
457 } else {
458 object( options, this );
459 }
460 });
461 }
462
463 return returnValue;
464 };
465 };
466
467 $.Widget = function( options, element ) {
468 // allow instantiation without "new" keyword
469 if ( !this._createWidget ) {
470 return new $[ namespace ][ name ]( options, element );
471 }
472
473 // allow instantiation without initializing for simple inheritance
474 // must use "new" keyword (the code above always passes args)
475 if ( arguments.length ) {
476 this._createWidget( options, element );
477 }
478 };
479
480 $.Widget.prototype = {
481 widgetName: "widget",
482 widgetEventPrefix: "",
483 defaultElement: "<div>",
484 options: {
485 disabled: false,
486
487 // callbacks
488 create: null
489 },
490 _createWidget: function( options, element ) {
491 element = $( element || this.defaultElement || this )[ 0 ];
492 this.element = $( element );
493 this.options = $.widget.extend( {},
494 this.options,
495 this._getCreateOptions(),
496 options );
497
498 this.bindings = $();
499 this.hoverable = $();
500 this.focusable = $();
501
502 if ( element !== this ) {
503 $.data( element, this.widgetName, this );
504 this._bind({ remove: "destroy" });
505 this.document = $( element.style ?
506 // element within the document
507 element.ownerDocument :
508 // element is window or document
509 element.document || element );
510 this.window = $( this.document[0].defaultView || this.document[0].parentWindow );
511 }
512
513 this._create();
514 this._trigger( "create" );
515 this._init();
516 },
517 _getCreateOptions: $.noop,
518 _create: $.noop,
519 _init: $.noop,
520
521 destroy: function() {
522 this._destroy();
523 // we can probably remove the unbind calls in 2.0
524 // all event bindings should go through this._bind()
525 this.element
526 .unbind( "." + this.widgetName )
527 .removeData( this.widgetName );
528 this.widget()
529 .unbind( "." + this.widgetName )
530 .removeAttr( "aria-disabled" )
531 .removeClass(
532 this.widgetBaseClass + "-disabled " +
533 "ui-state-disabled" );
534
535 // clean up events and states
536 this.bindings.unbind( "." + this.widgetName );
537 this.hoverable.removeClass( "ui-state-hover" );
538 this.focusable.removeClass( "ui-state-focus" );
539 },
540 _destroy: $.noop,
541
542 widget: function() {
543 return this.element;
544 },
545
546 option: function( key, value ) {
547 var options = key,
548 parts,
549 curOption,
550 i;
551
552 if ( arguments.length === 0 ) {
553 // don't return a reference to the internal hash
554 return $.widget.extend( {}, this.options );
555 }
556
557 if ( typeof key === "string" ) {
558 // handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
559 options = {};
560 parts = key.split( "." );
561 key = parts.shift();
562 if ( parts.length ) {
563 curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );
564 for ( i = 0; i < parts.length - 1; i++ ) {
565 curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};
566 curOption = curOption[ parts[ i ] ];
567 }
568 key = parts.pop();
569 if ( value === undefined ) {
570 return curOption[ key ] === undefined ? null : curOption[ key ];
571 }
572 curOption[ key ] = value;
573 } else {
574 if ( value === undefined ) {
575 return this.options[ key ] === undefined ? null : this.options[ key ];
576 }
577 options[ key ] = value;
578 }
579 }
580
581 this._setOptions( options );
582
583 return this;
584 },
585 _setOptions: function( options ) {
586 var key;
587
588 for ( key in options ) {
589 this._setOption( key, options[ key ] );
590 }
591
592 return this;
593 },
594 _setOption: function( key, value ) {
595 this.options[ key ] = value;
596
597 if ( key === "disabled" ) {
598 this.widget()
599 .toggleClass( this.widgetBaseClass + "-disabled ui-state-disabled", !!value )
600 .attr( "aria-disabled", value );
601 this.hoverable.removeClass( "ui-state-hover" );
602 this.focusable.removeClass( "ui-state-focus" );
603 }
604
605 return this;
606 },
607
608 enable: function() {
609 return this._setOption( "disabled", false );
610 },
611 disable: function() {
612 return this._setOption( "disabled", true );
613 },
614
615 _bind: function( element, handlers ) {
616 // no element argument, shuffle and use this.element
617 if ( !handlers ) {
618 handlers = element;
619 element = this.element;
620 } else {
621 // accept selectors, DOM elements
622 element = $( element );
623 this.bindings = this.bindings.add( element );
624 }
625
626 var instance = this;
627 $.each( handlers, function( event, handler ) {
628 function handlerProxy() {
629 // allow widgets to customize the disabled handling
630 // - disabled as an array instead of boolean
631 // - disabled class as method for disabling individual parts
632 if ( instance.options.disabled === true ||
633 $( this ).hasClass( "ui-state-disabled" ) ) {
634 return;
635 }
636 return ( typeof handler === "string" ? instance[ handler ] : handler )
637 .apply( instance, arguments );
638 }
639 var match = event.match( /^(\w+)\s*(.*)$/ ),
640 eventName = match[1] + "." + instance.widgetName,
641 selector = match[2];
642 if ( selector ) {
643 instance.widget().delegate( selector, eventName, handlerProxy );
644 } else {
645 element.bind( eventName, handlerProxy );
646 }
647 });
648 },
649
650 _delay: function( handler, delay ) {
651 function handlerProxy() {
652 return ( typeof handler === "string" ? instance[ handler ] : handler )
653 .apply( instance, arguments );
654 }
655 var instance = this;
656 return setTimeout( handlerProxy, delay || 0 );
657 },
658
659 _hoverable: function( element ) {
660 this.hoverable = this.hoverable.add( element );
661 this._bind( element, {
662 mouseenter: function( event ) {
663 $( event.currentTarget ).addClass( "ui-state-hover" );
664 },
665 mouseleave: function( event ) {
666 $( event.currentTarget ).removeClass( "ui-state-hover" );
667 }
668 });
669 },
670
671 _focusable: function( element ) {
672 this.focusable = this.focusable.add( element );
673 this._bind( element, {
674 focusin: function( event ) {
675 $( event.currentTarget ).addClass( "ui-state-focus" );
676 },
677 focusout: function( event ) {
678 $( event.currentTarget ).removeClass( "ui-state-focus" );
679 }
680 });
681 },
682
683 _trigger: function( type, event, data ) {
684 var prop, orig,
685 callback = this.options[ type ];
686
687 data = data || {};
688 event = $.Event( event );
689 event.type = ( type === this.widgetEventPrefix ?
690 type :
691 this.widgetEventPrefix + type ).toLowerCase();
692 // the original event may come from any element
693 // so we need to reset the target on the new event
694 event.target = this.element[ 0 ];
695
696 // copy original event properties over to the new event
697 orig = event.originalEvent;
698 if ( orig ) {
699 for ( prop in orig ) {
700 if ( !( prop in event ) ) {
701 event[ prop ] = orig[ prop ];
702 }
703 }
704 }
705
706 this.element.trigger( event, data );
707 return !( $.isFunction( callback ) &&
708 callback.apply( this.element[0], [ event ].concat( data ) ) === false ||
709 event.isDefaultPrevented() );
710 }
711 };
712
713 $.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {
714 $.Widget.prototype[ "_" + method ] = function( element, options, callback ) {
715 if ( typeof options === "string" ) {
716 options = { effect: options };
717 }
718 var hasOptions,
719 effectName = !options ?
720 method :
721 options === true || typeof options === "number" ?
722 defaultEffect :
723 options.effect || defaultEffect;
724 options = options || {};
725 if ( typeof options === "number" ) {
726 options = { duration: options };
727 }
728 hasOptions = !$.isEmptyObject( options );
729 options.complete = callback;
730 if ( options.delay ) {
731 element.delay( options.delay );
732 }
733 if ( hasOptions && $.effects && ( $.effects.effect[ effectName ] || $.uiBackCompat !== false && $.effects[ effectName ] ) ) {
734 element[ method ]( options );
735 } else if ( effectName !== method && element[ effectName ] ) {
736 element[ effectName ]( options.duration, options.easing, callback );
737 } else {
738 element.queue(function( next ) {
739 $( this )[ method ]();
740 if ( callback ) {
741 callback.call( element[ 0 ] );
742 }
743 next();
744 });
745 }
746 };
747 });
748
749 // DEPRECATED
750 if ( $.uiBackCompat !== false ) {
751 $.Widget.prototype._getCreateOptions = function() {
752 return $.metadata && $.metadata.get( this.element[0] )[ this.widgetName ];
753 };
754 }
755
756 })( jQuery );
757 /*!
758 * jQuery UI Mouse @VERSION
759 *
760 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
761 * Dual licensed under the MIT or GPL Version 2 licenses.
762 * http://jquery.org/license
763 *
764 * http://docs.jquery.com/UI/Mouse
765 *
766 * Depends:
767 * jquery.ui.widget.js
768 */
769 (function( $, undefined ) {
770
771 var mouseHandled = false;
772 $( document ).mouseup( function( e ) {
773 mouseHandled = false;
774 });
775
776 $.widget("ui.mouse", {
777 version: "@VERSION",
778 options: {
779 cancel: ':input,option',
780 distance: 1,
781 delay: 0
782 },
783 _mouseInit: function() {
784 var self = this;
785
786 this.element
787 .bind('mousedown.'+this.widgetName, function(event) {
788 return self._mouseDown(event);
789 })
790 .bind('click.'+this.widgetName, function(event) {
791 if (true === $.data(event.target, self.widgetName + '.preventClickEvent')) {
792 $.removeData(event.target, self.widgetName + '.preventClickEvent');
793 event.stopImmediatePropagation();
794 return false;
795 }
796 });
797
798 this.started = false;
799 },
800
801 // TODO: make sure destroying one instance of mouse doesn't mess with
802 // other instances of mouse
803 _mouseDestroy: function() {
804 this.element.unbind('.'+this.widgetName);
805 },
806
807 _mouseDown: function(event) {
808 // don't let more than one widget handle mouseStart
809 if( mouseHandled ) { return };
810
811 // we may have missed mouseup (out of window)
812 (this._mouseStarted && this._mouseUp(event));
813
814 this._mouseDownEvent = event;
815
816 var self = this,
817 btnIsLeft = (event.which == 1),
818 // event.target.nodeName works around a bug in IE 8 with
819 // disabled inputs (#7620)
820 elIsCancel = (typeof this.options.cancel == "string" && event.target.nodeName ? $(event.target).closest(this.options.cancel).length : false);
821 if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
822 return true;
823 }
824
825 this.mouseDelayMet = !this.options.delay;
826 if (!this.mouseDelayMet) {
827 this._mouseDelayTimer = setTimeout(function() {
828 self.mouseDelayMet = true;
829 }, this.options.delay);
830 }
831
832 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
833 this._mouseStarted = (this._mouseStart(event) !== false);
834 if (!this._mouseStarted) {
835 event.preventDefault();
836 return true;
837 }
838 }
839
840 // Click event may never have fired (Gecko & Opera)
841 if (true === $.data(event.target, this.widgetName + '.preventClickEvent')) {
842 $.removeData(event.target, this.widgetName + '.preventClickEvent');
843 }
844
845 // these delegates are required to keep context
846 this._mouseMoveDelegate = function(event) {
847 return self._mouseMove(event);
848 };
849 this._mouseUpDelegate = function(event) {
850 return self._mouseUp(event);
851 };
852 $(document)
853 .bind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
854 .bind('mouseup.'+this.widgetName, this._mouseUpDelegate);
855
856 event.preventDefault();
857
858 mouseHandled = true;
859 return true;
860 },
861
862 _mouseMove: function(event) {
863 // IE mouseup check - mouseup happened when mouse was out of window
864 if ($.browser.msie && !(document.documentMode >= 9) && !event.button) {
865 return this._mouseUp(event);
866 }
867
868 if (this._mouseStarted) {
869 this._mouseDrag(event);
870 return event.preventDefault();
871 }
872
873 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
874 this._mouseStarted =
875 (this._mouseStart(this._mouseDownEvent, event) !== false);
876 (this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
877 }
878
879 return !this._mouseStarted;
880 },
881
882 _mouseUp: function(event) {
883 $(document)
884 .unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
885 .unbind('mouseup.'+this.widgetName, this._mouseUpDelegate);
886
887 if (this._mouseStarted) {
888 this._mouseStarted = false;
889
890 if (event.target == this._mouseDownEvent.target) {
891 $.data(event.target, this.widgetName + '.preventClickEvent', true);
892 }
893
894 this._mouseStop(event);
895 }
896
897 return false;
898 },
899
900 _mouseDistanceMet: function(event) {
901 return (Math.max(
902 Math.abs(this._mouseDownEvent.pageX - event.pageX),
903 Math.abs(this._mouseDownEvent.pageY - event.pageY)
904 ) >= this.options.distance
905 );
906 },
907
908 _mouseDelayMet: function(event) {
909 return this.mouseDelayMet;
910 },
911
912 // These are placeholder methods, to be overriden by extending plugin
913 _mouseStart: function(event) {},
914 _mouseDrag: function(event) {},
915 _mouseStop: function(event) {},
916 _mouseCapture: function(event) { return true; }
917 });
918
919 })(jQuery);
920 /*
921 * jQuery UI Draggable @VERSION
922 *
923 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
924 * Dual licensed under the MIT or GPL Version 2 licenses.
925 * http://jquery.org/license
926 *
927 * http://docs.jquery.com/UI/Draggables
928 *
929 * Depends:
930 * jquery.ui.core.js
931 * jquery.ui.mouse.js
932 * jquery.ui.widget.js
933 */
934 (function( $, undefined ) {
935
936 $.widget("ui.draggable", $.ui.mouse, {
937 version: "@VERSION",
938 widgetEventPrefix: "drag",
939 options: {
940 addClasses: true,
941 appendTo: "parent",
942 axis: false,
943 connectToSortable: false,
944 containment: false,
945 cursor: "auto",
946 cursorAt: false,
947 grid: false,
948 handle: false,
949 helper: "original",
950 iframeFix: false,
951 opacity: false,
952 refreshPositions: false,
953 revert: false,
954 revertDuration: 500,
955 scope: "default",
956 scroll: true,
957 scrollSensitivity: 20,
958 scrollSpeed: 20,
959 snap: false,
960 snapMode: "both",
961 snapTolerance: 20,
962 stack: false,
963 zIndex: false
964 },
965 _create: function() {
966
967 if (this.options.helper == 'original' && !(/^(?:r|a|f)/).test(this.element.css("position")))
968 this.element[0].style.position = 'relative';
969
970 (this.options.addClasses && this.element.addClass("ui-draggable"));
971 (this.options.disabled && this.element.addClass("ui-draggable-disabled"));
972
973 this._mouseInit();
974
975 },
976
977 destroy: function() {
978 if(!this.element.data('draggable')) return;
979 this.element
980 .removeData("draggable")
981 .unbind(".draggable")
982 .removeClass("ui-draggable"
983 + " ui-draggable-dragging"
984 + " ui-draggable-disabled");
985 this._mouseDestroy();
986
987 return this;
988 },
989
990 _mouseCapture: function(event) {
991
992 var o = this.options;
993
994 // among others, prevent a drag on a resizable-handle
995 if (this.helper || o.disabled || $(event.target).is('.ui-resizable-handle'))
996 return false;
997
998 //Quit if we're not on a valid handle
999 this.handle = this._getHandle(event);
1000 if (!this.handle)
1001 return false;
1002
1003 $(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() {
1004 $('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>')
1005 .css({
1006 width: this.offsetWidth+"px", height: this.offsetHeight+"px",
1007 position: "absolute", opacity: "0.001", zIndex: 1000
1008 })
1009 .css($(this).offset())
1010 .appendTo("body");
1011 });
1012
1013 return true;
1014
1015 },
1016
1017 _mouseStart: function(event) {
1018
1019 var o = this.options;
1020
1021 //Create and append the visible helper
1022 this.helper = this._createHelper(event);
1023
1024 //Cache the helper size
1025 this._cacheHelperProportions();
1026
1027 //If ddmanager is used for droppables, set the global draggable
1028 if($.ui.ddmanager)
1029 $.ui.ddmanager.current = this;
1030
1031 /*
1032 * - Position generation -
1033 * This block generates everything position related - it's the core of draggables.
1034 */
1035
1036 //Cache the margins of the original element
1037 this._cacheMargins();
1038
1039 //Store the helper's css position
1040 this.cssPosition = this.helper.css("position");
1041 this.scrollParent = this.helper.scrollParent();
1042
1043 //The element's absolute position on the page minus margins
1044 this.offset = this.positionAbs = this.element.offset();
1045 this.offset = {
1046 top: this.offset.top - this.margins.top,
1047 left: this.offset.left - this.margins.left
1048 };
1049
1050 $.extend(this.offset, {
1051 click: { //Where the click happened, relative to the element
1052 left: event.pageX - this.offset.left,
1053 top: event.pageY - this.offset.top
1054 },
1055 parent: this._getParentOffset(),
1056 relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
1057 });
1058
1059 //Generate the original position
1060 this.originalPosition = this.position = this._generatePosition(event);
1061 this.originalPageX = event.pageX;
1062 this.originalPageY = event.pageY;
1063
1064 //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
1065 (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
1066
1067 //Set a containment if given in the options
1068 if(o.containment)
1069 this._setContainment();
1070
1071 //Trigger event + callbacks
1072 if(this._trigger("start", event) === false) {
1073 this._clear();
1074 return false;
1075 }
1076
1077 //Recache the helper size
1078 this._cacheHelperProportions();
1079
1080 //Prepare the droppable offsets
1081 if ($.ui.ddmanager && !o.dropBehaviour)
1082 $.ui.ddmanager.prepareOffsets(this, event);
1083
1084 this.helper.addClass("ui-draggable-dragging");
1085 this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position
1086
1087 //If the ddmanager is used for droppables, inform the manager that dragging has started (see #5003)
1088 if ( $.ui.ddmanager ) $.ui.ddmanager.dragStart(this, event);
1089
1090 return true;
1091 },
1092
1093 _mouseDrag: function(event, noPropagation) {
1094
1095 //Compute the helpers position
1096 this.position = this._generatePosition(event);
1097 this.positionAbs = this._convertPositionTo("absolute");
1098
1099 //Call plugins and callbacks and use the resulting position if something is returned
1100 if (!noPropagation) {
1101 var ui = this._uiHash();
1102 if(this._trigger('drag', event, ui) === false) {
1103 this._mouseUp({});
1104 return false;
1105 }
1106 this.position = ui.position;
1107 }
1108
1109 if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
1110 if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
1111 if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
1112
1113 return false;
1114 },
1115
1116 _mouseStop: function(event) {
1117
1118 //If we are using droppables, inform the manager about the drop
1119 var dropped = false;
1120 if ($.ui.ddmanager && !this.options.dropBehaviour)
1121 dropped = $.ui.ddmanager.drop(this, event);
1122
1123 //if a drop comes from outside (a sortable)
1124 if(this.dropped) {
1125 dropped = this.dropped;
1126 this.dropped = false;
1127 }
1128
1129 //if the original element is removed, don't bother to continue
1130 if((!this.element[0] || !this.element[0].parentNode) && this.options.helper === "original")
1131 return false;
1132
1133 if((this.options.revert == "invalid" && !dropped) || (this.options.revert == "valid" && dropped) || this.options.revert === true || ($.isFunction(this.options.revert) && this.options.revert.call(this.element, dropped))) {
1134 var self = this;
1135 $(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() {
1136 if(self._trigger("stop", event) !== false) {
1137 self._clear();
1138 }
1139 });
1140 } else {
1141 if(this._trigger("stop", event) !== false) {
1142 this._clear();
1143 }
1144 }
1145
1146 return false;
1147 },
1148
1149 _mouseUp: function(event) {
1150 if (this.options.iframeFix === true) {
1151 $("div.ui-draggable-iframeFix").each(function() {
1152 this.parentNode.removeChild(this);
1153 }); //Remove frame helpers
1154 }
1155
1156 //If the ddmanager is used for droppables, inform the manager that dragging has stopped (see #5003)
1157 if( $.ui.ddmanager ) $.ui.ddmanager.dragStop(this, event);
1158
1159 return $.ui.mouse.prototype._mouseUp.call(this, event);
1160 },
1161
1162 cancel: function() {
1163
1164 if(this.helper.is(".ui-draggable-dragging")) {
1165 this._mouseUp({});
1166 } else {
1167 this._clear();
1168 }
1169
1170 return this;
1171
1172 },
1173
1174 _getHandle: function(event) {
1175
1176 var handle = !this.options.handle || !$(this.options.handle, this.element).length ? true : false;
1177 $(this.options.handle, this.element)
1178 .find("*")
1179 .andSelf()
1180 .each(function() {
1181 if(this == event.target) handle = true;
1182 });
1183
1184 return handle;
1185
1186 },
1187
1188 _createHelper: function(event) {
1189
1190 var o = this.options;
1191 var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper == 'clone' ? this.element.clone().removeAttr('id') : this.element);
1192
1193 if(!helper.parents('body').length)
1194 helper.appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo));
1195
1196 if(helper[0] != this.element[0] && !(/(fixed|absolute)/).test(helper.css("position")))
1197 helper.css("position", "absolute");
1198
1199 return helper;
1200
1201 },
1202
1203 _adjustOffsetFromHelper: function(obj) {
1204 if (typeof obj == 'string') {
1205 obj = obj.split(' ');
1206 }
1207 if ($.isArray(obj)) {
1208 obj = {left: +obj[0], top: +obj[1] || 0};
1209 }
1210 if ('left' in obj) {
1211 this.offset.click.left = obj.left + this.margins.left;
1212 }
1213 if ('right' in obj) {
1214 this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
1215 }
1216 if ('top' in obj) {
1217 this.offset.click.top = obj.top + this.margins.top;
1218 }
1219 if ('bottom' in obj) {
1220 this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
1221 }
1222 },
1223
1224 _getParentOffset: function() {
1225
1226 //Get the offsetParent and cache its position
1227 this.offsetParent = this.helper.offsetParent();
1228 var po = this.offsetParent.offset();
1229
1230 // This is a special case where we need to modify a offset calculated on start, since the following happened:
1231 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
1232 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
1233 // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
1234 if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.contains(this.scrollParent[0], this.offsetParent[0])) {
1235 po.left += this.scrollParent.scrollLeft();
1236 po.top += this.scrollParent.scrollTop();
1237 }
1238
1239 if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
1240 || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix
1241 po = { top: 0, left: 0 };
1242
1243 return {
1244 top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
1245 left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
1246 };
1247
1248 },
1249
1250 _getRelativeOffset: function() {
1251
1252 if(this.cssPosition == "relative") {
1253 var p = this.element.position();
1254 return {
1255 top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
1256 left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
1257 };
1258 } else {
1259 return { top: 0, left: 0 };
1260 }
1261
1262 },
1263
1264 _cacheMargins: function() {
1265 this.margins = {
1266 left: (parseInt(this.element.css("marginLeft"),10) || 0),
1267 top: (parseInt(this.element.css("marginTop"),10) || 0),
1268 right: (parseInt(this.element.css("marginRight"),10) || 0),
1269 bottom: (parseInt(this.element.css("marginBottom"),10) || 0)
1270 };
1271 },
1272
1273 _cacheHelperProportions: function() {
1274 this.helperProportions = {
1275 width: this.helper.outerWidth(),
1276 height: this.helper.outerHeight()
1277 };
1278 },
1279
1280 _setContainment: function() {
1281
1282 var o = this.options;
1283 if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
1284 if(o.containment == 'document' || o.containment == 'window') this.containment = [
1285 o.containment == 'document' ? 0 : $(window).scrollLeft() - this.offset.relative.left - this.offset.parent.left,
1286 o.containment == 'document' ? 0 : $(window).scrollTop() - this.offset.relative.top - this.offset.parent.top,
1287 (o.containment == 'document' ? 0 : $(window).scrollLeft()) + $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
1288 (o.containment == 'document' ? 0 : $(window).scrollTop()) + ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
1289 ];
1290
1291 if(!(/^(document|window|parent)$/).test(o.containment) && o.containment.constructor != Array) {
1292 var c = $(o.containment);
1293 var ce = c[0]; if(!ce) return;
1294 var co = c.offset();
1295 var over = ($(ce).css("overflow") != 'hidden');
1296
1297 this.containment = [
1298 (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0),
1299 (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0),
1300 (over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left - this.margins.right,
1301 (over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top - this.margins.bottom
1302 ];
1303 this.relative_container = c;
1304
1305 } else if(o.containment.constructor == Array) {
1306 this.containment = o.containment;
1307 }
1308
1309 },
1310
1311 _convertPositionTo: function(d, pos) {
1312
1313 if(!pos) pos = this.position;
1314 var mod = d == "absolute" ? 1 : -1;
1315 var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
1316
1317 return {
1318 top: (
1319 pos.top // The absolute mouse position
1320 + this.offset.relative.top * mod // Only for relative positioned nodes: Relative offset from element to offset parent
1321 + this.offset.parent.top * mod // The offsetParent's offset without borders (offset + border)
1322 - ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
1323 ),
1324 left: (
1325 pos.left // The absolute mouse position
1326 + this.offset.relative.left * mod // Only for relative positioned nodes: Relative offset from element to offset parent
1327 + this.offset.parent.left * mod // The offsetParent's offset without borders (offset + border)
1328 - ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
1329 )
1330 };
1331
1332 },
1333
1334 _generatePosition: function(event) {
1335
1336 var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
1337 var pageX = event.pageX;
1338 var pageY = event.pageY;
1339
1340 /*
1341 * - Position constraining -
1342 * Constrain the position to a mix of grid, containment.
1343 */
1344
1345 if(this.originalPosition) { //If we are not dragging yet, we won't check for options
1346 var containment;
1347 if(this.containment) {
1348 if (this.relative_container){
1349 var co = this.relative_container.offset();
1350 containment = [ this.containment[0] + co.left,
1351 this.containment[1] + co.top,
1352 this.containment[2] + co.left,
1353 this.containment[3] + co.top ];
1354 }
1355 else {
1356 containment = this.containment;
1357 }
1358
1359 if(event.pageX - this.offset.click.left < containment[0]) pageX = containment[0] + this.offset.click.left;
1360 if(event.pageY - this.offset.click.top < containment[1]) pageY = containment[1] + this.offset.click.top;
1361 if(event.pageX - this.offset.click.left > containment[2]) pageX = containment[2] + this.offset.click.left;
1362 if(event.pageY - this.offset.click.top > containment[3]) pageY = containment[3] + this.offset.click.top;
1363 }
1364
1365 if(o.grid) {
1366 //Check for grid elements set to 0 to prevent divide by 0 error causing invalid argument errors in IE (see ticket #6950)
1367 var top = o.grid[1] ? this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1] : this.originalPageY;
1368 pageY = containment ? (!(top - this.offset.click.top < containment[1] || top - this.offset.click.top > containment[3]) ? top : (!(top - this.offset.click.top < containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;
1369
1370 var left = o.grid[0] ? this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0] : this.originalPageX;
1371 pageX = containment ? (!(left - this.offset.click.left < containment[0] || left - this.offset.click.left > containment[2]) ? left : (!(left - this.offset.click.left < containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
1372 }
1373
1374 }
1375
1376 return {
1377 top: (
1378 pageY // The absolute mouse position
1379 - this.offset.click.top // Click offset (relative to the element)
1380 - this.offset.relative.top // Only for relative positioned nodes: Relative offset from element to offset parent
1381 - this.offset.parent.top // The offsetParent's offset without borders (offset + border)
1382 + ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
1383 ),
1384 left: (
1385 pageX // The absolute mouse position
1386 - this.offset.click.left // Click offset (relative to the element)
1387 - this.offset.relative.left // Only for relative positioned nodes: Relative offset from element to offset parent
1388 - this.offset.parent.left // The offsetParent's offset without borders (offset + border)
1389 + ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
1390 )
1391 };
1392
1393 },
1394
1395 _clear: function() {
1396 this.helper.removeClass("ui-draggable-dragging");
1397 if(this.helper[0] != this.element[0] && !this.cancelHelperRemoval) this.helper.remove();
1398 //if($.ui.ddmanager) $.ui.ddmanager.current = null;
1399 this.helper = null;
1400 this.cancelHelperRemoval = false;
1401 },
1402
1403 // From now on bulk stuff - mainly helpers
1404
1405 _trigger: function(type, event, ui) {
1406 ui = ui || this._uiHash();
1407 $.ui.plugin.call(this, type, [event, ui]);
1408 if(type == "drag") this.positionAbs = this._convertPositionTo("absolute"); //The absolute position has to be recalculated after plugins
1409 return $.Widget.prototype._trigger.call(this, type, event, ui);
1410 },
1411
1412 plugins: {},
1413
1414 _uiHash: function(event) {
1415 return {
1416 helper: this.helper,
1417 position: this.position,
1418 originalPosition: this.originalPosition,
1419 offset: this.positionAbs
1420 };
1421 }
1422
1423 });
1424
1425 $.ui.plugin.add("draggable", "connectToSortable", {
1426 start: function(event, ui) {
1427
1428 var inst = $(this).data("draggable"), o = inst.options,
1429 uiSortable = $.extend({}, ui, { item: inst.element });
1430 inst.sortables = [];
1431 $(o.connectToSortable).each(function() {
1432 var sortable = $.data(this, 'sortable');
1433 if (sortable && !sortable.options.disabled) {
1434 inst.sortables.push({
1435 instance: sortable,
1436 shouldRevert: sortable.options.revert
1437 });
1438 sortable.refreshPositions(); // Call the sortable's refreshPositions at drag start to refresh the containerCache since the sortable container cache is used in drag and needs to be up to date (this will ensure it's initialised as well as being kept in step with any changes that might have happened on the page).
1439 sortable._trigger("activate", event, uiSortable);
1440 }
1441 });
1442
1443 },
1444 stop: function(event, ui) {
1445
1446 //If we are still over the sortable, we fake the stop event of the sortable, but also remove helper
1447 var inst = $(this).data("draggable"),
1448 uiSortable = $.extend({}, ui, { item: inst.element });
1449
1450 $.each(inst.sortables, function() {
1451 if(this.instance.isOver) {
1452
1453 this.instance.isOver = 0;
1454
1455 inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance
1456 this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work)
1457
1458 //The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: 'valid/invalid'
1459 if(this.shouldRevert) this.instance.options.revert = true;
1460
1461 //Trigger the stop of the sortable
1462 this.instance._mouseStop(event);
1463
1464 this.instance.options.helper = this.instance.options._helper;
1465
1466 //If the helper has been the original item, restore properties in the sortable
1467 if(inst.options.helper == 'original')
1468 this.instance.currentItem.css({ top: 'auto', left: 'auto' });
1469
1470 } else {
1471 this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance
1472 this.instance._trigger("deactivate", event, uiSortable);
1473 }
1474
1475 });
1476
1477 },
1478 drag: function(event, ui) {
1479
1480 var inst = $(this).data("draggable"), self = this;
1481
1482 var checkPos = function(o) {
1483 var dyClick = this.offset.click.top, dxClick = this.offset.click.left;
1484 var helperTop = this.positionAbs.top, helperLeft = this.positionAbs.left;
1485 var itemHeight = o.height, itemWidth = o.width;
1486 var itemTop = o.top, itemLeft = o.left;
1487
1488 return $.ui.isOver(helperTop + dyClick, helperLeft + dxClick, itemTop, itemLeft, itemHeight, itemWidth);
1489 };
1490
1491 $.each(inst.sortables, function(i) {
1492
1493 //Copy over some variables to allow calling the sortable's native _intersectsWith
1494 this.instance.positionAbs = inst.positionAbs;
1495 this.instance.helperProportions = inst.helperProportions;
1496 this.instance.offset.click = inst.offset.click;
1497
1498 if(this.instance._intersectsWith(this.instance.containerCache)) {
1499
1500 //If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once
1501 if(!this.instance.isOver) {
1502
1503 this.instance.isOver = 1;
1504 //Now we fake the start of dragging for the sortable instance,
1505 //by cloning the list group item, appending it to the sortable and using it as inst.currentItem
1506 //We can then fire the start event of the sortable with our passed browser event, and our own helper (so it doesn't create a new one)
1507 this.instance.currentItem = $(self).clone().removeAttr('id').appendTo(this.instance.element).data("sortable-item", true);
1508 this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it
1509 this.instance.options.helper = function() { return ui.helper[0]; };
1510
1511 event.target = this.instance.currentItem[0];
1512 this.instance._mouseCapture(event, true);
1513 this.instance._mouseStart(event, true, true);
1514
1515 //Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes
1516 this.instance.offset.click.top = inst.offset.click.top;
1517 this.instance.offset.click.left = inst.offset.click.left;
1518 this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left;
1519 this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top;
1520
1521 inst._trigger("toSortable", event);
1522 inst.dropped = this.instance.element; //draggable revert needs that
1523 //hack so receive/update callbacks work (mostly)
1524 inst.currentItem = inst.element;
1525 this.instance.fromOutside = inst;
1526
1527 }
1528
1529 //Provided we did all the previous steps, we can fire the drag event of the sortable on every draggable drag, when it intersects with the sortable
1530 if(this.instance.currentItem) this.instance._mouseDrag(event);
1531
1532 } else {
1533
1534 //If it doesn't intersect with the sortable, and it intersected before,
1535 //we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval
1536 if(this.instance.isOver) {
1537
1538 this.instance.isOver = 0;
1539 this.instance.cancelHelperRemoval = true;
1540
1541 //Prevent reverting on this forced stop
1542 this.instance.options.revert = false;
1543
1544 // The out event needs to be triggered independently
1545 this.instance._trigger('out', event, this.instance._uiHash(this.instance));
1546
1547 this.instance._mouseStop(event, true);
1548 this.instance.options.helper = this.instance.options._helper;
1549
1550 //Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size
1551 this.instance.currentItem.remove();
1552 if(this.instance.placeholder) this.instance.placeholder.remove();
1553
1554 inst._trigger("fromSortable", event);
1555 inst.dropped = false; //draggable revert needs that
1556 }
1557
1558 };
1559
1560 });
1561
1562 }
1563 });
1564
1565 $.ui.plugin.add("draggable", "cursor", {
1566 start: function(event, ui) {
1567 var t = $('body'), o = $(this).data('draggable').options;
1568 if (t.css("cursor")) o._cursor = t.css("cursor");
1569 t.css("cursor", o.cursor);
1570 },
1571 stop: function(event, ui) {
1572 var o = $(this).data('draggable').options;
1573 if (o._cursor) $('body').css("cursor", o._cursor);
1574 }
1575 });
1576
1577 $.ui.plugin.add("draggable", "opacity", {
1578 start: function(event, ui) {
1579 var t = $(ui.helper), o = $(this).data('draggable').options;
1580 if(t.css("opacity")) o._opacity = t.css("opacity");
1581 t.css('opacity', o.opacity);
1582 },
1583 stop: function(event, ui) {
1584 var o = $(this).data('draggable').options;
1585 if(o._opacity) $(ui.helper).css('opacity', o._opacity);
1586 }
1587 });
1588
1589 $.ui.plugin.add("draggable", "scroll", {
1590 start: function(event, ui) {
1591 var i = $(this).data("draggable");
1592 if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') i.overflowOffset = i.scrollParent.offset();
1593 },
1594 drag: function(event, ui) {
1595
1596 var i = $(this).data("draggable"), o = i.options, scrolled = false;
1597
1598 if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') {
1599
1600 if(!o.axis || o.axis != 'x') {
1601 if((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
1602 i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed;
1603 else if(event.pageY - i.overflowOffset.top < o.scrollSensitivity)
1604 i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed;
1605 }
1606
1607 if(!o.axis || o.axis != 'y') {
1608 if((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
1609 i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed;
1610 else if(event.pageX - i.overflowOffset.left < o.scrollSensitivity)
1611 i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed;
1612 }
1613
1614 } else {
1615
1616 if(!o.axis || o.axis != 'x') {
1617 if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
1618 scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
1619 else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
1620 scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
1621 }
1622
1623 if(!o.axis || o.axis != 'y') {
1624 if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
1625 scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
1626 else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
1627 scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
1628 }
1629
1630 }
1631
1632 if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
1633 $.ui.ddmanager.prepareOffsets(i, event);
1634
1635 }
1636 });
1637
1638 $.ui.plugin.add("draggable", "snap", {
1639 start: function(event, ui) {
1640
1641 var i = $(this).data("draggable"), o = i.options;
1642 i.snapElements = [];
1643
1644 $(o.snap.constructor != String ? ( o.snap.items || ':data(draggable)' ) : o.snap).each(function() {
1645 var $t = $(this); var $o = $t.offset();
1646 if(this != i.element[0]) i.snapElements.push({
1647 item: this,
1648 width: $t.outerWidth(), height: $t.outerHeight(),
1649 top: $o.top, left: $o.left
1650 });
1651 });
1652
1653 },
1654 drag: function(event, ui) {
1655
1656 var inst = $(this).data("draggable"), o = inst.options;
1657 var d = o.snapTolerance;
1658
1659 var x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
1660 y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
1661
1662 for (var i = inst.snapElements.length - 1; i >= 0; i--){
1663
1664 var l = inst.snapElements[i].left, r = l + inst.snapElements[i].width,
1665 t = inst.snapElements[i].top, b = t + inst.snapElements[i].height;
1666
1667 //Yes, I know, this is insane ;)
1668 if(!((l-d < x1 && x1 < r+d && t-d < y1 && y1 < b+d) || (l-d < x1 && x1 < r+d && t-d < y2 && y2 < b+d) || (l-d < x2 && x2 < r+d && t-d < y1 && y1 < b+d) || (l-d < x2 && x2 < r+d && t-d < y2 && y2 < b+d))) {
1669 if(inst.snapElements[i].snapping) (inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
1670 inst.snapElements[i].snapping = false;
1671 continue;
1672 }
1673
1674 if(o.snapMode != 'inner') {
1675 var ts = Math.abs(t - y2) <= d;
1676 var bs = Math.abs(b - y1) <= d;
1677 var ls = Math.abs(l - x2) <= d;
1678 var rs = Math.abs(r - x1) <= d;
1679 if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
1680 if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top;
1681 if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left;
1682 if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left;
1683 }
1684
1685 var first = (ts || bs || ls || rs);
1686
1687 if(o.snapMode != 'outer') {
1688 var ts = Math.abs(t - y1) <= d;
1689 var bs = Math.abs(b - y2) <= d;
1690 var ls = Math.abs(l - x1) <= d;
1691 var rs = Math.abs(r - x2) <= d;
1692 if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top;
1693 if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
1694 if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left;
1695 if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left;
1696 }
1697
1698 if(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first))
1699 (inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
1700 inst.snapElements[i].snapping = (ts || bs || ls || rs || first);
1701
1702 };
1703
1704 }
1705 });
1706
1707 $.ui.plugin.add("draggable", "stack", {
1708 start: function(event, ui) {
1709
1710 var o = $(this).data("draggable").options;
1711
1712 var group = $.makeArray($(o.stack)).sort(function(a,b) {
1713 return (parseInt($(a).css("zIndex"),10) || 0) - (parseInt($(b).css("zIndex"),10) || 0);
1714 });
1715 if (!group.length) { return; }
1716
1717 var min = parseInt(group[0].style.zIndex) || 0;
1718 $(group).each(function(i) {
1719 this.style.zIndex = min + i;
1720 });
1721
1722 this[0].style.zIndex = min + group.length;
1723
1724 }
1725 });
1726
1727 $.ui.plugin.add("draggable", "zIndex", {
1728 start: function(event, ui) {
1729 var t = $(ui.helper), o = $(this).data("draggable").options;
1730 if(t.css("zIndex")) o._zIndex = t.css("zIndex");
1731 t.css('zIndex', o.zIndex);
1732 },
1733 stop: function(event, ui) {
1734 var o = $(this).data("draggable").options;
1735 if(o._zIndex) $(ui.helper).css('zIndex', o._zIndex);
1736 }
1737 });
1738
1739 })(jQuery);
1740 /*
1741 * jQuery UI Droppable @VERSION
1742 *
1743 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
1744 * Dual licensed under the MIT or GPL Version 2 licenses.
1745 * http://jquery.org/license
1746 *
1747 * http://docs.jquery.com/UI/Droppables
1748 *
1749 * Depends:
1750 * jquery.ui.core.js
1751 * jquery.ui.widget.js
1752 * jquery.ui.mouse.js
1753 * jquery.ui.draggable.js
1754 */
1755 (function( $, undefined ) {
1756
1757 $.widget("ui.droppable", {
1758 version: "@VERSION",
1759 widgetEventPrefix: "drop",
1760 options: {
1761 accept: '*',
1762 activeClass: false,
1763 addClasses: true,
1764 greedy: false,
1765 hoverClass: false,
1766 scope: 'default',
1767 tolerance: 'intersect'
1768 },
1769 _create: function() {
1770
1771 var o = this.options, accept = o.accept;
1772 this.isover = 0; this.isout = 1;
1773
1774 this.accept = $.isFunction(accept) ? accept : function(d) {
1775 return d.is(accept);
1776 };
1777
1778 //Store the droppable's proportions
1779 this.proportions = { width: this.element[0].offsetWidth, height: this.element[0].offsetHeight };
1780
1781 // Add the reference and positions to the manager
1782 $.ui.ddmanager.droppables[o.scope] = $.ui.ddmanager.droppables[o.scope] || [];
1783 $.ui.ddmanager.droppables[o.scope].push(this);
1784
1785 (o.addClasses && this.element.addClass("ui-droppable"));
1786
1787 },
1788
1789 destroy: function() {
1790 var drop = $.ui.ddmanager.droppables[this.options.scope];
1791 for ( var i = 0; i < drop.length; i++ )
1792 if ( drop[i] == this )
1793 drop.splice(i, 1);
1794
1795 this.element
1796 .removeClass("ui-droppable ui-droppable-disabled")
1797 .removeData("droppable")
1798 .unbind(".droppable");
1799
1800 return this;
1801 },
1802
1803 _setOption: function(key, value) {
1804
1805 if(key == 'accept') {
1806 this.accept = $.isFunction(value) ? value : function(d) {
1807 return d.is(value);
1808 };
1809 }
1810 $.Widget.prototype._setOption.apply(this, arguments);
1811 },
1812
1813 _activate: function(event) {
1814 var draggable = $.ui.ddmanager.current;
1815 if(this.options.activeClass) this.element.addClass(this.options.activeClass);
1816 (draggable && this._trigger('activate', event, this.ui(draggable)));
1817 },
1818
1819 _deactivate: function(event) {
1820 var draggable = $.ui.ddmanager.current;
1821 if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
1822 (draggable && this._trigger('deactivate', event, this.ui(draggable)));
1823 },
1824
1825 _over: function(event) {
1826
1827 var draggable = $.ui.ddmanager.current;
1828 if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
1829
1830 if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
1831 if(this.options.hoverClass) this.element.addClass(this.options.hoverClass);
1832 this._trigger('over', event, this.ui(draggable));
1833 }
1834
1835 },
1836
1837 _out: function(event) {
1838
1839 var draggable = $.ui.ddmanager.current;
1840 if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
1841
1842 if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
1843 if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
1844 this._trigger('out', event, this.ui(draggable));
1845 }
1846
1847 },
1848
1849 _drop: function(event,custom) {
1850
1851 var draggable = custom || $.ui.ddmanager.current;
1852 if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return false; // Bail if draggable and droppable are same element
1853
1854 var childrenIntersection = false;
1855 this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function() {
1856 var inst = $.data(this, 'droppable');
1857 if(
1858 inst.options.greedy
1859 && !inst.options.disabled
1860 && inst.options.scope == draggable.options.scope
1861 && inst.accept.call(inst.element[0], (draggable.currentItem || draggable.element))
1862 && $.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance)
1863 ) { childrenIntersection = true; return false; }
1864 });
1865 if(childrenIntersection) return false;
1866
1867 if(this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
1868 if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
1869 if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
1870 this._trigger('drop', event, this.ui(draggable));
1871 return this.element;
1872 }
1873
1874 return false;
1875
1876 },
1877
1878 ui: function(c) {
1879 return {
1880 draggable: (c.currentItem || c.element),
1881 helper: c.helper,
1882 position: c.position,
1883 offset: c.positionAbs
1884 };
1885 }
1886
1887 });
1888
1889 $.ui.intersect = function(draggable, droppable, toleranceMode) {
1890
1891 if (!droppable.offset) return false;
1892
1893 var x1 = (draggable.positionAbs || draggable.position.absolute).left, x2 = x1 + draggable.helperProportions.width,
1894 y1 = (draggable.positionAbs || draggable.position.absolute).top, y2 = y1 + draggable.helperProportions.height;
1895 var l = droppable.offset.left, r = l + droppable.proportions.width,
1896 t = droppable.offset.top, b = t + droppable.proportions.height;
1897
1898 switch (toleranceMode) {
1899 case 'fit':
1900 return (l <= x1 && x2 <= r
1901 && t <= y1 && y2 <= b);
1902 break;
1903 case 'intersect':
1904 return (l < x1 + (draggable.helperProportions.width / 2) // Right Half
1905 && x2 - (draggable.helperProportions.width / 2) < r // Left Half
1906 && t < y1 + (draggable.helperProportions.height / 2) // Bottom Half
1907 && y2 - (draggable.helperProportions.height / 2) < b ); // Top Half
1908 break;
1909 case 'pointer':
1910 var draggableLeft = ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left),
1911 draggableTop = ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top),
1912 isOver = $.ui.isOver(draggableTop, draggableLeft, t, l, droppable.proportions.height, droppable.proportions.width);
1913 return isOver;
1914 break;
1915 case 'touch':
1916 return (
1917 (y1 >= t && y1 <= b) || // Top edge touching
1918 (y2 >= t && y2 <= b) || // Bottom edge touching
1919 (y1 < t && y2 > b) // Surrounded vertically
1920 ) && (
1921 (x1 >= l && x1 <= r) || // Left edge touching
1922 (x2 >= l && x2 <= r) || // Right edge touching
1923 (x1 < l && x2 > r) // Surrounded horizontally
1924 );
1925 break;
1926 default:
1927 return false;
1928 break;
1929 }
1930
1931 };
1932
1933 /*
1934 This manager tracks offsets of draggables and droppables
1935 */
1936 $.ui.ddmanager = {
1937 current: null,
1938 droppables: { 'default': [] },
1939 prepareOffsets: function(t, event) {
1940
1941 var m = $.ui.ddmanager.droppables[t.options.scope] || [];
1942 var type = event ? event.type : null; // workaround for #2317
1943 var list = (t.currentItem || t.element).find(":data(droppable)").andSelf();
1944
1945 droppablesLoop: for (var i = 0; i < m.length; i++) {
1946
1947 if(m[i].options.disabled || (t && !m[i].accept.call(m[i].element[0],(t.currentItem || t.element)))) continue; //No disabled and non-accepted
1948 for (var j=0; j < list.length; j++) { if(list[j] == m[i].element[0]) { m[i].proportions.height = 0; continue droppablesLoop; } }; //Filter out elements in the current dragged item
1949 m[i].visible = m[i].element.css("display") != "none"; if(!m[i].visible) continue; //If the element is not visible, continue
1950
1951 if(type == "mousedown") m[i]._activate.call(m[i], event); //Activate the droppable if used directly from draggables
1952
1953 m[i].offset = m[i].element.offset();
1954 m[i].proportions = { width: m[i].element[0].offsetWidth, height: m[i].element[0].offsetHeight };
1955
1956 }
1957
1958 },
1959 drop: function(draggable, event) {
1960
1961 var dropped = false;
1962 $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
1963
1964 if(!this.options) return;
1965 if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance))
1966 dropped = this._drop.call(this, event) || dropped;
1967
1968 if (!this.options.disabled && this.visible && this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
1969 this.isout = 1; this.isover = 0;
1970 this._deactivate.call(this, event);
1971 }
1972
1973 });
1974 return dropped;
1975
1976 },
1977 dragStart: function( draggable, event ) {
1978 //Listen for scrolling so that if the dragging causes scrolling the position of the droppables can be recalculated (see #5003)
1979 draggable.element.parentsUntil( "body" ).bind( "scroll.droppable", function() {
1980 if( !draggable.options.refreshPositions ) $.ui.ddmanager.prepareOffsets( draggable, event );
1981 });
1982 },
1983 drag: function(draggable, event) {
1984
1985 //If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse.
1986 if(draggable.options.refreshPositions) $.ui.ddmanager.prepareOffsets(draggable, event);
1987
1988 //Run through all droppables and check their positions based on specific tolerance options
1989 $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
1990
1991 if(this.options.disabled || this.greedyChild || !this.visible) return;
1992 var intersects = $.ui.intersect(draggable, this, this.options.tolerance);
1993
1994 var c = !intersects && this.isover == 1 ? 'isout' : (intersects && this.isover == 0 ? 'isover' : null);
1995 if(!c) return;
1996
1997 var parentInstance;
1998 if (this.options.greedy) {
1999 var parent = this.element.parents(':data(droppable):eq(0)');
2000 if (parent.length) {
2001 parentInstance = $.data(parent[0], 'droppable');
2002 parentInstance.greedyChild = (c == 'isover' ? 1 : 0);
2003 }
2004 }
2005
2006 // we just moved into a greedy child
2007 if (parentInstance && c == 'isover') {
2008 parentInstance['isover'] = 0;
2009 parentInstance['isout'] = 1;
2010 parentInstance._out.call(parentInstance, event);
2011 }
2012
2013 this[c] = 1; this[c == 'isout' ? 'isover' : 'isout'] = 0;
2014 this[c == "isover" ? "_over" : "_out"].call(this, event);
2015
2016 // we just moved out of a greedy child
2017 if (parentInstance && c == 'isout') {
2018 parentInstance['isout'] = 0;
2019 parentInstance['isover'] = 1;
2020 parentInstance._over.call(parentInstance, event);
2021 }
2022 });
2023
2024 },
2025 dragStop: function( draggable, event ) {
2026 draggable.element.parentsUntil( "body" ).unbind( "scroll.droppable" );
2027 //Call prepareOffsets one final time since IE does not fire return scroll events when overflow was caused by drag (see #5003)
2028 if( !draggable.options.refreshPositions ) $.ui.ddmanager.prepareOffsets( draggable, event );
2029 }
2030 };
2031
2032 })(jQuery);
2033 /*
2034 * jQuery UI Resizable @VERSION
2035 *
2036 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
2037 * Dual licensed under the MIT or GPL Version 2 licenses.
2038 * http://jquery.org/license
2039 *
2040 * http://docs.jquery.com/UI/Resizables
2041 *
2042 * Depends:
2043 * jquery.ui.core.js
2044 * jquery.ui.mouse.js
2045 * jquery.ui.widget.js
2046 */
2047 (function( $, undefined ) {
2048
2049 $.widget("ui.resizable", $.ui.mouse, {
2050 version: "@VERSION",
2051 widgetEventPrefix: "resize",
2052 options: {
2053 alsoResize: false,
2054 animate: false,
2055 animateDuration: "slow",
2056 animateEasing: "swing",
2057 aspectRatio: false,
2058 autoHide: false,
2059 containment: false,
2060 ghost: false,
2061 grid: false,
2062 handles: "e,s,se",
2063 helper: false,
2064 maxHeight: null,
2065 maxWidth: null,
2066 minHeight: 10,
2067 minWidth: 10,
2068 zIndex: 1000
2069 },
2070 _create: function() {
2071
2072 var self = this, o = this.options;
2073 this.element.addClass("ui-resizable");
2074
2075 $.extend(this, {
2076 _aspectRatio: !!(o.aspectRatio),
2077 aspectRatio: o.aspectRatio,
2078 originalElement: this.element,
2079 _proportionallyResizeElements: [],
2080 _helper: o.helper || o.ghost || o.animate ? o.helper || 'ui-resizable-helper' : null
2081 });
2082
2083 //Wrap the element if it cannot hold child nodes
2084 if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) {
2085
2086 //Opera fix for relative positioning
2087 if (/relative/.test(this.element.css('position')) && $.browser.opera)
2088 this.element.css({ position: 'relative', top: 'auto', left: 'auto' });
2089
2090 //Create a wrapper element and set the wrapper to the new current internal element
2091 this.element.wrap(
2092 $('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({
2093 position: this.element.css('position'),
2094 width: this.element.outerWidth(),
2095 height: this.element.outerHeight(),
2096 top: this.element.css('top'),
2097 left: this.element.css('left')
2098 })
2099 );
2100
2101 //Overwrite the original this.element
2102 this.element = this.element.parent().data(
2103 "resizable", this.element.data('resizable')
2104 );
2105
2106 this.elementIsWrapper = true;
2107
2108 //Move margins to the wrapper
2109 this.element.css({ marginLeft: this.originalElement.css("marginLeft"), marginTop: this.originalElement.css("marginTop"), marginRight: this.originalElement.css("marginRight"), marginBottom: this.originalElement.css("marginBottom") });
2110 this.originalElement.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0});
2111
2112 //Prevent Safari textarea resize
2113 this.originalResizeStyle = this.originalElement.css('resize');
2114 this.originalElement.css('resize', 'none');
2115
2116 //Push the actual element to our proportionallyResize internal array
2117 this._proportionallyResizeElements.push(this.originalElement.css({ position: 'static', zoom: 1, display: 'block' }));
2118
2119 // avoid IE jump (hard set the margin)
2120 this.originalElement.css({ margin: this.originalElement.css('margin') });
2121
2122 // fix handlers offset
2123 this._proportionallyResize();
2124
2125 }
2126
2127 this.handles = o.handles || (!$('.ui-resizable-handle', this.element).length ? "e,s,se" : { n: '.ui-resizable-n', e: '.ui-resizable-e', s: '.ui-resizable-s', w: '.ui-resizable-w', se: '.ui-resizable-se', sw: '.ui-resizable-sw', ne: '.ui-resizable-ne', nw: '.ui-resizable-nw' });
2128 if(this.handles.constructor == String) {
2129
2130 if(this.handles == 'all') this.handles = 'n,e,s,w,se,sw,ne,nw';
2131 var n = this.handles.split(","); this.handles = {};
2132
2133 for(var i = 0; i < n.length; i++) {
2134
2135 var handle = $.trim(n[i]), hname = 'ui-resizable-'+handle;
2136 var axis = $('<div class="ui-resizable-handle ' + hname + '"></div>');
2137
2138 // increase zIndex of sw, se, ne, nw axis
2139 //TODO : this modifies original option
2140 if(/sw|se|ne|nw/.test(handle)) axis.css({ zIndex: ++o.zIndex });
2141
2142 //TODO : What's going on here?
2143 if ('se' == handle) {
2144 axis.addClass('ui-icon ui-icon-gripsmall-diagonal-se');
2145 };
2146
2147 //Insert into internal handles object and append to element
2148 this.handles[handle] = '.ui-resizable-'+handle;
2149 this.element.append(axis);
2150 }
2151
2152 }
2153
2154 this._renderAxis = function(target) {
2155
2156 target = target || this.element;
2157
2158 for(var i in this.handles) {
2159
2160 if(this.handles[i].constructor == String)
2161 this.handles[i] = $(this.handles[i], this.element).show();
2162
2163 //Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls)
2164 if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) {
2165
2166 var axis = $(this.handles[i], this.element), padWrapper = 0;
2167
2168 //Checking the correct pad and border
2169 padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth();
2170
2171 //The padding type i have to apply...
2172 var padPos = [ 'padding',
2173 /ne|nw|n/.test(i) ? 'Top' :
2174 /se|sw|s/.test(i) ? 'Bottom' :
2175 /^e$/.test(i) ? 'Right' : 'Left' ].join("");
2176
2177 target.css(padPos, padWrapper);
2178
2179 this._proportionallyResize();
2180
2181 }
2182
2183 //TODO: What's that good for? There's not anything to be executed left
2184 if(!$(this.handles[i]).length)
2185 continue;
2186
2187 }
2188 };
2189
2190 //TODO: make renderAxis a prototype function
2191 this._renderAxis(this.element);
2192
2193 this._handles = $('.ui-resizable-handle', this.element)
2194 .disableSelection();
2195
2196 //Matching axis name
2197 this._handles.mouseover(function() {
2198 if (!self.resizing) {
2199 if (this.className)
2200 var axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);
2201 //Axis, default = se
2202 self.axis = axis && axis[1] ? axis[1] : 'se';
2203 }
2204 });
2205
2206 //If we want to auto hide the elements
2207 if (o.autoHide) {
2208 this._handles.hide();
2209 $(this.element)
2210 .addClass("ui-resizable-autohide")
2211 .hover(function() {
2212 if (o.disabled) return;
2213 $(this).removeClass("ui-resizable-autohide");
2214 self._handles.show();
2215 },
2216 function(){
2217 if (o.disabled) return;
2218 if (!self.resizing) {
2219 $(this).addClass("ui-resizable-autohide");
2220 self._handles.hide();
2221 }
2222 });
2223 }
2224
2225 //Initialize the mouse interaction
2226 this._mouseInit();
2227
2228 },
2229
2230 destroy: function() {
2231
2232 this._mouseDestroy();
2233
2234 var _destroy = function(exp) {
2235 $(exp).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing")
2236 .removeData("resizable").unbind(".resizable").find('.ui-resizable-handle').remove();
2237 };
2238
2239 //TODO: Unwrap at same DOM position
2240 if (this.elementIsWrapper) {
2241 _destroy(this.element);
2242 var wrapper = this.element;
2243 wrapper.after(
2244 this.originalElement.css({
2245 position: wrapper.css('position'),
2246 width: wrapper.outerWidth(),
2247 height: wrapper.outerHeight(),
2248 top: wrapper.css('top'),
2249 left: wrapper.css('left')
2250 })
2251 ).remove();
2252 }
2253
2254 this.originalElement.css('resize', this.originalResizeStyle);
2255 _destroy(this.originalElement);
2256
2257 return this;
2258 },
2259
2260 _mouseCapture: function(event) {
2261 var handle = false;
2262 for (var i in this.handles) {
2263 if ($(this.handles[i])[0] == event.target) {
2264 handle = true;
2265 }
2266 }
2267
2268 return !this.options.disabled && handle;
2269 },
2270
2271 _mouseStart: function(event) {
2272
2273 var o = this.options, iniPos = this.element.position(), el = this.element;
2274
2275 this.resizing = true;
2276 this.documentScroll = { top: $(document).scrollTop(), left: $(document).scrollLeft() };
2277
2278 // bugfix for http://dev.jquery.com/ticket/1749
2279 if (el.is('.ui-draggable') || (/absolute/).test(el.css('position'))) {
2280 el.css({ position: 'absolute', top: iniPos.top, left: iniPos.left });
2281 }
2282
2283 //Opera fixing relative position
2284 if ($.browser.opera && (/relative/).test(el.css('position')))
2285 el.css({ position: 'relative', top: 'auto', left: 'auto' });
2286
2287 this._renderProxy();
2288
2289 var curleft = num(this.helper.css('left')), curtop = num(this.helper.css('top'));
2290
2291 if (o.containment) {
2292 curleft += $(o.containment).scrollLeft() || 0;
2293 curtop += $(o.containment).scrollTop() || 0;
2294 }
2295
2296 //Store needed variables
2297 this.offset = this.helper.offset();
2298 this.position = { left: curleft, top: curtop };
2299 this.size = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
2300 this.originalSize = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
2301 this.originalPosition = { left: curleft, top: curtop };
2302 this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() };
2303 this.originalMousePosition = { left: event.pageX, top: event.pageY };
2304
2305 //Aspect Ratio
2306 this.aspectRatio = (typeof o.aspectRatio == 'number') ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1);
2307
2308 var cursor = $('.ui-resizable-' + this.axis).css('cursor');
2309 $('body').css('cursor', cursor == 'auto' ? this.axis + '-resize' : cursor);
2310
2311 el.addClass("ui-resizable-resizing");
2312 this._propagate("start", event);
2313 return true;
2314 },
2315
2316 _mouseDrag: function(event) {
2317
2318 //Increase performance, avoid regex
2319 var el = this.helper, o = this.options, props = {},
2320 self = this, smp = this.originalMousePosition, a = this.axis;
2321
2322 var dx = (event.pageX-smp.left)||0, dy = (event.pageY-smp.top)||0;
2323 var trigger = this._change[a];
2324 if (!trigger) return false;
2325
2326 // Calculate the attrs that will be change
2327 var data = trigger.apply(this, [event, dx, dy]);
2328
2329 // Put this in the mouseDrag handler since the user can start pressing shift while resizing
2330 this._updateVirtualBoundaries(event.shiftKey);
2331 if (this._aspectRatio || event.shiftKey)
2332 data = this._updateRatio(data, event);
2333
2334 data = this._respectSize(data, event);
2335
2336 // plugins callbacks need to be called first
2337 this._propagate("resize", event);
2338
2339 el.css({
2340 top: this.position.top + "px", left: this.position.left + "px",
2341 width: this.size.width + "px", height: this.size.height + "px"
2342 });
2343
2344 if (!this._helper && this._proportionallyResizeElements.length)
2345 this._proportionallyResize();
2346
2347 this._updateCache(data);
2348
2349 // calling the user callback at the end
2350 this._trigger('resize', event, this.ui());
2351
2352 return false;
2353 },
2354
2355 _mouseStop: function(event) {
2356
2357 this.resizing = false;
2358 var o = this.options, self = this;
2359
2360 if(this._helper) {
2361 var pr = this._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
2362 soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
2363 soffsetw = ista ? 0 : self.sizeDiff.width;
2364
2365 var s = { width: (self.helper.width() - soffsetw), height: (self.helper.height() - soffseth) },
2366 left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
2367 top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
2368
2369 if (!o.animate)
2370 this.element.css($.extend(s, { top: top, left: left }));
2371
2372 self.helper.height(self.size.height);
2373 self.helper.width(self.size.width);
2374
2375 if (this._helper && !o.animate) this._proportionallyResize();
2376 }
2377
2378 $('body').css('cursor', 'auto');
2379
2380 this.element.removeClass("ui-resizable-resizing");
2381
2382 this._propagate("stop", event);
2383
2384 if (this._helper) this.helper.remove();
2385 return false;
2386
2387 },
2388
2389 _updateVirtualBoundaries: function(forceAspectRatio) {
2390 var o = this.options, pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b;
2391
2392 b = {
2393 minWidth: isNumber(o.minWidth) ? o.minWidth : 0,
2394 maxWidth: isNumber(o.maxWidth) ? o.maxWidth : Infinity,
2395 minHeight: isNumber(o.minHeight) ? o.minHeight : 0,
2396 maxHeight: isNumber(o.maxHeight) ? o.maxHeight : Infinity
2397 };
2398
2399 if(this._aspectRatio || forceAspectRatio) {
2400 // We want to create an enclosing box whose aspect ration is the requested one
2401 // First, compute the "projected" size for each dimension based on the aspect ratio and other dimension
2402 pMinWidth = b.minHeight * this.aspectRatio;
2403 pMinHeight = b.minWidth / this.aspectRatio;
2404 pMaxWidth = b.maxHeight * this.aspectRatio;
2405 pMaxHeight = b.maxWidth / this.aspectRatio;
2406
2407 if(pMinWidth > b.minWidth) b.minWidth = pMinWidth;
2408 if(pMinHeight > b.minHeight) b.minHeight = pMinHeight;
2409 if(pMaxWidth < b.maxWidth) b.maxWidth = pMaxWidth;
2410 if(pMaxHeight < b.maxHeight) b.maxHeight = pMaxHeight;
2411 }
2412 this._vBoundaries = b;
2413 },
2414
2415 _updateCache: function(data) {
2416 var o = this.options;
2417 this.offset = this.helper.offset();
2418 if (isNumber(data.left)) this.position.left = data.left;
2419 if (isNumber(data.top)) this.position.top = data.top;
2420 if (isNumber(data.height)) this.size.height = data.height;
2421 if (isNumber(data.width)) this.size.width = data.width;
2422 },
2423
2424 _updateRatio: function(data, event) {
2425
2426 var o = this.options, cpos = this.position, csize = this.size, a = this.axis;
2427
2428 if (isNumber(data.height)) data.width = (data.height * this.aspectRatio);
2429 else if (isNumber(data.width)) data.height = (data.width / this.aspectRatio);
2430
2431 if (a == 'sw') {
2432 data.left = cpos.left + (csize.width - data.width);
2433 data.top = null;
2434 }
2435 if (a == 'nw') {
2436 data.top = cpos.top + (csize.height - data.height);
2437 data.left = cpos.left + (csize.width - data.width);
2438 }
2439
2440 return data;
2441 },
2442
2443 _respectSize: function(data, event) {
2444
2445 var el = this.helper, o = this._vBoundaries, pRatio = this._aspectRatio || event.shiftKey, a = this.axis,
2446 ismaxw = isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh = isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height),
2447 isminw = isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh = isNumber(data.height) && o.minHeight && (o.minHeight > data.height);
2448
2449 if (isminw) data.width = o.minWidth;
2450 if (isminh) data.height = o.minHeight;
2451 if (ismaxw) data.width = o.maxWidth;
2452 if (ismaxh) data.height = o.maxHeight;
2453
2454 var dw = this.originalPosition.left + this.originalSize.width, dh = this.position.top + this.size.height;
2455 var cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a);
2456
2457 if (isminw && cw) data.left = dw - o.minWidth;
2458 if (ismaxw && cw) data.left = dw - o.maxWidth;
2459 if (isminh && ch) data.top = dh - o.minHeight;
2460 if (ismaxh && ch) data.top = dh - o.maxHeight;
2461
2462 // fixing jump error on top/left - bug #2330
2463 var isNotwh = !data.width && !data.height;
2464 if (isNotwh && !data.left && data.top) data.top = null;
2465 else if (isNotwh && !data.top && data.left) data.left = null;
2466
2467 return data;
2468 },
2469
2470 _proportionallyResize: function() {
2471
2472 var o = this.options;
2473 if (!this._proportionallyResizeElements.length) return;
2474 var element = this.helper || this.element;
2475
2476 for (var i=0; i < this._proportionallyResizeElements.length; i++) {
2477
2478 var prel = this._proportionallyResizeElements[i];
2479
2480 if (!this.borderDif) {
2481 var b = [prel.css('borderTopWidth'), prel.css('borderRightWidth'), prel.css('borderBottomWidth'), prel.css('borderLeftWidth')],
2482 p = [prel.css('paddingTop'), prel.css('paddingRight'), prel.css('paddingBottom'), prel.css('paddingLeft')];
2483
2484 this.borderDif = $.map(b, function(v, i) {
2485 var border = parseInt(v,10)||0, padding = parseInt(p[i],10)||0;
2486 return border + padding;
2487 });
2488 }
2489
2490 if ($.browser.msie && !(!($(element).is(':hidden') || $(element).parents(':hidden').length)))
2491 continue;
2492
2493 prel.css({
2494 height: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0,
2495 width: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0
2496 });
2497
2498 };
2499
2500 },
2501
2502 _renderProxy: function() {
2503
2504 var el = this.element, o = this.options;
2505 this.elementOffset = el.offset();
2506
2507 if(this._helper) {
2508
2509 this.helper = this.helper || $('<div style="overflow:hidden;"></div>');
2510
2511 // fix ie6 offset TODO: This seems broken
2512 var ie6 = $.browser.msie && $.browser.version < 7, ie6offset = (ie6 ? 1 : 0),
2513 pxyoffset = ( ie6 ? 2 : -1 );
2514
2515 this.helper.addClass(this._helper).css({
2516 width: this.element.outerWidth() + pxyoffset,
2517 height: this.element.outerHeight() + pxyoffset,
2518 position: 'absolute',
2519 left: this.elementOffset.left - ie6offset +'px',
2520 top: this.elementOffset.top - ie6offset +'px',
2521 zIndex: ++o.zIndex //TODO: Don't modify option
2522 });
2523
2524 this.helper
2525 .appendTo("body")
2526 .disableSelection();
2527
2528 } else {
2529 this.helper = this.element;
2530 }
2531
2532 },
2533
2534 _change: {
2535 e: function(event, dx, dy) {
2536 return { width: this.originalSize.width + dx };
2537 },
2538 w: function(event, dx, dy) {
2539 var o = this.options, cs = this.originalSize, sp = this.originalPosition;
2540 return { left: sp.left + dx, width: cs.width - dx };
2541 },
2542 n: function(event, dx, dy) {
2543 var o = this.options, cs = this.originalSize, sp = this.originalPosition;
2544 return { top: sp.top + dy, height: cs.height - dy };
2545 },
2546 s: function(event, dx, dy) {
2547 return { height: this.originalSize.height + dy };
2548 },
2549 se: function(event, dx, dy) {
2550 return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
2551 },
2552 sw: function(event, dx, dy) {
2553 return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
2554 },
2555 ne: function(event, dx, dy) {
2556 return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
2557 },
2558 nw: function(event, dx, dy) {
2559 return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
2560 }
2561 },
2562
2563 _propagate: function(n, event) {
2564 $.ui.plugin.call(this, n, [event, this.ui()]);
2565 (n != "resize" && this._trigger(n, event, this.ui()));
2566 },
2567
2568 plugins: {},
2569
2570 ui: function() {
2571 return {
2572 originalElement: this.originalElement,
2573 element: this.element,
2574 helper: this.helper,
2575 position: this.position,
2576 size: this.size,
2577 originalSize: this.originalSize,
2578 originalPosition: this.originalPosition
2579 };
2580 }
2581
2582 });
2583
2584 /*
2585 * Resizable Extensions
2586 */
2587
2588 $.ui.plugin.add("resizable", "alsoResize", {
2589
2590 start: function (event, ui) {
2591 var self = $(this).data("resizable"), o = self.options;
2592
2593 var _store = function (exp) {
2594 $(exp).each(function() {
2595 var el = $(this);
2596 el.data("resizable-alsoresize", {
2597 width: parseInt(el.width(), 10), height: parseInt(el.height(), 10),
2598 left: parseInt(el.css('left'), 10), top: parseInt(el.css('top'), 10),
2599 position: el.css('position') // to reset Opera on stop()
2600 });
2601 });
2602 };
2603
2604 if (typeof(o.alsoResize) == 'object' && !o.alsoResize.parentNode) {
2605 if (o.alsoResize.length) { o.alsoResize = o.alsoResize[0]; _store(o.alsoResize); }
2606 else { $.each(o.alsoResize, function (exp) { _store(exp); }); }
2607 }else{
2608 _store(o.alsoResize);
2609 }
2610 },
2611
2612 resize: function (event, ui) {
2613 var self = $(this).data("resizable"), o = self.options, os = self.originalSize, op = self.originalPosition;
2614
2615 var delta = {
2616 height: (self.size.height - os.height) || 0, width: (self.size.width - os.width) || 0,
2617 top: (self.position.top - op.top) || 0, left: (self.position.left - op.left) || 0
2618 },
2619
2620 _alsoResize = function (exp, c) {
2621 $(exp).each(function() {
2622 var el = $(this), start = $(this).data("resizable-alsoresize"), style = {},
2623 css = c && c.length ? c : el.parents(ui.originalElement[0]).length ? ['width', 'height'] : ['width', 'height', 'top', 'left'];
2624
2625 $.each(css, function (i, prop) {
2626 var sum = (start[prop]||0) + (delta[prop]||0);
2627 if (sum && sum >= 0)
2628 style[prop] = sum || null;
2629 });
2630
2631 // Opera fixing relative position
2632 if ($.browser.opera && /relative/.test(el.css('position'))) {
2633 self._revertToRelativePosition = true;
2634 el.css({ position: 'absolute', top: 'auto', left: 'auto' });
2635 }
2636
2637 el.css(style);
2638 });
2639 };
2640
2641 if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) {
2642 $.each(o.alsoResize, function (exp, c) { _alsoResize(exp, c); });
2643 }else{
2644 _alsoResize(o.alsoResize);
2645 }
2646 },
2647
2648 stop: function (event, ui) {
2649 var self = $(this).data("resizable"), o = self.options;
2650
2651 var _reset = function (exp) {
2652 $(exp).each(function() {
2653 var el = $(this);
2654 // reset position for Opera - no need to verify it was changed
2655 el.css({ position: el.data("resizable-alsoresize").position });
2656 });
2657 };
2658
2659 if (self._revertToRelativePosition) {
2660 self._revertToRelativePosition = false;
2661 if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) {
2662 $.each(o.alsoResize, function (exp) { _reset(exp); });
2663 }else{
2664 _reset(o.alsoResize);
2665 }
2666 }
2667
2668 $(this).removeData("resizable-alsoresize");
2669 }
2670 });
2671
2672 $.ui.plugin.add("resizable", "animate", {
2673
2674 stop: function(event, ui) {
2675 var self = $(this).data("resizable"), o = self.options;
2676
2677 var pr = self._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
2678 soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
2679 soffsetw = ista ? 0 : self.sizeDiff.width;
2680
2681 var style = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },
2682 left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
2683 top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
2684
2685 self.element.animate(
2686 $.extend(style, top && left ? { top: top, left: left } : {}), {
2687 duration: o.animateDuration,
2688 easing: o.animateEasing,
2689 step: function() {
2690
2691 var data = {
2692 width: parseInt(self.element.css('width'), 10),
2693 height: parseInt(self.element.css('height'), 10),
2694 top: parseInt(self.element.css('top'), 10),
2695 left: parseInt(self.element.css('left'), 10)
2696 };
2697
2698 if (pr && pr.length) $(pr[0]).css({ width: data.width, height: data.height });
2699
2700 // propagating resize, and updating values for each animation step
2701 self._updateCache(data);
2702 self._propagate("resize", event);
2703
2704 }
2705 }
2706 );
2707 }
2708
2709 });
2710
2711 $.ui.plugin.add("resizable", "containment", {
2712
2713 start: function(event, ui) {
2714 var self = $(this).data("resizable"), o = self.options, el = self.element;
2715 var oc = o.containment, ce = (oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc;
2716 if (!ce) return;
2717
2718 self.containerElement = $(ce);
2719
2720 if (/document/.test(oc) || oc == document) {
2721 self.containerOffset = { left: 0, top: 0 };
2722 self.containerPosition = { left: 0, top: 0 };
2723
2724 self.parentData = {
2725 element: $(document), left: 0, top: 0,
2726 width: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight
2727 };
2728 }
2729
2730 // i'm a node, so compute top, left, right, bottom
2731 else {
2732 var element = $(ce), p = [];
2733 $([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) { p[i] = num(element.css("padding" + name)); });
2734
2735 self.containerOffset = element.offset();
2736 self.containerPosition = element.position();
2737 self.containerSize = { height: (element.innerHeight() - p[3]), width: (element.innerWidth() - p[1]) };
2738
2739 var co = self.containerOffset, ch = self.containerSize.height, cw = self.containerSize.width,
2740 width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw ), height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch);
2741
2742 self.parentData = {
2743 element: ce, left: co.left, top: co.top, width: width, height: height
2744 };
2745 }
2746 },
2747
2748 resize: function(event, ui) {
2749 var self = $(this).data("resizable"), o = self.options,
2750 ps = self.containerSize, co = self.containerOffset, cs = self.size, cp = self.position,
2751 pRatio = self._aspectRatio || event.shiftKey, cop = { top:0, left:0 }, ce = self.containerElement;
2752
2753 if (ce[0] != document && (/static/).test(ce.css('position'))) cop = co;
2754
2755 if (cp.left < (self._helper ? co.left : 0)) {
2756 self.size.width = self.size.width + (self._helper ? (self.position.left - co.left) : (self.position.left - cop.left));
2757 if (pRatio) self.size.height = self.size.width / o.aspectRatio;
2758 self.position.left = o.helper ? co.left : 0;
2759 }
2760
2761 if (cp.top < (self._helper ? co.top : 0)) {
2762 self.size.height = self.size.height + (self._helper ? (self.position.top - co.top) : self.position.top);
2763 if (pRatio) self.size.width = self.size.height * o.aspectRatio;
2764 self.position.top = self._helper ? co.top : 0;
2765 }
2766
2767 self.offset.left = self.parentData.left+self.position.left;
2768 self.offset.top = self.parentData.top+self.position.top;
2769
2770 var woset = Math.abs( (self._helper ? self.offset.left - cop.left : (self.offset.left - cop.left)) + self.sizeDiff.width ),
2771 hoset = Math.abs( (self._helper ? self.offset.top - cop.top : (self.offset.top - co.top)) + self.sizeDiff.height );
2772
2773 var isParent = self.containerElement.get(0) == self.element.parent().get(0),
2774 isOffsetRelative = /relative|absolute/.test(self.containerElement.css('position'));
2775
2776 if(isParent && isOffsetRelative) woset -= self.parentData.left;
2777
2778 if (woset + self.size.width >= self.parentData.width) {
2779 self.size.width = self.parentData.width - woset;
2780 if (pRatio) self.size.height = self.size.width / self.aspectRatio;
2781 }
2782
2783 if (hoset + self.size.height >= self.parentData.height) {
2784 self.size.height = self.parentData.height - hoset;
2785 if (pRatio) self.size.width = self.size.height * self.aspectRatio;
2786 }
2787 },
2788
2789 stop: function(event, ui){
2790 var self = $(this).data("resizable"), o = self.options, cp = self.position,
2791 co = self.containerOffset, cop = self.containerPosition, ce = self.containerElement;
2792
2793 var helper = $(self.helper), ho = helper.offset(), w = helper.outerWidth() - self.sizeDiff.width, h = helper.outerHeight() - self.sizeDiff.height;
2794
2795 if (self._helper && !o.animate && (/relative/).test(ce.css('position')))
2796 $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
2797
2798 if (self._helper && !o.animate && (/static/).test(ce.css('position')))
2799 $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
2800
2801 }
2802 });
2803
2804 $.ui.plugin.add("resizable", "ghost", {
2805
2806 start: function(event, ui) {
2807
2808 var self = $(this).data("resizable"), o = self.options, cs = self.size;
2809
2810 self.ghost = self.originalElement.clone();
2811 self.ghost
2812 .css({ opacity: .25, display: 'block', position: 'relative', height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 })
2813 .addClass('ui-resizable-ghost')
2814 .addClass(typeof o.ghost == 'string' ? o.ghost : '');
2815
2816 self.ghost.appendTo(self.helper);
2817
2818 },
2819
2820 resize: function(event, ui){
2821 var self = $(this).data("resizable"), o = self.options;
2822 if (self.ghost) self.ghost.css({ position: 'relative', height: self.size.height, width: self.size.width });
2823 },
2824
2825 stop: function(event, ui){
2826 var self = $(this).data("resizable"), o = self.options;
2827 if (self.ghost && self.helper) self.helper.get(0).removeChild(self.ghost.get(0));
2828 }
2829
2830 });
2831
2832 $.ui.plugin.add("resizable", "grid", {
2833
2834 resize: function(event, ui) {
2835 var self = $(this).data("resizable"), o = self.options, cs = self.size, os = self.originalSize, op = self.originalPosition, a = self.axis, ratio = o._aspectRatio || event.shiftKey;
2836 o.grid = typeof o.grid == "number" ? [o.grid, o.grid] : o.grid;
2837 var ox = Math.round((cs.width - os.width) / (o.grid[0]||1)) * (o.grid[0]||1), oy = Math.round((cs.height - os.height) / (o.grid[1]||1)) * (o.grid[1]||1);
2838
2839 if (/^(se|s|e)$/.test(a)) {
2840 self.size.width = os.width + ox;
2841 self.size.height = os.height + oy;
2842 }
2843 else if (/^(ne)$/.test(a)) {
2844 self.size.width = os.width + ox;
2845 self.size.height = os.height + oy;
2846 self.position.top = op.top - oy;
2847 }
2848 else if (/^(sw)$/.test(a)) {
2849 self.size.width = os.width + ox;
2850 self.size.height = os.height + oy;
2851 self.position.left = op.left - ox;
2852 }
2853 else {
2854 self.size.width = os.width + ox;
2855 self.size.height = os.height + oy;
2856 self.position.top = op.top - oy;
2857 self.position.left = op.left - ox;
2858 }
2859 }
2860
2861 });
2862
2863 var num = function(v) {
2864 return parseInt(v, 10) || 0;
2865 };
2866
2867 var isNumber = function(value) {
2868 return !isNaN(parseInt(value, 10));
2869 };
2870
2871 })(jQuery);
2872 /*
2873 * jQuery UI Selectable @VERSION
2874 *
2875 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
2876 * Dual licensed under the MIT or GPL Version 2 licenses.
2877 * http://jquery.org/license
2878 *
2879 * http://docs.jquery.com/UI/Selectables
2880 *
2881 * Depends:
2882 * jquery.ui.core.js
2883 * jquery.ui.mouse.js
2884 * jquery.ui.widget.js
2885 */
2886 (function( $, undefined ) {
2887
2888 $.widget("ui.selectable", $.ui.mouse, {
2889 version: "@VERSION",
2890 options: {
2891 appendTo: 'body',
2892 autoRefresh: true,
2893 distance: 0,
2894 filter: '*',
2895 tolerance: 'touch'
2896 },
2897 _create: function() {
2898 var self = this;
2899
2900 this.element.addClass("ui-selectable");
2901
2902 this.dragged = false;
2903
2904 // cache selectee children based on filter
2905 var selectees;
2906 this.refresh = function() {
2907 selectees = $(self.options.filter, self.element[0]);
2908 selectees.addClass("ui-selectee");
2909 selectees.each(function() {
2910 var $this = $(this);
2911 var pos = $this.offset();
2912 $.data(this, "selectable-item", {
2913 element: this,
2914 $element: $this,
2915 left: pos.left,
2916 top: pos.top,
2917 right: pos.left + $this.outerWidth(),
2918 bottom: pos.top + $this.outerHeight(),
2919 startselected: false,
2920 selected: $this.hasClass('ui-selected'),
2921 selecting: $this.hasClass('ui-selecting'),
2922 unselecting: $this.hasClass('ui-unselecting')
2923 });
2924 });
2925 };
2926 this.refresh();
2927
2928 this.selectees = selectees.addClass("ui-selectee");
2929
2930 this._mouseInit();
2931
2932 this.helper = $("<div class='ui-selectable-helper'></div>");
2933 },
2934
2935 destroy: function() {
2936 this.selectees
2937 .removeClass("ui-selectee")
2938 .removeData("selectable-item");
2939 this.element
2940 .removeClass("ui-selectable ui-selectable-disabled")
2941 .removeData("selectable")
2942 .unbind(".selectable");
2943 this._mouseDestroy();
2944
2945 return this;
2946 },
2947
2948 _mouseStart: function(event) {
2949 var self = this;
2950
2951 this.opos = [event.pageX, event.pageY];
2952
2953 if (this.options.disabled)
2954 return;
2955
2956 var options = this.options;
2957
2958 this.selectees = $(options.filter, this.element[0]);
2959
2960 this._trigger("start", event);
2961
2962 $(options.appendTo).append(this.helper);
2963 // position helper (lasso)
2964 this.helper.css({
2965 "left": event.clientX,
2966 "top": event.clientY,
2967 "width": 0,
2968 "height": 0
2969 });
2970
2971 if (options.autoRefresh) {
2972 this.refresh();
2973 }
2974
2975 this.selectees.filter('.ui-selected').each(function() {
2976 var selectee = $.data(this, "selectable-item");
2977 selectee.startselected = true;
2978 if (!event.metaKey && !event.ctrlKey) {
2979 selectee.$element.removeClass('ui-selected');
2980 selectee.selected = false;
2981 selectee.$element.addClass('ui-unselecting');
2982 selectee.unselecting = true;
2983 // selectable UNSELECTING callback
2984 self._trigger("unselecting", event, {
2985 unselecting: selectee.element
2986 });
2987 }
2988 });
2989
2990 $(event.target).parents().andSelf().each(function() {
2991 var selectee = $.data(this, "selectable-item");
2992 if (selectee) {
2993 var doSelect = (!event.metaKey && !event.ctrlKey) || !selectee.$element.hasClass('ui-selected');
2994 selectee.$element
2995 .removeClass(doSelect ? "ui-unselecting" : "ui-selected")
2996 .addClass(doSelect ? "ui-selecting" : "ui-unselecting");
2997 selectee.unselecting = !doSelect;
2998 selectee.selecting = doSelect;
2999 selectee.selected = doSelect;
3000 // selectable (UN)SELECTING callback
3001 if (doSelect) {
3002 self._trigger("selecting", event, {
3003 selecting: selectee.element
3004 });
3005 } else {
3006 self._trigger("unselecting", event, {
3007 unselecting: selectee.element
3008 });
3009 }
3010 return false;
3011 }
3012 });
3013
3014 },
3015
3016 _mouseDrag: function(event) {
3017 var self = this;
3018 this.dragged = true;
3019
3020 if (this.options.disabled)
3021 return;
3022
3023 var options = this.options;
3024
3025 var x1 = this.opos[0], y1 = this.opos[1], x2 = event.pageX, y2 = event.pageY;
3026 if (x1 > x2) { var tmp = x2; x2 = x1; x1 = tmp; }
3027 if (y1 > y2) { var tmp = y2; y2 = y1; y1 = tmp; }
3028 this.helper.css({left: x1, top: y1, width: x2-x1, height: y2-y1});
3029
3030 this.selectees.each(function() {
3031 var selectee = $.data(this, "selectable-item");
3032 //prevent helper from being selected if appendTo: selectable
3033 if (!selectee || selectee.element == self.element[0])
3034 return;
3035 var hit = false;
3036 if (options.tolerance == 'touch') {
3037 hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) );
3038 } else if (options.tolerance == 'fit') {
3039 hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2);
3040 }
3041
3042 if (hit) {
3043 // SELECT
3044 if (selectee.selected) {
3045 selectee.$element.removeClass('ui-selected');
3046 selectee.selected = false;
3047 }
3048 if (selectee.unselecting) {
3049 selectee.$element.removeClass('ui-unselecting');
3050 selectee.unselecting = false;
3051 }
3052 if (!selectee.selecting) {
3053 selectee.$element.addClass('ui-selecting');
3054 selectee.selecting = true;
3055 // selectable SELECTING callback
3056 self._trigger("selecting", event, {
3057 selecting: selectee.element
3058 });
3059 }
3060 } else {
3061 // UNSELECT
3062 if (selectee.selecting) {
3063 if ((event.metaKey || event.ctrlKey) && selectee.startselected) {
3064 selectee.$element.removeClass('ui-selecting');
3065 selectee.selecting = false;
3066 selectee.$element.addClass('ui-selected');
3067 selectee.selected = true;
3068 } else {
3069 selectee.$element.removeClass('ui-selecting');
3070 selectee.selecting = false;
3071 if (selectee.startselected) {
3072 selectee.$element.addClass('ui-unselecting');
3073 selectee.unselecting = true;
3074 }
3075 // selectable UNSELECTING callback
3076 self._trigger("unselecting", event, {
3077 unselecting: selectee.element
3078 });
3079 }
3080 }
3081 if (selectee.selected) {
3082 if (!event.metaKey && !event.ctrlKey && !selectee.startselected) {
3083 selectee.$element.removeClass('ui-selected');
3084 selectee.selected = false;
3085
3086 selectee.$element.addClass('ui-unselecting');
3087 selectee.unselecting = true;
3088 // selectable UNSELECTING callback
3089 self._trigger("unselecting", event, {
3090 unselecting: selectee.element
3091 });
3092 }
3093 }
3094 }
3095 });
3096
3097 return false;
3098 },
3099
3100 _mouseStop: function(event) {
3101 var self = this;
3102
3103 this.dragged = false;
3104
3105 var options = this.options;
3106
3107 $('.ui-unselecting', this.element[0]).each(function() {
3108 var selectee = $.data(this, "selectable-item");
3109 selectee.$element.removeClass('ui-unselecting');
3110 selectee.unselecting = false;
3111 selectee.startselected = false;
3112 self._trigger("unselected", event, {
3113 unselected: selectee.element
3114 });
3115 });
3116 $('.ui-selecting', this.element[0]).each(function() {
3117 var selectee = $.data(this, "selectable-item");
3118 selectee.$element.removeClass('ui-selecting').addClass('ui-selected');
3119 selectee.selecting = false;
3120 selectee.selected = true;
3121 selectee.startselected = true;
3122 self._trigger("selected", event, {
3123 selected: selectee.element
3124 });
3125 });
3126 this._trigger("stop", event);
3127
3128 this.helper.remove();
3129
3130 return false;
3131 }
3132
3133 });
3134
3135 })(jQuery);
3136 /*
3137 * jQuery UI Sortable @VERSION
3138 *
3139 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
3140 * Dual licensed under the MIT or GPL Version 2 licenses.
3141 * http://jquery.org/license
3142 *
3143 * http://docs.jquery.com/UI/Sortables
3144 *
3145 * Depends:
3146 * jquery.ui.core.js
3147 * jquery.ui.mouse.js
3148 * jquery.ui.widget.js
3149 */
3150 (function( $, undefined ) {
3151
3152 $.widget("ui.sortable", $.ui.mouse, {
3153 version: "@VERSION",
3154 widgetEventPrefix: "sort",
3155 options: {
3156 appendTo: "parent",
3157 axis: false,
3158 connectWith: false,
3159 containment: false,
3160 cursor: 'auto',
3161 cursorAt: false,
3162 dropOnEmpty: true,
3163 forcePlaceholderSize: false,
3164 forceHelperSize: false,
3165 grid: false,
3166 handle: false,
3167 helper: "original",
3168 items: '> *',
3169 opacity: false,
3170 placeholder: false,
3171 revert: false,
3172 scroll: true,
3173 scrollSensitivity: 20,
3174 scrollSpeed: 20,
3175 scope: "default",
3176 tolerance: "intersect",
3177 zIndex: 1000
3178 },
3179 _create: function() {
3180
3181 var o = this.options;
3182 this.containerCache = {};
3183 this.element.addClass("ui-sortable");
3184
3185 //Get the items
3186 this.refresh();
3187
3188 //Let's determine if the items are being displayed horizontally
3189 this.floating = this.items.length ? o.axis === 'x' || (/left|right/).test(this.items[0].item.css('float')) || (/inline|table-cell/).test(this.items[0].item.css('display')) : false;
3190
3191 //Let's determine the parent's offset
3192 this.offset = this.element.offset();
3193
3194 //Initialize mouse events for interaction
3195 this._mouseInit();
3196
3197 },
3198
3199 destroy: function() {
3200 this.element
3201 .removeClass("ui-sortable ui-sortable-disabled");
3202 this._mouseDestroy();
3203
3204 for ( var i = this.items.length - 1; i >= 0; i-- )
3205 this.items[i].item.removeData(this.widgetName + "-item");
3206
3207 return this;
3208 },
3209
3210 _setOption: function(key, value){
3211 if ( key === "disabled" ) {
3212 this.options[ key ] = value;
3213
3214 this.widget().toggleClass( "ui-sortable-disabled", !!value );
3215 } else {
3216 // Don't call widget base _setOption for disable as it adds ui-state-disabled class
3217 $.Widget.prototype._setOption.apply(this, arguments);
3218 }
3219 },
3220
3221 _mouseCapture: function(event, overrideHandle) {
3222 var that = this;
3223
3224 if (this.reverting) {
3225 return false;
3226 }
3227
3228 if(this.options.disabled || this.options.type == 'static') return false;
3229
3230 //We have to refresh the items data once first
3231 this._refreshItems(event);
3232
3233 //Find out if the clicked node (or one of its parents) is a actual item in this.items
3234 var currentItem = null, self = this, nodes = $(event.target).parents().each(function() {
3235 if($.data(this, that.widgetName + '-item') == self) {
3236 currentItem = $(this);
3237 return false;
3238 }
3239 });
3240 if($.data(event.target, that.widgetName + '-item') == self) currentItem = $(event.target);
3241
3242 if(!currentItem) return false;
3243 if(this.options.handle && !overrideHandle) {
3244 var validHandle = false;
3245
3246 $(this.options.handle, currentItem).find("*").andSelf().each(function() { if(this == event.target) validHandle = true; });
3247 if(!validHandle) return false;
3248 }
3249
3250 this.currentItem = currentItem;
3251 this._removeCurrentsFromItems();
3252 return true;
3253
3254 },
3255
3256 _mouseStart: function(event, overrideHandle, noActivation) {
3257
3258 var o = this.options, self = this;
3259 this.currentContainer = this;
3260
3261 //We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture
3262 this.refreshPositions();
3263
3264 //Create and append the visible helper
3265 this.helper = this._createHelper(event);
3266
3267 //Cache the helper size
3268 this._cacheHelperProportions();
3269
3270 /*
3271 * - Position generation -
3272 * This block generates everything position related - it's the core of draggables.
3273 */
3274
3275 //Cache the margins of the original element
3276 this._cacheMargins();
3277
3278 //Get the next scrolling parent
3279 this.scrollParent = this.helper.scrollParent();
3280
3281 //The element's absolute position on the page minus margins
3282 this.offset = this.currentItem.offset();
3283 this.offset = {
3284 top: this.offset.top - this.margins.top,
3285 left: this.offset.left - this.margins.left
3286 };
3287
3288 // Only after we got the offset, we can change the helper's position to absolute
3289 // TODO: Still need to figure out a way to make relative sorting possible
3290 this.helper.css("position", "absolute");
3291 this.cssPosition = this.helper.css("position");
3292
3293 $.extend(this.offset, {
3294 click: { //Where the click happened, relative to the element
3295 left: event.pageX - this.offset.left,
3296 top: event.pageY - this.offset.top
3297 },
3298 parent: this._getParentOffset(),
3299 relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
3300 });
3301
3302 //Generate the original position
3303 this.originalPosition = this._generatePosition(event);
3304 this.originalPageX = event.pageX;
3305 this.originalPageY = event.pageY;
3306
3307 //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
3308 (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
3309
3310 //Cache the former DOM position
3311 this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] };
3312
3313 //If the helper is not the original, hide the original so it's not playing any role during the drag, won't cause anything bad this way
3314 if(this.helper[0] != this.currentItem[0]) {
3315 this.currentItem.hide();
3316 }
3317
3318 //Create the placeholder
3319 this._createPlaceholder();
3320
3321 //Set a containment if given in the options
3322 if(o.containment)
3323 this._setContainment();
3324
3325 if(o.cursor) { // cursor option
3326 if ($('body').css("cursor")) this._storedCursor = $('body').css("cursor");
3327 $('body').css("cursor", o.cursor);
3328 }
3329
3330 if(o.opacity) { // opacity option
3331 if (this.helper.css("opacity")) this._storedOpacity = this.helper.css("opacity");
3332 this.helper.css("opacity", o.opacity);
3333 }
3334
3335 if(o.zIndex) { // zIndex option
3336 if (this.helper.css("zIndex")) this._storedZIndex = this.helper.css("zIndex");
3337 this.helper.css("zIndex", o.zIndex);
3338 }
3339
3340 //Prepare scrolling
3341 if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML')
3342 this.overflowOffset = this.scrollParent.offset();
3343
3344 //Call callbacks
3345 this._trigger("start", event, this._uiHash());
3346
3347 //Recache the helper size
3348 if(!this._preserveHelperProportions)
3349 this._cacheHelperProportions();
3350
3351
3352 //Post 'activate' events to possible containers
3353 if(!noActivation) {
3354 for (var i = this.containers.length - 1; i >= 0; i--) { this.containers[i]._trigger("activate", event, self._uiHash(this)); }
3355 }
3356
3357 //Prepare possible droppables
3358 if($.ui.ddmanager)
3359 $.ui.ddmanager.current = this;
3360
3361 if ($.ui.ddmanager && !o.dropBehaviour)
3362 $.ui.ddmanager.prepareOffsets(this, event);
3363
3364 this.dragging = true;
3365
3366 this.helper.addClass("ui-sortable-helper");
3367 this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position
3368 return true;
3369
3370 },
3371
3372 _mouseDrag: function(event) {
3373
3374 //Compute the helpers position
3375 this.position = this._generatePosition(event);
3376 this.positionAbs = this._convertPositionTo("absolute");
3377
3378 if (!this.lastPositionAbs) {
3379 this.lastPositionAbs = this.positionAbs;
3380 }
3381
3382 //Do scrolling
3383 if(this.options.scroll) {
3384 var o = this.options, scrolled = false;
3385 if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') {
3386
3387 if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
3388 this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed;
3389 else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity)
3390 this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed;
3391
3392 if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
3393 this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed;
3394 else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity)
3395 this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed;
3396
3397 } else {
3398
3399 if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
3400 scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
3401 else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
3402 scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
3403
3404 if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
3405 scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
3406 else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
3407 scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
3408
3409 }
3410
3411 if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
3412 $.ui.ddmanager.prepareOffsets(this, event);
3413 }
3414
3415 //Regenerate the absolute position used for position checks
3416 this.positionAbs = this._convertPositionTo("absolute");
3417
3418 //Set the helper position
3419 if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
3420 if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
3421
3422 //Rearrange
3423 for (var i = this.items.length - 1; i >= 0; i--) {
3424
3425 //Cache variables and intersection, continue if no intersection
3426 var item = this.items[i], itemElement = item.item[0], intersection = this._intersectsWithPointer(item);
3427 if (!intersection) continue;
3428
3429 if(itemElement != this.currentItem[0] //cannot intersect with itself
3430 && this.placeholder[intersection == 1 ? "next" : "prev"]()[0] != itemElement //no useless actions that have been done before
3431 && !$.contains(this.placeholder[0], itemElement) //no action if the item moved is the parent of the item checked
3432 && (this.options.type == 'semi-dynamic' ? !$.contains(this.element[0], itemElement) : true)
3433 //&& itemElement.parentNode == this.placeholder[0].parentNode // only rearrange items within the same container
3434 ) {
3435
3436 this.direction = intersection == 1 ? "down" : "up";
3437
3438 if (this.options.tolerance == "pointer" || this._intersectsWithSides(item)) {
3439 this._rearrange(event, item);
3440 } else {
3441 break;
3442 }
3443
3444 this._trigger("change", event, this._uiHash());
3445 break;
3446 }
3447 }
3448
3449 //Post events to containers
3450 this._contactContainers(event);
3451
3452 //Interconnect with droppables
3453 if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
3454
3455 //Call callbacks
3456 this._trigger('sort', event, this._uiHash());
3457
3458 this.lastPositionAbs = this.positionAbs;
3459 return false;
3460
3461 },
3462
3463 _mouseStop: function(event, noPropagation) {
3464
3465 if(!event) return;
3466
3467 //If we are using droppables, inform the manager about the drop
3468 if ($.ui.ddmanager && !this.options.dropBehaviour)
3469 $.ui.ddmanager.drop(this, event);
3470
3471 if(this.options.revert) {
3472 var self = this;
3473 var cur = self.placeholder.offset();
3474
3475 self.reverting = true;
3476
3477 $(this.helper).animate({
3478 left: cur.left - this.offset.parent.left - self.margins.left + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollLeft),
3479 top: cur.top - this.offset.parent.top - self.margins.top + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollTop)
3480 }, parseInt(this.options.revert, 10) || 500, function() {
3481 self._clear(event);
3482 });
3483 } else {
3484 this._clear(event, noPropagation);
3485 }
3486
3487 return false;
3488
3489 },
3490
3491 cancel: function() {
3492
3493 var self = this;
3494
3495 if(this.dragging) {
3496
3497 this._mouseUp({ target: null });
3498
3499 if(this.options.helper == "original")
3500 this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
3501 else
3502 this.currentItem.show();
3503
3504 //Post deactivating events to containers
3505 for (var i = this.containers.length - 1; i >= 0; i--){
3506 this.containers[i]._trigger("deactivate", null, self._uiHash(this));
3507 if(this.containers[i].containerCache.over) {
3508 this.containers[i]._trigger("out", null, self._uiHash(this));
3509 this.containers[i].containerCache.over = 0;
3510 }
3511 }
3512
3513 }
3514
3515 if (this.placeholder) {
3516 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
3517 if(this.placeholder[0].parentNode) this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
3518 if(this.options.helper != "original" && this.helper && this.helper[0].parentNode) this.helper.remove();
3519
3520 $.extend(this, {
3521 helper: null,
3522 dragging: false,
3523 reverting: false,
3524 _noFinalSort: null
3525 });
3526
3527 if(this.domPosition.prev) {
3528 $(this.domPosition.prev).after(this.currentItem);
3529 } else {
3530 $(this.domPosition.parent).prepend(this.currentItem);
3531 }
3532 }
3533
3534 return this;
3535
3536 },
3537
3538 serialize: function(o) {
3539
3540 var items = this._getItemsAsjQuery(o && o.connected);
3541 var str = []; o = o || {};
3542
3543 $(items).each(function() {
3544 var res = ($(o.item || this).attr(o.attribute || 'id') || '').match(o.expression || (/(.+)[-=_](.+)/));
3545 if(res) str.push((o.key || res[1]+'[]')+'='+(o.key && o.expression ? res[1] : res[2]));
3546 });
3547
3548 if(!str.length && o.key) {
3549 str.push(o.key + '=');
3550 }
3551
3552 return str.join('&');
3553
3554 },
3555
3556 toArray: function(o) {
3557
3558 var items = this._getItemsAsjQuery(o && o.connected);
3559 var ret = []; o = o || {};
3560
3561 items.each(function() { ret.push($(o.item || this).attr(o.attribute || 'id') || ''); });
3562 return ret;
3563
3564 },
3565
3566 /* Be careful with the following core functions */
3567 _intersectsWith: function(item) {
3568
3569 var x1 = this.positionAbs.left,
3570 x2 = x1 + this.helperProportions.width,
3571 y1 = this.positionAbs.top,
3572 y2 = y1 + this.helperProportions.height;
3573
3574 var l = item.left,
3575 r = l + item.width,
3576 t = item.top,
3577 b = t + item.height;
3578
3579 var dyClick = this.offset.click.top,
3580 dxClick = this.offset.click.left;
3581
3582 var isOverElement = (y1 + dyClick) > t && (y1 + dyClick) < b && (x1 + dxClick) > l && (x1 + dxClick) < r;
3583
3584 if( this.options.tolerance == "pointer"
3585 || this.options.forcePointerForContainers
3586 || (this.options.tolerance != "pointer" && this.helperProportions[this.floating ? 'width' : 'height'] > item[this.floating ? 'width' : 'height'])
3587 ) {
3588 return isOverElement;
3589 } else {
3590
3591 return (l < x1 + (this.helperProportions.width / 2) // Right Half
3592 && x2 - (this.helperProportions.width / 2) < r // Left Half
3593 && t < y1 + (this.helperProportions.height / 2) // Bottom Half
3594 && y2 - (this.helperProportions.height / 2) < b ); // Top Half
3595
3596 }
3597 },
3598
3599 _intersectsWithPointer: function(item) {
3600
3601 var isOverElementHeight = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height),
3602 isOverElementWidth = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width),
3603 isOverElement = isOverElementHeight && isOverElementWidth,
3604 verticalDirection = this._getDragVerticalDirection(),
3605 horizontalDirection = this._getDragHorizontalDirection();
3606
3607 if (!isOverElement)
3608 return false;
3609
3610 return this.floating ?
3611 ( ((horizontalDirection && horizontalDirection == "right") || verticalDirection == "down") ? 2 : 1 )
3612 : ( verticalDirection && (verticalDirection == "down" ? 2 : 1) );
3613
3614 },
3615
3616 _intersectsWithSides: function(item) {
3617
3618 var isOverBottomHalf = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height),
3619 isOverRightHalf = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width),
3620 verticalDirection = this._getDragVerticalDirection(),
3621 horizontalDirection = this._getDragHorizontalDirection();
3622
3623 if (this.floating && horizontalDirection) {
3624 return ((horizontalDirection == "right" && isOverRightHalf) || (horizontalDirection == "left" && !isOverRightHalf));
3625 } else {
3626 return verticalDirection && ((verticalDirection == "down" && isOverBottomHalf) || (verticalDirection == "up" && !isOverBottomHalf));
3627 }
3628
3629 },
3630
3631 _getDragVerticalDirection: function() {
3632 var delta = this.positionAbs.top - this.lastPositionAbs.top;
3633 return delta != 0 && (delta > 0 ? "down" : "up");
3634 },
3635
3636 _getDragHorizontalDirection: function() {
3637 var delta = this.positionAbs.left - this.lastPositionAbs.left;
3638 return delta != 0 && (delta > 0 ? "right" : "left");
3639 },
3640
3641 refresh: function(event) {
3642 this._refreshItems(event);
3643 this.refreshPositions();
3644 return this;
3645 },
3646
3647 _connectWith: function() {
3648 var options = this.options;
3649 return options.connectWith.constructor == String
3650 ? [options.connectWith]
3651 : options.connectWith;
3652 },
3653
3654 _getItemsAsjQuery: function(connected) {
3655
3656 var self = this;
3657 var items = [];
3658 var queries = [];
3659 var connectWith = this._connectWith();
3660
3661 if(connectWith && connected) {
3662 for (var i = connectWith.length - 1; i >= 0; i--){
3663 var cur = $(connectWith[i]);
3664 for (var j = cur.length - 1; j >= 0; j--){
3665 var inst = $.data(cur[j], this.widgetName);
3666 if(inst && inst != this && !inst.options.disabled) {
3667 queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element) : $(inst.options.items, inst.element).not(".ui-sortable-helper").not('.ui-sortable-placeholder'), inst]);
3668 }
3669 };
3670 };
3671 }
3672
3673 queries.push([$.isFunction(this.options.items) ? this.options.items.call(this.element, null, { options: this.options, item: this.currentItem }) : $(this.options.items, this.element).not(".ui-sortable-helper").not('.ui-sortable-placeholder'), this]);
3674
3675 for (var i = queries.length - 1; i >= 0; i--){
3676 queries[i][0].each(function() {
3677 items.push(this);
3678 });
3679 };
3680
3681 return $(items);
3682
3683 },
3684
3685 _removeCurrentsFromItems: function() {
3686
3687 var list = this.currentItem.find(":data(" + this.widgetName + "-item)");
3688
3689 for (var i=0; i < this.items.length; i++) {
3690
3691 for (var j=0; j < list.length; j++) {
3692 if(list[j] == this.items[i].item[0])
3693 this.items.splice(i,1);
3694 };
3695
3696 };
3697
3698 },
3699
3700 _refreshItems: function(event) {
3701
3702 this.items = [];
3703 this.containers = [this];
3704 var items = this.items;
3705 var self = this;
3706 var queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]];
3707 var connectWith = this._connectWith();
3708
3709 if(connectWith) {
3710 for (var i = connectWith.length - 1; i >= 0; i--){
3711 var cur = $(connectWith[i]);
3712 for (var j = cur.length - 1; j >= 0; j--){
3713 var inst = $.data(cur[j], this.widgetName);
3714 if(inst && inst != this && !inst.options.disabled) {
3715 queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]);
3716 this.containers.push(inst);
3717 }
3718 };
3719 };
3720 }
3721
3722 for (var i = queries.length - 1; i >= 0; i--) {
3723 var targetData = queries[i][1];
3724 var _queries = queries[i][0];
3725
3726 for (var j=0, queriesLength = _queries.length; j < queriesLength; j++) {
3727 var item = $(_queries[j]);
3728
3729 item.data(this.widgetName + '-item', targetData); // Data for target checking (mouse manager)
3730
3731 items.push({
3732 item: item,
3733 instance: targetData,
3734 width: 0, height: 0,
3735 left: 0, top: 0
3736 });
3737 };
3738 };
3739
3740 },
3741
3742 refreshPositions: function(fast) {
3743
3744 //This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change
3745 if(this.offsetParent && this.helper) {
3746 this.offset.parent = this._getParentOffset();
3747 }
3748
3749 for (var i = this.items.length - 1; i >= 0; i--){
3750 var item = this.items[i];
3751
3752 //We ignore calculating positions of all connected containers when we're not over them
3753 if(item.instance != this.currentContainer && this.currentContainer && item.item[0] != this.currentItem[0])
3754 continue;
3755
3756 var t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item;
3757
3758 if (!fast) {
3759 item.width = t.outerWidth();
3760 item.height = t.outerHeight();
3761 }
3762
3763 var p = t.offset();
3764 item.left = p.left;
3765 item.top = p.top;
3766 };
3767
3768 if(this.options.custom && this.options.custom.refreshContainers) {
3769 this.options.custom.refreshContainers.call(this);
3770 } else {
3771 for (var i = this.containers.length - 1; i >= 0; i--){
3772 var p = this.containers[i].element.offset();
3773 this.containers[i].containerCache.left = p.left;
3774 this.containers[i].containerCache.top = p.top;
3775 this.containers[i].containerCache.width = this.containers[i].element.outerWidth();
3776 this.containers[i].containerCache.height = this.containers[i].element.outerHeight();
3777 };
3778 }
3779
3780 return this;
3781 },
3782
3783 _createPlaceholder: function(that) {
3784
3785 var self = that || this, o = self.options;
3786
3787 if(!o.placeholder || o.placeholder.constructor == String) {
3788 var className = o.placeholder;
3789 o.placeholder = {
3790 element: function() {
3791
3792 var el = $(document.createElement(self.currentItem[0].nodeName))
3793 .addClass(className || self.currentItem[0].className+" ui-sortable-placeholder")
3794 .removeClass("ui-sortable-helper")[0];
3795
3796 if(!className)
3797 el.style.visibility = "hidden";
3798
3799 return el;
3800 },
3801 update: function(container, p) {
3802
3803 // 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that
3804 // 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified
3805 if(className && !o.forcePlaceholderSize) return;
3806
3807 //If the element doesn't have a actual height by itself (without styles coming from a stylesheet), it receives the inline height from the dragged item
3808 if(!p.height()) { p.height(self.currentItem.innerHeight() - parseInt(self.currentItem.css('paddingTop')||0, 10) - parseInt(self.currentItem.css('paddingBottom')||0, 10)); };
3809 if(!p.width()) { p.width(self.currentItem.innerWidth() - parseInt(self.currentItem.css('paddingLeft')||0, 10) - parseInt(self.currentItem.css('paddingRight')||0, 10)); };
3810 }
3811 };
3812 }
3813
3814 //Create the placeholder
3815 self.placeholder = $(o.placeholder.element.call(self.element, self.currentItem));
3816
3817 //Append it after the actual current item
3818 self.currentItem.after(self.placeholder);
3819
3820 //Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
3821 o.placeholder.update(self, self.placeholder);
3822
3823 },
3824
3825 _contactContainers: function(event) {
3826
3827 // get innermost container that intersects with item
3828 var innermostContainer = null, innermostIndex = null;
3829
3830
3831 for (var i = this.containers.length - 1; i >= 0; i--){
3832
3833 // never consider a container that's located within the item itself
3834 if($.contains(this.currentItem[0], this.containers[i].element[0]))
3835 continue;
3836
3837 if(this._intersectsWith(this.containers[i].containerCache)) {
3838
3839 // if we've already found a container and it's more "inner" than this, then continue
3840 if(innermostContainer && $.contains(this.containers[i].element[0], innermostContainer.element[0]))
3841 continue;
3842
3843 innermostContainer = this.containers[i];
3844 innermostIndex = i;
3845
3846 } else {
3847 // container doesn't intersect. trigger "out" event if necessary
3848 if(this.containers[i].containerCache.over) {
3849 this.containers[i]._trigger("out", event, this._uiHash(this));
3850 this.containers[i].containerCache.over = 0;
3851 }
3852 }
3853
3854 }
3855
3856 // if no intersecting containers found, return
3857 if(!innermostContainer) return;
3858
3859 // move the item into the container if it's not there already
3860 if(this.containers.length === 1) {
3861 this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
3862 this.containers[innermostIndex].containerCache.over = 1;
3863 } else if(this.currentContainer != this.containers[innermostIndex]) {
3864
3865 //When entering a new container, we will find the item with the least distance and append our item near it
3866 var dist = 10000; var itemWithLeastDistance = null; var base = this.positionAbs[this.containers[innermostIndex].floating ? 'left' : 'top'];
3867 for (var j = this.items.length - 1; j >= 0; j--) {
3868 if(!$.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) continue;
3869 var cur = this.items[j][this.containers[innermostIndex].floating ? 'left' : 'top'];
3870 if(Math.abs(cur - base) < dist) {
3871 dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j];
3872 }
3873 }
3874
3875 if(!itemWithLeastDistance && !this.options.dropOnEmpty) //Check if dropOnEmpty is enabled
3876 return;
3877
3878 this.currentContainer = this.containers[innermostIndex];
3879 itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true);
3880 this._trigger("change", event, this._uiHash());
3881 this.containers[innermostIndex]._trigger("change", event, this._uiHash(this));
3882
3883 //Update the placeholder
3884 this.options.placeholder.update(this.currentContainer, this.placeholder);
3885
3886 this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
3887 this.containers[innermostIndex].containerCache.over = 1;
3888 }
3889
3890
3891 },
3892
3893 _createHelper: function(event) {
3894
3895 var o = this.options;
3896 var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper == 'clone' ? this.currentItem.clone() : this.currentItem);
3897
3898 if(!helper.parents('body').length) //Add the helper to the DOM if that didn't happen already
3899 $(o.appendTo != 'parent' ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]);
3900
3901 if(helper[0] == this.currentItem[0])
3902 this._storedCSS = { width: this.currentItem[0].style.width, height: this.currentItem[0].style.height, position: this.currentItem.css("position"), top: this.currentItem.css("top"), left: this.currentItem.css("left") };
3903
3904 if(helper[0].style.width == '' || o.forceHelperSize) helper.width(this.currentItem.width());
3905 if(helper[0].style.height == '' || o.forceHelperSize) helper.height(this.currentItem.height());
3906
3907 return helper;
3908
3909 },
3910
3911 _adjustOffsetFromHelper: function(obj) {
3912 if (typeof obj == 'string') {
3913 obj = obj.split(' ');
3914 }
3915 if ($.isArray(obj)) {
3916 obj = {left: +obj[0], top: +obj[1] || 0};
3917 }
3918 if ('left' in obj) {
3919 this.offset.click.left = obj.left + this.margins.left;
3920 }
3921 if ('right' in obj) {
3922 this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
3923 }
3924 if ('top' in obj) {
3925 this.offset.click.top = obj.top + this.margins.top;
3926 }
3927 if ('bottom' in obj) {
3928 this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
3929 }
3930 },
3931
3932 _getParentOffset: function() {
3933
3934
3935 //Get the offsetParent and cache its position
3936 this.offsetParent = this.helper.offsetParent();
3937 var po = this.offsetParent.offset();
3938
3939 // This is a special case where we need to modify a offset calculated on start, since the following happened:
3940 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
3941 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
3942 // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
3943 if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.contains(this.scrollParent[0], this.offsetParent[0])) {
3944 po.left += this.scrollParent.scrollLeft();
3945 po.top += this.scrollParent.scrollTop();
3946 }
3947
3948 if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
3949 || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix
3950 po = { top: 0, left: 0 };
3951
3952 return {
3953 top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
3954 left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
3955 };
3956
3957 },
3958
3959 _getRelativeOffset: function() {
3960
3961 if(this.cssPosition == "relative") {
3962 var p = this.currentItem.position();
3963 return {
3964 top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
3965 left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
3966 };
3967 } else {
3968 return { top: 0, left: 0 };
3969 }
3970
3971 },
3972
3973 _cacheMargins: function() {
3974 this.margins = {
3975 left: (parseInt(this.currentItem.css("marginLeft"),10) || 0),
3976 top: (parseInt(this.currentItem.css("marginTop"),10) || 0)
3977 };
3978 },
3979
3980 _cacheHelperProportions: function() {
3981 this.helperProportions = {
3982 width: this.helper.outerWidth(),
3983 height: this.helper.outerHeight()
3984 };
3985 },
3986
3987 _setContainment: function() {
3988
3989 var o = this.options;
3990 if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
3991 if(o.containment == 'document' || o.containment == 'window') this.containment = [
3992 0 - this.offset.relative.left - this.offset.parent.left,
3993 0 - this.offset.relative.top - this.offset.parent.top,
3994 $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
3995 ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
3996 ];
3997
3998 if(!(/^(document|window|parent)$/).test(o.containment)) {
3999 var ce = $(o.containment)[0];
4000 var co = $(o.containment).offset();
4001 var over = ($(ce).css("overflow") != 'hidden');
4002
4003 this.containment = [
4004 co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
4005 co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
4006 co.left+(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left,
4007 co.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top
4008 ];
4009 }
4010
4011 },
4012
4013 _convertPositionTo: function(d, pos) {
4014
4015 if(!pos) pos = this.position;
4016 var mod = d == "absolute" ? 1 : -1;
4017 var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
4018
4019 return {
4020 top: (
4021 pos.top // The absolute mouse position
4022 + this.offset.relative.top * mod // Only for relative positioned nodes: Relative offset from element to offset parent
4023 + this.offset.parent.top * mod // The offsetParent's offset without borders (offset + border)
4024 - ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
4025 ),
4026 left: (
4027 pos.left // The absolute mouse position
4028 + this.offset.relative.left * mod // Only for relative positioned nodes: Relative offset from element to offset parent
4029 + this.offset.parent.left * mod // The offsetParent's offset without borders (offset + border)
4030 - ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
4031 )
4032 };
4033
4034 },
4035
4036 _generatePosition: function(event) {
4037
4038 var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
4039
4040 // This is another very weird special case that only happens for relative elements:
4041 // 1. If the css position is relative
4042 // 2. and the scroll parent is the document or similar to the offset parent
4043 // we have to refresh the relative offset during the scroll so there are no jumps
4044 if(this.cssPosition == 'relative' && !(this.scrollParent[0] != document && this.scrollParent[0] != this.offsetParent[0])) {
4045 this.offset.relative = this._getRelativeOffset();
4046 }
4047
4048 var pageX = event.pageX;
4049 var pageY = event.pageY;
4050
4051 /*
4052 * - Position constraining -
4053 * Constrain the position to a mix of grid, containment.
4054 */
4055
4056 if(this.originalPosition) { //If we are not dragging yet, we won't check for options
4057
4058 if(this.containment) {
4059 if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left;
4060 if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top;
4061 if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left;
4062 if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top;
4063 }
4064
4065 if(o.grid) {
4066 var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
4067 pageY = this.containment ? (!(top - this.offset.click.top < this.containment[1] || top - this.offset.click.top > this.containment[3]) ? top : (!(top - this.offset.click.top < this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;
4068
4069 var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
4070 pageX = this.containment ? (!(left - this.offset.click.left < this.containment[0] || left - this.offset.click.left > this.containment[2]) ? left : (!(left - this.offset.click.left < this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
4071 }
4072
4073 }
4074
4075 return {
4076 top: (
4077 pageY // The absolute mouse position
4078 - this.offset.click.top // Click offset (relative to the element)
4079 - this.offset.relative.top // Only for relative positioned nodes: Relative offset from element to offset parent
4080 - this.offset.parent.top // The offsetParent's offset without borders (offset + border)
4081 + ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
4082 ),
4083 left: (
4084 pageX // The absolute mouse position
4085 - this.offset.click.left // Click offset (relative to the element)
4086 - this.offset.relative.left // Only for relative positioned nodes: Relative offset from element to offset parent
4087 - this.offset.parent.left // The offsetParent's offset without borders (offset + border)
4088 + ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
4089 )
4090 };
4091
4092 },
4093
4094 _rearrange: function(event, i, a, hardRefresh) {
4095
4096 a ? a[0].appendChild(this.placeholder[0]) : i.item[0].parentNode.insertBefore(this.placeholder[0], (this.direction == 'down' ? i.item[0] : i.item[0].nextSibling));
4097
4098 //Various things done here to improve the performance:
4099 // 1. we create a setTimeout, that calls refreshPositions
4100 // 2. on the instance, we have a counter variable, that get's higher after every append
4101 // 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same
4102 // 4. this lets only the last addition to the timeout stack through
4103 this.counter = this.counter ? ++this.counter : 1;
4104 var self = this, counter = this.counter;
4105
4106 window.setTimeout(function() {
4107 if(counter == self.counter) self.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove
4108 },0);
4109
4110 },
4111
4112 _clear: function(event, noPropagation) {
4113
4114 this.reverting = false;
4115 // We delay all events that have to be triggered to after the point where the placeholder has been removed and
4116 // everything else normalized again
4117 var delayedTriggers = [], self = this;
4118
4119 // We first have to update the dom position of the actual currentItem
4120 // Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088)
4121 if(!this._noFinalSort && this.currentItem.parent().length) this.placeholder.before(this.currentItem);
4122 this._noFinalSort = null;
4123
4124 if(this.helper[0] == this.currentItem[0]) {
4125 for(var i in this._storedCSS) {
4126 if(this._storedCSS[i] == 'auto' || this._storedCSS[i] == 'static') this._storedCSS[i] = '';
4127 }
4128 this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
4129 } else {
4130 this.currentItem.show();
4131 }
4132
4133 if(this.fromOutside && !noPropagation) delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); });
4134 if((this.fromOutside || this.domPosition.prev != this.currentItem.prev().not(".ui-sortable-helper")[0] || this.domPosition.parent != this.currentItem.parent()[0]) && !noPropagation) delayedTriggers.push(function(event) { this._trigger("update", event, this._uiHash()); }); //Trigger update callback if the DOM position has changed
4135 if(!$.contains(this.element[0], this.currentItem[0])) { //Node was moved out of the current element
4136 if(!noPropagation) delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); });
4137 for (var i = this.containers.length - 1; i >= 0; i--){
4138 if($.contains(this.containers[i].element[0], this.currentItem[0]) && !noPropagation) {
4139 delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); }; }).call(this, this.containers[i]));
4140 delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this)); }; }).call(this, this.containers[i]));
4141 }
4142 };
4143 };
4144
4145 //Post events to containers
4146 for (var i = this.containers.length - 1; i >= 0; i--){
4147 if(!noPropagation) delayedTriggers.push((function(c) { return function(event) { c._trigger("deactivate", event, this._uiHash(this)); }; }).call(this, this.containers[i]));
4148 if(this.containers[i].containerCache.over) {
4149 delayedTriggers.push((function(c) { return function(event) { c._trigger("out", event, this._uiHash(this)); }; }).call(this, this.containers[i]));
4150 this.containers[i].containerCache.over = 0;
4151 }
4152 }
4153
4154 //Do what was originally in plugins
4155 if(this._storedCursor) $('body').css("cursor", this._storedCursor); //Reset cursor
4156 if(this._storedOpacity) this.helper.css("opacity", this._storedOpacity); //Reset opacity
4157 if(this._storedZIndex) this.helper.css("zIndex", this._storedZIndex == 'auto' ? '' : this._storedZIndex); //Reset z-index
4158
4159 this.dragging = false;
4160 if(this.cancelHelperRemoval) {
4161 if(!noPropagation) {
4162 this._trigger("beforeStop", event, this._uiHash());
4163 for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events
4164 this._trigger("stop", event, this._uiHash());
4165 }
4166 return false;
4167 }
4168
4169 if(!noPropagation) this._trigger("beforeStop", event, this._uiHash());
4170
4171 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
4172 this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
4173
4174 if(this.helper[0] != this.currentItem[0]) this.helper.remove(); this.helper = null;
4175
4176 if(!noPropagation) {
4177 for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events
4178 this._trigger("stop", event, this._uiHash());
4179 }
4180
4181 this.fromOutside = false;
4182 return true;
4183
4184 },
4185
4186 _trigger: function() {
4187 if ($.Widget.prototype._trigger.apply(this, arguments) === false) {
4188 this.cancel();
4189 }
4190 },
4191
4192 _uiHash: function(inst) {
4193 var self = inst || this;
4194 return {
4195 helper: self.helper,
4196 placeholder: self.placeholder || $([]),
4197 position: self.position,
4198 originalPosition: self.originalPosition,
4199 offset: self.positionAbs,
4200 item: self.currentItem,
4201 sender: inst ? inst.element : null
4202 };
4203 }
4204
4205 });
4206
4207 })(jQuery);
4208 /*
4209 * jQuery UI Effects @VERSION
4210 *
4211 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
4212 * Dual licensed under the MIT or GPL Version 2 licenses.
4213 * http://jquery.org/license
4214 *
4215 * http://docs.jquery.com/UI/Effects/
4216 */
4217 ;jQuery.effects || (function($, undefined) {
4218
4219 var backCompat = $.uiBackCompat !== false;
4220
4221 $.effects = {
4222 effect: {}
4223 };
4224
4225 /******************************************************************************/
4226 /****************************** COLOR ANIMATIONS ******************************/
4227 /******************************************************************************/
4228
4229 // override the animation for color styles
4230 $.each(["backgroundColor", "borderBottomColor", "borderLeftColor",
4231 "borderRightColor", "borderTopColor", "borderColor", "color", "outlineColor"],
4232 function(i, attr) {
4233 $.fx.step[attr] = function(fx) {
4234 if (!fx.colorInit) {
4235 fx.start = getColor(fx.elem, attr);
4236 fx.end = getRGB(fx.end);
4237 fx.colorInit = true;
4238 }
4239
4240 fx.elem.style[attr] = "rgb(" +
4241 Math.max(Math.min(parseInt((fx.pos * (fx.end[0] - fx.start[0])) + fx.start[0], 10), 255), 0) + "," +
4242 Math.max(Math.min(parseInt((fx.pos * (fx.end[1] - fx.start[1])) + fx.start[1], 10), 255), 0) + "," +
4243 Math.max(Math.min(parseInt((fx.pos * (fx.end[2] - fx.start[2])) + fx.start[2], 10), 255), 0) + ")";
4244 };
4245 });
4246
4247 // Color Conversion functions from highlightFade
4248 // By Blair Mitchelmore
4249 // http://jquery.offput.ca/highlightFade/
4250
4251 // Parse strings looking for color tuples [255,255,255]
4252 function getRGB(color) {
4253 var result;
4254
4255 // Check if we're already dealing with an array of colors
4256 if ( color && color.constructor === Array && color.length === 3 )
4257 return color;
4258
4259 // Look for rgb(num,num,num)
4260 if (result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(color))
4261 return [parseInt(result[1],10), parseInt(result[2],10), parseInt(result[3],10)];
4262
4263 // Look for rgb(num%,num%,num%)
4264 if (result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(color))
4265 return [parseFloat(result[1])*2.55, parseFloat(result[2])*2.55, parseFloat(result[3])*2.55];
4266
4267 // Look for #a0b1c2
4268 if (result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(color))
4269 return [parseInt(result[1],16), parseInt(result[2],16), parseInt(result[3],16)];
4270
4271 // Look for #fff
4272 if (result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(color))
4273 return [parseInt(result[1]+result[1],16), parseInt(result[2]+result[2],16), parseInt(result[3]+result[3],16)];
4274
4275 // Look for rgba(0, 0, 0, 0) == transparent in Safari 3
4276 if (result = /rgba\(0, 0, 0, 0\)/.exec(color))
4277 return colors["transparent"];
4278
4279 // Otherwise, we're most likely dealing with a named color
4280 return colors[$.trim(color).toLowerCase()];
4281 }
4282
4283 function getColor(elem, attr) {
4284 var color;
4285
4286 do {
4287 color = $.curCSS(elem, attr);
4288
4289 // Keep going until we find an element that has color, or we hit the body
4290 if ( color != "" && color !== "transparent" || $.nodeName(elem, "body") )
4291 break;
4292
4293 attr = "backgroundColor";
4294 } while ( elem = elem.parentNode );
4295
4296 return getRGB(color);
4297 };
4298
4299 // Some named colors to work with
4300 // From Interface by Stefan Petre
4301 // http://interface.eyecon.ro/
4302
4303 var colors = {
4304 aqua:[0,255,255],
4305 azure:[240,255,255],
4306 beige:[245,245,220],
4307 black:[0,0,0],
4308 blue:[0,0,255],
4309 brown:[165,42,42],
4310 cyan:[0,255,255],
4311 darkblue:[0,0,139],
4312 darkcyan:[0,139,139],
4313 darkgrey:[169,169,169],
4314 darkgreen:[0,100,0],
4315 darkkhaki:[189,183,107],
4316 darkmagenta:[139,0,139],
4317 darkolivegreen:[85,107,47],
4318 darkorange:[255,140,0],
4319 darkorchid:[153,50,204],
4320 darkred:[139,0,0],
4321 darksalmon:[233,150,122],
4322 darkviolet:[148,0,211],
4323 fuchsia:[255,0,255],
4324 gold:[255,215,0],
4325 green:[0,128,0],
4326 indigo:[75,0,130],
4327 khaki:[240,230,140],
4328 lightblue:[173,216,230],
4329 lightcyan:[224,255,255],
4330 lightgreen:[144,238,144],
4331 lightgrey:[211,211,211],
4332 lightpink:[255,182,193],
4333 lightyellow:[255,255,224],
4334 lime:[0,255,0],
4335 magenta:[255,0,255],
4336 maroon:[128,0,0],
4337 navy:[0,0,128],
4338 olive:[128,128,0],
4339 orange:[255,165,0],
4340 pink:[255,192,203],
4341 purple:[128,0,128],
4342 violet:[128,0,128],
4343 red:[255,0,0],
4344 silver:[192,192,192],
4345 white:[255,255,255],
4346 yellow:[255,255,0],
4347 transparent: [255,255,255]
4348 };
4349
4350
4351
4352 /******************************************************************************/
4353 /****************************** CLASS ANIMATIONS ******************************/
4354 /******************************************************************************/
4355
4356 var classAnimationActions = [ "add", "remove", "toggle" ],
4357 shorthandStyles = {
4358 border: 1,
4359 borderBottom: 1,
4360 borderColor: 1,
4361 borderLeft: 1,
4362 borderRight: 1,
4363 borderTop: 1,
4364 borderWidth: 1,
4365 margin: 1,
4366 padding: 1
4367 },
4368 // prefix used for storing data on .data()
4369 dataSpace = "ec.storage.";
4370
4371 $.each([ "borderLeftStyle", "borderRightStyle", "borderBottomStyle", "borderTopStyle" ], function( _, prop ) {
4372 $.fx.step[ prop ] = function( fx ) {
4373 if ( fx.end !== "none" && !fx.setAttr || fx.pos === 1 && !fx.setAttr ) {
4374 jQuery.style( fx.elem, prop, fx.end );
4375 fx.setAttr = true;
4376 }
4377 };
4378 });
4379
4380 function getElementStyles() {
4381 var style = this.ownerDocument.defaultView
4382 ? this.ownerDocument.defaultView.getComputedStyle( this, null )
4383 : this.currentStyle,
4384 newStyle = {},
4385 key,
4386 camelCase,
4387 len;
4388
4389 // webkit enumerates style porperties
4390 if ( style && style.length && style[ 0 ] && style[ style[ 0 ] ] ) {
4391 len = style.length;
4392 while ( len-- ) {
4393 key = style[ len ];
4394 if ( typeof style[ key ] === "string" ) {
4395 newStyle[ $.camelCase( key ) ] = style[ key ];
4396 }
4397 }
4398 } else {
4399 for ( key in style ) {
4400 if ( typeof style[ key ] === "string" ) {
4401 newStyle[ key ] = style[ key ];
4402 }
4403 }
4404 }
4405
4406 return newStyle;
4407 }
4408
4409
4410 function styleDifference( oldStyle, newStyle ) {
4411 var diff = {},
4412 name, value;
4413
4414 for ( name in newStyle ) {
4415 value = newStyle[ name ];
4416 if ( oldStyle[ name ] != value ) {
4417 if ( !shorthandStyles[ name ] ) {
4418 if ( $.fx.step[ name ] || !isNaN( parseFloat( value ) ) ) {
4419 diff[ name ] = value;
4420 }
4421 }
4422 }
4423 }
4424
4425 return diff;
4426 }
4427
4428 $.effects.animateClass = function( value, duration, easing, callback ) {
4429 var o = $.speed( duration, easing, callback );
4430
4431 return this.queue( function() {
4432 var animated = $( this ),
4433 baseClass = animated.attr( "class" ) || "",
4434 applyClassChange,
4435 allAnimations = o.children ? animated.find( "*" ).andSelf() : animated;
4436
4437 // map the animated objects to store the original styles.
4438 allAnimations = allAnimations.map(function() {
4439 var el = $( this );
4440 return {
4441 el: el,
4442 start: getElementStyles.call( this )
4443 };
4444 });
4445
4446 // apply class change
4447 applyClassChange = function() {
4448 $.each( classAnimationActions, function(i, action) {
4449 if ( value[ action ] ) {
4450 animated[ action + "Class" ]( value[ action ] );
4451 }
4452 });
4453 };
4454 applyClassChange();
4455
4456 // map all animated objects again - calculate new styles and diff
4457 allAnimations = allAnimations.map(function() {
4458 this.end = getElementStyles.call( this.el[ 0 ] );
4459 this.diff = styleDifference( this.start, this.end );
4460 return this;
4461 });
4462
4463 // apply original class
4464 animated.attr( "class", baseClass );
4465
4466 // map all animated objects again - this time collecting a promise
4467 allAnimations = allAnimations.map(function() {
4468 var styleInfo = this,
4469 dfd = $.Deferred();
4470
4471 this.el.animate( this.diff, {
4472 duration: o.duration,
4473 easing: o.easing,
4474 queue: false,
4475 complete: function() {
4476 dfd.resolve( styleInfo );
4477 }
4478 });
4479 return dfd.promise();
4480 });
4481
4482 // once all animations have completed:
4483 $.when.apply( $, allAnimations.get() ).done(function() {
4484
4485 // set the final class
4486 applyClassChange();
4487
4488 // for each animated element,
4489 // clear all css properties that were animated
4490 $.each( arguments, function() {
4491 var el = this.el;
4492 $.each( this.diff, function(key) {
4493 el.css( key, '' );
4494 });
4495 });
4496
4497 // this is guarnteed to be there if you use jQuery.speed()
4498 // it also handles dequeuing the next anim...
4499 o.complete.call( animated[ 0 ] );
4500 });
4501 });
4502 };
4503
4504 $.fn.extend({
4505 _addClass: $.fn.addClass,
4506 addClass: function( classNames, speed, easing, callback ) {
4507 return speed ?
4508 $.effects.animateClass.apply( this, [{ add: classNames }, speed, easing, callback ]) :
4509 this._addClass(classNames);
4510 },
4511
4512 _removeClass: $.fn.removeClass,
4513 removeClass: function( classNames, speed, easing, callback ) {
4514 return speed ?
4515 $.effects.animateClass.apply( this, [{ remove: classNames }, speed, easing, callback ]) :
4516 this._removeClass(classNames);
4517 },
4518
4519 _toggleClass: $.fn.toggleClass,
4520 toggleClass: function( classNames, force, speed, easing, callback ) {
4521 if ( typeof force === "boolean" || force === undefined ) {
4522 if ( !speed ) {
4523 // without speed parameter;
4524 return this._toggleClass( classNames, force );
4525 } else {
4526 return $.effects.animateClass.apply( this, [( force ? { add:classNames } : { remove:classNames }), speed, easing, callback ]);
4527 }
4528 } else {
4529 // without force parameter;
4530 return $.effects.animateClass.apply( this, [{ toggle: classNames }, force, speed, easing ]);
4531 }
4532 },
4533
4534 switchClass: function( remove, add, speed, easing, callback) {
4535 return $.effects.animateClass.apply( this, [{
4536 add: add,
4537 remove: remove
4538 }, speed, easing, callback ]);
4539 }
4540 });
4541
4542
4543
4544 /******************************************************************************/
4545 /*********************************** EFFECTS **********************************/
4546 /******************************************************************************/
4547
4548 $.extend( $.effects, {
4549 version: "@VERSION",
4550
4551 // Saves a set of properties in a data storage
4552 save: function( element, set ) {
4553 for( var i=0; i < set.length; i++ ) {
4554 if ( set[ i ] !== null ) {
4555 element.data( dataSpace + set[ i ], element[ 0 ].style[ set[ i ] ] );
4556 }
4557 }
4558 },
4559
4560 // Restores a set of previously saved properties from a data storage
4561 restore: function( element, set ) {
4562 for( var i=0; i < set.length; i++ ) {
4563 if ( set[ i ] !== null ) {
4564 element.css( set[ i ], element.data( dataSpace + set[ i ] ) );
4565 }
4566 }
4567 },
4568
4569 setMode: function( el, mode ) {
4570 if (mode === "toggle") {
4571 mode = el.is( ":hidden" ) ? "show" : "hide";
4572 }
4573 return mode;
4574 },
4575
4576 // Translates a [top,left] array into a baseline value
4577 // this should be a little more flexible in the future to handle a string & hash
4578 getBaseline: function( origin, original ) {
4579 var y, x;
4580 switch ( origin[ 0 ] ) {
4581 case "top": y = 0; break;
4582 case "middle": y = 0.5; break;
4583 case "bottom": y = 1; break;
4584 default: y = origin[ 0 ] / original.height;
4585 };
4586 switch ( origin[ 1 ] ) {
4587 case "left": x = 0; break;
4588 case "center": x = 0.5; break;
4589 case "right": x = 1; break;
4590 default: x = origin[ 1 ] / original.width;
4591 };
4592 return {
4593 x: x,
4594 y: y
4595 };
4596 },
4597
4598 // Wraps the element around a wrapper that copies position properties
4599 createWrapper: function( element ) {
4600
4601 // if the element is already wrapped, return it
4602 if ( element.parent().is( ".ui-effects-wrapper" )) {
4603 return element.parent();
4604 }
4605
4606 // wrap the element
4607 var props = {
4608 width: element.outerWidth(true),
4609 height: element.outerHeight(true),
4610 "float": element.css( "float" )
4611 },
4612 wrapper = $( "<div></div>" )
4613 .addClass( "ui-effects-wrapper" )
4614 .css({
4615 fontSize: "100%",
4616 background: "transparent",
4617 border: "none",
4618 margin: 0,
4619 padding: 0
4620 }),
4621 // Store the size in case width/height are defined in % - Fixes #5245
4622 size = {
4623 width: element.width(),
4624 height: element.height()
4625 },
4626 active = document.activeElement;
4627
4628 element.wrap( wrapper );
4629
4630 // Fixes #7595 - Elements lose focus when wrapped.
4631 if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
4632 $( active ).focus();
4633 }
4634
4635 wrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually lose the reference to the wrapped element
4636
4637 // transfer positioning properties to the wrapper
4638 if ( element.css( "position" ) === "static" ) {
4639 wrapper.css({ position: "relative" });
4640 element.css({ position: "relative" });
4641 } else {
4642 $.extend( props, {
4643 position: element.css( "position" ),
4644 zIndex: element.css( "z-index" )
4645 });
4646 $.each([ "top", "left", "bottom", "right" ], function(i, pos) {
4647 props[ pos ] = element.css( pos );
4648 if ( isNaN( parseInt( props[ pos ], 10 ) ) ) {
4649 props[ pos ] = "auto";
4650 }
4651 });
4652 element.css({
4653 position: "relative",
4654 top: 0,
4655 left: 0,
4656 right: "auto",
4657 bottom: "auto"
4658 });
4659 }
4660 element.css(size);
4661
4662 return wrapper.css( props ).show();
4663 },
4664
4665 removeWrapper: function( element ) {
4666 var active = document.activeElement;
4667
4668 if ( element.parent().is( ".ui-effects-wrapper" ) ) {
4669 element.parent().replaceWith( element );
4670
4671 // Fixes #7595 - Elements lose focus when wrapped.
4672 if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
4673 $( active ).focus();
4674 }
4675 }
4676
4677
4678 return element;
4679 },
4680
4681 setTransition: function( element, list, factor, value ) {
4682 value = value || {};
4683 $.each( list, function(i, x){
4684 var unit = element.cssUnit( x );
4685 if ( unit[ 0 ] > 0 ) value[ x ] = unit[ 0 ] * factor + unit[ 1 ];
4686 });
4687 return value;
4688 }
4689 });
4690
4691 // return an effect options object for the given parameters:
4692 function _normalizeArguments( effect, options, speed, callback ) {
4693
4694 // short path for passing an effect options object:
4695 if ( $.isPlainObject( effect ) ) {
4696 return effect;
4697 }
4698
4699 // convert to an object
4700 effect = { effect: effect };
4701
4702 // catch (effect)
4703 if ( options === undefined ) {
4704 options = {};
4705 }
4706
4707 // catch (effect, callback)
4708 if ( $.isFunction( options ) ) {
4709 callback = options;
4710 speed = null;
4711 options = {};
4712 }
4713
4714 // catch (effect, speed, ?)
4715 if ( $.type( options ) === "number" || $.fx.speeds[ options ]) {
4716 callback = speed;
4717 speed = options;
4718 options = {};
4719 }
4720
4721 // catch (effect, options, callback)
4722 if ( $.isFunction( speed ) ) {
4723 callback = speed;
4724 speed = null;
4725 }
4726
4727 // add options to effect
4728 if ( options ) {
4729 $.extend( effect, options );
4730 }
4731
4732 speed = speed || options.duration;
4733 effect.duration = $.fx.off ? 0 : typeof speed === "number"
4734 ? speed : speed in $.fx.speeds ? $.fx.speeds[ speed ] : $.fx.speeds._default;
4735
4736 effect.complete = callback || options.complete;
4737
4738 return effect;
4739 }
4740
4741 function standardSpeed( speed ) {
4742 // valid standard speeds
4743 if ( !speed || typeof speed === "number" || $.fx.speeds[ speed ] ) {
4744 return true;
4745 }
4746
4747 // invalid strings - treat as "normal" speed
4748 if ( typeof speed === "string" && !$.effects.effect[ speed ] ) {
4749 // TODO: remove in 2.0 (#7115)
4750 if ( backCompat && $.effects[ speed ] ) {
4751 return false;
4752 }
4753 return true;
4754 }
4755
4756 return false;
4757 }
4758
4759 $.fn.extend({
4760 effect: function( effect, options, speed, callback ) {
4761 var args = _normalizeArguments.apply( this, arguments ),
4762 mode = args.mode,
4763 queue = args.queue,
4764 effectMethod = $.effects.effect[ args.effect ],
4765
4766 // DEPRECATED: remove in 2.0 (#7115)
4767 oldEffectMethod = !effectMethod && backCompat && $.effects[ args.effect ];
4768
4769 if ( $.fx.off || !( effectMethod || oldEffectMethod ) ) {
4770 // delegate to the original method (e.g., .show()) if possible
4771 if ( mode ) {
4772 return this[ mode ]( args.duration, args.complete );
4773 } else {
4774 return this.each( function() {
4775 if ( args.complete ) {
4776 args.complete.call( this );
4777 }
4778 });
4779 }
4780 }
4781
4782 function run( next ) {
4783 var elem = $( this ),
4784 complete = args.complete,
4785 mode = args.mode;
4786
4787 function done() {
4788 if ( $.isFunction( complete ) ) {
4789 complete.call( elem[0] );
4790 }
4791 if ( $.isFunction( next ) ) {
4792 next();
4793 }
4794 }
4795
4796 // if the element is hiddden and mode is hide,
4797 // or element is visible and mode is show
4798 if ( elem.is( ":hidden" ) ? mode === "hide" : mode === "show" ) {
4799 done();
4800 } else {
4801 effectMethod.call( elem[0], args, done );
4802 }
4803 }
4804
4805 // TODO: remove this check in 2.0, effectMethod will always be true
4806 if ( effectMethod ) {
4807 return queue === false ? this.each( run ) : this.queue( queue || "fx", run );
4808 } else {
4809 // DEPRECATED: remove in 2.0 (#7115)
4810 return oldEffectMethod.call(this, {
4811 options: args,
4812 duration: args.duration,
4813 callback: args.complete,
4814 mode: args.mode
4815 });
4816 }
4817 },
4818
4819 _show: $.fn.show,
4820 show: function( speed ) {
4821 if ( standardSpeed( speed ) ) {
4822 return this._show.apply( this, arguments );
4823 } else {
4824 var args = _normalizeArguments.apply( this, arguments );
4825 args.mode = "show";
4826 return this.effect.call( this, args );
4827 }
4828 },
4829
4830 _hide: $.fn.hide,
4831 hide: function( speed ) {
4832 if ( standardSpeed( speed ) ) {
4833 return this._hide.apply( this, arguments );
4834 } else {
4835 var args = _normalizeArguments.apply( this, arguments );
4836 args.mode = "hide";
4837 return this.effect.call( this, args );
4838 }
4839 },
4840
4841 // jQuery core overloads toggle and creates _toggle
4842 __toggle: $.fn.toggle,
4843 toggle: function( speed ) {
4844 if ( standardSpeed( speed ) || typeof speed === "boolean" || $.isFunction( speed ) ) {
4845 return this.__toggle.apply( this, arguments );
4846 } else {
4847 var args = _normalizeArguments.apply( this, arguments );
4848 args.mode = "toggle";
4849 return this.effect.call( this, args );
4850 }
4851 },
4852
4853 // helper functions
4854 cssUnit: function(key) {
4855 var style = this.css( key ),
4856 val = [];
4857
4858 $.each( [ "em", "px", "%", "pt" ], function( i, unit ) {
4859 if ( style.indexOf( unit ) > 0 )
4860 val = [ parseFloat( style ), unit ];
4861 });
4862 return val;
4863 }
4864 });
4865
4866
4867
4868 /******************************************************************************/
4869 /*********************************** EASING ***********************************/
4870 /******************************************************************************/
4871
4872 /*
4873 * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
4874 *
4875 * Uses the built in easing capabilities added In jQuery 1.1
4876 * to offer multiple easing options
4877 *
4878 * TERMS OF USE - jQuery Easing
4879 *
4880 * Open source under the BSD License.
4881 *
4882 * Copyright 2008 George McGinley Smith
4883 * All rights reserved.
4884 *
4885 * Redistribution and use in source and binary forms, with or without modification,
4886 * are permitted provided that the following conditions are met:
4887 *
4888 * Redistributions of source code must retain the above copyright notice, this list of
4889 * conditions and the following disclaimer.
4890 * Redistributions in binary form must reproduce the above copyright notice, this list
4891 * of conditions and the following disclaimer in the documentation and/or other materials
4892 * provided with the distribution.
4893 *
4894 * Neither the name of the author nor the names of contributors may be used to endorse
4895 * or promote products derived from this software without specific prior written permission.
4896 *
4897 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
4898 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
4899 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
4900 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
4901 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
4902 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
4903 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
4904 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
4905 * OF THE POSSIBILITY OF SUCH DAMAGE.
4906 *
4907 */
4908
4909 // t: current time, b: begInnIng value, c: change In value, d: duration
4910 $.easing.jswing = $.easing.swing;
4911
4912 $.extend( $.easing, {
4913 def: "easeOutQuad",
4914 swing: function ( x, t, b, c, d ) {
4915 return $.easing[ $.easing.def ]( x, t, b, c, d );
4916 },
4917 easeInQuad: function ( x, t, b, c, d ) {
4918 return c * ( t /= d ) * t + b;
4919 },
4920 easeOutQuad: function ( x, t, b, c, d ) {
4921 return -c * ( t /= d ) * ( t - 2 ) + b;
4922 },
4923 easeInOutQuad: function ( x, t, b, c, d ) {
4924 if ( ( t /= d / 2 ) < 1 ) return c / 2 * t * t + b;
4925 return -c / 2 * ( ( --t ) * ( t-2 ) - 1) + b;
4926 },
4927 easeInCubic: function ( x, t, b, c, d ) {
4928 return c * ( t /= d ) * t * t + b;
4929 },
4930 easeOutCubic: function ( x, t, b, c, d ) {
4931 return c * ( ( t = t / d - 1 ) * t * t + 1 ) + b;
4932 },
4933 easeInOutCubic: function ( x, t, b, c, d ) {
4934 if ( ( t /= d / 2 ) < 1 ) return c / 2 * t * t * t + b;
4935 return c / 2 * ( ( t -= 2 ) * t * t + 2) + b;
4936 },
4937 easeInQuart: function ( x, t, b, c, d ) {
4938 return c * ( t /= d ) * t * t * t + b;
4939 },
4940 easeOutQuart: function ( x, t, b, c, d ) {
4941 return -c * ( ( t = t / d - 1 ) * t * t * t - 1) + b;
4942 },
4943 easeInOutQuart: function ( x, t, b, c, d ) {
4944 if ( (t /= d / 2 ) < 1 ) return c / 2 * t * t * t * t + b;
4945 return -c / 2 * ( ( t -= 2 ) * t * t * t - 2) + b;
4946 },
4947 easeInQuint: function ( x, t, b, c, d ) {
4948 return c * ( t /= d ) * t * t * t * t + b;
4949 },
4950 easeOutQuint: function ( x, t, b, c, d ) {
4951 return c * ( ( t = t / d - 1 ) * t * t * t * t + 1) + b;
4952 },
4953 easeInOutQuint: function ( x, t, b, c, d ) {
4954 if ( ( t /= d / 2 ) < 1 ) return c / 2 * t * t * t * t * t + b;
4955 return c / 2 * ( ( t -= 2 ) * t * t * t * t + 2) + b;
4956 },
4957 easeInSine: function ( x, t, b, c, d ) {
4958 return -c * Math.cos( t / d * ( Math.PI / 2 ) ) + c + b;
4959 },
4960 easeOutSine: function ( x, t, b, c, d ) {
4961 return c * Math.sin( t / d * ( Math.PI /2 ) ) + b;
4962 },
4963 easeInOutSine: function ( x, t, b, c, d ) {
4964 return -c / 2 * ( Math.cos( Math.PI * t / d ) - 1 ) + b;
4965 },
4966 easeInExpo: function ( x, t, b, c, d ) {
4967 return ( t==0 ) ? b : c * Math.pow( 2, 10 * ( t / d - 1) ) + b;
4968 },
4969 easeOutExpo: function ( x, t, b, c, d ) {
4970 return ( t==d ) ? b + c : c * ( -Math.pow( 2, -10 * t / d) + 1) + b;
4971 },
4972 easeInOutExpo: function ( x, t, b, c, d ) {
4973 if ( t==0 ) return b;
4974 if ( t==d ) return b + c;
4975 if ( ( t /= d / 2) < 1) return c / 2 * Math.pow( 2, 10 * (t - 1) ) + b;
4976 return c / 2 * ( -Math.pow( 2, -10 * --t ) + 2 ) + b;
4977 },
4978 easeInCirc: function ( x, t, b, c, d ) {
4979 return -c * ( Math.sqrt( 1 - ( t /= d ) * t ) - 1 ) + b;
4980 },
4981 easeOutCirc: function ( x, t, b, c, d ) {
4982 return c * Math.sqrt( 1 - ( t = t / d - 1 ) * t ) + b;
4983 },
4984 easeInOutCirc: function ( x, t, b, c, d ) {
4985 if ( ( t /= d / 2) < 1 ) return -c / 2 * ( Math.sqrt( 1 - t * t ) - 1 ) + b;
4986 return c / 2 * ( Math.sqrt( 1 - ( t -= 2 ) * t ) + 1 ) + b;
4987 },
4988 easeInElastic: function ( x, t, b, c, d ) {
4989 var s = 1.70158,
4990 p = d * 0.3,
4991 a = c;
4992 if ( t == 0 ) return b;
4993 if ( ( t /= d ) == 1 ) return b+c;
4994 if ( a < Math.abs( c ) ) {
4995 a = c;
4996 s = p / 4;
4997 } else {
4998 s = p / ( 2 * Math.PI ) * Math.asin( c / a );
4999 }
5000 return - ( a * Math.pow( 2, 10 * ( t -= 1 ) ) * Math.sin( ( t * d - s) * ( 2 * Math.PI ) / p ) ) + b;
5001 },
5002 easeOutElastic: function ( x, t, b, c, d ) {
5003 var s = 1.70158,
5004 p = d * 0.3,
5005 a = c;
5006 if ( t == 0 ) return b;
5007 if ( ( t /= d ) == 1 ) return b+c;
5008 if ( a < Math.abs( c ) ) {
5009 a = c;
5010 s = p / 4;
5011 } else {
5012 s = p / ( 2 * Math.PI ) * Math.asin( c / a );
5013 }
5014 return a * Math.pow( 2, -10 * t ) * Math.sin( ( t * d - s ) * ( 2 * Math.PI ) / p ) + c + b;
5015 },
5016 easeInOutElastic: function ( x, t, b, c, d ) {
5017 var s = 1.70158,
5018 p = d * ( 0.3 * 1.5 ),
5019 a = c;
5020 if ( t == 0 ) return b;
5021 if ( ( t /= d / 2 ) == 2 ) return b+c;
5022 if ( a < Math.abs( c ) ) {
5023 a = c;
5024 s = p / 4;
5025 } else {
5026 s = p / ( 2 * Math.PI ) * Math.asin( c / a );
5027 }
5028 if ( t < 1 ) return -.5 * ( a * Math.pow( 2, 10 * ( t -= 1 ) ) * Math.sin( ( t * d - s ) * ( 2 * Math.PI ) / p ) ) + b;
5029 return a * Math.pow( 2, -10 * ( t -= 1 ) ) * Math.sin( ( t * d - s ) * ( 2 * Math.PI ) / p ) *.5 + c + b;
5030 },
5031 easeInBack: function ( x, t, b, c, d, s ) {
5032 if ( s == undefined ) s = 1.70158;
5033 return c * ( t /= d ) * t * ( ( s+1 ) * t - s ) + b;
5034 },
5035 easeOutBack: function ( x, t, b, c, d, s ) {
5036 if ( s == undefined ) s = 1.70158;
5037 return c * ( ( t = t / d - 1 ) * t * ( ( s + 1 ) * t + s) + 1) + b;
5038 },
5039 easeInOutBack: function ( x, t, b, c, d, s ) {
5040 if ( s == undefined ) s = 1.70158;
5041 if ( ( t /= d / 2 ) < 1 ) return c / 2 * ( t * t * ( ( ( s *= 1.525 ) + 1 ) * t - s ) ) + b;
5042 return c / 2 * ( ( t -= 2 ) * t * ( ( ( s *= 1.525 ) + 1 ) * t + s) + 2) + b;
5043 },
5044 easeInBounce: function ( x, t, b, c, d ) {
5045 return c - $.easing.easeOutBounce( x, d - t, 0, c, d ) + b;
5046 },
5047 easeOutBounce: function ( x, t, b, c, d ) {
5048 if ( ( t /= d ) < ( 1 / 2.75 ) ) {
5049 return c * ( 7.5625 * t * t ) + b;
5050 } else if ( t < ( 2 / 2.75 ) ) {
5051 return c * ( 7.5625 * ( t -= ( 1.5 / 2.75 ) ) * t + .75 ) + b;
5052 } else if ( t < ( 2.5 / 2.75 ) ) {
5053 return c * ( 7.5625 * ( t -= ( 2.25/ 2.75 ) ) * t + .9375 ) + b;
5054 } else {
5055 return c * ( 7.5625 * ( t -= ( 2.625 / 2.75 ) ) * t + .984375 ) + b;
5056 }
5057 },
5058 easeInOutBounce: function ( x, t, b, c, d ) {
5059 if ( t < d / 2 ) return $.easing.easeInBounce( x, t * 2, 0, c, d ) * .5 + b;
5060 return $.easing.easeOutBounce( x, t * 2 - d, 0, c, d ) * .5 + c * .5 + b;
5061 }
5062 });
5063
5064 /*
5065 *
5066 * TERMS OF USE - EASING EQUATIONS
5067 *
5068 * Open source under the BSD License.
5069 *
5070 * Copyright 2001 Robert Penner
5071 * All rights reserved.
5072 *
5073 * Redistribution and use in source and binary forms, with or without modification,
5074 * are permitted provided that the following conditions are met:
5075 *
5076 * Redistributions of source code must retain the above copyright notice, this list of
5077 * conditions and the following disclaimer.
5078 * Redistributions in binary form must reproduce the above copyright notice, this list
5079 * of conditions and the following disclaimer in the documentation and/or other materials
5080 * provided with the distribution.
5081 *
5082 * Neither the name of the author nor the names of contributors may be used to endorse
5083 * or promote products derived from this software without specific prior written permission.
5084 *
5085 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
5086 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
5087 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
5088 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
5089 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
5090 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
5091 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
5092 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
5093 * OF THE POSSIBILITY OF SUCH DAMAGE.
5094 *
5095 */
5096
5097 })(jQuery);
5098 /*
5099 * jQuery UI Effects Blind @VERSION
5100 *
5101 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
5102 * Dual licensed under the MIT or GPL Version 2 licenses.
5103 * http://jquery.org/license
5104 *
5105 * http://docs.jquery.com/UI/Effects/Blind
5106 *
5107 * Depends:
5108 * jquery.effects.core.js
5109 */
5110 (function( $, undefined ) {
5111
5112 var rvertical = /up|down|vertical/,
5113 rpositivemotion = /up|left|vertical|horizontal/;
5114
5115 $.effects.effect.blind = function( o, done ) {
5116 // Create element
5117 var el = $( this ),
5118 props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
5119 mode = $.effects.setMode( el, o.mode || "hide" ),
5120 direction = o.direction || "up",
5121 vertical = rvertical.test( direction ),
5122 ref = vertical ? "height" : "width",
5123 ref2 = vertical ? "top" : "left",
5124 motion = rpositivemotion.test( direction ),
5125 animation = {},
5126 show = mode === "show",
5127 wrapper, distance;
5128
5129 // if already wrapped, the wrapper's properties are my property. #6245
5130 if ( el.parent().is( ".ui-effects-wrapper" ) ) {
5131 $.effects.save( el.parent(), props );
5132 } else {
5133 $.effects.save( el, props );
5134 }
5135 el.show();
5136 wrapper = $.effects.createWrapper( el ).css({
5137 overflow: "hidden"
5138 });
5139
5140 distance = wrapper[ ref ]();
5141
5142 animation[ ref ] = show ? distance : 0;
5143 if ( !motion ) {
5144 el
5145 .css( vertical ? "bottom" : "right", 0 )
5146 .css( vertical ? "top" : "left", "" )
5147 .css({ position: "absolute" });
5148 animation[ ref2 ] = show ? 0 : distance;
5149 }
5150
5151 // start at 0 if we are showing
5152 if ( show ) {
5153 wrapper.css( ref, 0 );
5154 if ( ! motion ) {
5155 wrapper.css( ref2, distance );
5156 }
5157 }
5158
5159 // Animate
5160 wrapper.animate( animation, {
5161 duration: o.duration,
5162 easing: o.easing,
5163 queue: false,
5164 complete: function() {
5165 if ( mode === "hide" ) {
5166 el.hide();
5167 }
5168 $.effects.restore( el, props );
5169 $.effects.removeWrapper( el );
5170 done();
5171 }
5172 });
5173
5174 };
5175
5176 })(jQuery);
5177 /*
5178 * jQuery UI Effects Bounce @VERSION
5179 *
5180 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
5181 * Dual licensed under the MIT or GPL Version 2 licenses.
5182 * http://jquery.org/license
5183 *
5184 * http://docs.jquery.com/UI/Effects/Bounce
5185 *
5186 * Depends:
5187 * jquery.effects.core.js
5188 */
5189 (function( $, undefined ) {
5190
5191 $.effects.effect.bounce = function( o, done ) {
5192 var el = $( this ),
5193 props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
5194
5195 // defaults:
5196 mode = $.effects.setMode( el, o.mode || "effect" ),
5197 hide = mode === "hide",
5198 show = mode === "show",
5199 direction = o.direction || "up",
5200 distance = o.distance,
5201 times = o.times || 5,
5202
5203 // number of internal animations
5204 anims = times * 2 + ( show || hide ? 1 : 0 ),
5205 speed = o.duration / anims,
5206 easing = o.easing,
5207
5208 // utility:
5209 ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
5210 motion = ( direction === "up" || direction === "left" ),
5211 i,
5212 upAnim,
5213 downAnim,
5214
5215 // we will need to re-assemble the queue to stack our animations in place
5216 queue = el.queue(),
5217 queuelen = queue.length;
5218
5219 // Avoid touching opacity to prevent clearType and PNG issues in IE
5220 if ( show || hide ) {
5221 props.push( "opacity" );
5222 }
5223
5224 $.effects.save( el, props );
5225 el.show();
5226 $.effects.createWrapper( el ); // Create Wrapper
5227
5228 // default distance for the BIGGEST bounce is the outer Distance / 3
5229 if ( !distance ) {
5230 distance = el[ ref === "top" ? "outerHeight" : "outerWidth" ]() / 3;
5231 }
5232
5233 if ( show ) {
5234 downAnim = { opacity: 1 };
5235 downAnim[ ref ] = 0;
5236
5237 // if we are showing, force opacity 0 and set the initial position
5238 // then do the "first" animation
5239 el.css( "opacity", 0 )
5240 .css( ref, motion ? -distance * 2 : distance * 2 )
5241 .animate( downAnim, speed, easing );
5242 }
5243
5244 // start at the smallest distance if we are hiding
5245 if ( hide ) {
5246 distance = distance / Math.pow( 2, times - 1 );
5247 }
5248
5249 downAnim = {};
5250 downAnim[ ref ] = 0;
5251 // Bounces up/down/left/right then back to 0 -- times * 2 animations happen here
5252 for ( i = 0; i < times; i++ ) {
5253 upAnim = {};
5254 upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance;
5255
5256 el.animate( upAnim, speed, easing )
5257 .animate( downAnim, speed, easing );
5258
5259 distance = hide ? distance * 2 : distance / 2;
5260 }
5261
5262 // Last Bounce when Hiding
5263 if ( hide ) {
5264 upAnim = { opacity: 0 };
5265 upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance;
5266
5267 el.animate( upAnim, speed, easing );
5268 }
5269
5270 el.queue(function() {
5271 if ( hide ) {
5272 el.hide();
5273 }
5274 $.effects.restore( el, props );
5275 $.effects.removeWrapper( el );
5276 done();
5277 });
5278
5279 // inject all the animations we just queued to be first in line (after "inprogress")
5280 if ( queuelen > 1) {
5281 queue.splice.apply( queue,
5282 [ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) );
5283 }
5284 el.dequeue();
5285
5286 };
5287
5288 })(jQuery);
5289 /*
5290 * jQuery UI Effects Clip @VERSION
5291 *
5292 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
5293 * Dual licensed under the MIT or GPL Version 2 licenses.
5294 * http://jquery.org/license
5295 *
5296 * http://docs.jquery.com/UI/Effects/Clip
5297 *
5298 * Depends:
5299 * jquery.effects.core.js
5300 */
5301 (function( $, undefined ) {
5302
5303 $.effects.effect.clip = function( o, done ) {
5304 // Create element
5305 var el = $( this ),
5306 props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
5307 mode = $.effects.setMode( el, o.mode || "hide" ),
5308 show = mode === "show",
5309 direction = o.direction || "vertical",
5310 vert = direction === "vertical",
5311 size = vert ? "height" : "width",
5312 position = vert ? "top" : "left",
5313 animation = {},
5314 wrapper, animate, distance;
5315
5316 // Save & Show
5317 $.effects.save( el, props );
5318 el.show();
5319
5320 // Create Wrapper
5321 wrapper = $.effects.createWrapper( el ).css({
5322 overflow: "hidden"
5323 });
5324 animate = ( el[0].tagName === "IMG" ) ? wrapper : el;
5325 distance = animate[ size ]();
5326
5327 // Shift
5328 if ( show ) {
5329 animate.css( size, 0 );
5330 animate.css( position, distance / 2 );
5331 }
5332
5333 // Create Animation Object:
5334 animation[ size ] = show ? distance : 0;
5335 animation[ position ] = show ? 0 : distance / 2;
5336
5337 // Animate
5338 animate.animate( animation, {
5339 queue: false,
5340 duration: o.duration,
5341 easing: o.easing,
5342 complete: function() {
5343 if ( !show ) {
5344 el.hide();
5345 }
5346 $.effects.restore( el, props );
5347 $.effects.removeWrapper( el );
5348 done();
5349 }
5350 });
5351
5352 };
5353
5354 })(jQuery);
5355 /*
5356 * jQuery UI Effects Drop @VERSION
5357 *
5358 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
5359 * Dual licensed under the MIT or GPL Version 2 licenses.
5360 * http://jquery.org/license
5361 *
5362 * http://docs.jquery.com/UI/Effects/Drop
5363 *
5364 * Depends:
5365 * jquery.effects.core.js
5366 */
5367 (function( $, undefined ) {
5368
5369 $.effects.effect.drop = function( o, done ) {
5370
5371 var el = $( this ),
5372 props = [ "position", "top", "bottom", "left", "right", "opacity", "height", "width" ],
5373 mode = $.effects.setMode( el, o.mode || "hide" ),
5374 show = mode === "show",
5375 direction = o.direction || "left",
5376 ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
5377 motion = ( direction === "up" || direction === "left" ) ? "pos" : "neg",
5378 animation = {
5379 opacity: show ? 1 : 0
5380 },
5381 distance;
5382
5383 // Adjust
5384 $.effects.save( el, props );
5385 el.show();
5386 $.effects.createWrapper( el );
5387
5388 distance = o.distance || el[ ref == "top" ? "outerHeight": "outerWidth" ]({ margin: true }) / 2;
5389
5390 if ( show ) {
5391 el
5392 .css( "opacity", 0 )
5393 .css( ref, motion == "pos" ? -distance : distance );
5394 }
5395
5396 // Animation
5397 animation[ ref ] = ( show ?
5398 ( motion === "pos" ? "+=" : "-=" ) :
5399 ( motion === "pos" ? "-=" : "+=" ) )
5400 + distance;
5401
5402 // Animate
5403 el.animate( animation, {
5404 queue: false,
5405 duration: o.duration,
5406 easing: o.easing,
5407 complete: function() {
5408 mode == "hide" && el.hide();
5409 $.effects.restore( el, props );
5410 $.effects.removeWrapper( el );
5411 done();
5412 }
5413 });
5414
5415 };
5416
5417 })(jQuery);
5418 /*
5419 * jQuery UI Effects Explode @VERSION
5420 *
5421 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
5422 * Dual licensed under the MIT or GPL Version 2 licenses.
5423 * http://jquery.org/license
5424 *
5425 * http://docs.jquery.com/UI/Effects/Explode
5426 *
5427 * Depends:
5428 * jquery.effects.core.js
5429 */
5430 (function( $, undefined ) {
5431
5432 $.effects.effect.explode = function( o, done ) {
5433
5434 var rows = o.pieces ? Math.round( Math.sqrt( o.pieces ) ) : 3,
5435 cells = rows,
5436 el = $( this ),
5437 mode = $.effects.setMode( el, o.mode || "hide" ),
5438 show = mode === "show",
5439
5440 // show and then visibility:hidden the element before calculating offset
5441 offset = el.show().css( "visibility", "hidden" ).offset(),
5442
5443 // width and height of a piece
5444 width = Math.ceil( el.outerWidth() / cells ),
5445 height = Math.ceil( el.outerHeight() / rows ),
5446 pieces = [],
5447
5448 // loop
5449 i, j, left, top, mx, my;
5450
5451 // clone the element for each row and cell.
5452 for( i = 0; i < rows ; i++ ) { // ===>
5453 top = offset.top + i * height;
5454 my = i - ( rows - 1 ) / 2 ;
5455
5456 for( j = 0; j < cells ; j++ ) { // |||
5457 left = offset.left + j * width;
5458 mx = j - ( cells - 1 ) / 2 ;
5459
5460 // Create a clone of the now hidden main element that will be absolute positioned
5461 // within a wrapper div off the -left and -top equal to size of our pieces
5462 el
5463 .clone()
5464 .appendTo( "body" )
5465 .wrap( "<div></div>" )
5466 .css({
5467 position: "absolute",
5468 visibility: "visible",
5469 left: -j * width,
5470 top: -i * height
5471 })
5472
5473 // select the wrapper - make it overflow: hidden and absolute positioned based on
5474 // where the original was located +left and +top equal to the size of pieces
5475 .parent()
5476 .addClass( "ui-effects-explode" )
5477 .css({
5478 position: "absolute",
5479 overflow: "hidden",
5480 width: width,
5481 height: height,
5482 left: left + ( show ? mx * width : 0 ),
5483 top: top + ( show ? my * height : 0 ),
5484 opacity: show ? 0 : 1
5485 }).animate({
5486 left: left + ( show ? 0 : mx * width ),
5487 top: top + ( show ? 0 : my * height ),
5488 opacity: show ? 1 : 0
5489 }, o.duration || 500, o.easing, childComplete );
5490 }
5491 }
5492
5493 // children animate complete:
5494 function childComplete() {
5495 pieces.push( this );
5496 if ( pieces.length == rows * cells ) {
5497 animComplete();
5498 }
5499 }
5500
5501 function animComplete() {
5502 el.css({
5503 visibility: "visible"
5504 });
5505 $( pieces ).remove();
5506 if ( !show ) {
5507 el.hide();
5508 }
5509 done();
5510 }
5511 };
5512
5513 })(jQuery);
5514 /*
5515 * jQuery UI Effects Fade @VERSION
5516 *
5517 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
5518 * Dual licensed under the MIT or GPL Version 2 licenses.
5519 * http://jquery.org/license
5520 *
5521 * http://docs.jquery.com/UI/Effects/Fade
5522 *
5523 * Depends:
5524 * jquery.effects.core.js
5525 */
5526 (function( $, undefined ) {
5527
5528 $.effects.effect.fade = function( o, done ) {
5529 var el = $( this ),
5530 mode = $.effects.setMode( el, o.mode || "toggle" ),
5531 hide = mode === "hide";
5532
5533 el.show();
5534 el.animate({
5535 opacity: hide ? 0 : 1
5536 }, {
5537 queue: false,
5538 duration: o.duration,
5539 easing: o.easing,
5540 complete: function() {
5541 if ( hide ) {
5542 el.hide();
5543 }
5544 done();
5545 }
5546 });
5547 };
5548
5549 })(jQuery);
5550 /*
5551 * jQuery UI Effects Fold @VERSION
5552 *
5553 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
5554 * Dual licensed under the MIT or GPL Version 2 licenses.
5555 * http://jquery.org/license
5556 *
5557 * http://docs.jquery.com/UI/Effects/Fold
5558 *
5559 * Depends:
5560 * jquery.effects.core.js
5561 */
5562 (function( $, undefined ) {
5563
5564 $.effects.effect.fold = function( o, done ) {
5565
5566 // Create element
5567 var el = $( this ),
5568 props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
5569 mode = $.effects.setMode( el, o.mode || "hide" ),
5570 show = mode === "show",
5571 hide = mode === "hide",
5572 size = o.size || 15,
5573 percent = /([0-9]+)%/.exec( size ),
5574 horizFirst = !!o.horizFirst,
5575 widthFirst = show != horizFirst,
5576 ref = widthFirst ? [ "width", "height" ] : [ "height", "width" ],
5577 duration = o.duration / 2,
5578 wrapper, distance,
5579 animation1 = {}, animation2 = {};
5580
5581 $.effects.save( el, props );
5582 el.show();
5583
5584 // Create Wrapper
5585 wrapper = $.effects.createWrapper( el ).css({
5586 overflow: "hidden"
5587 });
5588 distance = widthFirst ?
5589 [ wrapper.width(), wrapper.height() ] :
5590 [ wrapper.height(), wrapper.width() ];
5591
5592 if ( percent ) {
5593 size = parseInt( percent[ 1 ], 10 ) / 100 * distance[ hide ? 0 : 1 ];
5594 }
5595 if ( show ) {
5596 wrapper.css( horizFirst ? {
5597 height: 0,
5598 width: size
5599 } : {
5600 height: size,
5601 width: 0
5602 });
5603 }
5604
5605 // Animation
5606 animation1[ ref[ 0 ] ] = show ? distance[ 0 ] : size;
5607 animation2[ ref[ 1 ] ] = show ? distance[ 1 ] : 0;
5608
5609 // Animate
5610 wrapper
5611 .animate( animation1, duration, o.easing )
5612 .animate( animation2, duration, o.easing, function() {
5613 if ( hide ) {
5614 el.hide();
5615 }
5616 $.effects.restore( el, props );
5617 $.effects.removeWrapper( el );
5618 done();
5619 });
5620
5621 };
5622
5623 })(jQuery);
5624 /*
5625 * jQuery UI Effects Highlight @VERSION
5626 *
5627 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
5628 * Dual licensed under the MIT or GPL Version 2 licenses.
5629 * http://jquery.org/license
5630 *
5631 * http://docs.jquery.com/UI/Effects/Highlight
5632 *
5633 * Depends:
5634 * jquery.effects.core.js
5635 */
5636 (function( $, undefined ) {
5637
5638 $.effects.effect.highlight = function( o, done ) {
5639 var elem = $( this ),
5640 props = [ "backgroundImage", "backgroundColor", "opacity" ],
5641 mode = $.effects.setMode( elem, o.mode || "show" ),
5642 animation = {
5643 backgroundColor: elem.css( "backgroundColor" )
5644 };
5645
5646 if (mode === "hide") {
5647 animation.opacity = 0;
5648 }
5649
5650 $.effects.save( elem, props );
5651
5652 elem
5653 .show()
5654 .css({
5655 backgroundImage: "none",
5656 backgroundColor: o.color || "#ffff99"
5657 })
5658 .animate( animation, {
5659 queue: false,
5660 duration: o.duration,
5661 easing: o.easing,
5662 complete: function() {
5663 if ( mode === "hide" ) {
5664 elem.hide();
5665 }
5666 $.effects.restore( elem, props );
5667 done();
5668 }
5669 });
5670 };
5671
5672 })(jQuery);
5673 /*
5674 * jQuery UI Effects Pulsate @VERSION
5675 *
5676 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
5677 * Dual licensed under the MIT or GPL Version 2 licenses.
5678 * http://jquery.org/license
5679 *
5680 * http://docs.jquery.com/UI/Effects/Pulsate
5681 *
5682 * Depends:
5683 * jquery.effects.core.js
5684 */
5685 (function( $, undefined ) {
5686
5687 $.effects.effect.pulsate = function( o, done ) {
5688 var elem = $( this ),
5689 mode = $.effects.setMode( elem, o.mode || "show" ),
5690 show = mode === "show",
5691 hide = mode === "hide",
5692 showhide = ( show || mode === "hide" ),
5693
5694 // showing or hiding leaves of the "last" animation
5695 anims = ( ( o.times || 5 ) * 2 ) + ( showhide ? 1 : 0 ),
5696 duration = o.duration / anims,
5697 animateTo = 0,
5698 queue = elem.queue(),
5699 queuelen = queue.length,
5700 i;
5701
5702 if ( show || !elem.is(":visible")) {
5703 elem.css( "opacity", 0 ).show();
5704 animateTo = 1;
5705 }
5706
5707 // anims - 1 opacity "toggles"
5708 for ( i = 1; i < anims; i++ ) {
5709 elem.animate({
5710 opacity: animateTo
5711 }, duration, o.easing );
5712 animateTo = 1 - animateTo;
5713 }
5714
5715 elem.animate({
5716 opacity: animateTo
5717 }, duration, o.easing);
5718
5719 elem.queue(function() {
5720 if ( hide ) {
5721 elem.hide();
5722 }
5723 done();
5724 });
5725
5726 // We just queued up "anims" animations, we need to put them next in the queue
5727 if ( queuelen > 1 ) {
5728 queue.splice.apply( queue,
5729 [ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) );
5730 }
5731 elem.dequeue();
5732 };
5733
5734 })(jQuery);
5735 /*
5736 * jQuery UI Effects Scale @VERSION
5737 *
5738 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
5739 * Dual licensed under the MIT or GPL Version 2 licenses.
5740 * http://jquery.org/license
5741 *
5742 * http://docs.jquery.com/UI/Effects/Scale
5743 *
5744 * Depends:
5745 * jquery.effects.core.js
5746 */
5747 (function( $, undefined ) {
5748
5749 $.effects.effect.puff = function( o, done ) {
5750 var elem = $( this ),
5751 mode = $.effects.setMode( elem, o.mode || "hide" ),
5752 hide = mode === "hide",
5753 percent = parseInt( o.percent, 10 ) || 150,
5754 factor = percent / 100,
5755 original = {
5756 height: elem.height(),
5757 width: elem.width()
5758 };
5759
5760 $.extend( o, {
5761 effect: "scale",
5762 queue: false,
5763 fade: true,
5764 mode: mode,
5765 complete: done,
5766 percent: hide ? percent : 100,
5767 from: hide
5768 ? original
5769 : {
5770 height: original.height * factor,
5771 width: original.width * factor
5772 }
5773 });
5774
5775 elem.effect( o );
5776 };
5777
5778 $.effects.effect.scale = function( o, done ) {
5779
5780 // Create element
5781 var el = $( this ),
5782 options = $.extend( true, {}, o ),
5783 mode = $.effects.setMode( el, o.mode || "effect" ),
5784 percent = parseInt( o.percent, 10 ) || ( parseInt( o.percent, 10 ) == 0 ? 0 : ( mode == "hide" ? 0 : 100 ) ),
5785 direction = o.direction || "both",
5786 origin = o.origin,
5787 original = {
5788 height: el.height(),
5789 width: el.width(),
5790 outerHeight: el.outerHeight(),
5791 outerWidth: el.outerWidth()
5792 },
5793 factor = {
5794 y: direction != "horizontal" ? (percent / 100) : 1,
5795 x: direction != "vertical" ? (percent / 100) : 1
5796 };
5797
5798 // We are going to pass this effect to the size effect:
5799 options.effect = "size";
5800 options.queue = false;
5801 options.complete = done;
5802
5803 // Set default origin and restore for show/hide
5804 if ( mode != "effect" ) {
5805 options.origin = origin || ["middle","center"];
5806 options.restore = true;
5807 }
5808
5809 options.from = o.from || ( mode == "show" ? { height: 0, width: 0 } : original );
5810 options.to = {
5811 height: original.height * factor.y,
5812 width: original.width * factor.x,
5813 outerHeight: original.outerHeight * factor.y,
5814 outerWidth: original.outerWidth * factor.x
5815 };
5816
5817 if ( options.fade ) { // Fade option to support puff
5818 if ( mode == "show" ) {
5819 options.from.opacity = 0;
5820 options.to.opacity = 1;
5821 }
5822 if ( mode == "hide" ) {
5823 options.from.opacity = 1;
5824 options.to.opacity = 0;
5825 }
5826 };
5827
5828 // Animate
5829 el.effect( options );
5830
5831 };
5832
5833 $.effects.effect.size = function( o, done ) {
5834
5835 // Create element
5836 var el = $( this ),
5837 props = [ "position", "top", "bottom", "left", "right", "width", "height", "overflow", "opacity" ],
5838
5839 // Always restore
5840 props1 = [ "position", "top", "bottom", "left", "right", "overflow", "opacity" ],
5841
5842 // Copy for children
5843 props2 = [ "width", "height", "overflow" ],
5844 cProps = [ "fontSize" ],
5845 vProps = [ "borderTopWidth", "borderBottomWidth", "paddingTop", "paddingBottom" ],
5846 hProps = [ "borderLeftWidth", "borderRightWidth", "paddingLeft", "paddingRight" ],
5847
5848 // Set options
5849 mode = $.effects.setMode( el, o.mode || "effect" ),
5850 restore = o.restore || mode !== "effect",
5851 scale = o.scale || "both",
5852 origin = o.origin || [ "middle", "center" ],
5853 original, baseline, factor,
5854 position = el.css( "position" );
5855
5856 if ( mode === "show" ) {
5857 el.show();
5858 }
5859 original = {
5860 height: el.height(),
5861 width: el.width(),
5862 outerHeight: el.outerHeight(),
5863 outerWidth: el.outerWidth()
5864 };
5865
5866 el.from = o.from || original;
5867 el.to = o.to || original;
5868
5869 // Set scaling factor
5870 factor = {
5871 from: {
5872 y: el.from.height / original.height,
5873 x: el.from.width / original.width
5874 },
5875 to: {
5876 y: el.to.height / original.height,
5877 x: el.to.width / original.width
5878 }
5879 };
5880
5881 // Scale the css box
5882 if ( scale == "box" || scale == "both" ) {
5883
5884 // Vertical props scaling
5885 if ( factor.from.y !== factor.to.y ) {
5886 props = props.concat( vProps );
5887 el.from = $.effects.setTransition( el, vProps, factor.from.y, el.from );
5888 el.to = $.effects.setTransition( el, vProps, factor.to.y, el.to );
5889 };
5890
5891 // Horizontal props scaling
5892 if ( factor.from.x !== factor.to.x ) {
5893 props = props.concat( hProps );
5894 el.from = $.effects.setTransition( el, hProps, factor.from.x, el.from );
5895 el.to = $.effects.setTransition( el, hProps, factor.to.x, el.to );
5896 };
5897 };
5898
5899 // Scale the content
5900 if ( scale == "content" || scale == "both" ) {
5901
5902 // Vertical props scaling
5903 if ( factor.from.y !== factor.to.y ) {
5904 props = props.concat( cProps );
5905 el.from = $.effects.setTransition( el, cProps, factor.from.y, el.from );
5906 el.to = $.effects.setTransition( el, cProps, factor.to.y, el.to );
5907 };
5908 };
5909
5910 $.effects.save( el, restore ? props : props1 );
5911 el.show();
5912 $.effects.createWrapper( el );
5913 el.css( "overflow", "hidden" ).css( el.from );
5914
5915 // Adjust
5916 if (origin) { // Calculate baseline shifts
5917 baseline = $.effects.getBaseline( origin, original );
5918 el.from.top = ( original.outerHeight - el.outerHeight() ) * baseline.y;
5919 el.from.left = ( original.outerWidth - el.outerWidth() ) * baseline.x;
5920 el.to.top = ( original.outerHeight - el.to.outerHeight ) * baseline.y;
5921 el.to.left = ( original.outerWidth - el.to.outerWidth ) * baseline.x;
5922 }
5923 el.css( el.from ); // set top & left
5924
5925 // Animate
5926 if ( scale == "content" || scale == "both" ) { // Scale the children
5927
5928 // Add margins/font-size
5929 vProps = vProps.concat([ "marginTop", "marginBottom" ]).concat(cProps);
5930 hProps = hProps.concat([ "marginLeft", "marginRight" ]);
5931 props2 = props.concat(vProps).concat(hProps);
5932
5933 el.find( "*[width]" ).each( function(){
5934 var child = $( this ),
5935 c_original = {
5936 height: child.height(),
5937 width: child.width()
5938 };
5939 if (restore) $.effects.save(child, props2);
5940
5941 child.from = {
5942 height: c_original.height * factor.from.y,
5943 width: c_original.width * factor.from.x
5944 };
5945 child.to = {
5946 height: c_original.height * factor.to.y,
5947 width: c_original.width * factor.to.x
5948 };
5949
5950 // Vertical props scaling
5951 if ( factor.from.y != factor.to.y ) {
5952 child.from = $.effects.setTransition( child, vProps, factor.from.y, child.from );
5953 child.to = $.effects.setTransition( child, vProps, factor.to.y, child.to );
5954 };
5955
5956 // Horizontal props scaling
5957 if ( factor.from.x != factor.to.x ) {
5958 child.from = $.effects.setTransition( child, hProps, factor.from.x, child.from );
5959 child.to = $.effects.setTransition( child, hProps, factor.to.x, child.to );
5960 };
5961
5962 // Animate children
5963 child.css( child.from );
5964 child.animate( child.to, o.duration, o.easing, function() {
5965
5966 // Restore children
5967 if (restore) $.effects.restore( child, props2 );
5968 });
5969 });
5970 };
5971
5972 // Animate
5973 el.animate( el.to, {
5974 queue: false,
5975 duration: o.duration,
5976 easing: o.easing,
5977 complete: function() {
5978 if ( el.to.opacity === 0 ) {
5979 el.css( "opacity", el.from.opacity );
5980 }
5981 if( mode == "hide" ) {
5982 el.hide();
5983 }
5984 $.effects.restore( el, restore ? props : props1 );
5985 if ( !restore ) {
5986
5987 // we need to calculate our new positioning based on the scaling
5988 if ( position === "static" ) {
5989 el.css({
5990 position: "relative",
5991 top: el.to.top,
5992 left: el.to.left
5993 });
5994 } else {
5995 $.each([ "top", "left" ], function( idx, pos ) {
5996 el.css( pos, function( _, str ) {
5997 var val = parseInt( str, 10 ),
5998 toRef = idx ? el.to.left : el.to.top,
5999 delta = idx ? el.to.outerWidth - el.from.outerWidth: el.to.outerHeight - el.from.outerHeight,
6000 same = origin[ idx ] === pos,
6001 mid = origin[ idx ] === "middle" || origin[ idx ] === "center";
6002
6003 // if original was "auto", recalculate the new value from wrapper
6004 if ( str === "auto" ) {
6005 return toRef + "px";
6006 }
6007
6008 return val + toRef + "px";
6009 });
6010 });
6011 }
6012 }
6013
6014 $.effects.removeWrapper( el );
6015 done();
6016 }
6017 });
6018
6019 };
6020
6021 })(jQuery);
6022 /*
6023 * jQuery UI Effects Shake @VERSION
6024 *
6025 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
6026 * Dual licensed under the MIT or GPL Version 2 licenses.
6027 * http://jquery.org/license
6028 *
6029 * http://docs.jquery.com/UI/Effects/Shake
6030 *
6031 * Depends:
6032 * jquery.effects.core.js
6033 */
6034 (function( $, undefined ) {
6035
6036 $.effects.effect.shake = function( o, done ) {
6037
6038 var el = $( this ),
6039 props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
6040 mode = $.effects.setMode( el, o.mode || "effect" ),
6041 direction = o.direction || "left",
6042 distance = o.distance || 20,
6043 times = o.times || 3,
6044 anims = times * 2 + 1,
6045 speed = o.duration,
6046 ref = (direction == "up" || direction == "down") ? "top" : "left",
6047 positiveMotion = (direction == "up" || direction == "left"),
6048 animation = {},
6049 animation1 = {},
6050 animation2 = {},
6051 i,
6052
6053 // we will need to re-assemble the queue to stack our animations in place
6054 queue = el.queue(),
6055 queuelen = queue.length;
6056
6057
6058 $.effects.save( el, props );
6059 el.show();
6060 $.effects.createWrapper( el );
6061
6062 // Animation
6063 animation[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance;
6064 animation1[ ref ] = ( positiveMotion ? "+=" : "-=" ) + distance * 2;
6065 animation2[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance * 2;
6066
6067 // Animate
6068 el.animate( animation, speed, o.easing );
6069
6070 // Shakes
6071 for ( i = 1; i < times; i++ ) {
6072 el.animate( animation1, speed, o.easing ).animate( animation2, speed, o.easing );
6073 };
6074 el
6075 .animate( animation1, speed, o.easing )
6076 .animate( animation, speed / 2, o.easing )
6077 .queue(function() {
6078 if ( mode === "hide" ) {
6079 el.hide();
6080 }
6081 $.effects.restore( el, props );
6082 $.effects.removeWrapper( el );
6083 done();
6084 });
6085
6086 // inject all the animations we just queued to be first in line (after "inprogress")
6087 if ( queuelen > 1) {
6088 queue.splice.apply( queue,
6089 [ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) );
6090 }
6091 el.dequeue();
6092
6093 };
6094
6095 })(jQuery);
6096 /*
6097 * jQuery UI Effects Slide @VERSION
6098 *
6099 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
6100 * Dual licensed under the MIT or GPL Version 2 licenses.
6101 * http://jquery.org/license
6102 *
6103 * http://docs.jquery.com/UI/Effects/Slide
6104 *
6105 * Depends:
6106 * jquery.effects.core.js
6107 */
6108 (function( $, undefined ) {
6109
6110 $.effects.effect.slide = function( o, done ) {
6111
6112 // Create element
6113 var el = $( this ),
6114 props = [ "position", "top", "bottom", "left", "right", "width", "height" ],
6115 mode = $.effects.setMode( el, o.mode || "show" ),
6116 show = mode === "show",
6117 direction = o.direction || "left",
6118 ref = (direction == "up" || direction == "down") ? "top" : "left",
6119 positiveMotion = (direction == "up" || direction == "left"),
6120 distance,
6121 animation = {},
6122 size;
6123
6124 // Adjust
6125 $.effects.save( el, props );
6126 el.show();
6127 distance = o.distance || el[ ref === "top" ? "outerHeight" : "outerWidth" ]({
6128 margin: true
6129 });
6130
6131 $.effects.createWrapper( el ).css({
6132 overflow: "hidden"
6133 });
6134
6135 if ( show ) {
6136 el.css( ref, positiveMotion ? (isNaN(distance) ? "-" + distance : -distance) : distance );
6137 }
6138
6139 // Animation
6140 animation[ ref ] = ( show ?
6141 ( positiveMotion ? "+=" : "-=") :
6142 ( positiveMotion ? "-=" : "+="))
6143 + distance;
6144
6145 // Animate
6146 el.animate( animation, {
6147 queue: false,
6148 duration: o.duration,
6149 easing: o.easing,
6150 complete: function() {
6151 if ( mode === "hide" ) {
6152 el.hide();
6153 }
6154 $.effects.restore( el, props );
6155 $.effects.removeWrapper( el );
6156 done();
6157 }
6158 });
6159
6160 };
6161
6162 })(jQuery);
6163 /*
6164 * jQuery UI Effects Transfer @VERSION
6165 *
6166 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
6167 * Dual licensed under the MIT or GPL Version 2 licenses.
6168 * http://jquery.org/license
6169 *
6170 * http://docs.jquery.com/UI/Effects/Transfer
6171 *
6172 * Depends:
6173 * jquery.effects.core.js
6174 */
6175 (function( $, undefined ) {
6176
6177 $.effects.effect.transfer = function( o, done ) {
6178 var elem = $( this ),
6179 target = $( o.to ),
6180 targetFixed = target.css( "position" ) === "fixed",
6181 body = $("body"),
6182 fixTop = targetFixed ? body.scrollTop() : 0,
6183 fixLeft = targetFixed ? body.scrollLeft() : 0,
6184 endPosition = target.offset(),
6185 animation = {
6186 top: endPosition.top - fixTop ,
6187 left: endPosition.left - fixLeft ,
6188 height: target.innerHeight(),
6189 width: target.innerWidth()
6190 },
6191 startPosition = elem.offset(),
6192 transfer = $( '<div class="ui-effects-transfer"></div>' )
6193 .appendTo( document.body )
6194 .addClass( o.className )
6195 .css({
6196 top: startPosition.top - fixTop ,
6197 left: startPosition.left - fixLeft ,
6198 height: elem.innerHeight(),
6199 width: elem.innerWidth(),
6200 position: targetFixed ? "fixed" : "absolute"
6201 })
6202 .animate( animation, o.duration, o.easing, function() {
6203 transfer.remove();
6204 done();
6205 });
6206 };
6207
6208 })(jQuery);
6209 /*
6210 * jQuery UI Accordion @VERSION
6211 *
6212 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
6213 * Dual licensed under the MIT or GPL Version 2 licenses.
6214 * http://jquery.org/license
6215 *
6216 * http://docs.jquery.com/UI/Accordion
6217 *
6218 * Depends:
6219 * jquery.ui.core.js
6220 * jquery.ui.widget.js
6221 */
6222 (function( $, undefined ) {
6223
6224 // TODO: use ui-accordion-header-active class and fix styling
6225 $.widget( "ui.accordion", {
6226 version: "@VERSION",
6227 options: {
6228 active: 0,
6229 animated: "slide",
6230 collapsible: false,
6231 event: "click",
6232 header: "> li > :first-child,> :not(li):even",
6233 heightStyle: "auto",
6234 icons: {
6235 activeHeader: "ui-icon-triangle-1-s",
6236 header: "ui-icon-triangle-1-e"
6237 },
6238
6239 // callbacks
6240 activate: null,
6241 beforeActivate: null
6242 },
6243
6244 _create: function() {
6245 var self = this,
6246 options = self.options;
6247
6248 self.lastToggle = {};
6249 self.element.addClass( "ui-accordion ui-widget ui-helper-reset" );
6250
6251 self.headers = self.element.find( options.header )
6252 .addClass( "ui-accordion-header ui-helper-reset ui-state-default ui-corner-all" );
6253 self._hoverable( self.headers );
6254 self._focusable( self.headers );
6255 self.headers.find( ":first-child" ).addClass( "ui-accordion-heading" );
6256
6257 self.headers.next()
6258 .addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" );
6259
6260 // don't allow collapsible: false and active: false
6261 if ( !options.collapsible && options.active === false ) {
6262 options.active = 0;
6263 }
6264 // handle negative values
6265 if ( options.active < 0 ) {
6266 options.active += this.headers.length;
6267 }
6268 self.active = self._findActive( options.active )
6269 .addClass( "ui-state-default ui-state-active" )
6270 .toggleClass( "ui-corner-all" )
6271 .toggleClass( "ui-corner-top" );
6272 self.active.next().addClass( "ui-accordion-content-active" );
6273
6274 self._createIcons();
6275 self.refresh();
6276
6277 // ARIA
6278 self.element.attr( "role", "tablist" );
6279
6280 self.headers
6281 .attr( "role", "tab" )
6282 .bind( "keydown.accordion", $.proxy( self, "_keydown" ) )
6283 .next()
6284 .attr( "role", "tabpanel" );
6285
6286 self.headers
6287 .not( self.active )
6288 .attr({
6289 "aria-expanded": "false",
6290 "aria-selected": "false",
6291 tabIndex: -1
6292 })
6293 .next()
6294 .hide();
6295
6296 // make sure at least one header is in the tab order
6297 if ( !self.active.length ) {
6298 self.headers.eq( 0 ).attr( "tabIndex", 0 );
6299 } else {
6300 self.active.attr({
6301 "aria-expanded": "true",
6302 "aria-selected": "true",
6303 tabIndex: 0
6304 });
6305 }
6306
6307 // only need links in tab order for Safari
6308 if ( !$.browser.safari ) {
6309 self.headers.find( "a" ).attr( "tabIndex", -1 );
6310 }
6311
6312 this._setupEvents( options.event );
6313 },
6314
6315 _createIcons: function() {
6316 var icons = this.options.icons;
6317 if ( icons ) {
6318 $( "<span>" )
6319 .addClass( "ui-accordion-header-icon ui-icon " + icons.header )
6320 .prependTo( this.headers );
6321 this.active.children( ".ui-accordion-header-icon" )
6322 .removeClass( icons.header )
6323 .addClass( icons.activeHeader );
6324 this.element.addClass( "ui-accordion-icons" );
6325 }
6326 },
6327
6328 _destroyIcons: function() {
6329 this.headers.children( ".ui-accordion-header-icon" ).remove();
6330 this.element.removeClass( "ui-accordion-icons" );
6331 },
6332
6333 _destroy: function() {
6334 // clean up main element
6335 this.element
6336 .removeClass( "ui-accordion ui-widget ui-helper-reset" )
6337 .removeAttr( "role" );
6338
6339 // clean up headers
6340 this.headers
6341 .unbind( ".accordion" )
6342 .removeClass( "ui-accordion-header ui-accordion-disabled ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top" )
6343 .removeAttr( "role" )
6344 .removeAttr( "aria-expanded" )
6345 .removeAttr( "aria-selected" )
6346 .removeAttr( "tabIndex" )
6347 .find( "a" )
6348 .removeAttr( "tabIndex" )
6349 .end()
6350 .find( ".ui-accordion-heading" )
6351 .removeClass( "ui-accordion-heading" );
6352 this._destroyIcons();
6353
6354 // clean up content panels
6355 var contents = this.headers.next()
6356 .css( "display", "" )
6357 .removeAttr( "role" )
6358 .removeClass( "ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-accordion-disabled ui-state-disabled" );
6359 if ( this.options.heightStyle !== "content" ) {
6360 contents.css( "height", "" );
6361 }
6362 },
6363
6364 _setOption: function( key, value ) {
6365 if ( key === "active" ) {
6366 // _activate() will handle invalid values and update this.options
6367 this._activate( value );
6368 return;
6369 }
6370
6371 if ( key === "event" ) {
6372 if ( this.options.event ) {
6373 this.headers.unbind( this.options.event + ".accordion", this._eventHandler );
6374 }
6375 this._setupEvents( value );
6376 }
6377
6378 this._super( key, value );
6379
6380 // setting collapsible: false while collapsed; open first panel
6381 if ( key === "collapsible" && !value && this.options.active === false ) {
6382 this._activate( 0 );
6383 }
6384
6385 if ( key === "icons" ) {
6386 this._destroyIcons();
6387 if ( value ) {
6388 this._createIcons();
6389 }
6390 }
6391
6392 // #5332 - opacity doesn't cascade to positioned elements in IE
6393 // so we need to add the disabled class to the headers and panels
6394 if ( key === "disabled" ) {
6395 this.headers.add(this.headers.next())
6396 .toggleClass( "ui-accordion-disabled ui-state-disabled", !!value );
6397 }
6398 },
6399
6400 _keydown: function( event ) {
6401 if ( this.options.disabled || event.altKey || event.ctrlKey ) {
6402 return;
6403 }
6404
6405 var keyCode = $.ui.keyCode,
6406 length = this.headers.length,
6407 currentIndex = this.headers.index( event.target ),
6408 toFocus = false;
6409
6410 switch ( event.keyCode ) {
6411 case keyCode.RIGHT:
6412 case keyCode.DOWN:
6413 toFocus = this.headers[ ( currentIndex + 1 ) % length ];
6414 break;
6415 case keyCode.LEFT:
6416 case keyCode.UP:
6417 toFocus = this.headers[ ( currentIndex - 1 + length ) % length ];
6418 break;
6419 case keyCode.SPACE:
6420 case keyCode.ENTER:
6421 this._eventHandler( event );
6422 }
6423
6424 if ( toFocus ) {
6425 $( event.target ).attr( "tabIndex", -1 );
6426 $( toFocus ).attr( "tabIndex", 0 );
6427 toFocus.focus();
6428 event.preventDefault();
6429 }
6430 },
6431
6432 refresh: function() {
6433 var options = this.options,
6434 parent = this.element.parent(),
6435 maxHeight,
6436 overflow;
6437
6438 if ( options.heightStyle === "fill" ) {
6439 // IE 6 treats height like minHeight, so we need to turn off overflow
6440 // in order to get a reliable height
6441 // we use the minHeight support test because we assume that only
6442 // browsers that don't support minHeight will treat height as minHeight
6443 if ( !$.support.minHeight ) {
6444 overflow = parent.css( "overflow" );
6445 parent.css( "overflow", "hidden");
6446 }
6447 maxHeight = parent.height();
6448 this.element.siblings( ":visible" ).each(function() {
6449 var elem = $( this ),
6450 position = elem.css( "position" );
6451
6452 if ( position === "absolute" || position === "fixed" ) {
6453 return;
6454 }
6455 maxHeight -= elem.outerHeight( true );
6456 });
6457 if ( overflow ) {
6458 parent.css( "overflow", overflow );
6459 }
6460
6461 this.headers.each(function() {
6462 maxHeight -= $( this ).outerHeight( true );
6463 });
6464
6465 this.headers.next()
6466 .each(function() {
6467 $( this ).height( Math.max( 0, maxHeight -
6468 $( this ).innerHeight() + $( this ).height() ) );
6469 })
6470 .css( "overflow", "auto" );
6471 } else if ( options.heightStyle === "auto" ) {
6472 maxHeight = 0;
6473 this.headers.next()
6474 .each(function() {
6475 maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() );
6476 })
6477 .height( maxHeight );
6478 }
6479
6480 return this;
6481 },
6482
6483 _activate: function( index ) {
6484 var active = this._findActive( index )[ 0 ];
6485
6486 // trying to activate the already active panel
6487 if ( active === this.active[ 0 ] ) {
6488 return;
6489 }
6490
6491 // trying to collapse, simulate a click on the currently active header
6492 active = active || this.active[ 0 ];
6493
6494 this._eventHandler({
6495 target: active,
6496 currentTarget: active,
6497 preventDefault: $.noop
6498 });
6499 },
6500
6501 _findActive: function( selector ) {
6502 return typeof selector === "number" ? this.headers.eq( selector ) : $();
6503 },
6504
6505 _setupEvents: function( event ) {
6506 if ( event ) {
6507 this.headers.bind( event.split( " " ).join( ".accordion " ) + ".accordion",
6508 $.proxy( this, "_eventHandler" ) );
6509 }
6510 },
6511
6512 _eventHandler: function( event ) {
6513 var options = this.options,
6514 active = this.active,
6515 clicked = $( event.currentTarget ),
6516 clickedIsActive = clicked[ 0 ] === active[ 0 ],
6517 collapsing = clickedIsActive && options.collapsible,
6518 toShow = collapsing ? $() : clicked.next(),
6519 toHide = active.next(),
6520 eventData = {
6521 oldHeader: active,
6522 oldContent: toHide,
6523 newHeader: collapsing ? $() : clicked,
6524 newContent: toShow
6525 };
6526
6527 event.preventDefault();
6528
6529 if ( options.disabled ||
6530 // click on active header, but not collapsible
6531 ( clickedIsActive && !options.collapsible ) ||
6532 // allow canceling activation
6533 ( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
6534 return;
6535 }
6536
6537 options.active = collapsing ? false : this.headers.index( clicked );
6538
6539 // when the call to ._toggle() comes after the class changes
6540 // it causes a very odd bug in IE 8 (see #6720)
6541 this.active = clickedIsActive ? $() : clicked;
6542 this._toggle( eventData );
6543
6544 // switch classes
6545 active
6546 .removeClass( "ui-state-active ui-corner-top" )
6547 .addClass( "ui-state-default ui-corner-all" )
6548 .children( ".ui-accordion-header-icon" )
6549 .removeClass( options.icons.activeHeader )
6550 .addClass( options.icons.header );
6551 if ( !clickedIsActive ) {
6552 clicked
6553 .removeClass( "ui-state-default ui-corner-all" )
6554 .addClass( "ui-state-active ui-corner-top" )
6555 .children( ".ui-accordion-header-icon" )
6556 .removeClass( options.icons.header )
6557 .addClass( options.icons.activeHeader );
6558 clicked
6559 .next()
6560 .addClass( "ui-accordion-content-active" );
6561 }
6562 },
6563
6564 _toggle: function( data ) {
6565 var self = this,
6566 options = self.options,
6567 toShow = data.newContent,
6568 toHide = data.oldContent;
6569
6570 function complete() {
6571 self._completed( data );
6572 }
6573
6574 if ( options.animated ) {
6575 var animations = $.ui.accordion.animations,
6576 animation = options.animated,
6577 additional;
6578
6579 if ( !animations[ animation ] ) {
6580 additional = {
6581 easing: $.easing[ animation ] ? animation : "slide",
6582 duration: 700
6583 };
6584 animation = "slide";
6585 }
6586
6587 animations[ animation ]({
6588 widget: self,
6589 toShow: toShow,
6590 toHide: toHide,
6591 prevShow: self.lastToggle.toShow,
6592 prevHide: self.lastToggle.toHide,
6593 complete: complete,
6594 down: toShow.length && ( !toHide.length || ( toShow.index() < toHide.index() ) )
6595 }, additional );
6596 } else {
6597 toHide.hide();
6598 toShow.show();
6599 complete();
6600 }
6601
6602 // TODO assert that the blur and focus triggers are really necessary, remove otherwise
6603 toHide.prev()
6604 .attr({
6605 "aria-expanded": "false",
6606 "aria-selected": "false",
6607 tabIndex: -1
6608 })
6609 .blur();
6610 toShow.prev()
6611 .attr({
6612 "aria-expanded": "true",
6613 "aria-selected": "true",
6614 tabIndex: 0
6615 })
6616 .focus();
6617 },
6618
6619 _completed: function( data ) {
6620 var toShow = data.newContent,
6621 toHide = data.oldContent;
6622
6623 if ( this.options.heightStyle === "content" ) {
6624 toShow.add( toHide ).css({
6625 height: "",
6626 overflow: ""
6627 });
6628 }
6629
6630 // other classes are removed before the animation; this one needs to stay until completed
6631 toHide.removeClass( "ui-accordion-content-active" );
6632 // Work around for rendering bug in IE (#5421)
6633 if ( toHide.length ) {
6634 toHide.parent()[0].className = toHide.parent()[0].className;
6635 }
6636
6637 this._trigger( "activate", null, data );
6638 }
6639 });
6640
6641 $.extend( $.ui.accordion, {
6642 animations: {
6643 slide: function( options, additions ) {
6644 if ( options.prevShow || options.prevHide ) {
6645 options.prevHide.stop( true, true );
6646 options.toHide = options.prevShow;
6647 }
6648
6649 var showOverflow = options.toShow.css( "overflow" ),
6650 hideOverflow = options.toHide.css( "overflow" ),
6651 percentDone = 0,
6652 showProps = {},
6653 hideProps = {},
6654 fxAttrs = [ "height", "paddingTop", "paddingBottom" ],
6655 originalWidth;
6656 options = $.extend({
6657 easing: "swing",
6658 duration: 300
6659 }, options, additions );
6660
6661 options.widget.lastToggle = options;
6662
6663 if ( !options.toHide.size() ) {
6664 originalWidth = options.toShow[0].style.width;
6665 options.toShow
6666 .show()
6667 .width( options.toShow.width() )
6668 .hide()
6669 .animate({
6670 height: "show",
6671 paddingTop: "show",
6672 paddingBottom: "show"
6673 }, {
6674 duration: options.duration,
6675 easing: options.easing,
6676 complete: function() {
6677 options.toShow.width( originalWidth );
6678 options.complete();
6679 }
6680 });
6681 return;
6682 }
6683 if ( !options.toShow.size() ) {
6684 options.toHide.animate({
6685 height: "hide",
6686 paddingTop: "hide",
6687 paddingBottom: "hide"
6688 }, options );
6689 return;
6690 }
6691 // fix width before calculating height of hidden element
6692 var s = options.toShow;
6693 originalWidth = s[0].style.width;
6694 s.width( s.parent().width()
6695 - parseFloat( s.css( "paddingLeft" ) )
6696 - parseFloat( s.css( "paddingRight" ) )
6697 - ( parseFloat( s.css( "borderLeftWidth" ) ) || 0 )
6698 - ( parseFloat( s.css( "borderRightWidth" ) ) || 0 ) );
6699
6700 $.each( fxAttrs, function( i, prop ) {
6701 hideProps[ prop ] = "hide";
6702
6703 var parts = ( "" + $.css( options.toShow[0], prop ) ).match( /^([\d+-.]+)(.*)$/ ),
6704 // work around bug when a panel has no height - #7335
6705 propVal = prop === "height" && parts[ 1 ] === "0" ? 1 : parts[ 1 ];
6706 showProps[ prop ] = {
6707 value: propVal,
6708 unit: parts[ 2 ] || "px"
6709 };
6710 });
6711 options.toShow.css({ height: 0, overflow: "hidden" }).show();
6712 options.toHide
6713 .filter( ":hidden" )
6714 .each( options.complete )
6715 .end()
6716 .filter( ":visible" )
6717 .animate( hideProps, {
6718 step: function( now, settings ) {
6719 if ( settings.prop == "height" || settings.prop == "paddingTop" || settings.prop == "paddingBottom" ) {
6720 percentDone = ( settings.end - settings.start === 0 ) ? 0 :
6721 ( settings.now - settings.start ) / ( settings.end - settings.start );
6722 }
6723
6724 options.toShow[ 0 ].style[ settings.prop ] =
6725 ( percentDone * showProps[ settings.prop ].value )
6726 + showProps[ settings.prop ].unit;
6727 },
6728 duration: options.duration,
6729 easing: options.easing,
6730 complete: function() {
6731 options.toShow.css({
6732 width: originalWidth,
6733 overflow: showOverflow
6734 });
6735 options.toHide.css( "overflow", hideOverflow );
6736 options.complete();
6737 }
6738 });
6739 },
6740 bounceslide: function( options ) {
6741 this.slide( options, {
6742 easing: options.down ? "easeOutBounce" : "swing",
6743 duration: options.down ? 1000 : 200
6744 });
6745 }
6746 }
6747 });
6748
6749
6750
6751 // DEPRECATED
6752 if ( $.uiBackCompat !== false ) {
6753 // navigation options
6754 (function( $, prototype ) {
6755 $.extend( prototype.options, {
6756 navigation: false,
6757 navigationFilter: function() {
6758 return this.href.toLowerCase() === location.href.toLowerCase();
6759 }
6760 });
6761
6762 var _create = prototype._create;
6763 prototype._create = function() {
6764 if ( this.options.navigation ) {
6765 var self = this,
6766 headers = this.element.find( this.options.header ),
6767 content = headers.next(),
6768 current = headers.add( content )
6769 .find( "a" )
6770 .filter( this.options.navigationFilter )
6771 [ 0 ];
6772 if ( current ) {
6773 headers.add( content ).each( function( index ) {
6774 if ( $.contains( this, current ) ) {
6775 self.options.active = Math.floor( index / 2 );
6776 return false;
6777 }
6778 });
6779 }
6780 }
6781 _create.call( this );
6782 };
6783 }( jQuery, jQuery.ui.accordion.prototype ) );
6784
6785 // height options
6786 (function( $, prototype ) {
6787 $.extend( prototype.options, {
6788 heightStyle: null, // remove default so we fall back to old values
6789 autoHeight: true, // use heightStyle: "auto"
6790 clearStyle: false, // use heightStyle: "content"
6791 fillSpace: false // use heightStyle: "fill"
6792 });
6793
6794 var _create = prototype._create,
6795 _setOption = prototype._setOption;
6796
6797 $.extend( prototype, {
6798 _create: function() {
6799 this.options.heightStyle = this.options.heightStyle ||
6800 this._mergeHeightStyle();
6801
6802 _create.call( this );
6803 },
6804
6805 _setOption: function( key, value ) {
6806 if ( key === "autoHeight" || key === "clearStyle" || key === "fillSpace" ) {
6807 this.options.heightStyle = this._mergeHeightStyle();
6808 }
6809 _setOption.apply( this, arguments );
6810 },
6811
6812 _mergeHeightStyle: function() {
6813 var options = this.options;
6814
6815 if ( options.fillSpace ) {
6816 return "fill";
6817 }
6818
6819 if ( options.clearStyle ) {
6820 return "content";
6821 }
6822
6823 if ( options.autoHeight ) {
6824 return "auto";
6825 }
6826 }
6827 });
6828 }( jQuery, jQuery.ui.accordion.prototype ) );
6829
6830 // icon options
6831 (function( $, prototype ) {
6832 $.extend( prototype.options.icons, {
6833 activeHeader: null, // remove default so we fall back to old values
6834 headerSelected: "ui-icon-triangle-1-s"
6835 });
6836
6837 var _createIcons = prototype._createIcons;
6838 prototype._createIcons = function() {
6839 if ( this.options.icons ) {
6840 this.options.icons.activeHeader = this.options.icons.activeHeader ||
6841 this.options.icons.headerSelected;
6842 }
6843 _createIcons.call( this );
6844 };
6845 }( jQuery, jQuery.ui.accordion.prototype ) );
6846
6847 // expanded active option, activate method
6848 (function( $, prototype ) {
6849 prototype.activate = prototype._activate;
6850
6851 var _findActive = prototype._findActive;
6852 prototype._findActive = function( index ) {
6853 if ( index === -1 ) {
6854 index = false;
6855 }
6856 if ( index && typeof index !== "number" ) {
6857 index = this.headers.index( this.headers.filter( index ) );
6858 if ( index === -1 ) {
6859 index = false;
6860 }
6861 }
6862 return _findActive.call( this, index );
6863 };
6864 }( jQuery, jQuery.ui.accordion.prototype ) );
6865
6866 // resize method
6867 jQuery.ui.accordion.prototype.resize = jQuery.ui.accordion.prototype.refresh;
6868
6869 // change events
6870 (function( $, prototype ) {
6871 $.extend( prototype.options, {
6872 change: null,
6873 changestart: null
6874 });
6875
6876 var _trigger = prototype._trigger;
6877 prototype._trigger = function( type, event, data ) {
6878 var ret = _trigger.apply( this, arguments );
6879 if ( !ret ) {
6880 return false;
6881 }
6882
6883 if ( type === "beforeActivate" ) {
6884 ret = _trigger.call( this, "changestart", event, data );
6885 } else if ( type === "activate" ) {
6886 ret = _trigger.call( this, "change", event, data );
6887 }
6888 return ret;
6889 };
6890 }( jQuery, jQuery.ui.accordion.prototype ) );
6891 }
6892
6893 })( jQuery );
6894 /*
6895 * jQuery UI Autocomplete @VERSION
6896 *
6897 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
6898 * Dual licensed under the MIT or GPL Version 2 licenses.
6899 * http://jquery.org/license
6900 *
6901 * http://docs.jquery.com/UI/Autocomplete
6902 *
6903 * Depends:
6904 * jquery.ui.core.js
6905 * jquery.ui.widget.js
6906 * jquery.ui.position.js
6907 * jquery.ui.menu.js
6908 */
6909 (function( $, undefined ) {
6910
6911 // used to prevent race conditions with remote data sources
6912 var requestIndex = 0;
6913
6914 $.widget( "ui.autocomplete", {
6915 version: "@VERSION",
6916 defaultElement: "<input>",
6917 options: {
6918 appendTo: "body",
6919 autoFocus: false,
6920 delay: 300,
6921 minLength: 1,
6922 position: {
6923 my: "left top",
6924 at: "left bottom",
6925 collision: "none"
6926 },
6927 source: null,
6928
6929 // callbacks
6930 change: null,
6931 close: null,
6932 focus: null,
6933 open: null,
6934 response: null,
6935 search: null,
6936 select: null
6937 },
6938
6939 pending: 0,
6940
6941 _create: function() {
6942 var self = this,
6943 // Some browsers only repeat keydown events, not keypress events,
6944 // so we use the suppressKeyPress flag to determine if we've already
6945 // handled the keydown event. #7269
6946 // Unfortunately the code for & in keypress is the same as the up arrow,
6947 // so we use the suppressKeyPressRepeat flag to avoid handling keypress
6948 // events when we know the keydown event was used to modify the
6949 // search term. #7799
6950 suppressKeyPress,
6951 suppressKeyPressRepeat,
6952 suppressInput;
6953
6954 this.isMultiLine = this.element.is( "textarea,[contenteditable]" );
6955 this.valueMethod = this.element[ this.element.is( "input,textarea" ) ? "val" : "text" ];
6956
6957 this.element
6958 .addClass( "ui-autocomplete-input" )
6959 .attr( "autocomplete", "off" )
6960 // TODO verify these actually work as intended
6961 .attr({
6962 role: "textbox",
6963 "aria-autocomplete": "list",
6964 "aria-haspopup": "true"
6965 })
6966 .bind( "keydown.autocomplete", function( event ) {
6967 if ( self.options.disabled || self.element.prop( "readOnly" ) ) {
6968 suppressKeyPress = true;
6969 suppressInput = true;
6970 suppressKeyPressRepeat = true;
6971 return;
6972 }
6973
6974 suppressKeyPress = false;
6975 suppressInput = false;
6976 suppressKeyPressRepeat = false;
6977 var keyCode = $.ui.keyCode;
6978 switch( event.keyCode ) {
6979 case keyCode.PAGE_UP:
6980 suppressKeyPress = true;
6981 self._move( "previousPage", event );
6982 break;
6983 case keyCode.PAGE_DOWN:
6984 suppressKeyPress = true;
6985 self._move( "nextPage", event );
6986 break;
6987 case keyCode.UP:
6988 suppressKeyPress = true;
6989 self._keyEvent( "previous", event );
6990 break;
6991 case keyCode.DOWN:
6992 suppressKeyPress = true;
6993 self._keyEvent( "next", event );
6994 break;
6995 case keyCode.ENTER:
6996 case keyCode.NUMPAD_ENTER:
6997 // when menu is open and has focus
6998 if ( self.menu.active ) {
6999 // #6055 - Opera still allows the keypress to occur
7000 // which causes forms to submit
7001 suppressKeyPress = true;
7002 event.preventDefault();
7003 }
7004 //passthrough - ENTER and TAB both select the current element
7005 case keyCode.TAB:
7006 if ( !self.menu.active ) {
7007 return;
7008 }
7009 self.menu.select( event );
7010 break;
7011 case keyCode.ESCAPE:
7012 if ( self.menu.element.is(":visible") ) {
7013 self._value( self.term );
7014 self.close( event );
7015 }
7016 break;
7017 default:
7018 suppressKeyPressRepeat = true;
7019 // search timeout should be triggered before the input value is changed
7020 self._searchTimeout( event );
7021 break;
7022 }
7023 })
7024 .bind( "keypress.autocomplete", function( event ) {
7025 if ( suppressKeyPress ) {
7026 suppressKeyPress = false;
7027 event.preventDefault();
7028 return;
7029 }
7030 if ( suppressKeyPressRepeat ) {
7031 return;
7032 }
7033
7034 // replicate some key handlers to allow them to repeat in Firefox and Opera
7035 var keyCode = $.ui.keyCode;
7036 switch( event.keyCode ) {
7037 case keyCode.PAGE_UP:
7038 self._move( "previousPage", event );
7039 break;
7040 case keyCode.PAGE_DOWN:
7041 self._move( "nextPage", event );
7042 break;
7043 case keyCode.UP:
7044 self._keyEvent( "previous", event );
7045 break;
7046 case keyCode.DOWN:
7047 self._keyEvent( "next", event );
7048 break;
7049 }
7050 })
7051 .bind( "input.autocomplete", function(event) {
7052 if ( suppressInput ) {
7053 suppressInput = false;
7054 event.preventDefault();
7055 return;
7056 }
7057 self._searchTimeout( event );
7058 })
7059 .bind( "focus.autocomplete", function() {
7060 if ( self.options.disabled ) {
7061 return;
7062 }
7063
7064 self.selectedItem = null;
7065 self.previous = self._value();
7066 })
7067 .bind( "blur.autocomplete", function( event ) {
7068 if ( self.options.disabled ) {
7069 return;
7070 }
7071
7072 clearTimeout( self.searching );
7073 self.cancelSearch = true;
7074 // clicks on the menu (or a button to trigger a search) will cause a blur event
7075 self.closing = setTimeout(function() {
7076 self.close( event );
7077 self._change( event );
7078 }, 150 );
7079 });
7080 this._initSource();
7081 this.response = function() {
7082 return self._response.apply( self, arguments );
7083 };
7084 this.menu = $( "<ul></ul>" )
7085 .addClass( "ui-autocomplete" )
7086 .appendTo( this.document.find( this.options.appendTo || "body" )[0] )
7087 // prevent the close-on-blur in case of a "slow" click on the menu (long mousedown)
7088 .mousedown(function( event ) {
7089 // clicking on the scrollbar causes focus to shift to the body
7090 // but we can't detect a mouseup or a click immediately afterward
7091 // so we have to track the next mousedown and close the menu if
7092 // the user clicks somewhere outside of the autocomplete
7093 var menuElement = self.menu.element[ 0 ];
7094 if ( !$( event.target ).closest( ".ui-menu-item" ).length ) {
7095 setTimeout(function() {
7096 self.document.one( 'mousedown', function( event ) {
7097 if ( event.target !== self.element[ 0 ] &&
7098 event.target !== menuElement &&
7099 !$.contains( menuElement, event.target ) ) {
7100 self.close();
7101 }
7102 });
7103 }, 1 );
7104 }
7105
7106 // use another timeout to make sure the blur-event-handler on the input was already triggered
7107 setTimeout(function() {
7108 clearTimeout( self.closing );
7109 }, 13);
7110 })
7111 .menu({
7112 // custom key handling for now
7113 input: $(),
7114 focus: function( event, ui ) {
7115 var item = ui.item.data( "item.autocomplete" );
7116 if ( false !== self._trigger( "focus", event, { item: item } ) ) {
7117 // use value to match what will end up in the input, if it was a key event
7118 if ( /^key/.test(event.originalEvent.type) ) {
7119 self._value( item.value );
7120 }
7121 }
7122 },
7123 select: function( event, ui ) {
7124 var item = ui.item.data( "item.autocomplete" ),
7125 previous = self.previous;
7126
7127 // only trigger when focus was lost (click on menu)
7128 if ( self.element[0] !== self.document[0].activeElement ) {
7129 self.element.focus();
7130 self.previous = previous;
7131 // #6109 - IE triggers two focus events and the second
7132 // is asynchronous, so we need to reset the previous
7133 // term synchronously and asynchronously :-(
7134 setTimeout(function() {
7135 self.previous = previous;
7136 self.selectedItem = item;
7137 }, 1);
7138 }
7139
7140 if ( false !== self._trigger( "select", event, { item: item } ) ) {
7141 self._value( item.value );
7142 }
7143 // reset the term after the select event
7144 // this allows custom select handling to work properly
7145 self.term = self._value();
7146
7147 self.close( event );
7148 self.selectedItem = item;
7149 }
7150 })
7151 .zIndex( this.element.zIndex() + 1 )
7152 .hide()
7153 .data( "menu" );
7154
7155 if ( $.fn.bgiframe ) {
7156 this.menu.element.bgiframe();
7157 }
7158
7159 // turning off autocomplete prevents the browser from remembering the
7160 // value when navigating through history, so we re-enable autocomplete
7161 // if the page is unloaded before the widget is destroyed. #7790
7162 this._bind( this.window, {
7163 beforeunload: function() {
7164 this.element.removeAttr( "autocomplete" );
7165 }
7166 });
7167 },
7168
7169 _destroy: function() {
7170 clearTimeout( this.searching );
7171 this.element
7172 .removeClass( "ui-autocomplete-input" )
7173 .removeAttr( "autocomplete" )
7174 .removeAttr( "role" )
7175 .removeAttr( "aria-autocomplete" )
7176 .removeAttr( "aria-haspopup" );
7177 this.menu.element.remove();
7178 },
7179
7180 _setOption: function( key, value ) {
7181 this._super( key, value );
7182 if ( key === "source" ) {
7183 this._initSource();
7184 }
7185 if ( key === "appendTo" ) {
7186 this.menu.element.appendTo( this.document.find( value || "body" )[0] );
7187 }
7188 if ( key === "disabled" && value && this.xhr ) {
7189 this.xhr.abort();
7190 }
7191 },
7192
7193 _initSource: function() {
7194 var self = this,
7195 array,
7196 url;
7197 if ( $.isArray(this.options.source) ) {
7198 array = this.options.source;
7199 this.source = function( request, response ) {
7200 response( $.ui.autocomplete.filter(array, request.term) );
7201 };
7202 } else if ( typeof this.options.source === "string" ) {
7203 url = this.options.source;
7204 this.source = function( request, response ) {
7205 if ( self.xhr ) {
7206 self.xhr.abort();
7207 }
7208 self.xhr = $.ajax({
7209 url: url,
7210 data: request,
7211 dataType: "json",
7212 autocompleteRequest: ++requestIndex,
7213 success: function( data, status ) {
7214 if ( this.autocompleteRequest === requestIndex ) {
7215 response( data );
7216 }
7217 },
7218 error: function() {
7219 if ( this.autocompleteRequest === requestIndex ) {
7220 response( [] );
7221 }
7222 }
7223 });
7224 };
7225 } else {
7226 this.source = this.options.source;
7227 }
7228 },
7229
7230 _searchTimeout: function( event ) {
7231 var self = this;
7232 clearTimeout( self.searching );
7233 self.searching = setTimeout(function() {
7234 // only search if the value has changed
7235 if ( self.term !== self._value() ) {
7236 self.selectedItem = null;
7237 self.search( null, event );
7238 }
7239 }, self.options.delay );
7240 },
7241
7242 search: function( value, event ) {
7243 value = value != null ? value : this._value();
7244
7245 // always save the actual value, not the one passed as an argument
7246 this.term = this._value();
7247
7248 if ( value.length < this.options.minLength ) {
7249 return this.close( event );
7250 }
7251
7252 clearTimeout( this.closing );
7253 if ( this._trigger( "search", event ) === false ) {
7254 return;
7255 }
7256
7257 return this._search( value );
7258 },
7259
7260 _search: function( value ) {
7261 this.pending++;
7262 this.element.addClass( "ui-autocomplete-loading" );
7263 this.cancelSearch = false;
7264
7265 this.source( { term: value }, this.response );
7266 },
7267
7268 _response: function( content ) {
7269 if ( content ) {
7270 content = this._normalize( content );
7271 }
7272 this._trigger( "response", null, { content: content } );
7273 if ( !this.options.disabled && content && content.length && !this.cancelSearch ) {
7274 this._suggest( content );
7275 this._trigger( "open" );
7276 } else {
7277 this.close();
7278 }
7279 this.pending--;
7280 if ( !this.pending ) {
7281 this.element.removeClass( "ui-autocomplete-loading" );
7282 }
7283 },
7284
7285 close: function( event ) {
7286 clearTimeout( this.closing );
7287 if ( this.menu.element.is(":visible") ) {
7288 this.menu.element.hide();
7289 this.menu.blur();
7290 this._trigger( "close", event );
7291 }
7292 },
7293
7294 _change: function( event ) {
7295 if ( this.previous !== this._value() ) {
7296 this._trigger( "change", event, { item: this.selectedItem } );
7297 }
7298 },
7299
7300 _normalize: function( items ) {
7301 // assume all items have the right format when the first item is complete
7302 if ( items.length && items[0].label && items[0].value ) {
7303 return items;
7304 }
7305 return $.map( items, function(item) {
7306 if ( typeof item === "string" ) {
7307 return {
7308 label: item,
7309 value: item
7310 };
7311 }
7312 return $.extend({
7313 label: item.label || item.value,
7314 value: item.value || item.label
7315 }, item );
7316 });
7317 },
7318
7319 _suggest: function( items ) {
7320 var ul = this.menu.element
7321 .empty()
7322 .zIndex( this.element.zIndex() + 1 );
7323 this._renderMenu( ul, items );
7324 // TODO refresh should check if the active item is still in the dom, removing the need for a manual blur
7325 this.menu.blur();
7326 this.menu.refresh();
7327
7328 // size and position menu
7329 ul.show();
7330 this._resizeMenu();
7331 ul.position( $.extend({
7332 of: this.element
7333 }, this.options.position ));
7334
7335 if ( this.options.autoFocus ) {
7336 this.menu.next( new $.Event("mouseover") );
7337 }
7338 },
7339
7340 _resizeMenu: function() {
7341 var ul = this.menu.element;
7342 ul.outerWidth( Math.max(
7343 // Firefox wraps long text (possibly a rounding bug)
7344 // so we add 1px to avoid the wrapping (#7513)
7345 ul.width( "" ).outerWidth() + 1,
7346 this.element.outerWidth()
7347 ) );
7348 },
7349
7350 _renderMenu: function( ul, items ) {
7351 var self = this;
7352 $.each( items, function( index, item ) {
7353 self._renderItem( ul, item );
7354 });
7355 },
7356
7357 _renderItem: function( ul, item) {
7358 return $( "<li></li>" )
7359 .data( "item.autocomplete", item )
7360 .append( $( "<a></a>" ).text( item.label ) )
7361 .appendTo( ul );
7362 },
7363
7364 _move: function( direction, event ) {
7365 if ( !this.menu.element.is(":visible") ) {
7366 this.search( null, event );
7367 return;
7368 }
7369 if ( this.menu.isFirstItem() && /^previous/.test(direction) ||
7370 this.menu.isLastItem() && /^next/.test(direction) ) {
7371 this._value( this.term );
7372 this.menu.blur();
7373 return;
7374 }
7375 this.menu[ direction ]( event );
7376 },
7377
7378 widget: function() {
7379 return this.menu.element;
7380 },
7381
7382 _value: function( value ) {
7383 return this.valueMethod.apply( this.element, arguments );
7384 },
7385
7386 _keyEvent: function( keyEvent, event ) {
7387 if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
7388 this._move( keyEvent, event );
7389
7390 // prevents moving cursor to beginning/end of the text field in some browsers
7391 event.preventDefault();
7392 }
7393 }
7394 });
7395
7396 $.extend( $.ui.autocomplete, {
7397 escapeRegex: function( value ) {
7398 return value.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
7399 },
7400 filter: function(array, term) {
7401 var matcher = new RegExp( $.ui.autocomplete.escapeRegex(term), "i" );
7402 return $.grep( array, function(value) {
7403 return matcher.test( value.label || value.value || value );
7404 });
7405 }
7406 });
7407
7408 }( jQuery ));
7409 /*
7410 * jQuery UI Button @VERSION
7411 *
7412 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
7413 * Dual licensed under the MIT or GPL Version 2 licenses.
7414 * http://jquery.org/license
7415 *
7416 * http://docs.jquery.com/UI/Button
7417 *
7418 * Depends:
7419 * jquery.ui.core.js
7420 * jquery.ui.widget.js
7421 */
7422 (function( $, undefined ) {
7423
7424 var lastActive, startXPos, startYPos, clickDragged,
7425 baseClasses = "ui-button ui-widget ui-state-default ui-corner-all",
7426 stateClasses = "ui-state-hover ui-state-active ",
7427 typeClasses = "ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only",
7428 formResetHandler = function() {
7429 var buttons = $( this ).find( ":ui-button" );
7430 setTimeout(function() {
7431 buttons.button( "refresh" );
7432 }, 1 );
7433 },
7434 radioGroup = function( radio ) {
7435 var name = radio.name,
7436 form = radio.form,
7437 radios = $( [] );
7438 if ( name ) {
7439 if ( form ) {
7440 radios = $( form ).find( "[name='" + name + "']" );
7441 } else {
7442 radios = $( "[name='" + name + "']", radio.ownerDocument )
7443 .filter(function() {
7444 return !this.form;
7445 });
7446 }
7447 }
7448 return radios;
7449 };
7450
7451 $.widget( "ui.button", {
7452 version: "@VERSION",
7453 defaultElement: "<button>",
7454 options: {
7455 disabled: null,
7456 text: true,
7457 label: null,
7458 icons: {
7459 primary: null,
7460 secondary: null
7461 }
7462 },
7463 _create: function() {
7464 this.element.closest( "form" )
7465 .unbind( "reset.button" )
7466 .bind( "reset.button", formResetHandler );
7467
7468 if ( typeof this.options.disabled !== "boolean" ) {
7469 this.options.disabled = this.element.prop( "disabled" );
7470 }
7471
7472 this._determineButtonType();
7473 this.hasTitle = !!this.buttonElement.attr( "title" );
7474
7475 var self = this,
7476 options = this.options,
7477 toggleButton = this.type === "checkbox" || this.type === "radio",
7478 hoverClass = "ui-state-hover" + ( !toggleButton ? " ui-state-active" : "" ),
7479 focusClass = "ui-state-focus";
7480
7481 if ( options.label === null ) {
7482 options.label = this.buttonElement.html();
7483 }
7484
7485 if ( this.element.is( ":disabled" ) ) {
7486 options.disabled = true;
7487 }
7488
7489 this.buttonElement
7490 .addClass( baseClasses )
7491 .attr( "role", "button" )
7492 .bind( "mouseenter.button", function() {
7493 if ( options.disabled ) {
7494 return;
7495 }
7496 $( this ).addClass( "ui-state-hover" );
7497 if ( this === lastActive ) {
7498 $( this ).addClass( "ui-state-active" );
7499 }
7500 })
7501 .bind( "mouseleave.button", function() {
7502 if ( options.disabled ) {
7503 return;
7504 }
7505 $( this ).removeClass( hoverClass );
7506 })
7507 .bind( "click.button", function( event ) {
7508 if ( options.disabled ) {
7509 event.preventDefault();
7510 event.stopImmediatePropagation();
7511 }
7512 });
7513
7514 this.element
7515 .bind( "focus.button", function() {
7516 // no need to check disabled, focus won't be triggered anyway
7517 self.buttonElement.addClass( focusClass );
7518 })
7519 .bind( "blur.button", function() {
7520 self.buttonElement.removeClass( focusClass );
7521 });
7522
7523 if ( toggleButton ) {
7524 this.element.bind( "change.button", function() {
7525 if ( clickDragged ) {
7526 return;
7527 }
7528 self.refresh();
7529 });
7530 // if mouse moves between mousedown and mouseup (drag) set clickDragged flag
7531 // prevents issue where button state changes but checkbox/radio checked state
7532 // does not in Firefox (see ticket #6970)
7533 this.buttonElement
7534 .bind( "mousedown.button", function( event ) {
7535 if ( options.disabled ) {
7536 return;
7537 }
7538 clickDragged = false;
7539 startXPos = event.pageX;
7540 startYPos = event.pageY;
7541 })
7542 .bind( "mouseup.button", function( event ) {
7543 if ( options.disabled ) {
7544 return;
7545 }
7546 if ( startXPos !== event.pageX || startYPos !== event.pageY ) {
7547 clickDragged = true;
7548 }
7549 });
7550 }
7551
7552 if ( this.type === "checkbox" ) {
7553 this.buttonElement.bind( "click.button", function() {
7554 if ( options.disabled || clickDragged ) {
7555 return false;
7556 }
7557 $( this ).toggleClass( "ui-state-active" );
7558 self.buttonElement.attr( "aria-pressed", self.element[0].checked );
7559 });
7560 } else if ( this.type === "radio" ) {
7561 this.buttonElement.bind( "click.button", function() {
7562 if ( options.disabled || clickDragged ) {
7563 return false;
7564 }
7565 $( this ).addClass( "ui-state-active" );
7566 self.buttonElement.attr( "aria-pressed", "true" );
7567
7568 var radio = self.element[ 0 ];
7569 radioGroup( radio )
7570 .not( radio )
7571 .map(function() {
7572 return $( this ).button( "widget" )[ 0 ];
7573 })
7574 .removeClass( "ui-state-active" )
7575 .attr( "aria-pressed", "false" );
7576 });
7577 } else {
7578 this.buttonElement
7579 .bind( "mousedown.button", function() {
7580 if ( options.disabled ) {
7581 return false;
7582 }
7583 $( this ).addClass( "ui-state-active" );
7584 lastActive = this;
7585 self.document.one( "mouseup", function() {
7586 lastActive = null;
7587 });
7588 })
7589 .bind( "mouseup.button", function() {
7590 if ( options.disabled ) {
7591 return false;
7592 }
7593 $( this ).removeClass( "ui-state-active" );
7594 })
7595 .bind( "keydown.button", function(event) {
7596 if ( options.disabled ) {
7597 return false;
7598 }
7599 if ( event.keyCode == $.ui.keyCode.SPACE || event.keyCode == $.ui.keyCode.ENTER ) {
7600 $( this ).addClass( "ui-state-active" );
7601 }
7602 })
7603 .bind( "keyup.button", function() {
7604 $( this ).removeClass( "ui-state-active" );
7605 });
7606
7607 if ( this.buttonElement.is("a") ) {
7608 this.buttonElement.keyup(function(event) {
7609 if ( event.keyCode === $.ui.keyCode.SPACE ) {
7610 // TODO pass through original event correctly (just as 2nd argument doesn't work)
7611 $( this ).click();
7612 }
7613 });
7614 }
7615 }
7616
7617 // TODO: pull out $.Widget's handling for the disabled option into
7618 // $.Widget.prototype._setOptionDisabled so it's easy to proxy and can
7619 // be overridden by individual plugins
7620 this._setOption( "disabled", options.disabled );
7621 this._resetButton();
7622 },
7623
7624 _determineButtonType: function() {
7625
7626 if ( this.element.is(":checkbox") ) {
7627 this.type = "checkbox";
7628 } else if ( this.element.is(":radio") ) {
7629 this.type = "radio";
7630 } else if ( this.element.is("input") ) {
7631 this.type = "input";
7632 } else {
7633 this.type = "button";
7634 }
7635
7636 if ( this.type === "checkbox" || this.type === "radio" ) {
7637 // we don't search against the document in case the element
7638 // is disconnected from the DOM
7639 var ancestor = this.element.parents().last(),
7640 labelSelector = "label[for='" + this.element.attr("id") + "']";
7641 this.buttonElement = ancestor.find( labelSelector );
7642 if ( !this.buttonElement.length ) {
7643 ancestor = ancestor.length ? ancestor.siblings() : this.element.siblings();
7644 this.buttonElement = ancestor.filter( labelSelector );
7645 if ( !this.buttonElement.length ) {
7646 this.buttonElement = ancestor.find( labelSelector );
7647 }
7648 }
7649 this.element.addClass( "ui-helper-hidden-accessible" );
7650
7651 var checked = this.element.is( ":checked" );
7652 if ( checked ) {
7653 this.buttonElement.addClass( "ui-state-active" );
7654 }
7655 this.buttonElement.prop( "aria-pressed", checked );
7656 } else {
7657 this.buttonElement = this.element;
7658 }
7659 },
7660
7661 widget: function() {
7662 return this.buttonElement;
7663 },
7664
7665 _destroy: function() {
7666 this.element
7667 .removeClass( "ui-helper-hidden-accessible" );
7668 this.buttonElement
7669 .removeClass( baseClasses + " " + stateClasses + " " + typeClasses )
7670 .removeAttr( "role" )
7671 .removeAttr( "aria-pressed" )
7672 .html( this.buttonElement.find(".ui-button-text").html() );
7673
7674 if ( !this.hasTitle ) {
7675 this.buttonElement.removeAttr( "title" );
7676 }
7677 },
7678
7679 _setOption: function( key, value ) {
7680 this._super( key, value );
7681 if ( key === "disabled" ) {
7682 if ( value ) {
7683 this.element.prop( "disabled", true );
7684 } else {
7685 this.element.prop( "disabled", false );
7686 }
7687 return;
7688 }
7689 this._resetButton();
7690 },
7691
7692 refresh: function() {
7693 var isDisabled = this.element.is( ":disabled" );
7694 if ( isDisabled !== this.options.disabled ) {
7695 this._setOption( "disabled", isDisabled );
7696 }
7697 if ( this.type === "radio" ) {
7698 radioGroup( this.element[0] ).each(function() {
7699 if ( $( this ).is( ":checked" ) ) {
7700 $( this ).button( "widget" )
7701 .addClass( "ui-state-active" )
7702 .attr( "aria-pressed", "true" );
7703 } else {
7704 $( this ).button( "widget" )
7705 .removeClass( "ui-state-active" )
7706 .attr( "aria-pressed", "false" );
7707 }
7708 });
7709 } else if ( this.type === "checkbox" ) {
7710 if ( this.element.is( ":checked" ) ) {
7711 this.buttonElement
7712 .addClass( "ui-state-active" )
7713 .attr( "aria-pressed", "true" );
7714 } else {
7715 this.buttonElement
7716 .removeClass( "ui-state-active" )
7717 .attr( "aria-pressed", "false" );
7718 }
7719 }
7720 },
7721
7722 _resetButton: function() {
7723 if ( this.type === "input" ) {
7724 if ( this.options.label ) {
7725 this.element.val( this.options.label );
7726 }
7727 return;
7728 }
7729 var buttonElement = this.buttonElement.removeClass( typeClasses ),
7730 buttonText = $( "<span></span>", this.document[0] )
7731 .addClass( "ui-button-text" )
7732 .html( this.options.label )
7733 .appendTo( buttonElement.empty() )
7734 .text(),
7735 icons = this.options.icons,
7736 multipleIcons = icons.primary && icons.secondary,
7737 buttonClasses = [];
7738
7739 if ( icons.primary || icons.secondary ) {
7740 if ( this.options.text ) {
7741 buttonClasses.push( "ui-button-text-icon" + ( multipleIcons ? "s" : ( icons.primary ? "-primary" : "-secondary" ) ) );
7742 }
7743
7744 if ( icons.primary ) {
7745 buttonElement.prepend( "<span class='ui-button-icon-primary ui-icon " + icons.primary + "'></span>" );
7746 }
7747
7748 if ( icons.secondary ) {
7749 buttonElement.append( "<span class='ui-button-icon-secondary ui-icon " + icons.secondary + "'></span>" );
7750 }
7751
7752 if ( !this.options.text ) {
7753 buttonClasses.push( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" );
7754
7755 if ( !this.hasTitle ) {
7756 buttonElement.attr( "title", buttonText );
7757 }
7758 }
7759 } else {
7760 buttonClasses.push( "ui-button-text-only" );
7761 }
7762 buttonElement.addClass( buttonClasses.join( " " ) );
7763 }
7764 });
7765
7766 $.ui.button.version = "@VERSION";
7767
7768 $.widget( "ui.buttonset", {
7769 options: {
7770 items: ":button, :submit, :reset, :checkbox, :radio, a, :data(button)"
7771 },
7772
7773 _create: function() {
7774 this.element.addClass( "ui-buttonset" );
7775 },
7776
7777 _init: function() {
7778 this.refresh();
7779 },
7780
7781 _setOption: function( key, value ) {
7782 if ( key === "disabled" ) {
7783 this.buttons.button( "option", key, value );
7784 }
7785
7786 this._super( key, value );
7787 },
7788
7789 refresh: function() {
7790 var rtl = this.element.css( "direction" ) === "rtl";
7791
7792 this.buttons = this.element.find( this.options.items )
7793 .filter( ":ui-button" )
7794 .button( "refresh" )
7795 .end()
7796 .not( ":ui-button" )
7797 .button()
7798 .end()
7799 .map(function() {
7800 return $( this ).button( "widget" )[ 0 ];
7801 })
7802 .removeClass( "ui-corner-all ui-corner-left ui-corner-right" )
7803 .filter( ":first" )
7804 .addClass( rtl ? "ui-corner-right" : "ui-corner-left" )
7805 .end()
7806 .filter( ":last" )
7807 .addClass( rtl ? "ui-corner-left" : "ui-corner-right" )
7808 .end()
7809 .end();
7810 },
7811
7812 _destroy: function() {
7813 this.element.removeClass( "ui-buttonset" );
7814 this.buttons
7815 .map(function() {
7816 return $( this ).button( "widget" )[ 0 ];
7817 })
7818 .removeClass( "ui-corner-left ui-corner-right" )
7819 .end()
7820 .button( "destroy" );
7821 }
7822 });
7823
7824 }( jQuery ) );
7825 /*
7826 * jQuery UI Datepicker @VERSION
7827 *
7828 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
7829 * Dual licensed under the MIT or GPL Version 2 licenses.
7830 * http://jquery.org/license
7831 *
7832 * http://docs.jquery.com/UI/Datepicker
7833 *
7834 * Depends:
7835 * jquery.ui.core.js
7836 */
7837 (function( $, undefined ) {
7838
7839 $.extend($.ui, { datepicker: { version: "@VERSION" } });
7840
7841 var PROP_NAME = 'datepicker';
7842 var dpuuid = new Date().getTime();
7843 var instActive;
7844
7845 /* Date picker manager.
7846 Use the singleton instance of this class, $.datepicker, to interact with the date picker.
7847 Settings for (groups of) date pickers are maintained in an instance object,
7848 allowing multiple different settings on the same page. */
7849
7850 function Datepicker() {
7851 this.debug = false; // Change this to true to start debugging
7852 this._curInst = null; // The current instance in use
7853 this._keyEvent = false; // If the last event was a key event
7854 this._disabledInputs = []; // List of date picker inputs that have been disabled
7855 this._datepickerShowing = false; // True if the popup picker is showing , false if not
7856 this._inDialog = false; // True if showing within a "dialog", false if not
7857 this._mainDivId = 'ui-datepicker-div'; // The ID of the main datepicker division
7858 this._inlineClass = 'ui-datepicker-inline'; // The name of the inline marker class
7859 this._appendClass = 'ui-datepicker-append'; // The name of the append marker class
7860 this._triggerClass = 'ui-datepicker-trigger'; // The name of the trigger marker class
7861 this._dialogClass = 'ui-datepicker-dialog'; // The name of the dialog marker class
7862 this._disableClass = 'ui-datepicker-disabled'; // The name of the disabled covering marker class
7863 this._unselectableClass = 'ui-datepicker-unselectable'; // The name of the unselectable cell marker class
7864 this._currentClass = 'ui-datepicker-current-day'; // The name of the current day marker class
7865 this._dayOverClass = 'ui-datepicker-days-cell-over'; // The name of the day hover marker class
7866 this.regional = []; // Available regional settings, indexed by language code
7867 this.regional[''] = { // Default regional settings
7868 closeText: 'Done', // Display text for close link
7869 prevText: 'Prev', // Display text for previous month link
7870 nextText: 'Next', // Display text for next month link
7871 currentText: 'Today', // Display text for current month link
7872 monthNames: ['January','February','March','April','May','June',
7873 'July','August','September','October','November','December'], // Names of months for drop-down and formatting
7874 monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], // For formatting
7875 dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], // For formatting
7876 dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], // For formatting
7877 dayNamesMin: ['Su','Mo','Tu','We','Th','Fr','Sa'], // Column headings for days starting at Sunday
7878 weekHeader: 'Wk', // Column header for week of the year
7879 dateFormat: 'mm/dd/yy', // See format options on parseDate
7880 firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
7881 isRTL: false, // True if right-to-left language, false if left-to-right
7882 showMonthAfterYear: false, // True if the year select precedes month, false for month then year
7883 yearSuffix: '' // Additional text to append to the year in the month headers
7884 };
7885 this._defaults = { // Global defaults for all the date picker instances
7886 showOn: 'focus', // 'focus' for popup on focus,
7887 // 'button' for trigger button, or 'both' for either
7888 showAnim: 'fadeIn', // Name of jQuery animation for popup
7889 showOptions: {}, // Options for enhanced animations
7890 defaultDate: null, // Used when field is blank: actual date,
7891 // +/-number for offset from today, null for today
7892 appendText: '', // Display text following the input box, e.g. showing the format
7893 buttonText: '...', // Text for trigger button
7894 buttonImage: '', // URL for trigger button image
7895 buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
7896 hideIfNoPrevNext: false, // True to hide next/previous month links
7897 // if not applicable, false to just disable them
7898 navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
7899 gotoCurrent: false, // True if today link goes back to current selection instead
7900 changeMonth: false, // True if month can be selected directly, false if only prev/next
7901 changeYear: false, // True if year can be selected directly, false if only prev/next
7902 yearRange: 'c-10:c+10', // Range of years to display in drop-down,
7903 // either relative to today's year (-nn:+nn), relative to currently displayed year
7904 // (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
7905 showOtherMonths: false, // True to show dates in other months, false to leave blank
7906 selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
7907 showWeek: false, // True to show week of the year, false to not show it
7908 calculateWeek: this.iso8601Week, // How to calculate the week of the year,
7909 // takes a Date and returns the number of the week for it
7910 shortYearCutoff: '+10', // Short year values < this are in the current century,
7911 // > this are in the previous century,
7912 // string value starting with '+' for current year + value
7913 minDate: null, // The earliest selectable date, or null for no limit
7914 maxDate: null, // The latest selectable date, or null for no limit
7915 duration: 'fast', // Duration of display/closure
7916 beforeShowDay: null, // Function that takes a date and returns an array with
7917 // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or '',
7918 // [2] = cell title (optional), e.g. $.datepicker.noWeekends
7919 beforeShow: null, // Function that takes an input field and
7920 // returns a set of custom settings for the date picker
7921 onSelect: null, // Define a callback function when a date is selected
7922 onChangeMonthYear: null, // Define a callback function when the month or year is changed
7923 onClose: null, // Define a callback function when the datepicker is closed
7924 numberOfMonths: 1, // Number of months to show at a time
7925 showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
7926 stepMonths: 1, // Number of months to step back/forward
7927 stepBigMonths: 12, // Number of months to step back/forward for the big links
7928 altField: '', // Selector for an alternate field to store selected dates into
7929 altFormat: '', // The date format to use for the alternate field
7930 constrainInput: true, // The input is constrained by the current date format
7931 showButtonPanel: false, // True to show button panel, false to not show it
7932 autoSize: false, // True to size the input for the date format, false to leave as is
7933 disabled: false // The initial disabled state
7934 };
7935 $.extend(this._defaults, this.regional['']);
7936 this.dpDiv = bindHover($('<div id="' + this._mainDivId + '" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>'));
7937 }
7938
7939 $.extend(Datepicker.prototype, {
7940 /* Class name added to elements to indicate already configured with a date picker. */
7941 markerClassName: 'hasDatepicker',
7942
7943 //Keep track of the maximum number of rows displayed (see #7043)
7944 maxRows: 4,
7945
7946 /* Debug logging (if enabled). */
7947 log: function () {
7948 if (this.debug)
7949 console.log.apply('', arguments);
7950 },
7951
7952 // TODO rename to "widget" when switching to widget factory
7953 _widgetDatepicker: function() {
7954 return this.dpDiv;
7955 },
7956
7957 /* Override the default settings for all instances of the date picker.
7958 @param settings object - the new settings to use as defaults (anonymous object)
7959 @return the manager object */
7960 setDefaults: function(settings) {
7961 extendRemove(this._defaults, settings || {});
7962 return this;
7963 },
7964
7965 /* Attach the date picker to a jQuery selection.
7966 @param target element - the target input field or division or span
7967 @param settings object - the new settings to use for this date picker instance (anonymous) */
7968 _attachDatepicker: function(target, settings) {
7969 // check for settings on the control itself - in namespace 'date:'
7970 var inlineSettings = null;
7971 for (var attrName in this._defaults) {
7972 var attrValue = target.getAttribute('date:' + attrName);
7973 if (attrValue) {
7974 inlineSettings = inlineSettings || {};
7975 try {
7976 inlineSettings[attrName] = eval(attrValue);
7977 } catch (err) {
7978 inlineSettings[attrName] = attrValue;
7979 }
7980 }
7981 }
7982 var nodeName = target.nodeName.toLowerCase();
7983 var inline = (nodeName == 'div' || nodeName == 'span');
7984 if (!target.id) {
7985 this.uuid += 1;
7986 target.id = 'dp' + this.uuid;
7987 }
7988 var inst = this._newInst($(target), inline);
7989 inst.settings = $.extend({}, settings || {}, inlineSettings || {});
7990 if (nodeName == 'input') {
7991 this._connectDatepicker(target, inst);
7992 } else if (inline) {
7993 this._inlineDatepicker(target, inst);
7994 }
7995 },
7996
7997 /* Create a new instance object. */
7998 _newInst: function(target, inline) {
7999 var id = target[0].id.replace(/([^A-Za-z0-9_-])/g, '\\\\$1'); // escape jQuery meta chars
8000 return {id: id, input: target, // associated target
8001 selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
8002 drawMonth: 0, drawYear: 0, // month being drawn
8003 inline: inline, // is datepicker inline or not
8004 dpDiv: (!inline ? this.dpDiv : // presentation div
8005 bindHover($('<div class="' + this._inlineClass + ' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>')))};
8006 },
8007
8008 /* Attach the date picker to an input field. */
8009 _connectDatepicker: function(target, inst) {
8010 var input = $(target);
8011 inst.append = $([]);
8012 inst.trigger = $([]);
8013 if (input.hasClass(this.markerClassName))
8014 return;
8015 this._attachments(input, inst);
8016 input.addClass(this.markerClassName).keydown(this._doKeyDown).
8017 keypress(this._doKeyPress).keyup(this._doKeyUp).
8018 bind("setData.datepicker", function(event, key, value) {
8019 inst.settings[key] = value;
8020 }).bind("getData.datepicker", function(event, key) {
8021 return this._get(inst, key);
8022 });
8023 this._autoSize(inst);
8024 $.data(target, PROP_NAME, inst);
8025 //If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665)
8026 if( inst.settings.disabled ) {
8027 this._disableDatepicker( target );
8028 }
8029 },
8030
8031 /* Make attachments based on settings. */
8032 _attachments: function(input, inst) {
8033 var appendText = this._get(inst, 'appendText');
8034 var isRTL = this._get(inst, 'isRTL');
8035 if (inst.append)
8036 inst.append.remove();
8037 if (appendText) {
8038 inst.append = $('<span class="' + this._appendClass + '">' + appendText + '</span>');
8039 input[isRTL ? 'before' : 'after'](inst.append);
8040 }
8041 input.unbind('focus', this._showDatepicker);
8042 if (inst.trigger)
8043 inst.trigger.remove();
8044 var showOn = this._get(inst, 'showOn');
8045 if (showOn == 'focus' || showOn == 'both') // pop-up date picker when in the marked field
8046 input.focus(this._showDatepicker);
8047 if (showOn == 'button' || showOn == 'both') { // pop-up date picker when button clicked
8048 var buttonText = this._get(inst, 'buttonText');
8049 var buttonImage = this._get(inst, 'buttonImage');
8050 inst.trigger = $(this._get(inst, 'buttonImageOnly') ?
8051 $('<img/>').addClass(this._triggerClass).
8052 attr({ src: buttonImage, alt: buttonText, title: buttonText }) :
8053 $('<button type="button"></button>').addClass(this._triggerClass).
8054 html(buttonImage == '' ? buttonText : $('<img/>').attr(
8055 { src:buttonImage, alt:buttonText, title:buttonText })));
8056 input[isRTL ? 'before' : 'after'](inst.trigger);
8057 inst.trigger.click(function() {
8058 if ($.datepicker._datepickerShowing && $.datepicker._lastInput == input[0])
8059 $.datepicker._hideDatepicker();
8060 else
8061 $.datepicker._showDatepicker(input[0]);
8062 return false;
8063 });
8064 }
8065 },
8066
8067 /* Apply the maximum length for the date format. */
8068 _autoSize: function(inst) {
8069 if (this._get(inst, 'autoSize') && !inst.inline) {
8070 var date = new Date(2009, 12 - 1, 20); // Ensure double digits
8071 var dateFormat = this._get(inst, 'dateFormat');
8072 if (dateFormat.match(/[DM]/)) {
8073 var findMax = function(names) {
8074 var max = 0;
8075 var maxI = 0;
8076 for (var i = 0; i < names.length; i++) {
8077 if (names[i].length > max) {
8078 max = names[i].length;
8079 maxI = i;
8080 }
8081 }
8082 return maxI;
8083 };
8084 date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ?
8085 'monthNames' : 'monthNamesShort'))));
8086 date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ?
8087 'dayNames' : 'dayNamesShort'))) + 20 - date.getDay());
8088 }
8089 inst.input.attr('size', this._formatDate(inst, date).length);
8090 }
8091 },
8092
8093 /* Attach an inline date picker to a div. */
8094 _inlineDatepicker: function(target, inst) {
8095 var divSpan = $(target);
8096 if (divSpan.hasClass(this.markerClassName))
8097 return;
8098 divSpan.addClass(this.markerClassName).append(inst.dpDiv).
8099 bind("setData.datepicker", function(event, key, value){
8100 inst.settings[key] = value;
8101 }).bind("getData.datepicker", function(event, key){
8102 return this._get(inst, key);
8103 });
8104 $.data(target, PROP_NAME, inst);
8105 this._setDate(inst, this._getDefaultDate(inst), true);
8106 this._updateDatepicker(inst);
8107 this._updateAlternate(inst);
8108 //If disabled option is true, disable the datepicker before showing it (see ticket #5665)
8109 if( inst.settings.disabled ) {
8110 this._disableDatepicker( target );
8111 }
8112 // Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements
8113 // http://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height
8114 inst.dpDiv.css( "display", "block" );
8115 },
8116
8117 /* Pop-up the date picker in a "dialog" box.
8118 @param input element - ignored
8119 @param date string or Date - the initial date to display
8120 @param onSelect function - the function to call when a date is selected
8121 @param settings object - update the dialog date picker instance's settings (anonymous object)
8122 @param pos int[2] - coordinates for the dialog's position within the screen or
8123 event - with x/y coordinates or
8124 leave empty for default (screen centre)
8125 @return the manager object */
8126 _dialogDatepicker: function(input, date, onSelect, settings, pos) {
8127 var inst = this._dialogInst; // internal instance
8128 if (!inst) {
8129 this.uuid += 1;
8130 var id = 'dp' + this.uuid;
8131 this._dialogInput = $('<input type="text" id="' + id +
8132 '" style="position: absolute; top: -100px; width: 0px; z-index: -10;"/>');
8133 this._dialogInput.keydown(this._doKeyDown);
8134 $('body').append(this._dialogInput);
8135 inst = this._dialogInst = this._newInst(this._dialogInput, false);
8136 inst.settings = {};
8137 $.data(this._dialogInput[0], PROP_NAME, inst);
8138 }
8139 extendRemove(inst.settings, settings || {});
8140 date = (date && date.constructor == Date ? this._formatDate(inst, date) : date);
8141 this._dialogInput.val(date);
8142
8143 this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);
8144 if (!this._pos) {
8145 var browserWidth = document.documentElement.clientWidth;
8146 var browserHeight = document.documentElement.clientHeight;
8147 var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
8148 var scrollY = document.documentElement.scrollTop || document.body.scrollTop;
8149 this._pos = // should use actual width/height below
8150 [(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY];
8151 }
8152
8153 // move input on screen for focus, but hidden behind dialog
8154 this._dialogInput.css('left', (this._pos[0] + 20) + 'px').css('top', this._pos[1] + 'px');
8155 inst.settings.onSelect = onSelect;
8156 this._inDialog = true;
8157 this.dpDiv.addClass(this._dialogClass);
8158 this._showDatepicker(this._dialogInput[0]);
8159 if ($.blockUI)
8160 $.blockUI(this.dpDiv);
8161 $.data(this._dialogInput[0], PROP_NAME, inst);
8162 return this;
8163 },
8164
8165 /* Detach a datepicker from its control.
8166 @param target element - the target input field or division or span */
8167 _destroyDatepicker: function(target) {
8168 var $target = $(target);
8169 var inst = $.data(target, PROP_NAME);
8170 if (!$target.hasClass(this.markerClassName)) {
8171 return;
8172 }
8173 var nodeName = target.nodeName.toLowerCase();
8174 $.removeData(target, PROP_NAME);
8175 if (nodeName == 'input') {
8176 inst.append.remove();
8177 inst.trigger.remove();
8178 $target.removeClass(this.markerClassName).
8179 unbind('focus', this._showDatepicker).
8180 unbind('keydown', this._doKeyDown).
8181 unbind('keypress', this._doKeyPress).
8182 unbind('keyup', this._doKeyUp);
8183 } else if (nodeName == 'div' || nodeName == 'span')
8184 $target.removeClass(this.markerClassName).empty();
8185 },
8186
8187 /* Enable the date picker to a jQuery selection.
8188 @param target element - the target input field or division or span */
8189 _enableDatepicker: function(target) {
8190 var $target = $(target);
8191 var inst = $.data(target, PROP_NAME);
8192 if (!$target.hasClass(this.markerClassName)) {
8193 return;
8194 }
8195 var nodeName = target.nodeName.toLowerCase();
8196 if (nodeName == 'input') {
8197 target.disabled = false;
8198 inst.trigger.filter('button').
8199 each(function() { this.disabled = false; }).end().
8200 filter('img').css({opacity: '1.0', cursor: ''});
8201 }
8202 else if (nodeName == 'div' || nodeName == 'span') {
8203 var inline = $target.children('.' + this._inlineClass);
8204 inline.children().removeClass('ui-state-disabled');
8205 inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
8206 prop("disabled", false);
8207 }
8208 this._disabledInputs = $.map(this._disabledInputs,
8209 function(value) { return (value == target ? null : value); }); // delete entry
8210 },
8211
8212 /* Disable the date picker to a jQuery selection.
8213 @param target element - the target input field or division or span */
8214 _disableDatepicker: function(target) {
8215 var $target = $(target);
8216 var inst = $.data(target, PROP_NAME);
8217 if (!$target.hasClass(this.markerClassName)) {
8218 return;
8219 }
8220 var nodeName = target.nodeName.toLowerCase();
8221 if (nodeName == 'input') {
8222 target.disabled = true;
8223 inst.trigger.filter('button').
8224 each(function() { this.disabled = true; }).end().
8225 filter('img').css({opacity: '0.5', cursor: 'default'});
8226 }
8227 else if (nodeName == 'div' || nodeName == 'span') {
8228 var inline = $target.children('.' + this._inlineClass);
8229 inline.children().addClass('ui-state-disabled');
8230 inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
8231 prop("disabled", true);
8232 }
8233 this._disabledInputs = $.map(this._disabledInputs,
8234 function(value) { return (value == target ? null : value); }); // delete entry
8235 this._disabledInputs[this._disabledInputs.length] = target;
8236 },
8237
8238 /* Is the first field in a jQuery collection disabled as a datepicker?
8239 @param target element - the target input field or division or span
8240 @return boolean - true if disabled, false if enabled */
8241 _isDisabledDatepicker: function(target) {
8242 if (!target) {
8243 return false;
8244 }
8245 for (var i = 0; i < this._disabledInputs.length; i++) {
8246 if (this._disabledInputs[i] == target)
8247 return true;
8248 }
8249 return false;
8250 },
8251
8252 /* Retrieve the instance data for the target control.
8253 @param target element - the target input field or division or span
8254 @return object - the associated instance data
8255 @throws error if a jQuery problem getting data */
8256 _getInst: function(target) {
8257 try {
8258 return $.data(target, PROP_NAME);
8259 }
8260 catch (err) {
8261 throw 'Missing instance data for this datepicker';
8262 }
8263 },
8264
8265 /* Update or retrieve the settings for a date picker attached to an input field or division.
8266 @param target element - the target input field or division or span
8267 @param name object - the new settings to update or
8268 string - the name of the setting to change or retrieve,
8269 when retrieving also 'all' for all instance settings or
8270 'defaults' for all global defaults
8271 @param value any - the new value for the setting
8272 (omit if above is an object or to retrieve a value) */
8273 _optionDatepicker: function(target, name, value) {
8274 var inst = this._getInst(target);
8275 if (arguments.length == 2 && typeof name == 'string') {
8276 return (name == 'defaults' ? $.extend({}, $.datepicker._defaults) :
8277 (inst ? (name == 'all' ? $.extend({}, inst.settings) :
8278 this._get(inst, name)) : null));
8279 }
8280 var settings = name || {};
8281 if (typeof name == 'string') {
8282 settings = {};
8283 settings[name] = value;
8284 }
8285 if (inst) {
8286 if (this._curInst == inst) {
8287 this._hideDatepicker();
8288 }
8289 var date = this._getDateDatepicker(target, true);
8290 var minDate = this._getMinMaxDate(inst, 'min');
8291 var maxDate = this._getMinMaxDate(inst, 'max');
8292 extendRemove(inst.settings, settings);
8293 // reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided
8294 if (minDate !== null && settings['dateFormat'] !== undefined && settings['minDate'] === undefined)
8295 inst.settings.minDate = this._formatDate(inst, minDate);
8296 if (maxDate !== null && settings['dateFormat'] !== undefined && settings['maxDate'] === undefined)
8297 inst.settings.maxDate = this._formatDate(inst, maxDate);
8298 this._attachments($(target), inst);
8299 this._autoSize(inst);
8300 this._setDate(inst, date);
8301 this._updateAlternate(inst);
8302 this._updateDatepicker(inst);
8303 }
8304 },
8305
8306 // change method deprecated
8307 _changeDatepicker: function(target, name, value) {
8308 this._optionDatepicker(target, name, value);
8309 },
8310
8311 /* Redraw the date picker attached to an input field or division.
8312 @param target element - the target input field or division or span */
8313 _refreshDatepicker: function(target) {
8314 var inst = this._getInst(target);
8315 if (inst) {
8316 this._updateDatepicker(inst);
8317 }
8318 },
8319
8320 /* Set the dates for a jQuery selection.
8321 @param target element - the target input field or division or span
8322 @param date Date - the new date */
8323 _setDateDatepicker: function(target, date) {
8324 var inst = this._getInst(target);
8325 if (inst) {
8326 this._setDate(inst, date);
8327 this._updateDatepicker(inst);
8328 this._updateAlternate(inst);
8329 }
8330 },
8331
8332 /* Get the date(s) for the first entry in a jQuery selection.
8333 @param target element - the target input field or division or span
8334 @param noDefault boolean - true if no default date is to be used
8335 @return Date - the current date */
8336 _getDateDatepicker: function(target, noDefault) {
8337 var inst = this._getInst(target);
8338 if (inst && !inst.inline)
8339 this._setDateFromField(inst, noDefault);
8340 return (inst ? this._getDate(inst) : null);
8341 },
8342
8343 /* Handle keystrokes. */
8344 _doKeyDown: function(event) {
8345 var inst = $.datepicker._getInst(event.target);
8346 var handled = true;
8347 var isRTL = inst.dpDiv.is('.ui-datepicker-rtl');
8348 inst._keyEvent = true;
8349 if ($.datepicker._datepickerShowing)
8350 switch (event.keyCode) {
8351 case 9: $.datepicker._hideDatepicker();
8352 handled = false;
8353 break; // hide on tab out
8354 case 13: var sel = $('td.' + $.datepicker._dayOverClass + ':not(.' +
8355 $.datepicker._currentClass + ')', inst.dpDiv);
8356 if (sel[0])
8357 $.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);
8358 var onSelect = $.datepicker._get(inst, 'onSelect');
8359 if (onSelect) {
8360 var dateStr = $.datepicker._formatDate(inst);
8361
8362 // trigger custom callback
8363 onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);
8364 }
8365 else
8366 $.datepicker._hideDatepicker();
8367 return false; // don't submit the form
8368 break; // select the value on enter
8369 case 27: $.datepicker._hideDatepicker();
8370 break; // hide on escape
8371 case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
8372 -$.datepicker._get(inst, 'stepBigMonths') :
8373 -$.datepicker._get(inst, 'stepMonths')), 'M');
8374 break; // previous month/year on page up/+ ctrl
8375 case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
8376 +$.datepicker._get(inst, 'stepBigMonths') :
8377 +$.datepicker._get(inst, 'stepMonths')), 'M');
8378 break; // next month/year on page down/+ ctrl
8379 case 35: if (event.ctrlKey || event.metaKey) $.datepicker._clearDate(event.target);
8380 handled = event.ctrlKey || event.metaKey;
8381 break; // clear on ctrl or command +end
8382 case 36: if (event.ctrlKey || event.metaKey) $.datepicker._gotoToday(event.target);
8383 handled = event.ctrlKey || event.metaKey;
8384 break; // current on ctrl or command +home
8385 case 37: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), 'D');
8386 handled = event.ctrlKey || event.metaKey;
8387 // -1 day on ctrl or command +left
8388 if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
8389 -$.datepicker._get(inst, 'stepBigMonths') :
8390 -$.datepicker._get(inst, 'stepMonths')), 'M');
8391 // next month/year on alt +left on Mac
8392 break;
8393 case 38: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, -7, 'D');
8394 handled = event.ctrlKey || event.metaKey;
8395 break; // -1 week on ctrl or command +up
8396 case 39: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), 'D');
8397 handled = event.ctrlKey || event.metaKey;
8398 // +1 day on ctrl or command +right
8399 if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
8400 +$.datepicker._get(inst, 'stepBigMonths') :
8401 +$.datepicker._get(inst, 'stepMonths')), 'M');
8402 // next month/year on alt +right
8403 break;
8404 case 40: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, +7, 'D');
8405 handled = event.ctrlKey || event.metaKey;
8406 break; // +1 week on ctrl or command +down
8407 default: handled = false;
8408 }
8409 else if (event.keyCode == 36 && event.ctrlKey) // display the date picker on ctrl+home
8410 $.datepicker._showDatepicker(this);
8411 else {
8412 handled = false;
8413 }
8414 if (handled) {
8415 event.preventDefault();
8416 event.stopPropagation();
8417 }
8418 },
8419
8420 /* Filter entered characters - based on date format. */
8421 _doKeyPress: function(event) {
8422 var inst = $.datepicker._getInst(event.target);
8423 if ($.datepicker._get(inst, 'constrainInput')) {
8424 var chars = $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat'));
8425 var chr = String.fromCharCode(event.charCode == undefined ? event.keyCode : event.charCode);
8426 return event.ctrlKey || event.metaKey || (chr < ' ' || !chars || chars.indexOf(chr) > -1);
8427 }
8428 },
8429
8430 /* Synchronise manual entry and field/alternate field. */
8431 _doKeyUp: function(event) {
8432 var inst = $.datepicker._getInst(event.target);
8433 if (inst.input.val() != inst.lastVal) {
8434 try {
8435 var date = $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
8436 (inst.input ? inst.input.val() : null),
8437 $.datepicker._getFormatConfig(inst));
8438 if (date) { // only if valid
8439 $.datepicker._setDateFromField(inst);
8440 $.datepicker._updateAlternate(inst);
8441 $.datepicker._updateDatepicker(inst);
8442 }
8443 }
8444 catch (event) {
8445 $.datepicker.log(event);
8446 }
8447 }
8448 return true;
8449 },
8450
8451 /* Pop-up the date picker for a given input field.
8452 If false returned from beforeShow event handler do not show.
8453 @param input element - the input field attached to the date picker or
8454 event - if triggered by focus */
8455 _showDatepicker: function(input) {
8456 input = input.target || input;
8457 if (input.nodeName.toLowerCase() != 'input') // find from button/image trigger
8458 input = $('input', input.parentNode)[0];
8459 if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput == input) // already here
8460 return;
8461 var inst = $.datepicker._getInst(input);
8462 if ($.datepicker._curInst && $.datepicker._curInst != inst) {
8463 $.datepicker._curInst.dpDiv.stop(true, true);
8464 if ( inst && $.datepicker._datepickerShowing ) {
8465 $.datepicker._hideDatepicker( $.datepicker._curInst.input[0] );
8466 }
8467 }
8468 var beforeShow = $.datepicker._get(inst, 'beforeShow');
8469 var beforeShowSettings = beforeShow ? beforeShow.apply(input, [input, inst]) : {};
8470 if(beforeShowSettings === false){
8471 //false
8472 return;
8473 }
8474 extendRemove(inst.settings, beforeShowSettings);
8475 inst.lastVal = null;
8476 $.datepicker._lastInput = input;
8477 $.datepicker._setDateFromField(inst);
8478 if ($.datepicker._inDialog) // hide cursor
8479 input.value = '';
8480 if (!$.datepicker._pos) { // position below input
8481 $.datepicker._pos = $.datepicker._findPos(input);
8482 $.datepicker._pos[1] += input.offsetHeight; // add the height
8483 }
8484 var isFixed = false;
8485 $(input).parents().each(function() {
8486 isFixed |= $(this).css('position') == 'fixed';
8487 return !isFixed;
8488 });
8489 if (isFixed && $.browser.opera) { // correction for Opera when fixed and scrolled
8490 $.datepicker._pos[0] -= document.documentElement.scrollLeft;
8491 $.datepicker._pos[1] -= document.documentElement.scrollTop;
8492 }
8493 var offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]};
8494 $.datepicker._pos = null;
8495 //to avoid flashes on Firefox
8496 inst.dpDiv.empty();
8497 // determine sizing offscreen
8498 inst.dpDiv.css({position: 'absolute', display: 'block', top: '-1000px'});
8499 $.datepicker._updateDatepicker(inst);
8500 // fix width for dynamic number of date pickers
8501 // and adjust position before showing
8502 offset = $.datepicker._checkOffset(inst, offset, isFixed);
8503 inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ?
8504 'static' : (isFixed ? 'fixed' : 'absolute')), display: 'none',
8505 left: offset.left + 'px', top: offset.top + 'px'});
8506 if (!inst.inline) {
8507 var showAnim = $.datepicker._get(inst, 'showAnim');
8508 var duration = $.datepicker._get(inst, 'duration');
8509 var postProcess = function() {
8510 var cover = inst.dpDiv.find('iframe.ui-datepicker-cover'); // IE6- only
8511 if( !! cover.length ){
8512 var borders = $.datepicker._getBorders(inst.dpDiv);
8513 cover.css({left: -borders[0], top: -borders[1],
8514 width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()});
8515 }
8516 };
8517 inst.dpDiv.zIndex($(input).zIndex()+1);
8518 $.datepicker._datepickerShowing = true;
8519
8520 // DEPRECATED: after BC for 1.8.x $.effects[ showAnim ] is not needed
8521 if ( $.effects && ( $.effects.effect[ showAnim ] || $.effects[ showAnim ] ) )
8522 inst.dpDiv.show(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
8523 else
8524 inst.dpDiv[showAnim || 'show']((showAnim ? duration : null), postProcess);
8525 if (!showAnim || !duration)
8526 postProcess();
8527 if (inst.input.is(':visible') && !inst.input.is(':disabled'))
8528 inst.input.focus();
8529 $.datepicker._curInst = inst;
8530 }
8531 },
8532
8533 /* Generate the date picker content. */
8534 _updateDatepicker: function(inst) {
8535 var self = this;
8536 self.maxRows = 4; //Reset the max number of rows being displayed (see #7043)
8537 var borders = $.datepicker._getBorders(inst.dpDiv);
8538 instActive = inst; // for delegate hover events
8539 inst.dpDiv.empty().append(this._generateHTML(inst));
8540 var cover = inst.dpDiv.find('iframe.ui-datepicker-cover'); // IE6- only
8541 if( !!cover.length ){ //avoid call to outerXXXX() when not in IE6
8542 cover.css({left: -borders[0], top: -borders[1], width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()})
8543 }
8544 inst.dpDiv.find('.' + this._dayOverClass + ' a').mouseover();
8545 var numMonths = this._getNumberOfMonths(inst);
8546 var cols = numMonths[1];
8547 var width = 17;
8548 inst.dpDiv.removeClass('ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4').width('');
8549 if (cols > 1)
8550 inst.dpDiv.addClass('ui-datepicker-multi-' + cols).css('width', (width * cols) + 'em');
8551 inst.dpDiv[(numMonths[0] != 1 || numMonths[1] != 1 ? 'add' : 'remove') +
8552 'Class']('ui-datepicker-multi');
8553 inst.dpDiv[(this._get(inst, 'isRTL') ? 'add' : 'remove') +
8554 'Class']('ui-datepicker-rtl');
8555 if (inst == $.datepicker._curInst && $.datepicker._datepickerShowing && inst.input &&
8556 // #6694 - don't focus the input if it's already focused
8557 // this breaks the change event in IE
8558 inst.input.is(':visible') && !inst.input.is(':disabled') && inst.input[0] != document.activeElement)
8559 inst.input.focus();
8560 // deffered render of the years select (to avoid flashes on Firefox)
8561 if( inst.yearshtml ){
8562 var origyearshtml = inst.yearshtml;
8563 setTimeout(function(){
8564 //assure that inst.yearshtml didn't change.
8565 if( origyearshtml === inst.yearshtml && inst.yearshtml ){
8566 inst.dpDiv.find('select.ui-datepicker-year:first').replaceWith(inst.yearshtml);
8567 }
8568 origyearshtml = inst.yearshtml = null;
8569 }, 0);
8570 }
8571 },
8572
8573 /* Retrieve the size of left and top borders for an element.
8574 @param elem (jQuery object) the element of interest
8575 @return (number[2]) the left and top borders */
8576 _getBorders: function(elem) {
8577 var convert = function(value) {
8578 return {thin: 1, medium: 2, thick: 3}[value] || value;
8579 };
8580 return [parseFloat(convert(elem.css('border-left-width'))),
8581 parseFloat(convert(elem.css('border-top-width')))];
8582 },
8583
8584 /* Check positioning to remain on screen. */
8585 _checkOffset: function(inst, offset, isFixed) {
8586 var dpWidth = inst.dpDiv.outerWidth();
8587 var dpHeight = inst.dpDiv.outerHeight();
8588 var inputWidth = inst.input ? inst.input.outerWidth() : 0;
8589 var inputHeight = inst.input ? inst.input.outerHeight() : 0;
8590 var viewWidth = document.documentElement.clientWidth + $(document).scrollLeft();
8591 var viewHeight = document.documentElement.clientHeight + $(document).scrollTop();
8592
8593 offset.left -= (this._get(inst, 'isRTL') ? (dpWidth - inputWidth) : 0);
8594 offset.left -= (isFixed && offset.left == inst.input.offset().left) ? $(document).scrollLeft() : 0;
8595 offset.top -= (isFixed && offset.top == (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;
8596
8597 // now check if datepicker is showing outside window viewport - move to a better place if so.
8598 offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?
8599 Math.abs(offset.left + dpWidth - viewWidth) : 0);
8600 offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?
8601 Math.abs(dpHeight + inputHeight) : 0);
8602
8603 return offset;
8604 },
8605
8606 /* Find an object's position on the screen. */
8607 _findPos: function(obj) {
8608 var inst = this._getInst(obj);
8609 var isRTL = this._get(inst, 'isRTL');
8610 while (obj && (obj.type == 'hidden' || obj.nodeType != 1 || $.expr.filters.hidden(obj))) {
8611 obj = obj[isRTL ? 'previousSibling' : 'nextSibling'];
8612 }
8613 var position = $(obj).offset();
8614 return [position.left, position.top];
8615 },
8616
8617 /* Hide the date picker from view.
8618 @param input element - the input field attached to the date picker */
8619 _hideDatepicker: function(input) {
8620 var inst = this._curInst;
8621 if (!inst || (input && inst != $.data(input, PROP_NAME)))
8622 return;
8623 if (this._datepickerShowing) {
8624 var showAnim = this._get(inst, 'showAnim');
8625 var duration = this._get(inst, 'duration');
8626 var self = this;
8627 var postProcess = function() {
8628 $.datepicker._tidyDialog(inst);
8629 self._curInst = null;
8630 };
8631
8632 // DEPRECATED: after BC for 1.8.x $.effects[ showAnim ] is not needed
8633 if ( $.effects && ( $.effects.effect[ showAnim ] || $.effects[ showAnim ] ) )
8634 inst.dpDiv.hide(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
8635 else
8636 inst.dpDiv[(showAnim == 'slideDown' ? 'slideUp' :
8637 (showAnim == 'fadeIn' ? 'fadeOut' : 'hide'))]((showAnim ? duration : null), postProcess);
8638 if (!showAnim)
8639 postProcess();
8640 this._datepickerShowing = false;
8641 var onClose = this._get(inst, 'onClose');
8642 if (onClose)
8643 onClose.apply((inst.input ? inst.input[0] : null),
8644 [(inst.input ? inst.input.val() : ''), inst]);
8645 this._lastInput = null;
8646 if (this._inDialog) {
8647 this._dialogInput.css({ position: 'absolute', left: '0', top: '-100px' });
8648 if ($.blockUI) {
8649 $.unblockUI();
8650 $('body').append(this.dpDiv);
8651 }
8652 }
8653 this._inDialog = false;
8654 }
8655 },
8656
8657 /* Tidy up after a dialog display. */
8658 _tidyDialog: function(inst) {
8659 inst.dpDiv.removeClass(this._dialogClass).unbind('.ui-datepicker-calendar');
8660 },
8661
8662 /* Close date picker if clicked elsewhere. */
8663 _checkExternalClick: function(event) {
8664 if (!$.datepicker._curInst)
8665 return;
8666
8667 var $target = $(event.target),
8668 inst = $.datepicker._getInst($target[0]);
8669
8670 if ( ( ( $target[0].id != $.datepicker._mainDivId &&
8671 $target.parents('#' + $.datepicker._mainDivId).length == 0 &&
8672 !$target.hasClass($.datepicker.markerClassName) &&
8673 !$target.hasClass($.datepicker._triggerClass) &&
8674 $.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI) ) ) ||
8675 ( $target.hasClass($.datepicker.markerClassName) && $.datepicker._curInst != inst ) )
8676 $.datepicker._hideDatepicker();
8677 },
8678
8679 /* Adjust one of the date sub-fields. */
8680 _adjustDate: function(id, offset, period) {
8681 var target = $(id);
8682 var inst = this._getInst(target[0]);
8683 if (this._isDisabledDatepicker(target[0])) {
8684 return;
8685 }
8686 this._adjustInstDate(inst, offset +
8687 (period == 'M' ? this._get(inst, 'showCurrentAtPos') : 0), // undo positioning
8688 period);
8689 this._updateDatepicker(inst);
8690 },
8691
8692 /* Action for current link. */
8693 _gotoToday: function(id) {
8694 var target = $(id);
8695 var inst = this._getInst(target[0]);
8696 if (this._get(inst, 'gotoCurrent') && inst.currentDay) {
8697 inst.selectedDay = inst.currentDay;
8698 inst.drawMonth = inst.selectedMonth = inst.currentMonth;
8699 inst.drawYear = inst.selectedYear = inst.currentYear;
8700 }
8701 else {
8702 var date = new Date();
8703 inst.selectedDay = date.getDate();
8704 inst.drawMonth = inst.selectedMonth = date.getMonth();
8705 inst.drawYear = inst.selectedYear = date.getFullYear();
8706 }
8707 this._notifyChange(inst);
8708 this._adjustDate(target);
8709 },
8710
8711 /* Action for selecting a new month/year. */
8712 _selectMonthYear: function(id, select, period) {
8713 var target = $(id);
8714 var inst = this._getInst(target[0]);
8715 inst['selected' + (period == 'M' ? 'Month' : 'Year')] =
8716 inst['draw' + (period == 'M' ? 'Month' : 'Year')] =
8717 parseInt(select.options[select.selectedIndex].value,10);
8718 this._notifyChange(inst);
8719 this._adjustDate(target);
8720 },
8721
8722 /* Action for selecting a day. */
8723 _selectDay: function(id, month, year, td) {
8724 var target = $(id);
8725 if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) {
8726 return;
8727 }
8728 var inst = this._getInst(target[0]);
8729 inst.selectedDay = inst.currentDay = $('a', td).html();
8730 inst.selectedMonth = inst.currentMonth = month;
8731 inst.selectedYear = inst.currentYear = year;
8732 this._selectDate(id, this._formatDate(inst,
8733 inst.currentDay, inst.currentMonth, inst.currentYear));
8734 },
8735
8736 /* Erase the input field and hide the date picker. */
8737 _clearDate: function(id) {
8738 var target = $(id);
8739 var inst = this._getInst(target[0]);
8740 this._selectDate(target, '');
8741 },
8742
8743 /* Update the input field with the selected date. */
8744 _selectDate: function(id, dateStr) {
8745 var target = $(id);
8746 var inst = this._getInst(target[0]);
8747 dateStr = (dateStr != null ? dateStr : this._formatDate(inst));
8748 if (inst.input)
8749 inst.input.val(dateStr);
8750 this._updateAlternate(inst);
8751 var onSelect = this._get(inst, 'onSelect');
8752 if (onSelect)
8753 onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); // trigger custom callback
8754 else if (inst.input)
8755 inst.input.trigger('change'); // fire the change event
8756 if (inst.inline)
8757 this._updateDatepicker(inst);
8758 else {
8759 this._hideDatepicker();
8760 this._lastInput = inst.input[0];
8761 if (typeof(inst.input[0]) != 'object')
8762 inst.input.focus(); // restore focus
8763 this._lastInput = null;
8764 }
8765 },
8766
8767 /* Update any alternate field to synchronise with the main field. */
8768 _updateAlternate: function(inst) {
8769 var altField = this._get(inst, 'altField');
8770 if (altField) { // update alternate field too
8771 var altFormat = this._get(inst, 'altFormat') || this._get(inst, 'dateFormat');
8772 var date = this._getDate(inst);
8773 var dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst));
8774 $(altField).each(function() { $(this).val(dateStr); });
8775 }
8776 },
8777
8778 /* Set as beforeShowDay function to prevent selection of weekends.
8779 @param date Date - the date to customise
8780 @return [boolean, string] - is this date selectable?, what is its CSS class? */
8781 noWeekends: function(date) {
8782 var day = date.getDay();
8783 return [(day > 0 && day < 6), ''];
8784 },
8785
8786 /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
8787 @param date Date - the date to get the week for
8788 @return number - the number of the week within the year that contains this date */
8789 iso8601Week: function(date) {
8790 var checkDate = new Date(date.getTime());
8791 // Find Thursday of this week starting on Monday
8792 checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7));
8793 var time = checkDate.getTime();
8794 checkDate.setMonth(0); // Compare with Jan 1
8795 checkDate.setDate(1);
8796 return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
8797 },
8798
8799 /* Parse a string value into a date object.
8800 See formatDate below for the possible formats.
8801
8802 @param format string - the expected format of the date
8803 @param value string - the date in the above format
8804 @param settings Object - attributes include:
8805 shortYearCutoff number - the cutoff year for determining the century (optional)
8806 dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
8807 dayNames string[7] - names of the days from Sunday (optional)
8808 monthNamesShort string[12] - abbreviated names of the months (optional)
8809 monthNames string[12] - names of the months (optional)
8810 @return Date - the extracted date value or null if value is blank */
8811 parseDate: function (format, value, settings) {
8812 if (format == null || value == null)
8813 throw 'Invalid arguments';
8814 value = (typeof value == 'object' ? value.toString() : value + '');
8815 if (value == '')
8816 return null;
8817 var shortYearCutoff = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff;
8818 shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff :
8819 new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
8820 var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
8821 var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
8822 var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
8823 var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
8824 var year = -1;
8825 var month = -1;
8826 var day = -1;
8827 var doy = -1;
8828 var literal = false;
8829 // Check whether a format character is doubled
8830 var lookAhead = function(match) {
8831 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
8832 if (matches)
8833 iFormat++;
8834 return matches;
8835 };
8836 // Extract a number from the string value
8837 var getNumber = function(match) {
8838 var isDoubled = lookAhead(match);
8839 var size = (match == '@' ? 14 : (match == '!' ? 20 :
8840 (match == 'y' && isDoubled ? 4 : (match == 'o' ? 3 : 2))));
8841 var digits = new RegExp('^\\d{1,' + size + '}');
8842 var num = value.substring(iValue).match(digits);
8843 if (!num)
8844 throw 'Missing number at position ' + iValue;
8845 iValue += num[0].length;
8846 return parseInt(num[0], 10);
8847 };
8848 // Extract a name from the string value and convert to an index
8849 var getName = function(match, shortNames, longNames) {
8850 var names = $.map(lookAhead(match) ? longNames : shortNames, function (v, k) {
8851 return [ [k, v] ];
8852 }).sort(function (a, b) {
8853 return -(a[1].length - b[1].length);
8854 });
8855 var index = -1;
8856 $.each(names, function (i, pair) {
8857 var name = pair[1];
8858 if (value.substr(iValue, name.length).toLowerCase() == name.toLowerCase()) {
8859 index = pair[0];
8860 iValue += name.length;
8861 return false;
8862 }
8863 });
8864 if (index != -1)
8865 return index + 1;
8866 else
8867 throw 'Unknown name at position ' + iValue;
8868 };
8869 // Confirm that a literal character matches the string value
8870 var checkLiteral = function() {
8871 if (value.charAt(iValue) != format.charAt(iFormat))
8872 throw 'Unexpected literal at position ' + iValue;
8873 iValue++;
8874 };
8875 var iValue = 0;
8876 for (var iFormat = 0; iFormat < format.length; iFormat++) {
8877 if (literal)
8878 if (format.charAt(iFormat) == "'" && !lookAhead("'"))
8879 literal = false;
8880 else
8881 checkLiteral();
8882 else
8883 switch (format.charAt(iFormat)) {
8884 case 'd':
8885 day = getNumber('d');
8886 break;
8887 case 'D':
8888 getName('D', dayNamesShort, dayNames);
8889 break;
8890 case 'o':
8891 doy = getNumber('o');
8892 break;
8893 case 'm':
8894 month = getNumber('m');
8895 break;
8896 case 'M':
8897 month = getName('M', monthNamesShort, monthNames);
8898 break;
8899 case 'y':
8900 year = getNumber('y');
8901 break;
8902 case '@':
8903 var date = new Date(getNumber('@'));
8904 year = date.getFullYear();
8905 month = date.getMonth() + 1;
8906 day = date.getDate();
8907 break;
8908 case '!':
8909 var date = new Date((getNumber('!') - this._ticksTo1970) / 10000);
8910 year = date.getFullYear();
8911 month = date.getMonth() + 1;
8912 day = date.getDate();
8913 break;
8914 case "'":
8915 if (lookAhead("'"))
8916 checkLiteral();
8917 else
8918 literal = true;
8919 break;
8920 default:
8921 checkLiteral();
8922 }
8923 }
8924 if (iValue < value.length){
8925 var extra = value.substr(iValue);
8926 if (!/^\s+/.test(extra)) {
8927 throw "Extra/unparsed characters found in date: " + extra;
8928 }
8929 }
8930 if (year == -1)
8931 year = new Date().getFullYear();
8932 else if (year < 100)
8933 year += new Date().getFullYear() - new Date().getFullYear() % 100 +
8934 (year <= shortYearCutoff ? 0 : -100);
8935 if (doy > -1) {
8936 month = 1;
8937 day = doy;
8938 do {
8939 var dim = this._getDaysInMonth(year, month - 1);
8940 if (day <= dim)
8941 break;
8942 month++;
8943 day -= dim;
8944 } while (true);
8945 }
8946 var date = this._daylightSavingAdjust(new Date(year, month - 1, day));
8947 if (date.getFullYear() != year || date.getMonth() + 1 != month || date.getDate() != day)
8948 throw 'Invalid date'; // E.g. 31/02/00
8949 return date;
8950 },
8951
8952 /* Standard date formats. */
8953 ATOM: 'yy-mm-dd', // RFC 3339 (ISO 8601)
8954 COOKIE: 'D, dd M yy',
8955 ISO_8601: 'yy-mm-dd',
8956 RFC_822: 'D, d M y',
8957 RFC_850: 'DD, dd-M-y',
8958 RFC_1036: 'D, d M y',
8959 RFC_1123: 'D, d M yy',
8960 RFC_2822: 'D, d M yy',
8961 RSS: 'D, d M y', // RFC 822
8962 TICKS: '!',
8963 TIMESTAMP: '@',
8964 W3C: 'yy-mm-dd', // ISO 8601
8965
8966 _ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) +
8967 Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000),
8968
8969 /* Format a date object into a string value.
8970 The format can be combinations of the following:
8971 d - day of month (no leading zero)
8972 dd - day of month (two digit)
8973 o - day of year (no leading zeros)
8974 oo - day of year (three digit)
8975 D - day name short
8976 DD - day name long
8977 m - month of year (no leading zero)
8978 mm - month of year (two digit)
8979 M - month name short
8980 MM - month name long
8981 y - year (two digit)
8982 yy - year (four digit)
8983 @ - Unix timestamp (ms since 01/01/1970)
8984 ! - Windows ticks (100ns since 01/01/0001)
8985 '...' - literal text
8986 '' - single quote
8987
8988 @param format string - the desired format of the date
8989 @param date Date - the date value to format
8990 @param settings Object - attributes include:
8991 dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
8992 dayNames string[7] - names of the days from Sunday (optional)
8993 monthNamesShort string[12] - abbreviated names of the months (optional)
8994 monthNames string[12] - names of the months (optional)
8995 @return string - the date in the above format */
8996 formatDate: function (format, date, settings) {
8997 if (!date)
8998 return '';
8999 var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
9000 var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
9001 var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
9002 var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
9003 // Check whether a format character is doubled
9004 var lookAhead = function(match) {
9005 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
9006 if (matches)
9007 iFormat++;
9008 return matches;
9009 };
9010 // Format a number, with leading zero if necessary
9011 var formatNumber = function(match, value, len) {
9012 var num = '' + value;
9013 if (lookAhead(match))
9014 while (num.length < len)
9015 num = '0' + num;
9016 return num;
9017 };
9018 // Format a name, short or long as requested
9019 var formatName = function(match, value, shortNames, longNames) {
9020 return (lookAhead(match) ? longNames[value] : shortNames[value]);
9021 };
9022 var output = '';
9023 var literal = false;
9024 if (date)
9025 for (var iFormat = 0; iFormat < format.length; iFormat++) {
9026 if (literal)
9027 if (format.charAt(iFormat) == "'" && !lookAhead("'"))
9028 literal = false;
9029 else
9030 output += format.charAt(iFormat);
9031 else
9032 switch (format.charAt(iFormat)) {
9033 case 'd':
9034 output += formatNumber('d', date.getDate(), 2);
9035 break;
9036 case 'D':
9037 output += formatName('D', date.getDay(), dayNamesShort, dayNames);
9038 break;
9039 case 'o':
9040 output += formatNumber('o',
9041 Math.round((new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000), 3);
9042 break;
9043 case 'm':
9044 output += formatNumber('m', date.getMonth() + 1, 2);
9045 break;
9046 case 'M':
9047 output += formatName('M', date.getMonth(), monthNamesShort, monthNames);
9048 break;
9049 case 'y':
9050 output += (lookAhead('y') ? date.getFullYear() :
9051 (date.getYear() % 100 < 10 ? '0' : '') + date.getYear() % 100);
9052 break;
9053 case '@':
9054 output += date.getTime();
9055 break;
9056 case '!':
9057 output += date.getTime() * 10000 + this._ticksTo1970;
9058 break;
9059 case "'":
9060 if (lookAhead("'"))
9061 output += "'";
9062 else
9063 literal = true;
9064 break;
9065 default:
9066 output += format.charAt(iFormat);
9067 }
9068 }
9069 return output;
9070 },
9071
9072 /* Extract all possible characters from the date format. */
9073 _possibleChars: function (format) {
9074 var chars = '';
9075 var literal = false;
9076 // Check whether a format character is doubled
9077 var lookAhead = function(match) {
9078 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
9079 if (matches)
9080 iFormat++;
9081 return matches;
9082 };
9083 for (var iFormat = 0; iFormat < format.length; iFormat++)
9084 if (literal)
9085 if (format.charAt(iFormat) == "'" && !lookAhead("'"))
9086 literal = false;
9087 else
9088 chars += format.charAt(iFormat);
9089 else
9090 switch (format.charAt(iFormat)) {
9091 case 'd': case 'm': case 'y': case '@':
9092 chars += '0123456789';
9093 break;
9094 case 'D': case 'M':
9095 return null; // Accept anything
9096 case "'":
9097 if (lookAhead("'"))
9098 chars += "'";
9099 else
9100 literal = true;
9101 break;
9102 default:
9103 chars += format.charAt(iFormat);
9104 }
9105 return chars;
9106 },
9107
9108 /* Get a setting value, defaulting if necessary. */
9109 _get: function(inst, name) {
9110 return inst.settings[name] !== undefined ?
9111 inst.settings[name] : this._defaults[name];
9112 },
9113
9114 /* Parse existing date and initialise date picker. */
9115 _setDateFromField: function(inst, noDefault) {
9116 if (inst.input.val() == inst.lastVal) {
9117 return;
9118 }
9119 var dateFormat = this._get(inst, 'dateFormat');
9120 var dates = inst.lastVal = inst.input ? inst.input.val() : null;
9121 var date, defaultDate;
9122 date = defaultDate = this._getDefaultDate(inst);
9123 var settings = this._getFormatConfig(inst);
9124 try {
9125 date = this.parseDate(dateFormat, dates, settings) || defaultDate;
9126 } catch (event) {
9127 this.log(event);
9128 dates = (noDefault ? '' : dates);
9129 }
9130 inst.selectedDay = date.getDate();
9131 inst.drawMonth = inst.selectedMonth = date.getMonth();
9132 inst.drawYear = inst.selectedYear = date.getFullYear();
9133 inst.currentDay = (dates ? date.getDate() : 0);
9134 inst.currentMonth = (dates ? date.getMonth() : 0);
9135 inst.currentYear = (dates ? date.getFullYear() : 0);
9136 this._adjustInstDate(inst);
9137 },
9138
9139 /* Retrieve the default date shown on opening. */
9140 _getDefaultDate: function(inst) {
9141 return this._restrictMinMax(inst,
9142 this._determineDate(inst, this._get(inst, 'defaultDate'), new Date()));
9143 },
9144
9145 /* A date may be specified as an exact value or a relative one. */
9146 _determineDate: function(inst, date, defaultDate) {
9147 var offsetNumeric = function(offset) {
9148 var date = new Date();
9149 date.setDate(date.getDate() + offset);
9150 return date;
9151 };
9152 var offsetString = function(offset) {
9153 try {
9154 return $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
9155 offset, $.datepicker._getFormatConfig(inst));
9156 }
9157 catch (e) {
9158 // Ignore
9159 }
9160 var date = (offset.toLowerCase().match(/^c/) ?
9161 $.datepicker._getDate(inst) : null) || new Date();
9162 var year = date.getFullYear();
9163 var month = date.getMonth();
9164 var day = date.getDate();
9165 var pattern = /([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g;
9166 var matches = pattern.exec(offset);
9167 while (matches) {
9168 switch (matches[2] || 'd') {
9169 case 'd' : case 'D' :
9170 day += parseInt(matches[1],10); break;
9171 case 'w' : case 'W' :
9172 day += parseInt(matches[1],10) * 7; break;
9173 case 'm' : case 'M' :
9174 month += parseInt(matches[1],10);
9175 day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
9176 break;
9177 case 'y': case 'Y' :
9178 year += parseInt(matches[1],10);
9179 day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
9180 break;
9181 }
9182 matches = pattern.exec(offset);
9183 }
9184 return new Date(year, month, day);
9185 };
9186 var newDate = (date == null || date === '' ? defaultDate : (typeof date == 'string' ? offsetString(date) :
9187 (typeof date == 'number' ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : new Date(date.getTime()))));
9188 newDate = (newDate && newDate.toString() == 'Invalid Date' ? defaultDate : newDate);
9189 if (newDate) {
9190 newDate.setHours(0);
9191 newDate.setMinutes(0);
9192 newDate.setSeconds(0);
9193 newDate.setMilliseconds(0);
9194 }
9195 return this._daylightSavingAdjust(newDate);
9196 },
9197
9198 /* Handle switch to/from daylight saving.
9199 Hours may be non-zero on daylight saving cut-over:
9200 > 12 when midnight changeover, but then cannot generate
9201 midnight datetime, so jump to 1AM, otherwise reset.
9202 @param date (Date) the date to check
9203 @return (Date) the corrected date */
9204 _daylightSavingAdjust: function(date) {
9205 if (!date) return null;
9206 date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
9207 return date;
9208 },
9209
9210 /* Set the date(s) directly. */
9211 _setDate: function(inst, date, noChange) {
9212 var clear = !date;
9213 var origMonth = inst.selectedMonth;
9214 var origYear = inst.selectedYear;
9215 var newDate = this._restrictMinMax(inst, this._determineDate(inst, date, new Date()));
9216 inst.selectedDay = inst.currentDay = newDate.getDate();
9217 inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth();
9218 inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear();
9219 if ((origMonth != inst.selectedMonth || origYear != inst.selectedYear) && !noChange)
9220 this._notifyChange(inst);
9221 this._adjustInstDate(inst);
9222 if (inst.input) {
9223 inst.input.val(clear ? '' : this._formatDate(inst));
9224 }
9225 },
9226
9227 /* Retrieve the date(s) directly. */
9228 _getDate: function(inst) {
9229 var startDate = (!inst.currentYear || (inst.input && inst.input.val() == '') ? null :
9230 this._daylightSavingAdjust(new Date(
9231 inst.currentYear, inst.currentMonth, inst.currentDay)));
9232 return startDate;
9233 },
9234
9235 /* Generate the HTML for the current state of the date picker. */
9236 _generateHTML: function(inst) {
9237 var today = new Date();
9238 today = this._daylightSavingAdjust(
9239 new Date(today.getFullYear(), today.getMonth(), today.getDate())); // clear time
9240 var isRTL = this._get(inst, 'isRTL');
9241 var showButtonPanel = this._get(inst, 'showButtonPanel');
9242 var hideIfNoPrevNext = this._get(inst, 'hideIfNoPrevNext');
9243 var navigationAsDateFormat = this._get(inst, 'navigationAsDateFormat');
9244 var numMonths = this._getNumberOfMonths(inst);
9245 var showCurrentAtPos = this._get(inst, 'showCurrentAtPos');
9246 var stepMonths = this._get(inst, 'stepMonths');
9247 var isMultiMonth = (numMonths[0] != 1 || numMonths[1] != 1);
9248 var currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) :
9249 new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
9250 var minDate = this._getMinMaxDate(inst, 'min');
9251 var maxDate = this._getMinMaxDate(inst, 'max');
9252 var drawMonth = inst.drawMonth - showCurrentAtPos;
9253 var drawYear = inst.drawYear;
9254 if (drawMonth < 0) {
9255 drawMonth += 12;
9256 drawYear--;
9257 }
9258 if (maxDate) {
9259 var maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),
9260 maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate()));
9261 maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);
9262 while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {
9263 drawMonth--;
9264 if (drawMonth < 0) {
9265 drawMonth = 11;
9266 drawYear--;
9267 }
9268 }
9269 }
9270 inst.drawMonth = drawMonth;
9271 inst.drawYear = drawYear;
9272 var prevText = this._get(inst, 'prevText');
9273 prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText,
9274 this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),
9275 this._getFormatConfig(inst)));
9276 var prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?
9277 '<a class="ui-datepicker-prev ui-corner-all" onclick="DP_jQuery_' + dpuuid +
9278 '.datepicker._adjustDate(\'#' + inst.id + '\', -' + stepMonths + ', \'M\');"' +
9279 ' title="' + prevText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>' :
9280 (hideIfNoPrevNext ? '' : '<a class="ui-datepicker-prev ui-corner-all ui-state-disabled" title="'+ prevText +'"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>'));
9281 var nextText = this._get(inst, 'nextText');
9282 nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText,
9283 this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),
9284 this._getFormatConfig(inst)));
9285 var next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?
9286 '<a class="ui-datepicker-next ui-corner-all" onclick="DP_jQuery_' + dpuuid +
9287 '.datepicker._adjustDate(\'#' + inst.id + '\', +' + stepMonths + ', \'M\');"' +
9288 ' title="' + nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>' :
9289 (hideIfNoPrevNext ? '' : '<a class="ui-datepicker-next ui-corner-all ui-state-disabled" title="'+ nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>'));
9290 var currentText = this._get(inst, 'currentText');
9291 var gotoDate = (this._get(inst, 'gotoCurrent') && inst.currentDay ? currentDate : today);
9292 currentText = (!navigationAsDateFormat ? currentText :
9293 this.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));
9294 var controls = (!inst.inline ? '<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" onclick="DP_jQuery_' + dpuuid +
9295 '.datepicker._hideDatepicker();">' + this._get(inst, 'closeText') + '</button>' : '');
9296 var buttonPanel = (showButtonPanel) ? '<div class="ui-datepicker-buttonpane ui-widget-content">' + (isRTL ? controls : '') +
9297 (this._isInRange(inst, gotoDate) ? '<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" onclick="DP_jQuery_' + dpuuid +
9298 '.datepicker._gotoToday(\'#' + inst.id + '\');"' +
9299 '>' + currentText + '</button>' : '') + (isRTL ? '' : controls) + '</div>' : '';
9300 var firstDay = parseInt(this._get(inst, 'firstDay'),10);
9301 firstDay = (isNaN(firstDay) ? 0 : firstDay);
9302 var showWeek = this._get(inst, 'showWeek');
9303 var dayNames = this._get(inst, 'dayNames');
9304 var dayNamesShort = this._get(inst, 'dayNamesShort');
9305 var dayNamesMin = this._get(inst, 'dayNamesMin');
9306 var monthNames = this._get(inst, 'monthNames');
9307 var monthNamesShort = this._get(inst, 'monthNamesShort');
9308 var beforeShowDay = this._get(inst, 'beforeShowDay');
9309 var showOtherMonths = this._get(inst, 'showOtherMonths');
9310 var selectOtherMonths = this._get(inst, 'selectOtherMonths');
9311 var calculateWeek = this._get(inst, 'calculateWeek') || this.iso8601Week;
9312 var defaultDate = this._getDefaultDate(inst);
9313 var html = '';
9314 for (var row = 0; row < numMonths[0]; row++) {
9315 var group = '';
9316 this.maxRows = 4;
9317 for (var col = 0; col < numMonths[1]; col++) {
9318 var selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay));
9319 var cornerClass = ' ui-corner-all';
9320 var calender = '';
9321 if (isMultiMonth) {
9322 calender += '<div class="ui-datepicker-group';
9323 if (numMonths[1] > 1)
9324 switch (col) {
9325 case 0: calender += ' ui-datepicker-group-first';
9326 cornerClass = ' ui-corner-' + (isRTL ? 'right' : 'left'); break;
9327 case numMonths[1]-1: calender += ' ui-datepicker-group-last';
9328 cornerClass = ' ui-corner-' + (isRTL ? 'left' : 'right'); break;
9329 default: calender += ' ui-datepicker-group-middle'; cornerClass = ''; break;
9330 }
9331 calender += '">';
9332 }
9333 calender += '<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix' + cornerClass + '">' +
9334 (/all|left/.test(cornerClass) && row == 0 ? (isRTL ? next : prev) : '') +
9335 (/all|right/.test(cornerClass) && row == 0 ? (isRTL ? prev : next) : '') +
9336 this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,
9337 row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers
9338 '</div><table class="ui-datepicker-calendar"><thead>' +
9339 '<tr>';
9340 var thead = (showWeek ? '<th class="ui-datepicker-week-col">' + this._get(inst, 'weekHeader') + '</th>' : '');
9341 for (var dow = 0; dow < 7; dow++) { // days of the week
9342 var day = (dow + firstDay) % 7;
9343 thead += '<th' + ((dow + firstDay + 6) % 7 >= 5 ? ' class="ui-datepicker-week-end"' : '') + '>' +
9344 '<span title="' + dayNames[day] + '">' + dayNamesMin[day] + '</span></th>';
9345 }
9346 calender += thead + '</tr></thead><tbody>';
9347 var daysInMonth = this._getDaysInMonth(drawYear, drawMonth);
9348 if (drawYear == inst.selectedYear && drawMonth == inst.selectedMonth)
9349 inst.selectedDay = Math.min(inst.selectedDay, daysInMonth);
9350 var leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;
9351 var curRows = Math.ceil((leadDays + daysInMonth) / 7); // calculate the number of rows to generate
9352 var numRows = (isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows); //If multiple months, use the higher number of rows (see #7043)
9353 this.maxRows = numRows;
9354 var printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
9355 for (var dRow = 0; dRow < numRows; dRow++) { // create date picker rows
9356 calender += '<tr>';
9357 var tbody = (!showWeek ? '' : '<td class="ui-datepicker-week-col">' +
9358 this._get(inst, 'calculateWeek')(printDate) + '</td>');
9359 for (var dow = 0; dow < 7; dow++) { // create date picker days
9360 var daySettings = (beforeShowDay ?
9361 beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, '']);
9362 var otherMonth = (printDate.getMonth() != drawMonth);
9363 var unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] ||
9364 (minDate && printDate < minDate) || (maxDate && printDate > maxDate);
9365 tbody += '<td class="' +
9366 ((dow + firstDay + 6) % 7 >= 5 ? ' ui-datepicker-week-end' : '') + // highlight weekends
9367 (otherMonth ? ' ui-datepicker-other-month' : '') + // highlight days from other months
9368 ((printDate.getTime() == selectedDate.getTime() && drawMonth == inst.selectedMonth && inst._keyEvent) || // user pressed key
9369 (defaultDate.getTime() == printDate.getTime() && defaultDate.getTime() == selectedDate.getTime()) ?
9370 // or defaultDate is current printedDate and defaultDate is selectedDate
9371 ' ' + this._dayOverClass : '') + // highlight selected day
9372 (unselectable ? ' ' + this._unselectableClass + ' ui-state-disabled': '') + // highlight unselectable days
9373 (otherMonth && !showOtherMonths ? '' : ' ' + daySettings[1] + // highlight custom dates
9374 (printDate.getTime() == currentDate.getTime() ? ' ' + this._currentClass : '') + // highlight selected day
9375 (printDate.getTime() == today.getTime() ? ' ui-datepicker-today' : '')) + '"' + // highlight today (if different)
9376 ((!otherMonth || showOtherMonths) && daySettings[2] ? ' title="' + daySettings[2] + '"' : '') + // cell title
9377 (unselectable ? '' : ' onclick="DP_jQuery_' + dpuuid + '.datepicker._selectDay(\'#' +
9378 inst.id + '\',' + printDate.getMonth() + ',' + printDate.getFullYear() + ', this);return false;"') + '>' + // actions
9379 (otherMonth && !showOtherMonths ? '&#xa0;' : // display for other months
9380 (unselectable ? '<span class="ui-state-default">' + printDate.getDate() + '</span>' : '<a class="ui-state-default' +
9381 (printDate.getTime() == today.getTime() ? ' ui-state-highlight' : '') +
9382 (printDate.getTime() == currentDate.getTime() ? ' ui-state-active' : '') + // highlight selected day
9383 (otherMonth ? ' ui-priority-secondary' : '') + // distinguish dates from other months
9384 '" href="#">' + printDate.getDate() + '</a>')) + '</td>'; // display selectable date
9385 printDate.setDate(printDate.getDate() + 1);
9386 printDate = this._daylightSavingAdjust(printDate);
9387 }
9388 calender += tbody + '</tr>';
9389 }
9390 drawMonth++;
9391 if (drawMonth > 11) {
9392 drawMonth = 0;
9393 drawYear++;
9394 }
9395 calender += '</tbody></table>' + (isMultiMonth ? '</div>' +
9396 ((numMonths[0] > 0 && col == numMonths[1]-1) ? '<div class="ui-datepicker-row-break"></div>' : '') : '');
9397 group += calender;
9398 }
9399 html += group;
9400 }
9401 html += buttonPanel + ($.browser.msie && parseInt($.browser.version,10) < 7 && !inst.inline ?
9402 '<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>' : '');
9403 inst._keyEvent = false;
9404 return html;
9405 },
9406
9407 /* Generate the month and year header. */
9408 _generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate,
9409 secondary, monthNames, monthNamesShort) {
9410 var changeMonth = this._get(inst, 'changeMonth');
9411 var changeYear = this._get(inst, 'changeYear');
9412 var showMonthAfterYear = this._get(inst, 'showMonthAfterYear');
9413 var html = '<div class="ui-datepicker-title">';
9414 var monthHtml = '';
9415 // month selection
9416 if (secondary || !changeMonth)
9417 monthHtml += '<span class="ui-datepicker-month">' + monthNames[drawMonth] + '</span>';
9418 else {
9419 var inMinYear = (minDate && minDate.getFullYear() == drawYear);
9420 var inMaxYear = (maxDate && maxDate.getFullYear() == drawYear);
9421 monthHtml += '<select class="ui-datepicker-month" ' +
9422 'onchange="DP_jQuery_' + dpuuid + '.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'M\');" ' +
9423 '>';
9424 for (var month = 0; month < 12; month++) {
9425 if ((!inMinYear || month >= minDate.getMonth()) &&
9426 (!inMaxYear || month <= maxDate.getMonth()))
9427 monthHtml += '<option value="' + month + '"' +
9428 (month == drawMonth ? ' selected="selected"' : '') +
9429 '>' + monthNamesShort[month] + '</option>';
9430 }
9431 monthHtml += '</select>';
9432 }
9433 if (!showMonthAfterYear)
9434 html += monthHtml + (secondary || !(changeMonth && changeYear) ? '&#xa0;' : '');
9435 // year selection
9436 if ( !inst.yearshtml ) {
9437 inst.yearshtml = '';
9438 if (secondary || !changeYear)
9439 html += '<span class="ui-datepicker-year">' + drawYear + '</span>';
9440 else {
9441 // determine range of years to display
9442 var years = this._get(inst, 'yearRange').split(':');
9443 var thisYear = new Date().getFullYear();
9444 var determineYear = function(value) {
9445 var year = (value.match(/c[+-].*/) ? drawYear + parseInt(value.substring(1), 10) :
9446 (value.match(/[+-].*/) ? thisYear + parseInt(value, 10) :
9447 parseInt(value, 10)));
9448 return (isNaN(year) ? thisYear : year);
9449 };
9450 var year = determineYear(years[0]);
9451 var endYear = Math.max(year, determineYear(years[1] || ''));
9452 year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
9453 endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
9454 inst.yearshtml += '<select class="ui-datepicker-year" ' +
9455 'onchange="DP_jQuery_' + dpuuid + '.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'Y\');" ' +
9456 '>';
9457 for (; year <= endYear; year++) {
9458 inst.yearshtml += '<option value="' + year + '"' +
9459 (year == drawYear ? ' selected="selected"' : '') +
9460 '>' + year + '</option>';
9461 }
9462 inst.yearshtml += '</select>';
9463
9464 html += inst.yearshtml;
9465 inst.yearshtml = null;
9466 }
9467 }
9468 html += this._get(inst, 'yearSuffix');
9469 if (showMonthAfterYear)
9470 html += (secondary || !(changeMonth && changeYear) ? '&#xa0;' : '') + monthHtml;
9471 html += '</div>'; // Close datepicker_header
9472 return html;
9473 },
9474
9475 /* Adjust one of the date sub-fields. */
9476 _adjustInstDate: function(inst, offset, period) {
9477 var year = inst.drawYear + (period == 'Y' ? offset : 0);
9478 var month = inst.drawMonth + (period == 'M' ? offset : 0);
9479 var day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) +
9480 (period == 'D' ? offset : 0);
9481 var date = this._restrictMinMax(inst,
9482 this._daylightSavingAdjust(new Date(year, month, day)));
9483 inst.selectedDay = date.getDate();
9484 inst.drawMonth = inst.selectedMonth = date.getMonth();
9485 inst.drawYear = inst.selectedYear = date.getFullYear();
9486 if (period == 'M' || period == 'Y')
9487 this._notifyChange(inst);
9488 },
9489
9490 /* Ensure a date is within any min/max bounds. */
9491 _restrictMinMax: function(inst, date) {
9492 var minDate = this._getMinMaxDate(inst, 'min');
9493 var maxDate = this._getMinMaxDate(inst, 'max');
9494 var newDate = (minDate && date < minDate ? minDate : date);
9495 newDate = (maxDate && newDate > maxDate ? maxDate : newDate);
9496 return newDate;
9497 },
9498
9499 /* Notify change of month/year. */
9500 _notifyChange: function(inst) {
9501 var onChange = this._get(inst, 'onChangeMonthYear');
9502 if (onChange)
9503 onChange.apply((inst.input ? inst.input[0] : null),
9504 [inst.selectedYear, inst.selectedMonth + 1, inst]);
9505 },
9506
9507 /* Determine the number of months to show. */
9508 _getNumberOfMonths: function(inst) {
9509 var numMonths = this._get(inst, 'numberOfMonths');
9510 return (numMonths == null ? [1, 1] : (typeof numMonths == 'number' ? [1, numMonths] : numMonths));
9511 },
9512
9513 /* Determine the current maximum date - ensure no time components are set. */
9514 _getMinMaxDate: function(inst, minMax) {
9515 return this._determineDate(inst, this._get(inst, minMax + 'Date'), null);
9516 },
9517
9518 /* Find the number of days in a given month. */
9519 _getDaysInMonth: function(year, month) {
9520 return 32 - this._daylightSavingAdjust(new Date(year, month, 32)).getDate();
9521 },
9522
9523 /* Find the day of the week of the first of a month. */
9524 _getFirstDayOfMonth: function(year, month) {
9525 return new Date(year, month, 1).getDay();
9526 },
9527
9528 /* Determines if we should allow a "next/prev" month display change. */
9529 _canAdjustMonth: function(inst, offset, curYear, curMonth) {
9530 var numMonths = this._getNumberOfMonths(inst);
9531 var date = this._daylightSavingAdjust(new Date(curYear,
9532 curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1));
9533 if (offset < 0)
9534 date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
9535 return this._isInRange(inst, date);
9536 },
9537
9538 /* Is the given date in the accepted range? */
9539 _isInRange: function(inst, date) {
9540 var minDate = this._getMinMaxDate(inst, 'min');
9541 var maxDate = this._getMinMaxDate(inst, 'max');
9542 return ((!minDate || date.getTime() >= minDate.getTime()) &&
9543 (!maxDate || date.getTime() <= maxDate.getTime()));
9544 },
9545
9546 /* Provide the configuration settings for formatting/parsing. */
9547 _getFormatConfig: function(inst) {
9548 var shortYearCutoff = this._get(inst, 'shortYearCutoff');
9549 shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff :
9550 new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
9551 return {shortYearCutoff: shortYearCutoff,
9552 dayNamesShort: this._get(inst, 'dayNamesShort'), dayNames: this._get(inst, 'dayNames'),
9553 monthNamesShort: this._get(inst, 'monthNamesShort'), monthNames: this._get(inst, 'monthNames')};
9554 },
9555
9556 /* Format the given date for display. */
9557 _formatDate: function(inst, day, month, year) {
9558 if (!day) {
9559 inst.currentDay = inst.selectedDay;
9560 inst.currentMonth = inst.selectedMonth;
9561 inst.currentYear = inst.selectedYear;
9562 }
9563 var date = (day ? (typeof day == 'object' ? day :
9564 this._daylightSavingAdjust(new Date(year, month, day))) :
9565 this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
9566 return this.formatDate(this._get(inst, 'dateFormat'), date, this._getFormatConfig(inst));
9567 }
9568 });
9569
9570 /*
9571 * Bind hover events for datepicker elements.
9572 * Done via delegate so the binding only occurs once in the lifetime of the parent div.
9573 * Global instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker.
9574 */
9575 function bindHover(dpDiv) {
9576 var selector = 'button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a';
9577 return dpDiv.delegate(selector, 'mouseout', function() {
9578 $(this).removeClass('ui-state-hover');
9579 if (this.className.indexOf('ui-datepicker-prev') != -1) $(this).removeClass('ui-datepicker-prev-hover');
9580 if (this.className.indexOf('ui-datepicker-next') != -1) $(this).removeClass('ui-datepicker-next-hover');
9581 })
9582 .delegate(selector, 'mouseover', function(){
9583 if (!$.datepicker._isDisabledDatepicker( instActive.inline ? dpDiv.parent()[0] : instActive.input[0])) {
9584 $(this).parents('.ui-datepicker-calendar').find('a').removeClass('ui-state-hover');
9585 $(this).addClass('ui-state-hover');
9586 if (this.className.indexOf('ui-datepicker-prev') != -1) $(this).addClass('ui-datepicker-prev-hover');
9587 if (this.className.indexOf('ui-datepicker-next') != -1) $(this).addClass('ui-datepicker-next-hover');
9588 }
9589 });
9590 }
9591
9592 /* jQuery extend now ignores nulls! */
9593 function extendRemove(target, props) {
9594 $.extend(target, props);
9595 for (var name in props)
9596 if (props[name] == null || props[name] == undefined)
9597 target[name] = props[name];
9598 return target;
9599 };
9600
9601 /* Determine whether an object is an array. */
9602 function isArray(a) {
9603 return (a && (($.browser.safari && typeof a == 'object' && a.length) ||
9604 (a.constructor && a.constructor.toString().match(/\Array\(\)/))));
9605 };
9606
9607 /* Invoke the datepicker functionality.
9608 @param options string - a command, optionally followed by additional parameters or
9609 Object - settings for attaching new datepicker functionality
9610 @return jQuery object */
9611 $.fn.datepicker = function(options){
9612
9613 /* Verify an empty collection wasn't passed - Fixes #6976 */
9614 if ( !this.length ) {
9615 return this;
9616 }
9617
9618 /* Initialise the date picker. */
9619 if (!$.datepicker.initialized) {
9620 $(document).mousedown($.datepicker._checkExternalClick).
9621 find('body').append($.datepicker.dpDiv);
9622 $.datepicker.initialized = true;
9623 }
9624
9625 var otherArgs = Array.prototype.slice.call(arguments, 1);
9626 if (typeof options == 'string' && (options == 'isDisabled' || options == 'getDate' || options == 'widget'))
9627 return $.datepicker['_' + options + 'Datepicker'].
9628 apply($.datepicker, [this[0]].concat(otherArgs));
9629 if (options == 'option' && arguments.length == 2 && typeof arguments[1] == 'string')
9630 return $.datepicker['_' + options + 'Datepicker'].
9631 apply($.datepicker, [this[0]].concat(otherArgs));
9632 return this.each(function() {
9633 typeof options == 'string' ?
9634 $.datepicker['_' + options + 'Datepicker'].
9635 apply($.datepicker, [this].concat(otherArgs)) :
9636 $.datepicker._attachDatepicker(this, options);
9637 });
9638 };
9639
9640 $.datepicker = new Datepicker(); // singleton instance
9641 $.datepicker.initialized = false;
9642 $.datepicker.uuid = new Date().getTime();
9643 $.datepicker.version = "@VERSION";
9644
9645 // Workaround for #4055
9646 // Add another global to avoid noConflict issues with inline event handlers
9647 window['DP_jQuery_' + dpuuid] = $;
9648
9649 })(jQuery);
9650 /*
9651 * jQuery UI Dialog @VERSION
9652 *
9653 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
9654 * Dual licensed under the MIT or GPL Version 2 licenses.
9655 * http://jquery.org/license
9656 *
9657 * http://docs.jquery.com/UI/Dialog
9658 *
9659 * Depends:
9660 * jquery.ui.core.js
9661 * jquery.ui.widget.js
9662 * jquery.ui.button.js
9663 * jquery.ui.draggable.js
9664 * jquery.ui.mouse.js
9665 * jquery.ui.position.js
9666 * jquery.ui.resizable.js
9667 */
9668 (function( $, undefined ) {
9669
9670 var uiDialogClasses = "ui-dialog ui-widget ui-widget-content ui-corner-all ",
9671 sizeRelatedOptions = {
9672 buttons: true,
9673 height: true,
9674 maxHeight: true,
9675 maxWidth: true,
9676 minHeight: true,
9677 minWidth: true,
9678 width: true
9679 },
9680 resizableRelatedOptions = {
9681 maxHeight: true,
9682 maxWidth: true,
9683 minHeight: true,
9684 minWidth: true
9685 };
9686
9687 $.widget("ui.dialog", {
9688 version: "@VERSION",
9689 options: {
9690 autoOpen: true,
9691 buttons: {},
9692 closeOnEscape: true,
9693 closeText: "close",
9694 dialogClass: "",
9695 draggable: true,
9696 hide: null,
9697 height: "auto",
9698 maxHeight: false,
9699 maxWidth: false,
9700 minHeight: 150,
9701 minWidth: 150,
9702 modal: false,
9703 position: {
9704 my: "center",
9705 at: "center",
9706 of: window,
9707 collision: "fit",
9708 // ensure that the titlebar is never outside the document
9709 using: function( pos ) {
9710 var topOffset = $( this ).css( pos ).offset().top;
9711 if ( topOffset < 0 ) {
9712 $( this ).css( "top", pos.top - topOffset );
9713 }
9714 }
9715 },
9716 resizable: true,
9717 show: null,
9718 stack: true,
9719 title: "",
9720 width: 300,
9721 zIndex: 1000
9722 },
9723
9724 _create: function() {
9725 this.originalTitle = this.element.attr( "title" );
9726 // #5742 - .attr() might return a DOMElement
9727 if ( typeof this.originalTitle !== "string" ) {
9728 this.originalTitle = "";
9729 }
9730 this.oldPosition = {
9731 parent: this.element.parent(),
9732 index: this.element.parent().children().index( this.element )
9733 };
9734 this.options.title = this.options.title || this.originalTitle;
9735 var self = this,
9736 options = self.options,
9737
9738 title = options.title || "&#160;",
9739 titleId = $.ui.dialog.getTitleId( self.element ),
9740
9741 uiDialog = ( self.uiDialog = $( "<div>" ) )
9742 .addClass( uiDialogClasses + options.dialogClass )
9743 .css({
9744 display: "none",
9745 outline: 0, // TODO: move to stylesheet
9746 zIndex: options.zIndex
9747 })
9748 // setting tabIndex makes the div focusable
9749 .attr( "tabIndex", -1)
9750 .keydown(function( event ) {
9751 if ( options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode &&
9752 event.keyCode === $.ui.keyCode.ESCAPE ) {
9753 self.close( event );
9754 event.preventDefault();
9755 }
9756 })
9757 .attr({
9758 role: "dialog",
9759 "aria-labelledby": titleId
9760 })
9761 .mousedown(function( event ) {
9762 self.moveToTop( false, event );
9763 })
9764 .appendTo( "body" ),
9765
9766 uiDialogContent = self.element
9767 .show()
9768 .removeAttr( "title" )
9769 .addClass( "ui-dialog-content ui-widget-content" )
9770 .appendTo( uiDialog ),
9771
9772 uiDialogTitlebar = ( self.uiDialogTitlebar = $( "<div>" ) )
9773 .addClass( "ui-dialog-titlebar ui-widget-header " +
9774 "ui-corner-all ui-helper-clearfix" )
9775 .prependTo( uiDialog ),
9776
9777 uiDialogTitlebarClose = $( "<a href='#'></a>" )
9778 .addClass( "ui-dialog-titlebar-close ui-corner-all" )
9779 .attr( "role", "button" )
9780 .click(function( event ) {
9781 event.preventDefault();
9782 self.close( event );
9783 })
9784 .appendTo( uiDialogTitlebar ),
9785
9786 uiDialogTitlebarCloseText = ( self.uiDialogTitlebarCloseText = $( "<span>" ) )
9787 .addClass( "ui-icon ui-icon-closethick" )
9788 .text( options.closeText )
9789 .appendTo( uiDialogTitlebarClose ),
9790
9791 uiDialogTitle = $( "<span>" )
9792 .addClass( "ui-dialog-title" )
9793 .attr( "id", titleId )
9794 .html( title )
9795 .prependTo( uiDialogTitlebar );
9796
9797 uiDialogTitlebar.find( "*" ).add( uiDialogTitlebar ).disableSelection();
9798 this._hoverable( uiDialogTitlebarClose );
9799 this._focusable( uiDialogTitlebarClose );
9800
9801 if ( options.draggable && $.fn.draggable ) {
9802 self._makeDraggable();
9803 }
9804 if ( options.resizable && $.fn.resizable ) {
9805 self._makeResizable();
9806 }
9807
9808 self._createButtons( options.buttons );
9809 self._isOpen = false;
9810
9811 if ( $.fn.bgiframe ) {
9812 uiDialog.bgiframe();
9813 }
9814 },
9815
9816 _init: function() {
9817 if ( this.options.autoOpen ) {
9818 this.open();
9819 }
9820 },
9821
9822 _destroy: function() {
9823 var self = this, next,
9824 oldPosition = this.oldPosition;
9825
9826 if ( self.overlay ) {
9827 self.overlay.destroy();
9828 }
9829 self.uiDialog.hide();
9830 self.element
9831 .removeClass( "ui-dialog-content ui-widget-content" )
9832 .hide()
9833 .appendTo( "body" );
9834 self.uiDialog.remove();
9835
9836 if ( self.originalTitle ) {
9837 self.element.attr( "title", self.originalTitle );
9838 }
9839
9840 next = oldPosition.parent.children().eq( oldPosition.index );
9841 if ( next.length ) {
9842 next.before( self.element );
9843 } else {
9844 oldPosition.parent.append( self.element );
9845 }
9846 },
9847
9848 widget: function() {
9849 return this.uiDialog;
9850 },
9851
9852 close: function( event ) {
9853 if ( !this._isOpen ) {
9854 return self;
9855 }
9856
9857 var self = this,
9858 maxZ, thisZ;
9859
9860 if ( false === self._trigger( "beforeClose", event ) ) {
9861 return;
9862 }
9863
9864 self._isOpen = false;
9865
9866 if ( self.overlay ) {
9867 self.overlay.destroy();
9868 }
9869 self.uiDialog.unbind( "keypress.ui-dialog" );
9870
9871 if ( self.options.hide ) {
9872 self.uiDialog.hide( self.options.hide, function() {
9873 self._trigger( "close", event );
9874 });
9875 } else {
9876 self.uiDialog.hide();
9877 self._trigger( "close", event );
9878 }
9879
9880 $.ui.dialog.overlay.resize();
9881
9882 // adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
9883 if ( self.options.modal ) {
9884 maxZ = 0;
9885 $( ".ui-dialog" ).each(function() {
9886 if ( this !== self.uiDialog[0] ) {
9887 thisZ = $( this ).css( "z-index" );
9888 if ( !isNaN( thisZ ) ) {
9889 maxZ = Math.max( maxZ, thisZ );
9890 }
9891 }
9892 });
9893 $.ui.dialog.maxZ = maxZ;
9894 }
9895
9896 return self;
9897 },
9898
9899 isOpen: function() {
9900 return this._isOpen;
9901 },
9902
9903 // the force parameter allows us to move modal dialogs to their correct
9904 // position on open
9905 moveToTop: function( force, event ) {
9906 var self = this,
9907 options = self.options,
9908 saveScroll;
9909
9910 if ( ( options.modal && !force ) ||
9911 ( !options.stack && !options.modal ) ) {
9912 return self._trigger( "focus", event );
9913 }
9914
9915 if ( options.zIndex > $.ui.dialog.maxZ ) {
9916 $.ui.dialog.maxZ = options.zIndex;
9917 }
9918 if ( self.overlay ) {
9919 $.ui.dialog.maxZ += 1;
9920 $.ui.dialog.overlay.maxZ = $.ui.dialog.maxZ;
9921 self.overlay.$el.css( "z-index", $.ui.dialog.overlay.maxZ );
9922 }
9923
9924 // Save and then restore scroll
9925 // Opera 9.5+ resets when parent z-index is changed.
9926 // http://bugs.jqueryui.com/ticket/3193
9927 saveScroll = {
9928 scrollTop: self.element.scrollTop(),
9929 scrollLeft: self.element.scrollLeft()
9930 };
9931 $.ui.dialog.maxZ += 1;
9932 self.uiDialog.css( "z-index", $.ui.dialog.maxZ );
9933 self.element.attr( saveScroll );
9934 self._trigger( "focus", event );
9935
9936 return self;
9937 },
9938
9939 open: function() {
9940 if ( this._isOpen ) {
9941 return;
9942 }
9943
9944 var self = this,
9945 options = self.options,
9946 uiDialog = self.uiDialog;
9947
9948 self._size();
9949 self._position( options.position );
9950 uiDialog.show( options.show );
9951 self.overlay = options.modal ? new $.ui.dialog.overlay( self ) : null;
9952 self.moveToTop( true );
9953
9954 // prevent tabbing out of modal dialogs
9955 if ( options.modal ) {
9956 uiDialog.bind( "keydown.ui-dialog", function( event ) {
9957 if ( event.keyCode !== $.ui.keyCode.TAB ) {
9958 return;
9959 }
9960
9961 var tabbables = $( ":tabbable", this ),
9962 first = tabbables.filter( ":first" ),
9963 last = tabbables.filter( ":last" );
9964
9965 if ( event.target === last[0] && !event.shiftKey ) {
9966 first.focus( 1 );
9967 return false;
9968 } else if ( event.target === first[0] && event.shiftKey ) {
9969 last.focus( 1 );
9970 return false;
9971 }
9972 });
9973 }
9974
9975 // set focus to the first tabbable element in the content area or the first button
9976 // if there are no tabbable elements, set focus on the dialog itself
9977 var hasFocus = self.element.find( ":tabbable" );
9978 if ( !hasFocus.length ) {
9979 hasFocus = uiDialog.find( ".ui-dialog-buttonpane :tabbable" );
9980 if ( !hasFocus.length ) {
9981 hasFocus = uiDialog;
9982 }
9983 }
9984 hasFocus.eq( 0 ).focus();
9985
9986 self._isOpen = true;
9987 self._trigger( "open" );
9988
9989 return self;
9990 },
9991
9992 _createButtons: function( buttons ) {
9993 var self = this,
9994 hasButtons = false;
9995
9996 // if we already have a button pane, remove it
9997 self.uiDialog.find( ".ui-dialog-buttonpane" ).remove();
9998
9999 if ( typeof buttons === "object" && buttons !== null ) {
10000 $.each( buttons, function() {
10001 return !(hasButtons = true);
10002 });
10003 }
10004 if ( hasButtons ) {
10005 var uiDialogButtonPane = $( "<div>" )
10006 .addClass( "ui-dialog-buttonpane ui-widget-content ui-helper-clearfix" ),
10007 uiButtonSet = $( "<div>" )
10008 .addClass( "ui-dialog-buttonset" )
10009 .appendTo( uiDialogButtonPane );
10010
10011 $.each( buttons, function( name, props ) {
10012 props = $.isFunction( props ) ?
10013 { click: props, text: name } :
10014 props;
10015 var button = $( "<button type='button'>" )
10016 .attr( props, true )
10017 .unbind( "click" )
10018 .click(function() {
10019 props.click.apply( self.element[0], arguments );
10020 })
10021 .appendTo( uiButtonSet );
10022 if ( $.fn.button ) {
10023 button.button();
10024 }
10025 });
10026 self.uiDialog.addClass( "ui-dialog-buttons" );
10027 uiDialogButtonPane.appendTo( self.uiDialog );
10028 } else {
10029 self.uiDialog.removeClass( "ui-dialog-buttons" );
10030 }
10031 },
10032
10033 _makeDraggable: function() {
10034 var self = this,
10035 options = self.options;
10036
10037 function filteredUi( ui ) {
10038 return {
10039 position: ui.position,
10040 offset: ui.offset
10041 };
10042 }
10043
10044 self.uiDialog.draggable({
10045 cancel: ".ui-dialog-content, .ui-dialog-titlebar-close",
10046 handle: ".ui-dialog-titlebar",
10047 containment: "document",
10048 start: function( event, ui ) {
10049 $( this )
10050 .addClass( "ui-dialog-dragging" );
10051 self._trigger( "dragStart", event, filteredUi( ui ) );
10052 },
10053 drag: function( event, ui ) {
10054 self._trigger( "drag", event, filteredUi( ui ) );
10055 },
10056 stop: function( event, ui ) {
10057 options.position = [
10058 ui.position.left - self.document.scrollLeft(),
10059 ui.position.top - self.document.scrollTop()
10060 ];
10061 $( this )
10062 .removeClass( "ui-dialog-dragging" );
10063 self._trigger( "dragStop", event, filteredUi( ui ) );
10064 $.ui.dialog.overlay.resize();
10065 }
10066 });
10067 },
10068
10069 _makeResizable: function( handles ) {
10070 handles = (handles === undefined ? this.options.resizable : handles);
10071 var self = this,
10072 options = self.options,
10073 // .ui-resizable has position: relative defined in the stylesheet
10074 // but dialogs have to use absolute or fixed positioning
10075 position = self.uiDialog.css( "position" ),
10076 resizeHandles = typeof handles === 'string' ?
10077 handles :
10078 "n,e,s,w,se,sw,ne,nw";
10079
10080 function filteredUi( ui ) {
10081 return {
10082 originalPosition: ui.originalPosition,
10083 originalSize: ui.originalSize,
10084 position: ui.position,
10085 size: ui.size
10086 };
10087 }
10088
10089 self.uiDialog.resizable({
10090 cancel: ".ui-dialog-content",
10091 containment: "document",
10092 alsoResize: self.element,
10093 maxWidth: options.maxWidth,
10094 maxHeight: options.maxHeight,
10095 minWidth: options.minWidth,
10096 minHeight: self._minHeight(),
10097 handles: resizeHandles,
10098 start: function( event, ui ) {
10099 $( this ).addClass( "ui-dialog-resizing" );
10100 self._trigger( "resizeStart", event, filteredUi( ui ) );
10101 },
10102 resize: function( event, ui ) {
10103 self._trigger( "resize", event, filteredUi( ui ) );
10104 },
10105 stop: function( event, ui ) {
10106 $( this ).removeClass( "ui-dialog-resizing" );
10107 options.height = $( this ).height();
10108 options.width = $( this ).width();
10109 self._trigger( "resizeStop", event, filteredUi( ui ) );
10110 $.ui.dialog.overlay.resize();
10111 }
10112 })
10113 .css( "position", position )
10114 .find( ".ui-resizable-se" )
10115 .addClass( "ui-icon ui-icon-grip-diagonal-se" );
10116 },
10117
10118 _minHeight: function() {
10119 var options = this.options;
10120
10121 if ( options.height === "auto" ) {
10122 return options.minHeight;
10123 } else {
10124 return Math.min( options.minHeight, options.height );
10125 }
10126 },
10127
10128 _position: function( position ) {
10129 var myAt = [],
10130 offset = [ 0, 0 ],
10131 isVisible;
10132
10133 if ( position ) {
10134 // deep extending converts arrays to objects in jQuery <= 1.3.2 :-(
10135 // if (typeof position == 'string' || $.isArray(position)) {
10136 // myAt = $.isArray(position) ? position : position.split(' ');
10137
10138 if ( typeof position === "string" || (typeof position === "object" && "0" in position ) ) {
10139 myAt = position.split ? position.split( " " ) : [ position[ 0 ], position[ 1 ] ];
10140 if ( myAt.length === 1 ) {
10141 myAt[ 1 ] = myAt[ 0 ];
10142 }
10143
10144 $.each( [ "left", "top" ], function( i, offsetPosition ) {
10145 if ( +myAt[ i ] === myAt[ i ] ) {
10146 offset[ i ] = myAt[ i ];
10147 myAt[ i ] = offsetPosition;
10148 }
10149 });
10150
10151 position = {
10152 my: myAt.join( " " ),
10153 at: myAt.join( " " ),
10154 offset: offset.join( " " )
10155 };
10156 }
10157
10158 position = $.extend( {}, $.ui.dialog.prototype.options.position, position );
10159 } else {
10160 position = $.ui.dialog.prototype.options.position;
10161 }
10162
10163 // need to show the dialog to get the actual offset in the position plugin
10164 isVisible = this.uiDialog.is( ":visible" );
10165 if ( !isVisible ) {
10166 this.uiDialog.show();
10167 }
10168 this.uiDialog.position( position );
10169 if ( !isVisible ) {
10170 this.uiDialog.hide();
10171 }
10172 },
10173
10174 _setOptions: function( options ) {
10175 var self = this,
10176 resizableOptions = {},
10177 resize = false;
10178
10179 $.each( options, function( key, value ) {
10180 self._setOption( key, value );
10181
10182 if ( key in sizeRelatedOptions ) {
10183 resize = true;
10184 }
10185 if ( key in resizableRelatedOptions ) {
10186 resizableOptions[ key ] = value;
10187 }
10188 });
10189
10190 if ( resize ) {
10191 this._size();
10192 }
10193 if ( this.uiDialog.is( ":data(resizable)" ) ) {
10194 this.uiDialog.resizable( "option", resizableOptions );
10195 }
10196 },
10197
10198 _setOption: function( key, value ) {
10199 var self = this,
10200 uiDialog = self.uiDialog;
10201
10202 switch ( key ) {
10203 case "buttons":
10204 self._createButtons( value );
10205 break;
10206 case "closeText":
10207 // ensure that we always pass a string
10208 self.uiDialogTitlebarCloseText.text( "" + value );
10209 break;
10210 case "dialogClass":
10211 uiDialog
10212 .removeClass( self.options.dialogClass )
10213 .addClass( uiDialogClasses + value );
10214 break;
10215 case "disabled":
10216 if ( value ) {
10217 uiDialog.addClass( "ui-dialog-disabled" );
10218 } else {
10219 uiDialog.removeClass( "ui-dialog-disabled" );
10220 }
10221 break;
10222 case "draggable":
10223 var isDraggable = uiDialog.is( ":data(draggable)" );
10224 if ( isDraggable && !value ) {
10225 uiDialog.draggable( "destroy" );
10226 }
10227
10228 if ( !isDraggable && value ) {
10229 self._makeDraggable();
10230 }
10231 break;
10232 case "position":
10233 self._position( value );
10234 break;
10235 case "resizable":
10236 // currently resizable, becoming non-resizable
10237 var isResizable = uiDialog.is( ":data(resizable)" );
10238 if ( isResizable && !value ) {
10239 uiDialog.resizable( "destroy" );
10240 }
10241
10242 // currently resizable, changing handles
10243 if ( isResizable && typeof value === "string" ) {
10244 uiDialog.resizable( "option", "handles", value );
10245 }
10246
10247 // currently non-resizable, becoming resizable
10248 if ( !isResizable && value !== false ) {
10249 self._makeResizable( value );
10250 }
10251 break;
10252 case "title":
10253 // convert whatever was passed in o a string, for html() to not throw up
10254 $( ".ui-dialog-title", self.uiDialogTitlebar )
10255 .html( "" + ( value || "&#160;" ) );
10256 break;
10257 }
10258
10259 this._super( key, value );
10260 },
10261
10262 _size: function() {
10263 /* If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
10264 * divs will both have width and height set, so we need to reset them
10265 */
10266 var options = this.options,
10267 nonContentHeight,
10268 minContentHeight,
10269 isVisible = this.uiDialog.is( ":visible" );
10270
10271 // reset content sizing
10272 this.element.show().css({
10273 width: "auto",
10274 minHeight: 0,
10275 height: 0
10276 });
10277
10278 if ( options.minWidth > options.width ) {
10279 options.width = options.minWidth;
10280 }
10281
10282 // reset wrapper sizing
10283 // determine the height of all the non-content elements
10284 nonContentHeight = this.uiDialog.css({
10285 height: "auto",
10286 width: options.width
10287 })
10288 .outerHeight();
10289 minContentHeight = Math.max( 0, options.minHeight - nonContentHeight );
10290
10291 if ( options.height === "auto" ) {
10292 // only needed for IE6 support
10293 if ( $.support.minHeight ) {
10294 this.element.css({
10295 minHeight: minContentHeight,
10296 height: "auto"
10297 });
10298 } else {
10299 this.uiDialog.show();
10300 var autoHeight = this.element.css( "height", "auto" ).height();
10301 if ( !isVisible ) {
10302 this.uiDialog.hide();
10303 }
10304 this.element.height( Math.max( autoHeight, minContentHeight ) );
10305 }
10306 } else {
10307 this.element.height( Math.max( options.height - nonContentHeight, 0 ) );
10308 }
10309
10310 if (this.uiDialog.is( ":data(resizable)" ) ) {
10311 this.uiDialog.resizable( "option", "minHeight", this._minHeight() );
10312 }
10313 }
10314 });
10315
10316 $.extend($.ui.dialog, {
10317 uuid: 0,
10318 maxZ: 0,
10319
10320 getTitleId: function($el) {
10321 var id = $el.attr( "id" );
10322 if ( !id ) {
10323 this.uuid += 1;
10324 id = this.uuid;
10325 }
10326 return "ui-dialog-title-" + id;
10327 },
10328
10329 overlay: function( dialog ) {
10330 this.$el = $.ui.dialog.overlay.create( dialog );
10331 }
10332 });
10333
10334 $.extend( $.ui.dialog.overlay, {
10335 instances: [],
10336 // reuse old instances due to IE memory leak with alpha transparency (see #5185)
10337 oldInstances: [],
10338 maxZ: 0,
10339 events: $.map(
10340 "focus,mousedown,mouseup,keydown,keypress,click".split( "," ),
10341 function( event ) {
10342 return event + ".dialog-overlay";
10343 }
10344 ).join( " " ),
10345 create: function( dialog ) {
10346 if ( this.instances.length === 0 ) {
10347 // prevent use of anchors and inputs
10348 // we use a setTimeout in case the overlay is created from an
10349 // event that we're going to be cancelling (see #2804)
10350 setTimeout(function() {
10351 // handle $(el).dialog().dialog('close') (see #4065)
10352 if ( $.ui.dialog.overlay.instances.length ) {
10353 $( document ).bind( $.ui.dialog.overlay.events, function( event ) {
10354 // stop events if the z-index of the target is < the z-index of the overlay
10355 // we cannot return true when we don't want to cancel the event (#3523)
10356 if ( $( event.target ).zIndex() < $.ui.dialog.overlay.maxZ ) {
10357 return false;
10358 }
10359 });
10360 }
10361 }, 1 );
10362
10363 // allow closing by pressing the escape key
10364 $( document ).bind( "keydown.dialog-overlay", function( event ) {
10365 if ( dialog.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode &&
10366 event.keyCode === $.ui.keyCode.ESCAPE ) {
10367
10368 dialog.close( event );
10369 event.preventDefault();
10370 }
10371 });
10372
10373 // handle window resize
10374 $( window ).bind( "resize.dialog-overlay", $.ui.dialog.overlay.resize );
10375 }
10376
10377 var $el = ( this.oldInstances.pop() || $( "<div>" ).addClass( "ui-widget-overlay" ) );
10378 $el.appendTo( document.body ).css({
10379 width: this.width(),
10380 height: this.height()
10381 });
10382
10383 if ( $.fn.bgiframe ) {
10384 $el.bgiframe();
10385 }
10386
10387 this.instances.push( $el );
10388 return $el;
10389 },
10390
10391 destroy: function( $el ) {
10392 var indexOf = $.inArray( $el, this.instances );
10393 if ( indexOf !== -1 ) {
10394 this.oldInstances.push( this.instances.splice( indexOf, 1 )[ 0 ] );
10395 }
10396
10397 if ( this.instances.length === 0 ) {
10398 $( [ document, window ] ).unbind( ".dialog-overlay" );
10399 }
10400
10401 $el.height( 0 ).width( 0 ).remove();
10402
10403 // adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
10404 var maxZ = 0;
10405 $.each( this.instances, function() {
10406 maxZ = Math.max( maxZ, this.css( "z-index" ) );
10407 });
10408 this.maxZ = maxZ;
10409 },
10410
10411 height: function() {
10412 var scrollHeight,
10413 offsetHeight;
10414 // handle IE
10415 if ( $.browser.msie ) {
10416 scrollHeight = Math.max(
10417 document.documentElement.scrollHeight,
10418 document.body.scrollHeight
10419 );
10420 offsetHeight = Math.max(
10421 document.documentElement.offsetHeight,
10422 document.body.offsetHeight
10423 );
10424
10425 if ( scrollHeight < offsetHeight ) {
10426 return $( window ).height() + "px";
10427 } else {
10428 return scrollHeight + "px";
10429 }
10430 // handle "good" browsers
10431 } else {
10432 return $( document ).height() + "px";
10433 }
10434 },
10435
10436 width: function() {
10437 var scrollWidth,
10438 offsetWidth;
10439 // handle IE
10440 if ( $.browser.msie ) {
10441 scrollWidth = Math.max(
10442 document.documentElement.scrollWidth,
10443 document.body.scrollWidth
10444 );
10445 offsetWidth = Math.max(
10446 document.documentElement.offsetWidth,
10447 document.body.offsetWidth
10448 );
10449
10450 if ( scrollWidth < offsetWidth ) {
10451 return $( window ).width() + "px";
10452 } else {
10453 return scrollWidth + "px";
10454 }
10455 // handle "good" browsers
10456 } else {
10457 return $( document ).width() + "px";
10458 }
10459 },
10460
10461 resize: function() {
10462 /* If the dialog is draggable and the user drags it past the
10463 * right edge of the window, the document becomes wider so we
10464 * need to stretch the overlay. If the user then drags the
10465 * dialog back to the left, the document will become narrower,
10466 * so we need to shrink the overlay to the appropriate size.
10467 * This is handled by shrinking the overlay before setting it
10468 * to the full document size.
10469 */
10470 var $overlays = $( [] );
10471 $.each( $.ui.dialog.overlay.instances, function() {
10472 $overlays = $overlays.add( this );
10473 });
10474
10475 $overlays.css({
10476 width: 0,
10477 height: 0
10478 }).css({
10479 width: $.ui.dialog.overlay.width(),
10480 height: $.ui.dialog.overlay.height()
10481 });
10482 }
10483 });
10484
10485 $.extend( $.ui.dialog.overlay.prototype, {
10486 destroy: function() {
10487 $.ui.dialog.overlay.destroy( this.$el );
10488 }
10489 });
10490
10491 }( jQuery ) );
10492 /*
10493 * jQuery UI Menu @VERSION
10494 *
10495 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
10496 * Dual licensed under the MIT or GPL Version 2 licenses.
10497 * http://jquery.org/license
10498 *
10499 * http://docs.jquery.com/UI/Menu
10500 *
10501 * Depends:
10502 * jquery.ui.core.js
10503 * jquery.ui.widget.js
10504 */
10505 (function($) {
10506
10507 var idIncrement = 0;
10508
10509 $.widget( "ui.menu", {
10510 version: "@VERSION",
10511 defaultElement: "<ul>",
10512 delay: 300,
10513 options: {
10514 menus: "ul",
10515 position: {
10516 my: "left top",
10517 at: "right top"
10518 },
10519 trigger: null
10520 },
10521 _create: function() {
10522 this.activeMenu = this.element;
10523 this.menuId = this.element.attr( "id" ) || "ui-menu-" + idIncrement++;
10524 if ( this.element.find( ".ui-icon" ).length ) {
10525 this.element.addClass( "ui-menu-icons" );
10526 }
10527 this.element
10528 .addClass( "ui-menu ui-widget ui-widget-content ui-corner-all" )
10529 .attr({
10530 id: this.menuId,
10531 role: "menu"
10532 })
10533 // need to catch all clicks on disabled menu
10534 // not possible through _bind
10535 .bind( "click.menu", $.proxy( function( event ) {
10536 if ( this.options.disabled ) {
10537 event.preventDefault();
10538 }
10539 }, this));
10540 this._bind({
10541 // Prevent focus from sticking to links inside menu after clicking
10542 // them (focus should always stay on UL during navigation).
10543 "mousedown .ui-menu-item > a": function( event ) {
10544 event.preventDefault();
10545 },
10546 "click .ui-menu-item:has(a)": function( event ) {
10547 event.stopImmediatePropagation();
10548 this.select( event );
10549 // Redirect focus to the menu with a delay for firefox
10550 this._delay( function() {
10551 if ( !this.element.is(":focus") ) {
10552 this.element.focus();
10553 }
10554 }, 20);
10555 },
10556 "mouseover .ui-menu-item": function( event ) {
10557 event.stopImmediatePropagation();
10558 var target = $( event.currentTarget );
10559 // Remove ui-state-active class from siblings of the newly focused menu item to avoid a jump caused by adjacent elements both having a class with a border
10560 target.siblings().children( ".ui-state-active" ).removeClass( "ui-state-active" );
10561 this.focus( event, target );
10562 },
10563 "mouseleave": "collapseAll",
10564 "mouseleave .ui-menu": "collapseAll",
10565 "focus": function( event ) {
10566 var firstItem = this.element.children( ".ui-menu-item" ).eq( 0 );
10567 if ( this._hasScroll() && !this.active ) {
10568 var menu = this.element;
10569 menu.children().each( function() {
10570 var currentItem = $( this );
10571 if ( currentItem.offset().top - menu.offset().top >= 0 ) {
10572 firstItem = currentItem;
10573 return false;
10574 }
10575 });
10576 } else if ( this.active ) {
10577 firstItem = this.active;
10578 }
10579 this.focus( event, firstItem );
10580 },
10581 blur: function( event ) {
10582 this._delay( function() {
10583 if ( ! $.contains( this.element[0], this.document[0].activeElement ) ) {
10584 this.collapseAll( event );
10585 }
10586 }, 0);
10587 }
10588 });
10589
10590 this.refresh();
10591
10592 this.element.attr( "tabIndex", 0 );
10593 this._bind({
10594 "keydown": function( event ) {
10595 switch ( event.keyCode ) {
10596 case $.ui.keyCode.PAGE_UP:
10597 this.previousPage( event );
10598 event.preventDefault();
10599 event.stopImmediatePropagation();
10600 break;
10601 case $.ui.keyCode.PAGE_DOWN:
10602 this.nextPage( event );
10603 event.preventDefault();
10604 event.stopImmediatePropagation();
10605 break;
10606 case $.ui.keyCode.HOME:
10607 this._move( "first", "first", event );
10608 event.preventDefault();
10609 event.stopImmediatePropagation();
10610 break;
10611 case $.ui.keyCode.END:
10612 this._move( "last", "last", event );
10613 event.preventDefault();
10614 event.stopImmediatePropagation();
10615 break;
10616 case $.ui.keyCode.UP:
10617 this.previous( event );
10618 event.preventDefault();
10619 event.stopImmediatePropagation();
10620 break;
10621 case $.ui.keyCode.DOWN:
10622 this.next( event );
10623 event.preventDefault();
10624 event.stopImmediatePropagation();
10625 break;
10626 case $.ui.keyCode.LEFT:
10627 if (this.collapse( event )) {
10628 event.stopImmediatePropagation();
10629 }
10630 event.preventDefault();
10631 break;
10632 case $.ui.keyCode.RIGHT:
10633 if (this.expand( event )) {
10634 event.stopImmediatePropagation();
10635 }
10636 event.preventDefault();
10637 break;
10638 case $.ui.keyCode.ENTER:
10639 if ( this.active.children( "a[aria-haspopup='true']" ).length ) {
10640 if ( this.expand( event ) ) {
10641 event.stopImmediatePropagation();
10642 }
10643 }
10644 else {
10645 this.select( event );
10646 event.stopImmediatePropagation();
10647 }
10648 event.preventDefault();
10649 break;
10650 case $.ui.keyCode.ESCAPE:
10651 if ( this.collapse( event ) ) {
10652 event.stopImmediatePropagation();
10653 }
10654 event.preventDefault();
10655 break;
10656 default:
10657 event.stopPropagation();
10658 clearTimeout( this.filterTimer );
10659 var match,
10660 prev = this.previousFilter || "",
10661 character = String.fromCharCode( event.keyCode ),
10662 skip = false;
10663
10664 if (character == prev) {
10665 skip = true;
10666 } else {
10667 character = prev + character;
10668 }
10669 function escape( value ) {
10670 return value.replace( /[-[\]{}()*+?.,\\^$|#\s]/g , "\\$&" );
10671 }
10672 match = this.activeMenu.children( ".ui-menu-item" ).filter( function() {
10673 return new RegExp("^" + escape(character), "i")
10674 .test( $( this ).children( "a" ).text() );
10675 });
10676 match = skip && match.index(this.active.next()) != -1 ? this.active.nextAll(".ui-menu-item") : match;
10677 if ( !match.length ) {
10678 character = String.fromCharCode(event.keyCode);
10679 match = this.activeMenu.children(".ui-menu-item").filter( function() {
10680 return new RegExp("^" + escape(character), "i")
10681 .test( $( this ).children( "a" ).text() );
10682 });
10683 }
10684 if ( match.length ) {
10685 this.focus( event, match );
10686 if (match.length > 1) {
10687 this.previousFilter = character;
10688 this.filterTimer = this._delay( function() {
10689 delete this.previousFilter;
10690 }, 1000 );
10691 } else {
10692 delete this.previousFilter;
10693 }
10694 } else {
10695 delete this.previousFilter;
10696 }
10697 }
10698 }
10699 });
10700
10701 this._bind( this.document, {
10702 click: function( event ) {
10703 if ( !$( event.target ).closest( ".ui-menu" ).length ) {
10704 this.collapseAll( event );
10705 }
10706 }
10707 });
10708
10709 if ( this.options.trigger ) {
10710 this.element.popup({
10711 trigger: this.options.trigger,
10712 managed: true,
10713 focusPopup: $.proxy( function( event, ui ) {
10714 this.focus( event, this.element.children( ".ui-menu-item" ).first() );
10715 this.element.focus( 1 );
10716 }, this)
10717 });
10718 }
10719 },
10720
10721 _destroy: function() {
10722 //destroy (sub)menus
10723 if ( this.options.trigger ) {
10724 this.element.popup( "destroy" );
10725 }
10726 this.element
10727 .removeAttr( "aria-activedescendant" )
10728 .find( ".ui-menu" )
10729 .andSelf()
10730 .removeClass( "ui-menu ui-widget ui-widget-content ui-corner-all" )
10731 .removeAttr( "role" )
10732 .removeAttr( "tabIndex" )
10733 .removeAttr( "aria-labelledby" )
10734 .removeAttr( "aria-expanded" )
10735 .removeAttr( "aria-hidden" )
10736 .show();
10737
10738 //destroy menu items
10739 this.element.find( ".ui-menu-item" )
10740 .unbind( ".menu" )
10741 .removeClass( "ui-menu-item" )
10742 .removeAttr( "role" )
10743 .children( "a" )
10744 .removeClass( "ui-corner-all ui-state-hover" )
10745 .removeAttr( "tabIndex" )
10746 .removeAttr( "role" )
10747 .removeAttr( "aria-haspopup" )
10748 .removeAttr( "id" )
10749 .children( ".ui-icon" )
10750 .remove();
10751 },
10752
10753 refresh: function() {
10754 // initialize nested menus
10755 var submenus = this.element.find( this.options.menus + ":not( .ui-menu )" )
10756 .addClass( "ui-menu ui-widget ui-widget-content ui-corner-all" )
10757 .attr( "role", "menu" )
10758 .hide()
10759 .attr( "aria-hidden", "true" )
10760 .attr( "aria-expanded", "false" );
10761
10762 // don't refresh list items that are already adapted
10763 var menuId = this.menuId;
10764 submenus.add( this.element ).children( ":not( .ui-menu-item ):has( a )" )
10765 .addClass( "ui-menu-item" )
10766 .attr( "role", "presentation" )
10767 .children( "a" )
10768 .addClass( "ui-corner-all" )
10769 .attr( "tabIndex", -1 )
10770 .attr( "role", "menuitem" )
10771 .attr( "id", function( i ) {
10772 return menuId + "-" + i;
10773 });
10774
10775 submenus.each( function() {
10776 var menu = $( this ),
10777 item = menu.prev( "a" );
10778
10779 item.attr( "aria-haspopup", "true" )
10780 .prepend( '<span class="ui-menu-icon ui-icon ui-icon-carat-1-e"></span>' );
10781 menu.attr( "aria-labelledby", item.attr( "id" ) );
10782 });
10783 },
10784
10785 focus: function( event, item ) {
10786 this.blur( event );
10787
10788 if ( this._hasScroll() ) {
10789 var borderTop = parseFloat( $.curCSS( this.activeMenu[0], "borderTopWidth", true ) ) || 0,
10790 paddingTop = parseFloat( $.curCSS( this.activeMenu[0], "paddingTop", true ) ) || 0,
10791 offset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop,
10792 scroll = this.activeMenu.scrollTop(),
10793 elementHeight = this.activeMenu.height(),
10794 itemHeight = item.height();
10795
10796 if ( offset < 0 ) {
10797 this.activeMenu.scrollTop( scroll + offset );
10798 } else if ( offset + itemHeight > elementHeight ) {
10799 this.activeMenu.scrollTop( scroll + offset - elementHeight + itemHeight );
10800 }
10801 }
10802
10803 this.active = item.first()
10804 .children( "a" )
10805 .addClass( "ui-state-focus" )
10806 .end();
10807 this.element.attr( "aria-activedescendant", this.active.children( "a" ).attr( "id" ) );
10808
10809 // highlight active parent menu item, if any
10810 this.active.parent().closest( ".ui-menu-item" ).children( "a:first" ).addClass( "ui-state-active" );
10811
10812 this.timer = this._delay( function() {
10813 this._close();
10814 }, this.delay );
10815
10816 var nested = $( "> .ui-menu", item );
10817 if ( nested.length && ( /^mouse/.test( event.type ) ) ) {
10818 this._startOpening(nested);
10819 }
10820 this.activeMenu = item.parent();
10821
10822 this._trigger( "focus", event, { item: item } );
10823 },
10824
10825 blur: function( event ) {
10826 clearTimeout( this.timer );
10827
10828 if ( !this.active ) {
10829 return;
10830 }
10831
10832 this.active.children( "a" ).removeClass( "ui-state-focus" );
10833 this.active = null;
10834
10835 this._trigger( "blur", event, { item: this.active } );
10836 },
10837
10838 _startOpening: function( submenu ) {
10839 clearTimeout( this.timer );
10840
10841 // Don't open if already open fixes a Firefox bug that caused a .5 pixel
10842 // shift in the submenu position when mousing over the carat icon
10843 if ( submenu.attr( "aria-hidden" ) !== "true" ) {
10844 return;
10845 }
10846
10847 this.timer = this._delay( function() {
10848 this._close();
10849 this._open( submenu );
10850 }, this.delay );
10851 },
10852
10853 _open: function( submenu ) {
10854 clearTimeout( this.timer );
10855 this.element
10856 .find( ".ui-menu" )
10857 .not( submenu.parents() )
10858 .hide()
10859 .attr( "aria-hidden", "true" );
10860
10861 var position = $.extend({}, {
10862 of: this.active
10863 }, $.type(this.options.position) == "function"
10864 ? this.options.position(this.active)
10865 : this.options.position
10866 );
10867
10868 submenu.show()
10869 .removeAttr( "aria-hidden" )
10870 .attr( "aria-expanded", "true" )
10871 .position( position );
10872 },
10873
10874 collapseAll: function( event, all ) {
10875 clearTimeout( this.timer );
10876 this.timer = this._delay( function() {
10877 // if we were passed an event, look for the submenu that contains the event
10878 var currentMenu = all ? this.element :
10879 $( event && event.target ).closest( this.element.find( ".ui-menu" ) );
10880
10881 // if we found no valid submenu ancestor, use the main menu to close all sub menus anyway
10882 if ( !currentMenu.length ) {
10883 currentMenu = this.element;
10884 }
10885
10886 this._close( currentMenu );
10887
10888 this.blur( event );
10889 this.activeMenu = currentMenu;
10890 }, this.delay);
10891 },
10892
10893 // With no arguments, closes the currently active menu - if nothing is active
10894 // it closes all menus. If passed an argument, it will search for menus BELOW
10895 _close: function( startMenu ) {
10896 if ( !startMenu ) {
10897 startMenu = this.active ? this.active.parent() : this.element;
10898 }
10899
10900 startMenu
10901 .find( ".ui-menu" )
10902 .hide()
10903 .attr( "aria-hidden", "true" )
10904 .attr( "aria-expanded", "false" )
10905 .end()
10906 .find( "a.ui-state-active" )
10907 .removeClass( "ui-state-active" );
10908 },
10909
10910 collapse: function( event ) {
10911 var newItem = this.active && this.active.parent().closest( ".ui-menu-item", this.element );
10912 if ( newItem && newItem.length ) {
10913 this._close();
10914 this.focus( event, newItem );
10915 return true;
10916 }
10917 },
10918
10919 expand: function( event ) {
10920 var newItem = this.active && this.active.children( ".ui-menu " ).children( ".ui-menu-item" ).first();
10921
10922 if ( newItem && newItem.length ) {
10923 this._open( newItem.parent() );
10924
10925 //timeout so Firefox will not hide activedescendant change in expanding submenu from AT
10926 this._delay( function() {
10927 this.focus( event, newItem );
10928 }, 20 );
10929 return true;
10930 }
10931 },
10932
10933 next: function(event) {
10934 this._move( "next", "first", event );
10935 },
10936
10937 previous: function(event) {
10938 this._move( "prev", "last", event );
10939 },
10940
10941 isFirstItem: function() {
10942 return this.active && !this.active.prevAll( ".ui-menu-item" ).length;
10943 },
10944
10945 isLastItem: function() {
10946 return this.active && !this.active.nextAll( ".ui-menu-item" ).length;
10947 },
10948
10949 _move: function( direction, filter, event ) {
10950 if ( !this.active ) {
10951 this.focus( event, this.activeMenu.children( ".ui-menu-item" )[ filter ]() );
10952 return;
10953 }
10954
10955 var next;
10956 if ( direction === "first" || direction === "last" ) {
10957 next = this.active[ direction === "first" ? "prevAll" : "nextAll" ]( ".ui-menu-item" ).eq( -1 );
10958 } else {
10959 next = this.active[ direction + "All" ]( ".ui-menu-item" ).eq( 0 );
10960 }
10961
10962 if ( next.length ) {
10963 this.focus( event, next );
10964 } else {
10965 this.focus( event, this.activeMenu.children( ".ui-menu-item" )[ filter ]() );
10966 }
10967 },
10968
10969 nextPage: function( event ) {
10970 if ( !this.active ) {
10971 this.focus( event, this.activeMenu.children( ".ui-menu-item" ).first() );
10972 return;
10973 }
10974 if ( this.isLastItem() ) {
10975 return;
10976 }
10977 if ( this._hasScroll() ) {
10978 var base = this.active.offset().top,
10979 height = this.element.height(),
10980 result;
10981 this.active.nextAll( ".ui-menu-item" ).each( function() {
10982 result = $( this );
10983 return $( this ).offset().top - base - height < 0;
10984 });
10985
10986 this.focus( event, result );
10987 } else {
10988 this.focus( event, this.activeMenu.children( ".ui-menu-item" )
10989 [ !this.active ? "first" : "last" ]() );
10990 }
10991 },
10992
10993 previousPage: function( event ) {
10994 if ( !this.active ) {
10995 this.focus( event, this.activeMenu.children( ".ui-menu-item" ).first() );
10996 return;
10997 }
10998 if ( this.isFirstItem() ) {
10999 return;
11000 }
11001 if ( this._hasScroll() ) {
11002 var base = this.active.offset().top,
11003 height = this.element.height(),
11004 result;
11005 this.active.prevAll( ".ui-menu-item" ).each( function() {
11006 result = $( this );
11007 return $(this).offset().top - base + height > 0;
11008 });
11009
11010 this.focus( event, result );
11011 } else {
11012 this.focus( event, this.activeMenu.children( ".ui-menu-item" ).first() );
11013 }
11014 },
11015
11016 _hasScroll: function() {
11017 return this.element.outerHeight() < this.element.prop( "scrollHeight" );
11018 },
11019
11020 select: function( event ) {
11021
11022 // save active reference before collapseAll triggers blur
11023 var ui = {
11024 item: this.active
11025 };
11026 this.collapseAll( event, true );
11027 if ( this.options.trigger ) {
11028 $( this.options.trigger ).focus( 1 );
11029 this.element.popup( "close" );
11030 }
11031 this._trigger( "select", event, ui );
11032 }
11033 });
11034
11035 }( jQuery ));
11036 /*
11037 * jQuery UI Menubar @VERSION
11038 *
11039 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
11040 * Dual licensed under the MIT or GPL Version 2 licenses.
11041 * http://jquery.org/license
11042 *
11043 * http://docs.jquery.com/UI/Menubar
11044 *
11045 * Depends:
11046 * jquery.ui.core.js
11047 * jquery.ui.widget.js
11048 * jquery.ui.position.js
11049 * jquery.ui.menu.js
11050 */
11051 (function( $ ) {
11052
11053 // TODO when mixing clicking menus and keyboard navigation, focus handling is broken
11054 // there has to be just one item that has tabindex
11055 $.widget( "ui.menubar", {
11056 version: "@VERSION",
11057 options: {
11058 autoExpand: false,
11059 buttons: false,
11060 items: "li",
11061 menuElement: "ul",
11062 menuIcon: false,
11063 position: {
11064 my: "left top",
11065 at: "left bottom"
11066 }
11067 },
11068 _create: function() {
11069 var that = this;
11070 this.menuItems = this.element.children( this.options.items );
11071 this.items = this.menuItems.children( "button, a" );
11072
11073 this.menuItems
11074 .addClass( "ui-menubar-item" )
11075 .attr( "role", "presentation" );
11076 // let only the first item receive focus
11077 this.items.slice(1).attr( "tabIndex", -1 );
11078
11079 this.element
11080 .addClass( "ui-menubar ui-widget-header ui-helper-clearfix" )
11081 .attr( "role", "menubar" );
11082 this._focusable( this.items );
11083 this._hoverable( this.items );
11084 this.items.siblings( this.options.menuElement )
11085 .menu({
11086 position: {
11087 within: this.options.position.within
11088 },
11089 select: function( event, ui ) {
11090 ui.item.parents( "ul.ui-menu:last" ).hide();
11091 that._close();
11092 // TODO what is this targetting? there's probably a better way to access it
11093 $(event.target).prev().focus();
11094 that._trigger( "select", event, ui );
11095 },
11096 menus: that.options.menuElement
11097 })
11098 .hide()
11099 .attr({
11100 "aria-hidden": "true",
11101 "aria-expanded": "false"
11102 })
11103 .bind( "keydown.menubar", function( event ) {
11104 var menu = $( this );
11105 if ( menu.is( ":hidden" ) )
11106 return;
11107 switch ( event.keyCode ) {
11108 case $.ui.keyCode.LEFT:
11109 that.previous( event );
11110 event.preventDefault();
11111 break;
11112 case $.ui.keyCode.RIGHT:
11113 that.next( event );
11114 event.preventDefault();
11115 break;
11116 };
11117 });
11118 this.items.each(function() {
11119 var input = $(this),
11120 // TODO menu var is only used on two places, doesn't quite justify the .each
11121 menu = input.next( that.options.menuElement );
11122
11123 input.bind( "click.menubar focus.menubar mouseenter.menubar", function( event ) {
11124 // ignore triggered focus event
11125 if ( event.type == "focus" && !event.originalEvent ) {
11126 return;
11127 }
11128 event.preventDefault();
11129 // TODO can we simplify or extractthis check? especially the last two expressions
11130 // there's a similar active[0] == menu[0] check in _open
11131 if ( event.type == "click" && menu.is( ":visible" ) && that.active && that.active[0] == menu[0] ) {
11132 that._close();
11133 return;
11134 }
11135 if ( ( that.open && event.type == "mouseenter" ) || event.type == "click" || that.options.autoExpand ) {
11136 if( that.options.autoExpand ) {
11137 clearTimeout( that.closeTimer );
11138 }
11139
11140 that._open( event, menu );
11141 }
11142 })
11143 .bind( "keydown", function( event ) {
11144 switch ( event.keyCode ) {
11145 case $.ui.keyCode.SPACE:
11146 case $.ui.keyCode.UP:
11147 case $.ui.keyCode.DOWN:
11148 that._open( event, $( this ).next() );
11149 event.preventDefault();
11150 break;
11151 case $.ui.keyCode.LEFT:
11152 that.previous( event );
11153 event.preventDefault();
11154 break;
11155 case $.ui.keyCode.RIGHT:
11156 that.next( event );
11157 event.preventDefault();
11158 break;
11159 }
11160 })
11161 .addClass( "ui-button ui-widget ui-button-text-only ui-menubar-link" )
11162 .attr( "role", "menuitem" )
11163 .attr( "aria-haspopup", "true" )
11164 .wrapInner( "<span class='ui-button-text'></span>" );
11165
11166 // TODO review if these options are a good choice, maybe they can be merged
11167 if ( that.options.menuIcon ) {
11168 input.addClass( "ui-state-default" ).append( "<span class='ui-button-icon-secondary ui-icon ui-icon-triangle-1-s'></span>" );
11169 input.removeClass( "ui-button-text-only" ).addClass( "ui-button-text-icon-secondary" );
11170 }
11171
11172 if ( !that.options.buttons ) {
11173 // TODO ui-menubar-link is added above, not needed here?
11174 input.addClass( "ui-menubar-link" ).removeClass( "ui-state-default" );
11175 };
11176
11177 });
11178 that._bind( {
11179 keydown: function( event ) {
11180 if ( event.keyCode == $.ui.keyCode.ESCAPE && that.active && that.active.menu( "collapse", event ) !== true ) {
11181 var active = that.active;
11182 that.active.blur();
11183 that._close( event );
11184 active.prev().focus();
11185 }
11186 },
11187 focusin: function( event ) {
11188 clearTimeout( that.closeTimer );
11189 },
11190 focusout: function( event ) {
11191 that.closeTimer = setTimeout( function() {
11192 that._close( event );
11193 }, 150);
11194 },
11195 "mouseleave .ui-menubar-item": function( event ) {
11196 if ( that.options.autoExpand ) {
11197 that.closeTimer = setTimeout( function() {
11198 that._close( event );
11199 }, 150);
11200 }
11201 },
11202 "mouseenter .ui-menubar-item": function( event ) {
11203 clearTimeout( that.closeTimer );
11204 }
11205 });
11206 },
11207
11208 _destroy : function() {
11209 this.menuItems
11210 .removeClass( "ui-menubar-item" )
11211 .removeAttr( "role" );
11212
11213 this.element
11214 .removeClass( "ui-menubar ui-widget-header ui-helper-clearfix" )
11215 .removeAttr( "role" )
11216 .unbind( ".menubar" );
11217
11218 this.items
11219 .unbind( ".menubar" )
11220 .removeClass( "ui-button ui-widget ui-button-text-only ui-menubar-link ui-state-default" )
11221 .removeAttr( "role" )
11222 .removeAttr( "aria-haspopup" )
11223 // TODO unwrap?
11224 .children( "span.ui-button-text" ).each(function( i, e ) {
11225 var item = $( this );
11226 item.parent().html( item.html() );
11227 })
11228 .end()
11229 .children( ".ui-icon" ).remove();
11230
11231 this.element.find( ":ui-menu" )
11232 .menu( "destroy" )
11233 .show()
11234 .removeAttr( "aria-hidden" )
11235 .removeAttr( "aria-expanded" )
11236 .removeAttr( "tabindex" )
11237 .unbind( ".menubar" );
11238 },
11239
11240 _close: function() {
11241 if ( !this.active || !this.active.length )
11242 return;
11243 this.active
11244 .menu( "collapseAll" )
11245 .hide()
11246 .attr({
11247 "aria-hidden": "true",
11248 "aria-expanded": "false"
11249 });
11250 this.active
11251 .prev()
11252 .removeClass( "ui-state-active" )
11253 .removeAttr( "tabIndex" );
11254 this.active = null;
11255 this.open = false;
11256 },
11257
11258 _open: function( event, menu ) {
11259 // on a single-button menubar, ignore reopening the same menu
11260 if ( this.active && this.active[0] == menu[0] ) {
11261 return;
11262 }
11263 // TODO refactor, almost the same as _close above, but don't remove tabIndex
11264 if ( this.active ) {
11265 this.active
11266 .menu( "collapseAll" )
11267 .hide()
11268 .attr({
11269 "aria-hidden": "true",
11270 "aria-expanded": "false"
11271 });
11272 this.active
11273 .prev()
11274 .removeClass( "ui-state-active" );
11275 }
11276 // set tabIndex -1 to have the button skipped on shift-tab when menu is open (it gets focus)
11277 var button = menu.prev().addClass( "ui-state-active" ).attr( "tabIndex", -1 );
11278 this.active = menu
11279 .show()
11280 .position( $.extend({
11281 of: button
11282 }, this.options.position ) )
11283 .removeAttr( "aria-hidden" )
11284 .attr( "aria-expanded", "true" )
11285 .menu("focus", event, menu.children( ".ui-menu-item" ).first() )
11286 // TODO need a comment here why both events are triggered
11287 .focus()
11288 .focusin();
11289 this.open = true;
11290 },
11291
11292 next: function( event ) {
11293 this._move( "next", "first", event );
11294 },
11295
11296 previous: function( event ) {
11297 this._move( "prev", "last", event );
11298 },
11299
11300 _move: function( direction, filter, event ) {
11301 var next,
11302 wrapItem;
11303 if ( this.open ) {
11304 next = this.active.closest( ".ui-menubar-item" )[ direction + "All" ]( this.options.items ).first().children( ".ui-menu" ).eq( 0 );
11305 wrapItem = this.menuItems[ filter ]().children( ".ui-menu" ).eq( 0 );
11306 } else {
11307 if ( event ) {
11308 next = $( event.target ).closest( ".ui-menubar-item" )[ direction + "All" ]( this.options.items ).children( ".ui-menubar-link" ).eq( 0 );
11309 wrapItem = this.menuItems[ filter ]().children( ".ui-menubar-link" ).eq( 0 );
11310 } else {
11311 next = wrapItem = this.menuItems.children( "a" ).eq( 0 );
11312 }
11313 }
11314
11315 if ( next.length ) {
11316 if ( this.open ) {
11317 this._open( event, next );
11318 } else {
11319 next.removeAttr( "tabIndex")[0].focus();
11320 }
11321 } else {
11322 if ( this.open ) {
11323 this._open( event, wrapItem );
11324 } else {
11325 wrapItem.removeAttr( "tabIndex")[0].focus();
11326 }
11327 }
11328 }
11329 });
11330
11331 }( jQuery ));
11332 /*
11333 * jQuery UI Popup @VERSION
11334 *
11335 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
11336 * Dual licensed under the MIT or GPL Version 2 licenses.
11337 * http://jquery.org/license
11338 *
11339 * http://docs.jquery.com/UI/Popup
11340 *
11341 * Depends:
11342 * jquery.ui.core.js
11343 * jquery.ui.widget.js
11344 * jquery.ui.position.js
11345 */
11346 (function($) {
11347
11348 var idIncrement = 0,
11349 suppressExpandOnFocus = false;
11350
11351 $.widget( "ui.popup", {
11352 version: "@VERSION",
11353 options: {
11354 position: {
11355 my: "left top",
11356 at: "left bottom"
11357 },
11358 managed: false,
11359 expandOnFocus: false,
11360 show: {
11361 effect: "slideDown",
11362 duration: "fast"
11363 },
11364 hide: {
11365 effect: "fadeOut",
11366 duration: "fast"
11367 }
11368 },
11369 _create: function() {
11370 if ( !this.options.trigger ) {
11371 this.options.trigger = this.element.prev();
11372 }
11373
11374 if ( !this.element.attr( "id" ) ) {
11375 this.element.attr( "id", "ui-popup-" + idIncrement++ );
11376 this.generatedId = true;
11377 }
11378
11379 if ( !this.element.attr( "role" ) ) {
11380 if ( !this.options.managed ) {
11381 this.element.attr( "role", "dialog" );
11382 this.generatedRole = true;
11383 }
11384 }
11385
11386 this.options.trigger
11387 .attr( "aria-haspopup", "true" )
11388 .attr( "aria-owns", this.element.attr( "id" ) );
11389
11390 this.element
11391 .addClass( "ui-popup" );
11392 this._beforeClose();
11393 this.element.hide();
11394
11395 this._bind(this.options.trigger, {
11396 keydown: function( event ) {
11397 switch ( event.keyCode ) {
11398 case $.ui.keyCode.TAB:
11399 // Waiting for close() will make popup hide too late, which breaks tab key behavior
11400 this.element.hide();
11401 this.close( event );
11402 break;
11403 case $.ui.keyCode.ESCAPE:
11404 if ( this.isOpen ) {
11405 this.close( event );
11406 }
11407 break;
11408 case $.ui.keyCode.SPACE:
11409 // prevent space-to-open to scroll the page, only happens for anchor ui.button
11410 // TODO check for $.ui.button before using custom selector, once more below
11411 if ( this.options.trigger.is( "a:ui-button" ) ) {
11412 event.preventDefault();
11413 }
11414
11415 else if (this.options.trigger.is( "a:not(:ui-button)" ) ) {
11416 this.options.trigger.trigger( "click", event );
11417 }
11418 break;
11419 case $.ui.keyCode.DOWN:
11420 case $.ui.keyCode.UP:
11421 // prevent scrolling
11422 event.preventDefault();
11423 clearTimeout( this.closeTimer );
11424 this._delay(function() {
11425 this.open( event );
11426 this.focusPopup( event );
11427 }, 1);
11428 break;
11429 }
11430 },
11431 click: function( event ) {
11432 event.stopPropagation();
11433 event.preventDefault();
11434 },
11435 mousedown: function( event ) {
11436 var noFocus = false;
11437 /* TODO: Determine in which cases focus should stay on the trigger after the popup opens
11438 (should apply for any trigger that has other interaction besides opening the popup, e.g. a text field) */
11439 if ( $( event.target ).is( "input" ) ) {
11440 noFocus = true;
11441 }
11442 if (this.isOpen) {
11443 suppressExpandOnFocus = true;
11444 this.close();
11445 return;
11446 }
11447 this.open( event );
11448 clearTimeout( this.closeTimer );
11449 this._delay( function() {
11450 if ( !noFocus ) {
11451 this.focusPopup();
11452 }
11453 }, 1 );
11454 }
11455 });
11456
11457 if ( this.options.expandOnFocus ) {
11458 this._bind( this.options.trigger, {
11459 focus : function( event ) {
11460 if ( !suppressExpandOnFocus ) {
11461 this._delay( function() {
11462 if ( !this.isOpen ) {
11463 this.open( event );
11464 }
11465 }, 1);
11466 }
11467 this._delay( function() {
11468 suppressExpandOnFocus = false;
11469 }, 100);
11470 },
11471 blur: function( event ) {
11472 suppressExpandOnFocus = false;
11473 }
11474 });
11475 }
11476 if ( !this.options.managed ) {
11477 //default use case, wrap tab order in popup
11478 this._bind({ keydown : function( event ) {
11479 if ( event.keyCode !== $.ui.keyCode.TAB ) {
11480 return;
11481 }
11482 var tabbables = $( ":tabbable", this.element ),
11483 first = tabbables.first(),
11484 last = tabbables.last();
11485 if ( event.target === last[ 0 ] && !event.shiftKey ) {
11486 first.focus( 1 );
11487 event.preventDefault();
11488 } else if ( event.target === first[ 0 ] && event.shiftKey ) {
11489 last.focus( 1 );
11490 event.preventDefault();
11491 }
11492 }
11493 });
11494 }
11495
11496 this._bind({
11497 focusout: function( event ) {
11498 // use a timer to allow click to clear it and letting that
11499 // handle the closing instead of opening again
11500 this.closeTimer = this._delay( function() {
11501 this.close( event );
11502 }, 150);
11503 },
11504 focusin: function( event ) {
11505 clearTimeout( this.closeTimer );
11506 },
11507 mouseup: function( event ) {
11508 clearTimeout( this.closeTimer );
11509 }
11510 });
11511
11512 this._bind({
11513 keyup: function( event ) {
11514 if ( event.keyCode == $.ui.keyCode.ESCAPE && this.element.is( ":visible" ) ) {
11515 this.close( event );
11516 this.focusTrigger();
11517 }
11518 }
11519 });
11520
11521 this._bind( this.document, {
11522 click: function( event ) {
11523 if ( this.isOpen && !$( event.target ).closest( this.element.add( this.options.trigger ) ).length ) {
11524 this.close( event );
11525 }
11526 }
11527 });
11528 },
11529
11530 _destroy: function() {
11531 this.element
11532 .show()
11533 .removeClass( "ui-popup" )
11534 .removeAttr( "aria-hidden" )
11535 .removeAttr( "aria-expanded" )
11536 .unbind( "keypress.ui-popup");
11537
11538 this.options.trigger
11539 .removeAttr( "aria-haspopup" )
11540 .removeAttr( "aria-owns" );
11541
11542 if ( this.generatedId ) {
11543 this.element.removeAttr( "id" );
11544 }
11545 if ( this.generatedRole ) {
11546 this.element.removeAttr( "role" );
11547 }
11548 },
11549
11550 open: function( event ) {
11551 var position = $.extend( {}, {
11552 of: this.options.trigger
11553 }, this.options.position );
11554
11555 this._show( this.element, this.options.show );
11556 this.element
11557 .attr( "aria-hidden", "false" )
11558 .attr( "aria-expanded", "true" )
11559 .position( position );
11560
11561 // take trigger out of tab order to allow shift-tab to skip trigger
11562 this.options.trigger.attr( "tabindex", -1 );
11563 this.isOpen = true;
11564 this._trigger( "open", event );
11565 },
11566
11567 focusPopup: function( event ) {
11568 if ( !this.options.managed ) {
11569 // set focus to the first tabbable element in the popup container
11570 // if there are no tabbable elements, set focus on the popup itself
11571 var tabbables = this.element.find( ":tabbable" );
11572 this.removeTabIndex = false;
11573 if ( !tabbables.length ) {
11574 if ( !this.element.is(":tabbable") ) {
11575 this.element.attr("tabindex", "0");
11576 this.removeTabIndex = true;
11577 }
11578 tabbables = tabbables.add( this.element[ 0 ] );
11579 }
11580 tabbables.first().focus( 1 );
11581 }
11582 this._trigger( "focusPopup", event );
11583 },
11584
11585 focusTrigger: function( event ) {
11586 suppressExpandOnFocus = true;
11587 this.options.trigger.focus();
11588 this._trigger( "focusTrigger", event );
11589 },
11590
11591 close: function( event ) {
11592 this._beforeClose();
11593 this._hide( this.element, this.options.hide );
11594
11595 this.options.trigger.attr( "tabindex" , 0 );
11596 if ( this.removeTabIndex ) {
11597 this.element.removeAttr( "tabindex" );
11598 }
11599 this.isOpen = false;
11600 this._trigger( "close", event );
11601 },
11602
11603 _beforeClose: function() {
11604 this.element
11605 .attr( "aria-hidden", "true" )
11606 .attr( "aria-expanded", "false" );
11607 }
11608 });
11609
11610 }(jQuery));
11611 /*
11612 * jQuery UI Position @VERSION
11613 *
11614 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
11615 * Dual licensed under the MIT or GPL Version 2 licenses.
11616 * http://jquery.org/license
11617 *
11618 * http://docs.jquery.com/UI/Position
11619 */
11620 (function( $, undefined ) {
11621
11622 $.ui = $.ui || {};
11623
11624 var rhorizontal = /left|center|right/,
11625 rvertical = /top|center|bottom/,
11626 roffset = /[+-]\d+%?/,
11627 rposition = /^\w+/,
11628 rpercent = /%$/,
11629 center = "center",
11630 _position = $.fn.position;
11631
11632 $.position = {
11633 scrollbarWidth: function() {
11634 var w1, w2,
11635 div = $( "<div style='display:block;width:50px;height:50px;overflow:hidden;'><div style='height:100px;width:auto;'></div></div>" ),
11636 innerDiv = div.children()[0];
11637
11638 $( "body" ).append( div );
11639 w1 = innerDiv.offsetWidth;
11640 div.css( "overflow", "scroll" );
11641
11642 w2 = innerDiv.offsetWidth;
11643
11644 if ( w1 === w2 ) {
11645 w2 = div[0].clientWidth;
11646 }
11647
11648 div.remove();
11649
11650 return w1 - w2;
11651 },
11652 getScrollInfo: function(within) {
11653 var notWindow = within[0] !== window,
11654 overflowX = notWindow ? within.css( "overflow-x" ) : "",
11655 overflowY = notWindow ? within.css( "overflow-y" ) : "",
11656 scrollbarWidth = overflowX === "auto" || overflowX === "scroll" ? $.position.scrollbarWidth() : 0,
11657 scrollbarHeight = overflowY === "auto" || overflowY === "scroll" ? $.position.scrollbarWidth() : 0;
11658
11659 return {
11660 height: within.height() < within[0].scrollHeight ? scrollbarHeight : 0,
11661 width: within.width() < within[0].scrollWidth ? scrollbarWidth : 0
11662 };
11663 }
11664 };
11665
11666 $.fn.position = function( options ) {
11667 if ( !options || !options.of ) {
11668 return _position.apply( this, arguments );
11669 }
11670
11671 // make a copy, we don't want to modify arguments
11672 options = $.extend( {}, options );
11673
11674 var target = $( options.of ),
11675 within = $( options.within || window ),
11676 targetElem = target[0],
11677 collision = ( options.collision || "flip" ).split( " " ),
11678 offsets = {},
11679 atOffset,
11680 targetWidth,
11681 targetHeight,
11682 basePosition;
11683
11684 if ( targetElem.nodeType === 9 ) {
11685 targetWidth = target.width();
11686 targetHeight = target.height();
11687 basePosition = { top: 0, left: 0 };
11688 } else if ( $.isWindow( targetElem ) ) {
11689 targetWidth = target.width();
11690 targetHeight = target.height();
11691 basePosition = { top: target.scrollTop(), left: target.scrollLeft() };
11692 } else if ( targetElem.preventDefault ) {
11693 // force left top to allow flipping
11694 options.at = "left top";
11695 targetWidth = targetHeight = 0;
11696 basePosition = { top: options.of.pageY, left: options.of.pageX };
11697 } else {
11698 targetWidth = target.outerWidth();
11699 targetHeight = target.outerHeight();
11700 basePosition = target.offset();
11701 }
11702
11703 // force my and at to have valid horizontal and vertical positions
11704 // if a value is missing or invalid, it will be converted to center
11705 $.each( [ "my", "at" ], function() {
11706 var pos = ( options[ this ] || "" ).split( " " ),
11707 horizontalOffset,
11708 verticalOffset;
11709
11710 if ( pos.length === 1) {
11711 pos = rhorizontal.test( pos[ 0 ] ) ?
11712 pos.concat( [ center ] ) :
11713 rvertical.test( pos[ 0 ] ) ?
11714 [ center ].concat( pos ) :
11715 [ center, center ];
11716 }
11717 pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : center;
11718 pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : center;
11719
11720 // calculate offsets
11721 horizontalOffset = roffset.exec( pos[ 0 ] );
11722 verticalOffset = roffset.exec( pos[ 1 ] );
11723 offsets[ this ] = [
11724 horizontalOffset ? horizontalOffset[ 0 ] : 0,
11725 verticalOffset ? verticalOffset[ 0 ] : 0
11726 ];
11727
11728 // reduce to just the positions without the offsets
11729 options[ this ] = [
11730 rposition.exec( pos[ 0 ] )[ 0 ],
11731 rposition.exec( pos[ 1 ] )[ 0 ]
11732 ];
11733 });
11734
11735 // normalize collision option
11736 if ( collision.length === 1 ) {
11737 collision[ 1 ] = collision[ 0 ];
11738 }
11739
11740 if ( options.at[ 0 ] === "right" ) {
11741 basePosition.left += targetWidth;
11742 } else if ( options.at[ 0 ] === center ) {
11743 basePosition.left += targetWidth / 2;
11744 }
11745
11746 if ( options.at[ 1 ] === "bottom" ) {
11747 basePosition.top += targetHeight;
11748 } else if ( options.at[ 1 ] === center ) {
11749 basePosition.top += targetHeight / 2;
11750 }
11751
11752 atOffset = [
11753 parseInt( offsets.at[ 0 ], 10 ) *
11754 ( rpercent.test( offsets.at[ 0 ] ) ? targetWidth / 100 : 1 ),
11755 parseInt( offsets.at[ 1 ], 10 ) *
11756 ( rpercent.test( offsets.at[ 1 ] ) ? targetHeight / 100 : 1 )
11757 ];
11758 basePosition.left += atOffset[ 0 ];
11759 basePosition.top += atOffset[ 1 ];
11760
11761 return this.each(function() {
11762 var elem = $( this ),
11763 elemWidth = elem.outerWidth(),
11764 elemHeight = elem.outerHeight(),
11765 marginLeft = parseInt( $.curCSS( this, "marginLeft", true ) ) || 0,
11766 marginTop = parseInt( $.curCSS( this, "marginTop", true ) ) || 0,
11767 scrollInfo = $.position.getScrollInfo( within ),
11768 collisionWidth = elemWidth + marginLeft +
11769 ( parseInt( $.curCSS( this, "marginRight", true ) ) || 0 ) + scrollInfo.width,
11770 collisionHeight = elemHeight + marginTop +
11771 ( parseInt( $.curCSS( this, "marginBottom", true ) ) || 0 ) + scrollInfo.height,
11772 position = $.extend( {}, basePosition ),
11773 myOffset = [
11774 parseInt( offsets.my[ 0 ], 10 ) *
11775 ( rpercent.test( offsets.my[ 0 ] ) ? elem.outerWidth() / 100 : 1 ),
11776 parseInt( offsets.my[ 1 ], 10 ) *
11777 ( rpercent.test( offsets.my[ 1 ] ) ? elem.outerHeight() / 100 : 1 )
11778 ],
11779 collisionPosition;
11780
11781 if ( options.my[ 0 ] === "right" ) {
11782 position.left -= elemWidth;
11783 } else if ( options.my[ 0 ] === center ) {
11784 position.left -= elemWidth / 2;
11785 }
11786
11787 if ( options.my[ 1 ] === "bottom" ) {
11788 position.top -= elemHeight;
11789 } else if ( options.my[ 1 ] === center ) {
11790 position.top -= elemHeight / 2;
11791 }
11792
11793 position.left += myOffset[ 0 ];
11794 position.top += myOffset[ 1 ];
11795
11796 // if the browser doesn't support fractions, then round for consistent results
11797 if ( !$.support.offsetFractions ) {
11798 position.left = Math.round( position.left );
11799 position.top = Math.round( position.top );
11800 }
11801
11802 collisionPosition = {
11803 marginLeft: marginLeft,
11804 marginTop: marginTop
11805 };
11806
11807 $.each( [ "left", "top" ], function( i, dir ) {
11808 if ( $.ui.position[ collision[ i ] ] ) {
11809 $.ui.position[ collision[ i ] ][ dir ]( position, {
11810 targetWidth: targetWidth,
11811 targetHeight: targetHeight,
11812 elemWidth: elemWidth,
11813 elemHeight: elemHeight,
11814 collisionPosition: collisionPosition,
11815 collisionWidth: collisionWidth,
11816 collisionHeight: collisionHeight,
11817 offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ],
11818 my: options.my,
11819 at: options.at,
11820 within: within,
11821 elem : elem
11822 });
11823 }
11824 });
11825
11826 if ( $.fn.bgiframe ) {
11827 elem.bgiframe();
11828 }
11829 elem.offset( $.extend( position, { using: options.using } ) );
11830 });
11831 };
11832
11833 $.ui.position = {
11834 fit: {
11835 left: function( position, data ) {
11836 var within = data.within,
11837 win = $( window ),
11838 isWindow = $.isWindow( data.within[0] ),
11839 withinOffset = isWindow ? win.scrollLeft() : within.offset().left,
11840 outerWidth = isWindow ? win.width() : within.outerWidth(),
11841 collisionPosLeft = position.left - data.collisionPosition.marginLeft,
11842 overLeft = withinOffset - collisionPosLeft,
11843 overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset,
11844 newOverRight,
11845 newOverLeft;
11846
11847 // element is wider than within
11848 if ( data.collisionWidth > outerWidth ) {
11849 // element is initially over the left side of within
11850 if ( overLeft > 0 && overRight <= 0 ) {
11851 newOverRight = position.left + overLeft + data.collisionWidth - outerWidth - withinOffset;
11852 position.left += overLeft - newOverRight;
11853 // element is initially over right side of within
11854 } else if ( overRight > 0 && overLeft <= 0 ) {
11855 position.left = withinOffset;
11856 // element is initially over both left and right sides of within
11857 } else {
11858 if ( overLeft > overRight ) {
11859 position.left = withinOffset + outerWidth - data.collisionWidth;
11860 } else {
11861 position.left = withinOffset;
11862 }
11863 }
11864 // too far left -> align with left edge
11865 } else if ( overLeft > 0 ) {
11866 position.left += overLeft;
11867 // too far right -> align with right edge
11868 } else if ( overRight > 0 ) {
11869 position.left -= overRight;
11870 // adjust based on position and margin
11871 } else {
11872 position.left = Math.max( position.left - collisionPosLeft, position.left );
11873 }
11874 },
11875 top: function( position, data ) {
11876 var within = data.within,
11877 win = $( window ),
11878 isWindow = $.isWindow( data.within[0] ),
11879 withinOffset = isWindow ? win.scrollTop() : within.offset().top,
11880 outerHeight = isWindow ? win.height() : within.outerHeight(),
11881 collisionPosTop = position.top - data.collisionPosition.marginTop,
11882 overTop = withinOffset - collisionPosTop,
11883 overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset,
11884 newOverTop,
11885 newOverBottom;
11886
11887 // element is taller than within
11888 if ( data.collisionHeight > outerHeight ) {
11889 // element is initially over the top of within
11890 if ( overTop > 0 && overBottom <= 0 ) {
11891 newOverBottom = position.top + overTop + data.collisionHeight - outerHeight - withinOffset;
11892 position.top += overTop - newOverBottom;
11893 // element is initially over bottom of within
11894 } else if ( overBottom > 0 && overTop <= 0 ) {
11895 position.top = withinOffset;
11896 // element is initially over both top and bottom of within
11897 } else {
11898 if ( overTop > overBottom ) {
11899 position.top = withinOffset + outerHeight - data.collisionHeight;
11900 } else {
11901 position.top = withinOffset;
11902 }
11903 }
11904 // too far up -> align with top
11905 } else if ( overTop > 0 ) {
11906 position.top += overTop;
11907 // too far down -> align with bottom edge
11908 } else if ( overBottom > 0 ) {
11909 position.top -= overBottom;
11910 // adjust based on position and margin
11911 } else {
11912 position.top = Math.max( position.top - collisionPosTop, position.top );
11913 }
11914 }
11915 },
11916 flip: {
11917 left: function( position, data ) {
11918 if ( data.at[ 0 ] === center ) {
11919 return;
11920 }
11921
11922 data.elem
11923 .removeClass( "ui-flipped-left ui-flipped-right" );
11924
11925 var within = data.within,
11926 win = $( window ),
11927 isWindow = $.isWindow( data.within[0] ),
11928 withinOffset = ( isWindow ? 0 : within.offset().left ) + within.scrollLeft(),
11929 outerWidth = isWindow ? within.width() : within.outerWidth(),
11930 collisionPosLeft = position.left - data.collisionPosition.marginLeft,
11931 overLeft = collisionPosLeft - withinOffset,
11932 overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset,
11933 left = data.my[ 0 ] === "left",
11934 myOffset = data.my[ 0 ] === "left" ?
11935 -data.elemWidth :
11936 data.my[ 0 ] === "right" ?
11937 data.elemWidth :
11938 0,
11939 atOffset = data.at[ 0 ] === "left" ?
11940 data.targetWidth :
11941 -data.targetWidth,
11942 offset = -2 * data.offset[ 0 ],
11943 newOverRight,
11944 newOverLeft;
11945
11946 if ( overLeft < 0 ) {
11947 newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth - outerWidth - withinOffset;
11948 if ( newOverRight < 0 || newOverRight < Math.abs( overLeft ) ) {
11949 data.elem
11950 .addClass( "ui-flipped-right" );
11951
11952 position.left += myOffset + atOffset + offset;
11953 }
11954 }
11955 else if ( overRight > 0 ) {
11956 newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset + atOffset + offset - withinOffset;
11957 if ( newOverLeft > 0 || Math.abs( newOverLeft ) < overRight ) {
11958 data.elem
11959 .addClass( "ui-flipped-left" );
11960
11961 position.left += myOffset + atOffset + offset;
11962 }
11963 }
11964 },
11965 top: function( position, data ) {
11966 if ( data.at[ 1 ] === center ) {
11967 return;
11968 }
11969
11970 data.elem
11971 .removeClass( "ui-flipped-top ui-flipped-bottom" );
11972
11973 var within = data.within,
11974 win = $( window ),
11975 isWindow = $.isWindow( data.within[0] ),
11976 withinOffset = ( isWindow ? 0 : within.offset().top ) + within.scrollTop(),
11977 outerHeight = isWindow ? within.height() : within.outerHeight(),
11978 collisionPosTop = position.top - data.collisionPosition.marginTop,
11979 overTop = collisionPosTop - withinOffset,
11980 overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset,
11981 top = data.my[ 1 ] === "top",
11982 myOffset = top ?
11983 -data.elemHeight :
11984 data.my[ 1 ] === "bottom" ?
11985 data.elemHeight :
11986 0,
11987 atOffset = data.at[ 1 ] === "top" ?
11988 data.targetHeight :
11989 -data.targetHeight,
11990 offset = -2 * data.offset[ 1 ],
11991 newOverTop,
11992 newOverBottom;
11993 if ( overTop < 0 ) {
11994 newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight - outerHeight - withinOffset;
11995 if ( ( position.top + myOffset + atOffset + offset) > overTop && ( newOverBottom < 0 || newOverBottom < Math.abs( overTop ) ) ) {
11996 data.elem
11997 .addClass( "ui-flipped-bottom" );
11998
11999 position.top += myOffset + atOffset + offset;
12000 }
12001 }
12002 else if ( overBottom > 0 ) {
12003 newOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset + offset - withinOffset;
12004 if ( ( position.top + myOffset + atOffset + offset) > overBottom && ( newOverTop > 0 || Math.abs( newOverTop ) < overBottom ) ) {
12005 data.elem
12006 .addClass( "ui-flipped-top" );
12007
12008 position.top += myOffset + atOffset + offset;
12009 }
12010 }
12011 }
12012 },
12013 flipfit: {
12014 left: function() {
12015 $.ui.position.flip.left.apply( this, arguments );
12016 $.ui.position.fit.left.apply( this, arguments );
12017 },
12018 top: function() {
12019 $.ui.position.flip.top.apply( this, arguments );
12020 $.ui.position.fit.top.apply( this, arguments );
12021 }
12022 }
12023 };
12024
12025 // fraction support test
12026 (function () {
12027 var testElement, testElementParent, testElementStyle, offsetLeft, i
12028 body = document.getElementsByTagName( "body" )[ 0 ],
12029 div = document.createElement( "div" );
12030
12031 //Create a "fake body" for testing based on method used in jQuery.support
12032 testElement = document.createElement( body ? "div" : "body" );
12033 testElementStyle = {
12034 visibility: "hidden",
12035 width: 0,
12036 height: 0,
12037 border: 0,
12038 margin: 0,
12039 background: "none"
12040 };
12041 if ( body ) {
12042 jQuery.extend( testElementStyle, {
12043 position: "absolute",
12044 left: "-1000px",
12045 top: "-1000px"
12046 });
12047 }
12048 for ( i in testElementStyle ) {
12049 testElement.style[ i ] = testElementStyle[ i ];
12050 }
12051 testElement.appendChild( div );
12052 testElementParent = body || document.documentElement;
12053 testElementParent.insertBefore( testElement, testElementParent.firstChild );
12054
12055 div.style.cssText = "position: absolute; left: 10.7432222px;";
12056
12057 offsetLeft = $( div ).offset().left;
12058 $.support.offsetFractions = offsetLeft > 10 && offsetLeft < 11;
12059
12060 testElement.innerHTML = "";
12061 testElementParent.removeChild( testElement );
12062 })();
12063
12064 // DEPRECATED
12065 if ( $.uiBackCompat !== false ) {
12066 // offset option
12067 (function( $ ) {
12068 var _position = $.fn.position;
12069 $.fn.position = function( options ) {
12070 if ( !options || !options.offset ) {
12071 return _position.call( this, options );
12072 }
12073 var offset = options.offset.split( " " ),
12074 at = options.at.split( " " );
12075 if ( offset.length === 1 ) {
12076 offset[ 1 ] = offset[ 0 ];
12077 }
12078 if ( /^\d/.test( offset[ 0 ] ) ) {
12079 offset[ 0 ] = "+" + offset[ 0 ];
12080 }
12081 if ( /^\d/.test( offset[ 1 ] ) ) {
12082 offset[ 1 ] = "+" + offset[ 1 ];
12083 }
12084 if ( at.length === 1 ) {
12085 if ( /left|center|right/.test( at[ 0 ] ) ) {
12086 at[ 1 ] = "center";
12087 } else {
12088 at[ 1 ] = at[ 0 ];
12089 at[ 0 ] = "center";
12090 }
12091 }
12092 return _position.call( this, $.extend( options, {
12093 at: at[ 0 ] + offset[ 0 ] + " " + at[ 1 ] + offset[ 1 ],
12094 offset: undefined
12095 } ) );
12096 }
12097 }( jQuery ) );
12098 }
12099
12100 }( jQuery ) );
12101 /*
12102 * jQuery UI Progressbar @VERSION
12103 *
12104 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
12105 * Dual licensed under the MIT or GPL Version 2 licenses.
12106 * http://jquery.org/license
12107 *
12108 * http://docs.jquery.com/UI/Progressbar
12109 *
12110 * Depends:
12111 * jquery.ui.core.js
12112 * jquery.ui.widget.js
12113 */
12114 (function( $, undefined ) {
12115
12116 $.widget( "ui.progressbar", {
12117 version: "@VERSION",
12118 options: {
12119 value: 0,
12120 max: 100
12121 },
12122
12123 min: 0,
12124
12125 _create: function() {
12126 this.element
12127 .addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
12128 .attr({
12129 role: "progressbar",
12130 "aria-valuemin": this.min,
12131 "aria-valuemax": this.options.max,
12132 "aria-valuenow": this._value()
12133 });
12134
12135 this.valueDiv = $( "<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>" )
12136 .appendTo( this.element );
12137
12138 this.oldValue = this._value();
12139 this._refreshValue();
12140 },
12141
12142 _destroy: function() {
12143 this.element
12144 .removeClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
12145 .removeAttr( "role" )
12146 .removeAttr( "aria-valuemin" )
12147 .removeAttr( "aria-valuemax" )
12148 .removeAttr( "aria-valuenow" );
12149
12150 this.valueDiv.remove();
12151 },
12152
12153 value: function( newValue ) {
12154 if ( newValue === undefined ) {
12155 return this._value();
12156 }
12157
12158 this._setOption( "value", newValue );
12159 return this;
12160 },
12161
12162 _setOption: function( key, value ) {
12163 if ( key === "value" ) {
12164 this.options.value = value;
12165 this._refreshValue();
12166 if ( this._value() === this.options.max ) {
12167 this._trigger( "complete" );
12168 }
12169 }
12170
12171 this._super( key, value );
12172 },
12173
12174 _value: function() {
12175 var val = this.options.value;
12176 // normalize invalid value
12177 if ( typeof val !== "number" ) {
12178 val = 0;
12179 }
12180 return Math.min( this.options.max, Math.max( this.min, val ) );
12181 },
12182
12183 _percentage: function() {
12184 return 100 * this._value() / this.options.max;
12185 },
12186
12187 _refreshValue: function() {
12188 var value = this.value();
12189 var percentage = this._percentage();
12190
12191 if ( this.oldValue !== value ) {
12192 this.oldValue = value;
12193 this._trigger( "change" );
12194 }
12195
12196 this.valueDiv
12197 .toggle( value > this.min )
12198 .toggleClass( "ui-corner-right", value === this.options.max )
12199 .width( percentage.toFixed(0) + "%" );
12200 this.element.attr( "aria-valuenow", value );
12201 }
12202 });
12203
12204 })( jQuery );
12205 /*
12206 * jQuery UI Slider @VERSION
12207 *
12208 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
12209 * Dual licensed under the MIT or GPL Version 2 licenses.
12210 * http://jquery.org/license
12211 *
12212 * http://docs.jquery.com/UI/Slider
12213 *
12214 * Depends:
12215 * jquery.ui.core.js
12216 * jquery.ui.mouse.js
12217 * jquery.ui.widget.js
12218 */
12219 (function( $, undefined ) {
12220
12221 // number of pages in a slider
12222 // (how many times can you page up/down to go through the whole range)
12223 var numPages = 5;
12224
12225 $.widget( "ui.slider", $.ui.mouse, {
12226 version: "@VERSION",
12227 widgetEventPrefix: "slide",
12228
12229 options: {
12230 animate: false,
12231 distance: 0,
12232 max: 100,
12233 min: 0,
12234 orientation: "horizontal",
12235 range: false,
12236 step: 1,
12237 value: 0,
12238 values: null
12239 },
12240
12241 _create: function() {
12242 var self = this,
12243 o = this.options,
12244 existingHandles = this.element.find( ".ui-slider-handle" ).addClass( "ui-state-default ui-corner-all" ),
12245 handle = "<a class='ui-slider-handle ui-state-default ui-corner-all' href='#'></a>",
12246 handleCount = ( o.values && o.values.length ) || 1,
12247 handles = [];
12248
12249 this._keySliding = false;
12250 this._mouseSliding = false;
12251 this._animateOff = true;
12252 this._handleIndex = null;
12253 this._detectOrientation();
12254 this._mouseInit();
12255
12256 this.element
12257 .addClass( "ui-slider" +
12258 " ui-slider-" + this.orientation +
12259 " ui-widget" +
12260 " ui-widget-content" +
12261 " ui-corner-all" +
12262 ( o.disabled ? " ui-slider-disabled ui-disabled" : "" ) );
12263
12264 this.range = $([]);
12265
12266 if ( o.range ) {
12267 if ( o.range === true ) {
12268 if ( !o.values ) {
12269 o.values = [ this._valueMin(), this._valueMin() ];
12270 }
12271 if ( o.values.length && o.values.length !== 2 ) {
12272 o.values = [ o.values[0], o.values[0] ];
12273 }
12274 }
12275
12276 this.range = $( "<div></div>" )
12277 .appendTo( this.element )
12278 .addClass( "ui-slider-range" +
12279 // note: this isn't the most fittingly semantic framework class for this element,
12280 // but worked best visually with a variety of themes
12281 " ui-widget-header" +
12282 ( ( o.range === "min" || o.range === "max" ) ? " ui-slider-range-" + o.range : "" ) );
12283 }
12284
12285 for ( var i = existingHandles.length; i < handleCount; i += 1 ) {
12286 handles.push( handle );
12287 }
12288
12289 this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( self.element ) );
12290
12291 this.handle = this.handles.eq( 0 );
12292
12293 this.handles.add( this.range ).filter( "a" )
12294 .click(function( event ) {
12295 event.preventDefault();
12296 })
12297 .hover(function() {
12298 if ( !o.disabled ) {
12299 $( this ).addClass( "ui-state-hover" );
12300 }
12301 }, function() {
12302 $( this ).removeClass( "ui-state-hover" );
12303 })
12304 .focus(function() {
12305 if ( !o.disabled ) {
12306 $( ".ui-slider .ui-state-focus" ).removeClass( "ui-state-focus" );
12307 $( this ).addClass( "ui-state-focus" );
12308 } else {
12309 $( this ).blur();
12310 }
12311 })
12312 .blur(function() {
12313 $( this ).removeClass( "ui-state-focus" );
12314 });
12315
12316 this.handles.each(function( i ) {
12317 $( this ).data( "index.ui-slider-handle", i );
12318 });
12319
12320 this.handles
12321 .keydown(function( event ) {
12322 var ret = true,
12323 index = $( this ).data( "index.ui-slider-handle" ),
12324 allowed,
12325 curVal,
12326 newVal,
12327 step;
12328
12329 if ( self.options.disabled ) {
12330 return;
12331 }
12332
12333 switch ( event.keyCode ) {
12334 case $.ui.keyCode.HOME:
12335 case $.ui.keyCode.END:
12336 case $.ui.keyCode.PAGE_UP:
12337 case $.ui.keyCode.PAGE_DOWN:
12338 case $.ui.keyCode.UP:
12339 case $.ui.keyCode.RIGHT:
12340 case $.ui.keyCode.DOWN:
12341 case $.ui.keyCode.LEFT:
12342 ret = false;
12343 if ( !self._keySliding ) {
12344 self._keySliding = true;
12345 $( this ).addClass( "ui-state-active" );
12346 allowed = self._start( event, index );
12347 if ( allowed === false ) {
12348 return;
12349 }
12350 }
12351 break;
12352 }
12353
12354 step = self.options.step;
12355 if ( self.options.values && self.options.values.length ) {
12356 curVal = newVal = self.values( index );
12357 } else {
12358 curVal = newVal = self.value();
12359 }
12360
12361 switch ( event.keyCode ) {
12362 case $.ui.keyCode.HOME:
12363 newVal = self._valueMin();
12364 break;
12365 case $.ui.keyCode.END:
12366 newVal = self._valueMax();
12367 break;
12368 case $.ui.keyCode.PAGE_UP:
12369 newVal = self._trimAlignValue( curVal + ( (self._valueMax() - self._valueMin()) / numPages ) );
12370 break;
12371 case $.ui.keyCode.PAGE_DOWN:
12372 newVal = self._trimAlignValue( curVal - ( (self._valueMax() - self._valueMin()) / numPages ) );
12373 break;
12374 case $.ui.keyCode.UP:
12375 case $.ui.keyCode.RIGHT:
12376 if ( curVal === self._valueMax() ) {
12377 return;
12378 }
12379 newVal = self._trimAlignValue( curVal + step );
12380 break;
12381 case $.ui.keyCode.DOWN:
12382 case $.ui.keyCode.LEFT:
12383 if ( curVal === self._valueMin() ) {
12384 return;
12385 }
12386 newVal = self._trimAlignValue( curVal - step );
12387 break;
12388 }
12389
12390 self._slide( event, index, newVal );
12391
12392 return ret;
12393
12394 })
12395 .keyup(function( event ) {
12396 var index = $( this ).data( "index.ui-slider-handle" );
12397
12398 if ( self._keySliding ) {
12399 self._keySliding = false;
12400 self._stop( event, index );
12401 self._change( event, index );
12402 $( this ).removeClass( "ui-state-active" );
12403 }
12404
12405 });
12406
12407 this._refreshValue();
12408
12409 this._animateOff = false;
12410 },
12411
12412 destroy: function() {
12413 this.handles.remove();
12414 this.range.remove();
12415
12416 this.element
12417 .removeClass( "ui-slider" +
12418 " ui-slider-horizontal" +
12419 " ui-slider-vertical" +
12420 " ui-slider-disabled" +
12421 " ui-widget" +
12422 " ui-widget-content" +
12423 " ui-corner-all" )
12424 .removeData( "slider" )
12425 .unbind( ".slider" );
12426
12427 this._mouseDestroy();
12428
12429 return this;
12430 },
12431
12432 _mouseCapture: function( event ) {
12433 var o = this.options,
12434 position,
12435 normValue,
12436 distance,
12437 closestHandle,
12438 self,
12439 index,
12440 allowed,
12441 offset,
12442 mouseOverHandle;
12443
12444 if ( o.disabled ) {
12445 return false;
12446 }
12447
12448 this.elementSize = {
12449 width: this.element.outerWidth(),
12450 height: this.element.outerHeight()
12451 };
12452 this.elementOffset = this.element.offset();
12453
12454 position = { x: event.pageX, y: event.pageY };
12455 normValue = this._normValueFromMouse( position );
12456 distance = this._valueMax() - this._valueMin() + 1;
12457 self = this;
12458 this.handles.each(function( i ) {
12459 var thisDistance = Math.abs( normValue - self.values(i) );
12460 if ( distance > thisDistance ) {
12461 distance = thisDistance;
12462 closestHandle = $( this );
12463 index = i;
12464 }
12465 });
12466
12467 // workaround for bug #3736 (if both handles of a range are at 0,
12468 // the first is always used as the one with least distance,
12469 // and moving it is obviously prevented by preventing negative ranges)
12470 if( o.range === true && this.values(1) === o.min ) {
12471 index += 1;
12472 closestHandle = $( this.handles[index] );
12473 }
12474
12475 allowed = this._start( event, index );
12476 if ( allowed === false ) {
12477 return false;
12478 }
12479 this._mouseSliding = true;
12480
12481 self._handleIndex = index;
12482
12483 closestHandle
12484 .addClass( "ui-state-active" )
12485 .focus();
12486
12487 offset = closestHandle.offset();
12488 mouseOverHandle = !$( event.target ).parents().andSelf().is( ".ui-slider-handle" );
12489 this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
12490 left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
12491 top: event.pageY - offset.top -
12492 ( closestHandle.height() / 2 ) -
12493 ( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) -
12494 ( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) +
12495 ( parseInt( closestHandle.css("marginTop"), 10 ) || 0)
12496 };
12497
12498 if ( !this.handles.hasClass( "ui-state-hover" ) ) {
12499 this._slide( event, index, normValue );
12500 }
12501 this._animateOff = true;
12502 return true;
12503 },
12504
12505 _mouseStart: function( event ) {
12506 return true;
12507 },
12508
12509 _mouseDrag: function( event ) {
12510 var position = { x: event.pageX, y: event.pageY },
12511 normValue = this._normValueFromMouse( position );
12512
12513 this._slide( event, this._handleIndex, normValue );
12514
12515 return false;
12516 },
12517
12518 _mouseStop: function( event ) {
12519 this.handles.removeClass( "ui-state-active" );
12520 this._mouseSliding = false;
12521
12522 this._stop( event, this._handleIndex );
12523 this._change( event, this._handleIndex );
12524
12525 this._handleIndex = null;
12526 this._clickOffset = null;
12527 this._animateOff = false;
12528
12529 return false;
12530 },
12531
12532 _detectOrientation: function() {
12533 this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
12534 },
12535
12536 _normValueFromMouse: function( position ) {
12537 var pixelTotal,
12538 pixelMouse,
12539 percentMouse,
12540 valueTotal,
12541 valueMouse;
12542
12543 if ( this.orientation === "horizontal" ) {
12544 pixelTotal = this.elementSize.width;
12545 pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 );
12546 } else {
12547 pixelTotal = this.elementSize.height;
12548 pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 );
12549 }
12550
12551 percentMouse = ( pixelMouse / pixelTotal );
12552 if ( percentMouse > 1 ) {
12553 percentMouse = 1;
12554 }
12555 if ( percentMouse < 0 ) {
12556 percentMouse = 0;
12557 }
12558 if ( this.orientation === "vertical" ) {
12559 percentMouse = 1 - percentMouse;
12560 }
12561
12562 valueTotal = this._valueMax() - this._valueMin();
12563 valueMouse = this._valueMin() + percentMouse * valueTotal;
12564
12565 return this._trimAlignValue( valueMouse );
12566 },
12567
12568 _start: function( event, index ) {
12569 var uiHash = {
12570 handle: this.handles[ index ],
12571 value: this.value()
12572 };
12573 if ( this.options.values && this.options.values.length ) {
12574 uiHash.value = this.values( index );
12575 uiHash.values = this.values();
12576 }
12577 return this._trigger( "start", event, uiHash );
12578 },
12579
12580 _slide: function( event, index, newVal ) {
12581 var otherVal,
12582 newValues,
12583 allowed;
12584
12585 if ( this.options.values && this.options.values.length ) {
12586 otherVal = this.values( index ? 0 : 1 );
12587
12588 if ( ( this.options.values.length === 2 && this.options.range === true ) &&
12589 ( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) )
12590 ) {
12591 newVal = otherVal;
12592 }
12593
12594 if ( newVal !== this.values( index ) ) {
12595 newValues = this.values();
12596 newValues[ index ] = newVal;
12597 // A slide can be canceled by returning false from the slide callback
12598 allowed = this._trigger( "slide", event, {
12599 handle: this.handles[ index ],
12600 value: newVal,
12601 values: newValues
12602 } );
12603 otherVal = this.values( index ? 0 : 1 );
12604 if ( allowed !== false ) {
12605 this.values( index, newVal, true );
12606 }
12607 }
12608 } else {
12609 if ( newVal !== this.value() ) {
12610 // A slide can be canceled by returning false from the slide callback
12611 allowed = this._trigger( "slide", event, {
12612 handle: this.handles[ index ],
12613 value: newVal
12614 } );
12615 if ( allowed !== false ) {
12616 this.value( newVal );
12617 }
12618 }
12619 }
12620 },
12621
12622 _stop: function( event, index ) {
12623 var uiHash = {
12624 handle: this.handles[ index ],
12625 value: this.value()
12626 };
12627 if ( this.options.values && this.options.values.length ) {
12628 uiHash.value = this.values( index );
12629 uiHash.values = this.values();
12630 }
12631
12632 this._trigger( "stop", event, uiHash );
12633 },
12634
12635 _change: function( event, index ) {
12636 if ( !this._keySliding && !this._mouseSliding ) {
12637 var uiHash = {
12638 handle: this.handles[ index ],
12639 value: this.value()
12640 };
12641 if ( this.options.values && this.options.values.length ) {
12642 uiHash.value = this.values( index );
12643 uiHash.values = this.values();
12644 }
12645
12646 this._trigger( "change", event, uiHash );
12647 }
12648 },
12649
12650 value: function( newValue ) {
12651 if ( arguments.length ) {
12652 this.options.value = this._trimAlignValue( newValue );
12653 this._refreshValue();
12654 this._change( null, 0 );
12655 return;
12656 }
12657
12658 return this._value();
12659 },
12660
12661 values: function( index, newValue ) {
12662 var vals,
12663 newValues,
12664 i;
12665
12666 if ( arguments.length > 1 ) {
12667 this.options.values[ index ] = this._trimAlignValue( newValue );
12668 this._refreshValue();
12669 this._change( null, index );
12670 return;
12671 }
12672
12673 if ( arguments.length ) {
12674 if ( $.isArray( arguments[ 0 ] ) ) {
12675 vals = this.options.values;
12676 newValues = arguments[ 0 ];
12677 for ( i = 0; i < vals.length; i += 1 ) {
12678 vals[ i ] = this._trimAlignValue( newValues[ i ] );
12679 this._change( null, i );
12680 }
12681 this._refreshValue();
12682 } else {
12683 if ( this.options.values && this.options.values.length ) {
12684 return this._values( index );
12685 } else {
12686 return this.value();
12687 }
12688 }
12689 } else {
12690 return this._values();
12691 }
12692 },
12693
12694 _setOption: function( key, value ) {
12695 var i,
12696 valsLength = 0;
12697
12698 if ( $.isArray( this.options.values ) ) {
12699 valsLength = this.options.values.length;
12700 }
12701
12702 $.Widget.prototype._setOption.apply( this, arguments );
12703
12704 switch ( key ) {
12705 case "disabled":
12706 if ( value ) {
12707 this.handles.filter( ".ui-state-focus" ).blur();
12708 this.handles.removeClass( "ui-state-hover" );
12709 this.handles.prop( "disabled", true );
12710 this.element.addClass( "ui-disabled" );
12711 } else {
12712 this.handles.prop( "disabled", false );
12713 this.element.removeClass( "ui-disabled" );
12714 }
12715 break;
12716 case "orientation":
12717 this._detectOrientation();
12718 this.element
12719 .removeClass( "ui-slider-horizontal ui-slider-vertical" )
12720 .addClass( "ui-slider-" + this.orientation );
12721 this._refreshValue();
12722 break;
12723 case "value":
12724 this._animateOff = true;
12725 this._refreshValue();
12726 this._change( null, 0 );
12727 this._animateOff = false;
12728 break;
12729 case "values":
12730 this._animateOff = true;
12731 this._refreshValue();
12732 for ( i = 0; i < valsLength; i += 1 ) {
12733 this._change( null, i );
12734 }
12735 this._animateOff = false;
12736 break;
12737 }
12738 },
12739
12740 //internal value getter
12741 // _value() returns value trimmed by min and max, aligned by step
12742 _value: function() {
12743 var val = this.options.value;
12744 val = this._trimAlignValue( val );
12745
12746 return val;
12747 },
12748
12749 //internal values getter
12750 // _values() returns array of values trimmed by min and max, aligned by step
12751 // _values( index ) returns single value trimmed by min and max, aligned by step
12752 _values: function( index ) {
12753 var val,
12754 vals,
12755 i;
12756
12757 if ( arguments.length ) {
12758 val = this.options.values[ index ];
12759 val = this._trimAlignValue( val );
12760
12761 return val;
12762 } else {
12763 // .slice() creates a copy of the array
12764 // this copy gets trimmed by min and max and then returned
12765 vals = this.options.values.slice();
12766 for ( i = 0; i < vals.length; i+= 1) {
12767 vals[ i ] = this._trimAlignValue( vals[ i ] );
12768 }
12769
12770 return vals;
12771 }
12772 },
12773
12774 // returns the step-aligned value that val is closest to, between (inclusive) min and max
12775 _trimAlignValue: function( val ) {
12776 if ( val <= this._valueMin() ) {
12777 return this._valueMin();
12778 }
12779 if ( val >= this._valueMax() ) {
12780 return this._valueMax();
12781 }
12782 var step = ( this.options.step > 0 ) ? this.options.step : 1,
12783 valModStep = (val - this._valueMin()) % step,
12784 alignValue = val - valModStep;
12785
12786 if ( Math.abs(valModStep) * 2 >= step ) {
12787 alignValue += ( valModStep > 0 ) ? step : ( -step );
12788 }
12789
12790 // Since JavaScript has problems with large floats, round
12791 // the final value to 5 digits after the decimal point (see #4124)
12792 return parseFloat( alignValue.toFixed(5) );
12793 },
12794
12795 _valueMin: function() {
12796 return this.options.min;
12797 },
12798
12799 _valueMax: function() {
12800 return this.options.max;
12801 },
12802
12803 _refreshValue: function() {
12804 var oRange = this.options.range,
12805 o = this.options,
12806 self = this,
12807 animate = ( !this._animateOff ) ? o.animate : false,
12808 valPercent,
12809 _set = {},
12810 lastValPercent,
12811 value,
12812 valueMin,
12813 valueMax;
12814
12815 if ( this.options.values && this.options.values.length ) {
12816 this.handles.each(function( i, j ) {
12817 valPercent = ( self.values(i) - self._valueMin() ) / ( self._valueMax() - self._valueMin() ) * 100;
12818 _set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
12819 $( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
12820 if ( self.options.range === true ) {
12821 if ( self.orientation === "horizontal" ) {
12822 if ( i === 0 ) {
12823 self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate );
12824 }
12825 if ( i === 1 ) {
12826 self.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
12827 }
12828 } else {
12829 if ( i === 0 ) {
12830 self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate );
12831 }
12832 if ( i === 1 ) {
12833 self.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
12834 }
12835 }
12836 }
12837 lastValPercent = valPercent;
12838 });
12839 } else {
12840 value = this.value();
12841 valueMin = this._valueMin();
12842 valueMax = this._valueMax();
12843 valPercent = ( valueMax !== valueMin ) ?
12844 ( value - valueMin ) / ( valueMax - valueMin ) * 100 :
12845 0;
12846 _set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
12847 this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
12848
12849 if ( oRange === "min" && this.orientation === "horizontal" ) {
12850 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate );
12851 }
12852 if ( oRange === "max" && this.orientation === "horizontal" ) {
12853 this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
12854 }
12855 if ( oRange === "min" && this.orientation === "vertical" ) {
12856 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate );
12857 }
12858 if ( oRange === "max" && this.orientation === "vertical" ) {
12859 this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
12860 }
12861 }
12862 }
12863
12864 });
12865
12866 }(jQuery));
12867 /*
12868 * jQuery UI Spinner @VERSION
12869 *
12870 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
12871 * Dual licensed under the MIT or GPL Version 2 licenses.
12872 * http://jquery.org/license
12873 *
12874 * http://docs.jquery.com/UI/Spinner
12875 *
12876 * Depends:
12877 * jquery.ui.core.js
12878 * jquery.ui.widget.js
12879 * jquery.ui.button.js
12880 */
12881 (function( $ ) {
12882
12883 function modifier( fn ) {
12884 return function() {
12885 var previous = this.element.val();
12886 fn.apply( this, arguments );
12887 this._refresh();
12888 if ( previous !== this.element.val() ) {
12889 this._trigger( "change" );
12890 }
12891 };
12892 }
12893
12894 $.widget( "ui.spinner", {
12895 version: "@VERSION",
12896 defaultElement: "<input>",
12897 widgetEventPrefix: "spin",
12898 options: {
12899 culture: null,
12900 incremental: true,
12901 max: null,
12902 min: null,
12903 numberFormat: null,
12904 page: 10,
12905 step: 1,
12906
12907 change: null,
12908 spin: null,
12909 start: null,
12910 stop: null
12911 },
12912
12913 _create: function() {
12914 this._value( this.element.val(), true );
12915 this._draw();
12916 this._bind( this._events );
12917 this._refresh();
12918
12919 // turning off autocomplete prevents the browser from remembering the
12920 // value when navigating through history, so we re-enable autocomplete
12921 // if the page is unloaded before the widget is destroyed. #7790
12922 this._bind( this.window, {
12923 beforeunload: function() {
12924 this.element.removeAttr( "autocomplete" );
12925 }
12926 });
12927 },
12928
12929 _getCreateOptions: function() {
12930 var options = {},
12931 element = this.element;
12932
12933 $.each( [ "min", "max", "step" ], function( i, option ) {
12934 var value = element.attr( option );
12935 if ( value !== undefined && value.length ) {
12936 options[ option ] = value;
12937 }
12938 });
12939
12940 return options;
12941 },
12942
12943 _events: {
12944 keydown: function( event ) {
12945 if ( this._start( event ) && this._keydown( event ) ) {
12946 event.preventDefault();
12947 }
12948 },
12949 keyup: "_stop",
12950 focus: function() {
12951 this.uiSpinner.addClass( "ui-state-active" );
12952 this.previous = this.element.val();
12953 },
12954 blur: function( event ) {
12955 this._refresh();
12956 this.uiSpinner.removeClass( "ui-state-active" );
12957 if ( this.previous !== this.element.val() ) {
12958 this._trigger( "change", event );
12959 }
12960 },
12961 mousewheel: function( event, delta ) {
12962 if ( !delta ) {
12963 return;
12964 }
12965 if ( !this.spinning && !this._start( event ) ) {
12966 return false;
12967 }
12968
12969 this._spin( (delta > 0 ? 1 : -1) * this.options.step, event );
12970 clearTimeout( this.mousewheelTimer );
12971 this.mousewheelTimer = this._delay(function() {
12972 if ( this.spinning ) {
12973 this._stop( event );
12974 }
12975 }, 100 );
12976 event.preventDefault();
12977 },
12978 "mousedown .ui-spinner-button": function( event ) {
12979 // ensure focus is on (or stays on) the text field
12980 event.preventDefault();
12981 if ( this.document[0].activeElement !== this.element[ 0 ] ) {
12982 this.element.focus();
12983 }
12984
12985 if ( this._start( event ) === false ) {
12986 return;
12987 }
12988
12989 this._repeat( null, $( event.currentTarget ).hasClass( "ui-spinner-up" ) ? 1 : -1, event );
12990 },
12991 "mouseup .ui-spinner-button": "_stop",
12992 "mouseenter .ui-spinner-button": function( event ) {
12993 // button will add ui-state-active if mouse was down while mouseleave and kept down
12994 if ( !$( event.currentTarget ).hasClass( "ui-state-active" ) ) {
12995 return;
12996 }
12997
12998 if ( this._start( event ) === false ) {
12999 return false;
13000 }
13001 this._repeat( null, $( event.currentTarget ).hasClass( "ui-spinner-up" ) ? 1 : -1, event );
13002 },
13003 // TODO: do we really want to consider this a stop?
13004 // shouldn't we just stop the repeater and wait until mouseup before
13005 // we trigger the stop event?
13006 "mouseleave .ui-spinner-button": "_stop"
13007 },
13008
13009 _draw: function() {
13010 var uiSpinner = this.uiSpinner = this.element
13011 .addClass( "ui-spinner-input" )
13012 .attr( "autocomplete", "off" )
13013 .wrap( this._uiSpinnerHtml() )
13014 .parent()
13015 // add buttons
13016 .append( this._buttonHtml() );
13017 this._hoverable( uiSpinner );
13018
13019 this.element.attr( "role", "spinbutton" );
13020
13021 // button bindings
13022 this.buttons = uiSpinner.find( ".ui-spinner-button" )
13023 .attr( "tabIndex", -1 )
13024 .button()
13025 .removeClass( "ui-corner-all" );
13026
13027 // IE 6 doesn't understand height: 50% for the buttons
13028 // unless the wrapper has an explicit height
13029 if ( this.buttons.height() > Math.ceil( uiSpinner.height() * 0.5 ) &&
13030 uiSpinner.height() > 0 ) {
13031 uiSpinner.height( uiSpinner.height() );
13032 }
13033
13034 // disable spinner if element was already disabled
13035 if ( this.options.disabled ) {
13036 this.disable();
13037 }
13038 },
13039
13040 _keydown: function( event ) {
13041 var options = this.options,
13042 keyCode = $.ui.keyCode;
13043
13044 switch ( event.keyCode ) {
13045 case keyCode.UP:
13046 this._repeat( null, 1, event );
13047 return true;
13048 case keyCode.DOWN:
13049 this._repeat( null, -1, event );
13050 return true;
13051 case keyCode.PAGE_UP:
13052 this._repeat( null, options.page, event );
13053 return true;
13054 case keyCode.PAGE_DOWN:
13055 this._repeat( null, -options.page, event );
13056 return true;
13057 }
13058
13059 return false;
13060 },
13061
13062 _uiSpinnerHtml: function() {
13063 return "<span class='ui-spinner ui-state-default ui-widget ui-widget-content ui-corner-all'></span>";
13064 },
13065
13066 _buttonHtml: function() {
13067 return "" +
13068 "<a class='ui-spinner-button ui-spinner-up ui-corner-tr'>" +
13069 "<span class='ui-icon ui-icon-triangle-1-n'>&#9650;</span>" +
13070 "</a>" +
13071 "<a class='ui-spinner-button ui-spinner-down ui-corner-br'>" +
13072 "<span class='ui-icon ui-icon-triangle-1-s'>&#9660;</span>" +
13073 "</a>";
13074 },
13075
13076 _start: function( event ) {
13077 if ( !this.spinning && this._trigger( "start", event ) === false ) {
13078 return false;
13079 }
13080
13081 if ( !this.counter ) {
13082 this.counter = 1;
13083 }
13084 this.spinning = true;
13085 return true;
13086 },
13087
13088 _repeat: function( i, steps, event ) {
13089 i = i || 500;
13090
13091 clearTimeout( this.timer );
13092 this.timer = this._delay(function() {
13093 this._repeat( 40, steps, event );
13094 }, i );
13095
13096 this._spin( steps * this.options.step, event );
13097 },
13098
13099 _spin: function( step, event ) {
13100 var value = this.value() || 0;
13101
13102 if ( !this.counter ) {
13103 this.counter = 1;
13104 }
13105
13106 value = this._adjustValue( value + step * this._increment( this.counter ) );
13107
13108 if ( !this.spinning || this._trigger( "spin", event, { value: value } ) !== false) {
13109 this._value( value );
13110 this.counter++;
13111 }
13112 },
13113
13114 _increment: function( i ) {
13115 var incremental = this.options.incremental;
13116
13117 if ( incremental ) {
13118 return $.isFunction( incremental ) ?
13119 incremental( i ) :
13120 Math.floor( i*i*i/50000 - i*i/500 + 17*i/200 + 1 );
13121 }
13122
13123 return 1;
13124 },
13125
13126 _precision: function() {
13127 var precision = this._precisionOf( this.options.step );
13128 if ( this.options.min !== null ) {
13129 precision = Math.max( precision, this._precisionOf( this.options.min ) );
13130 }
13131 return precision;
13132 },
13133
13134 _precisionOf: function( num ) {
13135 var str = num.toString(),
13136 decimal = str.indexOf( "." );
13137 return decimal === -1 ? 0 : str.length - decimal - 1;
13138 },
13139
13140 _adjustValue: function( value ) {
13141 var base, aboveMin,
13142 options = this.options;
13143
13144 // make sure we're at a valid step
13145 // - find out where we are relative to the base (min or 0)
13146 base = options.min !== null ? options.min : 0;
13147 aboveMin = value - base;
13148 // - round to the nearest step
13149 aboveMin = Math.round(aboveMin / options.step) * options.step;
13150 // - rounding is based on 0, so adjust back to our base
13151 value = base + aboveMin;
13152
13153 // fix precision from bad JS floating point math
13154 value = parseFloat( value.toFixed( this._precision() ) );
13155
13156 // clamp the value
13157 if ( options.max !== null && value > options.max) {
13158 return options.max;
13159 }
13160 if ( options.min !== null && value < options.min ) {
13161 return options.min;
13162 }
13163
13164 return value;
13165 },
13166
13167 _stop: function( event ) {
13168 if ( !this.spinning ) {
13169 return;
13170 }
13171
13172 clearTimeout( this.timer );
13173 clearTimeout( this.mousewheelTimer );
13174 this.counter = 0;
13175 this.spinning = false;
13176 this._trigger( "stop", event );
13177 },
13178
13179 _setOption: function( key, value ) {
13180 if ( key === "culture" || key === "numberFormat" ) {
13181 var prevValue = this._parse( this.element.val() );
13182 this.options[ key ] = value;
13183 this.element.val( this._format( prevValue ) );
13184 return;
13185 }
13186
13187 this._super( key, value );
13188
13189 if ( key === "disabled" ) {
13190 if ( value ) {
13191 this.element.prop( "disabled", true );
13192 this.buttons.button( "disable" );
13193 } else {
13194 this.element.prop( "disabled", false );
13195 this.buttons.button( "enable" );
13196 }
13197 }
13198 },
13199
13200 _setOptions: modifier(function( options ) {
13201 this._super( options );
13202 this._value( this.element.val() );
13203 }),
13204
13205 _parse: function( val ) {
13206 if ( typeof val === "string" && val !== "" ) {
13207 val = window.Globalize && this.options.numberFormat ?
13208 Globalize.parseFloat( val, 10, this.options.culture ) : +val;
13209 }
13210 return val === "" || isNaN( val ) ? null : val;
13211 },
13212
13213 _format: function( value ) {
13214 if ( value === "" ) {
13215 return "";
13216 }
13217 return window.Globalize && this.options.numberFormat ?
13218 Globalize.format( value, this.options.numberFormat, this.options.culture ) :
13219 value;
13220 },
13221
13222 _refresh: function() {
13223 this.element.attr({
13224 "aria-valuemin": this.options.min,
13225 "aria-valuemax": this.options.max,
13226 // TODO: what should we do with values that can't be parsed?
13227 "aria-valuenow": this._parse( this.element.val() )
13228 });
13229 },
13230
13231 // update the value without triggering change
13232 _value: function( value, allowAny ) {
13233 var parsed;
13234 if ( value !== "" ) {
13235 parsed = this._parse( value );
13236 if ( parsed !== null ) {
13237 if ( !allowAny ) {
13238 parsed = this._adjustValue( parsed );
13239 }
13240 value = this._format( parsed );
13241 }
13242 }
13243 this.element.val( value );
13244 this._refresh();
13245 },
13246
13247 destroy: function() {
13248 this.element
13249 .removeClass( "ui-spinner-input" )
13250 .prop( "disabled", false )
13251 .removeAttr( "autocomplete" )
13252 .removeAttr( "role" )
13253 .removeAttr( "aria-valuemin" )
13254 .removeAttr( "aria-valuemax" )
13255 .removeAttr( "aria-valuenow" );
13256 this._super();
13257 this.uiSpinner.replaceWith( this.element );
13258 },
13259
13260 stepUp: modifier(function( steps ) {
13261 this._stepUp( steps );
13262 }),
13263 _stepUp: function( steps ) {
13264 this._spin( (steps || 1) * this.options.step );
13265 },
13266
13267 stepDown: modifier(function( steps ) {
13268 this._stepDown( steps );
13269 }),
13270 _stepDown: function( steps ) {
13271 this._spin( (steps || 1) * -this.options.step );
13272 },
13273
13274 pageUp: modifier(function( pages ) {
13275 this._stepUp( (pages || 1) * this.options.page );
13276 }),
13277
13278 pageDown: modifier(function( pages ) {
13279 this._stepDown( (pages || 1) * this.options.page );
13280 }),
13281
13282 value: function( newVal ) {
13283 if ( !arguments.length ) {
13284 return this._parse( this.element.val() );
13285 }
13286 modifier( this._value ).call( this, newVal );
13287 },
13288
13289 widget: function() {
13290 return this.uiSpinner;
13291 }
13292 });
13293
13294 }( jQuery ) );
13295 /*
13296 * jQuery UI Tabs @VERSION
13297 *
13298 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
13299 * Dual licensed under the MIT or GPL Version 2 licenses.
13300 * http://jquery.org/license
13301 *
13302 * http://docs.jquery.com/UI/Tabs
13303 *
13304 * Depends:
13305 * jquery.ui.core.js
13306 * jquery.ui.widget.js
13307 */
13308 (function( $, undefined ) {
13309
13310 var tabId = 0;
13311 function getNextTabId() {
13312 return ++tabId;
13313 }
13314
13315 var isLocal = (function() {
13316 var rhash = /#.*$/,
13317 currentPage = location.href.replace( rhash, "" );
13318
13319 return function( anchor ) {
13320 // clone the node to work around IE 6 not normalizing the href property
13321 // if it's manually set, i.e., a.href = "#foo" kills the normalization
13322 anchor = anchor.cloneNode( false );
13323 return anchor.hash.length > 1 &&
13324 anchor.href.replace( rhash, "" ) === currentPage;
13325 };
13326 })();
13327
13328 $.widget( "ui.tabs", {
13329 version: "@VERSION",
13330 options: {
13331 active: null,
13332 collapsible: false,
13333 event: "click",
13334 fx: null, // e.g. { height: 'toggle', opacity: 'toggle', duration: 200 }
13335
13336 // callbacks
13337 activate: null,
13338 beforeActivate: null,
13339 beforeLoad: null,
13340 load: null
13341 },
13342
13343 _create: function() {
13344 var that = this,
13345 options = that.options,
13346 active = options.active;
13347
13348 that.running = false;
13349
13350 that.element.addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" );
13351
13352 that._processTabs();
13353
13354 if ( active === null ) {
13355 // check the fragment identifier in the URL
13356 if ( location.hash ) {
13357 that.anchors.each(function( i, tab ) {
13358 if ( tab.hash === location.hash ) {
13359 active = i;
13360 return false;
13361 }
13362 });
13363 }
13364
13365 // check for a tab marked active via a class
13366 if ( active === null ) {
13367 active = that.lis.filter( ".ui-tabs-active" ).index();
13368 }
13369
13370 // no active tab, set to false
13371 if ( active === null || active === -1 ) {
13372 active = that.lis.length ? 0 : false;
13373 }
13374 }
13375
13376 // handle numbers: negative, out of range
13377 if ( active !== false ) {
13378 active = this.lis.eq( active ).index();
13379 if ( active === -1 ) {
13380 active = options.collapsible ? false : 0;
13381 }
13382 }
13383 options.active = active;
13384
13385 // don't allow collapsible: false and active: false
13386 if ( !options.collapsible && options.active === false && this.anchors.length ) {
13387 options.active = 0;
13388 }
13389
13390 // Take disabling tabs via class attribute from HTML
13391 // into account and update option properly.
13392 if ( $.isArray( options.disabled ) ) {
13393 options.disabled = $.unique( options.disabled.concat(
13394 $.map( this.lis.filter( ".ui-state-disabled" ), function( n, i ) {
13395 return that.lis.index( n );
13396 })
13397 ) ).sort();
13398 }
13399
13400 this._setupFx( options.fx );
13401
13402 this._refresh();
13403
13404 // highlight selected tab
13405 this.panels.hide();
13406 this.lis.removeClass( "ui-tabs-active ui-state-active" );
13407 // check for length avoids error when initializing empty list
13408 if ( options.active !== false && this.anchors.length ) {
13409 this.active = this._findActive( options.active );
13410 var panel = that._getPanelForTab( this.active );
13411
13412 panel.show();
13413 this.lis.eq( options.active ).addClass( "ui-tabs-active ui-state-active" );
13414 this.load( options.active );
13415 } else {
13416 this.active = $();
13417 }
13418 },
13419
13420 _setOption: function( key, value ) {
13421 if ( key == "active" ) {
13422 // _activate() will handle invalid values and update this.options
13423 this._activate( value );
13424 return;
13425 }
13426
13427 if ( key === "disabled" ) {
13428 // don't use the widget factory's disabled handling
13429 this._setupDisabled( value );
13430 return;
13431 }
13432
13433 this._super( key, value);
13434
13435 // setting collapsible: false while collapsed; open first panel
13436 if ( key === "collapsible" && !value && this.options.active === false ) {
13437 this._activate( 0 );
13438 }
13439
13440 if ( key === "event" ) {
13441 this._setupEvents( value );
13442 }
13443
13444 if ( key === "fx" ) {
13445 this._setupFx( value );
13446 }
13447 },
13448
13449 _tabId: function( a ) {
13450 return $( a ).attr( "aria-controls" ) || "ui-tabs-" + getNextTabId();
13451 },
13452
13453 _sanitizeSelector: function( hash ) {
13454 // we need this because an id may contain a ":"
13455 return hash ? hash.replace( /[!"$%&'()*+,.\/:;<=>?@[\]^`{|}~]/g, "\\$&" ) : "";
13456 },
13457
13458 refresh: function() {
13459 var self = this,
13460 options = this.options,
13461 lis = this.list.children( ":has(a[href])" );
13462
13463 // get disabled tabs from class attribute from HTML
13464 // this will get converted to a boolean if needed in _refresh()
13465 options.disabled = $.map( lis.filter( ".ui-state-disabled" ), function( tab ) {
13466 return lis.index( tab );
13467 });
13468
13469 this._processTabs();
13470 this._refresh();
13471 this.panels.not( this._getPanelForTab( this.active ) ).hide();
13472
13473 // was collapsed or no tabs
13474 if ( options.active === false || !this.anchors.length ) {
13475 options.active = false;
13476 this.active = $();
13477 // was active, but active tab is gone
13478 } else if ( this.active.length && !$.contains( this.list[ 0 ], this.active[ 0 ] ) ) {
13479 // activate previous tab
13480 var next = options.active - 1;
13481 this._activate( next >= 0 ? next : 0 );
13482 // was active, active tab still exists
13483 } else {
13484 // make sure active index is correct
13485 options.active = this.anchors.index( this.active );
13486 }
13487 },
13488
13489 _refresh: function() {
13490 var options = this.options;
13491
13492 this.element.toggleClass( "ui-tabs-collapsible", options.collapsible );
13493 this.list.addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" );
13494 this.lis.addClass( "ui-state-default ui-corner-top" );
13495 this.panels.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" );
13496
13497 this._setupDisabled( options.disabled );
13498 this._setupEvents( options.event );
13499
13500 // remove all handlers, may run on existing tabs
13501 this.lis.unbind( ".tabs" );
13502 this._focusable( this.lis );
13503 this._hoverable( this.lis );
13504 },
13505
13506 _processTabs: function() {
13507 var self = this;
13508
13509 this.list = this.element.find( "ol,ul" ).eq( 0 );
13510 this.lis = $( " > li:has(a[href])", this.list );
13511 this.anchors = this.lis.map(function() {
13512 return $( "a", this )[ 0 ];
13513 });
13514 this.panels = $( [] );
13515
13516 this.anchors.each(function( i, a ) {
13517 var selector, panel;
13518
13519 // inline tab
13520 if ( isLocal( a ) ) {
13521 selector = a.hash;
13522 panel = self.element.find( self._sanitizeSelector( selector ) );
13523 // remote tab
13524 } else {
13525 var id = self._tabId( a );
13526 selector = "#" + id;
13527 panel = self.element.find( selector );
13528 if ( !panel.length ) {
13529 panel = self._createPanel( id );
13530 panel.insertAfter( self.panels[ i - 1 ] || self.list );
13531 }
13532 }
13533
13534 if ( panel.length) {
13535 self.panels = self.panels.add( panel );
13536 }
13537 $( a ).attr( "aria-controls", selector.substring( 1 ) );
13538 });
13539 },
13540
13541 _createPanel: function( id ) {
13542 return $( "<div></div>" )
13543 .attr( "id", id )
13544 .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
13545 .data( "destroy.tabs", true );
13546 },
13547
13548 _setupDisabled: function( disabled ) {
13549 if ( $.isArray( disabled ) ) {
13550 if ( !disabled.length ) {
13551 disabled = false;
13552 } else if ( disabled.length === this.anchors.length ) {
13553 disabled = true;
13554 }
13555 }
13556
13557 // disable tabs
13558 for ( var i = 0, li; ( li = this.lis[ i ] ); i++ ) {
13559 $( li ).toggleClass( "ui-state-disabled", ( disabled === true || $.inArray( i, disabled ) !== -1 ) );
13560 }
13561
13562 this.options.disabled = disabled;
13563 },
13564
13565 _setupFx: function( fx ) {
13566 // set up animations
13567 if ( fx ) {
13568 if ( $.isArray( fx ) ) {
13569 this.hideFx = fx[ 0 ];
13570 this.showFx = fx[ 1 ];
13571 } else {
13572 this.hideFx = this.showFx = fx;
13573 }
13574 }
13575 },
13576
13577 // TODO: remove once jQuery core properly removes filters - see #4621
13578 _resetStyle: function ( $el, fx ) {
13579 if ( !$.support.opacity && fx.opacity ) {
13580 $el[ 0 ].style.removeAttribute( "filter" );
13581 }
13582 },
13583
13584 _setupEvents: function( event ) {
13585 // attach tab event handler, unbind to avoid duplicates from former tabifying...
13586 this.anchors.unbind( ".tabs" );
13587
13588 if ( event ) {
13589 this.anchors.bind( event.split( " " ).join( ".tabs " ) + ".tabs",
13590 $.proxy( this, "_eventHandler" ) );
13591 }
13592
13593 // disable click in any case
13594 this.anchors.bind( "click.tabs", function( event ){
13595 event.preventDefault();
13596 });
13597 },
13598
13599 _eventHandler: function( event ) {
13600 var that = this,
13601 options = that.options,
13602 active = that.active,
13603 clicked = $( event.currentTarget ),
13604 clickedIsActive = clicked[ 0 ] === active[ 0 ],
13605 collapsing = clickedIsActive && options.collapsible,
13606 toShow = collapsing ? $() : that._getPanelForTab( clicked ),
13607 toHide = !active.length ? $() : that._getPanelForTab( active ),
13608 tab = clicked.closest( "li" ),
13609 eventData = {
13610 oldTab: active,
13611 oldPanel: toHide,
13612 newTab: collapsing ? $() : clicked,
13613 newPanel: toShow
13614 };
13615
13616 event.preventDefault();
13617
13618 if ( tab.hasClass( "ui-state-disabled" ) ||
13619 // tab is already loading
13620 tab.hasClass( "ui-tabs-loading" ) ||
13621 // can't switch durning an animation
13622 that.running ||
13623 // click on active header, but not collapsible
13624 ( clickedIsActive && !options.collapsible ) ||
13625 // allow canceling activation
13626 ( that._trigger( "beforeActivate", event, eventData ) === false ) ) {
13627 clicked[ 0 ].blur();
13628 return;
13629 }
13630
13631 options.active = collapsing ? false : that.anchors.index( clicked );
13632
13633 that.active = clickedIsActive ? $() : clicked;
13634 if ( that.xhr ) {
13635 that.xhr.abort();
13636 }
13637
13638 if ( !toHide.length && !toShow.length ) {
13639 throw "jQuery UI Tabs: Mismatching fragment identifier.";
13640 }
13641
13642 if ( toShow.length ) {
13643
13644 // TODO make passing in node possible
13645 that.load( that.anchors.index( clicked ), event );
13646
13647 clicked[ 0 ].blur();
13648 }
13649 that._toggle( event, eventData );
13650 },
13651
13652 // handles show/hide for selecting tabs
13653 _toggle: function( event, eventData ) {
13654 var that = this,
13655 options = that.options,
13656 toShow = eventData.newPanel,
13657 toHide = eventData.oldPanel;
13658
13659 that.running = true;
13660
13661 function complete() {
13662 that.running = false;
13663 that._trigger( "activate", event, eventData );
13664 }
13665
13666 function show() {
13667 eventData.newTab.closest( "li" ).addClass( "ui-tabs-active ui-state-active" );
13668
13669 if ( toShow.length && that.showFx ) {
13670 toShow
13671 .animate( that.showFx, that.showFx.duration || "normal", function() {
13672 that._resetStyle( $( this ), that.showFx );
13673 complete();
13674 });
13675 } else {
13676 toShow.show();
13677 complete();
13678 }
13679 }
13680
13681 // start out by hiding, then showing, then completing
13682 if ( toHide.length && that.hideFx ) {
13683 toHide.animate( that.hideFx, that.hideFx.duration || "normal", function() {
13684 eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" );
13685 that._resetStyle( $( this ), that.hideFx );
13686 show();
13687 });
13688 } else {
13689 eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" );
13690 toHide.hide();
13691 show();
13692 }
13693 },
13694
13695 _activate: function( index ) {
13696 var active = this._findActive( index )[ 0 ];
13697
13698 // trying to activate the already active panel
13699 if ( active === this.active[ 0 ] ) {
13700 return;
13701 }
13702
13703 // trying to collapse, simulate a click on the current active header
13704 active = active || this.active[ 0 ];
13705
13706 this._eventHandler({
13707 target: active,
13708 currentTarget: active,
13709 preventDefault: $.noop
13710 });
13711 },
13712
13713 _findActive: function( selector ) {
13714 return typeof selector === "number" ? this.anchors.eq( selector ) :
13715 typeof selector === "string" ? this.anchors.filter( "[href$='" + selector + "']" ) : $();
13716 },
13717
13718 _getIndex: function( index ) {
13719 // meta-function to give users option to provide a href string instead of a numerical index.
13720 // also sanitizes numerical indexes to valid values.
13721 if ( typeof index == "string" ) {
13722 index = this.anchors.index( this.anchors.filter( "[href$=" + index + "]" ) );
13723 }
13724
13725 return index;
13726 },
13727
13728 _destroy: function() {
13729 var o = this.options;
13730
13731 if ( this.xhr ) {
13732 this.xhr.abort();
13733 }
13734
13735 this.element.removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" );
13736
13737 this.list.removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" );
13738
13739 this.anchors
13740 .unbind( ".tabs" )
13741 .removeData( "href.tabs" )
13742 .removeData( "load.tabs" );
13743
13744 this.lis.unbind( ".tabs" ).add( this.panels ).each(function() {
13745 if ( $.data( this, "destroy.tabs" ) ) {
13746 $( this ).remove();
13747 } else {
13748 $( this ).removeClass([
13749 "ui-state-default",
13750 "ui-corner-top",
13751 "ui-tabs-active",
13752 "ui-state-active",
13753 "ui-state-disabled",
13754 "ui-tabs-panel",
13755 "ui-widget-content",
13756 "ui-corner-bottom"
13757 ].join( " " ) );
13758 }
13759 });
13760
13761 return this;
13762 },
13763
13764 enable: function( index ) {
13765 var disabled = this.options.disabled;
13766 if ( disabled === false ) {
13767 return;
13768 }
13769
13770 if ( index === undefined ) {
13771 disabled = false;
13772 } else {
13773 index = this._getIndex( index );
13774 if ( $.isArray( disabled ) ) {
13775 disabled = $.map( disabled, function( num ) {
13776 return num !== index ? num : null;
13777 });
13778 } else {
13779 disabled = $.map( this.lis, function( li, num ) {
13780 return num !== index ? num : null;
13781 });
13782 }
13783 }
13784 this._setupDisabled( disabled );
13785 },
13786
13787 disable: function( index ) {
13788 var disabled = this.options.disabled;
13789 if ( disabled === true ) {
13790 return;
13791 }
13792
13793 if ( index === undefined ) {
13794 disabled = true;
13795 } else {
13796 index = this._getIndex( index );
13797 if ( $.inArray( index, disabled ) !== -1 ) {
13798 return;
13799 }
13800 if ( $.isArray( disabled ) ) {
13801 disabled = $.merge( [ index ], disabled ).sort();
13802 } else {
13803 disabled = [ index ];
13804 }
13805 }
13806 this._setupDisabled( disabled );
13807 },
13808
13809 load: function( index, event ) {
13810 index = this._getIndex( index );
13811 var self = this,
13812 options = this.options,
13813 anchor = this.anchors.eq( index ),
13814 panel = self._getPanelForTab( anchor ),
13815 eventData = {
13816 tab: anchor,
13817 panel: panel
13818 };
13819
13820 // not remote
13821 if ( isLocal( anchor[ 0 ] ) ) {
13822 return;
13823 }
13824
13825 this.xhr = $.ajax({
13826 url: anchor.attr( "href" ),
13827 beforeSend: function( jqXHR, settings ) {
13828 return self._trigger( "beforeLoad", event,
13829 $.extend( { jqXHR : jqXHR, ajaxSettings: settings }, eventData ) );
13830 }
13831 });
13832
13833 if ( this.xhr ) {
13834 this.lis.eq( index ).addClass( "ui-tabs-loading" );
13835
13836 this.xhr
13837 .success(function( response ) {
13838 // TODO: IE resolves cached XHRs immediately
13839 // remove when core #10467 is fixed
13840 setTimeout(function() {
13841 panel.html( response );
13842 self._trigger( "load", event, eventData );
13843 }, 1 );
13844 })
13845 .complete(function( jqXHR, status ) {
13846 // TODO: IE resolves cached XHRs immediately
13847 // remove when core #10467 is fixed
13848 setTimeout(function() {
13849 if ( status === "abort" ) {
13850 self.panels.stop( false, true );
13851 }
13852
13853 self.lis.eq( index ).removeClass( "ui-tabs-loading" );
13854
13855 if ( jqXHR === self.xhr ) {
13856 delete self.xhr;
13857 }
13858 }, 1 );
13859 });
13860 }
13861
13862 return this;
13863 },
13864
13865 _getPanelForTab: function( tab ) {
13866 var id = $( tab ).attr( "aria-controls" );
13867 return this.element.find( this._sanitizeSelector( "#" + id ) );
13868 }
13869 });
13870
13871 // DEPRECATED
13872 if ( $.uiBackCompat !== false ) {
13873
13874 // helper method for a lot of the back compat extensions
13875 $.ui.tabs.prototype._ui = function( tab, panel ) {
13876 return {
13877 tab: tab,
13878 panel: panel,
13879 index: this.anchors.index( tab )
13880 };
13881 };
13882
13883 // url method
13884 (function( $, prototype ) {
13885 prototype.url = function( index, url ) {
13886 this.anchors.eq( index ).attr( "href", url );
13887 };
13888 }( jQuery, jQuery.ui.tabs.prototype ) );
13889
13890 // ajaxOptions and cache options
13891 (function( $, prototype ) {
13892 $.extend( prototype.options, {
13893 ajaxOptions: null,
13894 cache: false
13895 });
13896
13897 var _create = prototype._create,
13898 _setOption = prototype._setOption,
13899 _destroy = prototype._destroy,
13900 oldurl = prototype.url || $.noop;
13901
13902 $.extend( prototype, {
13903 _create: function() {
13904 _create.call( this );
13905
13906 var self = this;
13907
13908 this.element.bind( "tabsbeforeload.tabs", function( event, ui ) {
13909 // tab is already cached
13910 if ( $.data( ui.tab[ 0 ], "cache.tabs" ) ) {
13911 event.preventDefault();
13912 return;
13913 }
13914
13915 $.extend( ui.ajaxSettings, self.options.ajaxOptions, {
13916 error: function( xhr, s, e ) {
13917 try {
13918 // Passing index avoid a race condition when this method is
13919 // called after the user has selected another tab.
13920 // Pass the anchor that initiated this request allows
13921 // loadError to manipulate the tab content panel via $(a.hash)
13922 self.options.ajaxOptions.error( xhr, s, ui.tab.closest( "li" ).index(), ui.tab[ 0 ] );
13923 }
13924 catch ( e ) {}
13925 }
13926 });
13927
13928 ui.jqXHR.success(function() {
13929 if ( self.options.cache ) {
13930 $.data( ui.tab[ 0 ], "cache.tabs", true );
13931 }
13932 });
13933 });
13934 },
13935
13936 _setOption: function( key, value ) {
13937 // reset cache if switching from cached to not cached
13938 if ( key === "cache" && value === false ) {
13939 this.anchors.removeData( "cache.tabs" );
13940 }
13941 _setOption.apply( this, arguments );
13942 },
13943
13944 _destroy: function() {
13945 this.anchors.removeData( "cache.tabs" );
13946 _destroy.call( this );
13947 },
13948
13949 url: function( index, url ){
13950 this.anchors.eq( index ).removeData( "cache.tabs" );
13951 oldurl.apply( this, arguments );
13952 }
13953 });
13954 }( jQuery, jQuery.ui.tabs.prototype ) );
13955
13956 // abort method
13957 (function( $, prototype ) {
13958 prototype.abort = function() {
13959 if ( this.xhr ) {
13960 this.xhr.abort();
13961 }
13962 };
13963 }( jQuery, jQuery.ui.tabs.prototype ) );
13964
13965 // spinner
13966 $.widget( "ui.tabs", $.ui.tabs, {
13967 options: {
13968 spinner: "<em>Loading&#8230;</em>"
13969 },
13970 _create: function() {
13971 this._super();
13972 this._bind({
13973 tabsbeforeload: function( event, ui ) {
13974 if ( !this.options.spinner ) {
13975 return;
13976 }
13977
13978 var span = ui.tab.find( "span" ),
13979 html = span.html();
13980 span.html( this.options.spinner );
13981 ui.jqXHR.complete(function() {
13982 span.html( html );
13983 });
13984 }
13985 });
13986 }
13987 });
13988
13989 // enable/disable events
13990 (function( $, prototype ) {
13991 $.extend( prototype.options, {
13992 enable: null,
13993 disable: null
13994 });
13995
13996 var enable = prototype.enable,
13997 disable = prototype.disable;
13998
13999 prototype.enable = function( index ) {
14000 var options = this.options,
14001 trigger;
14002
14003 if ( index && options.disabled === true ||
14004 ( $.isArray( options.disabled ) && $.inArray( index, options.disabled ) !== -1 ) ) {
14005 trigger = true;
14006 }
14007
14008 enable.apply( this, arguments );
14009
14010 if ( trigger ) {
14011 this._trigger( "enable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
14012 }
14013 };
14014
14015 prototype.disable = function( index ) {
14016 var options = this.options,
14017 trigger;
14018
14019 if ( index && options.disabled === false ||
14020 ( $.isArray( options.disabled ) && $.inArray( index, options.disabled ) === -1 ) ) {
14021 trigger = true;
14022 }
14023
14024 disable.apply( this, arguments );
14025
14026 if ( trigger ) {
14027 this._trigger( "disable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
14028 }
14029 };
14030 }( jQuery, jQuery.ui.tabs.prototype ) );
14031
14032 // add/remove methods and events
14033 (function( $, prototype ) {
14034 $.extend( prototype.options, {
14035 add: null,
14036 remove: null,
14037 tabTemplate: "<li><a href='#{href}'><span>#{label}</span></a></li>"
14038 });
14039
14040 prototype.add = function( url, label, index ) {
14041 if ( index === undefined ) {
14042 index = this.anchors.length;
14043 }
14044
14045 var options = this.options,
14046 li = $( options.tabTemplate
14047 .replace( /#\{href\}/g, url )
14048 .replace( /#\{label\}/g, label ) ),
14049 id = !url.indexOf( "#" ) ?
14050 url.replace( "#", "" ) :
14051 this._tabId( li.find( "a" )[ 0 ] );
14052
14053 li.addClass( "ui-state-default ui-corner-top" ).data( "destroy.tabs", true );
14054 li.find( "a" ).attr( "aria-controls", id );
14055
14056 var doInsertAfter = index >= this.lis.length;
14057
14058 // try to find an existing element before creating a new one
14059 var panel = this.element.find( "#" + id );
14060 if ( !panel.length ) {
14061 panel = this._createPanel( id );
14062 if ( doInsertAfter ) {
14063 if ( index > 0 ) {
14064 panel.insertAfter( this.panels.eq( -1 ) );
14065 } else {
14066 panel.appendTo( this.element );
14067 }
14068 } else {
14069 panel.insertBefore( this.panels[ index ] );
14070 }
14071 }
14072 panel.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" ).hide();
14073
14074 if ( doInsertAfter ) {
14075 li.appendTo( this.list );
14076 } else {
14077 li.insertBefore( this.lis[ index ] );
14078 }
14079
14080 options.disabled = $.map( options.disabled, function( n ) {
14081 return n >= index ? ++n : n;
14082 });
14083
14084 this.refresh();
14085 if ( this.lis.length === 1 && options.active === false ) {
14086 this.option( "active", 0 );
14087 }
14088
14089 this._trigger( "add", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
14090 return this;
14091 };
14092
14093 prototype.remove = function( index ) {
14094 index = this._getIndex( index );
14095 var options = this.options,
14096 tab = this.lis.eq( index ).remove(),
14097 panel = this._getPanelForTab( tab.find( "a[aria-controls]" ) ).remove();
14098
14099 // If selected tab was removed focus tab to the right or
14100 // in case the last tab was removed the tab to the left.
14101 // We check for more than 2 tabs, because if there are only 2,
14102 // then when we remove this tab, there will only be one tab left
14103 // so we don't need to detect which tab to activate.
14104 if ( tab.hasClass( "ui-tabs-active" ) && this.anchors.length > 2 ) {
14105 this._activate( index + ( index + 1 < this.anchors.length ? 1 : -1 ) );
14106 }
14107
14108 options.disabled = $.map(
14109 $.grep( options.disabled, function( n ) {
14110 return n !== index;
14111 }),
14112 function( n ) {
14113 return n >= index ? --n : n;
14114 });
14115
14116 this.refresh();
14117
14118 this._trigger( "remove", null, this._ui( tab.find( "a" )[ 0 ], panel[ 0 ] ) );
14119 return this;
14120 };
14121 }( jQuery, jQuery.ui.tabs.prototype ) );
14122
14123 // length method
14124 (function( $, prototype ) {
14125 prototype.length = function() {
14126 return this.anchors.length;
14127 };
14128 }( jQuery, jQuery.ui.tabs.prototype ) );
14129
14130 // panel ids (idPrefix option + title attribute)
14131 (function( $, prototype ) {
14132 $.extend( prototype.options, {
14133 idPrefix: "ui-tabs-"
14134 });
14135
14136 var _tabId = prototype._tabId;
14137 prototype._tabId = function( a ) {
14138 return $( a ).attr( "aria-controls" ) ||
14139 a.title && a.title.replace( /\s/g, "_" ).replace( /[^\w\u00c0-\uFFFF-]/g, "" ) ||
14140 this.options.idPrefix + getNextTabId();
14141 };
14142 }( jQuery, jQuery.ui.tabs.prototype ) );
14143
14144 // _createPanel method
14145 (function( $, prototype ) {
14146 $.extend( prototype.options, {
14147 panelTemplate: "<div></div>"
14148 });
14149
14150 var _createPanel = prototype._createPanel;
14151 prototype._createPanel = function( id ) {
14152 return $( this.options.panelTemplate )
14153 .attr( "id", id )
14154 .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
14155 .data( "destroy.tabs", true );
14156 };
14157 }( jQuery, jQuery.ui.tabs.prototype ) );
14158
14159 // selected option
14160 (function( $, prototype ) {
14161 var _create = prototype._create,
14162 _setOption = prototype._setOption,
14163 _eventHandler = prototype._eventHandler;
14164
14165 prototype._create = function() {
14166 var options = this.options;
14167 if ( options.active === null && options.selected !== undefined ) {
14168 options.active = options.selected === -1 ? false : options.selected;
14169 }
14170 _create.call( this );
14171 options.selected = options.active;
14172 if ( options.selected === false ) {
14173 options.selected = -1;
14174 }
14175 };
14176
14177 prototype._setOption = function( key, value ) {
14178 if ( key !== "selected" ) {
14179 return _setOption.apply( this, arguments );
14180 }
14181
14182 var options = this.options;
14183 _setOption.call( this, "active", value === -1 ? false : value );
14184 options.selected = options.active;
14185 if ( options.selected === false ) {
14186 options.selected = -1;
14187 }
14188 };
14189
14190 prototype._eventHandler = function( event ) {
14191 _eventHandler.apply( this, arguments );
14192 this.options.selected = this.options.active;
14193 if ( this.options.selected === false ) {
14194 this.options.selected = -1;
14195 }
14196 };
14197 }( jQuery, jQuery.ui.tabs.prototype ) );
14198
14199 // show and select event
14200 (function( $, prototype ) {
14201 $.extend( prototype.options, {
14202 show: null,
14203 select: null
14204 });
14205 var _create = prototype._create,
14206 _trigger = prototype._trigger;
14207
14208 prototype._create = function() {
14209 _create.call( this );
14210 if ( this.options.active !== false ) {
14211 this._trigger( "show", null, this._ui(
14212 this.active[ 0 ], this._getPanelForTab( this.active )[ 0 ] ) );
14213 }
14214 };
14215 prototype._trigger = function( type, event, data ) {
14216 var ret = _trigger.apply( this, arguments );
14217 if ( !ret ) {
14218 return false;
14219 }
14220 if ( type === "beforeActivate" && data.newTab.length ) {
14221 ret = _trigger.call( this, "select", event, {
14222 tab: data.newTab[ 0],
14223 panel: data.newPanel[ 0 ],
14224 index: data.newTab.closest( "li" ).index()
14225 });
14226 } else if ( type === "activate" && data.newTab.length ) {
14227 ret = _trigger.call( this, "show", event, {
14228 tab: data.newTab[ 0 ],
14229 panel: data.newPanel[ 0 ],
14230 index: data.newTab.closest( "li" ).index()
14231 });
14232 }
14233 };
14234 }( jQuery, jQuery.ui.tabs.prototype ) );
14235
14236 // select method
14237 (function( $, prototype ) {
14238 prototype.select = function( index ) {
14239 index = this._getIndex( index );
14240 if ( index === -1 ) {
14241 if ( this.options.collapsible && this.options.selected !== -1 ) {
14242 index = this.options.selected;
14243 } else {
14244 return;
14245 }
14246 }
14247 this.anchors.eq( index ).trigger( this.options.event + ".tabs" );
14248 };
14249 }( jQuery, jQuery.ui.tabs.prototype ) );
14250
14251 // cookie option
14252 var listId = 0;
14253 function getNextListId() {
14254 return ++listId;
14255 }
14256 $.widget( "ui.tabs", $.ui.tabs, {
14257 options: {
14258 cookie: null // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true }
14259 },
14260 _create: function() {
14261 var options = this.options,
14262 active;
14263 if ( options.active == null && options.cookie ) {
14264 active = parseInt( this._cookie(), 10 );
14265 if ( active === -1 ) {
14266 active = false;
14267 }
14268 options.active = active;
14269 }
14270 this._super();
14271 },
14272 _cookie: function( active ) {
14273 var cookie = [ this.cookie ||
14274 ( this.cookie = this.options.cookie.name || "ui-tabs-" + getNextListId() ) ];
14275 if ( arguments.length ) {
14276 cookie.push( active === false ? -1 : active );
14277 cookie.push( this.options.cookie );
14278 }
14279 return $.cookie.apply( null, cookie );
14280 },
14281 _refresh: function() {
14282 this._super();
14283 if ( this.options.cookie ) {
14284 this._cookie( this.options.active, this.options.cookie );
14285 }
14286 },
14287 _eventHandler: function( event ) {
14288 this._superApply( arguments );
14289 if ( this.options.cookie ) {
14290 this._cookie( this.options.active, this.options.cookie );
14291 }
14292 },
14293 _destroy: function() {
14294 this._super();
14295 if ( this.options.cookie ) {
14296 this._cookie( null, this.options.cookie );
14297 }
14298 }
14299 });
14300
14301 // load event
14302 $.widget( "ui.tabs", $.ui.tabs, {
14303 _trigger: function( type, event, data ) {
14304 var _data = $.extend( {}, data );
14305 if ( type === "load" ) {
14306 _data.panel = _data.panel[ 0 ];
14307 _data.tab = _data.tab[ 0 ];
14308 }
14309 return this._super( type, event, _data );
14310 }
14311 });
14312 }
14313
14314 })( jQuery );
14315 /*
14316 * jQuery UI Tooltip @VERSION
14317 *
14318 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
14319 * Dual licensed under the MIT or GPL Version 2 licenses.
14320 * http://jquery.org/license
14321 *
14322 * http://docs.jquery.com/UI/Tooltip
14323 *
14324 * Depends:
14325 * jquery.ui.core.js
14326 * jquery.ui.widget.js
14327 * jquery.ui.position.js
14328 */
14329 (function( $ ) {
14330
14331 var increments = 0;
14332
14333 $.widget( "ui.tooltip", {
14334 version: "@VERSION",
14335 options: {
14336 content: function() {
14337 return $( this ).attr( "title" );
14338 },
14339 hide: true,
14340 items: "[title]",
14341 position: {
14342 my: "left+15 center",
14343 at: "right center",
14344 collision: "flipfit flipfit"
14345 },
14346 show: true,
14347 tooltipClass: null,
14348
14349 // callbacks
14350 close: null,
14351 open: null
14352 },
14353
14354 _create: function() {
14355 this._bind({
14356 mouseover: "open",
14357 focusin: "open"
14358 });
14359
14360 // IDs of generated tooltips, needed for destroy
14361 this.tooltips = {};
14362 },
14363
14364 _setOption: function( key, value ) {
14365 if ( key === "disabled" ) {
14366 this[ value ? "_disable" : "_enable" ]();
14367 this.options[ key ] = value;
14368 // disable element style changes
14369 return;
14370 }
14371 this._super( key, value );
14372 },
14373
14374 _disable: function() {
14375 var that = this;
14376
14377 // close open tooltips
14378 $.each( this.tooltips, function( id, element ) {
14379 var event = $.Event( "blur" );
14380 event.target = event.currentTarget = element[0];
14381 that.close( event, true );
14382 });
14383
14384 // remove title attributes to prevent native tooltips
14385 this.element.find( this.options.items ).andSelf().each(function() {
14386 var element = $( this );
14387 if ( element.is( "[title]" ) ) {
14388 element
14389 .data( "tooltip-title", element.attr( "title" ) )
14390 .attr( "title", "" );
14391 }
14392 });
14393 },
14394
14395 _enable: function() {
14396 // restore title attributes
14397 this.element.find( this.options.items ).andSelf().each(function() {
14398 var element = $( this );
14399 if ( element.data( "tooltip-title" ) ) {
14400 element.attr( "title", element.data( "tooltip-title" ) );
14401 }
14402 });
14403 },
14404
14405 open: function( event ) {
14406 var content,
14407 that = this,
14408 target = $( event ? event.target : this.element )
14409 .closest( this.options.items );
14410
14411 // if aria-describedby exists, then the tooltip is already open
14412 if ( !target.length || target.attr( "aria-describedby" ) ) {
14413 return;
14414 }
14415
14416 if ( !target.data( "tooltip-title" ) ) {
14417 target.data( "tooltip-title", target.attr( "title" ) );
14418 }
14419
14420 content = this.options.content.call( target[0], function( response ) {
14421 // IE may instantly serve a cached response for ajax requests
14422 // delay this call to _open so the other call to _open runs first
14423 setTimeout(function() {
14424 that._open( event, target, response );
14425 }, 1 );
14426 });
14427 if ( content ) {
14428 that._open( event, target, content );
14429 }
14430 },
14431
14432 _open: function( event, target, content ) {
14433 if ( !content ) {
14434 return;
14435 }
14436
14437 // if we have a title, clear it to prevent the native tooltip
14438 // we have to check first to avoid defining a title if none exists
14439 // (we don't want to cause an element to start matching [title])
14440 // TODO: document why we don't use .removeAttr()
14441 if ( target.is( "[title]" ) ) {
14442 target.attr( "title", "" );
14443 }
14444
14445 // ajaxy tooltip can update an existing one
14446 var tooltip = this._find( target );
14447 if ( !tooltip.length ) {
14448 tooltip = this._tooltip( target );
14449 target.attr( "aria-describedby", tooltip.attr( "id" ) );
14450 }
14451 tooltip.find( ".ui-tooltip-content" ).html( content );
14452 tooltip
14453 .stop( true )
14454 .position( $.extend({
14455 of: target
14456 }, this.options.position ) )
14457 .hide();
14458
14459 this._show( tooltip, this.options.show );
14460
14461 this._trigger( "open", event, { tooltip: tooltip } );
14462
14463 this._bind( target, {
14464 mouseleave: "close",
14465 blur: "close",
14466 keyup: function( event ) {
14467 if ( event.keyCode == $.ui.keyCode.ESCAPE ) {
14468 var fakeEvent = $.Event(event);
14469 fakeEvent.currentTarget = target[0];
14470 this.close( fakeEvent, true );
14471 }
14472 }
14473 });
14474 },
14475
14476 close: function( event, force ) {
14477 var that = this,
14478 target = $( event ? event.currentTarget : this.element ),
14479 tooltip = this._find( target );
14480
14481 // don't close if the element has focus
14482 // this prevents the tooltip from closing if you hover while focused
14483 if ( !force && this.document[0].activeElement === target[0] ) {
14484 return;
14485 }
14486
14487 // only set title if we had one before (see comment in _open())
14488 if ( target.data( "tooltip-title" ) ) {
14489 target.attr( "title", target.data( "tooltip-title" ) );
14490 }
14491
14492 target.removeAttr( "aria-describedby" );
14493
14494 tooltip.stop( true );
14495 this._hide( tooltip, this.options.hide, function() {
14496 $( this ).remove();
14497 delete that.tooltips[ this.id ];
14498 });
14499
14500 target.unbind( "mouseleave.tooltip blur.tooltip keyup.tooltip" );
14501
14502 this._trigger( "close", event, { tooltip: tooltip } );
14503 },
14504
14505 _tooltip: function( element ) {
14506 var id = "ui-tooltip-" + increments++,
14507 tooltip = $( "<div>" )
14508 .attr({
14509 id: id,
14510 role: "tooltip"
14511 })
14512 .addClass( "ui-tooltip ui-widget ui-corner-all ui-widget-content " +
14513 ( this.options.tooltipClass || "" ) );
14514 $( "<div>" )
14515 .addClass( "ui-tooltip-content" )
14516 .appendTo( tooltip );
14517 tooltip.appendTo( this.document[0].body );
14518 if ( $.fn.bgiframe ) {
14519 tooltip.bgiframe();
14520 }
14521 this.tooltips[ id ] = element;
14522 return tooltip;
14523 },
14524
14525 _find: function( target ) {
14526 var id = target.attr( "aria-describedby" );
14527 return id ? $( "#" + id ) : $();
14528 },
14529
14530 _destroy: function() {
14531 $.each( this.tooltips, function( id ) {
14532 $( "#" + id ).remove();
14533 });
14534 }
14535 });
14536
14537 }( jQuery ) );
This diff has been collapsed as it changes many lines, (1477 lines changed) Show them Hide them
@@ -1,1477 +0,0
1 // Copyright (C) 2006 Google Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15
16 /**
17 * @fileoverview
18 * some functions for browser-side pretty printing of code contained in html.
19 *
20 * <p>
21 * For a fairly comprehensive set of languages see the
22 * <a href="http://google-code-prettify.googlecode.com/svn/trunk/README.html#langs">README</a>
23 * file that came with this source. At a minimum, the lexer should work on a
24 * number of languages including C and friends, Java, Python, Bash, SQL, HTML,
25 * XML, CSS, Javascript, and Makefiles. It works passably on Ruby, PHP and Awk
26 * and a subset of Perl, but, because of commenting conventions, doesn't work on
27 * Smalltalk, Lisp-like, or CAML-like languages without an explicit lang class.
28 * <p>
29 * Usage: <ol>
30 * <li> include this source file in an html page via
31 * {@code <script type="text/javascript" src="/path/to/prettify.js"></script>}
32 * <li> define style rules. See the example page for examples.
33 * <li> mark the {@code <pre>} and {@code <code>} tags in your source with
34 * {@code class=prettyprint.}
35 * You can also use the (html deprecated) {@code <xmp>} tag, but the pretty
36 * printer needs to do more substantial DOM manipulations to support that, so
37 * some css styles may not be preserved.
38 * </ol>
39 * That's it. I wanted to keep the API as simple as possible, so there's no
40 * need to specify which language the code is in, but if you wish, you can add
41 * another class to the {@code <pre>} or {@code <code>} element to specify the
42 * language, as in {@code <pre class="prettyprint lang-java">}. Any class that
43 * starts with "lang-" followed by a file extension, specifies the file type.
44 * See the "lang-*.js" files in this directory for code that implements
45 * per-language file handlers.
46 * <p>
47 * Change log:<br>
48 * cbeust, 2006/08/22
49 * <blockquote>
50 * Java annotations (start with "@") are now captured as literals ("lit")
51 * </blockquote>
52 * @requires console
53 */
54
55 // JSLint declarations
56 /*global console, document, navigator, setTimeout, window */
57
58 /**
59 * Split {@code prettyPrint} into multiple timeouts so as not to interfere with
60 * UI events.
61 * If set to {@code false}, {@code prettyPrint()} is synchronous.
62 */
63 window['PR_SHOULD_USE_CONTINUATION'] = true;
64
65 (function () {
66 // Keyword lists for various languages.
67 // We use things that coerce to strings to make them compact when minified
68 // and to defeat aggressive optimizers that fold large string constants.
69 var FLOW_CONTROL_KEYWORDS = ["break,continue,do,else,for,if,return,while"];
70 var C_KEYWORDS = [FLOW_CONTROL_KEYWORDS,"auto,case,char,const,default," +
71 "double,enum,extern,float,goto,int,long,register,short,signed,sizeof," +
72 "static,struct,switch,typedef,union,unsigned,void,volatile"];
73 var COMMON_KEYWORDS = [C_KEYWORDS,"catch,class,delete,false,import," +
74 "new,operator,private,protected,public,this,throw,true,try,typeof"];
75 var CPP_KEYWORDS = [COMMON_KEYWORDS,"alignof,align_union,asm,axiom,bool," +
76 "concept,concept_map,const_cast,constexpr,decltype," +
77 "dynamic_cast,explicit,export,friend,inline,late_check," +
78 "mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast," +
79 "template,typeid,typename,using,virtual,where"];
80 var JAVA_KEYWORDS = [COMMON_KEYWORDS,
81 "abstract,boolean,byte,extends,final,finally,implements,import," +
82 "instanceof,null,native,package,strictfp,super,synchronized,throws," +
83 "transient"];
84 var CSHARP_KEYWORDS = [JAVA_KEYWORDS,
85 "as,base,by,checked,decimal,delegate,descending,dynamic,event," +
86 "fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock," +
87 "object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed," +
88 "stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"];
89 var COFFEE_KEYWORDS = "all,and,by,catch,class,else,extends,false,finally," +
90 "for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then," +
91 "true,try,unless,until,when,while,yes";
92 var JSCRIPT_KEYWORDS = [COMMON_KEYWORDS,
93 "debugger,eval,export,function,get,null,set,undefined,var,with," +
94 "Infinity,NaN"];
95 var PERL_KEYWORDS = "caller,delete,die,do,dump,elsif,eval,exit,foreach,for," +
96 "goto,if,import,last,local,my,next,no,our,print,package,redo,require," +
97 "sub,undef,unless,until,use,wantarray,while,BEGIN,END";
98 var PYTHON_KEYWORDS = [FLOW_CONTROL_KEYWORDS, "and,as,assert,class,def,del," +
99 "elif,except,exec,finally,from,global,import,in,is,lambda," +
100 "nonlocal,not,or,pass,print,raise,try,with,yield," +
101 "False,True,None"];
102 var RUBY_KEYWORDS = [FLOW_CONTROL_KEYWORDS, "alias,and,begin,case,class," +
103 "def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo," +
104 "rescue,retry,self,super,then,true,undef,unless,until,when,yield," +
105 "BEGIN,END"];
106 var SH_KEYWORDS = [FLOW_CONTROL_KEYWORDS, "case,done,elif,esac,eval,fi," +
107 "function,in,local,set,then,until"];
108 var ALL_KEYWORDS = [
109 CPP_KEYWORDS, CSHARP_KEYWORDS, JSCRIPT_KEYWORDS, PERL_KEYWORDS +
110 PYTHON_KEYWORDS, RUBY_KEYWORDS, SH_KEYWORDS];
111 var C_TYPES = /^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/;
112
113 // token style names. correspond to css classes
114 /**
115 * token style for a string literal
116 * @const
117 */
118 var PR_STRING = 'str';
119 /**
120 * token style for a keyword
121 * @const
122 */
123 var PR_KEYWORD = 'kwd';
124 /**
125 * token style for a comment
126 * @const
127 */
128 var PR_COMMENT = 'com';
129 /**
130 * token style for a type
131 * @const
132 */
133 var PR_TYPE = 'typ';
134 /**
135 * token style for a literal value. e.g. 1, null, true.
136 * @const
137 */
138 var PR_LITERAL = 'lit';
139 /**
140 * token style for a punctuation string.
141 * @const
142 */
143 var PR_PUNCTUATION = 'pun';
144 /**
145 * token style for a punctuation string.
146 * @const
147 */
148 var PR_PLAIN = 'pln';
149
150 /**
151 * token style for an sgml tag.
152 * @const
153 */
154 var PR_TAG = 'tag';
155 /**
156 * token style for a markup declaration such as a DOCTYPE.
157 * @const
158 */
159 var PR_DECLARATION = 'dec';
160 /**
161 * token style for embedded source.
162 * @const
163 */
164 var PR_SOURCE = 'src';
165 /**
166 * token style for an sgml attribute name.
167 * @const
168 */
169 var PR_ATTRIB_NAME = 'atn';
170 /**
171 * token style for an sgml attribute value.
172 * @const
173 */
174 var PR_ATTRIB_VALUE = 'atv';
175
176 /**
177 * A class that indicates a section of markup that is not code, e.g. to allow
178 * embedding of line numbers within code listings.
179 * @const
180 */
181 var PR_NOCODE = 'nocode';
182
183
184
185 /**
186 * A set of tokens that can precede a regular expression literal in
187 * javascript
188 * http://web.archive.org/web/20070717142515/http://www.mozilla.org/js/language/js20/rationale/syntax.html
189 * has the full list, but I've removed ones that might be problematic when
190 * seen in languages that don't support regular expression literals.
191 *
192 * <p>Specifically, I've removed any keywords that can't precede a regexp
193 * literal in a syntactically legal javascript program, and I've removed the
194 * "in" keyword since it's not a keyword in many languages, and might be used
195 * as a count of inches.
196 *
197 * <p>The link a above does not accurately describe EcmaScript rules since
198 * it fails to distinguish between (a=++/b/i) and (a++/b/i) but it works
199 * very well in practice.
200 *
201 * @private
202 * @const
203 */
204 var REGEXP_PRECEDER_PATTERN = '(?:^^\\.?|[+-]|\\!|\\!=|\\!==|\\#|\\%|\\%=|&|&&|&&=|&=|\\(|\\*|\\*=|\\+=|\\,|\\-=|\\->|\\/|\\/=|:|::|\\;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|\\?|\\@|\\[|\\^|\\^=|\\^\\^|\\^\\^=|\\{|\\||\\|=|\\|\\||\\|\\|=|\\~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*';
205
206 // CAVEAT: this does not properly handle the case where a regular
207 // expression immediately follows another since a regular expression may
208 // have flags for case-sensitivity and the like. Having regexp tokens
209 // adjacent is not valid in any language I'm aware of, so I'm punting.
210 // TODO: maybe style special characters inside a regexp as punctuation.
211
212
213 /**
214 * Given a group of {@link RegExp}s, returns a {@code RegExp} that globally
215 * matches the union of the sets of strings matched by the input RegExp.
216 * Since it matches globally, if the input strings have a start-of-input
217 * anchor (/^.../), it is ignored for the purposes of unioning.
218 * @param {Array.<RegExp>} regexs non multiline, non-global regexs.
219 * @return {RegExp} a global regex.
220 */
221 function combinePrefixPatterns(regexs) {
222 var capturedGroupIndex = 0;
223
224 var needToFoldCase = false;
225 var ignoreCase = false;
226 for (var i = 0, n = regexs.length; i < n; ++i) {
227 var regex = regexs[i];
228 if (regex.ignoreCase) {
229 ignoreCase = true;
230 } else if (/[a-z]/i.test(regex.source.replace(
231 /\\u[0-9a-f]{4}|\\x[0-9a-f]{2}|\\[^ux]/gi, ''))) {
232 needToFoldCase = true;
233 ignoreCase = false;
234 break;
235 }
236 }
237
238 var escapeCharToCodeUnit = {
239 'b': 8,
240 't': 9,
241 'n': 0xa,
242 'v': 0xb,
243 'f': 0xc,
244 'r': 0xd
245 };
246
247 function decodeEscape(charsetPart) {
248 var cc0 = charsetPart.charCodeAt(0);
249 if (cc0 !== 92 /* \\ */) {
250 return cc0;
251 }
252 var c1 = charsetPart.charAt(1);
253 cc0 = escapeCharToCodeUnit[c1];
254 if (cc0) {
255 return cc0;
256 } else if ('0' <= c1 && c1 <= '7') {
257 return parseInt(charsetPart.substring(1), 8);
258 } else if (c1 === 'u' || c1 === 'x') {
259 return parseInt(charsetPart.substring(2), 16);
260 } else {
261 return charsetPart.charCodeAt(1);
262 }
263 }
264
265 function encodeEscape(charCode) {
266 if (charCode < 0x20) {
267 return (charCode < 0x10 ? '\\x0' : '\\x') + charCode.toString(16);
268 }
269 var ch = String.fromCharCode(charCode);
270 if (ch === '\\' || ch === '-' || ch === '[' || ch === ']') {
271 ch = '\\' + ch;
272 }
273 return ch;
274 }
275
276 function caseFoldCharset(charSet) {
277 var charsetParts = charSet.substring(1, charSet.length - 1).match(
278 new RegExp(
279 '\\\\u[0-9A-Fa-f]{4}'
280 + '|\\\\x[0-9A-Fa-f]{2}'
281 + '|\\\\[0-3][0-7]{0,2}'
282 + '|\\\\[0-7]{1,2}'
283 + '|\\\\[\\s\\S]'
284 + '|-'
285 + '|[^-\\\\]',
286 'g'));
287 var groups = [];
288 var ranges = [];
289 var inverse = charsetParts[0] === '^';
290 for (var i = inverse ? 1 : 0, n = charsetParts.length; i < n; ++i) {
291 var p = charsetParts[i];
292 if (/\\[bdsw]/i.test(p)) { // Don't muck with named groups.
293 groups.push(p);
294 } else {
295 var start = decodeEscape(p);
296 var end;
297 if (i + 2 < n && '-' === charsetParts[i + 1]) {
298 end = decodeEscape(charsetParts[i + 2]);
299 i += 2;
300 } else {
301 end = start;
302 }
303 ranges.push([start, end]);
304 // If the range might intersect letters, then expand it.
305 // This case handling is too simplistic.
306 // It does not deal with non-latin case folding.
307 // It works for latin source code identifiers though.
308 if (!(end < 65 || start > 122)) {
309 if (!(end < 65 || start > 90)) {
310 ranges.push([Math.max(65, start) | 32, Math.min(end, 90) | 32]);
311 }
312 if (!(end < 97 || start > 122)) {
313 ranges.push([Math.max(97, start) & ~32, Math.min(end, 122) & ~32]);
314 }
315 }
316 }
317 }
318
319 // [[1, 10], [3, 4], [8, 12], [14, 14], [16, 16], [17, 17]]
320 // -> [[1, 12], [14, 14], [16, 17]]
321 ranges.sort(function (a, b) { return (a[0] - b[0]) || (b[1] - a[1]); });
322 var consolidatedRanges = [];
323 var lastRange = [NaN, NaN];
324 for (var i = 0; i < ranges.length; ++i) {
325 var range = ranges[i];
326 if (range[0] <= lastRange[1] + 1) {
327 lastRange[1] = Math.max(lastRange[1], range[1]);
328 } else {
329 consolidatedRanges.push(lastRange = range);
330 }
331 }
332
333 var out = ['['];
334 if (inverse) { out.push('^'); }
335 out.push.apply(out, groups);
336 for (var i = 0; i < consolidatedRanges.length; ++i) {
337 var range = consolidatedRanges[i];
338 out.push(encodeEscape(range[0]));
339 if (range[1] > range[0]) {
340 if (range[1] + 1 > range[0]) { out.push('-'); }
341 out.push(encodeEscape(range[1]));
342 }
343 }
344 out.push(']');
345 return out.join('');
346 }
347
348 function allowAnywhereFoldCaseAndRenumberGroups(regex) {
349 // Split into character sets, escape sequences, punctuation strings
350 // like ('(', '(?:', ')', '^'), and runs of characters that do not
351 // include any of the above.
352 var parts = regex.source.match(
353 new RegExp(
354 '(?:'
355 + '\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]' // a character set
356 + '|\\\\u[A-Fa-f0-9]{4}' // a unicode escape
357 + '|\\\\x[A-Fa-f0-9]{2}' // a hex escape
358 + '|\\\\[0-9]+' // a back-reference or octal escape
359 + '|\\\\[^ux0-9]' // other escape sequence
360 + '|\\(\\?[:!=]' // start of a non-capturing group
361 + '|[\\(\\)\\^]' // start/emd of a group, or line start
362 + '|[^\\x5B\\x5C\\(\\)\\^]+' // run of other characters
363 + ')',
364 'g'));
365 var n = parts.length;
366
367 // Maps captured group numbers to the number they will occupy in
368 // the output or to -1 if that has not been determined, or to
369 // undefined if they need not be capturing in the output.
370 var capturedGroups = [];
371
372 // Walk over and identify back references to build the capturedGroups
373 // mapping.
374 for (var i = 0, groupIndex = 0; i < n; ++i) {
375 var p = parts[i];
376 if (p === '(') {
377 // groups are 1-indexed, so max group index is count of '('
378 ++groupIndex;
379 } else if ('\\' === p.charAt(0)) {
380 var decimalValue = +p.substring(1);
381 if (decimalValue && decimalValue <= groupIndex) {
382 capturedGroups[decimalValue] = -1;
383 }
384 }
385 }
386
387 // Renumber groups and reduce capturing groups to non-capturing groups
388 // where possible.
389 for (var i = 1; i < capturedGroups.length; ++i) {
390 if (-1 === capturedGroups[i]) {
391 capturedGroups[i] = ++capturedGroupIndex;
392 }
393 }
394 for (var i = 0, groupIndex = 0; i < n; ++i) {
395 var p = parts[i];
396 if (p === '(') {
397 ++groupIndex;
398 if (capturedGroups[groupIndex] === undefined) {
399 parts[i] = '(?:';
400 }
401 } else if ('\\' === p.charAt(0)) {
402 var decimalValue = +p.substring(1);
403 if (decimalValue && decimalValue <= groupIndex) {
404 parts[i] = '\\' + capturedGroups[groupIndex];
405 }
406 }
407 }
408
409 // Remove any prefix anchors so that the output will match anywhere.
410 // ^^ really does mean an anchored match though.
411 for (var i = 0, groupIndex = 0; i < n; ++i) {
412 if ('^' === parts[i] && '^' !== parts[i + 1]) { parts[i] = ''; }
413 }
414
415 // Expand letters to groups to handle mixing of case-sensitive and
416 // case-insensitive patterns if necessary.
417 if (regex.ignoreCase && needToFoldCase) {
418 for (var i = 0; i < n; ++i) {
419 var p = parts[i];
420 var ch0 = p.charAt(0);
421 if (p.length >= 2 && ch0 === '[') {
422 parts[i] = caseFoldCharset(p);
423 } else if (ch0 !== '\\') {
424 // TODO: handle letters in numeric escapes.
425 parts[i] = p.replace(
426 /[a-zA-Z]/g,
427 function (ch) {
428 var cc = ch.charCodeAt(0);
429 return '[' + String.fromCharCode(cc & ~32, cc | 32) + ']';
430 });
431 }
432 }
433 }
434
435 return parts.join('');
436 }
437
438 var rewritten = [];
439 for (var i = 0, n = regexs.length; i < n; ++i) {
440 var regex = regexs[i];
441 if (regex.global || regex.multiline) { throw new Error('' + regex); }
442 rewritten.push(
443 '(?:' + allowAnywhereFoldCaseAndRenumberGroups(regex) + ')');
444 }
445
446 return new RegExp(rewritten.join('|'), ignoreCase ? 'gi' : 'g');
447 }
448
449
450 /**
451 * Split markup into a string of source code and an array mapping ranges in
452 * that string to the text nodes in which they appear.
453 *
454 * <p>
455 * The HTML DOM structure:</p>
456 * <pre>
457 * (Element "p"
458 * (Element "b"
459 * (Text "print ")) ; #1
460 * (Text "'Hello '") ; #2
461 * (Element "br") ; #3
462 * (Text " + 'World';")) ; #4
463 * </pre>
464 * <p>
465 * corresponds to the HTML
466 * {@code <p><b>print </b>'Hello '<br> + 'World';</p>}.</p>
467 *
468 * <p>
469 * It will produce the output:</p>
470 * <pre>
471 * {
472 * sourceCode: "print 'Hello '\n + 'World';",
473 * // 1 2
474 * // 012345678901234 5678901234567
475 * spans: [0, #1, 6, #2, 14, #3, 15, #4]
476 * }
477 * </pre>
478 * <p>
479 * where #1 is a reference to the {@code "print "} text node above, and so
480 * on for the other text nodes.
481 * </p>
482 *
483 * <p>
484 * The {@code} spans array is an array of pairs. Even elements are the start
485 * indices of substrings, and odd elements are the text nodes (or BR elements)
486 * that contain the text for those substrings.
487 * Substrings continue until the next index or the end of the source.
488 * </p>
489 *
490 * @param {Node} node an HTML DOM subtree containing source-code.
491 * @return {Object} source code and the text nodes in which they occur.
492 */
493 function extractSourceSpans(node) {
494 var nocode = /(?:^|\s)nocode(?:\s|$)/;
495
496 var chunks = [];
497 var length = 0;
498 var spans = [];
499 var k = 0;
500
501 var whitespace;
502 if (node.currentStyle) {
503 whitespace = node.currentStyle.whiteSpace;
504 } else if (window.getComputedStyle) {
505 whitespace = document.defaultView.getComputedStyle(node, null)
506 .getPropertyValue('white-space');
507 }
508 var isPreformatted = whitespace && 'pre' === whitespace.substring(0, 3);
509
510 function walk(node) {
511 switch (node.nodeType) {
512 case 1: // Element
513 if (nocode.test(node.className)) { return; }
514 for (var child = node.firstChild; child; child = child.nextSibling) {
515 walk(child);
516 }
517 var nodeName = node.nodeName;
518 if ('BR' === nodeName || 'LI' === nodeName) {
519 chunks[k] = '\n';
520 spans[k << 1] = length++;
521 spans[(k++ << 1) | 1] = node;
522 }
523 break;
524 case 3: case 4: // Text
525 var text = node.nodeValue;
526 if (text.length) {
527 if (!isPreformatted) {
528 text = text.replace(/[ \t\r\n]+/g, ' ');
529 } else {
530 text = text.replace(/\r\n?/g, '\n'); // Normalize newlines.
531 }
532 // TODO: handle tabs here?
533 chunks[k] = text;
534 spans[k << 1] = length;
535 length += text.length;
536 spans[(k++ << 1) | 1] = node;
537 }
538 break;
539 }
540 }
541
542 walk(node);
543
544 return {
545 sourceCode: chunks.join('').replace(/\n$/, ''),
546 spans: spans
547 };
548 }
549
550
551 /**
552 * Apply the given language handler to sourceCode and add the resulting
553 * decorations to out.
554 * @param {number} basePos the index of sourceCode within the chunk of source
555 * whose decorations are already present on out.
556 */
557 function appendDecorations(basePos, sourceCode, langHandler, out) {
558 if (!sourceCode) { return; }
559 var job = {
560 sourceCode: sourceCode,
561 basePos: basePos
562 };
563 langHandler(job);
564 out.push.apply(out, job.decorations);
565 }
566
567 var notWs = /\S/;
568
569 /**
570 * Given an element, if it contains only one child element and any text nodes
571 * it contains contain only space characters, return the sole child element.
572 * Otherwise returns undefined.
573 * <p>
574 * This is meant to return the CODE element in {@code <pre><code ...>} when
575 * there is a single child element that contains all the non-space textual
576 * content, but not to return anything where there are multiple child elements
577 * as in {@code <pre><code>...</code><code>...</code></pre>} or when there
578 * is textual content.
579 */
580 function childContentWrapper(element) {
581 var wrapper = undefined;
582 for (var c = element.firstChild; c; c = c.nextSibling) {
583 var type = c.nodeType;
584 wrapper = (type === 1) // Element Node
585 ? (wrapper ? element : c)
586 : (type === 3) // Text Node
587 ? (notWs.test(c.nodeValue) ? element : wrapper)
588 : wrapper;
589 }
590 return wrapper === element ? undefined : wrapper;
591 }
592
593 /** Given triples of [style, pattern, context] returns a lexing function,
594 * The lexing function interprets the patterns to find token boundaries and
595 * returns a decoration list of the form
596 * [index_0, style_0, index_1, style_1, ..., index_n, style_n]
597 * where index_n is an index into the sourceCode, and style_n is a style
598 * constant like PR_PLAIN. index_n-1 <= index_n, and style_n-1 applies to
599 * all characters in sourceCode[index_n-1:index_n].
600 *
601 * The stylePatterns is a list whose elements have the form
602 * [style : string, pattern : RegExp, DEPRECATED, shortcut : string].
603 *
604 * Style is a style constant like PR_PLAIN, or can be a string of the
605 * form 'lang-FOO', where FOO is a language extension describing the
606 * language of the portion of the token in $1 after pattern executes.
607 * E.g., if style is 'lang-lisp', and group 1 contains the text
608 * '(hello (world))', then that portion of the token will be passed to the
609 * registered lisp handler for formatting.
610 * The text before and after group 1 will be restyled using this decorator
611 * so decorators should take care that this doesn't result in infinite
612 * recursion. For example, the HTML lexer rule for SCRIPT elements looks
613 * something like ['lang-js', /<[s]cript>(.+?)<\/script>/]. This may match
614 * '<script>foo()<\/script>', which would cause the current decorator to
615 * be called with '<script>' which would not match the same rule since
616 * group 1 must not be empty, so it would be instead styled as PR_TAG by
617 * the generic tag rule. The handler registered for the 'js' extension would
618 * then be called with 'foo()', and finally, the current decorator would
619 * be called with '<\/script>' which would not match the original rule and
620 * so the generic tag rule would identify it as a tag.
621 *
622 * Pattern must only match prefixes, and if it matches a prefix, then that
623 * match is considered a token with the same style.
624 *
625 * Context is applied to the last non-whitespace, non-comment token
626 * recognized.
627 *
628 * Shortcut is an optional string of characters, any of which, if the first
629 * character, gurantee that this pattern and only this pattern matches.
630 *
631 * @param {Array} shortcutStylePatterns patterns that always start with
632 * a known character. Must have a shortcut string.
633 * @param {Array} fallthroughStylePatterns patterns that will be tried in
634 * order if the shortcut ones fail. May have shortcuts.
635 *
636 * @return {function (Object)} a
637 * function that takes source code and returns a list of decorations.
638 */
639 function createSimpleLexer(shortcutStylePatterns, fallthroughStylePatterns) {
640 var shortcuts = {};
641 var tokenizer;
642 (function () {
643 var allPatterns = shortcutStylePatterns.concat(fallthroughStylePatterns);
644 var allRegexs = [];
645 var regexKeys = {};
646 for (var i = 0, n = allPatterns.length; i < n; ++i) {
647 var patternParts = allPatterns[i];
648 var shortcutChars = patternParts[3];
649 if (shortcutChars) {
650 for (var c = shortcutChars.length; --c >= 0;) {
651 shortcuts[shortcutChars.charAt(c)] = patternParts;
652 }
653 }
654 var regex = patternParts[1];
655 var k = '' + regex;
656 if (!regexKeys.hasOwnProperty(k)) {
657 allRegexs.push(regex);
658 regexKeys[k] = null;
659 }
660 }
661 allRegexs.push(/[\0-\uffff]/);
662 tokenizer = combinePrefixPatterns(allRegexs);
663 })();
664
665 var nPatterns = fallthroughStylePatterns.length;
666
667 /**
668 * Lexes job.sourceCode and produces an output array job.decorations of
669 * style classes preceded by the position at which they start in
670 * job.sourceCode in order.
671 *
672 * @param {Object} job an object like <pre>{
673 * sourceCode: {string} sourceText plain text,
674 * basePos: {int} position of job.sourceCode in the larger chunk of
675 * sourceCode.
676 * }</pre>
677 */
678 var decorate = function (job) {
679 var sourceCode = job.sourceCode, basePos = job.basePos;
680 /** Even entries are positions in source in ascending order. Odd enties
681 * are style markers (e.g., PR_COMMENT) that run from that position until
682 * the end.
683 * @type {Array.<number|string>}
684 */
685 var decorations = [basePos, PR_PLAIN];
686 var pos = 0; // index into sourceCode
687 var tokens = sourceCode.match(tokenizer) || [];
688 var styleCache = {};
689
690 for (var ti = 0, nTokens = tokens.length; ti < nTokens; ++ti) {
691 var token = tokens[ti];
692 var style = styleCache[token];
693 var match = void 0;
694
695 var isEmbedded;
696 if (typeof style === 'string') {
697 isEmbedded = false;
698 } else {
699 var patternParts = shortcuts[token.charAt(0)];
700 if (patternParts) {
701 match = token.match(patternParts[1]);
702 style = patternParts[0];
703 } else {
704 for (var i = 0; i < nPatterns; ++i) {
705 patternParts = fallthroughStylePatterns[i];
706 match = token.match(patternParts[1]);
707 if (match) {
708 style = patternParts[0];
709 break;
710 }
711 }
712
713 if (!match) { // make sure that we make progress
714 style = PR_PLAIN;
715 }
716 }
717
718 isEmbedded = style.length >= 5 && 'lang-' === style.substring(0, 5);
719 if (isEmbedded && !(match && typeof match[1] === 'string')) {
720 isEmbedded = false;
721 style = PR_SOURCE;
722 }
723
724 if (!isEmbedded) { styleCache[token] = style; }
725 }
726
727 var tokenStart = pos;
728 pos += token.length;
729
730 if (!isEmbedded) {
731 decorations.push(basePos + tokenStart, style);
732 } else { // Treat group 1 as an embedded block of source code.
733 var embeddedSource = match[1];
734 var embeddedSourceStart = token.indexOf(embeddedSource);
735 var embeddedSourceEnd = embeddedSourceStart + embeddedSource.length;
736 if (match[2]) {
737 // If embeddedSource can be blank, then it would match at the
738 // beginning which would cause us to infinitely recurse on the
739 // entire token, so we catch the right context in match[2].
740 embeddedSourceEnd = token.length - match[2].length;
741 embeddedSourceStart = embeddedSourceEnd - embeddedSource.length;
742 }
743 var lang = style.substring(5);
744 // Decorate the left of the embedded source
745 appendDecorations(
746 basePos + tokenStart,
747 token.substring(0, embeddedSourceStart),
748 decorate, decorations);
749 // Decorate the embedded source
750 appendDecorations(
751 basePos + tokenStart + embeddedSourceStart,
752 embeddedSource,
753 langHandlerForExtension(lang, embeddedSource),
754 decorations);
755 // Decorate the right of the embedded section
756 appendDecorations(
757 basePos + tokenStart + embeddedSourceEnd,
758 token.substring(embeddedSourceEnd),
759 decorate, decorations);
760 }
761 }
762 job.decorations = decorations;
763 };
764 return decorate;
765 }
766
767 /** returns a function that produces a list of decorations from source text.
768 *
769 * This code treats ", ', and ` as string delimiters, and \ as a string
770 * escape. It does not recognize perl's qq() style strings.
771 * It has no special handling for double delimiter escapes as in basic, or
772 * the tripled delimiters used in python, but should work on those regardless
773 * although in those cases a single string literal may be broken up into
774 * multiple adjacent string literals.
775 *
776 * It recognizes C, C++, and shell style comments.
777 *
778 * @param {Object} options a set of optional parameters.
779 * @return {function (Object)} a function that examines the source code
780 * in the input job and builds the decoration list.
781 */
782 function sourceDecorator(options) {
783 var shortcutStylePatterns = [], fallthroughStylePatterns = [];
784 if (options['tripleQuotedStrings']) {
785 // '''multi-line-string''', 'single-line-string', and double-quoted
786 shortcutStylePatterns.push(
787 [PR_STRING, /^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/,
788 null, '\'"']);
789 } else if (options['multiLineStrings']) {
790 // 'multi-line-string', "multi-line-string"
791 shortcutStylePatterns.push(
792 [PR_STRING, /^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,
793 null, '\'"`']);
794 } else {
795 // 'single-line-string', "single-line-string"
796 shortcutStylePatterns.push(
797 [PR_STRING,
798 /^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,
799 null, '"\'']);
800 }
801 if (options['verbatimStrings']) {
802 // verbatim-string-literal production from the C# grammar. See issue 93.
803 fallthroughStylePatterns.push(
804 [PR_STRING, /^@\"(?:[^\"]|\"\")*(?:\"|$)/, null]);
805 }
806 var hc = options['hashComments'];
807 if (hc) {
808 if (options['cStyleComments']) {
809 if (hc > 1) { // multiline hash comments
810 shortcutStylePatterns.push(
811 [PR_COMMENT, /^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/, null, '#']);
812 } else {
813 // Stop C preprocessor declarations at an unclosed open comment
814 shortcutStylePatterns.push(
815 [PR_COMMENT, /^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\r\n]*)/,
816 null, '#']);
817 }
818 fallthroughStylePatterns.push(
819 [PR_STRING,
820 /^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,
821 null]);
822 } else {
823 shortcutStylePatterns.push([PR_COMMENT, /^#[^\r\n]*/, null, '#']);
824 }
825 }
826 if (options['cStyleComments']) {
827 fallthroughStylePatterns.push([PR_COMMENT, /^\/\/[^\r\n]*/, null]);
828 fallthroughStylePatterns.push(
829 [PR_COMMENT, /^\/\*[\s\S]*?(?:\*\/|$)/, null]);
830 }
831 if (options['regexLiterals']) {
832 /**
833 * @const
834 */
835 var REGEX_LITERAL = (
836 // A regular expression literal starts with a slash that is
837 // not followed by * or / so that it is not confused with
838 // comments.
839 '/(?=[^/*])'
840 // and then contains any number of raw characters,
841 + '(?:[^/\\x5B\\x5C]'
842 // escape sequences (\x5C),
843 + '|\\x5C[\\s\\S]'
844 // or non-nesting character sets (\x5B\x5D);
845 + '|\\x5B(?:[^\\x5C\\x5D]|\\x5C[\\s\\S])*(?:\\x5D|$))+'
846 // finally closed by a /.
847 + '/');
848 fallthroughStylePatterns.push(
849 ['lang-regex',
850 new RegExp('^' + REGEXP_PRECEDER_PATTERN + '(' + REGEX_LITERAL + ')')
851 ]);
852 }
853
854 var types = options['types'];
855 if (types) {
856 fallthroughStylePatterns.push([PR_TYPE, types]);
857 }
858
859 var keywords = ("" + options['keywords']).replace(/^ | $/g, '');
860 if (keywords.length) {
861 fallthroughStylePatterns.push(
862 [PR_KEYWORD,
863 new RegExp('^(?:' + keywords.replace(/[\s,]+/g, '|') + ')\\b'),
864 null]);
865 }
866
867 shortcutStylePatterns.push([PR_PLAIN, /^\s+/, null, ' \r\n\t\xA0']);
868 fallthroughStylePatterns.push(
869 // TODO(mikesamuel): recognize non-latin letters and numerals in idents
870 [PR_LITERAL, /^@[a-z_$][a-z_$@0-9]*/i, null],
871 [PR_TYPE, /^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\w+_t\b)/, null],
872 [PR_PLAIN, /^[a-z_$][a-z_$@0-9]*/i, null],
873 [PR_LITERAL,
874 new RegExp(
875 '^(?:'
876 // A hex number
877 + '0x[a-f0-9]+'
878 // or an octal or decimal number,
879 + '|(?:\\d(?:_\\d+)*\\d*(?:\\.\\d*)?|\\.\\d\\+)'
880 // possibly in scientific notation
881 + '(?:e[+\\-]?\\d+)?'
882 + ')'
883 // with an optional modifier like UL for unsigned long
884 + '[a-z]*', 'i'),
885 null, '0123456789'],
886 // Don't treat escaped quotes in bash as starting strings. See issue 144.
887 [PR_PLAIN, /^\\[\s\S]?/, null],
888 [PR_PUNCTUATION, /^.[^\s\w\.$@\'\"\`\/\#\\]*/, null]);
889
890 return createSimpleLexer(shortcutStylePatterns, fallthroughStylePatterns);
891 }
892
893 var decorateSource = sourceDecorator({
894 'keywords': ALL_KEYWORDS,
895 'hashComments': true,
896 'cStyleComments': true,
897 'multiLineStrings': true,
898 'regexLiterals': true
899 });
900
901 /**
902 * Given a DOM subtree, wraps it in a list, and puts each line into its own
903 * list item.
904 *
905 * @param {Node} node modified in place. Its content is pulled into an
906 * HTMLOListElement, and each line is moved into a separate list item.
907 * This requires cloning elements, so the input might not have unique
908 * IDs after numbering.
909 */
910 function numberLines(node, opt_startLineNum) {
911 var nocode = /(?:^|\s)nocode(?:\s|$)/;
912 var lineBreak = /\r\n?|\n/;
913
914 var document = node.ownerDocument;
915
916 var whitespace;
917 if (node.currentStyle) {
918 whitespace = node.currentStyle.whiteSpace;
919 } else if (window.getComputedStyle) {
920 whitespace = document.defaultView.getComputedStyle(node, null)
921 .getPropertyValue('white-space');
922 }
923 // If it's preformatted, then we need to split lines on line breaks
924 // in addition to <BR>s.
925 var isPreformatted = whitespace && 'pre' === whitespace.substring(0, 3);
926
927 var li = document.createElement('LI');
928 while (node.firstChild) {
929 li.appendChild(node.firstChild);
930 }
931 // An array of lines. We split below, so this is initialized to one
932 // un-split line.
933 var listItems = [li];
934
935 function walk(node) {
936 switch (node.nodeType) {
937 case 1: // Element
938 if (nocode.test(node.className)) { break; }
939 if ('BR' === node.nodeName) {
940 breakAfter(node);
941 // Discard the <BR> since it is now flush against a </LI>.
942 if (node.parentNode) {
943 node.parentNode.removeChild(node);
944 }
945 } else {
946 for (var child = node.firstChild; child; child = child.nextSibling) {
947 walk(child);
948 }
949 }
950 break;
951 case 3: case 4: // Text
952 if (isPreformatted) {
953 var text = node.nodeValue;
954 var match = text.match(lineBreak);
955 if (match) {
956 var firstLine = text.substring(0, match.index);
957 node.nodeValue = firstLine;
958 var tail = text.substring(match.index + match[0].length);
959 if (tail) {
960 var parent = node.parentNode;
961 parent.insertBefore(
962 document.createTextNode(tail), node.nextSibling);
963 }
964 breakAfter(node);
965 if (!firstLine) {
966 // Don't leave blank text nodes in the DOM.
967 node.parentNode.removeChild(node);
968 }
969 }
970 }
971 break;
972 }
973 }
974
975 // Split a line after the given node.
976 function breakAfter(lineEndNode) {
977 // If there's nothing to the right, then we can skip ending the line
978 // here, and move root-wards since splitting just before an end-tag
979 // would require us to create a bunch of empty copies.
980 while (!lineEndNode.nextSibling) {
981 lineEndNode = lineEndNode.parentNode;
982 if (!lineEndNode) { return; }
983 }
984
985 function breakLeftOf(limit, copy) {
986 // Clone shallowly if this node needs to be on both sides of the break.
987 var rightSide = copy ? limit.cloneNode(false) : limit;
988 var parent = limit.parentNode;
989 if (parent) {
990 // We clone the parent chain.
991 // This helps us resurrect important styling elements that cross lines.
992 // E.g. in <i>Foo<br>Bar</i>
993 // should be rewritten to <li><i>Foo</i></li><li><i>Bar</i></li>.
994 var parentClone = breakLeftOf(parent, 1);
995 // Move the clone and everything to the right of the original
996 // onto the cloned parent.
997 var next = limit.nextSibling;
998 parentClone.appendChild(rightSide);
999 for (var sibling = next; sibling; sibling = next) {
1000 next = sibling.nextSibling;
1001 parentClone.appendChild(sibling);
1002 }
1003 }
1004 return rightSide;
1005 }
1006
1007 var copiedListItem = breakLeftOf(lineEndNode.nextSibling, 0);
1008
1009 // Walk the parent chain until we reach an unattached LI.
1010 for (var parent;
1011 // Check nodeType since IE invents document fragments.
1012 (parent = copiedListItem.parentNode) && parent.nodeType === 1;) {
1013 copiedListItem = parent;
1014 }
1015 // Put it on the list of lines for later processing.
1016 listItems.push(copiedListItem);
1017 }
1018
1019 // Split lines while there are lines left to split.
1020 for (var i = 0; // Number of lines that have been split so far.
1021 i < listItems.length; // length updated by breakAfter calls.
1022 ++i) {
1023 walk(listItems[i]);
1024 }
1025
1026 // Make sure numeric indices show correctly.
1027 if (opt_startLineNum === (opt_startLineNum|0)) {
1028 listItems[0].setAttribute('value', opt_startLineNum);
1029 }
1030
1031 var ol = document.createElement('OL');
1032 ol.className = 'linenums';
1033 var offset = Math.max(0, ((opt_startLineNum - 1 /* zero index */)) | 0) || 0;
1034 for (var i = 0, n = listItems.length; i < n; ++i) {
1035 li = listItems[i];
1036 // Stick a class on the LIs so that stylesheets can
1037 // color odd/even rows, or any other row pattern that
1038 // is co-prime with 10.
1039 li.className = 'L' + ((i + offset) % 10);
1040 if (!li.firstChild) {
1041 li.appendChild(document.createTextNode('\xA0'));
1042 }
1043 ol.appendChild(li);
1044 }
1045
1046 node.appendChild(ol);
1047 }
1048
1049 /**
1050 * Breaks {@code job.sourceCode} around style boundaries in
1051 * {@code job.decorations} and modifies {@code job.sourceNode} in place.
1052 * @param {Object} job like <pre>{
1053 * sourceCode: {string} source as plain text,
1054 * spans: {Array.<number|Node>} alternating span start indices into source
1055 * and the text node or element (e.g. {@code <BR>}) corresponding to that
1056 * span.
1057 * decorations: {Array.<number|string} an array of style classes preceded
1058 * by the position at which they start in job.sourceCode in order
1059 * }</pre>
1060 * @private
1061 */
1062 function recombineTagsAndDecorations(job) {
1063 var isIE = /\bMSIE\b/.test(navigator.userAgent);
1064 var newlineRe = /\n/g;
1065
1066 var source = job.sourceCode;
1067 var sourceLength = source.length;
1068 // Index into source after the last code-unit recombined.
1069 var sourceIndex = 0;
1070
1071 var spans = job.spans;
1072 var nSpans = spans.length;
1073 // Index into spans after the last span which ends at or before sourceIndex.
1074 var spanIndex = 0;
1075
1076 var decorations = job.decorations;
1077 var nDecorations = decorations.length;
1078 // Index into decorations after the last decoration which ends at or before
1079 // sourceIndex.
1080 var decorationIndex = 0;
1081
1082 // Remove all zero-length decorations.
1083 decorations[nDecorations] = sourceLength;
1084 var decPos, i;
1085 for (i = decPos = 0; i < nDecorations;) {
1086 if (decorations[i] !== decorations[i + 2]) {
1087 decorations[decPos++] = decorations[i++];
1088 decorations[decPos++] = decorations[i++];
1089 } else {
1090 i += 2;
1091 }
1092 }
1093 nDecorations = decPos;
1094
1095 // Simplify decorations.
1096 for (i = decPos = 0; i < nDecorations;) {
1097 var startPos = decorations[i];
1098 // Conflate all adjacent decorations that use the same style.
1099 var startDec = decorations[i + 1];
1100 var end = i + 2;
1101 while (end + 2 <= nDecorations && decorations[end + 1] === startDec) {
1102 end += 2;
1103 }
1104 decorations[decPos++] = startPos;
1105 decorations[decPos++] = startDec;
1106 i = end;
1107 }
1108
1109 nDecorations = decorations.length = decPos;
1110
1111 var decoration = null;
1112 while (spanIndex < nSpans) {
1113 var spanStart = spans[spanIndex];
1114 var spanEnd = spans[spanIndex + 2] || sourceLength;
1115
1116 var decStart = decorations[decorationIndex];
1117 var decEnd = decorations[decorationIndex + 2] || sourceLength;
1118
1119 var end = Math.min(spanEnd, decEnd);
1120
1121 var textNode = spans[spanIndex + 1];
1122 var styledText;
1123 if (textNode.nodeType !== 1 // Don't muck with <BR>s or <LI>s
1124 // Don't introduce spans around empty text nodes.
1125 && (styledText = source.substring(sourceIndex, end))) {
1126 // This may seem bizarre, and it is. Emitting LF on IE causes the
1127 // code to display with spaces instead of line breaks.
1128 // Emitting Windows standard issue linebreaks (CRLF) causes a blank
1129 // space to appear at the beginning of every line but the first.
1130 // Emitting an old Mac OS 9 line separator makes everything spiffy.
1131 if (isIE) { styledText = styledText.replace(newlineRe, '\r'); }
1132 textNode.nodeValue = styledText;
1133 var document = textNode.ownerDocument;
1134 var span = document.createElement('SPAN');
1135 span.className = decorations[decorationIndex + 1];
1136 var parentNode = textNode.parentNode;
1137 parentNode.replaceChild(span, textNode);
1138 span.appendChild(textNode);
1139 if (sourceIndex < spanEnd) { // Split off a text node.
1140 spans[spanIndex + 1] = textNode
1141 // TODO: Possibly optimize by using '' if there's no flicker.
1142 = document.createTextNode(source.substring(end, spanEnd));
1143 parentNode.insertBefore(textNode, span.nextSibling);
1144 }
1145 }
1146
1147 sourceIndex = end;
1148
1149 if (sourceIndex >= spanEnd) {
1150 spanIndex += 2;
1151 }
1152 if (sourceIndex >= decEnd) {
1153 decorationIndex += 2;
1154 }
1155 }
1156 }
1157
1158
1159 /** Maps language-specific file extensions to handlers. */
1160 var langHandlerRegistry = {};
1161 /** Register a language handler for the given file extensions.
1162 * @param {function (Object)} handler a function from source code to a list
1163 * of decorations. Takes a single argument job which describes the
1164 * state of the computation. The single parameter has the form
1165 * {@code {
1166 * sourceCode: {string} as plain text.
1167 * decorations: {Array.<number|string>} an array of style classes
1168 * preceded by the position at which they start in
1169 * job.sourceCode in order.
1170 * The language handler should assigned this field.
1171 * basePos: {int} the position of source in the larger source chunk.
1172 * All positions in the output decorations array are relative
1173 * to the larger source chunk.
1174 * } }
1175 * @param {Array.<string>} fileExtensions
1176 */
1177 function registerLangHandler(handler, fileExtensions) {
1178 for (var i = fileExtensions.length; --i >= 0;) {
1179 var ext = fileExtensions[i];
1180 if (!langHandlerRegistry.hasOwnProperty(ext)) {
1181 langHandlerRegistry[ext] = handler;
1182 } else if (window['console']) {
1183 console['warn']('cannot override language handler %s', ext);
1184 }
1185 }
1186 }
1187 function langHandlerForExtension(extension, source) {
1188 if (!(extension && langHandlerRegistry.hasOwnProperty(extension))) {
1189 // Treat it as markup if the first non whitespace character is a < and
1190 // the last non-whitespace character is a >.
1191 extension = /^\s*</.test(source)
1192 ? 'default-markup'
1193 : 'default-code';
1194 }
1195 return langHandlerRegistry[extension];
1196 }
1197 registerLangHandler(decorateSource, ['default-code']);
1198 registerLangHandler(
1199 createSimpleLexer(
1200 [],
1201 [
1202 [PR_PLAIN, /^[^<?]+/],
1203 [PR_DECLARATION, /^<!\w[^>]*(?:>|$)/],
1204 [PR_COMMENT, /^<\!--[\s\S]*?(?:-\->|$)/],
1205 // Unescaped content in an unknown language
1206 ['lang-', /^<\?([\s\S]+?)(?:\?>|$)/],
1207 ['lang-', /^<%([\s\S]+?)(?:%>|$)/],
1208 [PR_PUNCTUATION, /^(?:<[%?]|[%?]>)/],
1209 ['lang-', /^<xmp\b[^>]*>([\s\S]+?)<\/xmp\b[^>]*>/i],
1210 // Unescaped content in javascript. (Or possibly vbscript).
1211 ['lang-js', /^<script\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],
1212 // Contains unescaped stylesheet content
1213 ['lang-css', /^<style\b[^>]*>([\s\S]*?)(<\/style\b[^>]*>)/i],
1214 ['lang-in.tag', /^(<\/?[a-z][^<>]*>)/i]
1215 ]),
1216 ['default-markup', 'htm', 'html', 'mxml', 'xhtml', 'xml', 'xsl']);
1217 registerLangHandler(
1218 createSimpleLexer(
1219 [
1220 [PR_PLAIN, /^[\s]+/, null, ' \t\r\n'],
1221 [PR_ATTRIB_VALUE, /^(?:\"[^\"]*\"?|\'[^\']*\'?)/, null, '\"\'']
1222 ],
1223 [
1224 [PR_TAG, /^^<\/?[a-z](?:[\w.:-]*\w)?|\/?>$/i],
1225 [PR_ATTRIB_NAME, /^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],
1226 ['lang-uq.val', /^=\s*([^>\'\"\s]*(?:[^>\'\"\s\/]|\/(?=\s)))/],
1227 [PR_PUNCTUATION, /^[=<>\/]+/],
1228 ['lang-js', /^on\w+\s*=\s*\"([^\"]+)\"/i],
1229 ['lang-js', /^on\w+\s*=\s*\'([^\']+)\'/i],
1230 ['lang-js', /^on\w+\s*=\s*([^\"\'>\s]+)/i],
1231 ['lang-css', /^style\s*=\s*\"([^\"]+)\"/i],
1232 ['lang-css', /^style\s*=\s*\'([^\']+)\'/i],
1233 ['lang-css', /^style\s*=\s*([^\"\'>\s]+)/i]
1234 ]),
1235 ['in.tag']);
1236 registerLangHandler(
1237 createSimpleLexer([], [[PR_ATTRIB_VALUE, /^[\s\S]+/]]), ['uq.val']);
1238 registerLangHandler(sourceDecorator({
1239 'keywords': CPP_KEYWORDS,
1240 'hashComments': true,
1241 'cStyleComments': true,
1242 'types': C_TYPES
1243 }), ['c', 'cc', 'cpp', 'cxx', 'cyc', 'm']);
1244 registerLangHandler(sourceDecorator({
1245 'keywords': 'null,true,false'
1246 }), ['json']);
1247 registerLangHandler(sourceDecorator({
1248 'keywords': CSHARP_KEYWORDS,
1249 'hashComments': true,
1250 'cStyleComments': true,
1251 'verbatimStrings': true,
1252 'types': C_TYPES
1253 }), ['cs']);
1254 registerLangHandler(sourceDecorator({
1255 'keywords': JAVA_KEYWORDS,
1256 'cStyleComments': true
1257 }), ['java']);
1258 registerLangHandler(sourceDecorator({
1259 'keywords': SH_KEYWORDS,
1260 'hashComments': true,
1261 'multiLineStrings': true
1262 }), ['bsh', 'csh', 'sh']);
1263 registerLangHandler(sourceDecorator({
1264 'keywords': PYTHON_KEYWORDS,
1265 'hashComments': true,
1266 'multiLineStrings': true,
1267 'tripleQuotedStrings': true
1268 }), ['cv', 'py']);
1269 registerLangHandler(sourceDecorator({
1270 'keywords': PERL_KEYWORDS,
1271 'hashComments': true,
1272 'multiLineStrings': true,
1273 'regexLiterals': true
1274 }), ['perl', 'pl', 'pm']);
1275 registerLangHandler(sourceDecorator({
1276 'keywords': RUBY_KEYWORDS,
1277 'hashComments': true,
1278 'multiLineStrings': true,
1279 'regexLiterals': true
1280 }), ['rb']);
1281 registerLangHandler(sourceDecorator({
1282 'keywords': JSCRIPT_KEYWORDS,
1283 'cStyleComments': true,
1284 'regexLiterals': true
1285 }), ['js']);
1286 registerLangHandler(sourceDecorator({
1287 'keywords': COFFEE_KEYWORDS,
1288 'hashComments': 3, // ### style block comments
1289 'cStyleComments': true,
1290 'multilineStrings': true,
1291 'tripleQuotedStrings': true,
1292 'regexLiterals': true
1293 }), ['coffee']);
1294 registerLangHandler(createSimpleLexer([], [[PR_STRING, /^[\s\S]+/]]), ['regex']);
1295
1296 function applyDecorator(job) {
1297 var opt_langExtension = job.langExtension;
1298
1299 try {
1300 // Extract tags, and convert the source code to plain text.
1301 var sourceAndSpans = extractSourceSpans(job.sourceNode);
1302 /** Plain text. @type {string} */
1303 var source = sourceAndSpans.sourceCode;
1304 job.sourceCode = source;
1305 job.spans = sourceAndSpans.spans;
1306 job.basePos = 0;
1307
1308 // Apply the appropriate language handler
1309 langHandlerForExtension(opt_langExtension, source)(job);
1310
1311 // Integrate the decorations and tags back into the source code,
1312 // modifying the sourceNode in place.
1313 recombineTagsAndDecorations(job);
1314 } catch (e) {
1315 if ('console' in window) {
1316 console['log'](e && e['stack'] ? e['stack'] : e);
1317 }
1318 }
1319 }
1320
1321 /**
1322 * @param sourceCodeHtml {string} The HTML to pretty print.
1323 * @param opt_langExtension {string} The language name to use.
1324 * Typically, a filename extension like 'cpp' or 'java'.
1325 * @param opt_numberLines {number|boolean} True to number lines,
1326 * or the 1-indexed number of the first line in sourceCodeHtml.
1327 */
1328 function prettyPrintOne(sourceCodeHtml, opt_langExtension, opt_numberLines) {
1329 var container = document.createElement('PRE');
1330 // This could cause images to load and onload listeners to fire.
1331 // E.g. <img onerror="alert(1337)" src="nosuchimage.png">.
1332 // We assume that the inner HTML is from a trusted source.
1333 container.innerHTML = sourceCodeHtml;
1334 if (opt_numberLines) {
1335 numberLines(container, opt_numberLines);
1336 }
1337
1338 var job = {
1339 langExtension: opt_langExtension,
1340 numberLines: opt_numberLines,
1341 sourceNode: container
1342 };
1343 applyDecorator(job);
1344 return container.innerHTML;
1345 }
1346
1347 function prettyPrint(opt_whenDone) {
1348 function byTagName(tn) { return document.getElementsByTagName(tn); }
1349 // fetch a list of nodes to rewrite
1350 var codeSegments = [byTagName('pre'), byTagName('code'), byTagName('xmp')];
1351 var elements = [];
1352 for (var i = 0; i < codeSegments.length; ++i) {
1353 for (var j = 0, n = codeSegments[i].length; j < n; ++j) {
1354 elements.push(codeSegments[i][j]);
1355 }
1356 }
1357 codeSegments = null;
1358
1359 var clock = Date;
1360 if (!clock['now']) {
1361 clock = { 'now': function () { return +(new Date); } };
1362 }
1363
1364 // The loop is broken into a series of continuations to make sure that we
1365 // don't make the browser unresponsive when rewriting a large page.
1366 var k = 0;
1367 var prettyPrintingJob;
1368
1369 var langExtensionRe = /\blang(?:uage)?-([\w.]+)(?!\S)/;
1370 var prettyPrintRe = /\bprettyprint\b/;
1371
1372 function doWork() {
1373 var endTime = (window['PR_SHOULD_USE_CONTINUATION'] ?
1374 clock['now']() + 250 /* ms */ :
1375 Infinity);
1376 for (; k < elements.length && clock['now']() < endTime; k++) {
1377 var cs = elements[k];
1378 var className = cs.className;
1379 if (className.indexOf('prettyprint') >= 0) {
1380 // If the classes includes a language extensions, use it.
1381 // Language extensions can be specified like
1382 // <pre class="prettyprint lang-cpp">
1383 // the language extension "cpp" is used to find a language handler as
1384 // passed to PR.registerLangHandler.
1385 // HTML5 recommends that a language be specified using "language-"
1386 // as the prefix instead. Google Code Prettify supports both.
1387 // http://dev.w3.org/html5/spec-author-view/the-code-element.html
1388 var langExtension = className.match(langExtensionRe);
1389 // Support <pre class="prettyprint"><code class="language-c">
1390 var wrapper;
1391 if (!langExtension && (wrapper = childContentWrapper(cs))
1392 && "CODE" === wrapper.tagName) {
1393 langExtension = wrapper.className.match(langExtensionRe);
1394 }
1395
1396 if (langExtension) {
1397 langExtension = langExtension[1];
1398 }
1399
1400 // make sure this is not nested in an already prettified element
1401 var nested = false;
1402 for (var p = cs.parentNode; p; p = p.parentNode) {
1403 if ((p.tagName === 'pre' || p.tagName === 'code' ||
1404 p.tagName === 'xmp') &&
1405 p.className && p.className.indexOf('prettyprint') >= 0) {
1406 nested = true;
1407 break;
1408 }
1409 }
1410 if (!nested) {
1411 // Look for a class like linenums or linenums:<n> where <n> is the
1412 // 1-indexed number of the first line.
1413 var lineNums = cs.className.match(/\blinenums\b(?::(\d+))?/);
1414 lineNums = lineNums
1415 ? lineNums[1] && lineNums[1].length ? +lineNums[1] : true
1416 : false;
1417 if (lineNums) { numberLines(cs, lineNums); }
1418
1419 // do the pretty printing
1420 prettyPrintingJob = {
1421 langExtension: langExtension,
1422 sourceNode: cs,
1423 numberLines: lineNums
1424 };
1425 applyDecorator(prettyPrintingJob);
1426 }
1427 }
1428 }
1429 if (k < elements.length) {
1430 // finish up in a continuation
1431 setTimeout(doWork, 250);
1432 } else if (opt_whenDone) {
1433 opt_whenDone();
1434 }
1435 }
1436
1437 doWork();
1438 }
1439
1440 /**
1441 * Find all the {@code <pre>} and {@code <code>} tags in the DOM with
1442 * {@code class=prettyprint} and prettify them.
1443 *
1444 * @param {Function?} opt_whenDone if specified, called when the last entry
1445 * has been finished.
1446 */
1447 window['prettyPrintOne'] = prettyPrintOne;
1448 /**
1449 * Pretty print a chunk of code.
1450 *
1451 * @param {string} sourceCodeHtml code as html
1452 * @return {string} code as html, but prettier
1453 */
1454 window['prettyPrint'] = prettyPrint;
1455 /**
1456 * Contains functions for creating and registering new language handlers.
1457 * @type {Object}
1458 */
1459 window['PR'] = {
1460 'createSimpleLexer': createSimpleLexer,
1461 'registerLangHandler': registerLangHandler,
1462 'sourceDecorator': sourceDecorator,
1463 'PR_ATTRIB_NAME': PR_ATTRIB_NAME,
1464 'PR_ATTRIB_VALUE': PR_ATTRIB_VALUE,
1465 'PR_COMMENT': PR_COMMENT,
1466 'PR_DECLARATION': PR_DECLARATION,
1467 'PR_KEYWORD': PR_KEYWORD,
1468 'PR_LITERAL': PR_LITERAL,
1469 'PR_NOCODE': PR_NOCODE,
1470 'PR_PLAIN': PR_PLAIN,
1471 'PR_PUNCTUATION': PR_PUNCTUATION,
1472 'PR_SOURCE': PR_SOURCE,
1473 'PR_STRING': PR_STRING,
1474 'PR_TAG': PR_TAG,
1475 'PR_TYPE': PR_TYPE
1476 };
1477 })();
General Comments 0
You need to be logged in to leave comments. Login now