filter special characters..
[sgn.git] / js / source / legacy / jqueryui.js
blob7b727e74350cbef7d079ea93d8da23a511eaa961
1 /*! jQuery UI - v1.10.3 - 2013-05-03
2 * http://jqueryui.com
3 * Includes: jquery.ui.core.js, jquery.ui.widget.js, jquery.ui.mouse.js, jquery.ui.draggable.js, jquery.ui.droppable.js, jquery.ui.resizable.js, jquery.ui.selectable.js, jquery.ui.sortable.js, jquery.ui.effect.js, jquery.ui.accordion.js, jquery.ui.autocomplete.js, jquery.ui.button.js, jquery.ui.datepicker.js, jquery.ui.dialog.js, jquery.ui.effect-blind.js, jquery.ui.effect-bounce.js, jquery.ui.effect-clip.js, jquery.ui.effect-drop.js, jquery.ui.effect-explode.js, jquery.ui.effect-fade.js, jquery.ui.effect-fold.js, jquery.ui.effect-highlight.js, jquery.ui.effect-pulsate.js, jquery.ui.effect-scale.js, jquery.ui.effect-shake.js, jquery.ui.effect-slide.js, jquery.ui.effect-transfer.js, jquery.ui.menu.js, jquery.ui.position.js, jquery.ui.progressbar.js, jquery.ui.slider.js, jquery.ui.spinner.js, jquery.ui.tabs.js, jquery.ui.tooltip.js
4 * Copyright 2013 jQuery Foundation and other contributors; Licensed MIT */
5 (function( $, undefined ) {
7 var uuid = 0,
8         runiqueId = /^ui-id-\d+$/;
10 // $.ui might exist from components with no dependencies, e.g., $.ui.position
11 $.ui = $.ui || {};
13 $.extend( $.ui, {
14         version: "1.10.3",
16         keyCode: {
17                 BACKSPACE: 8,
18                 COMMA: 188,
19                 DELETE: 46,
20                 DOWN: 40,
21                 END: 35,
22                 ENTER: 13,
23                 ESCAPE: 27,
24                 HOME: 36,
25                 LEFT: 37,
26                 NUMPAD_ADD: 107,
27                 NUMPAD_DECIMAL: 110,
28                 NUMPAD_DIVIDE: 111,
29                 NUMPAD_ENTER: 108,
30                 NUMPAD_MULTIPLY: 106,
31                 NUMPAD_SUBTRACT: 109,
32                 PAGE_DOWN: 34,
33                 PAGE_UP: 33,
34                 PERIOD: 190,
35                 RIGHT: 39,
36                 SPACE: 32,
37                 TAB: 9,
38                 UP: 38
39         }
40 });
42 // plugins
43 $.fn.extend({
44         focus: (function( orig ) {
45                 return function( delay, fn ) {
46                         return typeof delay === "number" ?
47                                 this.each(function() {
48                                         var elem = this;
49                                         setTimeout(function() {
50                                                 $( elem ).focus();
51                                                 if ( fn ) {
52                                                         fn.call( elem );
53                                                 }
54                                         }, delay );
55                                 }) :
56                                 orig.apply( this, arguments );
57                 };
58         })( $.fn.focus ),
60         scrollParent: function() {
61                 var scrollParent;
62                 if (($.ui.ie && (/(static|relative)/).test(this.css("position"))) || (/absolute/).test(this.css("position"))) {
63                         scrollParent = this.parents().filter(function() {
64                                 return (/(relative|absolute|fixed)/).test($.css(this,"position")) && (/(auto|scroll)/).test($.css(this,"overflow")+$.css(this,"overflow-y")+$.css(this,"overflow-x"));
65                         }).eq(0);
66                 } else {
67                         scrollParent = this.parents().filter(function() {
68                                 return (/(auto|scroll)/).test($.css(this,"overflow")+$.css(this,"overflow-y")+$.css(this,"overflow-x"));
69                         }).eq(0);
70                 }
72                 return (/fixed/).test(this.css("position")) || !scrollParent.length ? $(document) : scrollParent;
73         },
75         zIndex: function( zIndex ) {
76                 if ( zIndex !== undefined ) {
77                         return this.css( "zIndex", zIndex );
78                 }
80                 if ( this.length ) {
81                         var elem = $( this[ 0 ] ), position, value;
82                         while ( elem.length && elem[ 0 ] !== document ) {
83                                 // Ignore z-index if position is set to a value where z-index is ignored by the browser
84                                 // This makes behavior of this function consistent across browsers
85                                 // WebKit always returns auto if the element is positioned
86                                 position = elem.css( "position" );
87                                 if ( position === "absolute" || position === "relative" || position === "fixed" ) {
88                                         // IE returns 0 when zIndex is not specified
89                                         // other browsers return a string
90                                         // we ignore the case of nested elements with an explicit value of 0
91                                         // <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
92                                         value = parseInt( elem.css( "zIndex" ), 10 );
93                                         if ( !isNaN( value ) && value !== 0 ) {
94                                                 return value;
95                                         }
96                                 }
97                                 elem = elem.parent();
98                         }
99                 }
101                 return 0;
102         },
104         uniqueId: function() {
105                 return this.each(function() {
106                         if ( !this.id ) {
107                                 this.id = "ui-id-" + (++uuid);
108                         }
109                 });
110         },
112         removeUniqueId: function() {
113                 return this.each(function() {
114                         if ( runiqueId.test( this.id ) ) {
115                                 $( this ).removeAttr( "id" );
116                         }
117                 });
118         }
121 // selectors
122 function focusable( element, isTabIndexNotNaN ) {
123         var map, mapName, img,
124                 nodeName = element.nodeName.toLowerCase();
125         if ( "area" === nodeName ) {
126                 map = element.parentNode;
127                 mapName = map.name;
128                 if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
129                         return false;
130                 }
131                 img = $( "img[usemap=#" + mapName + "]" )[0];
132                 return !!img && visible( img );
133         }
134         return ( /input|select|textarea|button|object/.test( nodeName ) ?
135                 !element.disabled :
136                 "a" === nodeName ?
137                         element.href || isTabIndexNotNaN :
138                         isTabIndexNotNaN) &&
139                 // the element and all of its ancestors must be visible
140                 visible( element );
143 function visible( element ) {
144         return $.expr.filters.visible( element ) &&
145                 !$( element ).parents().addBack().filter(function() {
146                         return $.css( this, "visibility" ) === "hidden";
147                 }).length;
150 $.extend( $.expr[ ":" ], {
151         data: $.expr.createPseudo ?
152                 $.expr.createPseudo(function( dataName ) {
153                         return function( elem ) {
154                                 return !!$.data( elem, dataName );
155                         };
156                 }) :
157                 // support: jQuery <1.8
158                 function( elem, i, match ) {
159                         return !!$.data( elem, match[ 3 ] );
160                 },
162         focusable: function( element ) {
163                 return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) );
164         },
166         tabbable: function( element ) {
167                 var tabIndex = $.attr( element, "tabindex" ),
168                         isTabIndexNaN = isNaN( tabIndex );
169                 return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN );
170         }
173 // support: jQuery <1.8
174 if ( !$( "<a>" ).outerWidth( 1 ).jquery ) {
175         $.each( [ "Width", "Height" ], function( i, name ) {
176                 var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
177                         type = name.toLowerCase(),
178                         orig = {
179                                 innerWidth: $.fn.innerWidth,
180                                 innerHeight: $.fn.innerHeight,
181                                 outerWidth: $.fn.outerWidth,
182                                 outerHeight: $.fn.outerHeight
183                         };
185                 function reduce( elem, size, border, margin ) {
186                         $.each( side, function() {
187                                 size -= parseFloat( $.css( elem, "padding" + this ) ) || 0;
188                                 if ( border ) {
189                                         size -= parseFloat( $.css( elem, "border" + this + "Width" ) ) || 0;
190                                 }
191                                 if ( margin ) {
192                                         size -= parseFloat( $.css( elem, "margin" + this ) ) || 0;
193                                 }
194                         });
195                         return size;
196                 }
198                 $.fn[ "inner" + name ] = function( size ) {
199                         if ( size === undefined ) {
200                                 return orig[ "inner" + name ].call( this );
201                         }
203                         return this.each(function() {
204                                 $( this ).css( type, reduce( this, size ) + "px" );
205                         });
206                 };
208                 $.fn[ "outer" + name] = function( size, margin ) {
209                         if ( typeof size !== "number" ) {
210                                 return orig[ "outer" + name ].call( this, size );
211                         }
213                         return this.each(function() {
214                                 $( this).css( type, reduce( this, size, true, margin ) + "px" );
215                         });
216                 };
217         });
220 // support: jQuery <1.8
221 if ( !$.fn.addBack ) {
222         $.fn.addBack = function( selector ) {
223                 return this.add( selector == null ?
224                         this.prevObject : this.prevObject.filter( selector )
225                 );
226         };
229 // support: jQuery 1.6.1, 1.6.2 (http://bugs.jquery.com/ticket/9413)
230 if ( $( "<a>" ).data( "a-b", "a" ).removeData( "a-b" ).data( "a-b" ) ) {
231         $.fn.removeData = (function( removeData ) {
232                 return function( key ) {
233                         if ( arguments.length ) {
234                                 return removeData.call( this, $.camelCase( key ) );
235                         } else {
236                                 return removeData.call( this );
237                         }
238                 };
239         })( $.fn.removeData );
246 // deprecated
247 $.ui.ie = !!/msie [\w.]+/.exec( navigator.userAgent.toLowerCase() );
249 $.support.selectstart = "onselectstart" in document.createElement( "div" );
250 $.fn.extend({
251         disableSelection: function() {
252                 return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) +
253                         ".ui-disableSelection", function( event ) {
254                                 event.preventDefault();
255                         });
256         },
258         enableSelection: function() {
259                 return this.unbind( ".ui-disableSelection" );
260         }
263 $.extend( $.ui, {
264         // $.ui.plugin is deprecated. Use $.widget() extensions instead.
265         plugin: {
266                 add: function( module, option, set ) {
267                         var i,
268                                 proto = $.ui[ module ].prototype;
269                         for ( i in set ) {
270                                 proto.plugins[ i ] = proto.plugins[ i ] || [];
271                                 proto.plugins[ i ].push( [ option, set[ i ] ] );
272                         }
273                 },
274                 call: function( instance, name, args ) {
275                         var i,
276                                 set = instance.plugins[ name ];
277                         if ( !set || !instance.element[ 0 ].parentNode || instance.element[ 0 ].parentNode.nodeType === 11 ) {
278                                 return;
279                         }
281                         for ( i = 0; i < set.length; i++ ) {
282                                 if ( instance.options[ set[ i ][ 0 ] ] ) {
283                                         set[ i ][ 1 ].apply( instance.element, args );
284                                 }
285                         }
286                 }
287         },
289         // only used by resizable
290         hasScroll: function( el, a ) {
292                 //If overflow is hidden, the element might have extra content, but the user wants to hide it
293                 if ( $( el ).css( "overflow" ) === "hidden") {
294                         return false;
295                 }
297                 var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
298                         has = false;
300                 if ( el[ scroll ] > 0 ) {
301                         return true;
302                 }
304                 // TODO: determine which cases actually cause this to happen
305                 // if the element doesn't have the scroll set, see if it's possible to
306                 // set the scroll
307                 el[ scroll ] = 1;
308                 has = ( el[ scroll ] > 0 );
309                 el[ scroll ] = 0;
310                 return has;
311         }
314 })( jQuery );
316 (function( $, undefined ) {
318 var uuid = 0,
319         slice = Array.prototype.slice,
320         _cleanData = $.cleanData;
321 $.cleanData = function( elems ) {
322         for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
323                 try {
324                         $( elem ).triggerHandler( "remove" );
325                 // http://bugs.jquery.com/ticket/8235
326                 } catch( e ) {}
327         }
328         _cleanData( elems );
331 $.widget = function( name, base, prototype ) {
332         var fullName, existingConstructor, constructor, basePrototype,
333                 // proxiedPrototype allows the provided prototype to remain unmodified
334                 // so that it can be used as a mixin for multiple widgets (#8876)
335                 proxiedPrototype = {},
336                 namespace = name.split( "." )[ 0 ];
338         name = name.split( "." )[ 1 ];
339         fullName = namespace + "-" + name;
341         if ( !prototype ) {
342                 prototype = base;
343                 base = $.Widget;
344         }
346         // create selector for plugin
347         $.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) {
348                 return !!$.data( elem, fullName );
349         };
351         $[ namespace ] = $[ namespace ] || {};
352         existingConstructor = $[ namespace ][ name ];
353         constructor = $[ namespace ][ name ] = function( options, element ) {
354                 // allow instantiation without "new" keyword
355                 if ( !this._createWidget ) {
356                         return new constructor( options, element );
357                 }
359                 // allow instantiation without initializing for simple inheritance
360                 // must use "new" keyword (the code above always passes args)
361                 if ( arguments.length ) {
362                         this._createWidget( options, element );
363                 }
364         };
365         // extend with the existing constructor to carry over any static properties
366         $.extend( constructor, existingConstructor, {
367                 version: prototype.version,
368                 // copy the object used to create the prototype in case we need to
369                 // redefine the widget later
370                 _proto: $.extend( {}, prototype ),
371                 // track widgets that inherit from this widget in case this widget is
372                 // redefined after a widget inherits from it
373                 _childConstructors: []
374         });
376         basePrototype = new base();
377         // we need to make the options hash a property directly on the new instance
378         // otherwise we'll modify the options hash on the prototype that we're
379         // inheriting from
380         basePrototype.options = $.widget.extend( {}, basePrototype.options );
381         $.each( prototype, function( prop, value ) {
382                 if ( !$.isFunction( value ) ) {
383                         proxiedPrototype[ prop ] = value;
384                         return;
385                 }
386                 proxiedPrototype[ prop ] = (function() {
387                         var _super = function() {
388                                         return base.prototype[ prop ].apply( this, arguments );
389                                 },
390                                 _superApply = function( args ) {
391                                         return base.prototype[ prop ].apply( this, args );
392                                 };
393                         return function() {
394                                 var __super = this._super,
395                                         __superApply = this._superApply,
396                                         returnValue;
398                                 this._super = _super;
399                                 this._superApply = _superApply;
401                                 returnValue = value.apply( this, arguments );
403                                 this._super = __super;
404                                 this._superApply = __superApply;
406                                 return returnValue;
407                         };
408                 })();
409         });
410         constructor.prototype = $.widget.extend( basePrototype, {
411                 // TODO: remove support for widgetEventPrefix
412                 // always use the name + a colon as the prefix, e.g., draggable:start
413                 // don't prefix for widgets that aren't DOM-based
414                 widgetEventPrefix: existingConstructor ? basePrototype.widgetEventPrefix : name
415         }, proxiedPrototype, {
416                 constructor: constructor,
417                 namespace: namespace,
418                 widgetName: name,
419                 widgetFullName: fullName
420         });
422         // If this widget is being redefined then we need to find all widgets that
423         // are inheriting from it and redefine all of them so that they inherit from
424         // the new version of this widget. We're essentially trying to replace one
425         // level in the prototype chain.
426         if ( existingConstructor ) {
427                 $.each( existingConstructor._childConstructors, function( i, child ) {
428                         var childPrototype = child.prototype;
430                         // redefine the child widget using the same prototype that was
431                         // originally used, but inherit from the new version of the base
432                         $.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, child._proto );
433                 });
434                 // remove the list of existing child constructors from the old constructor
435                 // so the old child constructors can be garbage collected
436                 delete existingConstructor._childConstructors;
437         } else {
438                 base._childConstructors.push( constructor );
439         }
441         $.widget.bridge( name, constructor );
444 $.widget.extend = function( target ) {
445         var input = slice.call( arguments, 1 ),
446                 inputIndex = 0,
447                 inputLength = input.length,
448                 key,
449                 value;
450         for ( ; inputIndex < inputLength; inputIndex++ ) {
451                 for ( key in input[ inputIndex ] ) {
452                         value = input[ inputIndex ][ key ];
453                         if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) {
454                                 // Clone objects
455                                 if ( $.isPlainObject( value ) ) {
456                                         target[ key ] = $.isPlainObject( target[ key ] ) ?
457                                                 $.widget.extend( {}, target[ key ], value ) :
458                                                 // Don't extend strings, arrays, etc. with objects
459                                                 $.widget.extend( {}, value );
460                                 // Copy everything else by reference
461                                 } else {
462                                         target[ key ] = value;
463                                 }
464                         }
465                 }
466         }
467         return target;
470 $.widget.bridge = function( name, object ) {
471         var fullName = object.prototype.widgetFullName || name;
472         $.fn[ name ] = function( options ) {
473                 var isMethodCall = typeof options === "string",
474                         args = slice.call( arguments, 1 ),
475                         returnValue = this;
477                 // allow multiple hashes to be passed on init
478                 options = !isMethodCall && args.length ?
479                         $.widget.extend.apply( null, [ options ].concat(args) ) :
480                         options;
482                 if ( isMethodCall ) {
483                         this.each(function() {
484                                 var methodValue,
485                                         instance = $.data( this, fullName );
486                                 if ( !instance ) {
487                                         return $.error( "cannot call methods on " + name + " prior to initialization; " +
488                                                 "attempted to call method '" + options + "'" );
489                                 }
490                                 if ( !$.isFunction( instance[options] ) || options.charAt( 0 ) === "_" ) {
491                                         return $.error( "no such method '" + options + "' for " + name + " widget instance" );
492                                 }
493                                 methodValue = instance[ options ].apply( instance, args );
494                                 if ( methodValue !== instance && methodValue !== undefined ) {
495                                         returnValue = methodValue && methodValue.jquery ?
496                                                 returnValue.pushStack( methodValue.get() ) :
497                                                 methodValue;
498                                         return false;
499                                 }
500                         });
501                 } else {
502                         this.each(function() {
503                                 var instance = $.data( this, fullName );
504                                 if ( instance ) {
505                                         instance.option( options || {} )._init();
506                                 } else {
507                                         $.data( this, fullName, new object( options, this ) );
508                                 }
509                         });
510                 }
512                 return returnValue;
513         };
516 $.Widget = function( /* options, element */ ) {};
517 $.Widget._childConstructors = [];
519 $.Widget.prototype = {
520         widgetName: "widget",
521         widgetEventPrefix: "",
522         defaultElement: "<div>",
523         options: {
524                 disabled: false,
526                 // callbacks
527                 create: null
528         },
529         _createWidget: function( options, element ) {
530                 element = $( element || this.defaultElement || this )[ 0 ];
531                 this.element = $( element );
532                 this.uuid = uuid++;
533                 this.eventNamespace = "." + this.widgetName + this.uuid;
534                 this.options = $.widget.extend( {},
535                         this.options,
536                         this._getCreateOptions(),
537                         options );
539                 this.bindings = $();
540                 this.hoverable = $();
541                 this.focusable = $();
543                 if ( element !== this ) {
544                         $.data( element, this.widgetFullName, this );
545                         this._on( true, this.element, {
546                                 remove: function( event ) {
547                                         if ( event.target === element ) {
548                                                 this.destroy();
549                                         }
550                                 }
551                         });
552                         this.document = $( element.style ?
553                                 // element within the document
554                                 element.ownerDocument :
555                                 // element is window or document
556                                 element.document || element );
557                         this.window = $( this.document[0].defaultView || this.document[0].parentWindow );
558                 }
560                 this._create();
561                 this._trigger( "create", null, this._getCreateEventData() );
562                 this._init();
563         },
564         _getCreateOptions: $.noop,
565         _getCreateEventData: $.noop,
566         _create: $.noop,
567         _init: $.noop,
569         destroy: function() {
570                 this._destroy();
571                 // we can probably remove the unbind calls in 2.0
572                 // all event bindings should go through this._on()
573                 this.element
574                         .unbind( this.eventNamespace )
575                         // 1.9 BC for #7810
576                         // TODO remove dual storage
577                         .removeData( this.widgetName )
578                         .removeData( this.widgetFullName )
579                         // support: jquery <1.6.3
580                         // http://bugs.jquery.com/ticket/9413
581                         .removeData( $.camelCase( this.widgetFullName ) );
582                 this.widget()
583                         .unbind( this.eventNamespace )
584                         .removeAttr( "aria-disabled" )
585                         .removeClass(
586                                 this.widgetFullName + "-disabled " +
587                                 "ui-state-disabled" );
589                 // clean up events and states
590                 this.bindings.unbind( this.eventNamespace );
591                 this.hoverable.removeClass( "ui-state-hover" );
592                 this.focusable.removeClass( "ui-state-focus" );
593         },
594         _destroy: $.noop,
596         widget: function() {
597                 return this.element;
598         },
600         option: function( key, value ) {
601                 var options = key,
602                         parts,
603                         curOption,
604                         i;
606                 if ( arguments.length === 0 ) {
607                         // don't return a reference to the internal hash
608                         return $.widget.extend( {}, this.options );
609                 }
611                 if ( typeof key === "string" ) {
612                         // handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
613                         options = {};
614                         parts = key.split( "." );
615                         key = parts.shift();
616                         if ( parts.length ) {
617                                 curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );
618                                 for ( i = 0; i < parts.length - 1; i++ ) {
619                                         curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};
620                                         curOption = curOption[ parts[ i ] ];
621                                 }
622                                 key = parts.pop();
623                                 if ( value === undefined ) {
624                                         return curOption[ key ] === undefined ? null : curOption[ key ];
625                                 }
626                                 curOption[ key ] = value;
627                         } else {
628                                 if ( value === undefined ) {
629                                         return this.options[ key ] === undefined ? null : this.options[ key ];
630                                 }
631                                 options[ key ] = value;
632                         }
633                 }
635                 this._setOptions( options );
637                 return this;
638         },
639         _setOptions: function( options ) {
640                 var key;
642                 for ( key in options ) {
643                         this._setOption( key, options[ key ] );
644                 }
646                 return this;
647         },
648         _setOption: function( key, value ) {
649                 this.options[ key ] = value;
651                 if ( key === "disabled" ) {
652                         this.widget()
653                                 .toggleClass( this.widgetFullName + "-disabled ui-state-disabled", !!value )
654                                 .attr( "aria-disabled", value );
655                         this.hoverable.removeClass( "ui-state-hover" );
656                         this.focusable.removeClass( "ui-state-focus" );
657                 }
659                 return this;
660         },
662         enable: function() {
663                 return this._setOption( "disabled", false );
664         },
665         disable: function() {
666                 return this._setOption( "disabled", true );
667         },
669         _on: function( suppressDisabledCheck, element, handlers ) {
670                 var delegateElement,
671                         instance = this;
673                 // no suppressDisabledCheck flag, shuffle arguments
674                 if ( typeof suppressDisabledCheck !== "boolean" ) {
675                         handlers = element;
676                         element = suppressDisabledCheck;
677                         suppressDisabledCheck = false;
678                 }
680                 // no element argument, shuffle and use this.element
681                 if ( !handlers ) {
682                         handlers = element;
683                         element = this.element;
684                         delegateElement = this.widget();
685                 } else {
686                         // accept selectors, DOM elements
687                         element = delegateElement = $( element );
688                         this.bindings = this.bindings.add( element );
689                 }
691                 $.each( handlers, function( event, handler ) {
692                         function handlerProxy() {
693                                 // allow widgets to customize the disabled handling
694                                 // - disabled as an array instead of boolean
695                                 // - disabled class as method for disabling individual parts
696                                 if ( !suppressDisabledCheck &&
697                                                 ( instance.options.disabled === true ||
698                                                         $( this ).hasClass( "ui-state-disabled" ) ) ) {
699                                         return;
700                                 }
701                                 return ( typeof handler === "string" ? instance[ handler ] : handler )
702                                         .apply( instance, arguments );
703                         }
705                         // copy the guid so direct unbinding works
706                         if ( typeof handler !== "string" ) {
707                                 handlerProxy.guid = handler.guid =
708                                         handler.guid || handlerProxy.guid || $.guid++;
709                         }
711                         var match = event.match( /^(\w+)\s*(.*)$/ ),
712                                 eventName = match[1] + instance.eventNamespace,
713                                 selector = match[2];
714                         if ( selector ) {
715                                 delegateElement.delegate( selector, eventName, handlerProxy );
716                         } else {
717                                 element.bind( eventName, handlerProxy );
718                         }
719                 });
720         },
722         _off: function( element, eventName ) {
723                 eventName = (eventName || "").split( " " ).join( this.eventNamespace + " " ) + this.eventNamespace;
724                 element.unbind( eventName ).undelegate( eventName );
725         },
727         _delay: function( handler, delay ) {
728                 function handlerProxy() {
729                         return ( typeof handler === "string" ? instance[ handler ] : handler )
730                                 .apply( instance, arguments );
731                 }
732                 var instance = this;
733                 return setTimeout( handlerProxy, delay || 0 );
734         },
736         _hoverable: function( element ) {
737                 this.hoverable = this.hoverable.add( element );
738                 this._on( element, {
739                         mouseenter: function( event ) {
740                                 $( event.currentTarget ).addClass( "ui-state-hover" );
741                         },
742                         mouseleave: function( event ) {
743                                 $( event.currentTarget ).removeClass( "ui-state-hover" );
744                         }
745                 });
746         },
748         _focusable: function( element ) {
749                 this.focusable = this.focusable.add( element );
750                 this._on( element, {
751                         focusin: function( event ) {
752                                 $( event.currentTarget ).addClass( "ui-state-focus" );
753                         },
754                         focusout: function( event ) {
755                                 $( event.currentTarget ).removeClass( "ui-state-focus" );
756                         }
757                 });
758         },
760         _trigger: function( type, event, data ) {
761                 var prop, orig,
762                         callback = this.options[ type ];
764                 data = data || {};
765                 event = $.Event( event );
766                 event.type = ( type === this.widgetEventPrefix ?
767                         type :
768                         this.widgetEventPrefix + type ).toLowerCase();
769                 // the original event may come from any element
770                 // so we need to reset the target on the new event
771                 event.target = this.element[ 0 ];
773                 // copy original event properties over to the new event
774                 orig = event.originalEvent;
775                 if ( orig ) {
776                         for ( prop in orig ) {
777                                 if ( !( prop in event ) ) {
778                                         event[ prop ] = orig[ prop ];
779                                 }
780                         }
781                 }
783                 this.element.trigger( event, data );
784                 return !( $.isFunction( callback ) &&
785                         callback.apply( this.element[0], [ event ].concat( data ) ) === false ||
786                         event.isDefaultPrevented() );
787         }
790 $.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {
791         $.Widget.prototype[ "_" + method ] = function( element, options, callback ) {
792                 if ( typeof options === "string" ) {
793                         options = { effect: options };
794                 }
795                 var hasOptions,
796                         effectName = !options ?
797                                 method :
798                                 options === true || typeof options === "number" ?
799                                         defaultEffect :
800                                         options.effect || defaultEffect;
801                 options = options || {};
802                 if ( typeof options === "number" ) {
803                         options = { duration: options };
804                 }
805                 hasOptions = !$.isEmptyObject( options );
806                 options.complete = callback;
807                 if ( options.delay ) {
808                         element.delay( options.delay );
809                 }
810                 if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) {
811                         element[ method ]( options );
812                 } else if ( effectName !== method && element[ effectName ] ) {
813                         element[ effectName ]( options.duration, options.easing, callback );
814                 } else {
815                         element.queue(function( next ) {
816                                 $( this )[ method ]();
817                                 if ( callback ) {
818                                         callback.call( element[ 0 ] );
819                                 }
820                                 next();
821                         });
822                 }
823         };
826 })( jQuery );
828 (function( $, undefined ) {
830 var mouseHandled = false;
831 $( document ).mouseup( function() {
832         mouseHandled = false;
835 $.widget("ui.mouse", {
836         version: "1.10.3",
837         options: {
838                 cancel: "input,textarea,button,select,option",
839                 distance: 1,
840                 delay: 0
841         },
842         _mouseInit: function() {
843                 var that = this;
845                 this.element
846                         .bind("mousedown."+this.widgetName, function(event) {
847                                 return that._mouseDown(event);
848                         })
849                         .bind("click."+this.widgetName, function(event) {
850                                 if (true === $.data(event.target, that.widgetName + ".preventClickEvent")) {
851                                         $.removeData(event.target, that.widgetName + ".preventClickEvent");
852                                         event.stopImmediatePropagation();
853                                         return false;
854                                 }
855                         });
857                 this.started = false;
858         },
860         // TODO: make sure destroying one instance of mouse doesn't mess with
861         // other instances of mouse
862         _mouseDestroy: function() {
863                 this.element.unbind("."+this.widgetName);
864                 if ( this._mouseMoveDelegate ) {
865                         $(document)
866                                 .unbind("mousemove."+this.widgetName, this._mouseMoveDelegate)
867                                 .unbind("mouseup."+this.widgetName, this._mouseUpDelegate);
868                 }
869         },
871         _mouseDown: function(event) {
872                 // don't let more than one widget handle mouseStart
873                 if( mouseHandled ) { return; }
875                 // we may have missed mouseup (out of window)
876                 (this._mouseStarted && this._mouseUp(event));
878                 this._mouseDownEvent = event;
880                 var that = this,
881                         btnIsLeft = (event.which === 1),
882                         // event.target.nodeName works around a bug in IE 8 with
883                         // disabled inputs (#7620)
884                         elIsCancel = (typeof this.options.cancel === "string" && event.target.nodeName ? $(event.target).closest(this.options.cancel).length : false);
885                 if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
886                         return true;
887                 }
889                 this.mouseDelayMet = !this.options.delay;
890                 if (!this.mouseDelayMet) {
891                         this._mouseDelayTimer = setTimeout(function() {
892                                 that.mouseDelayMet = true;
893                         }, this.options.delay);
894                 }
896                 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
897                         this._mouseStarted = (this._mouseStart(event) !== false);
898                         if (!this._mouseStarted) {
899                                 event.preventDefault();
900                                 return true;
901                         }
902                 }
904                 // Click event may never have fired (Gecko & Opera)
905                 if (true === $.data(event.target, this.widgetName + ".preventClickEvent")) {
906                         $.removeData(event.target, this.widgetName + ".preventClickEvent");
907                 }
909                 // these delegates are required to keep context
910                 this._mouseMoveDelegate = function(event) {
911                         return that._mouseMove(event);
912                 };
913                 this._mouseUpDelegate = function(event) {
914                         return that._mouseUp(event);
915                 };
916                 $(document)
917                         .bind("mousemove."+this.widgetName, this._mouseMoveDelegate)
918                         .bind("mouseup."+this.widgetName, this._mouseUpDelegate);
920                 event.preventDefault();
922                 mouseHandled = true;
923                 return true;
924         },
926         _mouseMove: function(event) {
927                 // IE mouseup check - mouseup happened when mouse was out of window
928                 if ($.ui.ie && ( !document.documentMode || document.documentMode < 9 ) && !event.button) {
929                         return this._mouseUp(event);
930                 }
932                 if (this._mouseStarted) {
933                         this._mouseDrag(event);
934                         return event.preventDefault();
935                 }
937                 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
938                         this._mouseStarted =
939                                 (this._mouseStart(this._mouseDownEvent, event) !== false);
940                         (this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
941                 }
943                 return !this._mouseStarted;
944         },
946         _mouseUp: function(event) {
947                 $(document)
948                         .unbind("mousemove."+this.widgetName, this._mouseMoveDelegate)
949                         .unbind("mouseup."+this.widgetName, this._mouseUpDelegate);
951                 if (this._mouseStarted) {
952                         this._mouseStarted = false;
954                         if (event.target === this._mouseDownEvent.target) {
955                                 $.data(event.target, this.widgetName + ".preventClickEvent", true);
956                         }
958                         this._mouseStop(event);
959                 }
961                 return false;
962         },
964         _mouseDistanceMet: function(event) {
965                 return (Math.max(
966                                 Math.abs(this._mouseDownEvent.pageX - event.pageX),
967                                 Math.abs(this._mouseDownEvent.pageY - event.pageY)
968                         ) >= this.options.distance
969                 );
970         },
972         _mouseDelayMet: function(/* event */) {
973                 return this.mouseDelayMet;
974         },
976         // These are placeholder methods, to be overriden by extending plugin
977         _mouseStart: function(/* event */) {},
978         _mouseDrag: function(/* event */) {},
979         _mouseStop: function(/* event */) {},
980         _mouseCapture: function(/* event */) { return true; }
983 })(jQuery);
985 (function( $, undefined ) {
987 $.widget("ui.draggable", $.ui.mouse, {
988         version: "1.10.3",
989         widgetEventPrefix: "drag",
990         options: {
991                 addClasses: true,
992                 appendTo: "parent",
993                 axis: false,
994                 connectToSortable: false,
995                 containment: false,
996                 cursor: "auto",
997                 cursorAt: false,
998                 grid: false,
999                 handle: false,
1000                 helper: "original",
1001                 iframeFix: false,
1002                 opacity: false,
1003                 refreshPositions: false,
1004                 revert: false,
1005                 revertDuration: 500,
1006                 scope: "default",
1007                 scroll: true,
1008                 scrollSensitivity: 20,
1009                 scrollSpeed: 20,
1010                 snap: false,
1011                 snapMode: "both",
1012                 snapTolerance: 20,
1013                 stack: false,
1014                 zIndex: false,
1016                 // callbacks
1017                 drag: null,
1018                 start: null,
1019                 stop: null
1020         },
1021         _create: function() {
1023                 if (this.options.helper === "original" && !(/^(?:r|a|f)/).test(this.element.css("position"))) {
1024                         this.element[0].style.position = "relative";
1025                 }
1026                 if (this.options.addClasses){
1027                         this.element.addClass("ui-draggable");
1028                 }
1029                 if (this.options.disabled){
1030                         this.element.addClass("ui-draggable-disabled");
1031                 }
1033                 this._mouseInit();
1035         },
1037         _destroy: function() {
1038                 this.element.removeClass( "ui-draggable ui-draggable-dragging ui-draggable-disabled" );
1039                 this._mouseDestroy();
1040         },
1042         _mouseCapture: function(event) {
1044                 var o = this.options;
1046                 // among others, prevent a drag on a resizable-handle
1047                 if (this.helper || o.disabled || $(event.target).closest(".ui-resizable-handle").length > 0) {
1048                         return false;
1049                 }
1051                 //Quit if we're not on a valid handle
1052                 this.handle = this._getHandle(event);
1053                 if (!this.handle) {
1054                         return false;
1055                 }
1057                 $(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() {
1058                         $("<div class='ui-draggable-iframeFix' style='background: #fff;'></div>")
1059                         .css({
1060                                 width: this.offsetWidth+"px", height: this.offsetHeight+"px",
1061                                 position: "absolute", opacity: "0.001", zIndex: 1000
1062                         })
1063                         .css($(this).offset())
1064                         .appendTo("body");
1065                 });
1067                 return true;
1069         },
1071         _mouseStart: function(event) {
1073                 var o = this.options;
1075                 //Create and append the visible helper
1076                 this.helper = this._createHelper(event);
1078                 this.helper.addClass("ui-draggable-dragging");
1080                 //Cache the helper size
1081                 this._cacheHelperProportions();
1083                 //If ddmanager is used for droppables, set the global draggable
1084                 if($.ui.ddmanager) {
1085                         $.ui.ddmanager.current = this;
1086                 }
1088                 /*
1089                  * - Position generation -
1090                  * This block generates everything position related - it's the core of draggables.
1091                  */
1093                 //Cache the margins of the original element
1094                 this._cacheMargins();
1096                 //Store the helper's css position
1097                 this.cssPosition = this.helper.css( "position" );
1098                 this.scrollParent = this.helper.scrollParent();
1099                 this.offsetParent = this.helper.offsetParent();
1100                 this.offsetParentCssPosition = this.offsetParent.css( "position" );
1102                 //The element's absolute position on the page minus margins
1103                 this.offset = this.positionAbs = this.element.offset();
1104                 this.offset = {
1105                         top: this.offset.top - this.margins.top,
1106                         left: this.offset.left - this.margins.left
1107                 };
1109                 //Reset scroll cache
1110                 this.offset.scroll = false;
1112                 $.extend(this.offset, {
1113                         click: { //Where the click happened, relative to the element
1114                                 left: event.pageX - this.offset.left,
1115                                 top: event.pageY - this.offset.top
1116                         },
1117                         parent: this._getParentOffset(),
1118                         relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
1119                 });
1121                 //Generate the original position
1122                 this.originalPosition = this.position = this._generatePosition(event);
1123                 this.originalPageX = event.pageX;
1124                 this.originalPageY = event.pageY;
1126                 //Adjust the mouse offset relative to the helper if "cursorAt" is supplied
1127                 (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
1129                 //Set a containment if given in the options
1130                 this._setContainment();
1132                 //Trigger event + callbacks
1133                 if(this._trigger("start", event) === false) {
1134                         this._clear();
1135                         return false;
1136                 }
1138                 //Recache the helper size
1139                 this._cacheHelperProportions();
1141                 //Prepare the droppable offsets
1142                 if ($.ui.ddmanager && !o.dropBehaviour) {
1143                         $.ui.ddmanager.prepareOffsets(this, event);
1144                 }
1147                 this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position
1149                 //If the ddmanager is used for droppables, inform the manager that dragging has started (see #5003)
1150                 if ( $.ui.ddmanager ) {
1151                         $.ui.ddmanager.dragStart(this, event);
1152                 }
1154                 return true;
1155         },
1157         _mouseDrag: function(event, noPropagation) {
1158                 // reset any necessary cached properties (see #5009)
1159                 if ( this.offsetParentCssPosition === "fixed" ) {
1160                         this.offset.parent = this._getParentOffset();
1161                 }
1163                 //Compute the helpers position
1164                 this.position = this._generatePosition(event);
1165                 this.positionAbs = this._convertPositionTo("absolute");
1167                 //Call plugins and callbacks and use the resulting position if something is returned
1168                 if (!noPropagation) {
1169                         var ui = this._uiHash();
1170                         if(this._trigger("drag", event, ui) === false) {
1171                                 this._mouseUp({});
1172                                 return false;
1173                         }
1174                         this.position = ui.position;
1175                 }
1177                 if(!this.options.axis || this.options.axis !== "y") {
1178                         this.helper[0].style.left = this.position.left+"px";
1179                 }
1180                 if(!this.options.axis || this.options.axis !== "x") {
1181                         this.helper[0].style.top = this.position.top+"px";
1182                 }
1183                 if($.ui.ddmanager) {
1184                         $.ui.ddmanager.drag(this, event);
1185                 }
1187                 return false;
1188         },
1190         _mouseStop: function(event) {
1192                 //If we are using droppables, inform the manager about the drop
1193                 var that = this,
1194                         dropped = false;
1195                 if ($.ui.ddmanager && !this.options.dropBehaviour) {
1196                         dropped = $.ui.ddmanager.drop(this, event);
1197                 }
1199                 //if a drop comes from outside (a sortable)
1200                 if(this.dropped) {
1201                         dropped = this.dropped;
1202                         this.dropped = false;
1203                 }
1205                 //if the original element is no longer in the DOM don't bother to continue (see #8269)
1206                 if ( this.options.helper === "original" && !$.contains( this.element[ 0 ].ownerDocument, this.element[ 0 ] ) ) {
1207                         return false;
1208                 }
1210                 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))) {
1211                         $(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() {
1212                                 if(that._trigger("stop", event) !== false) {
1213                                         that._clear();
1214                                 }
1215                         });
1216                 } else {
1217                         if(this._trigger("stop", event) !== false) {
1218                                 this._clear();
1219                         }
1220                 }
1222                 return false;
1223         },
1225         _mouseUp: function(event) {
1226                 //Remove frame helpers
1227                 $("div.ui-draggable-iframeFix").each(function() {
1228                         this.parentNode.removeChild(this);
1229                 });
1231                 //If the ddmanager is used for droppables, inform the manager that dragging has stopped (see #5003)
1232                 if( $.ui.ddmanager ) {
1233                         $.ui.ddmanager.dragStop(this, event);
1234                 }
1236                 return $.ui.mouse.prototype._mouseUp.call(this, event);
1237         },
1239         cancel: function() {
1241                 if(this.helper.is(".ui-draggable-dragging")) {
1242                         this._mouseUp({});
1243                 } else {
1244                         this._clear();
1245                 }
1247                 return this;
1249         },
1251         _getHandle: function(event) {
1252                 return this.options.handle ?
1253                         !!$( event.target ).closest( this.element.find( this.options.handle ) ).length :
1254                         true;
1255         },
1257         _createHelper: function(event) {
1259                 var o = this.options,
1260                         helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper === "clone" ? this.element.clone().removeAttr("id") : this.element);
1262                 if(!helper.parents("body").length) {
1263                         helper.appendTo((o.appendTo === "parent" ? this.element[0].parentNode : o.appendTo));
1264                 }
1266                 if(helper[0] !== this.element[0] && !(/(fixed|absolute)/).test(helper.css("position"))) {
1267                         helper.css("position", "absolute");
1268                 }
1270                 return helper;
1272         },
1274         _adjustOffsetFromHelper: function(obj) {
1275                 if (typeof obj === "string") {
1276                         obj = obj.split(" ");
1277                 }
1278                 if ($.isArray(obj)) {
1279                         obj = {left: +obj[0], top: +obj[1] || 0};
1280                 }
1281                 if ("left" in obj) {
1282                         this.offset.click.left = obj.left + this.margins.left;
1283                 }
1284                 if ("right" in obj) {
1285                         this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
1286                 }
1287                 if ("top" in obj) {
1288                         this.offset.click.top = obj.top + this.margins.top;
1289                 }
1290                 if ("bottom" in obj) {
1291                         this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
1292                 }
1293         },
1295         _getParentOffset: function() {
1297                 //Get the offsetParent and cache its position
1298                 var po = this.offsetParent.offset();
1300                 // This is a special case where we need to modify a offset calculated on start, since the following happened:
1301                 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
1302                 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
1303                 //    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
1304                 if(this.cssPosition === "absolute" && this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) {
1305                         po.left += this.scrollParent.scrollLeft();
1306                         po.top += this.scrollParent.scrollTop();
1307                 }
1309                 //This needs to be actually done for all browsers, since pageX/pageY includes this information
1310                 //Ugly IE fix
1311                 if((this.offsetParent[0] === document.body) ||
1312                         (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() === "html" && $.ui.ie)) {
1313                         po = { top: 0, left: 0 };
1314                 }
1316                 return {
1317                         top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
1318                         left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
1319                 };
1321         },
1323         _getRelativeOffset: function() {
1325                 if(this.cssPosition === "relative") {
1326                         var p = this.element.position();
1327                         return {
1328                                 top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
1329                                 left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
1330                         };
1331                 } else {
1332                         return { top: 0, left: 0 };
1333                 }
1335         },
1337         _cacheMargins: function() {
1338                 this.margins = {
1339                         left: (parseInt(this.element.css("marginLeft"),10) || 0),
1340                         top: (parseInt(this.element.css("marginTop"),10) || 0),
1341                         right: (parseInt(this.element.css("marginRight"),10) || 0),
1342                         bottom: (parseInt(this.element.css("marginBottom"),10) || 0)
1343                 };
1344         },
1346         _cacheHelperProportions: function() {
1347                 this.helperProportions = {
1348                         width: this.helper.outerWidth(),
1349                         height: this.helper.outerHeight()
1350                 };
1351         },
1353         _setContainment: function() {
1355                 var over, c, ce,
1356                         o = this.options;
1358                 if ( !o.containment ) {
1359                         this.containment = null;
1360                         return;
1361                 }
1363                 if ( o.containment === "window" ) {
1364                         this.containment = [
1365                                 $( window ).scrollLeft() - this.offset.relative.left - this.offset.parent.left,
1366                                 $( window ).scrollTop() - this.offset.relative.top - this.offset.parent.top,
1367                                 $( window ).scrollLeft() + $( window ).width() - this.helperProportions.width - this.margins.left,
1368                                 $( window ).scrollTop() + ( $( window ).height() || document.body.parentNode.scrollHeight ) - this.helperProportions.height - this.margins.top
1369                         ];
1370                         return;
1371                 }
1373                 if ( o.containment === "document") {
1374                         this.containment = [
1375                                 0,
1376                                 0,
1377                                 $( document ).width() - this.helperProportions.width - this.margins.left,
1378                                 ( $( document ).height() || document.body.parentNode.scrollHeight ) - this.helperProportions.height - this.margins.top
1379                         ];
1380                         return;
1381                 }
1383                 if ( o.containment.constructor === Array ) {
1384                         this.containment = o.containment;
1385                         return;
1386                 }
1388                 if ( o.containment === "parent" ) {
1389                         o.containment = this.helper[ 0 ].parentNode;
1390                 }
1392                 c = $( o.containment );
1393                 ce = c[ 0 ];
1395                 if( !ce ) {
1396                         return;
1397                 }
1399                 over = c.css( "overflow" ) !== "hidden";
1401                 this.containment = [
1402                         ( parseInt( c.css( "borderLeftWidth" ), 10 ) || 0 ) + ( parseInt( c.css( "paddingLeft" ), 10 ) || 0 ),
1403                         ( parseInt( c.css( "borderTopWidth" ), 10 ) || 0 ) + ( parseInt( c.css( "paddingTop" ), 10 ) || 0 ) ,
1404                         ( over ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) - ( parseInt( c.css( "borderRightWidth" ), 10 ) || 0 ) - ( parseInt( c.css( "paddingRight" ), 10 ) || 0 ) - this.helperProportions.width - this.margins.left - this.margins.right,
1405                         ( over ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) - ( parseInt( c.css( "borderBottomWidth" ), 10 ) || 0 ) - ( parseInt( c.css( "paddingBottom" ), 10 ) || 0 ) - this.helperProportions.height - this.margins.top  - this.margins.bottom
1406                 ];
1407                 this.relative_container = c;
1408         },
1410         _convertPositionTo: function(d, pos) {
1412                 if(!pos) {
1413                         pos = this.position;
1414                 }
1416                 var mod = d === "absolute" ? 1 : -1,
1417                         scroll = this.cssPosition === "absolute" && !( this.scrollParent[ 0 ] !== document && $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ? this.offsetParent : this.scrollParent;
1419                 //Cache the scroll
1420                 if (!this.offset.scroll) {
1421                         this.offset.scroll = {top : scroll.scrollTop(), left : scroll.scrollLeft()};
1422                 }
1424                 return {
1425                         top: (
1426                                 pos.top +                                                                                                                               // The absolute mouse position
1427                                 this.offset.relative.top * mod +                                                                                // Only for relative positioned nodes: Relative offset from element to offset parent
1428                                 this.offset.parent.top * mod -                                                                          // The offsetParent's offset without borders (offset + border)
1429                                 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : this.offset.scroll.top ) * mod )
1430                         ),
1431                         left: (
1432                                 pos.left +                                                                                                                              // The absolute mouse position
1433                                 this.offset.relative.left * mod +                                                                               // Only for relative positioned nodes: Relative offset from element to offset parent
1434                                 this.offset.parent.left * mod   -                                                                               // The offsetParent's offset without borders (offset + border)
1435                                 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : this.offset.scroll.left ) * mod )
1436                         )
1437                 };
1439         },
1441         _generatePosition: function(event) {
1443                 var containment, co, top, left,
1444                         o = this.options,
1445                         scroll = this.cssPosition === "absolute" && !( this.scrollParent[ 0 ] !== document && $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ? this.offsetParent : this.scrollParent,
1446                         pageX = event.pageX,
1447                         pageY = event.pageY;
1449                 //Cache the scroll
1450                 if (!this.offset.scroll) {
1451                         this.offset.scroll = {top : scroll.scrollTop(), left : scroll.scrollLeft()};
1452                 }
1454                 /*
1455                  * - Position constraining -
1456                  * Constrain the position to a mix of grid, containment.
1457                  */
1459                 // If we are not dragging yet, we won't check for options
1460                 if ( this.originalPosition ) {
1461                         if ( this.containment ) {
1462                                 if ( this.relative_container ){
1463                                         co = this.relative_container.offset();
1464                                         containment = [
1465                                                 this.containment[ 0 ] + co.left,
1466                                                 this.containment[ 1 ] + co.top,
1467                                                 this.containment[ 2 ] + co.left,
1468                                                 this.containment[ 3 ] + co.top
1469                                         ];
1470                                 }
1471                                 else {
1472                                         containment = this.containment;
1473                                 }
1475                                 if(event.pageX - this.offset.click.left < containment[0]) {
1476                                         pageX = containment[0] + this.offset.click.left;
1477                                 }
1478                                 if(event.pageY - this.offset.click.top < containment[1]) {
1479                                         pageY = containment[1] + this.offset.click.top;
1480                                 }
1481                                 if(event.pageX - this.offset.click.left > containment[2]) {
1482                                         pageX = containment[2] + this.offset.click.left;
1483                                 }
1484                                 if(event.pageY - this.offset.click.top > containment[3]) {
1485                                         pageY = containment[3] + this.offset.click.top;
1486                                 }
1487                         }
1489                         if(o.grid) {
1490                                 //Check for grid elements set to 0 to prevent divide by 0 error causing invalid argument errors in IE (see ticket #6950)
1491                                 top = o.grid[1] ? this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1] : this.originalPageY;
1492                                 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;
1494                                 left = o.grid[0] ? this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0] : this.originalPageX;
1495                                 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;
1496                         }
1498                 }
1500                 return {
1501                         top: (
1502                                 pageY -                                                                                                                                 // The absolute mouse position
1503                                 this.offset.click.top   -                                                                                               // Click offset (relative to the element)
1504                                 this.offset.relative.top -                                                                                              // Only for relative positioned nodes: Relative offset from element to offset parent
1505                                 this.offset.parent.top +                                                                                                // The offsetParent's offset without borders (offset + border)
1506                                 ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : this.offset.scroll.top )
1507                         ),
1508                         left: (
1509                                 pageX -                                                                                                                                 // The absolute mouse position
1510                                 this.offset.click.left -                                                                                                // Click offset (relative to the element)
1511                                 this.offset.relative.left -                                                                                             // Only for relative positioned nodes: Relative offset from element to offset parent
1512                                 this.offset.parent.left +                                                                                               // The offsetParent's offset without borders (offset + border)
1513                                 ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : this.offset.scroll.left )
1514                         )
1515                 };
1517         },
1519         _clear: function() {
1520                 this.helper.removeClass("ui-draggable-dragging");
1521                 if(this.helper[0] !== this.element[0] && !this.cancelHelperRemoval) {
1522                         this.helper.remove();
1523                 }
1524                 this.helper = null;
1525                 this.cancelHelperRemoval = false;
1526         },
1528         // From now on bulk stuff - mainly helpers
1530         _trigger: function(type, event, ui) {
1531                 ui = ui || this._uiHash();
1532                 $.ui.plugin.call(this, type, [event, ui]);
1533                 //The absolute position has to be recalculated after plugins
1534                 if(type === "drag") {
1535                         this.positionAbs = this._convertPositionTo("absolute");
1536                 }
1537                 return $.Widget.prototype._trigger.call(this, type, event, ui);
1538         },
1540         plugins: {},
1542         _uiHash: function() {
1543                 return {
1544                         helper: this.helper,
1545                         position: this.position,
1546                         originalPosition: this.originalPosition,
1547                         offset: this.positionAbs
1548                 };
1549         }
1553 $.ui.plugin.add("draggable", "connectToSortable", {
1554         start: function(event, ui) {
1556                 var inst = $(this).data("ui-draggable"), o = inst.options,
1557                         uiSortable = $.extend({}, ui, { item: inst.element });
1558                 inst.sortables = [];
1559                 $(o.connectToSortable).each(function() {
1560                         var sortable = $.data(this, "ui-sortable");
1561                         if (sortable && !sortable.options.disabled) {
1562                                 inst.sortables.push({
1563                                         instance: sortable,
1564                                         shouldRevert: sortable.options.revert
1565                                 });
1566                                 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).
1567                                 sortable._trigger("activate", event, uiSortable);
1568                         }
1569                 });
1571         },
1572         stop: function(event, ui) {
1574                 //If we are still over the sortable, we fake the stop event of the sortable, but also remove helper
1575                 var inst = $(this).data("ui-draggable"),
1576                         uiSortable = $.extend({}, ui, { item: inst.element });
1578                 $.each(inst.sortables, function() {
1579                         if(this.instance.isOver) {
1581                                 this.instance.isOver = 0;
1583                                 inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance
1584                                 this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work)
1586                                 //The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: "valid/invalid"
1587                                 if(this.shouldRevert) {
1588                                         this.instance.options.revert = this.shouldRevert;
1589                                 }
1591                                 //Trigger the stop of the sortable
1592                                 this.instance._mouseStop(event);
1594                                 this.instance.options.helper = this.instance.options._helper;
1596                                 //If the helper has been the original item, restore properties in the sortable
1597                                 if(inst.options.helper === "original") {
1598                                         this.instance.currentItem.css({ top: "auto", left: "auto" });
1599                                 }
1601                         } else {
1602                                 this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance
1603                                 this.instance._trigger("deactivate", event, uiSortable);
1604                         }
1606                 });
1608         },
1609         drag: function(event, ui) {
1611                 var inst = $(this).data("ui-draggable"), that = this;
1613                 $.each(inst.sortables, function() {
1615                         var innermostIntersecting = false,
1616                                 thisSortable = this;
1618                         //Copy over some variables to allow calling the sortable's native _intersectsWith
1619                         this.instance.positionAbs = inst.positionAbs;
1620                         this.instance.helperProportions = inst.helperProportions;
1621                         this.instance.offset.click = inst.offset.click;
1623                         if(this.instance._intersectsWith(this.instance.containerCache)) {
1624                                 innermostIntersecting = true;
1625                                 $.each(inst.sortables, function () {
1626                                         this.instance.positionAbs = inst.positionAbs;
1627                                         this.instance.helperProportions = inst.helperProportions;
1628                                         this.instance.offset.click = inst.offset.click;
1629                                         if (this !== thisSortable &&
1630                                                 this.instance._intersectsWith(this.instance.containerCache) &&
1631                                                 $.contains(thisSortable.instance.element[0], this.instance.element[0])
1632                                         ) {
1633                                                 innermostIntersecting = false;
1634                                         }
1635                                         return innermostIntersecting;
1636                                 });
1637                         }
1640                         if(innermostIntersecting) {
1641                                 //If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once
1642                                 if(!this.instance.isOver) {
1644                                         this.instance.isOver = 1;
1645                                         //Now we fake the start of dragging for the sortable instance,
1646                                         //by cloning the list group item, appending it to the sortable and using it as inst.currentItem
1647                                         //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)
1648                                         this.instance.currentItem = $(that).clone().removeAttr("id").appendTo(this.instance.element).data("ui-sortable-item", true);
1649                                         this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it
1650                                         this.instance.options.helper = function() { return ui.helper[0]; };
1652                                         event.target = this.instance.currentItem[0];
1653                                         this.instance._mouseCapture(event, true);
1654                                         this.instance._mouseStart(event, true, true);
1656                                         //Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes
1657                                         this.instance.offset.click.top = inst.offset.click.top;
1658                                         this.instance.offset.click.left = inst.offset.click.left;
1659                                         this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left;
1660                                         this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top;
1662                                         inst._trigger("toSortable", event);
1663                                         inst.dropped = this.instance.element; //draggable revert needs that
1664                                         //hack so receive/update callbacks work (mostly)
1665                                         inst.currentItem = inst.element;
1666                                         this.instance.fromOutside = inst;
1668                                 }
1670                                 //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
1671                                 if(this.instance.currentItem) {
1672                                         this.instance._mouseDrag(event);
1673                                 }
1675                         } else {
1677                                 //If it doesn't intersect with the sortable, and it intersected before,
1678                                 //we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval
1679                                 if(this.instance.isOver) {
1681                                         this.instance.isOver = 0;
1682                                         this.instance.cancelHelperRemoval = true;
1684                                         //Prevent reverting on this forced stop
1685                                         this.instance.options.revert = false;
1687                                         // The out event needs to be triggered independently
1688                                         this.instance._trigger("out", event, this.instance._uiHash(this.instance));
1690                                         this.instance._mouseStop(event, true);
1691                                         this.instance.options.helper = this.instance.options._helper;
1693                                         //Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size
1694                                         this.instance.currentItem.remove();
1695                                         if(this.instance.placeholder) {
1696                                                 this.instance.placeholder.remove();
1697                                         }
1699                                         inst._trigger("fromSortable", event);
1700                                         inst.dropped = false; //draggable revert needs that
1701                                 }
1703                         }
1705                 });
1707         }
1710 $.ui.plugin.add("draggable", "cursor", {
1711         start: function() {
1712                 var t = $("body"), o = $(this).data("ui-draggable").options;
1713                 if (t.css("cursor")) {
1714                         o._cursor = t.css("cursor");
1715                 }
1716                 t.css("cursor", o.cursor);
1717         },
1718         stop: function() {
1719                 var o = $(this).data("ui-draggable").options;
1720                 if (o._cursor) {
1721                         $("body").css("cursor", o._cursor);
1722                 }
1723         }
1726 $.ui.plugin.add("draggable", "opacity", {
1727         start: function(event, ui) {
1728                 var t = $(ui.helper), o = $(this).data("ui-draggable").options;
1729                 if(t.css("opacity")) {
1730                         o._opacity = t.css("opacity");
1731                 }
1732                 t.css("opacity", o.opacity);
1733         },
1734         stop: function(event, ui) {
1735                 var o = $(this).data("ui-draggable").options;
1736                 if(o._opacity) {
1737                         $(ui.helper).css("opacity", o._opacity);
1738                 }
1739         }
1742 $.ui.plugin.add("draggable", "scroll", {
1743         start: function() {
1744                 var i = $(this).data("ui-draggable");
1745                 if(i.scrollParent[0] !== document && i.scrollParent[0].tagName !== "HTML") {
1746                         i.overflowOffset = i.scrollParent.offset();
1747                 }
1748         },
1749         drag: function( event ) {
1751                 var i = $(this).data("ui-draggable"), o = i.options, scrolled = false;
1753                 if(i.scrollParent[0] !== document && i.scrollParent[0].tagName !== "HTML") {
1755                         if(!o.axis || o.axis !== "x") {
1756                                 if((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) {
1757                                         i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed;
1758                                 } else if(event.pageY - i.overflowOffset.top < o.scrollSensitivity) {
1759                                         i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed;
1760                                 }
1761                         }
1763                         if(!o.axis || o.axis !== "y") {
1764                                 if((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) {
1765                                         i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed;
1766                                 } else if(event.pageX - i.overflowOffset.left < o.scrollSensitivity) {
1767                                         i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed;
1768                                 }
1769                         }
1771                 } else {
1773                         if(!o.axis || o.axis !== "x") {
1774                                 if(event.pageY - $(document).scrollTop() < o.scrollSensitivity) {
1775                                         scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
1776                                 } else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) {
1777                                         scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
1778                                 }
1779                         }
1781                         if(!o.axis || o.axis !== "y") {
1782                                 if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity) {
1783                                         scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
1784                                 } else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) {
1785                                         scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
1786                                 }
1787                         }
1789                 }
1791                 if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) {
1792                         $.ui.ddmanager.prepareOffsets(i, event);
1793                 }
1795         }
1798 $.ui.plugin.add("draggable", "snap", {
1799         start: function() {
1801                 var i = $(this).data("ui-draggable"),
1802                         o = i.options;
1804                 i.snapElements = [];
1806                 $(o.snap.constructor !== String ? ( o.snap.items || ":data(ui-draggable)" ) : o.snap).each(function() {
1807                         var $t = $(this),
1808                                 $o = $t.offset();
1809                         if(this !== i.element[0]) {
1810                                 i.snapElements.push({
1811                                         item: this,
1812                                         width: $t.outerWidth(), height: $t.outerHeight(),
1813                                         top: $o.top, left: $o.left
1814                                 });
1815                         }
1816                 });
1818         },
1819         drag: function(event, ui) {
1821                 var ts, bs, ls, rs, l, r, t, b, i, first,
1822                         inst = $(this).data("ui-draggable"),
1823                         o = inst.options,
1824                         d = o.snapTolerance,
1825                         x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
1826                         y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
1828                 for (i = inst.snapElements.length - 1; i >= 0; i--){
1830                         l = inst.snapElements[i].left;
1831                         r = l + inst.snapElements[i].width;
1832                         t = inst.snapElements[i].top;
1833                         b = t + inst.snapElements[i].height;
1835                         if ( x2 < l - d || x1 > r + d || y2 < t - d || y1 > b + d || !$.contains( inst.snapElements[ i ].item.ownerDocument, inst.snapElements[ i ].item ) ) {
1836                                 if(inst.snapElements[i].snapping) {
1837                                         (inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
1838                                 }
1839                                 inst.snapElements[i].snapping = false;
1840                                 continue;
1841                         }
1843                         if(o.snapMode !== "inner") {
1844                                 ts = Math.abs(t - y2) <= d;
1845                                 bs = Math.abs(b - y1) <= d;
1846                                 ls = Math.abs(l - x2) <= d;
1847                                 rs = Math.abs(r - x1) <= d;
1848                                 if(ts) {
1849                                         ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
1850                                 }
1851                                 if(bs) {
1852                                         ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top;
1853                                 }
1854                                 if(ls) {
1855                                         ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left;
1856                                 }
1857                                 if(rs) {
1858                                         ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left;
1859                                 }
1860                         }
1862                         first = (ts || bs || ls || rs);
1864                         if(o.snapMode !== "outer") {
1865                                 ts = Math.abs(t - y1) <= d;
1866                                 bs = Math.abs(b - y2) <= d;
1867                                 ls = Math.abs(l - x1) <= d;
1868                                 rs = Math.abs(r - x2) <= d;
1869                                 if(ts) {
1870                                         ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top;
1871                                 }
1872                                 if(bs) {
1873                                         ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
1874                                 }
1875                                 if(ls) {
1876                                         ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left;
1877                                 }
1878                                 if(rs) {
1879                                         ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left;
1880                                 }
1881                         }
1883                         if(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first)) {
1884                                 (inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
1885                         }
1886                         inst.snapElements[i].snapping = (ts || bs || ls || rs || first);
1888                 }
1890         }
1893 $.ui.plugin.add("draggable", "stack", {
1894         start: function() {
1895                 var min,
1896                         o = this.data("ui-draggable").options,
1897                         group = $.makeArray($(o.stack)).sort(function(a,b) {
1898                                 return (parseInt($(a).css("zIndex"),10) || 0) - (parseInt($(b).css("zIndex"),10) || 0);
1899                         });
1901                 if (!group.length) { return; }
1903                 min = parseInt($(group[0]).css("zIndex"), 10) || 0;
1904                 $(group).each(function(i) {
1905                         $(this).css("zIndex", min + i);
1906                 });
1907                 this.css("zIndex", (min + group.length));
1908         }
1911 $.ui.plugin.add("draggable", "zIndex", {
1912         start: function(event, ui) {
1913                 var t = $(ui.helper), o = $(this).data("ui-draggable").options;
1914                 if(t.css("zIndex")) {
1915                         o._zIndex = t.css("zIndex");
1916                 }
1917                 t.css("zIndex", o.zIndex);
1918         },
1919         stop: function(event, ui) {
1920                 var o = $(this).data("ui-draggable").options;
1921                 if(o._zIndex) {
1922                         $(ui.helper).css("zIndex", o._zIndex);
1923                 }
1924         }
1927 })(jQuery);
1929 (function( $, undefined ) {
1931 function isOverAxis( x, reference, size ) {
1932         return ( x > reference ) && ( x < ( reference + size ) );
1935 $.widget("ui.droppable", {
1936         version: "1.10.3",
1937         widgetEventPrefix: "drop",
1938         options: {
1939                 accept: "*",
1940                 activeClass: false,
1941                 addClasses: true,
1942                 greedy: false,
1943                 hoverClass: false,
1944                 scope: "default",
1945                 tolerance: "intersect",
1947                 // callbacks
1948                 activate: null,
1949                 deactivate: null,
1950                 drop: null,
1951                 out: null,
1952                 over: null
1953         },
1954         _create: function() {
1956                 var o = this.options,
1957                         accept = o.accept;
1959                 this.isover = false;
1960                 this.isout = true;
1962                 this.accept = $.isFunction(accept) ? accept : function(d) {
1963                         return d.is(accept);
1964                 };
1966                 //Store the droppable's proportions
1967                 this.proportions = { width: this.element[0].offsetWidth, height: this.element[0].offsetHeight };
1969                 // Add the reference and positions to the manager
1970                 $.ui.ddmanager.droppables[o.scope] = $.ui.ddmanager.droppables[o.scope] || [];
1971                 $.ui.ddmanager.droppables[o.scope].push(this);
1973                 (o.addClasses && this.element.addClass("ui-droppable"));
1975         },
1977         _destroy: function() {
1978                 var i = 0,
1979                         drop = $.ui.ddmanager.droppables[this.options.scope];
1981                 for ( ; i < drop.length; i++ ) {
1982                         if ( drop[i] === this ) {
1983                                 drop.splice(i, 1);
1984                         }
1985                 }
1987                 this.element.removeClass("ui-droppable ui-droppable-disabled");
1988         },
1990         _setOption: function(key, value) {
1992                 if(key === "accept") {
1993                         this.accept = $.isFunction(value) ? value : function(d) {
1994                                 return d.is(value);
1995                         };
1996                 }
1997                 $.Widget.prototype._setOption.apply(this, arguments);
1998         },
2000         _activate: function(event) {
2001                 var draggable = $.ui.ddmanager.current;
2002                 if(this.options.activeClass) {
2003                         this.element.addClass(this.options.activeClass);
2004                 }
2005                 if(draggable){
2006                         this._trigger("activate", event, this.ui(draggable));
2007                 }
2008         },
2010         _deactivate: function(event) {
2011                 var draggable = $.ui.ddmanager.current;
2012                 if(this.options.activeClass) {
2013                         this.element.removeClass(this.options.activeClass);
2014                 }
2015                 if(draggable){
2016                         this._trigger("deactivate", event, this.ui(draggable));
2017                 }
2018         },
2020         _over: function(event) {
2022                 var draggable = $.ui.ddmanager.current;
2024                 // Bail if draggable and droppable are same element
2025                 if (!draggable || (draggable.currentItem || draggable.element)[0] === this.element[0]) {
2026                         return;
2027                 }
2029                 if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
2030                         if(this.options.hoverClass) {
2031                                 this.element.addClass(this.options.hoverClass);
2032                         }
2033                         this._trigger("over", event, this.ui(draggable));
2034                 }
2036         },
2038         _out: function(event) {
2040                 var draggable = $.ui.ddmanager.current;
2042                 // Bail if draggable and droppable are same element
2043                 if (!draggable || (draggable.currentItem || draggable.element)[0] === this.element[0]) {
2044                         return;
2045                 }
2047                 if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
2048                         if(this.options.hoverClass) {
2049                                 this.element.removeClass(this.options.hoverClass);
2050                         }
2051                         this._trigger("out", event, this.ui(draggable));
2052                 }
2054         },
2056         _drop: function(event,custom) {
2058                 var draggable = custom || $.ui.ddmanager.current,
2059                         childrenIntersection = false;
2061                 // Bail if draggable and droppable are same element
2062                 if (!draggable || (draggable.currentItem || draggable.element)[0] === this.element[0]) {
2063                         return false;
2064                 }
2066                 this.element.find(":data(ui-droppable)").not(".ui-draggable-dragging").each(function() {
2067                         var inst = $.data(this, "ui-droppable");
2068                         if(
2069                                 inst.options.greedy &&
2070                                 !inst.options.disabled &&
2071                                 inst.options.scope === draggable.options.scope &&
2072                                 inst.accept.call(inst.element[0], (draggable.currentItem || draggable.element)) &&
2073                                 $.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance)
2074                         ) { childrenIntersection = true; return false; }
2075                 });
2076                 if(childrenIntersection) {
2077                         return false;
2078                 }
2080                 if(this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
2081                         if(this.options.activeClass) {
2082                                 this.element.removeClass(this.options.activeClass);
2083                         }
2084                         if(this.options.hoverClass) {
2085                                 this.element.removeClass(this.options.hoverClass);
2086                         }
2087                         this._trigger("drop", event, this.ui(draggable));
2088                         return this.element;
2089                 }
2091                 return false;
2093         },
2095         ui: function(c) {
2096                 return {
2097                         draggable: (c.currentItem || c.element),
2098                         helper: c.helper,
2099                         position: c.position,
2100                         offset: c.positionAbs
2101                 };
2102         }
2106 $.ui.intersect = function(draggable, droppable, toleranceMode) {
2108         if (!droppable.offset) {
2109                 return false;
2110         }
2112         var draggableLeft, draggableTop,
2113                 x1 = (draggable.positionAbs || draggable.position.absolute).left, x2 = x1 + draggable.helperProportions.width,
2114                 y1 = (draggable.positionAbs || draggable.position.absolute).top, y2 = y1 + draggable.helperProportions.height,
2115                 l = droppable.offset.left, r = l + droppable.proportions.width,
2116                 t = droppable.offset.top, b = t + droppable.proportions.height;
2118         switch (toleranceMode) {
2119                 case "fit":
2120                         return (l <= x1 && x2 <= r && t <= y1 && y2 <= b);
2121                 case "intersect":
2122                         return (l < x1 + (draggable.helperProportions.width / 2) && // Right Half
2123                                 x2 - (draggable.helperProportions.width / 2) < r && // Left Half
2124                                 t < y1 + (draggable.helperProportions.height / 2) && // Bottom Half
2125                                 y2 - (draggable.helperProportions.height / 2) < b ); // Top Half
2126                 case "pointer":
2127                         draggableLeft = ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left);
2128                         draggableTop = ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top);
2129                         return isOverAxis( draggableTop, t, droppable.proportions.height ) && isOverAxis( draggableLeft, l, droppable.proportions.width );
2130                 case "touch":
2131                         return (
2132                                 (y1 >= t && y1 <= b) || // Top edge touching
2133                                 (y2 >= t && y2 <= b) || // Bottom edge touching
2134                                 (y1 < t && y2 > b)              // Surrounded vertically
2135                         ) && (
2136                                 (x1 >= l && x1 <= r) || // Left edge touching
2137                                 (x2 >= l && x2 <= r) || // Right edge touching
2138                                 (x1 < l && x2 > r)              // Surrounded horizontally
2139                         );
2140                 default:
2141                         return false;
2142                 }
2147         This manager tracks offsets of draggables and droppables
2149 $.ui.ddmanager = {
2150         current: null,
2151         droppables: { "default": [] },
2152         prepareOffsets: function(t, event) {
2154                 var i, j,
2155                         m = $.ui.ddmanager.droppables[t.options.scope] || [],
2156                         type = event ? event.type : null, // workaround for #2317
2157                         list = (t.currentItem || t.element).find(":data(ui-droppable)").addBack();
2159                 droppablesLoop: for (i = 0; i < m.length; i++) {
2161                         //No disabled and non-accepted
2162                         if(m[i].options.disabled || (t && !m[i].accept.call(m[i].element[0],(t.currentItem || t.element)))) {
2163                                 continue;
2164                         }
2166                         // Filter out elements in the current dragged item
2167                         for (j=0; j < list.length; j++) {
2168                                 if(list[j] === m[i].element[0]) {
2169                                         m[i].proportions.height = 0;
2170                                         continue droppablesLoop;
2171                                 }
2172                         }
2174                         m[i].visible = m[i].element.css("display") !== "none";
2175                         if(!m[i].visible) {
2176                                 continue;
2177                         }
2179                         //Activate the droppable if used directly from draggables
2180                         if(type === "mousedown") {
2181                                 m[i]._activate.call(m[i], event);
2182                         }
2184                         m[i].offset = m[i].element.offset();
2185                         m[i].proportions = { width: m[i].element[0].offsetWidth, height: m[i].element[0].offsetHeight };
2187                 }
2189         },
2190         drop: function(draggable, event) {
2192                 var dropped = false;
2193                 // Create a copy of the droppables in case the list changes during the drop (#9116)
2194                 $.each(($.ui.ddmanager.droppables[draggable.options.scope] || []).slice(), function() {
2196                         if(!this.options) {
2197                                 return;
2198                         }
2199                         if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance)) {
2200                                 dropped = this._drop.call(this, event) || dropped;
2201                         }
2203                         if (!this.options.disabled && this.visible && this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
2204                                 this.isout = true;
2205                                 this.isover = false;
2206                                 this._deactivate.call(this, event);
2207                         }
2209                 });
2210                 return dropped;
2212         },
2213         dragStart: function( draggable, event ) {
2214                 //Listen for scrolling so that if the dragging causes scrolling the position of the droppables can be recalculated (see #5003)
2215                 draggable.element.parentsUntil( "body" ).bind( "scroll.droppable", function() {
2216                         if( !draggable.options.refreshPositions ) {
2217                                 $.ui.ddmanager.prepareOffsets( draggable, event );
2218                         }
2219                 });
2220         },
2221         drag: function(draggable, event) {
2223                 //If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse.
2224                 if(draggable.options.refreshPositions) {
2225                         $.ui.ddmanager.prepareOffsets(draggable, event);
2226                 }
2228                 //Run through all droppables and check their positions based on specific tolerance options
2229                 $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
2231                         if(this.options.disabled || this.greedyChild || !this.visible) {
2232                                 return;
2233                         }
2235                         var parentInstance, scope, parent,
2236                                 intersects = $.ui.intersect(draggable, this, this.options.tolerance),
2237                                 c = !intersects && this.isover ? "isout" : (intersects && !this.isover ? "isover" : null);
2238                         if(!c) {
2239                                 return;
2240                         }
2242                         if (this.options.greedy) {
2243                                 // find droppable parents with same scope
2244                                 scope = this.options.scope;
2245                                 parent = this.element.parents(":data(ui-droppable)").filter(function () {
2246                                         return $.data(this, "ui-droppable").options.scope === scope;
2247                                 });
2249                                 if (parent.length) {
2250                                         parentInstance = $.data(parent[0], "ui-droppable");
2251                                         parentInstance.greedyChild = (c === "isover");
2252                                 }
2253                         }
2255                         // we just moved into a greedy child
2256                         if (parentInstance && c === "isover") {
2257                                 parentInstance.isover = false;
2258                                 parentInstance.isout = true;
2259                                 parentInstance._out.call(parentInstance, event);
2260                         }
2262                         this[c] = true;
2263                         this[c === "isout" ? "isover" : "isout"] = false;
2264                         this[c === "isover" ? "_over" : "_out"].call(this, event);
2266                         // we just moved out of a greedy child
2267                         if (parentInstance && c === "isout") {
2268                                 parentInstance.isout = false;
2269                                 parentInstance.isover = true;
2270                                 parentInstance._over.call(parentInstance, event);
2271                         }
2272                 });
2274         },
2275         dragStop: function( draggable, event ) {
2276                 draggable.element.parentsUntil( "body" ).unbind( "scroll.droppable" );
2277                 //Call prepareOffsets one final time since IE does not fire return scroll events when overflow was caused by drag (see #5003)
2278                 if( !draggable.options.refreshPositions ) {
2279                         $.ui.ddmanager.prepareOffsets( draggable, event );
2280                 }
2281         }
2284 })(jQuery);
2286 (function( $, undefined ) {
2288 function num(v) {
2289         return parseInt(v, 10) || 0;
2292 function isNumber(value) {
2293         return !isNaN(parseInt(value, 10));
2296 $.widget("ui.resizable", $.ui.mouse, {
2297         version: "1.10.3",
2298         widgetEventPrefix: "resize",
2299         options: {
2300                 alsoResize: false,
2301                 animate: false,
2302                 animateDuration: "slow",
2303                 animateEasing: "swing",
2304                 aspectRatio: false,
2305                 autoHide: false,
2306                 containment: false,
2307                 ghost: false,
2308                 grid: false,
2309                 handles: "e,s,se",
2310                 helper: false,
2311                 maxHeight: null,
2312                 maxWidth: null,
2313                 minHeight: 10,
2314                 minWidth: 10,
2315                 // See #7960
2316                 zIndex: 90,
2318                 // callbacks
2319                 resize: null,
2320                 start: null,
2321                 stop: null
2322         },
2323         _create: function() {
2325                 var n, i, handle, axis, hname,
2326                         that = this,
2327                         o = this.options;
2328                 this.element.addClass("ui-resizable");
2330                 $.extend(this, {
2331                         _aspectRatio: !!(o.aspectRatio),
2332                         aspectRatio: o.aspectRatio,
2333                         originalElement: this.element,
2334                         _proportionallyResizeElements: [],
2335                         _helper: o.helper || o.ghost || o.animate ? o.helper || "ui-resizable-helper" : null
2336                 });
2338                 //Wrap the element if it cannot hold child nodes
2339                 if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) {
2341                         //Create a wrapper element and set the wrapper to the new current internal element
2342                         this.element.wrap(
2343                                 $("<div class='ui-wrapper' style='overflow: hidden;'></div>").css({
2344                                         position: this.element.css("position"),
2345                                         width: this.element.outerWidth(),
2346                                         height: this.element.outerHeight(),
2347                                         top: this.element.css("top"),
2348                                         left: this.element.css("left")
2349                                 })
2350                         );
2352                         //Overwrite the original this.element
2353                         this.element = this.element.parent().data(
2354                                 "ui-resizable", this.element.data("ui-resizable")
2355                         );
2357                         this.elementIsWrapper = true;
2359                         //Move margins to the wrapper
2360                         this.element.css({ marginLeft: this.originalElement.css("marginLeft"), marginTop: this.originalElement.css("marginTop"), marginRight: this.originalElement.css("marginRight"), marginBottom: this.originalElement.css("marginBottom") });
2361                         this.originalElement.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0});
2363                         //Prevent Safari textarea resize
2364                         this.originalResizeStyle = this.originalElement.css("resize");
2365                         this.originalElement.css("resize", "none");
2367                         //Push the actual element to our proportionallyResize internal array
2368                         this._proportionallyResizeElements.push(this.originalElement.css({ position: "static", zoom: 1, display: "block" }));
2370                         // avoid IE jump (hard set the margin)
2371                         this.originalElement.css({ margin: this.originalElement.css("margin") });
2373                         // fix handlers offset
2374                         this._proportionallyResize();
2376                 }
2378                 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" });
2379                 if(this.handles.constructor === String) {
2381                         if ( this.handles === "all") {
2382                                 this.handles = "n,e,s,w,se,sw,ne,nw";
2383                         }
2385                         n = this.handles.split(",");
2386                         this.handles = {};
2388                         for(i = 0; i < n.length; i++) {
2390                                 handle = $.trim(n[i]);
2391                                 hname = "ui-resizable-"+handle;
2392                                 axis = $("<div class='ui-resizable-handle " + hname + "'></div>");
2394                                 // Apply zIndex to all handles - see #7960
2395                                 axis.css({ zIndex: o.zIndex });
2397                                 //TODO : What's going on here?
2398                                 if ("se" === handle) {
2399                                         axis.addClass("ui-icon ui-icon-gripsmall-diagonal-se");
2400                                 }
2402                                 //Insert into internal handles object and append to element
2403                                 this.handles[handle] = ".ui-resizable-"+handle;
2404                                 this.element.append(axis);
2405                         }
2407                 }
2409                 this._renderAxis = function(target) {
2411                         var i, axis, padPos, padWrapper;
2413                         target = target || this.element;
2415                         for(i in this.handles) {
2417                                 if(this.handles[i].constructor === String) {
2418                                         this.handles[i] = $(this.handles[i], this.element).show();
2419                                 }
2421                                 //Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls)
2422                                 if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) {
2424                                         axis = $(this.handles[i], this.element);
2426                                         //Checking the correct pad and border
2427                                         padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth();
2429                                         //The padding type i have to apply...
2430                                         padPos = [ "padding",
2431                                                 /ne|nw|n/.test(i) ? "Top" :
2432                                                 /se|sw|s/.test(i) ? "Bottom" :
2433                                                 /^e$/.test(i) ? "Right" : "Left" ].join("");
2435                                         target.css(padPos, padWrapper);
2437                                         this._proportionallyResize();
2439                                 }
2441                                 //TODO: What's that good for? There's not anything to be executed left
2442                                 if(!$(this.handles[i]).length) {
2443                                         continue;
2444                                 }
2445                         }
2446                 };
2448                 //TODO: make renderAxis a prototype function
2449                 this._renderAxis(this.element);
2451                 this._handles = $(".ui-resizable-handle", this.element)
2452                         .disableSelection();
2454                 //Matching axis name
2455                 this._handles.mouseover(function() {
2456                         if (!that.resizing) {
2457                                 if (this.className) {
2458                                         axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);
2459                                 }
2460                                 //Axis, default = se
2461                                 that.axis = axis && axis[1] ? axis[1] : "se";
2462                         }
2463                 });
2465                 //If we want to auto hide the elements
2466                 if (o.autoHide) {
2467                         this._handles.hide();
2468                         $(this.element)
2469                                 .addClass("ui-resizable-autohide")
2470                                 .mouseenter(function() {
2471                                         if (o.disabled) {
2472                                                 return;
2473                                         }
2474                                         $(this).removeClass("ui-resizable-autohide");
2475                                         that._handles.show();
2476                                 })
2477                                 .mouseleave(function(){
2478                                         if (o.disabled) {
2479                                                 return;
2480                                         }
2481                                         if (!that.resizing) {
2482                                                 $(this).addClass("ui-resizable-autohide");
2483                                                 that._handles.hide();
2484                                         }
2485                                 });
2486                 }
2488                 //Initialize the mouse interaction
2489                 this._mouseInit();
2491         },
2493         _destroy: function() {
2495                 this._mouseDestroy();
2497                 var wrapper,
2498                         _destroy = function(exp) {
2499                                 $(exp).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing")
2500                                         .removeData("resizable").removeData("ui-resizable").unbind(".resizable").find(".ui-resizable-handle").remove();
2501                         };
2503                 //TODO: Unwrap at same DOM position
2504                 if (this.elementIsWrapper) {
2505                         _destroy(this.element);
2506                         wrapper = this.element;
2507                         this.originalElement.css({
2508                                 position: wrapper.css("position"),
2509                                 width: wrapper.outerWidth(),
2510                                 height: wrapper.outerHeight(),
2511                                 top: wrapper.css("top"),
2512                                 left: wrapper.css("left")
2513                         }).insertAfter( wrapper );
2514                         wrapper.remove();
2515                 }
2517                 this.originalElement.css("resize", this.originalResizeStyle);
2518                 _destroy(this.originalElement);
2520                 return this;
2521         },
2523         _mouseCapture: function(event) {
2524                 var i, handle,
2525                         capture = false;
2527                 for (i in this.handles) {
2528                         handle = $(this.handles[i])[0];
2529                         if (handle === event.target || $.contains(handle, event.target)) {
2530                                 capture = true;
2531                         }
2532                 }
2534                 return !this.options.disabled && capture;
2535         },
2537         _mouseStart: function(event) {
2539                 var curleft, curtop, cursor,
2540                         o = this.options,
2541                         iniPos = this.element.position(),
2542                         el = this.element;
2544                 this.resizing = true;
2546                 // bugfix for http://dev.jquery.com/ticket/1749
2547                 if ( (/absolute/).test( el.css("position") ) ) {
2548                         el.css({ position: "absolute", top: el.css("top"), left: el.css("left") });
2549                 } else if (el.is(".ui-draggable")) {
2550                         el.css({ position: "absolute", top: iniPos.top, left: iniPos.left });
2551                 }
2553                 this._renderProxy();
2555                 curleft = num(this.helper.css("left"));
2556                 curtop = num(this.helper.css("top"));
2558                 if (o.containment) {
2559                         curleft += $(o.containment).scrollLeft() || 0;
2560                         curtop += $(o.containment).scrollTop() || 0;
2561                 }
2563                 //Store needed variables
2564                 this.offset = this.helper.offset();
2565                 this.position = { left: curleft, top: curtop };
2566                 this.size = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
2567                 this.originalSize = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
2568                 this.originalPosition = { left: curleft, top: curtop };
2569                 this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() };
2570                 this.originalMousePosition = { left: event.pageX, top: event.pageY };
2572                 //Aspect Ratio
2573                 this.aspectRatio = (typeof o.aspectRatio === "number") ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1);
2575                 cursor = $(".ui-resizable-" + this.axis).css("cursor");
2576                 $("body").css("cursor", cursor === "auto" ? this.axis + "-resize" : cursor);
2578                 el.addClass("ui-resizable-resizing");
2579                 this._propagate("start", event);
2580                 return true;
2581         },
2583         _mouseDrag: function(event) {
2585                 //Increase performance, avoid regex
2586                 var data,
2587                         el = this.helper, props = {},
2588                         smp = this.originalMousePosition,
2589                         a = this.axis,
2590                         prevTop = this.position.top,
2591                         prevLeft = this.position.left,
2592                         prevWidth = this.size.width,
2593                         prevHeight = this.size.height,
2594                         dx = (event.pageX-smp.left)||0,
2595                         dy = (event.pageY-smp.top)||0,
2596                         trigger = this._change[a];
2598                 if (!trigger) {
2599                         return false;
2600                 }
2602                 // Calculate the attrs that will be change
2603                 data = trigger.apply(this, [event, dx, dy]);
2605                 // Put this in the mouseDrag handler since the user can start pressing shift while resizing
2606                 this._updateVirtualBoundaries(event.shiftKey);
2607                 if (this._aspectRatio || event.shiftKey) {
2608                         data = this._updateRatio(data, event);
2609                 }
2611                 data = this._respectSize(data, event);
2613                 this._updateCache(data);
2615                 // plugins callbacks need to be called first
2616                 this._propagate("resize", event);
2618                 if (this.position.top !== prevTop) {
2619                         props.top = this.position.top + "px";
2620                 }
2621                 if (this.position.left !== prevLeft) {
2622                         props.left = this.position.left + "px";
2623                 }
2624                 if (this.size.width !== prevWidth) {
2625                         props.width = this.size.width + "px";
2626                 }
2627                 if (this.size.height !== prevHeight) {
2628                         props.height = this.size.height + "px";
2629                 }
2630                 el.css(props);
2632                 if (!this._helper && this._proportionallyResizeElements.length) {
2633                         this._proportionallyResize();
2634                 }
2636                 // Call the user callback if the element was resized
2637                 if ( ! $.isEmptyObject(props) ) {
2638                         this._trigger("resize", event, this.ui());
2639                 }
2641                 return false;
2642         },
2644         _mouseStop: function(event) {
2646                 this.resizing = false;
2647                 var pr, ista, soffseth, soffsetw, s, left, top,
2648                         o = this.options, that = this;
2650                 if(this._helper) {
2652                         pr = this._proportionallyResizeElements;
2653                         ista = pr.length && (/textarea/i).test(pr[0].nodeName);
2654                         soffseth = ista && $.ui.hasScroll(pr[0], "left") /* TODO - jump height */ ? 0 : that.sizeDiff.height;
2655                         soffsetw = ista ? 0 : that.sizeDiff.width;
2657                         s = { width: (that.helper.width()  - soffsetw), height: (that.helper.height() - soffseth) };
2658                         left = (parseInt(that.element.css("left"), 10) + (that.position.left - that.originalPosition.left)) || null;
2659                         top = (parseInt(that.element.css("top"), 10) + (that.position.top - that.originalPosition.top)) || null;
2661                         if (!o.animate) {
2662                                 this.element.css($.extend(s, { top: top, left: left }));
2663                         }
2665                         that.helper.height(that.size.height);
2666                         that.helper.width(that.size.width);
2668                         if (this._helper && !o.animate) {
2669                                 this._proportionallyResize();
2670                         }
2671                 }
2673                 $("body").css("cursor", "auto");
2675                 this.element.removeClass("ui-resizable-resizing");
2677                 this._propagate("stop", event);
2679                 if (this._helper) {
2680                         this.helper.remove();
2681                 }
2683                 return false;
2685         },
2687         _updateVirtualBoundaries: function(forceAspectRatio) {
2688                 var pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b,
2689                         o = this.options;
2691                 b = {
2692                         minWidth: isNumber(o.minWidth) ? o.minWidth : 0,
2693                         maxWidth: isNumber(o.maxWidth) ? o.maxWidth : Infinity,
2694                         minHeight: isNumber(o.minHeight) ? o.minHeight : 0,
2695                         maxHeight: isNumber(o.maxHeight) ? o.maxHeight : Infinity
2696                 };
2698                 if(this._aspectRatio || forceAspectRatio) {
2699                         // We want to create an enclosing box whose aspect ration is the requested one
2700                         // First, compute the "projected" size for each dimension based on the aspect ratio and other dimension
2701                         pMinWidth = b.minHeight * this.aspectRatio;
2702                         pMinHeight = b.minWidth / this.aspectRatio;
2703                         pMaxWidth = b.maxHeight * this.aspectRatio;
2704                         pMaxHeight = b.maxWidth / this.aspectRatio;
2706                         if(pMinWidth > b.minWidth) {
2707                                 b.minWidth = pMinWidth;
2708                         }
2709                         if(pMinHeight > b.minHeight) {
2710                                 b.minHeight = pMinHeight;
2711                         }
2712                         if(pMaxWidth < b.maxWidth) {
2713                                 b.maxWidth = pMaxWidth;
2714                         }
2715                         if(pMaxHeight < b.maxHeight) {
2716                                 b.maxHeight = pMaxHeight;
2717                         }
2718                 }
2719                 this._vBoundaries = b;
2720         },
2722         _updateCache: function(data) {
2723                 this.offset = this.helper.offset();
2724                 if (isNumber(data.left)) {
2725                         this.position.left = data.left;
2726                 }
2727                 if (isNumber(data.top)) {
2728                         this.position.top = data.top;
2729                 }
2730                 if (isNumber(data.height)) {
2731                         this.size.height = data.height;
2732                 }
2733                 if (isNumber(data.width)) {
2734                         this.size.width = data.width;
2735                 }
2736         },
2738         _updateRatio: function( data ) {
2740                 var cpos = this.position,
2741                         csize = this.size,
2742                         a = this.axis;
2744                 if (isNumber(data.height)) {
2745                         data.width = (data.height * this.aspectRatio);
2746                 } else if (isNumber(data.width)) {
2747                         data.height = (data.width / this.aspectRatio);
2748                 }
2750                 if (a === "sw") {
2751                         data.left = cpos.left + (csize.width - data.width);
2752                         data.top = null;
2753                 }
2754                 if (a === "nw") {
2755                         data.top = cpos.top + (csize.height - data.height);
2756                         data.left = cpos.left + (csize.width - data.width);
2757                 }
2759                 return data;
2760         },
2762         _respectSize: function( data ) {
2764                 var o = this._vBoundaries,
2765                         a = this.axis,
2766                         ismaxw = isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh = isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height),
2767                         isminw = isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh = isNumber(data.height) && o.minHeight && (o.minHeight > data.height),
2768                         dw = this.originalPosition.left + this.originalSize.width,
2769                         dh = this.position.top + this.size.height,
2770                         cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a);
2771                 if (isminw) {
2772                         data.width = o.minWidth;
2773                 }
2774                 if (isminh) {
2775                         data.height = o.minHeight;
2776                 }
2777                 if (ismaxw) {
2778                         data.width = o.maxWidth;
2779                 }
2780                 if (ismaxh) {
2781                         data.height = o.maxHeight;
2782                 }
2784                 if (isminw && cw) {
2785                         data.left = dw - o.minWidth;
2786                 }
2787                 if (ismaxw && cw) {
2788                         data.left = dw - o.maxWidth;
2789                 }
2790                 if (isminh && ch) {
2791                         data.top = dh - o.minHeight;
2792                 }
2793                 if (ismaxh && ch) {
2794                         data.top = dh - o.maxHeight;
2795                 }
2797                 // fixing jump error on top/left - bug #2330
2798                 if (!data.width && !data.height && !data.left && data.top) {
2799                         data.top = null;
2800                 } else if (!data.width && !data.height && !data.top && data.left) {
2801                         data.left = null;
2802                 }
2804                 return data;
2805         },
2807         _proportionallyResize: function() {
2809                 if (!this._proportionallyResizeElements.length) {
2810                         return;
2811                 }
2813                 var i, j, borders, paddings, prel,
2814                         element = this.helper || this.element;
2816                 for ( i=0; i < this._proportionallyResizeElements.length; i++) {
2818                         prel = this._proportionallyResizeElements[i];
2820                         if (!this.borderDif) {
2821                                 this.borderDif = [];
2822                                 borders = [prel.css("borderTopWidth"), prel.css("borderRightWidth"), prel.css("borderBottomWidth"), prel.css("borderLeftWidth")];
2823                                 paddings = [prel.css("paddingTop"), prel.css("paddingRight"), prel.css("paddingBottom"), prel.css("paddingLeft")];
2825                                 for ( j = 0; j < borders.length; j++ ) {
2826                                         this.borderDif[ j ] = ( parseInt( borders[ j ], 10 ) || 0 ) + ( parseInt( paddings[ j ], 10 ) || 0 );
2827                                 }
2828                         }
2830                         prel.css({
2831                                 height: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0,
2832                                 width: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0
2833                         });
2835                 }
2837         },
2839         _renderProxy: function() {
2841                 var el = this.element, o = this.options;
2842                 this.elementOffset = el.offset();
2844                 if(this._helper) {
2846                         this.helper = this.helper || $("<div style='overflow:hidden;'></div>");
2848                         this.helper.addClass(this._helper).css({
2849                                 width: this.element.outerWidth() - 1,
2850                                 height: this.element.outerHeight() - 1,
2851                                 position: "absolute",
2852                                 left: this.elementOffset.left +"px",
2853                                 top: this.elementOffset.top +"px",
2854                                 zIndex: ++o.zIndex //TODO: Don't modify option
2855                         });
2857                         this.helper
2858                                 .appendTo("body")
2859                                 .disableSelection();
2861                 } else {
2862                         this.helper = this.element;
2863                 }
2865         },
2867         _change: {
2868                 e: function(event, dx) {
2869                         return { width: this.originalSize.width + dx };
2870                 },
2871                 w: function(event, dx) {
2872                         var cs = this.originalSize, sp = this.originalPosition;
2873                         return { left: sp.left + dx, width: cs.width - dx };
2874                 },
2875                 n: function(event, dx, dy) {
2876                         var cs = this.originalSize, sp = this.originalPosition;
2877                         return { top: sp.top + dy, height: cs.height - dy };
2878                 },
2879                 s: function(event, dx, dy) {
2880                         return { height: this.originalSize.height + dy };
2881                 },
2882                 se: function(event, dx, dy) {
2883                         return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
2884                 },
2885                 sw: function(event, dx, dy) {
2886                         return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
2887                 },
2888                 ne: function(event, dx, dy) {
2889                         return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
2890                 },
2891                 nw: function(event, dx, dy) {
2892                         return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
2893                 }
2894         },
2896         _propagate: function(n, event) {
2897                 $.ui.plugin.call(this, n, [event, this.ui()]);
2898                 (n !== "resize" && this._trigger(n, event, this.ui()));
2899         },
2901         plugins: {},
2903         ui: function() {
2904                 return {
2905                         originalElement: this.originalElement,
2906                         element: this.element,
2907                         helper: this.helper,
2908                         position: this.position,
2909                         size: this.size,
2910                         originalSize: this.originalSize,
2911                         originalPosition: this.originalPosition
2912                 };
2913         }
2918  * Resizable Extensions
2919  */
2921 $.ui.plugin.add("resizable", "animate", {
2923         stop: function( event ) {
2924                 var that = $(this).data("ui-resizable"),
2925                         o = that.options,
2926                         pr = that._proportionallyResizeElements,
2927                         ista = pr.length && (/textarea/i).test(pr[0].nodeName),
2928                         soffseth = ista && $.ui.hasScroll(pr[0], "left") /* TODO - jump height */ ? 0 : that.sizeDiff.height,
2929                         soffsetw = ista ? 0 : that.sizeDiff.width,
2930                         style = { width: (that.size.width - soffsetw), height: (that.size.height - soffseth) },
2931                         left = (parseInt(that.element.css("left"), 10) + (that.position.left - that.originalPosition.left)) || null,
2932                         top = (parseInt(that.element.css("top"), 10) + (that.position.top - that.originalPosition.top)) || null;
2934                 that.element.animate(
2935                         $.extend(style, top && left ? { top: top, left: left } : {}), {
2936                                 duration: o.animateDuration,
2937                                 easing: o.animateEasing,
2938                                 step: function() {
2940                                         var data = {
2941                                                 width: parseInt(that.element.css("width"), 10),
2942                                                 height: parseInt(that.element.css("height"), 10),
2943                                                 top: parseInt(that.element.css("top"), 10),
2944                                                 left: parseInt(that.element.css("left"), 10)
2945                                         };
2947                                         if (pr && pr.length) {
2948                                                 $(pr[0]).css({ width: data.width, height: data.height });
2949                                         }
2951                                         // propagating resize, and updating values for each animation step
2952                                         that._updateCache(data);
2953                                         that._propagate("resize", event);
2955                                 }
2956                         }
2957                 );
2958         }
2962 $.ui.plugin.add("resizable", "containment", {
2964         start: function() {
2965                 var element, p, co, ch, cw, width, height,
2966                         that = $(this).data("ui-resizable"),
2967                         o = that.options,
2968                         el = that.element,
2969                         oc = o.containment,
2970                         ce = (oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc;
2972                 if (!ce) {
2973                         return;
2974                 }
2976                 that.containerElement = $(ce);
2978                 if (/document/.test(oc) || oc === document) {
2979                         that.containerOffset = { left: 0, top: 0 };
2980                         that.containerPosition = { left: 0, top: 0 };
2982                         that.parentData = {
2983                                 element: $(document), left: 0, top: 0,
2984                                 width: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight
2985                         };
2986                 }
2988                 // i'm a node, so compute top, left, right, bottom
2989                 else {
2990                         element = $(ce);
2991                         p = [];
2992                         $([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) { p[i] = num(element.css("padding" + name)); });
2994                         that.containerOffset = element.offset();
2995                         that.containerPosition = element.position();
2996                         that.containerSize = { height: (element.innerHeight() - p[3]), width: (element.innerWidth() - p[1]) };
2998                         co = that.containerOffset;
2999                         ch = that.containerSize.height;
3000                         cw = that.containerSize.width;
3001                         width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw );
3002                         height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch);
3004                         that.parentData = {
3005                                 element: ce, left: co.left, top: co.top, width: width, height: height
3006                         };
3007                 }
3008         },
3010         resize: function( event ) {
3011                 var woset, hoset, isParent, isOffsetRelative,
3012                         that = $(this).data("ui-resizable"),
3013                         o = that.options,
3014                         co = that.containerOffset, cp = that.position,
3015                         pRatio = that._aspectRatio || event.shiftKey,
3016                         cop = { top:0, left:0 }, ce = that.containerElement;
3018                 if (ce[0] !== document && (/static/).test(ce.css("position"))) {
3019                         cop = co;
3020                 }
3022                 if (cp.left < (that._helper ? co.left : 0)) {
3023                         that.size.width = that.size.width + (that._helper ? (that.position.left - co.left) : (that.position.left - cop.left));
3024                         if (pRatio) {
3025                                 that.size.height = that.size.width / that.aspectRatio;
3026                         }
3027                         that.position.left = o.helper ? co.left : 0;
3028                 }
3030                 if (cp.top < (that._helper ? co.top : 0)) {
3031                         that.size.height = that.size.height + (that._helper ? (that.position.top - co.top) : that.position.top);
3032                         if (pRatio) {
3033                                 that.size.width = that.size.height * that.aspectRatio;
3034                         }
3035                         that.position.top = that._helper ? co.top : 0;
3036                 }
3038                 that.offset.left = that.parentData.left+that.position.left;
3039                 that.offset.top = that.parentData.top+that.position.top;
3041                 woset = Math.abs( (that._helper ? that.offset.left - cop.left : (that.offset.left - cop.left)) + that.sizeDiff.width );
3042                 hoset = Math.abs( (that._helper ? that.offset.top - cop.top : (that.offset.top - co.top)) + that.sizeDiff.height );
3044                 isParent = that.containerElement.get(0) === that.element.parent().get(0);
3045                 isOffsetRelative = /relative|absolute/.test(that.containerElement.css("position"));
3047                 if(isParent && isOffsetRelative) {
3048                         woset -= that.parentData.left;
3049                 }
3051                 if (woset + that.size.width >= that.parentData.width) {
3052                         that.size.width = that.parentData.width - woset;
3053                         if (pRatio) {
3054                                 that.size.height = that.size.width / that.aspectRatio;
3055                         }
3056                 }
3058                 if (hoset + that.size.height >= that.parentData.height) {
3059                         that.size.height = that.parentData.height - hoset;
3060                         if (pRatio) {
3061                                 that.size.width = that.size.height * that.aspectRatio;
3062                         }
3063                 }
3064         },
3066         stop: function(){
3067                 var that = $(this).data("ui-resizable"),
3068                         o = that.options,
3069                         co = that.containerOffset,
3070                         cop = that.containerPosition,
3071                         ce = that.containerElement,
3072                         helper = $(that.helper),
3073                         ho = helper.offset(),
3074                         w = helper.outerWidth() - that.sizeDiff.width,
3075                         h = helper.outerHeight() - that.sizeDiff.height;
3077                 if (that._helper && !o.animate && (/relative/).test(ce.css("position"))) {
3078                         $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
3079                 }
3081                 if (that._helper && !o.animate && (/static/).test(ce.css("position"))) {
3082                         $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
3083                 }
3085         }
3088 $.ui.plugin.add("resizable", "alsoResize", {
3090         start: function () {
3091                 var that = $(this).data("ui-resizable"),
3092                         o = that.options,
3093                         _store = function (exp) {
3094                                 $(exp).each(function() {
3095                                         var el = $(this);
3096                                         el.data("ui-resizable-alsoresize", {
3097                                                 width: parseInt(el.width(), 10), height: parseInt(el.height(), 10),
3098                                                 left: parseInt(el.css("left"), 10), top: parseInt(el.css("top"), 10)
3099                                         });
3100                                 });
3101                         };
3103                 if (typeof(o.alsoResize) === "object" && !o.alsoResize.parentNode) {
3104                         if (o.alsoResize.length) { o.alsoResize = o.alsoResize[0]; _store(o.alsoResize); }
3105                         else { $.each(o.alsoResize, function (exp) { _store(exp); }); }
3106                 }else{
3107                         _store(o.alsoResize);
3108                 }
3109         },
3111         resize: function (event, ui) {
3112                 var that = $(this).data("ui-resizable"),
3113                         o = that.options,
3114                         os = that.originalSize,
3115                         op = that.originalPosition,
3116                         delta = {
3117                                 height: (that.size.height - os.height) || 0, width: (that.size.width - os.width) || 0,
3118                                 top: (that.position.top - op.top) || 0, left: (that.position.left - op.left) || 0
3119                         },
3121                         _alsoResize = function (exp, c) {
3122                                 $(exp).each(function() {
3123                                         var el = $(this), start = $(this).data("ui-resizable-alsoresize"), style = {},
3124                                                 css = c && c.length ? c : el.parents(ui.originalElement[0]).length ? ["width", "height"] : ["width", "height", "top", "left"];
3126                                         $.each(css, function (i, prop) {
3127                                                 var sum = (start[prop]||0) + (delta[prop]||0);
3128                                                 if (sum && sum >= 0) {
3129                                                         style[prop] = sum || null;
3130                                                 }
3131                                         });
3133                                         el.css(style);
3134                                 });
3135                         };
3137                 if (typeof(o.alsoResize) === "object" && !o.alsoResize.nodeType) {
3138                         $.each(o.alsoResize, function (exp, c) { _alsoResize(exp, c); });
3139                 }else{
3140                         _alsoResize(o.alsoResize);
3141                 }
3142         },
3144         stop: function () {
3145                 $(this).removeData("resizable-alsoresize");
3146         }
3149 $.ui.plugin.add("resizable", "ghost", {
3151         start: function() {
3153                 var that = $(this).data("ui-resizable"), o = that.options, cs = that.size;
3155                 that.ghost = that.originalElement.clone();
3156                 that.ghost
3157                         .css({ opacity: 0.25, display: "block", position: "relative", height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 })
3158                         .addClass("ui-resizable-ghost")
3159                         .addClass(typeof o.ghost === "string" ? o.ghost : "");
3161                 that.ghost.appendTo(that.helper);
3163         },
3165         resize: function(){
3166                 var that = $(this).data("ui-resizable");
3167                 if (that.ghost) {
3168                         that.ghost.css({ position: "relative", height: that.size.height, width: that.size.width });
3169                 }
3170         },
3172         stop: function() {
3173                 var that = $(this).data("ui-resizable");
3174                 if (that.ghost && that.helper) {
3175                         that.helper.get(0).removeChild(that.ghost.get(0));
3176                 }
3177         }
3181 $.ui.plugin.add("resizable", "grid", {
3183         resize: function() {
3184                 var that = $(this).data("ui-resizable"),
3185                         o = that.options,
3186                         cs = that.size,
3187                         os = that.originalSize,
3188                         op = that.originalPosition,
3189                         a = that.axis,
3190                         grid = typeof o.grid === "number" ? [o.grid, o.grid] : o.grid,
3191                         gridX = (grid[0]||1),
3192                         gridY = (grid[1]||1),
3193                         ox = Math.round((cs.width - os.width) / gridX) * gridX,
3194                         oy = Math.round((cs.height - os.height) / gridY) * gridY,
3195                         newWidth = os.width + ox,
3196                         newHeight = os.height + oy,
3197                         isMaxWidth = o.maxWidth && (o.maxWidth < newWidth),
3198                         isMaxHeight = o.maxHeight && (o.maxHeight < newHeight),
3199                         isMinWidth = o.minWidth && (o.minWidth > newWidth),
3200                         isMinHeight = o.minHeight && (o.minHeight > newHeight);
3202                 o.grid = grid;
3204                 if (isMinWidth) {
3205                         newWidth = newWidth + gridX;
3206                 }
3207                 if (isMinHeight) {
3208                         newHeight = newHeight + gridY;
3209                 }
3210                 if (isMaxWidth) {
3211                         newWidth = newWidth - gridX;
3212                 }
3213                 if (isMaxHeight) {
3214                         newHeight = newHeight - gridY;
3215                 }
3217                 if (/^(se|s|e)$/.test(a)) {
3218                         that.size.width = newWidth;
3219                         that.size.height = newHeight;
3220                 } else if (/^(ne)$/.test(a)) {
3221                         that.size.width = newWidth;
3222                         that.size.height = newHeight;
3223                         that.position.top = op.top - oy;
3224                 } else if (/^(sw)$/.test(a)) {
3225                         that.size.width = newWidth;
3226                         that.size.height = newHeight;
3227                         that.position.left = op.left - ox;
3228                 } else {
3229                         that.size.width = newWidth;
3230                         that.size.height = newHeight;
3231                         that.position.top = op.top - oy;
3232                         that.position.left = op.left - ox;
3233                 }
3234         }
3238 })(jQuery);
3240 (function( $, undefined ) {
3242 $.widget("ui.selectable", $.ui.mouse, {
3243         version: "1.10.3",
3244         options: {
3245                 appendTo: "body",
3246                 autoRefresh: true,
3247                 distance: 0,
3248                 filter: "*",
3249                 tolerance: "touch",
3251                 // callbacks
3252                 selected: null,
3253                 selecting: null,
3254                 start: null,
3255                 stop: null,
3256                 unselected: null,
3257                 unselecting: null
3258         },
3259         _create: function() {
3260                 var selectees,
3261                         that = this;
3263                 this.element.addClass("ui-selectable");
3265                 this.dragged = false;
3267                 // cache selectee children based on filter
3268                 this.refresh = function() {
3269                         selectees = $(that.options.filter, that.element[0]);
3270                         selectees.addClass("ui-selectee");
3271                         selectees.each(function() {
3272                                 var $this = $(this),
3273                                         pos = $this.offset();
3274                                 $.data(this, "selectable-item", {
3275                                         element: this,
3276                                         $element: $this,
3277                                         left: pos.left,
3278                                         top: pos.top,
3279                                         right: pos.left + $this.outerWidth(),
3280                                         bottom: pos.top + $this.outerHeight(),
3281                                         startselected: false,
3282                                         selected: $this.hasClass("ui-selected"),
3283                                         selecting: $this.hasClass("ui-selecting"),
3284                                         unselecting: $this.hasClass("ui-unselecting")
3285                                 });
3286                         });
3287                 };
3288                 this.refresh();
3290                 this.selectees = selectees.addClass("ui-selectee");
3292                 this._mouseInit();
3294                 this.helper = $("<div class='ui-selectable-helper'></div>");
3295         },
3297         _destroy: function() {
3298                 this.selectees
3299                         .removeClass("ui-selectee")
3300                         .removeData("selectable-item");
3301                 this.element
3302                         .removeClass("ui-selectable ui-selectable-disabled");
3303                 this._mouseDestroy();
3304         },
3306         _mouseStart: function(event) {
3307                 var that = this,
3308                         options = this.options;
3310                 this.opos = [event.pageX, event.pageY];
3312                 if (this.options.disabled) {
3313                         return;
3314                 }
3316                 this.selectees = $(options.filter, this.element[0]);
3318                 this._trigger("start", event);
3320                 $(options.appendTo).append(this.helper);
3321                 // position helper (lasso)
3322                 this.helper.css({
3323                         "left": event.pageX,
3324                         "top": event.pageY,
3325                         "width": 0,
3326                         "height": 0
3327                 });
3329                 if (options.autoRefresh) {
3330                         this.refresh();
3331                 }
3333                 this.selectees.filter(".ui-selected").each(function() {
3334                         var selectee = $.data(this, "selectable-item");
3335                         selectee.startselected = true;
3336                         if (!event.metaKey && !event.ctrlKey) {
3337                                 selectee.$element.removeClass("ui-selected");
3338                                 selectee.selected = false;
3339                                 selectee.$element.addClass("ui-unselecting");
3340                                 selectee.unselecting = true;
3341                                 // selectable UNSELECTING callback
3342                                 that._trigger("unselecting", event, {
3343                                         unselecting: selectee.element
3344                                 });
3345                         }
3346                 });
3348                 $(event.target).parents().addBack().each(function() {
3349                         var doSelect,
3350                                 selectee = $.data(this, "selectable-item");
3351                         if (selectee) {
3352                                 doSelect = (!event.metaKey && !event.ctrlKey) || !selectee.$element.hasClass("ui-selected");
3353                                 selectee.$element
3354                                         .removeClass(doSelect ? "ui-unselecting" : "ui-selected")
3355                                         .addClass(doSelect ? "ui-selecting" : "ui-unselecting");
3356                                 selectee.unselecting = !doSelect;
3357                                 selectee.selecting = doSelect;
3358                                 selectee.selected = doSelect;
3359                                 // selectable (UN)SELECTING callback
3360                                 if (doSelect) {
3361                                         that._trigger("selecting", event, {
3362                                                 selecting: selectee.element
3363                                         });
3364                                 } else {
3365                                         that._trigger("unselecting", event, {
3366                                                 unselecting: selectee.element
3367                                         });
3368                                 }
3369                                 return false;
3370                         }
3371                 });
3373         },
3375         _mouseDrag: function(event) {
3377                 this.dragged = true;
3379                 if (this.options.disabled) {
3380                         return;
3381                 }
3383                 var tmp,
3384                         that = this,
3385                         options = this.options,
3386                         x1 = this.opos[0],
3387                         y1 = this.opos[1],
3388                         x2 = event.pageX,
3389                         y2 = event.pageY;
3391                 if (x1 > x2) { tmp = x2; x2 = x1; x1 = tmp; }
3392                 if (y1 > y2) { tmp = y2; y2 = y1; y1 = tmp; }
3393                 this.helper.css({left: x1, top: y1, width: x2-x1, height: y2-y1});
3395                 this.selectees.each(function() {
3396                         var selectee = $.data(this, "selectable-item"),
3397                                 hit = false;
3399                         //prevent helper from being selected if appendTo: selectable
3400                         if (!selectee || selectee.element === that.element[0]) {
3401                                 return;
3402                         }
3404                         if (options.tolerance === "touch") {
3405                                 hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) );
3406                         } else if (options.tolerance === "fit") {
3407                                 hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2);
3408                         }
3410                         if (hit) {
3411                                 // SELECT
3412                                 if (selectee.selected) {
3413                                         selectee.$element.removeClass("ui-selected");
3414                                         selectee.selected = false;
3415                                 }
3416                                 if (selectee.unselecting) {
3417                                         selectee.$element.removeClass("ui-unselecting");
3418                                         selectee.unselecting = false;
3419                                 }
3420                                 if (!selectee.selecting) {
3421                                         selectee.$element.addClass("ui-selecting");
3422                                         selectee.selecting = true;
3423                                         // selectable SELECTING callback
3424                                         that._trigger("selecting", event, {
3425                                                 selecting: selectee.element
3426                                         });
3427                                 }
3428                         } else {
3429                                 // UNSELECT
3430                                 if (selectee.selecting) {
3431                                         if ((event.metaKey || event.ctrlKey) && selectee.startselected) {
3432                                                 selectee.$element.removeClass("ui-selecting");
3433                                                 selectee.selecting = false;
3434                                                 selectee.$element.addClass("ui-selected");
3435                                                 selectee.selected = true;
3436                                         } else {
3437                                                 selectee.$element.removeClass("ui-selecting");
3438                                                 selectee.selecting = false;
3439                                                 if (selectee.startselected) {
3440                                                         selectee.$element.addClass("ui-unselecting");
3441                                                         selectee.unselecting = true;
3442                                                 }
3443                                                 // selectable UNSELECTING callback
3444                                                 that._trigger("unselecting", event, {
3445                                                         unselecting: selectee.element
3446                                                 });
3447                                         }
3448                                 }
3449                                 if (selectee.selected) {
3450                                         if (!event.metaKey && !event.ctrlKey && !selectee.startselected) {
3451                                                 selectee.$element.removeClass("ui-selected");
3452                                                 selectee.selected = false;
3454                                                 selectee.$element.addClass("ui-unselecting");
3455                                                 selectee.unselecting = true;
3456                                                 // selectable UNSELECTING callback
3457                                                 that._trigger("unselecting", event, {
3458                                                         unselecting: selectee.element
3459                                                 });
3460                                         }
3461                                 }
3462                         }
3463                 });
3465                 return false;
3466         },
3468         _mouseStop: function(event) {
3469                 var that = this;
3471                 this.dragged = false;
3473                 $(".ui-unselecting", this.element[0]).each(function() {
3474                         var selectee = $.data(this, "selectable-item");
3475                         selectee.$element.removeClass("ui-unselecting");
3476                         selectee.unselecting = false;
3477                         selectee.startselected = false;
3478                         that._trigger("unselected", event, {
3479                                 unselected: selectee.element
3480                         });
3481                 });
3482                 $(".ui-selecting", this.element[0]).each(function() {
3483                         var selectee = $.data(this, "selectable-item");
3484                         selectee.$element.removeClass("ui-selecting").addClass("ui-selected");
3485                         selectee.selecting = false;
3486                         selectee.selected = true;
3487                         selectee.startselected = true;
3488                         that._trigger("selected", event, {
3489                                 selected: selectee.element
3490                         });
3491                 });
3492                 this._trigger("stop", event);
3494                 this.helper.remove();
3496                 return false;
3497         }
3501 })(jQuery);
3503 (function( $, undefined ) {
3505 /*jshint loopfunc: true */
3507 function isOverAxis( x, reference, size ) {
3508         return ( x > reference ) && ( x < ( reference + size ) );
3511 function isFloating(item) {
3512         return (/left|right/).test(item.css("float")) || (/inline|table-cell/).test(item.css("display"));
3515 $.widget("ui.sortable", $.ui.mouse, {
3516         version: "1.10.3",
3517         widgetEventPrefix: "sort",
3518         ready: false,
3519         options: {
3520                 appendTo: "parent",
3521                 axis: false,
3522                 connectWith: false,
3523                 containment: false,
3524                 cursor: "auto",
3525                 cursorAt: false,
3526                 dropOnEmpty: true,
3527                 forcePlaceholderSize: false,
3528                 forceHelperSize: false,
3529                 grid: false,
3530                 handle: false,
3531                 helper: "original",
3532                 items: "> *",
3533                 opacity: false,
3534                 placeholder: false,
3535                 revert: false,
3536                 scroll: true,
3537                 scrollSensitivity: 20,
3538                 scrollSpeed: 20,
3539                 scope: "default",
3540                 tolerance: "intersect",
3541                 zIndex: 1000,
3543                 // callbacks
3544                 activate: null,
3545                 beforeStop: null,
3546                 change: null,
3547                 deactivate: null,
3548                 out: null,
3549                 over: null,
3550                 receive: null,
3551                 remove: null,
3552                 sort: null,
3553                 start: null,
3554                 stop: null,
3555                 update: null
3556         },
3557         _create: function() {
3559                 var o = this.options;
3560                 this.containerCache = {};
3561                 this.element.addClass("ui-sortable");
3563                 //Get the items
3564                 this.refresh();
3566                 //Let's determine if the items are being displayed horizontally
3567                 this.floating = this.items.length ? o.axis === "x" || isFloating(this.items[0].item) : false;
3569                 //Let's determine the parent's offset
3570                 this.offset = this.element.offset();
3572                 //Initialize mouse events for interaction
3573                 this._mouseInit();
3575                 //We're ready to go
3576                 this.ready = true;
3578         },
3580         _destroy: function() {
3581                 this.element
3582                         .removeClass("ui-sortable ui-sortable-disabled");
3583                 this._mouseDestroy();
3585                 for ( var i = this.items.length - 1; i >= 0; i-- ) {
3586                         this.items[i].item.removeData(this.widgetName + "-item");
3587                 }
3589                 return this;
3590         },
3592         _setOption: function(key, value){
3593                 if ( key === "disabled" ) {
3594                         this.options[ key ] = value;
3596                         this.widget().toggleClass( "ui-sortable-disabled", !!value );
3597                 } else {
3598                         // Don't call widget base _setOption for disable as it adds ui-state-disabled class
3599                         $.Widget.prototype._setOption.apply(this, arguments);
3600                 }
3601         },
3603         _mouseCapture: function(event, overrideHandle) {
3604                 var currentItem = null,
3605                         validHandle = false,
3606                         that = this;
3608                 if (this.reverting) {
3609                         return false;
3610                 }
3612                 if(this.options.disabled || this.options.type === "static") {
3613                         return false;
3614                 }
3616                 //We have to refresh the items data once first
3617                 this._refreshItems(event);
3619                 //Find out if the clicked node (or one of its parents) is a actual item in this.items
3620                 $(event.target).parents().each(function() {
3621                         if($.data(this, that.widgetName + "-item") === that) {
3622                                 currentItem = $(this);
3623                                 return false;
3624                         }
3625                 });
3626                 if($.data(event.target, that.widgetName + "-item") === that) {
3627                         currentItem = $(event.target);
3628                 }
3630                 if(!currentItem) {
3631                         return false;
3632                 }
3633                 if(this.options.handle && !overrideHandle) {
3634                         $(this.options.handle, currentItem).find("*").addBack().each(function() {
3635                                 if(this === event.target) {
3636                                         validHandle = true;
3637                                 }
3638                         });
3639                         if(!validHandle) {
3640                                 return false;
3641                         }
3642                 }
3644                 this.currentItem = currentItem;
3645                 this._removeCurrentsFromItems();
3646                 return true;
3648         },
3650         _mouseStart: function(event, overrideHandle, noActivation) {
3652                 var i, body,
3653                         o = this.options;
3655                 this.currentContainer = this;
3657                 //We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture
3658                 this.refreshPositions();
3660                 //Create and append the visible helper
3661                 this.helper = this._createHelper(event);
3663                 //Cache the helper size
3664                 this._cacheHelperProportions();
3666                 /*
3667                  * - Position generation -
3668                  * This block generates everything position related - it's the core of draggables.
3669                  */
3671                 //Cache the margins of the original element
3672                 this._cacheMargins();
3674                 //Get the next scrolling parent
3675                 this.scrollParent = this.helper.scrollParent();
3677                 //The element's absolute position on the page minus margins
3678                 this.offset = this.currentItem.offset();
3679                 this.offset = {
3680                         top: this.offset.top - this.margins.top,
3681                         left: this.offset.left - this.margins.left
3682                 };
3684                 $.extend(this.offset, {
3685                         click: { //Where the click happened, relative to the element
3686                                 left: event.pageX - this.offset.left,
3687                                 top: event.pageY - this.offset.top
3688                         },
3689                         parent: this._getParentOffset(),
3690                         relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
3691                 });
3693                 // Only after we got the offset, we can change the helper's position to absolute
3694                 // TODO: Still need to figure out a way to make relative sorting possible
3695                 this.helper.css("position", "absolute");
3696                 this.cssPosition = this.helper.css("position");
3698                 //Generate the original position
3699                 this.originalPosition = this._generatePosition(event);
3700                 this.originalPageX = event.pageX;
3701                 this.originalPageY = event.pageY;
3703                 //Adjust the mouse offset relative to the helper if "cursorAt" is supplied
3704                 (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
3706                 //Cache the former DOM position
3707                 this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] };
3709                 //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
3710                 if(this.helper[0] !== this.currentItem[0]) {
3711                         this.currentItem.hide();
3712                 }
3714                 //Create the placeholder
3715                 this._createPlaceholder();
3717                 //Set a containment if given in the options
3718                 if(o.containment) {
3719                         this._setContainment();
3720                 }
3722                 if( o.cursor && o.cursor !== "auto" ) { // cursor option
3723                         body = this.document.find( "body" );
3725                         // support: IE
3726                         this.storedCursor = body.css( "cursor" );
3727                         body.css( "cursor", o.cursor );
3729                         this.storedStylesheet = $( "<style>*{ cursor: "+o.cursor+" !important; }</style>" ).appendTo( body );
3730                 }
3732                 if(o.opacity) { // opacity option
3733                         if (this.helper.css("opacity")) {
3734                                 this._storedOpacity = this.helper.css("opacity");
3735                         }
3736                         this.helper.css("opacity", o.opacity);
3737                 }
3739                 if(o.zIndex) { // zIndex option
3740                         if (this.helper.css("zIndex")) {
3741                                 this._storedZIndex = this.helper.css("zIndex");
3742                         }
3743                         this.helper.css("zIndex", o.zIndex);
3744                 }
3746                 //Prepare scrolling
3747                 if(this.scrollParent[0] !== document && this.scrollParent[0].tagName !== "HTML") {
3748                         this.overflowOffset = this.scrollParent.offset();
3749                 }
3751                 //Call callbacks
3752                 this._trigger("start", event, this._uiHash());
3754                 //Recache the helper size
3755                 if(!this._preserveHelperProportions) {
3756                         this._cacheHelperProportions();
3757                 }
3760                 //Post "activate" events to possible containers
3761                 if( !noActivation ) {
3762                         for ( i = this.containers.length - 1; i >= 0; i-- ) {
3763                                 this.containers[ i ]._trigger( "activate", event, this._uiHash( this ) );
3764                         }
3765                 }
3767                 //Prepare possible droppables
3768                 if($.ui.ddmanager) {
3769                         $.ui.ddmanager.current = this;
3770                 }
3772                 if ($.ui.ddmanager && !o.dropBehaviour) {
3773                         $.ui.ddmanager.prepareOffsets(this, event);
3774                 }
3776                 this.dragging = true;
3778                 this.helper.addClass("ui-sortable-helper");
3779                 this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position
3780                 return true;
3782         },
3784         _mouseDrag: function(event) {
3785                 var i, item, itemElement, intersection,
3786                         o = this.options,
3787                         scrolled = false;
3789                 //Compute the helpers position
3790                 this.position = this._generatePosition(event);
3791                 this.positionAbs = this._convertPositionTo("absolute");
3793                 if (!this.lastPositionAbs) {
3794                         this.lastPositionAbs = this.positionAbs;
3795                 }
3797                 //Do scrolling
3798                 if(this.options.scroll) {
3799                         if(this.scrollParent[0] !== document && this.scrollParent[0].tagName !== "HTML") {
3801                                 if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) {
3802                                         this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed;
3803                                 } else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity) {
3804                                         this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed;
3805                                 }
3807                                 if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) {
3808                                         this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed;
3809                                 } else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity) {
3810                                         this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed;
3811                                 }
3813                         } else {
3815                                 if(event.pageY - $(document).scrollTop() < o.scrollSensitivity) {
3816                                         scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
3817                                 } else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) {
3818                                         scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
3819                                 }
3821                                 if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity) {
3822                                         scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
3823                                 } else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) {
3824                                         scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
3825                                 }
3827                         }
3829                         if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) {
3830                                 $.ui.ddmanager.prepareOffsets(this, event);
3831                         }
3832                 }
3834                 //Regenerate the absolute position used for position checks
3835                 this.positionAbs = this._convertPositionTo("absolute");
3837                 //Set the helper position
3838                 if(!this.options.axis || this.options.axis !== "y") {
3839                         this.helper[0].style.left = this.position.left+"px";
3840                 }
3841                 if(!this.options.axis || this.options.axis !== "x") {
3842                         this.helper[0].style.top = this.position.top+"px";
3843                 }
3845                 //Rearrange
3846                 for (i = this.items.length - 1; i >= 0; i--) {
3848                         //Cache variables and intersection, continue if no intersection
3849                         item = this.items[i];
3850                         itemElement = item.item[0];
3851                         intersection = this._intersectsWithPointer(item);
3852                         if (!intersection) {
3853                                 continue;
3854                         }
3856                         // Only put the placeholder inside the current Container, skip all
3857                         // items form other containers. This works because when moving
3858                         // an item from one container to another the
3859                         // currentContainer is switched before the placeholder is moved.
3860                         //
3861                         // Without this moving items in "sub-sortables" can cause the placeholder to jitter
3862                         // beetween the outer and inner container.
3863                         if (item.instance !== this.currentContainer) {
3864                                 continue;
3865                         }
3867                         // cannot intersect with itself
3868                         // no useless actions that have been done before
3869                         // no action if the item moved is the parent of the item checked
3870                         if (itemElement !== this.currentItem[0] &&
3871                                 this.placeholder[intersection === 1 ? "next" : "prev"]()[0] !== itemElement &&
3872                                 !$.contains(this.placeholder[0], itemElement) &&
3873                                 (this.options.type === "semi-dynamic" ? !$.contains(this.element[0], itemElement) : true)
3874                         ) {
3876                                 this.direction = intersection === 1 ? "down" : "up";
3878                                 if (this.options.tolerance === "pointer" || this._intersectsWithSides(item)) {
3879                                         this._rearrange(event, item);
3880                                 } else {
3881                                         break;
3882                                 }
3884                                 this._trigger("change", event, this._uiHash());
3885                                 break;
3886                         }
3887                 }
3889                 //Post events to containers
3890                 this._contactContainers(event);
3892                 //Interconnect with droppables
3893                 if($.ui.ddmanager) {
3894                         $.ui.ddmanager.drag(this, event);
3895                 }
3897                 //Call callbacks
3898                 this._trigger("sort", event, this._uiHash());
3900                 this.lastPositionAbs = this.positionAbs;
3901                 return false;
3903         },
3905         _mouseStop: function(event, noPropagation) {
3907                 if(!event) {
3908                         return;
3909                 }
3911                 //If we are using droppables, inform the manager about the drop
3912                 if ($.ui.ddmanager && !this.options.dropBehaviour) {
3913                         $.ui.ddmanager.drop(this, event);
3914                 }
3916                 if(this.options.revert) {
3917                         var that = this,
3918                                 cur = this.placeholder.offset(),
3919                                 axis = this.options.axis,
3920                                 animation = {};
3922                         if ( !axis || axis === "x" ) {
3923                                 animation.left = cur.left - this.offset.parent.left - this.margins.left + (this.offsetParent[0] === document.body ? 0 : this.offsetParent[0].scrollLeft);
3924                         }
3925                         if ( !axis || axis === "y" ) {
3926                                 animation.top = cur.top - this.offset.parent.top - this.margins.top + (this.offsetParent[0] === document.body ? 0 : this.offsetParent[0].scrollTop);
3927                         }
3928                         this.reverting = true;
3929                         $(this.helper).animate( animation, parseInt(this.options.revert, 10) || 500, function() {
3930                                 that._clear(event);
3931                         });
3932                 } else {
3933                         this._clear(event, noPropagation);
3934                 }
3936                 return false;
3938         },
3940         cancel: function() {
3942                 if(this.dragging) {
3944                         this._mouseUp({ target: null });
3946                         if(this.options.helper === "original") {
3947                                 this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
3948                         } else {
3949                                 this.currentItem.show();
3950                         }
3952                         //Post deactivating events to containers
3953                         for (var i = this.containers.length - 1; i >= 0; i--){
3954                                 this.containers[i]._trigger("deactivate", null, this._uiHash(this));
3955                                 if(this.containers[i].containerCache.over) {
3956                                         this.containers[i]._trigger("out", null, this._uiHash(this));
3957                                         this.containers[i].containerCache.over = 0;
3958                                 }
3959                         }
3961                 }
3963                 if (this.placeholder) {
3964                         //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
3965                         if(this.placeholder[0].parentNode) {
3966                                 this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
3967                         }
3968                         if(this.options.helper !== "original" && this.helper && this.helper[0].parentNode) {
3969                                 this.helper.remove();
3970                         }
3972                         $.extend(this, {
3973                                 helper: null,
3974                                 dragging: false,
3975                                 reverting: false,
3976                                 _noFinalSort: null
3977                         });
3979                         if(this.domPosition.prev) {
3980                                 $(this.domPosition.prev).after(this.currentItem);
3981                         } else {
3982                                 $(this.domPosition.parent).prepend(this.currentItem);
3983                         }
3984                 }
3986                 return this;
3988         },
3990         serialize: function(o) {
3992                 var items = this._getItemsAsjQuery(o && o.connected),
3993                         str = [];
3994                 o = o || {};
3996                 $(items).each(function() {
3997                         var res = ($(o.item || this).attr(o.attribute || "id") || "").match(o.expression || (/(.+)[\-=_](.+)/));
3998                         if (res) {
3999                                 str.push((o.key || res[1]+"[]")+"="+(o.key && o.expression ? res[1] : res[2]));
4000                         }
4001                 });
4003                 if(!str.length && o.key) {
4004                         str.push(o.key + "=");
4005                 }
4007                 return str.join("&");
4009         },
4011         toArray: function(o) {
4013                 var items = this._getItemsAsjQuery(o && o.connected),
4014                         ret = [];
4016                 o = o || {};
4018                 items.each(function() { ret.push($(o.item || this).attr(o.attribute || "id") || ""); });
4019                 return ret;
4021         },
4023         /* Be careful with the following core functions */
4024         _intersectsWith: function(item) {
4026                 var x1 = this.positionAbs.left,
4027                         x2 = x1 + this.helperProportions.width,
4028                         y1 = this.positionAbs.top,
4029                         y2 = y1 + this.helperProportions.height,
4030                         l = item.left,
4031                         r = l + item.width,
4032                         t = item.top,
4033                         b = t + item.height,
4034                         dyClick = this.offset.click.top,
4035                         dxClick = this.offset.click.left,
4036                         isOverElementHeight = ( this.options.axis === "x" ) || ( ( y1 + dyClick ) > t && ( y1 + dyClick ) < b ),
4037                         isOverElementWidth = ( this.options.axis === "y" ) || ( ( x1 + dxClick ) > l && ( x1 + dxClick ) < r ),
4038                         isOverElement = isOverElementHeight && isOverElementWidth;
4040                 if ( this.options.tolerance === "pointer" ||
4041                         this.options.forcePointerForContainers ||
4042                         (this.options.tolerance !== "pointer" && this.helperProportions[this.floating ? "width" : "height"] > item[this.floating ? "width" : "height"])
4043                 ) {
4044                         return isOverElement;
4045                 } else {
4047                         return (l < x1 + (this.helperProportions.width / 2) && // Right Half
4048                                 x2 - (this.helperProportions.width / 2) < r && // Left Half
4049                                 t < y1 + (this.helperProportions.height / 2) && // Bottom Half
4050                                 y2 - (this.helperProportions.height / 2) < b ); // Top Half
4052                 }
4053         },
4055         _intersectsWithPointer: function(item) {
4057                 var isOverElementHeight = (this.options.axis === "x") || isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height),
4058                         isOverElementWidth = (this.options.axis === "y") || isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width),
4059                         isOverElement = isOverElementHeight && isOverElementWidth,
4060                         verticalDirection = this._getDragVerticalDirection(),
4061                         horizontalDirection = this._getDragHorizontalDirection();
4063                 if (!isOverElement) {
4064                         return false;
4065                 }
4067                 return this.floating ?
4068                         ( ((horizontalDirection && horizontalDirection === "right") || verticalDirection === "down") ? 2 : 1 )
4069                         : ( verticalDirection && (verticalDirection === "down" ? 2 : 1) );
4071         },
4073         _intersectsWithSides: function(item) {
4075                 var isOverBottomHalf = isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height),
4076                         isOverRightHalf = isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width),
4077                         verticalDirection = this._getDragVerticalDirection(),
4078                         horizontalDirection = this._getDragHorizontalDirection();
4080                 if (this.floating && horizontalDirection) {
4081                         return ((horizontalDirection === "right" && isOverRightHalf) || (horizontalDirection === "left" && !isOverRightHalf));
4082                 } else {
4083                         return verticalDirection && ((verticalDirection === "down" && isOverBottomHalf) || (verticalDirection === "up" && !isOverBottomHalf));
4084                 }
4086         },
4088         _getDragVerticalDirection: function() {
4089                 var delta = this.positionAbs.top - this.lastPositionAbs.top;
4090                 return delta !== 0 && (delta > 0 ? "down" : "up");
4091         },
4093         _getDragHorizontalDirection: function() {
4094                 var delta = this.positionAbs.left - this.lastPositionAbs.left;
4095                 return delta !== 0 && (delta > 0 ? "right" : "left");
4096         },
4098         refresh: function(event) {
4099                 this._refreshItems(event);
4100                 this.refreshPositions();
4101                 return this;
4102         },
4104         _connectWith: function() {
4105                 var options = this.options;
4106                 return options.connectWith.constructor === String ? [options.connectWith] : options.connectWith;
4107         },
4109         _getItemsAsjQuery: function(connected) {
4111                 var i, j, cur, inst,
4112                         items = [],
4113                         queries = [],
4114                         connectWith = this._connectWith();
4116                 if(connectWith && connected) {
4117                         for (i = connectWith.length - 1; i >= 0; i--){
4118                                 cur = $(connectWith[i]);
4119                                 for ( j = cur.length - 1; j >= 0; j--){
4120                                         inst = $.data(cur[j], this.widgetFullName);
4121                                         if(inst && inst !== this && !inst.options.disabled) {
4122                                                 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]);
4123                                         }
4124                                 }
4125                         }
4126                 }
4128                 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]);
4130                 for (i = queries.length - 1; i >= 0; i--){
4131                         queries[i][0].each(function() {
4132                                 items.push(this);
4133                         });
4134                 }
4136                 return $(items);
4138         },
4140         _removeCurrentsFromItems: function() {
4142                 var list = this.currentItem.find(":data(" + this.widgetName + "-item)");
4144                 this.items = $.grep(this.items, function (item) {
4145                         for (var j=0; j < list.length; j++) {
4146                                 if(list[j] === item.item[0]) {
4147                                         return false;
4148                                 }
4149                         }
4150                         return true;
4151                 });
4153         },
4155         _refreshItems: function(event) {
4157                 this.items = [];
4158                 this.containers = [this];
4160                 var i, j, cur, inst, targetData, _queries, item, queriesLength,
4161                         items = this.items,
4162                         queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]],
4163                         connectWith = this._connectWith();
4165                 if(connectWith && this.ready) { //Shouldn't be run the first time through due to massive slow-down
4166                         for (i = connectWith.length - 1; i >= 0; i--){
4167                                 cur = $(connectWith[i]);
4168                                 for (j = cur.length - 1; j >= 0; j--){
4169                                         inst = $.data(cur[j], this.widgetFullName);
4170                                         if(inst && inst !== this && !inst.options.disabled) {
4171                                                 queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]);
4172                                                 this.containers.push(inst);
4173                                         }
4174                                 }
4175                         }
4176                 }
4178                 for (i = queries.length - 1; i >= 0; i--) {
4179                         targetData = queries[i][1];
4180                         _queries = queries[i][0];
4182                         for (j=0, queriesLength = _queries.length; j < queriesLength; j++) {
4183                                 item = $(_queries[j]);
4185                                 item.data(this.widgetName + "-item", targetData); // Data for target checking (mouse manager)
4187                                 items.push({
4188                                         item: item,
4189                                         instance: targetData,
4190                                         width: 0, height: 0,
4191                                         left: 0, top: 0
4192                                 });
4193                         }
4194                 }
4196         },
4198         refreshPositions: function(fast) {
4200                 //This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change
4201                 if(this.offsetParent && this.helper) {
4202                         this.offset.parent = this._getParentOffset();
4203                 }
4205                 var i, item, t, p;
4207                 for (i = this.items.length - 1; i >= 0; i--){
4208                         item = this.items[i];
4210                         //We ignore calculating positions of all connected containers when we're not over them
4211                         if(item.instance !== this.currentContainer && this.currentContainer && item.item[0] !== this.currentItem[0]) {
4212                                 continue;
4213                         }
4215                         t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item;
4217                         if (!fast) {
4218                                 item.width = t.outerWidth();
4219                                 item.height = t.outerHeight();
4220                         }
4222                         p = t.offset();
4223                         item.left = p.left;
4224                         item.top = p.top;
4225                 }
4227                 if(this.options.custom && this.options.custom.refreshContainers) {
4228                         this.options.custom.refreshContainers.call(this);
4229                 } else {
4230                         for (i = this.containers.length - 1; i >= 0; i--){
4231                                 p = this.containers[i].element.offset();
4232                                 this.containers[i].containerCache.left = p.left;
4233                                 this.containers[i].containerCache.top = p.top;
4234                                 this.containers[i].containerCache.width = this.containers[i].element.outerWidth();
4235                                 this.containers[i].containerCache.height = this.containers[i].element.outerHeight();
4236                         }
4237                 }
4239                 return this;
4240         },
4242         _createPlaceholder: function(that) {
4243                 that = that || this;
4244                 var className,
4245                         o = that.options;
4247                 if(!o.placeholder || o.placeholder.constructor === String) {
4248                         className = o.placeholder;
4249                         o.placeholder = {
4250                                 element: function() {
4252                                         var nodeName = that.currentItem[0].nodeName.toLowerCase(),
4253                                                 element = $( "<" + nodeName + ">", that.document[0] )
4254                                                         .addClass(className || that.currentItem[0].className+" ui-sortable-placeholder")
4255                                                         .removeClass("ui-sortable-helper");
4257                                         if ( nodeName === "tr" ) {
4258                                                 that.currentItem.children().each(function() {
4259                                                         $( "<td>&#160;</td>", that.document[0] )
4260                                                                 .attr( "colspan", $( this ).attr( "colspan" ) || 1 )
4261                                                                 .appendTo( element );
4262                                                 });
4263                                         } else if ( nodeName === "img" ) {
4264                                                 element.attr( "src", that.currentItem.attr( "src" ) );
4265                                         }
4267                                         if ( !className ) {
4268                                                 element.css( "visibility", "hidden" );
4269                                         }
4271                                         return element;
4272                                 },
4273                                 update: function(container, p) {
4275                                         // 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that
4276                                         // 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified
4277                                         if(className && !o.forcePlaceholderSize) {
4278                                                 return;
4279                                         }
4281                                         //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
4282                                         if(!p.height()) { p.height(that.currentItem.innerHeight() - parseInt(that.currentItem.css("paddingTop")||0, 10) - parseInt(that.currentItem.css("paddingBottom")||0, 10)); }
4283                                         if(!p.width()) { p.width(that.currentItem.innerWidth() - parseInt(that.currentItem.css("paddingLeft")||0, 10) - parseInt(that.currentItem.css("paddingRight")||0, 10)); }
4284                                 }
4285                         };
4286                 }
4288                 //Create the placeholder
4289                 that.placeholder = $(o.placeholder.element.call(that.element, that.currentItem));
4291                 //Append it after the actual current item
4292                 that.currentItem.after(that.placeholder);
4294                 //Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
4295                 o.placeholder.update(that, that.placeholder);
4297         },
4299         _contactContainers: function(event) {
4300                 var i, j, dist, itemWithLeastDistance, posProperty, sizeProperty, base, cur, nearBottom, floating,
4301                         innermostContainer = null,
4302                         innermostIndex = null;
4304                 // get innermost container that intersects with item
4305                 for (i = this.containers.length - 1; i >= 0; i--) {
4307                         // never consider a container that's located within the item itself
4308                         if($.contains(this.currentItem[0], this.containers[i].element[0])) {
4309                                 continue;
4310                         }
4312                         if(this._intersectsWith(this.containers[i].containerCache)) {
4314                                 // if we've already found a container and it's more "inner" than this, then continue
4315                                 if(innermostContainer && $.contains(this.containers[i].element[0], innermostContainer.element[0])) {
4316                                         continue;
4317                                 }
4319                                 innermostContainer = this.containers[i];
4320                                 innermostIndex = i;
4322                         } else {
4323                                 // container doesn't intersect. trigger "out" event if necessary
4324                                 if(this.containers[i].containerCache.over) {
4325                                         this.containers[i]._trigger("out", event, this._uiHash(this));
4326                                         this.containers[i].containerCache.over = 0;
4327                                 }
4328                         }
4330                 }
4332                 // if no intersecting containers found, return
4333                 if(!innermostContainer) {
4334                         return;
4335                 }
4337                 // move the item into the container if it's not there already
4338                 if(this.containers.length === 1) {
4339                         if (!this.containers[innermostIndex].containerCache.over) {
4340                                 this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
4341                                 this.containers[innermostIndex].containerCache.over = 1;
4342                         }
4343                 } else {
4345                         //When entering a new container, we will find the item with the least distance and append our item near it
4346                         dist = 10000;
4347                         itemWithLeastDistance = null;
4348                         floating = innermostContainer.floating || isFloating(this.currentItem);
4349                         posProperty = floating ? "left" : "top";
4350                         sizeProperty = floating ? "width" : "height";
4351                         base = this.positionAbs[posProperty] + this.offset.click[posProperty];
4352                         for (j = this.items.length - 1; j >= 0; j--) {
4353                                 if(!$.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) {
4354                                         continue;
4355                                 }
4356                                 if(this.items[j].item[0] === this.currentItem[0]) {
4357                                         continue;
4358                                 }
4359                                 if (floating && !isOverAxis(this.positionAbs.top + this.offset.click.top, this.items[j].top, this.items[j].height)) {
4360                                         continue;
4361                                 }
4362                                 cur = this.items[j].item.offset()[posProperty];
4363                                 nearBottom = false;
4364                                 if(Math.abs(cur - base) > Math.abs(cur + this.items[j][sizeProperty] - base)){
4365                                         nearBottom = true;
4366                                         cur += this.items[j][sizeProperty];
4367                                 }
4369                                 if(Math.abs(cur - base) < dist) {
4370                                         dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j];
4371                                         this.direction = nearBottom ? "up": "down";
4372                                 }
4373                         }
4375                         //Check if dropOnEmpty is enabled
4376                         if(!itemWithLeastDistance && !this.options.dropOnEmpty) {
4377                                 return;
4378                         }
4380                         if(this.currentContainer === this.containers[innermostIndex]) {
4381                                 return;
4382                         }
4384                         itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true);
4385                         this._trigger("change", event, this._uiHash());
4386                         this.containers[innermostIndex]._trigger("change", event, this._uiHash(this));
4387                         this.currentContainer = this.containers[innermostIndex];
4389                         //Update the placeholder
4390                         this.options.placeholder.update(this.currentContainer, this.placeholder);
4392                         this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
4393                         this.containers[innermostIndex].containerCache.over = 1;
4394                 }
4397         },
4399         _createHelper: function(event) {
4401                 var o = this.options,
4402                         helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper === "clone" ? this.currentItem.clone() : this.currentItem);
4404                 //Add the helper to the DOM if that didn't happen already
4405                 if(!helper.parents("body").length) {
4406                         $(o.appendTo !== "parent" ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]);
4407                 }
4409                 if(helper[0] === this.currentItem[0]) {
4410                         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") };
4411                 }
4413                 if(!helper[0].style.width || o.forceHelperSize) {
4414                         helper.width(this.currentItem.width());
4415                 }
4416                 if(!helper[0].style.height || o.forceHelperSize) {
4417                         helper.height(this.currentItem.height());
4418                 }
4420                 return helper;
4422         },
4424         _adjustOffsetFromHelper: function(obj) {
4425                 if (typeof obj === "string") {
4426                         obj = obj.split(" ");
4427                 }
4428                 if ($.isArray(obj)) {
4429                         obj = {left: +obj[0], top: +obj[1] || 0};
4430                 }
4431                 if ("left" in obj) {
4432                         this.offset.click.left = obj.left + this.margins.left;
4433                 }
4434                 if ("right" in obj) {
4435                         this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
4436                 }
4437                 if ("top" in obj) {
4438                         this.offset.click.top = obj.top + this.margins.top;
4439                 }
4440                 if ("bottom" in obj) {
4441                         this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
4442                 }
4443         },
4445         _getParentOffset: function() {
4448                 //Get the offsetParent and cache its position
4449                 this.offsetParent = this.helper.offsetParent();
4450                 var po = this.offsetParent.offset();
4452                 // This is a special case where we need to modify a offset calculated on start, since the following happened:
4453                 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
4454                 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
4455                 //    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
4456                 if(this.cssPosition === "absolute" && this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) {
4457                         po.left += this.scrollParent.scrollLeft();
4458                         po.top += this.scrollParent.scrollTop();
4459                 }
4461                 // This needs to be actually done for all browsers, since pageX/pageY includes this information
4462                 // with an ugly IE fix
4463                 if( this.offsetParent[0] === document.body || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() === "html" && $.ui.ie)) {
4464                         po = { top: 0, left: 0 };
4465                 }
4467                 return {
4468                         top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
4469                         left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
4470                 };
4472         },
4474         _getRelativeOffset: function() {
4476                 if(this.cssPosition === "relative") {
4477                         var p = this.currentItem.position();
4478                         return {
4479                                 top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
4480                                 left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
4481                         };
4482                 } else {
4483                         return { top: 0, left: 0 };
4484                 }
4486         },
4488         _cacheMargins: function() {
4489                 this.margins = {
4490                         left: (parseInt(this.currentItem.css("marginLeft"),10) || 0),
4491                         top: (parseInt(this.currentItem.css("marginTop"),10) || 0)
4492                 };
4493         },
4495         _cacheHelperProportions: function() {
4496                 this.helperProportions = {
4497                         width: this.helper.outerWidth(),
4498                         height: this.helper.outerHeight()
4499                 };
4500         },
4502         _setContainment: function() {
4504                 var ce, co, over,
4505                         o = this.options;
4506                 if(o.containment === "parent") {
4507                         o.containment = this.helper[0].parentNode;
4508                 }
4509                 if(o.containment === "document" || o.containment === "window") {
4510                         this.containment = [
4511                                 0 - this.offset.relative.left - this.offset.parent.left,
4512                                 0 - this.offset.relative.top - this.offset.parent.top,
4513                                 $(o.containment === "document" ? document : window).width() - this.helperProportions.width - this.margins.left,
4514                                 ($(o.containment === "document" ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
4515                         ];
4516                 }
4518                 if(!(/^(document|window|parent)$/).test(o.containment)) {
4519                         ce = $(o.containment)[0];
4520                         co = $(o.containment).offset();
4521                         over = ($(ce).css("overflow") !== "hidden");
4523                         this.containment = [
4524                                 co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
4525                                 co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
4526                                 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,
4527                                 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
4528                         ];
4529                 }
4531         },
4533         _convertPositionTo: function(d, pos) {
4535                 if(!pos) {
4536                         pos = this.position;
4537                 }
4538                 var mod = d === "absolute" ? 1 : -1,
4539                         scroll = this.cssPosition === "absolute" && !(this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent,
4540                         scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
4542                 return {
4543                         top: (
4544                                 pos.top +                                                                                                                               // The absolute mouse position
4545                                 this.offset.relative.top * mod +                                                                                // Only for relative positioned nodes: Relative offset from element to offset parent
4546                                 this.offset.parent.top * mod -                                                                                  // The offsetParent's offset without borders (offset + border)
4547                                 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
4548                         ),
4549                         left: (
4550                                 pos.left +                                                                                                                              // The absolute mouse position
4551                                 this.offset.relative.left * mod +                                                                               // Only for relative positioned nodes: Relative offset from element to offset parent
4552                                 this.offset.parent.left * mod   -                                                                               // The offsetParent's offset without borders (offset + border)
4553                                 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
4554                         )
4555                 };
4557         },
4559         _generatePosition: function(event) {
4561                 var top, left,
4562                         o = this.options,
4563                         pageX = event.pageX,
4564                         pageY = event.pageY,
4565                         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);
4567                 // This is another very weird special case that only happens for relative elements:
4568                 // 1. If the css position is relative
4569                 // 2. and the scroll parent is the document or similar to the offset parent
4570                 // we have to refresh the relative offset during the scroll so there are no jumps
4571                 if(this.cssPosition === "relative" && !(this.scrollParent[0] !== document && this.scrollParent[0] !== this.offsetParent[0])) {
4572                         this.offset.relative = this._getRelativeOffset();
4573                 }
4575                 /*
4576                  * - Position constraining -
4577                  * Constrain the position to a mix of grid, containment.
4578                  */
4580                 if(this.originalPosition) { //If we are not dragging yet, we won't check for options
4582                         if(this.containment) {
4583                                 if(event.pageX - this.offset.click.left < this.containment[0]) {
4584                                         pageX = this.containment[0] + this.offset.click.left;
4585                                 }
4586                                 if(event.pageY - this.offset.click.top < this.containment[1]) {
4587                                         pageY = this.containment[1] + this.offset.click.top;
4588                                 }
4589                                 if(event.pageX - this.offset.click.left > this.containment[2]) {
4590                                         pageX = this.containment[2] + this.offset.click.left;
4591                                 }
4592                                 if(event.pageY - this.offset.click.top > this.containment[3]) {
4593                                         pageY = this.containment[3] + this.offset.click.top;
4594                                 }
4595                         }
4597                         if(o.grid) {
4598                                 top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
4599                                 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;
4601                                 left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
4602                                 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;
4603                         }
4605                 }
4607                 return {
4608                         top: (
4609                                 pageY -                                                                                                                         // The absolute mouse position
4610                                 this.offset.click.top -                                                                                                 // Click offset (relative to the element)
4611                                 this.offset.relative.top        -                                                                                       // Only for relative positioned nodes: Relative offset from element to offset parent
4612                                 this.offset.parent.top +                                                                                                // The offsetParent's offset without borders (offset + border)
4613                                 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
4614                         ),
4615                         left: (
4616                                 pageX -                                                                                                                         // The absolute mouse position
4617                                 this.offset.click.left -                                                                                                // Click offset (relative to the element)
4618                                 this.offset.relative.left       -                                                                                       // Only for relative positioned nodes: Relative offset from element to offset parent
4619                                 this.offset.parent.left +                                                                                               // The offsetParent's offset without borders (offset + border)
4620                                 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
4621                         )
4622                 };
4624         },
4626         _rearrange: function(event, i, a, hardRefresh) {
4628                 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));
4630                 //Various things done here to improve the performance:
4631                 // 1. we create a setTimeout, that calls refreshPositions
4632                 // 2. on the instance, we have a counter variable, that get's higher after every append
4633                 // 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same
4634                 // 4. this lets only the last addition to the timeout stack through
4635                 this.counter = this.counter ? ++this.counter : 1;
4636                 var counter = this.counter;
4638                 this._delay(function() {
4639                         if(counter === this.counter) {
4640                                 this.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove
4641                         }
4642                 });
4644         },
4646         _clear: function(event, noPropagation) {
4648                 this.reverting = false;
4649                 // We delay all events that have to be triggered to after the point where the placeholder has been removed and
4650                 // everything else normalized again
4651                 var i,
4652                         delayedTriggers = [];
4654                 // We first have to update the dom position of the actual currentItem
4655                 // Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088)
4656                 if(!this._noFinalSort && this.currentItem.parent().length) {
4657                         this.placeholder.before(this.currentItem);
4658                 }
4659                 this._noFinalSort = null;
4661                 if(this.helper[0] === this.currentItem[0]) {
4662                         for(i in this._storedCSS) {
4663                                 if(this._storedCSS[i] === "auto" || this._storedCSS[i] === "static") {
4664                                         this._storedCSS[i] = "";
4665                                 }
4666                         }
4667                         this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
4668                 } else {
4669                         this.currentItem.show();
4670                 }
4672                 if(this.fromOutside && !noPropagation) {
4673                         delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); });
4674                 }
4675                 if((this.fromOutside || this.domPosition.prev !== this.currentItem.prev().not(".ui-sortable-helper")[0] || this.domPosition.parent !== this.currentItem.parent()[0]) && !noPropagation) {
4676                         delayedTriggers.push(function(event) { this._trigger("update", event, this._uiHash()); }); //Trigger update callback if the DOM position has changed
4677                 }
4679                 // Check if the items Container has Changed and trigger appropriate
4680                 // events.
4681                 if (this !== this.currentContainer) {
4682                         if(!noPropagation) {
4683                                 delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); });
4684                                 delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); };  }).call(this, this.currentContainer));
4685                                 delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this));  }; }).call(this, this.currentContainer));
4686                         }
4687                 }
4690                 //Post events to containers
4691                 for (i = this.containers.length - 1; i >= 0; i--){
4692                         if(!noPropagation) {
4693                                 delayedTriggers.push((function(c) { return function(event) { c._trigger("deactivate", event, this._uiHash(this)); };  }).call(this, this.containers[i]));
4694                         }
4695                         if(this.containers[i].containerCache.over) {
4696                                 delayedTriggers.push((function(c) { return function(event) { c._trigger("out", event, this._uiHash(this)); };  }).call(this, this.containers[i]));
4697                                 this.containers[i].containerCache.over = 0;
4698                         }
4699                 }
4701                 //Do what was originally in plugins
4702                 if ( this.storedCursor ) {
4703                         this.document.find( "body" ).css( "cursor", this.storedCursor );
4704                         this.storedStylesheet.remove();
4705                 }
4706                 if(this._storedOpacity) {
4707                         this.helper.css("opacity", this._storedOpacity);
4708                 }
4709                 if(this._storedZIndex) {
4710                         this.helper.css("zIndex", this._storedZIndex === "auto" ? "" : this._storedZIndex);
4711                 }
4713                 this.dragging = false;
4714                 if(this.cancelHelperRemoval) {
4715                         if(!noPropagation) {
4716                                 this._trigger("beforeStop", event, this._uiHash());
4717                                 for (i=0; i < delayedTriggers.length; i++) {
4718                                         delayedTriggers[i].call(this, event);
4719                                 } //Trigger all delayed events
4720                                 this._trigger("stop", event, this._uiHash());
4721                         }
4723                         this.fromOutside = false;
4724                         return false;
4725                 }
4727                 if(!noPropagation) {
4728                         this._trigger("beforeStop", event, this._uiHash());
4729                 }
4731                 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
4732                 this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
4734                 if(this.helper[0] !== this.currentItem[0]) {
4735                         this.helper.remove();
4736                 }
4737                 this.helper = null;
4739                 if(!noPropagation) {
4740                         for (i=0; i < delayedTriggers.length; i++) {
4741                                 delayedTriggers[i].call(this, event);
4742                         } //Trigger all delayed events
4743                         this._trigger("stop", event, this._uiHash());
4744                 }
4746                 this.fromOutside = false;
4747                 return true;
4749         },
4751         _trigger: function() {
4752                 if ($.Widget.prototype._trigger.apply(this, arguments) === false) {
4753                         this.cancel();
4754                 }
4755         },
4757         _uiHash: function(_inst) {
4758                 var inst = _inst || this;
4759                 return {
4760                         helper: inst.helper,
4761                         placeholder: inst.placeholder || $([]),
4762                         position: inst.position,
4763                         originalPosition: inst.originalPosition,
4764                         offset: inst.positionAbs,
4765                         item: inst.currentItem,
4766                         sender: _inst ? _inst.element : null
4767                 };
4768         }
4772 })(jQuery);
4774 (function($, undefined) {
4776 var dataSpace = "ui-effects-";
4778 $.effects = {
4779         effect: {}
4783  * jQuery Color Animations v2.1.2
4784  * https://github.com/jquery/jquery-color
4786  * Copyright 2013 jQuery Foundation and other contributors
4787  * Released under the MIT license.
4788  * http://jquery.org/license
4790  * Date: Wed Jan 16 08:47:09 2013 -0600
4791  */
4792 (function( jQuery, undefined ) {
4794         var stepHooks = "backgroundColor borderBottomColor borderLeftColor borderRightColor borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor",
4796         // plusequals test for += 100 -= 100
4797         rplusequals = /^([\-+])=\s*(\d+\.?\d*)/,
4798         // a set of RE's that can match strings and generate color tuples.
4799         stringParsers = [{
4800                         re: /rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
4801                         parse: function( execResult ) {
4802                                 return [
4803                                         execResult[ 1 ],
4804                                         execResult[ 2 ],
4805                                         execResult[ 3 ],
4806                                         execResult[ 4 ]
4807                                 ];
4808                         }
4809                 }, {
4810                         re: /rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
4811                         parse: function( execResult ) {
4812                                 return [
4813                                         execResult[ 1 ] * 2.55,
4814                                         execResult[ 2 ] * 2.55,
4815                                         execResult[ 3 ] * 2.55,
4816                                         execResult[ 4 ]
4817                                 ];
4818                         }
4819                 }, {
4820                         // this regex ignores A-F because it's compared against an already lowercased string
4821                         re: /#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/,
4822                         parse: function( execResult ) {
4823                                 return [
4824                                         parseInt( execResult[ 1 ], 16 ),
4825                                         parseInt( execResult[ 2 ], 16 ),
4826                                         parseInt( execResult[ 3 ], 16 )
4827                                 ];
4828                         }
4829                 }, {
4830                         // this regex ignores A-F because it's compared against an already lowercased string
4831                         re: /#([a-f0-9])([a-f0-9])([a-f0-9])/,
4832                         parse: function( execResult ) {
4833                                 return [
4834                                         parseInt( execResult[ 1 ] + execResult[ 1 ], 16 ),
4835                                         parseInt( execResult[ 2 ] + execResult[ 2 ], 16 ),
4836                                         parseInt( execResult[ 3 ] + execResult[ 3 ], 16 )
4837                                 ];
4838                         }
4839                 }, {
4840                         re: /hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
4841                         space: "hsla",
4842                         parse: function( execResult ) {
4843                                 return [
4844                                         execResult[ 1 ],
4845                                         execResult[ 2 ] / 100,
4846                                         execResult[ 3 ] / 100,
4847                                         execResult[ 4 ]
4848                                 ];
4849                         }
4850                 }],
4852         // jQuery.Color( )
4853         color = jQuery.Color = function( color, green, blue, alpha ) {
4854                 return new jQuery.Color.fn.parse( color, green, blue, alpha );
4855         },
4856         spaces = {
4857                 rgba: {
4858                         props: {
4859                                 red: {
4860                                         idx: 0,
4861                                         type: "byte"
4862                                 },
4863                                 green: {
4864                                         idx: 1,
4865                                         type: "byte"
4866                                 },
4867                                 blue: {
4868                                         idx: 2,
4869                                         type: "byte"
4870                                 }
4871                         }
4872                 },
4874                 hsla: {
4875                         props: {
4876                                 hue: {
4877                                         idx: 0,
4878                                         type: "degrees"
4879                                 },
4880                                 saturation: {
4881                                         idx: 1,
4882                                         type: "percent"
4883                                 },
4884                                 lightness: {
4885                                         idx: 2,
4886                                         type: "percent"
4887                                 }
4888                         }
4889                 }
4890         },
4891         propTypes = {
4892                 "byte": {
4893                         floor: true,
4894                         max: 255
4895                 },
4896                 "percent": {
4897                         max: 1
4898                 },
4899                 "degrees": {
4900                         mod: 360,
4901                         floor: true
4902                 }
4903         },
4904         support = color.support = {},
4906         // element for support tests
4907         supportElem = jQuery( "<p>" )[ 0 ],
4909         // colors = jQuery.Color.names
4910         colors,
4912         // local aliases of functions called often
4913         each = jQuery.each;
4915 // determine rgba support immediately
4916 supportElem.style.cssText = "background-color:rgba(1,1,1,.5)";
4917 support.rgba = supportElem.style.backgroundColor.indexOf( "rgba" ) > -1;
4919 // define cache name and alpha properties
4920 // for rgba and hsla spaces
4921 each( spaces, function( spaceName, space ) {
4922         space.cache = "_" + spaceName;
4923         space.props.alpha = {
4924                 idx: 3,
4925                 type: "percent",
4926                 def: 1
4927         };
4930 function clamp( value, prop, allowEmpty ) {
4931         var type = propTypes[ prop.type ] || {};
4933         if ( value == null ) {
4934                 return (allowEmpty || !prop.def) ? null : prop.def;
4935         }
4937         // ~~ is an short way of doing floor for positive numbers
4938         value = type.floor ? ~~value : parseFloat( value );
4940         // IE will pass in empty strings as value for alpha,
4941         // which will hit this case
4942         if ( isNaN( value ) ) {
4943                 return prop.def;
4944         }
4946         if ( type.mod ) {
4947                 // we add mod before modding to make sure that negatives values
4948                 // get converted properly: -10 -> 350
4949                 return (value + type.mod) % type.mod;
4950         }
4952         // for now all property types without mod have min and max
4953         return 0 > value ? 0 : type.max < value ? type.max : value;
4956 function stringParse( string ) {
4957         var inst = color(),
4958                 rgba = inst._rgba = [];
4960         string = string.toLowerCase();
4962         each( stringParsers, function( i, parser ) {
4963                 var parsed,
4964                         match = parser.re.exec( string ),
4965                         values = match && parser.parse( match ),
4966                         spaceName = parser.space || "rgba";
4968                 if ( values ) {
4969                         parsed = inst[ spaceName ]( values );
4971                         // if this was an rgba parse the assignment might happen twice
4972                         // oh well....
4973                         inst[ spaces[ spaceName ].cache ] = parsed[ spaces[ spaceName ].cache ];
4974                         rgba = inst._rgba = parsed._rgba;
4976                         // exit each( stringParsers ) here because we matched
4977                         return false;
4978                 }
4979         });
4981         // Found a stringParser that handled it
4982         if ( rgba.length ) {
4984                 // if this came from a parsed string, force "transparent" when alpha is 0
4985                 // chrome, (and maybe others) return "transparent" as rgba(0,0,0,0)
4986                 if ( rgba.join() === "0,0,0,0" ) {
4987                         jQuery.extend( rgba, colors.transparent );
4988                 }
4989                 return inst;
4990         }
4992         // named colors
4993         return colors[ string ];
4996 color.fn = jQuery.extend( color.prototype, {
4997         parse: function( red, green, blue, alpha ) {
4998                 if ( red === undefined ) {
4999                         this._rgba = [ null, null, null, null ];
5000                         return this;
5001                 }
5002                 if ( red.jquery || red.nodeType ) {
5003                         red = jQuery( red ).css( green );
5004                         green = undefined;
5005                 }
5007                 var inst = this,
5008                         type = jQuery.type( red ),
5009                         rgba = this._rgba = [];
5011                 // more than 1 argument specified - assume ( red, green, blue, alpha )
5012                 if ( green !== undefined ) {
5013                         red = [ red, green, blue, alpha ];
5014                         type = "array";
5015                 }
5017                 if ( type === "string" ) {
5018                         return this.parse( stringParse( red ) || colors._default );
5019                 }
5021                 if ( type === "array" ) {
5022                         each( spaces.rgba.props, function( key, prop ) {
5023                                 rgba[ prop.idx ] = clamp( red[ prop.idx ], prop );
5024                         });
5025                         return this;
5026                 }
5028                 if ( type === "object" ) {
5029                         if ( red instanceof color ) {
5030                                 each( spaces, function( spaceName, space ) {
5031                                         if ( red[ space.cache ] ) {
5032                                                 inst[ space.cache ] = red[ space.cache ].slice();
5033                                         }
5034                                 });
5035                         } else {
5036                                 each( spaces, function( spaceName, space ) {
5037                                         var cache = space.cache;
5038                                         each( space.props, function( key, prop ) {
5040                                                 // if the cache doesn't exist, and we know how to convert
5041                                                 if ( !inst[ cache ] && space.to ) {
5043                                                         // if the value was null, we don't need to copy it
5044                                                         // if the key was alpha, we don't need to copy it either
5045                                                         if ( key === "alpha" || red[ key ] == null ) {
5046                                                                 return;
5047                                                         }
5048                                                         inst[ cache ] = space.to( inst._rgba );
5049                                                 }
5051                                                 // this is the only case where we allow nulls for ALL properties.
5052                                                 // call clamp with alwaysAllowEmpty
5053                                                 inst[ cache ][ prop.idx ] = clamp( red[ key ], prop, true );
5054                                         });
5056                                         // everything defined but alpha?
5057                                         if ( inst[ cache ] && jQuery.inArray( null, inst[ cache ].slice( 0, 3 ) ) < 0 ) {
5058                                                 // use the default of 1
5059                                                 inst[ cache ][ 3 ] = 1;
5060                                                 if ( space.from ) {
5061                                                         inst._rgba = space.from( inst[ cache ] );
5062                                                 }
5063                                         }
5064                                 });
5065                         }
5066                         return this;
5067                 }
5068         },
5069         is: function( compare ) {
5070                 var is = color( compare ),
5071                         same = true,
5072                         inst = this;
5074                 each( spaces, function( _, space ) {
5075                         var localCache,
5076                                 isCache = is[ space.cache ];
5077                         if (isCache) {
5078                                 localCache = inst[ space.cache ] || space.to && space.to( inst._rgba ) || [];
5079                                 each( space.props, function( _, prop ) {
5080                                         if ( isCache[ prop.idx ] != null ) {
5081                                                 same = ( isCache[ prop.idx ] === localCache[ prop.idx ] );
5082                                                 return same;
5083                                         }
5084                                 });
5085                         }
5086                         return same;
5087                 });
5088                 return same;
5089         },
5090         _space: function() {
5091                 var used = [],
5092                         inst = this;
5093                 each( spaces, function( spaceName, space ) {
5094                         if ( inst[ space.cache ] ) {
5095                                 used.push( spaceName );
5096                         }
5097                 });
5098                 return used.pop();
5099         },
5100         transition: function( other, distance ) {
5101                 var end = color( other ),
5102                         spaceName = end._space(),
5103                         space = spaces[ spaceName ],
5104                         startColor = this.alpha() === 0 ? color( "transparent" ) : this,
5105                         start = startColor[ space.cache ] || space.to( startColor._rgba ),
5106                         result = start.slice();
5108                 end = end[ space.cache ];
5109                 each( space.props, function( key, prop ) {
5110                         var index = prop.idx,
5111                                 startValue = start[ index ],
5112                                 endValue = end[ index ],
5113                                 type = propTypes[ prop.type ] || {};
5115                         // if null, don't override start value
5116                         if ( endValue === null ) {
5117                                 return;
5118                         }
5119                         // if null - use end
5120                         if ( startValue === null ) {
5121                                 result[ index ] = endValue;
5122                         } else {
5123                                 if ( type.mod ) {
5124                                         if ( endValue - startValue > type.mod / 2 ) {
5125                                                 startValue += type.mod;
5126                                         } else if ( startValue - endValue > type.mod / 2 ) {
5127                                                 startValue -= type.mod;
5128                                         }
5129                                 }
5130                                 result[ index ] = clamp( ( endValue - startValue ) * distance + startValue, prop );
5131                         }
5132                 });
5133                 return this[ spaceName ]( result );
5134         },
5135         blend: function( opaque ) {
5136                 // if we are already opaque - return ourself
5137                 if ( this._rgba[ 3 ] === 1 ) {
5138                         return this;
5139                 }
5141                 var rgb = this._rgba.slice(),
5142                         a = rgb.pop(),
5143                         blend = color( opaque )._rgba;
5145                 return color( jQuery.map( rgb, function( v, i ) {
5146                         return ( 1 - a ) * blend[ i ] + a * v;
5147                 }));
5148         },
5149         toRgbaString: function() {
5150                 var prefix = "rgba(",
5151                         rgba = jQuery.map( this._rgba, function( v, i ) {
5152                                 return v == null ? ( i > 2 ? 1 : 0 ) : v;
5153                         });
5155                 if ( rgba[ 3 ] === 1 ) {
5156                         rgba.pop();
5157                         prefix = "rgb(";
5158                 }
5160                 return prefix + rgba.join() + ")";
5161         },
5162         toHslaString: function() {
5163                 var prefix = "hsla(",
5164                         hsla = jQuery.map( this.hsla(), function( v, i ) {
5165                                 if ( v == null ) {
5166                                         v = i > 2 ? 1 : 0;
5167                                 }
5169                                 // catch 1 and 2
5170                                 if ( i && i < 3 ) {
5171                                         v = Math.round( v * 100 ) + "%";
5172                                 }
5173                                 return v;
5174                         });
5176                 if ( hsla[ 3 ] === 1 ) {
5177                         hsla.pop();
5178                         prefix = "hsl(";
5179                 }
5180                 return prefix + hsla.join() + ")";
5181         },
5182         toHexString: function( includeAlpha ) {
5183                 var rgba = this._rgba.slice(),
5184                         alpha = rgba.pop();
5186                 if ( includeAlpha ) {
5187                         rgba.push( ~~( alpha * 255 ) );
5188                 }
5190                 return "#" + jQuery.map( rgba, function( v ) {
5192                         // default to 0 when nulls exist
5193                         v = ( v || 0 ).toString( 16 );
5194                         return v.length === 1 ? "0" + v : v;
5195                 }).join("");
5196         },
5197         toString: function() {
5198                 return this._rgba[ 3 ] === 0 ? "transparent" : this.toRgbaString();
5199         }
5201 color.fn.parse.prototype = color.fn;
5203 // hsla conversions adapted from:
5204 // https://code.google.com/p/maashaack/source/browse/packages/graphics/trunk/src/graphics/colors/HUE2RGB.as?r=5021
5206 function hue2rgb( p, q, h ) {
5207         h = ( h + 1 ) % 1;
5208         if ( h * 6 < 1 ) {
5209                 return p + (q - p) * h * 6;
5210         }
5211         if ( h * 2 < 1) {
5212                 return q;
5213         }
5214         if ( h * 3 < 2 ) {
5215                 return p + (q - p) * ((2/3) - h) * 6;
5216         }
5217         return p;
5220 spaces.hsla.to = function ( rgba ) {
5221         if ( rgba[ 0 ] == null || rgba[ 1 ] == null || rgba[ 2 ] == null ) {
5222                 return [ null, null, null, rgba[ 3 ] ];
5223         }
5224         var r = rgba[ 0 ] / 255,
5225                 g = rgba[ 1 ] / 255,
5226                 b = rgba[ 2 ] / 255,
5227                 a = rgba[ 3 ],
5228                 max = Math.max( r, g, b ),
5229                 min = Math.min( r, g, b ),
5230                 diff = max - min,
5231                 add = max + min,
5232                 l = add * 0.5,
5233                 h, s;
5235         if ( min === max ) {
5236                 h = 0;
5237         } else if ( r === max ) {
5238                 h = ( 60 * ( g - b ) / diff ) + 360;
5239         } else if ( g === max ) {
5240                 h = ( 60 * ( b - r ) / diff ) + 120;
5241         } else {
5242                 h = ( 60 * ( r - g ) / diff ) + 240;
5243         }
5245         // chroma (diff) == 0 means greyscale which, by definition, saturation = 0%
5246         // otherwise, saturation is based on the ratio of chroma (diff) to lightness (add)
5247         if ( diff === 0 ) {
5248                 s = 0;
5249         } else if ( l <= 0.5 ) {
5250                 s = diff / add;
5251         } else {
5252                 s = diff / ( 2 - add );
5253         }
5254         return [ Math.round(h) % 360, s, l, a == null ? 1 : a ];
5257 spaces.hsla.from = function ( hsla ) {
5258         if ( hsla[ 0 ] == null || hsla[ 1 ] == null || hsla[ 2 ] == null ) {
5259                 return [ null, null, null, hsla[ 3 ] ];
5260         }
5261         var h = hsla[ 0 ] / 360,
5262                 s = hsla[ 1 ],
5263                 l = hsla[ 2 ],
5264                 a = hsla[ 3 ],
5265                 q = l <= 0.5 ? l * ( 1 + s ) : l + s - l * s,
5266                 p = 2 * l - q;
5268         return [
5269                 Math.round( hue2rgb( p, q, h + ( 1 / 3 ) ) * 255 ),
5270                 Math.round( hue2rgb( p, q, h ) * 255 ),
5271                 Math.round( hue2rgb( p, q, h - ( 1 / 3 ) ) * 255 ),
5272                 a
5273         ];
5277 each( spaces, function( spaceName, space ) {
5278         var props = space.props,
5279                 cache = space.cache,
5280                 to = space.to,
5281                 from = space.from;
5283         // makes rgba() and hsla()
5284         color.fn[ spaceName ] = function( value ) {
5286                 // generate a cache for this space if it doesn't exist
5287                 if ( to && !this[ cache ] ) {
5288                         this[ cache ] = to( this._rgba );
5289                 }
5290                 if ( value === undefined ) {
5291                         return this[ cache ].slice();
5292                 }
5294                 var ret,
5295                         type = jQuery.type( value ),
5296                         arr = ( type === "array" || type === "object" ) ? value : arguments,
5297                         local = this[ cache ].slice();
5299                 each( props, function( key, prop ) {
5300                         var val = arr[ type === "object" ? key : prop.idx ];
5301                         if ( val == null ) {
5302                                 val = local[ prop.idx ];
5303                         }
5304                         local[ prop.idx ] = clamp( val, prop );
5305                 });
5307                 if ( from ) {
5308                         ret = color( from( local ) );
5309                         ret[ cache ] = local;
5310                         return ret;
5311                 } else {
5312                         return color( local );
5313                 }
5314         };
5316         // makes red() green() blue() alpha() hue() saturation() lightness()
5317         each( props, function( key, prop ) {
5318                 // alpha is included in more than one space
5319                 if ( color.fn[ key ] ) {
5320                         return;
5321                 }
5322                 color.fn[ key ] = function( value ) {
5323                         var vtype = jQuery.type( value ),
5324                                 fn = ( key === "alpha" ? ( this._hsla ? "hsla" : "rgba" ) : spaceName ),
5325                                 local = this[ fn ](),
5326                                 cur = local[ prop.idx ],
5327                                 match;
5329                         if ( vtype === "undefined" ) {
5330                                 return cur;
5331                         }
5333                         if ( vtype === "function" ) {
5334                                 value = value.call( this, cur );
5335                                 vtype = jQuery.type( value );
5336                         }
5337                         if ( value == null && prop.empty ) {
5338                                 return this;
5339                         }
5340                         if ( vtype === "string" ) {
5341                                 match = rplusequals.exec( value );
5342                                 if ( match ) {
5343                                         value = cur + parseFloat( match[ 2 ] ) * ( match[ 1 ] === "+" ? 1 : -1 );
5344                                 }
5345                         }
5346                         local[ prop.idx ] = value;
5347                         return this[ fn ]( local );
5348                 };
5349         });
5352 // add cssHook and .fx.step function for each named hook.
5353 // accept a space separated string of properties
5354 color.hook = function( hook ) {
5355         var hooks = hook.split( " " );
5356         each( hooks, function( i, hook ) {
5357                 jQuery.cssHooks[ hook ] = {
5358                         set: function( elem, value ) {
5359                                 var parsed, curElem,
5360                                         backgroundColor = "";
5362                                 if ( value !== "transparent" && ( jQuery.type( value ) !== "string" || ( parsed = stringParse( value ) ) ) ) {
5363                                         value = color( parsed || value );
5364                                         if ( !support.rgba && value._rgba[ 3 ] !== 1 ) {
5365                                                 curElem = hook === "backgroundColor" ? elem.parentNode : elem;
5366                                                 while (
5367                                                         (backgroundColor === "" || backgroundColor === "transparent") &&
5368                                                         curElem && curElem.style
5369                                                 ) {
5370                                                         try {
5371                                                                 backgroundColor = jQuery.css( curElem, "backgroundColor" );
5372                                                                 curElem = curElem.parentNode;
5373                                                         } catch ( e ) {
5374                                                         }
5375                                                 }
5377                                                 value = value.blend( backgroundColor && backgroundColor !== "transparent" ?
5378                                                         backgroundColor :
5379                                                         "_default" );
5380                                         }
5382                                         value = value.toRgbaString();
5383                                 }
5384                                 try {
5385                                         elem.style[ hook ] = value;
5386                                 } catch( e ) {
5387                                         // wrapped to prevent IE from throwing errors on "invalid" values like 'auto' or 'inherit'
5388                                 }
5389                         }
5390                 };
5391                 jQuery.fx.step[ hook ] = function( fx ) {
5392                         if ( !fx.colorInit ) {
5393                                 fx.start = color( fx.elem, hook );
5394                                 fx.end = color( fx.end );
5395                                 fx.colorInit = true;
5396                         }
5397                         jQuery.cssHooks[ hook ].set( fx.elem, fx.start.transition( fx.end, fx.pos ) );
5398                 };
5399         });
5403 color.hook( stepHooks );
5405 jQuery.cssHooks.borderColor = {
5406         expand: function( value ) {
5407                 var expanded = {};
5409                 each( [ "Top", "Right", "Bottom", "Left" ], function( i, part ) {
5410                         expanded[ "border" + part + "Color" ] = value;
5411                 });
5412                 return expanded;
5413         }
5416 // Basic color names only.
5417 // Usage of any of the other color names requires adding yourself or including
5418 // jquery.color.svg-names.js.
5419 colors = jQuery.Color.names = {
5420         // 4.1. Basic color keywords
5421         aqua: "#00ffff",
5422         black: "#000000",
5423         blue: "#0000ff",
5424         fuchsia: "#ff00ff",
5425         gray: "#808080",
5426         green: "#008000",
5427         lime: "#00ff00",
5428         maroon: "#800000",
5429         navy: "#000080",
5430         olive: "#808000",
5431         purple: "#800080",
5432         red: "#ff0000",
5433         silver: "#c0c0c0",
5434         teal: "#008080",
5435         white: "#ffffff",
5436         yellow: "#ffff00",
5438         // 4.2.3. "transparent" color keyword
5439         transparent: [ null, null, null, 0 ],
5441         _default: "#ffffff"
5444 })( jQuery );
5447 /******************************************************************************/
5448 /****************************** CLASS ANIMATIONS ******************************/
5449 /******************************************************************************/
5450 (function() {
5452 var classAnimationActions = [ "add", "remove", "toggle" ],
5453         shorthandStyles = {
5454                 border: 1,
5455                 borderBottom: 1,
5456                 borderColor: 1,
5457                 borderLeft: 1,
5458                 borderRight: 1,
5459                 borderTop: 1,
5460                 borderWidth: 1,
5461                 margin: 1,
5462                 padding: 1
5463         };
5465 $.each([ "borderLeftStyle", "borderRightStyle", "borderBottomStyle", "borderTopStyle" ], function( _, prop ) {
5466         $.fx.step[ prop ] = function( fx ) {
5467                 if ( fx.end !== "none" && !fx.setAttr || fx.pos === 1 && !fx.setAttr ) {
5468                         jQuery.style( fx.elem, prop, fx.end );
5469                         fx.setAttr = true;
5470                 }
5471         };
5474 function getElementStyles( elem ) {
5475         var key, len,
5476                 style = elem.ownerDocument.defaultView ?
5477                         elem.ownerDocument.defaultView.getComputedStyle( elem, null ) :
5478                         elem.currentStyle,
5479                 styles = {};
5481         if ( style && style.length && style[ 0 ] && style[ style[ 0 ] ] ) {
5482                 len = style.length;
5483                 while ( len-- ) {
5484                         key = style[ len ];
5485                         if ( typeof style[ key ] === "string" ) {
5486                                 styles[ $.camelCase( key ) ] = style[ key ];
5487                         }
5488                 }
5489         // support: Opera, IE <9
5490         } else {
5491                 for ( key in style ) {
5492                         if ( typeof style[ key ] === "string" ) {
5493                                 styles[ key ] = style[ key ];
5494                         }
5495                 }
5496         }
5498         return styles;
5502 function styleDifference( oldStyle, newStyle ) {
5503         var diff = {},
5504                 name, value;
5506         for ( name in newStyle ) {
5507                 value = newStyle[ name ];
5508                 if ( oldStyle[ name ] !== value ) {
5509                         if ( !shorthandStyles[ name ] ) {
5510                                 if ( $.fx.step[ name ] || !isNaN( parseFloat( value ) ) ) {
5511                                         diff[ name ] = value;
5512                                 }
5513                         }
5514                 }
5515         }
5517         return diff;
5520 // support: jQuery <1.8
5521 if ( !$.fn.addBack ) {
5522         $.fn.addBack = function( selector ) {
5523                 return this.add( selector == null ?
5524                         this.prevObject : this.prevObject.filter( selector )
5525                 );
5526         };
5529 $.effects.animateClass = function( value, duration, easing, callback ) {
5530         var o = $.speed( duration, easing, callback );
5532         return this.queue( function() {
5533                 var animated = $( this ),
5534                         baseClass = animated.attr( "class" ) || "",
5535                         applyClassChange,
5536                         allAnimations = o.children ? animated.find( "*" ).addBack() : animated;
5538                 // map the animated objects to store the original styles.
5539                 allAnimations = allAnimations.map(function() {
5540                         var el = $( this );
5541                         return {
5542                                 el: el,
5543                                 start: getElementStyles( this )
5544                         };
5545                 });
5547                 // apply class change
5548                 applyClassChange = function() {
5549                         $.each( classAnimationActions, function(i, action) {
5550                                 if ( value[ action ] ) {
5551                                         animated[ action + "Class" ]( value[ action ] );
5552                                 }
5553                         });
5554                 };
5555                 applyClassChange();
5557                 // map all animated objects again - calculate new styles and diff
5558                 allAnimations = allAnimations.map(function() {
5559                         this.end = getElementStyles( this.el[ 0 ] );
5560                         this.diff = styleDifference( this.start, this.end );
5561                         return this;
5562                 });
5564                 // apply original class
5565                 animated.attr( "class", baseClass );
5567                 // map all animated objects again - this time collecting a promise
5568                 allAnimations = allAnimations.map(function() {
5569                         var styleInfo = this,
5570                                 dfd = $.Deferred(),
5571                                 opts = $.extend({}, o, {
5572                                         queue: false,
5573                                         complete: function() {
5574                                                 dfd.resolve( styleInfo );
5575                                         }
5576                                 });
5578                         this.el.animate( this.diff, opts );
5579                         return dfd.promise();
5580                 });
5582                 // once all animations have completed:
5583                 $.when.apply( $, allAnimations.get() ).done(function() {
5585                         // set the final class
5586                         applyClassChange();
5588                         // for each animated element,
5589                         // clear all css properties that were animated
5590                         $.each( arguments, function() {
5591                                 var el = this.el;
5592                                 $.each( this.diff, function(key) {
5593                                         el.css( key, "" );
5594                                 });
5595                         });
5597                         // this is guarnteed to be there if you use jQuery.speed()
5598                         // it also handles dequeuing the next anim...
5599                         o.complete.call( animated[ 0 ] );
5600                 });
5601         });
5604 $.fn.extend({
5605         addClass: (function( orig ) {
5606                 return function( classNames, speed, easing, callback ) {
5607                         return speed ?
5608                                 $.effects.animateClass.call( this,
5609                                         { add: classNames }, speed, easing, callback ) :
5610                                 orig.apply( this, arguments );
5611                 };
5612         })( $.fn.addClass ),
5614         removeClass: (function( orig ) {
5615                 return function( classNames, speed, easing, callback ) {
5616                         return arguments.length > 1 ?
5617                                 $.effects.animateClass.call( this,
5618                                         { remove: classNames }, speed, easing, callback ) :
5619                                 orig.apply( this, arguments );
5620                 };
5621         })( $.fn.removeClass ),
5623         toggleClass: (function( orig ) {
5624                 return function( classNames, force, speed, easing, callback ) {
5625                         if ( typeof force === "boolean" || force === undefined ) {
5626                                 if ( !speed ) {
5627                                         // without speed parameter
5628                                         return orig.apply( this, arguments );
5629                                 } else {
5630                                         return $.effects.animateClass.call( this,
5631                                                 (force ? { add: classNames } : { remove: classNames }),
5632                                                 speed, easing, callback );
5633                                 }
5634                         } else {
5635                                 // without force parameter
5636                                 return $.effects.animateClass.call( this,
5637                                         { toggle: classNames }, force, speed, easing );
5638                         }
5639                 };
5640         })( $.fn.toggleClass ),
5642         switchClass: function( remove, add, speed, easing, callback) {
5643                 return $.effects.animateClass.call( this, {
5644                         add: add,
5645                         remove: remove
5646                 }, speed, easing, callback );
5647         }
5650 })();
5652 /******************************************************************************/
5653 /*********************************** EFFECTS **********************************/
5654 /******************************************************************************/
5656 (function() {
5658 $.extend( $.effects, {
5659         version: "1.10.3",
5661         // Saves a set of properties in a data storage
5662         save: function( element, set ) {
5663                 for( var i=0; i < set.length; i++ ) {
5664                         if ( set[ i ] !== null ) {
5665                                 element.data( dataSpace + set[ i ], element[ 0 ].style[ set[ i ] ] );
5666                         }
5667                 }
5668         },
5670         // Restores a set of previously saved properties from a data storage
5671         restore: function( element, set ) {
5672                 var val, i;
5673                 for( i=0; i < set.length; i++ ) {
5674                         if ( set[ i ] !== null ) {
5675                                 val = element.data( dataSpace + set[ i ] );
5676                                 // support: jQuery 1.6.2
5677                                 // http://bugs.jquery.com/ticket/9917
5678                                 // jQuery 1.6.2 incorrectly returns undefined for any falsy value.
5679                                 // We can't differentiate between "" and 0 here, so we just assume
5680                                 // empty string since it's likely to be a more common value...
5681                                 if ( val === undefined ) {
5682                                         val = "";
5683                                 }
5684                                 element.css( set[ i ], val );
5685                         }
5686                 }
5687         },
5689         setMode: function( el, mode ) {
5690                 if (mode === "toggle") {
5691                         mode = el.is( ":hidden" ) ? "show" : "hide";
5692                 }
5693                 return mode;
5694         },
5696         // Translates a [top,left] array into a baseline value
5697         // this should be a little more flexible in the future to handle a string & hash
5698         getBaseline: function( origin, original ) {
5699                 var y, x;
5700                 switch ( origin[ 0 ] ) {
5701                         case "top": y = 0; break;
5702                         case "middle": y = 0.5; break;
5703                         case "bottom": y = 1; break;
5704                         default: y = origin[ 0 ] / original.height;
5705                 }
5706                 switch ( origin[ 1 ] ) {
5707                         case "left": x = 0; break;
5708                         case "center": x = 0.5; break;
5709                         case "right": x = 1; break;
5710                         default: x = origin[ 1 ] / original.width;
5711                 }
5712                 return {
5713                         x: x,
5714                         y: y
5715                 };
5716         },
5718         // Wraps the element around a wrapper that copies position properties
5719         createWrapper: function( element ) {
5721                 // if the element is already wrapped, return it
5722                 if ( element.parent().is( ".ui-effects-wrapper" )) {
5723                         return element.parent();
5724                 }
5726                 // wrap the element
5727                 var props = {
5728                                 width: element.outerWidth(true),
5729                                 height: element.outerHeight(true),
5730                                 "float": element.css( "float" )
5731                         },
5732                         wrapper = $( "<div></div>" )
5733                                 .addClass( "ui-effects-wrapper" )
5734                                 .css({
5735                                         fontSize: "100%",
5736                                         background: "transparent",
5737                                         border: "none",
5738                                         margin: 0,
5739                                         padding: 0
5740                                 }),
5741                         // Store the size in case width/height are defined in % - Fixes #5245
5742                         size = {
5743                                 width: element.width(),
5744                                 height: element.height()
5745                         },
5746                         active = document.activeElement;
5748                 // support: Firefox
5749                 // Firefox incorrectly exposes anonymous content
5750                 // https://bugzilla.mozilla.org/show_bug.cgi?id=561664
5751                 try {
5752                         active.id;
5753                 } catch( e ) {
5754                         active = document.body;
5755                 }
5757                 element.wrap( wrapper );
5759                 // Fixes #7595 - Elements lose focus when wrapped.
5760                 if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
5761                         $( active ).focus();
5762                 }
5764                 wrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually lose the reference to the wrapped element
5766                 // transfer positioning properties to the wrapper
5767                 if ( element.css( "position" ) === "static" ) {
5768                         wrapper.css({ position: "relative" });
5769                         element.css({ position: "relative" });
5770                 } else {
5771                         $.extend( props, {
5772                                 position: element.css( "position" ),
5773                                 zIndex: element.css( "z-index" )
5774                         });
5775                         $.each([ "top", "left", "bottom", "right" ], function(i, pos) {
5776                                 props[ pos ] = element.css( pos );
5777                                 if ( isNaN( parseInt( props[ pos ], 10 ) ) ) {
5778                                         props[ pos ] = "auto";
5779                                 }
5780                         });
5781                         element.css({
5782                                 position: "relative",
5783                                 top: 0,
5784                                 left: 0,
5785                                 right: "auto",
5786                                 bottom: "auto"
5787                         });
5788                 }
5789                 element.css(size);
5791                 return wrapper.css( props ).show();
5792         },
5794         removeWrapper: function( element ) {
5795                 var active = document.activeElement;
5797                 if ( element.parent().is( ".ui-effects-wrapper" ) ) {
5798                         element.parent().replaceWith( element );
5800                         // Fixes #7595 - Elements lose focus when wrapped.
5801                         if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
5802                                 $( active ).focus();
5803                         }
5804                 }
5807                 return element;
5808         },
5810         setTransition: function( element, list, factor, value ) {
5811                 value = value || {};
5812                 $.each( list, function( i, x ) {
5813                         var unit = element.cssUnit( x );
5814                         if ( unit[ 0 ] > 0 ) {
5815                                 value[ x ] = unit[ 0 ] * factor + unit[ 1 ];
5816                         }
5817                 });
5818                 return value;
5819         }
5822 // return an effect options object for the given parameters:
5823 function _normalizeArguments( effect, options, speed, callback ) {
5825         // allow passing all options as the first parameter
5826         if ( $.isPlainObject( effect ) ) {
5827                 options = effect;
5828                 effect = effect.effect;
5829         }
5831         // convert to an object
5832         effect = { effect: effect };
5834         // catch (effect, null, ...)
5835         if ( options == null ) {
5836                 options = {};
5837         }
5839         // catch (effect, callback)
5840         if ( $.isFunction( options ) ) {
5841                 callback = options;
5842                 speed = null;
5843                 options = {};
5844         }
5846         // catch (effect, speed, ?)
5847         if ( typeof options === "number" || $.fx.speeds[ options ] ) {
5848                 callback = speed;
5849                 speed = options;
5850                 options = {};
5851         }
5853         // catch (effect, options, callback)
5854         if ( $.isFunction( speed ) ) {
5855                 callback = speed;
5856                 speed = null;
5857         }
5859         // add options to effect
5860         if ( options ) {
5861                 $.extend( effect, options );
5862         }
5864         speed = speed || options.duration;
5865         effect.duration = $.fx.off ? 0 :
5866                 typeof speed === "number" ? speed :
5867                 speed in $.fx.speeds ? $.fx.speeds[ speed ] :
5868                 $.fx.speeds._default;
5870         effect.complete = callback || options.complete;
5872         return effect;
5875 function standardAnimationOption( option ) {
5876         // Valid standard speeds (nothing, number, named speed)
5877         if ( !option || typeof option === "number" || $.fx.speeds[ option ] ) {
5878                 return true;
5879         }
5881         // Invalid strings - treat as "normal" speed
5882         if ( typeof option === "string" && !$.effects.effect[ option ] ) {
5883                 return true;
5884         }
5886         // Complete callback
5887         if ( $.isFunction( option ) ) {
5888                 return true;
5889         }
5891         // Options hash (but not naming an effect)
5892         if ( typeof option === "object" && !option.effect ) {
5893                 return true;
5894         }
5896         // Didn't match any standard API
5897         return false;
5900 $.fn.extend({
5901         effect: function( /* effect, options, speed, callback */ ) {
5902                 var args = _normalizeArguments.apply( this, arguments ),
5903                         mode = args.mode,
5904                         queue = args.queue,
5905                         effectMethod = $.effects.effect[ args.effect ];
5907                 if ( $.fx.off || !effectMethod ) {
5908                         // delegate to the original method (e.g., .show()) if possible
5909                         if ( mode ) {
5910                                 return this[ mode ]( args.duration, args.complete );
5911                         } else {
5912                                 return this.each( function() {
5913                                         if ( args.complete ) {
5914                                                 args.complete.call( this );
5915                                         }
5916                                 });
5917                         }
5918                 }
5920                 function run( next ) {
5921                         var elem = $( this ),
5922                                 complete = args.complete,
5923                                 mode = args.mode;
5925                         function done() {
5926                                 if ( $.isFunction( complete ) ) {
5927                                         complete.call( elem[0] );
5928                                 }
5929                                 if ( $.isFunction( next ) ) {
5930                                         next();
5931                                 }
5932                         }
5934                         // If the element already has the correct final state, delegate to
5935                         // the core methods so the internal tracking of "olddisplay" works.
5936                         if ( elem.is( ":hidden" ) ? mode === "hide" : mode === "show" ) {
5937                                 elem[ mode ]();
5938                                 done();
5939                         } else {
5940                                 effectMethod.call( elem[0], args, done );
5941                         }
5942                 }
5944                 return queue === false ? this.each( run ) : this.queue( queue || "fx", run );
5945         },
5947         show: (function( orig ) {
5948                 return function( option ) {
5949                         if ( standardAnimationOption( option ) ) {
5950                                 return orig.apply( this, arguments );
5951                         } else {
5952                                 var args = _normalizeArguments.apply( this, arguments );
5953                                 args.mode = "show";
5954                                 return this.effect.call( this, args );
5955                         }
5956                 };
5957         })( $.fn.show ),
5959         hide: (function( orig ) {
5960                 return function( option ) {
5961                         if ( standardAnimationOption( option ) ) {
5962                                 return orig.apply( this, arguments );
5963                         } else {
5964                                 var args = _normalizeArguments.apply( this, arguments );
5965                                 args.mode = "hide";
5966                                 return this.effect.call( this, args );
5967                         }
5968                 };
5969         })( $.fn.hide ),
5971         toggle: (function( orig ) {
5972                 return function( option ) {
5973                         if ( standardAnimationOption( option ) || typeof option === "boolean" ) {
5974                                 return orig.apply( this, arguments );
5975                         } else {
5976                                 var args = _normalizeArguments.apply( this, arguments );
5977                                 args.mode = "toggle";
5978                                 return this.effect.call( this, args );
5979                         }
5980                 };
5981         })( $.fn.toggle ),
5983         // helper functions
5984         cssUnit: function(key) {
5985                 var style = this.css( key ),
5986                         val = [];
5988                 $.each( [ "em", "px", "%", "pt" ], function( i, unit ) {
5989                         if ( style.indexOf( unit ) > 0 ) {
5990                                 val = [ parseFloat( style ), unit ];
5991                         }
5992                 });
5993                 return val;
5994         }
5997 })();
5999 /******************************************************************************/
6000 /*********************************** EASING ***********************************/
6001 /******************************************************************************/
6003 (function() {
6005 // based on easing equations from Robert Penner (http://www.robertpenner.com/easing)
6007 var baseEasings = {};
6009 $.each( [ "Quad", "Cubic", "Quart", "Quint", "Expo" ], function( i, name ) {
6010         baseEasings[ name ] = function( p ) {
6011                 return Math.pow( p, i + 2 );
6012         };
6015 $.extend( baseEasings, {
6016         Sine: function ( p ) {
6017                 return 1 - Math.cos( p * Math.PI / 2 );
6018         },
6019         Circ: function ( p ) {
6020                 return 1 - Math.sqrt( 1 - p * p );
6021         },
6022         Elastic: function( p ) {
6023                 return p === 0 || p === 1 ? p :
6024                         -Math.pow( 2, 8 * (p - 1) ) * Math.sin( ( (p - 1) * 80 - 7.5 ) * Math.PI / 15 );
6025         },
6026         Back: function( p ) {
6027                 return p * p * ( 3 * p - 2 );
6028         },
6029         Bounce: function ( p ) {
6030                 var pow2,
6031                         bounce = 4;
6033                 while ( p < ( ( pow2 = Math.pow( 2, --bounce ) ) - 1 ) / 11 ) {}
6034                 return 1 / Math.pow( 4, 3 - bounce ) - 7.5625 * Math.pow( ( pow2 * 3 - 2 ) / 22 - p, 2 );
6035         }
6038 $.each( baseEasings, function( name, easeIn ) {
6039         $.easing[ "easeIn" + name ] = easeIn;
6040         $.easing[ "easeOut" + name ] = function( p ) {
6041                 return 1 - easeIn( 1 - p );
6042         };
6043         $.easing[ "easeInOut" + name ] = function( p ) {
6044                 return p < 0.5 ?
6045                         easeIn( p * 2 ) / 2 :
6046                         1 - easeIn( p * -2 + 2 ) / 2;
6047         };
6050 })();
6052 })(jQuery);
6054 (function( $, undefined ) {
6056 var uid = 0,
6057         hideProps = {},
6058         showProps = {};
6060 hideProps.height = hideProps.paddingTop = hideProps.paddingBottom =
6061         hideProps.borderTopWidth = hideProps.borderBottomWidth = "hide";
6062 showProps.height = showProps.paddingTop = showProps.paddingBottom =
6063         showProps.borderTopWidth = showProps.borderBottomWidth = "show";
6065 $.widget( "ui.accordion", {
6066         version: "1.10.3",
6067         options: {
6068                 active: 0,
6069                 animate: {},
6070                 collapsible: false,
6071                 event: "click",
6072                 header: "> li > :first-child,> :not(li):even",
6073                 heightStyle: "auto",
6074                 icons: {
6075                         activeHeader: "ui-icon-triangle-1-s",
6076                         header: "ui-icon-triangle-1-e"
6077                 },
6079                 // callbacks
6080                 activate: null,
6081                 beforeActivate: null
6082         },
6084         _create: function() {
6085                 var options = this.options;
6086                 this.prevShow = this.prevHide = $();
6087                 this.element.addClass( "ui-accordion ui-widget ui-helper-reset" )
6088                         // ARIA
6089                         .attr( "role", "tablist" );
6091                 // don't allow collapsible: false and active: false / null
6092                 if ( !options.collapsible && (options.active === false || options.active == null) ) {
6093                         options.active = 0;
6094                 }
6096                 this._processPanels();
6097                 // handle negative values
6098                 if ( options.active < 0 ) {
6099                         options.active += this.headers.length;
6100                 }
6101                 this._refresh();
6102         },
6104         _getCreateEventData: function() {
6105                 return {
6106                         header: this.active,
6107                         panel: !this.active.length ? $() : this.active.next(),
6108                         content: !this.active.length ? $() : this.active.next()
6109                 };
6110         },
6112         _createIcons: function() {
6113                 var icons = this.options.icons;
6114                 if ( icons ) {
6115                         $( "<span>" )
6116                                 .addClass( "ui-accordion-header-icon ui-icon " + icons.header )
6117                                 .prependTo( this.headers );
6118                         this.active.children( ".ui-accordion-header-icon" )
6119                                 .removeClass( icons.header )
6120                                 .addClass( icons.activeHeader );
6121                         this.headers.addClass( "ui-accordion-icons" );
6122                 }
6123         },
6125         _destroyIcons: function() {
6126                 this.headers
6127                         .removeClass( "ui-accordion-icons" )
6128                         .children( ".ui-accordion-header-icon" )
6129                                 .remove();
6130         },
6132         _destroy: function() {
6133                 var contents;
6135                 // clean up main element
6136                 this.element
6137                         .removeClass( "ui-accordion ui-widget ui-helper-reset" )
6138                         .removeAttr( "role" );
6140                 // clean up headers
6141                 this.headers
6142                         .removeClass( "ui-accordion-header ui-accordion-header-active ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top" )
6143                         .removeAttr( "role" )
6144                         .removeAttr( "aria-selected" )
6145                         .removeAttr( "aria-controls" )
6146                         .removeAttr( "tabIndex" )
6147                         .each(function() {
6148                                 if ( /^ui-accordion/.test( this.id ) ) {
6149                                         this.removeAttribute( "id" );
6150                                 }
6151                         });
6152                 this._destroyIcons();
6154                 // clean up content panels
6155                 contents = this.headers.next()
6156                         .css( "display", "" )
6157                         .removeAttr( "role" )
6158                         .removeAttr( "aria-expanded" )
6159                         .removeAttr( "aria-hidden" )
6160                         .removeAttr( "aria-labelledby" )
6161                         .removeClass( "ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-state-disabled" )
6162                         .each(function() {
6163                                 if ( /^ui-accordion/.test( this.id ) ) {
6164                                         this.removeAttribute( "id" );
6165                                 }
6166                         });
6167                 if ( this.options.heightStyle !== "content" ) {
6168                         contents.css( "height", "" );
6169                 }
6170         },
6172         _setOption: function( key, value ) {
6173                 if ( key === "active" ) {
6174                         // _activate() will handle invalid values and update this.options
6175                         this._activate( value );
6176                         return;
6177                 }
6179                 if ( key === "event" ) {
6180                         if ( this.options.event ) {
6181                                 this._off( this.headers, this.options.event );
6182                         }
6183                         this._setupEvents( value );
6184                 }
6186                 this._super( key, value );
6188                 // setting collapsible: false while collapsed; open first panel
6189                 if ( key === "collapsible" && !value && this.options.active === false ) {
6190                         this._activate( 0 );
6191                 }
6193                 if ( key === "icons" ) {
6194                         this._destroyIcons();
6195                         if ( value ) {
6196                                 this._createIcons();
6197                         }
6198                 }
6200                 // #5332 - opacity doesn't cascade to positioned elements in IE
6201                 // so we need to add the disabled class to the headers and panels
6202                 if ( key === "disabled" ) {
6203                         this.headers.add( this.headers.next() )
6204                                 .toggleClass( "ui-state-disabled", !!value );
6205                 }
6206         },
6208         _keydown: function( event ) {
6209                 /*jshint maxcomplexity:15*/
6210                 if ( event.altKey || event.ctrlKey ) {
6211                         return;
6212                 }
6214                 var keyCode = $.ui.keyCode,
6215                         length = this.headers.length,
6216                         currentIndex = this.headers.index( event.target ),
6217                         toFocus = false;
6219                 switch ( event.keyCode ) {
6220                         case keyCode.RIGHT:
6221                         case keyCode.DOWN:
6222                                 toFocus = this.headers[ ( currentIndex + 1 ) % length ];
6223                                 break;
6224                         case keyCode.LEFT:
6225                         case keyCode.UP:
6226                                 toFocus = this.headers[ ( currentIndex - 1 + length ) % length ];
6227                                 break;
6228                         case keyCode.SPACE:
6229                         case keyCode.ENTER:
6230                                 this._eventHandler( event );
6231                                 break;
6232                         case keyCode.HOME:
6233                                 toFocus = this.headers[ 0 ];
6234                                 break;
6235                         case keyCode.END:
6236                                 toFocus = this.headers[ length - 1 ];
6237                                 break;
6238                 }
6240                 if ( toFocus ) {
6241                         $( event.target ).attr( "tabIndex", -1 );
6242                         $( toFocus ).attr( "tabIndex", 0 );
6243                         toFocus.focus();
6244                         event.preventDefault();
6245                 }
6246         },
6248         _panelKeyDown : function( event ) {
6249                 if ( event.keyCode === $.ui.keyCode.UP && event.ctrlKey ) {
6250                         $( event.currentTarget ).prev().focus();
6251                 }
6252         },
6254         refresh: function() {
6255                 var options = this.options;
6256                 this._processPanels();
6258                 // was collapsed or no panel
6259                 if ( ( options.active === false && options.collapsible === true ) || !this.headers.length ) {
6260                         options.active = false;
6261                         this.active = $();
6262                 // active false only when collapsible is true
6263                 } else if ( options.active === false ) {
6264                         this._activate( 0 );
6265                 // was active, but active panel is gone
6266                 } else if ( this.active.length && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
6267                         // all remaining panel are disabled
6268                         if ( this.headers.length === this.headers.find(".ui-state-disabled").length ) {
6269                                 options.active = false;
6270                                 this.active = $();
6271                         // activate previous panel
6272                         } else {
6273                                 this._activate( Math.max( 0, options.active - 1 ) );
6274                         }
6275                 // was active, active panel still exists
6276                 } else {
6277                         // make sure active index is correct
6278                         options.active = this.headers.index( this.active );
6279                 }
6281                 this._destroyIcons();
6283                 this._refresh();
6284         },
6286         _processPanels: function() {
6287                 this.headers = this.element.find( this.options.header )
6288                         .addClass( "ui-accordion-header ui-helper-reset ui-state-default ui-corner-all" );
6290                 this.headers.next()
6291                         .addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" )
6292                         .filter(":not(.ui-accordion-content-active)")
6293                         .hide();
6294         },
6296         _refresh: function() {
6297                 var maxHeight,
6298                         options = this.options,
6299                         heightStyle = options.heightStyle,
6300                         parent = this.element.parent(),
6301                         accordionId = this.accordionId = "ui-accordion-" +
6302                                 (this.element.attr( "id" ) || ++uid);
6304                 this.active = this._findActive( options.active )
6305                         .addClass( "ui-accordion-header-active ui-state-active ui-corner-top" )
6306                         .removeClass( "ui-corner-all" );
6307                 this.active.next()
6308                         .addClass( "ui-accordion-content-active" )
6309                         .show();
6311                 this.headers
6312                         .attr( "role", "tab" )
6313                         .each(function( i ) {
6314                                 var header = $( this ),
6315                                         headerId = header.attr( "id" ),
6316                                         panel = header.next(),
6317                                         panelId = panel.attr( "id" );
6318                                 if ( !headerId ) {
6319                                         headerId = accordionId + "-header-" + i;
6320                                         header.attr( "id", headerId );
6321                                 }
6322                                 if ( !panelId ) {
6323                                         panelId = accordionId + "-panel-" + i;
6324                                         panel.attr( "id", panelId );
6325                                 }
6326                                 header.attr( "aria-controls", panelId );
6327                                 panel.attr( "aria-labelledby", headerId );
6328                         })
6329                         .next()
6330                                 .attr( "role", "tabpanel" );
6332                 this.headers
6333                         .not( this.active )
6334                         .attr({
6335                                 "aria-selected": "false",
6336                                 tabIndex: -1
6337                         })
6338                         .next()
6339                                 .attr({
6340                                         "aria-expanded": "false",
6341                                         "aria-hidden": "true"
6342                                 })
6343                                 .hide();
6345                 // make sure at least one header is in the tab order
6346                 if ( !this.active.length ) {
6347                         this.headers.eq( 0 ).attr( "tabIndex", 0 );
6348                 } else {
6349                         this.active.attr({
6350                                 "aria-selected": "true",
6351                                 tabIndex: 0
6352                         })
6353                         .next()
6354                                 .attr({
6355                                         "aria-expanded": "true",
6356                                         "aria-hidden": "false"
6357                                 });
6358                 }
6360                 this._createIcons();
6362                 this._setupEvents( options.event );
6364                 if ( heightStyle === "fill" ) {
6365                         maxHeight = parent.height();
6366                         this.element.siblings( ":visible" ).each(function() {
6367                                 var elem = $( this ),
6368                                         position = elem.css( "position" );
6370                                 if ( position === "absolute" || position === "fixed" ) {
6371                                         return;
6372                                 }
6373                                 maxHeight -= elem.outerHeight( true );
6374                         });
6376                         this.headers.each(function() {
6377                                 maxHeight -= $( this ).outerHeight( true );
6378                         });
6380                         this.headers.next()
6381                                 .each(function() {
6382                                         $( this ).height( Math.max( 0, maxHeight -
6383                                                 $( this ).innerHeight() + $( this ).height() ) );
6384                                 })
6385                                 .css( "overflow", "auto" );
6386                 } else if ( heightStyle === "auto" ) {
6387                         maxHeight = 0;
6388                         this.headers.next()
6389                                 .each(function() {
6390                                         maxHeight = Math.max( maxHeight, $( this ).css( "height", "" ).height() );
6391                                 })
6392                                 .height( maxHeight );
6393                 }
6394         },
6396         _activate: function( index ) {
6397                 var active = this._findActive( index )[ 0 ];
6399                 // trying to activate the already active panel
6400                 if ( active === this.active[ 0 ] ) {
6401                         return;
6402                 }
6404                 // trying to collapse, simulate a click on the currently active header
6405                 active = active || this.active[ 0 ];
6407                 this._eventHandler({
6408                         target: active,
6409                         currentTarget: active,
6410                         preventDefault: $.noop
6411                 });
6412         },
6414         _findActive: function( selector ) {
6415                 return typeof selector === "number" ? this.headers.eq( selector ) : $();
6416         },
6418         _setupEvents: function( event ) {
6419                 var events = {
6420                         keydown: "_keydown"
6421                 };
6422                 if ( event ) {
6423                         $.each( event.split(" "), function( index, eventName ) {
6424                                 events[ eventName ] = "_eventHandler";
6425                         });
6426                 }
6428                 this._off( this.headers.add( this.headers.next() ) );
6429                 this._on( this.headers, events );
6430                 this._on( this.headers.next(), { keydown: "_panelKeyDown" });
6431                 this._hoverable( this.headers );
6432                 this._focusable( this.headers );
6433         },
6435         _eventHandler: function( event ) {
6436                 var options = this.options,
6437                         active = this.active,
6438                         clicked = $( event.currentTarget ),
6439                         clickedIsActive = clicked[ 0 ] === active[ 0 ],
6440                         collapsing = clickedIsActive && options.collapsible,
6441                         toShow = collapsing ? $() : clicked.next(),
6442                         toHide = active.next(),
6443                         eventData = {
6444                                 oldHeader: active,
6445                                 oldPanel: toHide,
6446                                 newHeader: collapsing ? $() : clicked,
6447                                 newPanel: toShow
6448                         };
6450                 event.preventDefault();
6452                 if (
6453                                 // click on active header, but not collapsible
6454                                 ( clickedIsActive && !options.collapsible ) ||
6455                                 // allow canceling activation
6456                                 ( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
6457                         return;
6458                 }
6460                 options.active = collapsing ? false : this.headers.index( clicked );
6462                 // when the call to ._toggle() comes after the class changes
6463                 // it causes a very odd bug in IE 8 (see #6720)
6464                 this.active = clickedIsActive ? $() : clicked;
6465                 this._toggle( eventData );
6467                 // switch classes
6468                 // corner classes on the previously active header stay after the animation
6469                 active.removeClass( "ui-accordion-header-active ui-state-active" );
6470                 if ( options.icons ) {
6471                         active.children( ".ui-accordion-header-icon" )
6472                                 .removeClass( options.icons.activeHeader )
6473                                 .addClass( options.icons.header );
6474                 }
6476                 if ( !clickedIsActive ) {
6477                         clicked
6478                                 .removeClass( "ui-corner-all" )
6479                                 .addClass( "ui-accordion-header-active ui-state-active ui-corner-top" );
6480                         if ( options.icons ) {
6481                                 clicked.children( ".ui-accordion-header-icon" )
6482                                         .removeClass( options.icons.header )
6483                                         .addClass( options.icons.activeHeader );
6484                         }
6486                         clicked
6487                                 .next()
6488                                 .addClass( "ui-accordion-content-active" );
6489                 }
6490         },
6492         _toggle: function( data ) {
6493                 var toShow = data.newPanel,
6494                         toHide = this.prevShow.length ? this.prevShow : data.oldPanel;
6496                 // handle activating a panel during the animation for another activation
6497                 this.prevShow.add( this.prevHide ).stop( true, true );
6498                 this.prevShow = toShow;
6499                 this.prevHide = toHide;
6501                 if ( this.options.animate ) {
6502                         this._animate( toShow, toHide, data );
6503                 } else {
6504                         toHide.hide();
6505                         toShow.show();
6506                         this._toggleComplete( data );
6507                 }
6509                 toHide.attr({
6510                         "aria-expanded": "false",
6511                         "aria-hidden": "true"
6512                 });
6513                 toHide.prev().attr( "aria-selected", "false" );
6514                 // if we're switching panels, remove the old header from the tab order
6515                 // if we're opening from collapsed state, remove the previous header from the tab order
6516                 // if we're collapsing, then keep the collapsing header in the tab order
6517                 if ( toShow.length && toHide.length ) {
6518                         toHide.prev().attr( "tabIndex", -1 );
6519                 } else if ( toShow.length ) {
6520                         this.headers.filter(function() {
6521                                 return $( this ).attr( "tabIndex" ) === 0;
6522                         })
6523                         .attr( "tabIndex", -1 );
6524                 }
6526                 toShow
6527                         .attr({
6528                                 "aria-expanded": "true",
6529                                 "aria-hidden": "false"
6530                         })
6531                         .prev()
6532                                 .attr({
6533                                         "aria-selected": "true",
6534                                         tabIndex: 0
6535                                 });
6536         },
6538         _animate: function( toShow, toHide, data ) {
6539                 var total, easing, duration,
6540                         that = this,
6541                         adjust = 0,
6542                         down = toShow.length &&
6543                                 ( !toHide.length || ( toShow.index() < toHide.index() ) ),
6544                         animate = this.options.animate || {},
6545                         options = down && animate.down || animate,
6546                         complete = function() {
6547                                 that._toggleComplete( data );
6548                         };
6550                 if ( typeof options === "number" ) {
6551                         duration = options;
6552                 }
6553                 if ( typeof options === "string" ) {
6554                         easing = options;
6555                 }
6556                 // fall back from options to animation in case of partial down settings
6557                 easing = easing || options.easing || animate.easing;
6558                 duration = duration || options.duration || animate.duration;
6560                 if ( !toHide.length ) {
6561                         return toShow.animate( showProps, duration, easing, complete );
6562                 }
6563                 if ( !toShow.length ) {
6564                         return toHide.animate( hideProps, duration, easing, complete );
6565                 }
6567                 total = toShow.show().outerHeight();
6568                 toHide.animate( hideProps, {
6569                         duration: duration,
6570                         easing: easing,
6571                         step: function( now, fx ) {
6572                                 fx.now = Math.round( now );
6573                         }
6574                 });
6575                 toShow
6576                         .hide()
6577                         .animate( showProps, {
6578                                 duration: duration,
6579                                 easing: easing,
6580                                 complete: complete,
6581                                 step: function( now, fx ) {
6582                                         fx.now = Math.round( now );
6583                                         if ( fx.prop !== "height" ) {
6584                                                 adjust += fx.now;
6585                                         } else if ( that.options.heightStyle !== "content" ) {
6586                                                 fx.now = Math.round( total - toHide.outerHeight() - adjust );
6587                                                 adjust = 0;
6588                                         }
6589                                 }
6590                         });
6591         },
6593         _toggleComplete: function( data ) {
6594                 var toHide = data.oldPanel;
6596                 toHide
6597                         .removeClass( "ui-accordion-content-active" )
6598                         .prev()
6599                                 .removeClass( "ui-corner-top" )
6600                                 .addClass( "ui-corner-all" );
6602                 // Work around for rendering bug in IE (#5421)
6603                 if ( toHide.length ) {
6604                         toHide.parent()[0].className = toHide.parent()[0].className;
6605                 }
6607                 this._trigger( "activate", null, data );
6608         }
6611 })( jQuery );
6613 (function( $, undefined ) {
6615 // used to prevent race conditions with remote data sources
6616 var requestIndex = 0;
6618 $.widget( "ui.autocomplete", {
6619         version: "1.10.3",
6620         defaultElement: "<input>",
6621         options: {
6622                 appendTo: null,
6623                 autoFocus: false,
6624                 delay: 300,
6625                 minLength: 1,
6626                 position: {
6627                         my: "left top",
6628                         at: "left bottom",
6629                         collision: "none"
6630                 },
6631                 source: null,
6633                 // callbacks
6634                 change: null,
6635                 close: null,
6636                 focus: null,
6637                 open: null,
6638                 response: null,
6639                 search: null,
6640                 select: null
6641         },
6643         pending: 0,
6645         _create: function() {
6646                 // Some browsers only repeat keydown events, not keypress events,
6647                 // so we use the suppressKeyPress flag to determine if we've already
6648                 // handled the keydown event. #7269
6649                 // Unfortunately the code for & in keypress is the same as the up arrow,
6650                 // so we use the suppressKeyPressRepeat flag to avoid handling keypress
6651                 // events when we know the keydown event was used to modify the
6652                 // search term. #7799
6653                 var suppressKeyPress, suppressKeyPressRepeat, suppressInput,
6654                         nodeName = this.element[0].nodeName.toLowerCase(),
6655                         isTextarea = nodeName === "textarea",
6656                         isInput = nodeName === "input";
6658                 this.isMultiLine =
6659                         // Textareas are always multi-line
6660                         isTextarea ? true :
6661                         // Inputs are always single-line, even if inside a contentEditable element
6662                         // IE also treats inputs as contentEditable
6663                         isInput ? false :
6664                         // All other element types are determined by whether or not they're contentEditable
6665                         this.element.prop( "isContentEditable" );
6667                 this.valueMethod = this.element[ isTextarea || isInput ? "val" : "text" ];
6668                 this.isNewMenu = true;
6670                 this.element
6671                         .addClass( "ui-autocomplete-input" )
6672                         .attr( "autocomplete", "off" );
6674                 this._on( this.element, {
6675                         keydown: function( event ) {
6676                                 /*jshint maxcomplexity:15*/
6677                                 if ( this.element.prop( "readOnly" ) ) {
6678                                         suppressKeyPress = true;
6679                                         suppressInput = true;
6680                                         suppressKeyPressRepeat = true;
6681                                         return;
6682                                 }
6684                                 suppressKeyPress = false;
6685                                 suppressInput = false;
6686                                 suppressKeyPressRepeat = false;
6687                                 var keyCode = $.ui.keyCode;
6688                                 switch( event.keyCode ) {
6689                                 case keyCode.PAGE_UP:
6690                                         suppressKeyPress = true;
6691                                         this._move( "previousPage", event );
6692                                         break;
6693                                 case keyCode.PAGE_DOWN:
6694                                         suppressKeyPress = true;
6695                                         this._move( "nextPage", event );
6696                                         break;
6697                                 case keyCode.UP:
6698                                         suppressKeyPress = true;
6699                                         this._keyEvent( "previous", event );
6700                                         break;
6701                                 case keyCode.DOWN:
6702                                         suppressKeyPress = true;
6703                                         this._keyEvent( "next", event );
6704                                         break;
6705                                 case keyCode.ENTER:
6706                                 case keyCode.NUMPAD_ENTER:
6707                                         // when menu is open and has focus
6708                                         if ( this.menu.active ) {
6709                                                 // #6055 - Opera still allows the keypress to occur
6710                                                 // which causes forms to submit
6711                                                 suppressKeyPress = true;
6712                                                 event.preventDefault();
6713                                                 this.menu.select( event );
6714                                         }
6715                                         break;
6716                                 case keyCode.TAB:
6717                                         if ( this.menu.active ) {
6718                                                 this.menu.select( event );
6719                                         }
6720                                         break;
6721                                 case keyCode.ESCAPE:
6722                                         if ( this.menu.element.is( ":visible" ) ) {
6723                                                 this._value( this.term );
6724                                                 this.close( event );
6725                                                 // Different browsers have different default behavior for escape
6726                                                 // Single press can mean undo or clear
6727                                                 // Double press in IE means clear the whole form
6728                                                 event.preventDefault();
6729                                         }
6730                                         break;
6731                                 default:
6732                                         suppressKeyPressRepeat = true;
6733                                         // search timeout should be triggered before the input value is changed
6734                                         this._searchTimeout( event );
6735                                         break;
6736                                 }
6737                         },
6738                         keypress: function( event ) {
6739                                 if ( suppressKeyPress ) {
6740                                         suppressKeyPress = false;
6741                                         if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
6742                                                 event.preventDefault();
6743                                         }
6744                                         return;
6745                                 }
6746                                 if ( suppressKeyPressRepeat ) {
6747                                         return;
6748                                 }
6750                                 // replicate some key handlers to allow them to repeat in Firefox and Opera
6751                                 var keyCode = $.ui.keyCode;
6752                                 switch( event.keyCode ) {
6753                                 case keyCode.PAGE_UP:
6754                                         this._move( "previousPage", event );
6755                                         break;
6756                                 case keyCode.PAGE_DOWN:
6757                                         this._move( "nextPage", event );
6758                                         break;
6759                                 case keyCode.UP:
6760                                         this._keyEvent( "previous", event );
6761                                         break;
6762                                 case keyCode.DOWN:
6763                                         this._keyEvent( "next", event );
6764                                         break;
6765                                 }
6766                         },
6767                         input: function( event ) {
6768                                 if ( suppressInput ) {
6769                                         suppressInput = false;
6770                                         event.preventDefault();
6771                                         return;
6772                                 }
6773                                 this._searchTimeout( event );
6774                         },
6775                         focus: function() {
6776                                 this.selectedItem = null;
6777                                 this.previous = this._value();
6778                         },
6779                         blur: function( event ) {
6780                                 if ( this.cancelBlur ) {
6781                                         delete this.cancelBlur;
6782                                         return;
6783                                 }
6785                                 clearTimeout( this.searching );
6786                                 this.close( event );
6787                                 this._change( event );
6788                         }
6789                 });
6791                 this._initSource();
6792                 this.menu = $( "<ul>" )
6793                         .addClass( "ui-autocomplete ui-front" )
6794                         .appendTo( this._appendTo() )
6795                         .menu({
6796                                 // disable ARIA support, the live region takes care of that
6797                                 role: null
6798                         })
6799                         .hide()
6800                         .data( "ui-menu" );
6802                 this._on( this.menu.element, {
6803                         mousedown: function( event ) {
6804                                 // prevent moving focus out of the text field
6805                                 event.preventDefault();
6807                                 // IE doesn't prevent moving focus even with event.preventDefault()
6808                                 // so we set a flag to know when we should ignore the blur event
6809                                 this.cancelBlur = true;
6810                                 this._delay(function() {
6811                                         delete this.cancelBlur;
6812                                 });
6814                                 // clicking on the scrollbar causes focus to shift to the body
6815                                 // but we can't detect a mouseup or a click immediately afterward
6816                                 // so we have to track the next mousedown and close the menu if
6817                                 // the user clicks somewhere outside of the autocomplete
6818                                 var menuElement = this.menu.element[ 0 ];
6819                                 if ( !$( event.target ).closest( ".ui-menu-item" ).length ) {
6820                                         this._delay(function() {
6821                                                 var that = this;
6822                                                 this.document.one( "mousedown", function( event ) {
6823                                                         if ( event.target !== that.element[ 0 ] &&
6824                                                                         event.target !== menuElement &&
6825                                                                         !$.contains( menuElement, event.target ) ) {
6826                                                                 that.close();
6827                                                         }
6828                                                 });
6829                                         });
6830                                 }
6831                         },
6832                         menufocus: function( event, ui ) {
6833                                 // support: Firefox
6834                                 // Prevent accidental activation of menu items in Firefox (#7024 #9118)
6835                                 if ( this.isNewMenu ) {
6836                                         this.isNewMenu = false;
6837                                         if ( event.originalEvent && /^mouse/.test( event.originalEvent.type ) ) {
6838                                                 this.menu.blur();
6840                                                 this.document.one( "mousemove", function() {
6841                                                         $( event.target ).trigger( event.originalEvent );
6842                                                 });
6844                                                 return;
6845                                         }
6846                                 }
6848                                 var item = ui.item.data( "ui-autocomplete-item" );
6849                                 if ( false !== this._trigger( "focus", event, { item: item } ) ) {
6850                                         // use value to match what will end up in the input, if it was a key event
6851                                         if ( event.originalEvent && /^key/.test( event.originalEvent.type ) ) {
6852                                                 this._value( item.value );
6853                                         }
6854                                 } else {
6855                                         // Normally the input is populated with the item's value as the
6856                                         // menu is navigated, causing screen readers to notice a change and
6857                                         // announce the item. Since the focus event was canceled, this doesn't
6858                                         // happen, so we update the live region so that screen readers can
6859                                         // still notice the change and announce it.
6860                                         this.liveRegion.text( item.value );
6861                                 }
6862                         },
6863                         menuselect: function( event, ui ) {
6864                                 var item = ui.item.data( "ui-autocomplete-item" ),
6865                                         previous = this.previous;
6867                                 // only trigger when focus was lost (click on menu)
6868                                 if ( this.element[0] !== this.document[0].activeElement ) {
6869                                         this.element.focus();
6870                                         this.previous = previous;
6871                                         // #6109 - IE triggers two focus events and the second
6872                                         // is asynchronous, so we need to reset the previous
6873                                         // term synchronously and asynchronously :-(
6874                                         this._delay(function() {
6875                                                 this.previous = previous;
6876                                                 this.selectedItem = item;
6877                                         });
6878                                 }
6880                                 if ( false !== this._trigger( "select", event, { item: item } ) ) {
6881                                         this._value( item.value );
6882                                 }
6883                                 // reset the term after the select event
6884                                 // this allows custom select handling to work properly
6885                                 this.term = this._value();
6887                                 this.close( event );
6888                                 this.selectedItem = item;
6889                         }
6890                 });
6892                 this.liveRegion = $( "<span>", {
6893                                 role: "status",
6894                                 "aria-live": "polite"
6895                         })
6896                         .addClass( "ui-helper-hidden-accessible" )
6897                         .insertBefore( this.element );
6899                 // turning off autocomplete prevents the browser from remembering the
6900                 // value when navigating through history, so we re-enable autocomplete
6901                 // if the page is unloaded before the widget is destroyed. #7790
6902                 this._on( this.window, {
6903                         beforeunload: function() {
6904                                 this.element.removeAttr( "autocomplete" );
6905                         }
6906                 });
6907         },
6909         _destroy: function() {
6910                 clearTimeout( this.searching );
6911                 this.element
6912                         .removeClass( "ui-autocomplete-input" )
6913                         .removeAttr( "autocomplete" );
6914                 this.menu.element.remove();
6915                 this.liveRegion.remove();
6916         },
6918         _setOption: function( key, value ) {
6919                 this._super( key, value );
6920                 if ( key === "source" ) {
6921                         this._initSource();
6922                 }
6923                 if ( key === "appendTo" ) {
6924                         this.menu.element.appendTo( this._appendTo() );
6925                 }
6926                 if ( key === "disabled" && value && this.xhr ) {
6927                         this.xhr.abort();
6928                 }
6929         },
6931         _appendTo: function() {
6932                 var element = this.options.appendTo;
6934                 if ( element ) {
6935                         element = element.jquery || element.nodeType ?
6936                                 $( element ) :
6937                                 this.document.find( element ).eq( 0 );
6938                 }
6940                 if ( !element ) {
6941                         element = this.element.closest( ".ui-front" );
6942                 }
6944                 if ( !element.length ) {
6945                         element = this.document[0].body;
6946                 }
6948                 return element;
6949         },
6951         _initSource: function() {
6952                 var array, url,
6953                         that = this;
6954                 if ( $.isArray(this.options.source) ) {
6955                         array = this.options.source;
6956                         this.source = function( request, response ) {
6957                                 response( $.ui.autocomplete.filter( array, request.term ) );
6958                         };
6959                 } else if ( typeof this.options.source === "string" ) {
6960                         url = this.options.source;
6961                         this.source = function( request, response ) {
6962                                 if ( that.xhr ) {
6963                                         that.xhr.abort();
6964                                 }
6965                                 that.xhr = $.ajax({
6966                                         url: url,
6967                                         data: request,
6968                                         dataType: "json",
6969                                         success: function( data ) {
6970                                                 response( data );
6971                                         },
6972                                         error: function() {
6973                                                 response( [] );
6974                                         }
6975                                 });
6976                         };
6977                 } else {
6978                         this.source = this.options.source;
6979                 }
6980         },
6982         _searchTimeout: function( event ) {
6983                 clearTimeout( this.searching );
6984                 this.searching = this._delay(function() {
6985                         // only search if the value has changed
6986                         if ( this.term !== this._value() ) {
6987                                 this.selectedItem = null;
6988                                 this.search( null, event );
6989                         }
6990                 }, this.options.delay );
6991         },
6993         search: function( value, event ) {
6994                 value = value != null ? value : this._value();
6996                 // always save the actual value, not the one passed as an argument
6997                 this.term = this._value();
6999                 if ( value.length < this.options.minLength ) {
7000                         return this.close( event );
7001                 }
7003                 if ( this._trigger( "search", event ) === false ) {
7004                         return;
7005                 }
7007                 return this._search( value );
7008         },
7010         _search: function( value ) {
7011                 this.pending++;
7012                 this.element.addClass( "ui-autocomplete-loading" );
7013                 this.cancelSearch = false;
7015                 this.source( { term: value }, this._response() );
7016         },
7018         _response: function() {
7019                 var that = this,
7020                         index = ++requestIndex;
7022                 return function( content ) {
7023                         if ( index === requestIndex ) {
7024                                 that.__response( content );
7025                         }
7027                         that.pending--;
7028                         if ( !that.pending ) {
7029                                 that.element.removeClass( "ui-autocomplete-loading" );
7030                         }
7031                 };
7032         },
7034         __response: function( content ) {
7035                 if ( content ) {
7036                         content = this._normalize( content );
7037                 }
7038                 this._trigger( "response", null, { content: content } );
7039                 if ( !this.options.disabled && content && content.length && !this.cancelSearch ) {
7040                         this._suggest( content );
7041                         this._trigger( "open" );
7042                 } else {
7043                         // use ._close() instead of .close() so we don't cancel future searches
7044                         this._close();
7045                 }
7046         },
7048         close: function( event ) {
7049                 this.cancelSearch = true;
7050                 this._close( event );
7051         },
7053         _close: function( event ) {
7054                 if ( this.menu.element.is( ":visible" ) ) {
7055                         this.menu.element.hide();
7056                         this.menu.blur();
7057                         this.isNewMenu = true;
7058                         this._trigger( "close", event );
7059                 }
7060         },
7062         _change: function( event ) {
7063                 if ( this.previous !== this._value() ) {
7064                         this._trigger( "change", event, { item: this.selectedItem } );
7065                 }
7066         },
7068         _normalize: function( items ) {
7069                 // assume all items have the right format when the first item is complete
7070                 if ( items.length && items[0].label && items[0].value ) {
7071                         return items;
7072                 }
7073                 return $.map( items, function( item ) {
7074                         if ( typeof item === "string" ) {
7075                                 return {
7076                                         label: item,
7077                                         value: item
7078                                 };
7079                         }
7080                         return $.extend({
7081                                 label: item.label || item.value,
7082                                 value: item.value || item.label
7083                         }, item );
7084                 });
7085         },
7087         _suggest: function( items ) {
7088                 var ul = this.menu.element.empty();
7089                 this._renderMenu( ul, items );
7090                 this.isNewMenu = true;
7091                 this.menu.refresh();
7093                 // size and position menu
7094                 ul.show();
7095                 this._resizeMenu();
7096                 ul.position( $.extend({
7097                         of: this.element
7098                 }, this.options.position ));
7100                 if ( this.options.autoFocus ) {
7101                         this.menu.next();
7102                 }
7103         },
7105         _resizeMenu: function() {
7106                 var ul = this.menu.element;
7107                 ul.outerWidth( Math.max(
7108                         // Firefox wraps long text (possibly a rounding bug)
7109                         // so we add 1px to avoid the wrapping (#7513)
7110                         ul.width( "" ).outerWidth() + 1,
7111                         this.element.outerWidth()
7112                 ) );
7113         },
7115         _renderMenu: function( ul, items ) {
7116                 var that = this;
7117                 $.each( items, function( index, item ) {
7118                         that._renderItemData( ul, item );
7119                 });
7120         },
7122         _renderItemData: function( ul, item ) {
7123                 return this._renderItem( ul, item ).data( "ui-autocomplete-item", item );
7124         },
7126         _renderItem: function( ul, item ) {
7127                 return $( "<li>" )
7128                         .append( $( "<a>" ).text( item.label ) )
7129                         .appendTo( ul );
7130         },
7132         _move: function( direction, event ) {
7133                 if ( !this.menu.element.is( ":visible" ) ) {
7134                         this.search( null, event );
7135                         return;
7136                 }
7137                 if ( this.menu.isFirstItem() && /^previous/.test( direction ) ||
7138                                 this.menu.isLastItem() && /^next/.test( direction ) ) {
7139                         this._value( this.term );
7140                         this.menu.blur();
7141                         return;
7142                 }
7143                 this.menu[ direction ]( event );
7144         },
7146         widget: function() {
7147                 return this.menu.element;
7148         },
7150         _value: function() {
7151                 return this.valueMethod.apply( this.element, arguments );
7152         },
7154         _keyEvent: function( keyEvent, event ) {
7155                 if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
7156                         this._move( keyEvent, event );
7158                         // prevents moving cursor to beginning/end of the text field in some browsers
7159                         event.preventDefault();
7160                 }
7161         }
7164 $.extend( $.ui.autocomplete, {
7165         escapeRegex: function( value ) {
7166                 return value.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&");
7167         },
7168         filter: function(array, term) {
7169                 var matcher = new RegExp( $.ui.autocomplete.escapeRegex(term), "i" );
7170                 return $.grep( array, function(value) {
7171                         return matcher.test( value.label || value.value || value );
7172                 });
7173         }
7177 // live region extension, adding a `messages` option
7178 // NOTE: This is an experimental API. We are still investigating
7179 // a full solution for string manipulation and internationalization.
7180 $.widget( "ui.autocomplete", $.ui.autocomplete, {
7181         options: {
7182                 messages: {
7183                         noResults: "No search results.",
7184                         results: function( amount ) {
7185                                 return amount + ( amount > 1 ? " results are" : " result is" ) +
7186                                         " available, use up and down arrow keys to navigate.";
7187                         }
7188                 }
7189         },
7191         __response: function( content ) {
7192                 var message;
7193                 this._superApply( arguments );
7194                 if ( this.options.disabled || this.cancelSearch ) {
7195                         return;
7196                 }
7197                 if ( content && content.length ) {
7198                         message = this.options.messages.results( content.length );
7199                 } else {
7200                         message = this.options.messages.noResults;
7201                 }
7202                 this.liveRegion.text( message );
7203         }
7206 }( jQuery ));
7208 (function( $, undefined ) {
7210 var lastActive, startXPos, startYPos, clickDragged,
7211         baseClasses = "ui-button ui-widget ui-state-default ui-corner-all",
7212         stateClasses = "ui-state-hover ui-state-active ",
7213         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",
7214         formResetHandler = function() {
7215                 var form = $( this );
7216                 setTimeout(function() {
7217                         form.find( ":ui-button" ).button( "refresh" );
7218                 }, 1 );
7219         },
7220         radioGroup = function( radio ) {
7221                 var name = radio.name,
7222                         form = radio.form,
7223                         radios = $( [] );
7224                 if ( name ) {
7225                         name = name.replace( /'/g, "\\'" );
7226                         if ( form ) {
7227                                 radios = $( form ).find( "[name='" + name + "']" );
7228                         } else {
7229                                 radios = $( "[name='" + name + "']", radio.ownerDocument )
7230                                         .filter(function() {
7231                                                 return !this.form;
7232                                         });
7233                         }
7234                 }
7235                 return radios;
7236         };
7238 $.widget( "ui.button", {
7239         version: "1.10.3",
7240         defaultElement: "<button>",
7241         options: {
7242                 disabled: null,
7243                 text: true,
7244                 label: null,
7245                 icons: {
7246                         primary: null,
7247                         secondary: null
7248                 }
7249         },
7250         _create: function() {
7251                 this.element.closest( "form" )
7252                         .unbind( "reset" + this.eventNamespace )
7253                         .bind( "reset" + this.eventNamespace, formResetHandler );
7255                 if ( typeof this.options.disabled !== "boolean" ) {
7256                         this.options.disabled = !!this.element.prop( "disabled" );
7257                 } else {
7258                         this.element.prop( "disabled", this.options.disabled );
7259                 }
7261                 this._determineButtonType();
7262                 this.hasTitle = !!this.buttonElement.attr( "title" );
7264                 var that = this,
7265                         options = this.options,
7266                         toggleButton = this.type === "checkbox" || this.type === "radio",
7267                         activeClass = !toggleButton ? "ui-state-active" : "",
7268                         focusClass = "ui-state-focus";
7270                 if ( options.label === null ) {
7271                         options.label = (this.type === "input" ? this.buttonElement.val() : this.buttonElement.html());
7272                 }
7274                 this._hoverable( this.buttonElement );
7276                 this.buttonElement
7277                         .addClass( baseClasses )
7278                         .attr( "role", "button" )
7279                         .bind( "mouseenter" + this.eventNamespace, function() {
7280                                 if ( options.disabled ) {
7281                                         return;
7282                                 }
7283                                 if ( this === lastActive ) {
7284                                         $( this ).addClass( "ui-state-active" );
7285                                 }
7286                         })
7287                         .bind( "mouseleave" + this.eventNamespace, function() {
7288                                 if ( options.disabled ) {
7289                                         return;
7290                                 }
7291                                 $( this ).removeClass( activeClass );
7292                         })
7293                         .bind( "click" + this.eventNamespace, function( event ) {
7294                                 if ( options.disabled ) {
7295                                         event.preventDefault();
7296                                         event.stopImmediatePropagation();
7297                                 }
7298                         });
7300                 this.element
7301                         .bind( "focus" + this.eventNamespace, function() {
7302                                 // no need to check disabled, focus won't be triggered anyway
7303                                 that.buttonElement.addClass( focusClass );
7304                         })
7305                         .bind( "blur" + this.eventNamespace, function() {
7306                                 that.buttonElement.removeClass( focusClass );
7307                         });
7309                 if ( toggleButton ) {
7310                         this.element.bind( "change" + this.eventNamespace, function() {
7311                                 if ( clickDragged ) {
7312                                         return;
7313                                 }
7314                                 that.refresh();
7315                         });
7316                         // if mouse moves between mousedown and mouseup (drag) set clickDragged flag
7317                         // prevents issue where button state changes but checkbox/radio checked state
7318                         // does not in Firefox (see ticket #6970)
7319                         this.buttonElement
7320                                 .bind( "mousedown" + this.eventNamespace, function( event ) {
7321                                         if ( options.disabled ) {
7322                                                 return;
7323                                         }
7324                                         clickDragged = false;
7325                                         startXPos = event.pageX;
7326                                         startYPos = event.pageY;
7327                                 })
7328                                 .bind( "mouseup" + this.eventNamespace, function( event ) {
7329                                         if ( options.disabled ) {
7330                                                 return;
7331                                         }
7332                                         if ( startXPos !== event.pageX || startYPos !== event.pageY ) {
7333                                                 clickDragged = true;
7334                                         }
7335                         });
7336                 }
7338                 if ( this.type === "checkbox" ) {
7339                         this.buttonElement.bind( "click" + this.eventNamespace, function() {
7340                                 if ( options.disabled || clickDragged ) {
7341                                         return false;
7342                                 }
7343                         });
7344                 } else if ( this.type === "radio" ) {
7345                         this.buttonElement.bind( "click" + this.eventNamespace, function() {
7346                                 if ( options.disabled || clickDragged ) {
7347                                         return false;
7348                                 }
7349                                 $( this ).addClass( "ui-state-active" );
7350                                 that.buttonElement.attr( "aria-pressed", "true" );
7352                                 var radio = that.element[ 0 ];
7353                                 radioGroup( radio )
7354                                         .not( radio )
7355                                         .map(function() {
7356                                                 return $( this ).button( "widget" )[ 0 ];
7357                                         })
7358                                         .removeClass( "ui-state-active" )
7359                                         .attr( "aria-pressed", "false" );
7360                         });
7361                 } else {
7362                         this.buttonElement
7363                                 .bind( "mousedown" + this.eventNamespace, function() {
7364                                         if ( options.disabled ) {
7365                                                 return false;
7366                                         }
7367                                         $( this ).addClass( "ui-state-active" );
7368                                         lastActive = this;
7369                                         that.document.one( "mouseup", function() {
7370                                                 lastActive = null;
7371                                         });
7372                                 })
7373                                 .bind( "mouseup" + this.eventNamespace, function() {
7374                                         if ( options.disabled ) {
7375                                                 return false;
7376                                         }
7377                                         $( this ).removeClass( "ui-state-active" );
7378                                 })
7379                                 .bind( "keydown" + this.eventNamespace, function(event) {
7380                                         if ( options.disabled ) {
7381                                                 return false;
7382                                         }
7383                                         if ( event.keyCode === $.ui.keyCode.SPACE || event.keyCode === $.ui.keyCode.ENTER ) {
7384                                                 $( this ).addClass( "ui-state-active" );
7385                                         }
7386                                 })
7387                                 // see #8559, we bind to blur here in case the button element loses
7388                                 // focus between keydown and keyup, it would be left in an "active" state
7389                                 .bind( "keyup" + this.eventNamespace + " blur" + this.eventNamespace, function() {
7390                                         $( this ).removeClass( "ui-state-active" );
7391                                 });
7393                         if ( this.buttonElement.is("a") ) {
7394                                 this.buttonElement.keyup(function(event) {
7395                                         if ( event.keyCode === $.ui.keyCode.SPACE ) {
7396                                                 // TODO pass through original event correctly (just as 2nd argument doesn't work)
7397                                                 $( this ).click();
7398                                         }
7399                                 });
7400                         }
7401                 }
7403                 // TODO: pull out $.Widget's handling for the disabled option into
7404                 // $.Widget.prototype._setOptionDisabled so it's easy to proxy and can
7405                 // be overridden by individual plugins
7406                 this._setOption( "disabled", options.disabled );
7407                 this._resetButton();
7408         },
7410         _determineButtonType: function() {
7411                 var ancestor, labelSelector, checked;
7413                 if ( this.element.is("[type=checkbox]") ) {
7414                         this.type = "checkbox";
7415                 } else if ( this.element.is("[type=radio]") ) {
7416                         this.type = "radio";
7417                 } else if ( this.element.is("input") ) {
7418                         this.type = "input";
7419                 } else {
7420                         this.type = "button";
7421                 }
7423                 if ( this.type === "checkbox" || this.type === "radio" ) {
7424                         // we don't search against the document in case the element
7425                         // is disconnected from the DOM
7426                         ancestor = this.element.parents().last();
7427                         labelSelector = "label[for='" + this.element.attr("id") + "']";
7428                         this.buttonElement = ancestor.find( labelSelector );
7429                         if ( !this.buttonElement.length ) {
7430                                 ancestor = ancestor.length ? ancestor.siblings() : this.element.siblings();
7431                                 this.buttonElement = ancestor.filter( labelSelector );
7432                                 if ( !this.buttonElement.length ) {
7433                                         this.buttonElement = ancestor.find( labelSelector );
7434                                 }
7435                         }
7436                         this.element.addClass( "ui-helper-hidden-accessible" );
7438                         checked = this.element.is( ":checked" );
7439                         if ( checked ) {
7440                                 this.buttonElement.addClass( "ui-state-active" );
7441                         }
7442                         this.buttonElement.prop( "aria-pressed", checked );
7443                 } else {
7444                         this.buttonElement = this.element;
7445                 }
7446         },
7448         widget: function() {
7449                 return this.buttonElement;
7450         },
7452         _destroy: function() {
7453                 this.element
7454                         .removeClass( "ui-helper-hidden-accessible" );
7455                 this.buttonElement
7456                         .removeClass( baseClasses + " " + stateClasses + " " + typeClasses )
7457                         .removeAttr( "role" )
7458                         .removeAttr( "aria-pressed" )
7459                         .html( this.buttonElement.find(".ui-button-text").html() );
7461                 if ( !this.hasTitle ) {
7462                         this.buttonElement.removeAttr( "title" );
7463                 }
7464         },
7466         _setOption: function( key, value ) {
7467                 this._super( key, value );
7468                 if ( key === "disabled" ) {
7469                         if ( value ) {
7470                                 this.element.prop( "disabled", true );
7471                         } else {
7472                                 this.element.prop( "disabled", false );
7473                         }
7474                         return;
7475                 }
7476                 this._resetButton();
7477         },
7479         refresh: function() {
7480                 //See #8237 & #8828
7481                 var isDisabled = this.element.is( "input, button" ) ? this.element.is( ":disabled" ) : this.element.hasClass( "ui-button-disabled" );
7483                 if ( isDisabled !== this.options.disabled ) {
7484                         this._setOption( "disabled", isDisabled );
7485                 }
7486                 if ( this.type === "radio" ) {
7487                         radioGroup( this.element[0] ).each(function() {
7488                                 if ( $( this ).is( ":checked" ) ) {
7489                                         $( this ).button( "widget" )
7490                                                 .addClass( "ui-state-active" )
7491                                                 .attr( "aria-pressed", "true" );
7492                                 } else {
7493                                         $( this ).button( "widget" )
7494                                                 .removeClass( "ui-state-active" )
7495                                                 .attr( "aria-pressed", "false" );
7496                                 }
7497                         });
7498                 } else if ( this.type === "checkbox" ) {
7499                         if ( this.element.is( ":checked" ) ) {
7500                                 this.buttonElement
7501                                         .addClass( "ui-state-active" )
7502                                         .attr( "aria-pressed", "true" );
7503                         } else {
7504                                 this.buttonElement
7505                                         .removeClass( "ui-state-active" )
7506                                         .attr( "aria-pressed", "false" );
7507                         }
7508                 }
7509         },
7511         _resetButton: function() {
7512                 if ( this.type === "input" ) {
7513                         if ( this.options.label ) {
7514                                 this.element.val( this.options.label );
7515                         }
7516                         return;
7517                 }
7518                 var buttonElement = this.buttonElement.removeClass( typeClasses ),
7519                         buttonText = $( "<span></span>", this.document[0] )
7520                                 .addClass( "ui-button-text" )
7521                                 .html( this.options.label )
7522                                 .appendTo( buttonElement.empty() )
7523                                 .text(),
7524                         icons = this.options.icons,
7525                         multipleIcons = icons.primary && icons.secondary,
7526                         buttonClasses = [];
7528                 if ( icons.primary || icons.secondary ) {
7529                         if ( this.options.text ) {
7530                                 buttonClasses.push( "ui-button-text-icon" + ( multipleIcons ? "s" : ( icons.primary ? "-primary" : "-secondary" ) ) );
7531                         }
7533                         if ( icons.primary ) {
7534                                 buttonElement.prepend( "<span class='ui-button-icon-primary ui-icon " + icons.primary + "'></span>" );
7535                         }
7537                         if ( icons.secondary ) {
7538                                 buttonElement.append( "<span class='ui-button-icon-secondary ui-icon " + icons.secondary + "'></span>" );
7539                         }
7541                         if ( !this.options.text ) {
7542                                 buttonClasses.push( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" );
7544                                 if ( !this.hasTitle ) {
7545                                         buttonElement.attr( "title", $.trim( buttonText ) );
7546                                 }
7547                         }
7548                 } else {
7549                         buttonClasses.push( "ui-button-text-only" );
7550                 }
7551                 buttonElement.addClass( buttonClasses.join( " " ) );
7552         }
7555 $.widget( "ui.buttonset", {
7556         version: "1.10.3",
7557         options: {
7558                 items: "button, input[type=button], input[type=submit], input[type=reset], input[type=checkbox], input[type=radio], a, :data(ui-button)"
7559         },
7561         _create: function() {
7562                 this.element.addClass( "ui-buttonset" );
7563         },
7565         _init: function() {
7566                 this.refresh();
7567         },
7569         _setOption: function( key, value ) {
7570                 if ( key === "disabled" ) {
7571                         this.buttons.button( "option", key, value );
7572                 }
7574                 this._super( key, value );
7575         },
7577         refresh: function() {
7578                 var rtl = this.element.css( "direction" ) === "rtl";
7580                 this.buttons = this.element.find( this.options.items )
7581                         .filter( ":ui-button" )
7582                                 .button( "refresh" )
7583                         .end()
7584                         .not( ":ui-button" )
7585                                 .button()
7586                         .end()
7587                         .map(function() {
7588                                 return $( this ).button( "widget" )[ 0 ];
7589                         })
7590                                 .removeClass( "ui-corner-all ui-corner-left ui-corner-right" )
7591                                 .filter( ":first" )
7592                                         .addClass( rtl ? "ui-corner-right" : "ui-corner-left" )
7593                                 .end()
7594                                 .filter( ":last" )
7595                                         .addClass( rtl ? "ui-corner-left" : "ui-corner-right" )
7596                                 .end()
7597                         .end();
7598         },
7600         _destroy: function() {
7601                 this.element.removeClass( "ui-buttonset" );
7602                 this.buttons
7603                         .map(function() {
7604                                 return $( this ).button( "widget" )[ 0 ];
7605                         })
7606                                 .removeClass( "ui-corner-left ui-corner-right" )
7607                         .end()
7608                         .button( "destroy" );
7609         }
7612 }( jQuery ) );
7614 (function( $, undefined ) {
7616 $.extend($.ui, { datepicker: { version: "1.10.3" } });
7618 var PROP_NAME = "datepicker",
7619         instActive;
7621 /* Date picker manager.
7622    Use the singleton instance of this class, $.datepicker, to interact with the date picker.
7623    Settings for (groups of) date pickers are maintained in an instance object,
7624    allowing multiple different settings on the same page. */
7626 function Datepicker() {
7627         this._curInst = null; // The current instance in use
7628         this._keyEvent = false; // If the last event was a key event
7629         this._disabledInputs = []; // List of date picker inputs that have been disabled
7630         this._datepickerShowing = false; // True if the popup picker is showing , false if not
7631         this._inDialog = false; // True if showing within a "dialog", false if not
7632         this._mainDivId = "ui-datepicker-div"; // The ID of the main datepicker division
7633         this._inlineClass = "ui-datepicker-inline"; // The name of the inline marker class
7634         this._appendClass = "ui-datepicker-append"; // The name of the append marker class
7635         this._triggerClass = "ui-datepicker-trigger"; // The name of the trigger marker class
7636         this._dialogClass = "ui-datepicker-dialog"; // The name of the dialog marker class
7637         this._disableClass = "ui-datepicker-disabled"; // The name of the disabled covering marker class
7638         this._unselectableClass = "ui-datepicker-unselectable"; // The name of the unselectable cell marker class
7639         this._currentClass = "ui-datepicker-current-day"; // The name of the current day marker class
7640         this._dayOverClass = "ui-datepicker-days-cell-over"; // The name of the day hover marker class
7641         this.regional = []; // Available regional settings, indexed by language code
7642         this.regional[""] = { // Default regional settings
7643                 closeText: "Done", // Display text for close link
7644                 prevText: "Prev", // Display text for previous month link
7645                 nextText: "Next", // Display text for next month link
7646                 currentText: "Today", // Display text for current month link
7647                 monthNames: ["January","February","March","April","May","June",
7648                         "July","August","September","October","November","December"], // Names of months for drop-down and formatting
7649                 monthNamesShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], // For formatting
7650                 dayNames: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], // For formatting
7651                 dayNamesShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], // For formatting
7652                 dayNamesMin: ["Su","Mo","Tu","We","Th","Fr","Sa"], // Column headings for days starting at Sunday
7653                 weekHeader: "Wk", // Column header for week of the year
7654                 dateFormat: "mm/dd/yy", // See format options on parseDate
7655                 firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
7656                 isRTL: false, // True if right-to-left language, false if left-to-right
7657                 showMonthAfterYear: false, // True if the year select precedes month, false for month then year
7658                 yearSuffix: "" // Additional text to append to the year in the month headers
7659         };
7660         this._defaults = { // Global defaults for all the date picker instances
7661                 showOn: "focus", // "focus" for popup on focus,
7662                         // "button" for trigger button, or "both" for either
7663                 showAnim: "fadeIn", // Name of jQuery animation for popup
7664                 showOptions: {}, // Options for enhanced animations
7665                 defaultDate: null, // Used when field is blank: actual date,
7666                         // +/-number for offset from today, null for today
7667                 appendText: "", // Display text following the input box, e.g. showing the format
7668                 buttonText: "...", // Text for trigger button
7669                 buttonImage: "", // URL for trigger button image
7670                 buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
7671                 hideIfNoPrevNext: false, // True to hide next/previous month links
7672                         // if not applicable, false to just disable them
7673                 navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
7674                 gotoCurrent: false, // True if today link goes back to current selection instead
7675                 changeMonth: false, // True if month can be selected directly, false if only prev/next
7676                 changeYear: false, // True if year can be selected directly, false if only prev/next
7677                 yearRange: "c-10:c+10", // Range of years to display in drop-down,
7678                         // either relative to today's year (-nn:+nn), relative to currently displayed year
7679                         // (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
7680                 showOtherMonths: false, // True to show dates in other months, false to leave blank
7681                 selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
7682                 showWeek: false, // True to show week of the year, false to not show it
7683                 calculateWeek: this.iso8601Week, // How to calculate the week of the year,
7684                         // takes a Date and returns the number of the week for it
7685                 shortYearCutoff: "+10", // Short year values < this are in the current century,
7686                         // > this are in the previous century,
7687                         // string value starting with "+" for current year + value
7688                 minDate: null, // The earliest selectable date, or null for no limit
7689                 maxDate: null, // The latest selectable date, or null for no limit
7690                 duration: "fast", // Duration of display/closure
7691                 beforeShowDay: null, // Function that takes a date and returns an array with
7692                         // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or "",
7693                         // [2] = cell title (optional), e.g. $.datepicker.noWeekends
7694                 beforeShow: null, // Function that takes an input field and
7695                         // returns a set of custom settings for the date picker
7696                 onSelect: null, // Define a callback function when a date is selected
7697                 onChangeMonthYear: null, // Define a callback function when the month or year is changed
7698                 onClose: null, // Define a callback function when the datepicker is closed
7699                 numberOfMonths: 1, // Number of months to show at a time
7700                 showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
7701                 stepMonths: 1, // Number of months to step back/forward
7702                 stepBigMonths: 12, // Number of months to step back/forward for the big links
7703                 altField: "", // Selector for an alternate field to store selected dates into
7704                 altFormat: "", // The date format to use for the alternate field
7705                 constrainInput: true, // The input is constrained by the current date format
7706                 showButtonPanel: false, // True to show button panel, false to not show it
7707                 autoSize: false, // True to size the input for the date format, false to leave as is
7708                 disabled: false // The initial disabled state
7709         };
7710         $.extend(this._defaults, this.regional[""]);
7711         this.dpDiv = bindHover($("<div id='" + this._mainDivId + "' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>"));
7714 $.extend(Datepicker.prototype, {
7715         /* Class name added to elements to indicate already configured with a date picker. */
7716         markerClassName: "hasDatepicker",
7718         //Keep track of the maximum number of rows displayed (see #7043)
7719         maxRows: 4,
7721         // TODO rename to "widget" when switching to widget factory
7722         _widgetDatepicker: function() {
7723                 return this.dpDiv;
7724         },
7726         /* Override the default settings for all instances of the date picker.
7727          * @param  settings  object - the new settings to use as defaults (anonymous object)
7728          * @return the manager object
7729          */
7730         setDefaults: function(settings) {
7731                 extendRemove(this._defaults, settings || {});
7732                 return this;
7733         },
7735         /* Attach the date picker to a jQuery selection.
7736          * @param  target       element - the target input field or division or span
7737          * @param  settings  object - the new settings to use for this date picker instance (anonymous)
7738          */
7739         _attachDatepicker: function(target, settings) {
7740                 var nodeName, inline, inst;
7741                 nodeName = target.nodeName.toLowerCase();
7742                 inline = (nodeName === "div" || nodeName === "span");
7743                 if (!target.id) {
7744                         this.uuid += 1;
7745                         target.id = "dp" + this.uuid;
7746                 }
7747                 inst = this._newInst($(target), inline);
7748                 inst.settings = $.extend({}, settings || {});
7749                 if (nodeName === "input") {
7750                         this._connectDatepicker(target, inst);
7751                 } else if (inline) {
7752                         this._inlineDatepicker(target, inst);
7753                 }
7754         },
7756         /* Create a new instance object. */
7757         _newInst: function(target, inline) {
7758                 var id = target[0].id.replace(/([^A-Za-z0-9_\-])/g, "\\\\$1"); // escape jQuery meta chars
7759                 return {id: id, input: target, // associated target
7760                         selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
7761                         drawMonth: 0, drawYear: 0, // month being drawn
7762                         inline: inline, // is datepicker inline or not
7763                         dpDiv: (!inline ? this.dpDiv : // presentation div
7764                         bindHover($("<div class='" + this._inlineClass + " ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>")))};
7765         },
7767         /* Attach the date picker to an input field. */
7768         _connectDatepicker: function(target, inst) {
7769                 var input = $(target);
7770                 inst.append = $([]);
7771                 inst.trigger = $([]);
7772                 if (input.hasClass(this.markerClassName)) {
7773                         return;
7774                 }
7775                 this._attachments(input, inst);
7776                 input.addClass(this.markerClassName).keydown(this._doKeyDown).
7777                         keypress(this._doKeyPress).keyup(this._doKeyUp);
7778                 this._autoSize(inst);
7779                 $.data(target, PROP_NAME, inst);
7780                 //If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665)
7781                 if( inst.settings.disabled ) {
7782                         this._disableDatepicker( target );
7783                 }
7784         },
7786         /* Make attachments based on settings. */
7787         _attachments: function(input, inst) {
7788                 var showOn, buttonText, buttonImage,
7789                         appendText = this._get(inst, "appendText"),
7790                         isRTL = this._get(inst, "isRTL");
7792                 if (inst.append) {
7793                         inst.append.remove();
7794                 }
7795                 if (appendText) {
7796                         inst.append = $("<span class='" + this._appendClass + "'>" + appendText + "</span>");
7797                         input[isRTL ? "before" : "after"](inst.append);
7798                 }
7800                 input.unbind("focus", this._showDatepicker);
7802                 if (inst.trigger) {
7803                         inst.trigger.remove();
7804                 }
7806                 showOn = this._get(inst, "showOn");
7807                 if (showOn === "focus" || showOn === "both") { // pop-up date picker when in the marked field
7808                         input.focus(this._showDatepicker);
7809                 }
7810                 if (showOn === "button" || showOn === "both") { // pop-up date picker when button clicked
7811                         buttonText = this._get(inst, "buttonText");
7812                         buttonImage = this._get(inst, "buttonImage");
7813                         inst.trigger = $(this._get(inst, "buttonImageOnly") ?
7814                                 $("<img/>").addClass(this._triggerClass).
7815                                         attr({ src: buttonImage, alt: buttonText, title: buttonText }) :
7816                                 $("<button type='button'></button>").addClass(this._triggerClass).
7817                                         html(!buttonImage ? buttonText : $("<img/>").attr(
7818                                         { src:buttonImage, alt:buttonText, title:buttonText })));
7819                         input[isRTL ? "before" : "after"](inst.trigger);
7820                         inst.trigger.click(function() {
7821                                 if ($.datepicker._datepickerShowing && $.datepicker._lastInput === input[0]) {
7822                                         $.datepicker._hideDatepicker();
7823                                 } else if ($.datepicker._datepickerShowing && $.datepicker._lastInput !== input[0]) {
7824                                         $.datepicker._hideDatepicker();
7825                                         $.datepicker._showDatepicker(input[0]);
7826                                 } else {
7827                                         $.datepicker._showDatepicker(input[0]);
7828                                 }
7829                                 return false;
7830                         });
7831                 }
7832         },
7834         /* Apply the maximum length for the date format. */
7835         _autoSize: function(inst) {
7836                 if (this._get(inst, "autoSize") && !inst.inline) {
7837                         var findMax, max, maxI, i,
7838                                 date = new Date(2009, 12 - 1, 20), // Ensure double digits
7839                                 dateFormat = this._get(inst, "dateFormat");
7841                         if (dateFormat.match(/[DM]/)) {
7842                                 findMax = function(names) {
7843                                         max = 0;
7844                                         maxI = 0;
7845                                         for (i = 0; i < names.length; i++) {
7846                                                 if (names[i].length > max) {
7847                                                         max = names[i].length;
7848                                                         maxI = i;
7849                                                 }
7850                                         }
7851                                         return maxI;
7852                                 };
7853                                 date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ?
7854                                         "monthNames" : "monthNamesShort"))));
7855                                 date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ?
7856                                         "dayNames" : "dayNamesShort"))) + 20 - date.getDay());
7857                         }
7858                         inst.input.attr("size", this._formatDate(inst, date).length);
7859                 }
7860         },
7862         /* Attach an inline date picker to a div. */
7863         _inlineDatepicker: function(target, inst) {
7864                 var divSpan = $(target);
7865                 if (divSpan.hasClass(this.markerClassName)) {
7866                         return;
7867                 }
7868                 divSpan.addClass(this.markerClassName).append(inst.dpDiv);
7869                 $.data(target, PROP_NAME, inst);
7870                 this._setDate(inst, this._getDefaultDate(inst), true);
7871                 this._updateDatepicker(inst);
7872                 this._updateAlternate(inst);
7873                 //If disabled option is true, disable the datepicker before showing it (see ticket #5665)
7874                 if( inst.settings.disabled ) {
7875                         this._disableDatepicker( target );
7876                 }
7877                 // Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements
7878                 // http://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height
7879                 inst.dpDiv.css( "display", "block" );
7880         },
7882         /* Pop-up the date picker in a "dialog" box.
7883          * @param  input element - ignored
7884          * @param  date string or Date - the initial date to display
7885          * @param  onSelect  function - the function to call when a date is selected
7886          * @param  settings  object - update the dialog date picker instance's settings (anonymous object)
7887          * @param  pos int[2] - coordinates for the dialog's position within the screen or
7888          *                                      event - with x/y coordinates or
7889          *                                      leave empty for default (screen centre)
7890          * @return the manager object
7891          */
7892         _dialogDatepicker: function(input, date, onSelect, settings, pos) {
7893                 var id, browserWidth, browserHeight, scrollX, scrollY,
7894                         inst = this._dialogInst; // internal instance
7896                 if (!inst) {
7897                         this.uuid += 1;
7898                         id = "dp" + this.uuid;
7899                         this._dialogInput = $("<input type='text' id='" + id +
7900                                 "' style='position: absolute; top: -100px; width: 0px;'/>");
7901                         this._dialogInput.keydown(this._doKeyDown);
7902                         $("body").append(this._dialogInput);
7903                         inst = this._dialogInst = this._newInst(this._dialogInput, false);
7904                         inst.settings = {};
7905                         $.data(this._dialogInput[0], PROP_NAME, inst);
7906                 }
7907                 extendRemove(inst.settings, settings || {});
7908                 date = (date && date.constructor === Date ? this._formatDate(inst, date) : date);
7909                 this._dialogInput.val(date);
7911                 this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);
7912                 if (!this._pos) {
7913                         browserWidth = document.documentElement.clientWidth;
7914                         browserHeight = document.documentElement.clientHeight;
7915                         scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
7916                         scrollY = document.documentElement.scrollTop || document.body.scrollTop;
7917                         this._pos = // should use actual width/height below
7918                                 [(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY];
7919                 }
7921                 // move input on screen for focus, but hidden behind dialog
7922                 this._dialogInput.css("left", (this._pos[0] + 20) + "px").css("top", this._pos[1] + "px");
7923                 inst.settings.onSelect = onSelect;
7924                 this._inDialog = true;
7925                 this.dpDiv.addClass(this._dialogClass);
7926                 this._showDatepicker(this._dialogInput[0]);
7927                 if ($.blockUI) {
7928                         $.blockUI(this.dpDiv);
7929                 }
7930                 $.data(this._dialogInput[0], PROP_NAME, inst);
7931                 return this;
7932         },
7934         /* Detach a datepicker from its control.
7935          * @param  target       element - the target input field or division or span
7936          */
7937         _destroyDatepicker: function(target) {
7938                 var nodeName,
7939                         $target = $(target),
7940                         inst = $.data(target, PROP_NAME);
7942                 if (!$target.hasClass(this.markerClassName)) {
7943                         return;
7944                 }
7946                 nodeName = target.nodeName.toLowerCase();
7947                 $.removeData(target, PROP_NAME);
7948                 if (nodeName === "input") {
7949                         inst.append.remove();
7950                         inst.trigger.remove();
7951                         $target.removeClass(this.markerClassName).
7952                                 unbind("focus", this._showDatepicker).
7953                                 unbind("keydown", this._doKeyDown).
7954                                 unbind("keypress", this._doKeyPress).
7955                                 unbind("keyup", this._doKeyUp);
7956                 } else if (nodeName === "div" || nodeName === "span") {
7957                         $target.removeClass(this.markerClassName).empty();
7958                 }
7959         },
7961         /* Enable the date picker to a jQuery selection.
7962          * @param  target       element - the target input field or division or span
7963          */
7964         _enableDatepicker: function(target) {
7965                 var nodeName, inline,
7966                         $target = $(target),
7967                         inst = $.data(target, PROP_NAME);
7969                 if (!$target.hasClass(this.markerClassName)) {
7970                         return;
7971                 }
7973                 nodeName = target.nodeName.toLowerCase();
7974                 if (nodeName === "input") {
7975                         target.disabled = false;
7976                         inst.trigger.filter("button").
7977                                 each(function() { this.disabled = false; }).end().
7978                                 filter("img").css({opacity: "1.0", cursor: ""});
7979                 } else if (nodeName === "div" || nodeName === "span") {
7980                         inline = $target.children("." + this._inlineClass);
7981                         inline.children().removeClass("ui-state-disabled");
7982                         inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
7983                                 prop("disabled", false);
7984                 }
7985                 this._disabledInputs = $.map(this._disabledInputs,
7986                         function(value) { return (value === target ? null : value); }); // delete entry
7987         },
7989         /* Disable the date picker to a jQuery selection.
7990          * @param  target       element - the target input field or division or span
7991          */
7992         _disableDatepicker: function(target) {
7993                 var nodeName, inline,
7994                         $target = $(target),
7995                         inst = $.data(target, PROP_NAME);
7997                 if (!$target.hasClass(this.markerClassName)) {
7998                         return;
7999                 }
8001                 nodeName = target.nodeName.toLowerCase();
8002                 if (nodeName === "input") {
8003                         target.disabled = true;
8004                         inst.trigger.filter("button").
8005                                 each(function() { this.disabled = true; }).end().
8006                                 filter("img").css({opacity: "0.5", cursor: "default"});
8007                 } else if (nodeName === "div" || nodeName === "span") {
8008                         inline = $target.children("." + this._inlineClass);
8009                         inline.children().addClass("ui-state-disabled");
8010                         inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
8011                                 prop("disabled", true);
8012                 }
8013                 this._disabledInputs = $.map(this._disabledInputs,
8014                         function(value) { return (value === target ? null : value); }); // delete entry
8015                 this._disabledInputs[this._disabledInputs.length] = target;
8016         },
8018         /* Is the first field in a jQuery collection disabled as a datepicker?
8019          * @param  target       element - the target input field or division or span
8020          * @return boolean - true if disabled, false if enabled
8021          */
8022         _isDisabledDatepicker: function(target) {
8023                 if (!target) {
8024                         return false;
8025                 }
8026                 for (var i = 0; i < this._disabledInputs.length; i++) {
8027                         if (this._disabledInputs[i] === target) {
8028                                 return true;
8029                         }
8030                 }
8031                 return false;
8032         },
8034         /* Retrieve the instance data for the target control.
8035          * @param  target  element - the target input field or division or span
8036          * @return  object - the associated instance data
8037          * @throws  error if a jQuery problem getting data
8038          */
8039         _getInst: function(target) {
8040                 try {
8041                         return $.data(target, PROP_NAME);
8042                 }
8043                 catch (err) {
8044                         throw "Missing instance data for this datepicker";
8045                 }
8046         },
8048         /* Update or retrieve the settings for a date picker attached to an input field or division.
8049          * @param  target  element - the target input field or division or span
8050          * @param  name object - the new settings to update or
8051          *                              string - the name of the setting to change or retrieve,
8052          *                              when retrieving also "all" for all instance settings or
8053          *                              "defaults" for all global defaults
8054          * @param  value   any - the new value for the setting
8055          *                              (omit if above is an object or to retrieve a value)
8056          */
8057         _optionDatepicker: function(target, name, value) {
8058                 var settings, date, minDate, maxDate,
8059                         inst = this._getInst(target);
8061                 if (arguments.length === 2 && typeof name === "string") {
8062                         return (name === "defaults" ? $.extend({}, $.datepicker._defaults) :
8063                                 (inst ? (name === "all" ? $.extend({}, inst.settings) :
8064                                 this._get(inst, name)) : null));
8065                 }
8067                 settings = name || {};
8068                 if (typeof name === "string") {
8069                         settings = {};
8070                         settings[name] = value;
8071                 }
8073                 if (inst) {
8074                         if (this._curInst === inst) {
8075                                 this._hideDatepicker();
8076                         }
8078                         date = this._getDateDatepicker(target, true);
8079                         minDate = this._getMinMaxDate(inst, "min");
8080                         maxDate = this._getMinMaxDate(inst, "max");
8081                         extendRemove(inst.settings, settings);
8082                         // reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided
8083                         if (minDate !== null && settings.dateFormat !== undefined && settings.minDate === undefined) {
8084                                 inst.settings.minDate = this._formatDate(inst, minDate);
8085                         }
8086                         if (maxDate !== null && settings.dateFormat !== undefined && settings.maxDate === undefined) {
8087                                 inst.settings.maxDate = this._formatDate(inst, maxDate);
8088                         }
8089                         if ( "disabled" in settings ) {
8090                                 if ( settings.disabled ) {
8091                                         this._disableDatepicker(target);
8092                                 } else {
8093                                         this._enableDatepicker(target);
8094                                 }
8095                         }
8096                         this._attachments($(target), inst);
8097                         this._autoSize(inst);
8098                         this._setDate(inst, date);
8099                         this._updateAlternate(inst);
8100                         this._updateDatepicker(inst);
8101                 }
8102         },
8104         // change method deprecated
8105         _changeDatepicker: function(target, name, value) {
8106                 this._optionDatepicker(target, name, value);
8107         },
8109         /* Redraw the date picker attached to an input field or division.
8110          * @param  target  element - the target input field or division or span
8111          */
8112         _refreshDatepicker: function(target) {
8113                 var inst = this._getInst(target);
8114                 if (inst) {
8115                         this._updateDatepicker(inst);
8116                 }
8117         },
8119         /* Set the dates for a jQuery selection.
8120          * @param  target element - the target input field or division or span
8121          * @param  date Date - the new date
8122          */
8123         _setDateDatepicker: function(target, date) {
8124                 var inst = this._getInst(target);
8125                 if (inst) {
8126                         this._setDate(inst, date);
8127                         this._updateDatepicker(inst);
8128                         this._updateAlternate(inst);
8129                 }
8130         },
8132         /* Get the date(s) for the first entry in a jQuery selection.
8133          * @param  target element - the target input field or division or span
8134          * @param  noDefault boolean - true if no default date is to be used
8135          * @return Date - the current date
8136          */
8137         _getDateDatepicker: function(target, noDefault) {
8138                 var inst = this._getInst(target);
8139                 if (inst && !inst.inline) {
8140                         this._setDateFromField(inst, noDefault);
8141                 }
8142                 return (inst ? this._getDate(inst) : null);
8143         },
8145         /* Handle keystrokes. */
8146         _doKeyDown: function(event) {
8147                 var onSelect, dateStr, sel,
8148                         inst = $.datepicker._getInst(event.target),
8149                         handled = true,
8150                         isRTL = inst.dpDiv.is(".ui-datepicker-rtl");
8152                 inst._keyEvent = true;
8153                 if ($.datepicker._datepickerShowing) {
8154                         switch (event.keyCode) {
8155                                 case 9: $.datepicker._hideDatepicker();
8156                                                 handled = false;
8157                                                 break; // hide on tab out
8158                                 case 13: sel = $("td." + $.datepicker._dayOverClass + ":not(." +
8159                                                                         $.datepicker._currentClass + ")", inst.dpDiv);
8160                                                 if (sel[0]) {
8161                                                         $.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);
8162                                                 }
8164                                                 onSelect = $.datepicker._get(inst, "onSelect");
8165                                                 if (onSelect) {
8166                                                         dateStr = $.datepicker._formatDate(inst);
8168                                                         // trigger custom callback
8169                                                         onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);
8170                                                 } else {
8171                                                         $.datepicker._hideDatepicker();
8172                                                 }
8174                                                 return false; // don't submit the form
8175                                 case 27: $.datepicker._hideDatepicker();
8176                                                 break; // hide on escape
8177                                 case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
8178                                                         -$.datepicker._get(inst, "stepBigMonths") :
8179                                                         -$.datepicker._get(inst, "stepMonths")), "M");
8180                                                 break; // previous month/year on page up/+ ctrl
8181                                 case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
8182                                                         +$.datepicker._get(inst, "stepBigMonths") :
8183                                                         +$.datepicker._get(inst, "stepMonths")), "M");
8184                                                 break; // next month/year on page down/+ ctrl
8185                                 case 35: if (event.ctrlKey || event.metaKey) {
8186                                                         $.datepicker._clearDate(event.target);
8187                                                 }
8188                                                 handled = event.ctrlKey || event.metaKey;
8189                                                 break; // clear on ctrl or command +end
8190                                 case 36: if (event.ctrlKey || event.metaKey) {
8191                                                         $.datepicker._gotoToday(event.target);
8192                                                 }
8193                                                 handled = event.ctrlKey || event.metaKey;
8194                                                 break; // current on ctrl or command +home
8195                                 case 37: if (event.ctrlKey || event.metaKey) {
8196                                                         $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), "D");
8197                                                 }
8198                                                 handled = event.ctrlKey || event.metaKey;
8199                                                 // -1 day on ctrl or command +left
8200                                                 if (event.originalEvent.altKey) {
8201                                                         $.datepicker._adjustDate(event.target, (event.ctrlKey ?
8202                                                                 -$.datepicker._get(inst, "stepBigMonths") :
8203                                                                 -$.datepicker._get(inst, "stepMonths")), "M");
8204                                                 }
8205                                                 // next month/year on alt +left on Mac
8206                                                 break;
8207                                 case 38: if (event.ctrlKey || event.metaKey) {
8208                                                         $.datepicker._adjustDate(event.target, -7, "D");
8209                                                 }
8210                                                 handled = event.ctrlKey || event.metaKey;
8211                                                 break; // -1 week on ctrl or command +up
8212                                 case 39: if (event.ctrlKey || event.metaKey) {
8213                                                         $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), "D");
8214                                                 }
8215                                                 handled = event.ctrlKey || event.metaKey;
8216                                                 // +1 day on ctrl or command +right
8217                                                 if (event.originalEvent.altKey) {
8218                                                         $.datepicker._adjustDate(event.target, (event.ctrlKey ?
8219                                                                 +$.datepicker._get(inst, "stepBigMonths") :
8220                                                                 +$.datepicker._get(inst, "stepMonths")), "M");
8221                                                 }
8222                                                 // next month/year on alt +right
8223                                                 break;
8224                                 case 40: if (event.ctrlKey || event.metaKey) {
8225                                                         $.datepicker._adjustDate(event.target, +7, "D");
8226                                                 }
8227                                                 handled = event.ctrlKey || event.metaKey;
8228                                                 break; // +1 week on ctrl or command +down
8229                                 default: handled = false;
8230                         }
8231                 } else if (event.keyCode === 36 && event.ctrlKey) { // display the date picker on ctrl+home
8232                         $.datepicker._showDatepicker(this);
8233                 } else {
8234                         handled = false;
8235                 }
8237                 if (handled) {
8238                         event.preventDefault();
8239                         event.stopPropagation();
8240                 }
8241         },
8243         /* Filter entered characters - based on date format. */
8244         _doKeyPress: function(event) {
8245                 var chars, chr,
8246                         inst = $.datepicker._getInst(event.target);
8248                 if ($.datepicker._get(inst, "constrainInput")) {
8249                         chars = $.datepicker._possibleChars($.datepicker._get(inst, "dateFormat"));
8250                         chr = String.fromCharCode(event.charCode == null ? event.keyCode : event.charCode);
8251                         return event.ctrlKey || event.metaKey || (chr < " " || !chars || chars.indexOf(chr) > -1);
8252                 }
8253         },
8255         /* Synchronise manual entry and field/alternate field. */
8256         _doKeyUp: function(event) {
8257                 var date,
8258                         inst = $.datepicker._getInst(event.target);
8260                 if (inst.input.val() !== inst.lastVal) {
8261                         try {
8262                                 date = $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"),
8263                                         (inst.input ? inst.input.val() : null),
8264                                         $.datepicker._getFormatConfig(inst));
8266                                 if (date) { // only if valid
8267                                         $.datepicker._setDateFromField(inst);
8268                                         $.datepicker._updateAlternate(inst);
8269                                         $.datepicker._updateDatepicker(inst);
8270                                 }
8271                         }
8272                         catch (err) {
8273                         }
8274                 }
8275                 return true;
8276         },
8278         /* Pop-up the date picker for a given input field.
8279          * If false returned from beforeShow event handler do not show.
8280          * @param  input  element - the input field attached to the date picker or
8281          *                                      event - if triggered by focus
8282          */
8283         _showDatepicker: function(input) {
8284                 input = input.target || input;
8285                 if (input.nodeName.toLowerCase() !== "input") { // find from button/image trigger
8286                         input = $("input", input.parentNode)[0];
8287                 }
8289                 if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput === input) { // already here
8290                         return;
8291                 }
8293                 var inst, beforeShow, beforeShowSettings, isFixed,
8294                         offset, showAnim, duration;
8296                 inst = $.datepicker._getInst(input);
8297                 if ($.datepicker._curInst && $.datepicker._curInst !== inst) {
8298                         $.datepicker._curInst.dpDiv.stop(true, true);
8299                         if ( inst && $.datepicker._datepickerShowing ) {
8300                                 $.datepicker._hideDatepicker( $.datepicker._curInst.input[0] );
8301                         }
8302                 }
8304                 beforeShow = $.datepicker._get(inst, "beforeShow");
8305                 beforeShowSettings = beforeShow ? beforeShow.apply(input, [input, inst]) : {};
8306                 if(beforeShowSettings === false){
8307                         return;
8308                 }
8309                 extendRemove(inst.settings, beforeShowSettings);
8311                 inst.lastVal = null;
8312                 $.datepicker._lastInput = input;
8313                 $.datepicker._setDateFromField(inst);
8315                 if ($.datepicker._inDialog) { // hide cursor
8316                         input.value = "";
8317                 }
8318                 if (!$.datepicker._pos) { // position below input
8319                         $.datepicker._pos = $.datepicker._findPos(input);
8320                         $.datepicker._pos[1] += input.offsetHeight; // add the height
8321                 }
8323                 isFixed = false;
8324                 $(input).parents().each(function() {
8325                         isFixed |= $(this).css("position") === "fixed";
8326                         return !isFixed;
8327                 });
8329                 offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]};
8330                 $.datepicker._pos = null;
8331                 //to avoid flashes on Firefox
8332                 inst.dpDiv.empty();
8333                 // determine sizing offscreen
8334                 inst.dpDiv.css({position: "absolute", display: "block", top: "-1000px"});
8335                 $.datepicker._updateDatepicker(inst);
8336                 // fix width for dynamic number of date pickers
8337                 // and adjust position before showing
8338                 offset = $.datepicker._checkOffset(inst, offset, isFixed);
8339                 inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ?
8340                         "static" : (isFixed ? "fixed" : "absolute")), display: "none",
8341                         left: offset.left + "px", top: offset.top + "px"});
8343                 if (!inst.inline) {
8344                         showAnim = $.datepicker._get(inst, "showAnim");
8345                         duration = $.datepicker._get(inst, "duration");
8346                         inst.dpDiv.zIndex($(input).zIndex()+1);
8347                         $.datepicker._datepickerShowing = true;
8349                         if ( $.effects && $.effects.effect[ showAnim ] ) {
8350                                 inst.dpDiv.show(showAnim, $.datepicker._get(inst, "showOptions"), duration);
8351                         } else {
8352                                 inst.dpDiv[showAnim || "show"](showAnim ? duration : null);
8353                         }
8355                         if ( $.datepicker._shouldFocusInput( inst ) ) {
8356                                 inst.input.focus();
8357                         }
8359                         $.datepicker._curInst = inst;
8360                 }
8361         },
8363         /* Generate the date picker content. */
8364         _updateDatepicker: function(inst) {
8365                 this.maxRows = 4; //Reset the max number of rows being displayed (see #7043)
8366                 instActive = inst; // for delegate hover events
8367                 inst.dpDiv.empty().append(this._generateHTML(inst));
8368                 this._attachHandlers(inst);
8369                 inst.dpDiv.find("." + this._dayOverClass + " a").mouseover();
8371                 var origyearshtml,
8372                         numMonths = this._getNumberOfMonths(inst),
8373                         cols = numMonths[1],
8374                         width = 17;
8376                 inst.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width("");
8377                 if (cols > 1) {
8378                         inst.dpDiv.addClass("ui-datepicker-multi-" + cols).css("width", (width * cols) + "em");
8379                 }
8380                 inst.dpDiv[(numMonths[0] !== 1 || numMonths[1] !== 1 ? "add" : "remove") +
8381                         "Class"]("ui-datepicker-multi");
8382                 inst.dpDiv[(this._get(inst, "isRTL") ? "add" : "remove") +
8383                         "Class"]("ui-datepicker-rtl");
8385                 if (inst === $.datepicker._curInst && $.datepicker._datepickerShowing && $.datepicker._shouldFocusInput( inst ) ) {
8386                         inst.input.focus();
8387                 }
8389                 // deffered render of the years select (to avoid flashes on Firefox)
8390                 if( inst.yearshtml ){
8391                         origyearshtml = inst.yearshtml;
8392                         setTimeout(function(){
8393                                 //assure that inst.yearshtml didn't change.
8394                                 if( origyearshtml === inst.yearshtml && inst.yearshtml ){
8395                                         inst.dpDiv.find("select.ui-datepicker-year:first").replaceWith(inst.yearshtml);
8396                                 }
8397                                 origyearshtml = inst.yearshtml = null;
8398                         }, 0);
8399                 }
8400         },
8402         // #6694 - don't focus the input if it's already focused
8403         // this breaks the change event in IE
8404         // Support: IE and jQuery <1.9
8405         _shouldFocusInput: function( inst ) {
8406                 return inst.input && inst.input.is( ":visible" ) && !inst.input.is( ":disabled" ) && !inst.input.is( ":focus" );
8407         },
8409         /* Check positioning to remain on screen. */
8410         _checkOffset: function(inst, offset, isFixed) {
8411                 var dpWidth = inst.dpDiv.outerWidth(),
8412                         dpHeight = inst.dpDiv.outerHeight(),
8413                         inputWidth = inst.input ? inst.input.outerWidth() : 0,
8414                         inputHeight = inst.input ? inst.input.outerHeight() : 0,
8415                         viewWidth = document.documentElement.clientWidth + (isFixed ? 0 : $(document).scrollLeft()),
8416                         viewHeight = document.documentElement.clientHeight + (isFixed ? 0 : $(document).scrollTop());
8418                 offset.left -= (this._get(inst, "isRTL") ? (dpWidth - inputWidth) : 0);
8419                 offset.left -= (isFixed && offset.left === inst.input.offset().left) ? $(document).scrollLeft() : 0;
8420                 offset.top -= (isFixed && offset.top === (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;
8422                 // now check if datepicker is showing outside window viewport - move to a better place if so.
8423                 offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?
8424                         Math.abs(offset.left + dpWidth - viewWidth) : 0);
8425                 offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?
8426                         Math.abs(dpHeight + inputHeight) : 0);
8428                 return offset;
8429         },
8431         /* Find an object's position on the screen. */
8432         _findPos: function(obj) {
8433                 var position,
8434                         inst = this._getInst(obj),
8435                         isRTL = this._get(inst, "isRTL");
8437                 while (obj && (obj.type === "hidden" || obj.nodeType !== 1 || $.expr.filters.hidden(obj))) {
8438                         obj = obj[isRTL ? "previousSibling" : "nextSibling"];
8439                 }
8441                 position = $(obj).offset();
8442                 return [position.left, position.top];
8443         },
8445         /* Hide the date picker from view.
8446          * @param  input  element - the input field attached to the date picker
8447          */
8448         _hideDatepicker: function(input) {
8449                 var showAnim, duration, postProcess, onClose,
8450                         inst = this._curInst;
8452                 if (!inst || (input && inst !== $.data(input, PROP_NAME))) {
8453                         return;
8454                 }
8456                 if (this._datepickerShowing) {
8457                         showAnim = this._get(inst, "showAnim");
8458                         duration = this._get(inst, "duration");
8459                         postProcess = function() {
8460                                 $.datepicker._tidyDialog(inst);
8461                         };
8463                         // DEPRECATED: after BC for 1.8.x $.effects[ showAnim ] is not needed
8464                         if ( $.effects && ( $.effects.effect[ showAnim ] || $.effects[ showAnim ] ) ) {
8465                                 inst.dpDiv.hide(showAnim, $.datepicker._get(inst, "showOptions"), duration, postProcess);
8466                         } else {
8467                                 inst.dpDiv[(showAnim === "slideDown" ? "slideUp" :
8468                                         (showAnim === "fadeIn" ? "fadeOut" : "hide"))]((showAnim ? duration : null), postProcess);
8469                         }
8471                         if (!showAnim) {
8472                                 postProcess();
8473                         }
8474                         this._datepickerShowing = false;
8476                         onClose = this._get(inst, "onClose");
8477                         if (onClose) {
8478                                 onClose.apply((inst.input ? inst.input[0] : null), [(inst.input ? inst.input.val() : ""), inst]);
8479                         }
8481                         this._lastInput = null;
8482                         if (this._inDialog) {
8483                                 this._dialogInput.css({ position: "absolute", left: "0", top: "-100px" });
8484                                 if ($.blockUI) {
8485                                         $.unblockUI();
8486                                         $("body").append(this.dpDiv);
8487                                 }
8488                         }
8489                         this._inDialog = false;
8490                 }
8491         },
8493         /* Tidy up after a dialog display. */
8494         _tidyDialog: function(inst) {
8495                 inst.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar");
8496         },
8498         /* Close date picker if clicked elsewhere. */
8499         _checkExternalClick: function(event) {
8500                 if (!$.datepicker._curInst) {
8501                         return;
8502                 }
8504                 var $target = $(event.target),
8505                         inst = $.datepicker._getInst($target[0]);
8507                 if ( ( ( $target[0].id !== $.datepicker._mainDivId &&
8508                                 $target.parents("#" + $.datepicker._mainDivId).length === 0 &&
8509                                 !$target.hasClass($.datepicker.markerClassName) &&
8510                                 !$target.closest("." + $.datepicker._triggerClass).length &&
8511                                 $.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI) ) ) ||
8512                         ( $target.hasClass($.datepicker.markerClassName) && $.datepicker._curInst !== inst ) ) {
8513                                 $.datepicker._hideDatepicker();
8514                 }
8515         },
8517         /* Adjust one of the date sub-fields. */
8518         _adjustDate: function(id, offset, period) {
8519                 var target = $(id),
8520                         inst = this._getInst(target[0]);
8522                 if (this._isDisabledDatepicker(target[0])) {
8523                         return;
8524                 }
8525                 this._adjustInstDate(inst, offset +
8526                         (period === "M" ? this._get(inst, "showCurrentAtPos") : 0), // undo positioning
8527                         period);
8528                 this._updateDatepicker(inst);
8529         },
8531         /* Action for current link. */
8532         _gotoToday: function(id) {
8533                 var date,
8534                         target = $(id),
8535                         inst = this._getInst(target[0]);
8537                 if (this._get(inst, "gotoCurrent") && inst.currentDay) {
8538                         inst.selectedDay = inst.currentDay;
8539                         inst.drawMonth = inst.selectedMonth = inst.currentMonth;
8540                         inst.drawYear = inst.selectedYear = inst.currentYear;
8541                 } else {
8542                         date = new Date();
8543                         inst.selectedDay = date.getDate();
8544                         inst.drawMonth = inst.selectedMonth = date.getMonth();
8545                         inst.drawYear = inst.selectedYear = date.getFullYear();
8546                 }
8547                 this._notifyChange(inst);
8548                 this._adjustDate(target);
8549         },
8551         /* Action for selecting a new month/year. */
8552         _selectMonthYear: function(id, select, period) {
8553                 var target = $(id),
8554                         inst = this._getInst(target[0]);
8556                 inst["selected" + (period === "M" ? "Month" : "Year")] =
8557                 inst["draw" + (period === "M" ? "Month" : "Year")] =
8558                         parseInt(select.options[select.selectedIndex].value,10);
8560                 this._notifyChange(inst);
8561                 this._adjustDate(target);
8562         },
8564         /* Action for selecting a day. */
8565         _selectDay: function(id, month, year, td) {
8566                 var inst,
8567                         target = $(id);
8569                 if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) {
8570                         return;
8571                 }
8573                 inst = this._getInst(target[0]);
8574                 inst.selectedDay = inst.currentDay = $("a", td).html();
8575                 inst.selectedMonth = inst.currentMonth = month;
8576                 inst.selectedYear = inst.currentYear = year;
8577                 this._selectDate(id, this._formatDate(inst,
8578                         inst.currentDay, inst.currentMonth, inst.currentYear));
8579         },
8581         /* Erase the input field and hide the date picker. */
8582         _clearDate: function(id) {
8583                 var target = $(id);
8584                 this._selectDate(target, "");
8585         },
8587         /* Update the input field with the selected date. */
8588         _selectDate: function(id, dateStr) {
8589                 var onSelect,
8590                         target = $(id),
8591                         inst = this._getInst(target[0]);
8593                 dateStr = (dateStr != null ? dateStr : this._formatDate(inst));
8594                 if (inst.input) {
8595                         inst.input.val(dateStr);
8596                 }
8597                 this._updateAlternate(inst);
8599                 onSelect = this._get(inst, "onSelect");
8600                 if (onSelect) {
8601                         onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);  // trigger custom callback
8602                 } else if (inst.input) {
8603                         inst.input.trigger("change"); // fire the change event
8604                 }
8606                 if (inst.inline){
8607                         this._updateDatepicker(inst);
8608                 } else {
8609                         this._hideDatepicker();
8610                         this._lastInput = inst.input[0];
8611                         if (typeof(inst.input[0]) !== "object") {
8612                                 inst.input.focus(); // restore focus
8613                         }
8614                         this._lastInput = null;
8615                 }
8616         },
8618         /* Update any alternate field to synchronise with the main field. */
8619         _updateAlternate: function(inst) {
8620                 var altFormat, date, dateStr,
8621                         altField = this._get(inst, "altField");
8623                 if (altField) { // update alternate field too
8624                         altFormat = this._get(inst, "altFormat") || this._get(inst, "dateFormat");
8625                         date = this._getDate(inst);
8626                         dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst));
8627                         $(altField).each(function() { $(this).val(dateStr); });
8628                 }
8629         },
8631         /* Set as beforeShowDay function to prevent selection of weekends.
8632          * @param  date  Date - the date to customise
8633          * @return [boolean, string] - is this date selectable?, what is its CSS class?
8634          */
8635         noWeekends: function(date) {
8636                 var day = date.getDay();
8637                 return [(day > 0 && day < 6), ""];
8638         },
8640         /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
8641          * @param  date  Date - the date to get the week for
8642          * @return  number - the number of the week within the year that contains this date
8643          */
8644         iso8601Week: function(date) {
8645                 var time,
8646                         checkDate = new Date(date.getTime());
8648                 // Find Thursday of this week starting on Monday
8649                 checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7));
8651                 time = checkDate.getTime();
8652                 checkDate.setMonth(0); // Compare with Jan 1
8653                 checkDate.setDate(1);
8654                 return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
8655         },
8657         /* Parse a string value into a date object.
8658          * See formatDate below for the possible formats.
8659          *
8660          * @param  format string - the expected format of the date
8661          * @param  value string - the date in the above format
8662          * @param  settings Object - attributes include:
8663          *                                      shortYearCutoff  number - the cutoff year for determining the century (optional)
8664          *                                      dayNamesShort   string[7] - abbreviated names of the days from Sunday (optional)
8665          *                                      dayNames                string[7] - names of the days from Sunday (optional)
8666          *                                      monthNamesShort string[12] - abbreviated names of the months (optional)
8667          *                                      monthNames              string[12] - names of the months (optional)
8668          * @return  Date - the extracted date value or null if value is blank
8669          */
8670         parseDate: function (format, value, settings) {
8671                 if (format == null || value == null) {
8672                         throw "Invalid arguments";
8673                 }
8675                 value = (typeof value === "object" ? value.toString() : value + "");
8676                 if (value === "") {
8677                         return null;
8678                 }
8680                 var iFormat, dim, extra,
8681                         iValue = 0,
8682                         shortYearCutoffTemp = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff,
8683                         shortYearCutoff = (typeof shortYearCutoffTemp !== "string" ? shortYearCutoffTemp :
8684                                 new Date().getFullYear() % 100 + parseInt(shortYearCutoffTemp, 10)),
8685                         dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort,
8686                         dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames,
8687                         monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort,
8688                         monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames,
8689                         year = -1,
8690                         month = -1,
8691                         day = -1,
8692                         doy = -1,
8693                         literal = false,
8694                         date,
8695                         // Check whether a format character is doubled
8696                         lookAhead = function(match) {
8697                                 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match);
8698                                 if (matches) {
8699                                         iFormat++;
8700                                 }
8701                                 return matches;
8702                         },
8703                         // Extract a number from the string value
8704                         getNumber = function(match) {
8705                                 var isDoubled = lookAhead(match),
8706                                         size = (match === "@" ? 14 : (match === "!" ? 20 :
8707                                         (match === "y" && isDoubled ? 4 : (match === "o" ? 3 : 2)))),
8708                                         digits = new RegExp("^\\d{1," + size + "}"),
8709                                         num = value.substring(iValue).match(digits);
8710                                 if (!num) {
8711                                         throw "Missing number at position " + iValue;
8712                                 }
8713                                 iValue += num[0].length;
8714                                 return parseInt(num[0], 10);
8715                         },
8716                         // Extract a name from the string value and convert to an index
8717                         getName = function(match, shortNames, longNames) {
8718                                 var index = -1,
8719                                         names = $.map(lookAhead(match) ? longNames : shortNames, function (v, k) {
8720                                                 return [ [k, v] ];
8721                                         }).sort(function (a, b) {
8722                                                 return -(a[1].length - b[1].length);
8723                                         });
8725                                 $.each(names, function (i, pair) {
8726                                         var name = pair[1];
8727                                         if (value.substr(iValue, name.length).toLowerCase() === name.toLowerCase()) {
8728                                                 index = pair[0];
8729                                                 iValue += name.length;
8730                                                 return false;
8731                                         }
8732                                 });
8733                                 if (index !== -1) {
8734                                         return index + 1;
8735                                 } else {
8736                                         throw "Unknown name at position " + iValue;
8737                                 }
8738                         },
8739                         // Confirm that a literal character matches the string value
8740                         checkLiteral = function() {
8741                                 if (value.charAt(iValue) !== format.charAt(iFormat)) {
8742                                         throw "Unexpected literal at position " + iValue;
8743                                 }
8744                                 iValue++;
8745                         };
8747                 for (iFormat = 0; iFormat < format.length; iFormat++) {
8748                         if (literal) {
8749                                 if (format.charAt(iFormat) === "'" && !lookAhead("'")) {
8750                                         literal = false;
8751                                 } else {
8752                                         checkLiteral();
8753                                 }
8754                         } else {
8755                                 switch (format.charAt(iFormat)) {
8756                                         case "d":
8757                                                 day = getNumber("d");
8758                                                 break;
8759                                         case "D":
8760                                                 getName("D", dayNamesShort, dayNames);
8761                                                 break;
8762                                         case "o":
8763                                                 doy = getNumber("o");
8764                                                 break;
8765                                         case "m":
8766                                                 month = getNumber("m");
8767                                                 break;
8768                                         case "M":
8769                                                 month = getName("M", monthNamesShort, monthNames);
8770                                                 break;
8771                                         case "y":
8772                                                 year = getNumber("y");
8773                                                 break;
8774                                         case "@":
8775                                                 date = new Date(getNumber("@"));
8776                                                 year = date.getFullYear();
8777                                                 month = date.getMonth() + 1;
8778                                                 day = date.getDate();
8779                                                 break;
8780                                         case "!":
8781                                                 date = new Date((getNumber("!") - this._ticksTo1970) / 10000);
8782                                                 year = date.getFullYear();
8783                                                 month = date.getMonth() + 1;
8784                                                 day = date.getDate();
8785                                                 break;
8786                                         case "'":
8787                                                 if (lookAhead("'")){
8788                                                         checkLiteral();
8789                                                 } else {
8790                                                         literal = true;
8791                                                 }
8792                                                 break;
8793                                         default:
8794                                                 checkLiteral();
8795                                 }
8796                         }
8797                 }
8799                 if (iValue < value.length){
8800                         extra = value.substr(iValue);
8801                         if (!/^\s+/.test(extra)) {
8802                                 throw "Extra/unparsed characters found in date: " + extra;
8803                         }
8804                 }
8806                 if (year === -1) {
8807                         year = new Date().getFullYear();
8808                 } else if (year < 100) {
8809                         year += new Date().getFullYear() - new Date().getFullYear() % 100 +
8810                                 (year <= shortYearCutoff ? 0 : -100);
8811                 }
8813                 if (doy > -1) {
8814                         month = 1;
8815                         day = doy;
8816                         do {
8817                                 dim = this._getDaysInMonth(year, month - 1);
8818                                 if (day <= dim) {
8819                                         break;
8820                                 }
8821                                 month++;
8822                                 day -= dim;
8823                         } while (true);
8824                 }
8826                 date = this._daylightSavingAdjust(new Date(year, month - 1, day));
8827                 if (date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day) {
8828                         throw "Invalid date"; // E.g. 31/02/00
8829                 }
8830                 return date;
8831         },
8833         /* Standard date formats. */
8834         ATOM: "yy-mm-dd", // RFC 3339 (ISO 8601)
8835         COOKIE: "D, dd M yy",
8836         ISO_8601: "yy-mm-dd",
8837         RFC_822: "D, d M y",
8838         RFC_850: "DD, dd-M-y",
8839         RFC_1036: "D, d M y",
8840         RFC_1123: "D, d M yy",
8841         RFC_2822: "D, d M yy",
8842         RSS: "D, d M y", // RFC 822
8843         TICKS: "!",
8844         TIMESTAMP: "@",
8845         W3C: "yy-mm-dd", // ISO 8601
8847         _ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) +
8848                 Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000),
8850         /* Format a date object into a string value.
8851          * The format can be combinations of the following:
8852          * d  - day of month (no leading zero)
8853          * dd - day of month (two digit)
8854          * o  - day of year (no leading zeros)
8855          * oo - day of year (three digit)
8856          * D  - day name short
8857          * DD - day name long
8858          * m  - month of year (no leading zero)
8859          * mm - month of year (two digit)
8860          * M  - month name short
8861          * MM - month name long
8862          * y  - year (two digit)
8863          * yy - year (four digit)
8864          * @ - Unix timestamp (ms since 01/01/1970)
8865          * ! - Windows ticks (100ns since 01/01/0001)
8866          * "..." - literal text
8867          * '' - single quote
8868          *
8869          * @param  format string - the desired format of the date
8870          * @param  date Date - the date value to format
8871          * @param  settings Object - attributes include:
8872          *                                      dayNamesShort   string[7] - abbreviated names of the days from Sunday (optional)
8873          *                                      dayNames                string[7] - names of the days from Sunday (optional)
8874          *                                      monthNamesShort string[12] - abbreviated names of the months (optional)
8875          *                                      monthNames              string[12] - names of the months (optional)
8876          * @return  string - the date in the above format
8877          */
8878         formatDate: function (format, date, settings) {
8879                 if (!date) {
8880                         return "";
8881                 }
8883                 var iFormat,
8884                         dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort,
8885                         dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames,
8886                         monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort,
8887                         monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames,
8888                         // Check whether a format character is doubled
8889                         lookAhead = function(match) {
8890                                 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match);
8891                                 if (matches) {
8892                                         iFormat++;
8893                                 }
8894                                 return matches;
8895                         },
8896                         // Format a number, with leading zero if necessary
8897                         formatNumber = function(match, value, len) {
8898                                 var num = "" + value;
8899                                 if (lookAhead(match)) {
8900                                         while (num.length < len) {
8901                                                 num = "0" + num;
8902                                         }
8903                                 }
8904                                 return num;
8905                         },
8906                         // Format a name, short or long as requested
8907                         formatName = function(match, value, shortNames, longNames) {
8908                                 return (lookAhead(match) ? longNames[value] : shortNames[value]);
8909                         },
8910                         output = "",
8911                         literal = false;
8913                 if (date) {
8914                         for (iFormat = 0; iFormat < format.length; iFormat++) {
8915                                 if (literal) {
8916                                         if (format.charAt(iFormat) === "'" && !lookAhead("'")) {
8917                                                 literal = false;
8918                                         } else {
8919                                                 output += format.charAt(iFormat);
8920                                         }
8921                                 } else {
8922                                         switch (format.charAt(iFormat)) {
8923                                                 case "d":
8924                                                         output += formatNumber("d", date.getDate(), 2);
8925                                                         break;
8926                                                 case "D":
8927                                                         output += formatName("D", date.getDay(), dayNamesShort, dayNames);
8928                                                         break;
8929                                                 case "o":
8930                                                         output += formatNumber("o",
8931                                                                 Math.round((new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000), 3);
8932                                                         break;
8933                                                 case "m":
8934                                                         output += formatNumber("m", date.getMonth() + 1, 2);
8935                                                         break;
8936                                                 case "M":
8937                                                         output += formatName("M", date.getMonth(), monthNamesShort, monthNames);
8938                                                         break;
8939                                                 case "y":
8940                                                         output += (lookAhead("y") ? date.getFullYear() :
8941                                                                 (date.getYear() % 100 < 10 ? "0" : "") + date.getYear() % 100);
8942                                                         break;
8943                                                 case "@":
8944                                                         output += date.getTime();
8945                                                         break;
8946                                                 case "!":
8947                                                         output += date.getTime() * 10000 + this._ticksTo1970;
8948                                                         break;
8949                                                 case "'":
8950                                                         if (lookAhead("'")) {
8951                                                                 output += "'";
8952                                                         } else {
8953                                                                 literal = true;
8954                                                         }
8955                                                         break;
8956                                                 default:
8957                                                         output += format.charAt(iFormat);
8958                                         }
8959                                 }
8960                         }
8961                 }
8962                 return output;
8963         },
8965         /* Extract all possible characters from the date format. */
8966         _possibleChars: function (format) {
8967                 var iFormat,
8968                         chars = "",
8969                         literal = false,
8970                         // Check whether a format character is doubled
8971                         lookAhead = function(match) {
8972                                 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match);
8973                                 if (matches) {
8974                                         iFormat++;
8975                                 }
8976                                 return matches;
8977                         };
8979                 for (iFormat = 0; iFormat < format.length; iFormat++) {
8980                         if (literal) {
8981                                 if (format.charAt(iFormat) === "'" && !lookAhead("'")) {
8982                                         literal = false;
8983                                 } else {
8984                                         chars += format.charAt(iFormat);
8985                                 }
8986                         } else {
8987                                 switch (format.charAt(iFormat)) {
8988                                         case "d": case "m": case "y": case "@":
8989                                                 chars += "0123456789";
8990                                                 break;
8991                                         case "D": case "M":
8992                                                 return null; // Accept anything
8993                                         case "'":
8994                                                 if (lookAhead("'")) {
8995                                                         chars += "'";
8996                                                 } else {
8997                                                         literal = true;
8998                                                 }
8999                                                 break;
9000                                         default:
9001                                                 chars += format.charAt(iFormat);
9002                                 }
9003                         }
9004                 }
9005                 return chars;
9006         },
9008         /* Get a setting value, defaulting if necessary. */
9009         _get: function(inst, name) {
9010                 return inst.settings[name] !== undefined ?
9011                         inst.settings[name] : this._defaults[name];
9012         },
9014         /* Parse existing date and initialise date picker. */
9015         _setDateFromField: function(inst, noDefault) {
9016                 if (inst.input.val() === inst.lastVal) {
9017                         return;
9018                 }
9020                 var dateFormat = this._get(inst, "dateFormat"),
9021                         dates = inst.lastVal = inst.input ? inst.input.val() : null,
9022                         defaultDate = this._getDefaultDate(inst),
9023                         date = defaultDate,
9024                         settings = this._getFormatConfig(inst);
9026                 try {
9027                         date = this.parseDate(dateFormat, dates, settings) || defaultDate;
9028                 } catch (event) {
9029                         dates = (noDefault ? "" : dates);
9030                 }
9031                 inst.selectedDay = date.getDate();
9032                 inst.drawMonth = inst.selectedMonth = date.getMonth();
9033                 inst.drawYear = inst.selectedYear = date.getFullYear();
9034                 inst.currentDay = (dates ? date.getDate() : 0);
9035                 inst.currentMonth = (dates ? date.getMonth() : 0);
9036                 inst.currentYear = (dates ? date.getFullYear() : 0);
9037                 this._adjustInstDate(inst);
9038         },
9040         /* Retrieve the default date shown on opening. */
9041         _getDefaultDate: function(inst) {
9042                 return this._restrictMinMax(inst,
9043                         this._determineDate(inst, this._get(inst, "defaultDate"), new Date()));
9044         },
9046         /* A date may be specified as an exact value or a relative one. */
9047         _determineDate: function(inst, date, defaultDate) {
9048                 var offsetNumeric = function(offset) {
9049                                 var date = new Date();
9050                                 date.setDate(date.getDate() + offset);
9051                                 return date;
9052                         },
9053                         offsetString = function(offset) {
9054                                 try {
9055                                         return $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"),
9056                                                 offset, $.datepicker._getFormatConfig(inst));
9057                                 }
9058                                 catch (e) {
9059                                         // Ignore
9060                                 }
9062                                 var date = (offset.toLowerCase().match(/^c/) ?
9063                                         $.datepicker._getDate(inst) : null) || new Date(),
9064                                         year = date.getFullYear(),
9065                                         month = date.getMonth(),
9066                                         day = date.getDate(),
9067                                         pattern = /([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,
9068                                         matches = pattern.exec(offset);
9070                                 while (matches) {
9071                                         switch (matches[2] || "d") {
9072                                                 case "d" : case "D" :
9073                                                         day += parseInt(matches[1],10); break;
9074                                                 case "w" : case "W" :
9075                                                         day += parseInt(matches[1],10) * 7; break;
9076                                                 case "m" : case "M" :
9077                                                         month += parseInt(matches[1],10);
9078                                                         day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
9079                                                         break;
9080                                                 case "y": case "Y" :
9081                                                         year += parseInt(matches[1],10);
9082                                                         day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
9083                                                         break;
9084                                         }
9085                                         matches = pattern.exec(offset);
9086                                 }
9087                                 return new Date(year, month, day);
9088                         },
9089                         newDate = (date == null || date === "" ? defaultDate : (typeof date === "string" ? offsetString(date) :
9090                                 (typeof date === "number" ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : new Date(date.getTime()))));
9092                 newDate = (newDate && newDate.toString() === "Invalid Date" ? defaultDate : newDate);
9093                 if (newDate) {
9094                         newDate.setHours(0);
9095                         newDate.setMinutes(0);
9096                         newDate.setSeconds(0);
9097                         newDate.setMilliseconds(0);
9098                 }
9099                 return this._daylightSavingAdjust(newDate);
9100         },
9102         /* Handle switch to/from daylight saving.
9103          * Hours may be non-zero on daylight saving cut-over:
9104          * > 12 when midnight changeover, but then cannot generate
9105          * midnight datetime, so jump to 1AM, otherwise reset.
9106          * @param  date  (Date) the date to check
9107          * @return  (Date) the corrected date
9108          */
9109         _daylightSavingAdjust: function(date) {
9110                 if (!date) {
9111                         return null;
9112                 }
9113                 date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
9114                 return date;
9115         },
9117         /* Set the date(s) directly. */
9118         _setDate: function(inst, date, noChange) {
9119                 var clear = !date,
9120                         origMonth = inst.selectedMonth,
9121                         origYear = inst.selectedYear,
9122                         newDate = this._restrictMinMax(inst, this._determineDate(inst, date, new Date()));
9124                 inst.selectedDay = inst.currentDay = newDate.getDate();
9125                 inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth();
9126                 inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear();
9127                 if ((origMonth !== inst.selectedMonth || origYear !== inst.selectedYear) && !noChange) {
9128                         this._notifyChange(inst);
9129                 }
9130                 this._adjustInstDate(inst);
9131                 if (inst.input) {
9132                         inst.input.val(clear ? "" : this._formatDate(inst));
9133                 }
9134         },
9136         /* Retrieve the date(s) directly. */
9137         _getDate: function(inst) {
9138                 var startDate = (!inst.currentYear || (inst.input && inst.input.val() === "") ? null :
9139                         this._daylightSavingAdjust(new Date(
9140                         inst.currentYear, inst.currentMonth, inst.currentDay)));
9141                         return startDate;
9142         },
9144         /* Attach the onxxx handlers.  These are declared statically so
9145          * they work with static code transformers like Caja.
9146          */
9147         _attachHandlers: function(inst) {
9148                 var stepMonths = this._get(inst, "stepMonths"),
9149                         id = "#" + inst.id.replace( /\\\\/g, "\\" );
9150                 inst.dpDiv.find("[data-handler]").map(function () {
9151                         var handler = {
9152                                 prev: function () {
9153                                         $.datepicker._adjustDate(id, -stepMonths, "M");
9154                                 },
9155                                 next: function () {
9156                                         $.datepicker._adjustDate(id, +stepMonths, "M");
9157                                 },
9158                                 hide: function () {
9159                                         $.datepicker._hideDatepicker();
9160                                 },
9161                                 today: function () {
9162                                         $.datepicker._gotoToday(id);
9163                                 },
9164                                 selectDay: function () {
9165                                         $.datepicker._selectDay(id, +this.getAttribute("data-month"), +this.getAttribute("data-year"), this);
9166                                         return false;
9167                                 },
9168                                 selectMonth: function () {
9169                                         $.datepicker._selectMonthYear(id, this, "M");
9170                                         return false;
9171                                 },
9172                                 selectYear: function () {
9173                                         $.datepicker._selectMonthYear(id, this, "Y");
9174                                         return false;
9175                                 }
9176                         };
9177                         $(this).bind(this.getAttribute("data-event"), handler[this.getAttribute("data-handler")]);
9178                 });
9179         },
9181         /* Generate the HTML for the current state of the date picker. */
9182         _generateHTML: function(inst) {
9183                 var maxDraw, prevText, prev, nextText, next, currentText, gotoDate,
9184                         controls, buttonPanel, firstDay, showWeek, dayNames, dayNamesMin,
9185                         monthNames, monthNamesShort, beforeShowDay, showOtherMonths,
9186                         selectOtherMonths, defaultDate, html, dow, row, group, col, selectedDate,
9187                         cornerClass, calender, thead, day, daysInMonth, leadDays, curRows, numRows,
9188                         printDate, dRow, tbody, daySettings, otherMonth, unselectable,
9189                         tempDate = new Date(),
9190                         today = this._daylightSavingAdjust(
9191                                 new Date(tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate())), // clear time
9192                         isRTL = this._get(inst, "isRTL"),
9193                         showButtonPanel = this._get(inst, "showButtonPanel"),
9194                         hideIfNoPrevNext = this._get(inst, "hideIfNoPrevNext"),
9195                         navigationAsDateFormat = this._get(inst, "navigationAsDateFormat"),
9196                         numMonths = this._getNumberOfMonths(inst),
9197                         showCurrentAtPos = this._get(inst, "showCurrentAtPos"),
9198                         stepMonths = this._get(inst, "stepMonths"),
9199                         isMultiMonth = (numMonths[0] !== 1 || numMonths[1] !== 1),
9200                         currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) :
9201                                 new Date(inst.currentYear, inst.currentMonth, inst.currentDay))),
9202                         minDate = this._getMinMaxDate(inst, "min"),
9203                         maxDate = this._getMinMaxDate(inst, "max"),
9204                         drawMonth = inst.drawMonth - showCurrentAtPos,
9205                         drawYear = inst.drawYear;
9207                 if (drawMonth < 0) {
9208                         drawMonth += 12;
9209                         drawYear--;
9210                 }
9211                 if (maxDate) {
9212                         maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),
9213                                 maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate()));
9214                         maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);
9215                         while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {
9216                                 drawMonth--;
9217                                 if (drawMonth < 0) {
9218                                         drawMonth = 11;
9219                                         drawYear--;
9220                                 }
9221                         }
9222                 }
9223                 inst.drawMonth = drawMonth;
9224                 inst.drawYear = drawYear;
9226                 prevText = this._get(inst, "prevText");
9227                 prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText,
9228                         this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),
9229                         this._getFormatConfig(inst)));
9231                 prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?
9232                         "<a class='ui-datepicker-prev ui-corner-all' data-handler='prev' data-event='click'" +
9233                         " title='" + prevText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "e" : "w") + "'>" + prevText + "</span></a>" :
9234                         (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>"));
9236                 nextText = this._get(inst, "nextText");
9237                 nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText,
9238                         this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),
9239                         this._getFormatConfig(inst)));
9241                 next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?
9242                         "<a class='ui-datepicker-next ui-corner-all' data-handler='next' data-event='click'" +
9243                         " title='" + nextText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "w" : "e") + "'>" + nextText + "</span></a>" :
9244                         (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>"));
9246                 currentText = this._get(inst, "currentText");
9247                 gotoDate = (this._get(inst, "gotoCurrent") && inst.currentDay ? currentDate : today);
9248                 currentText = (!navigationAsDateFormat ? currentText :
9249                         this.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));
9251                 controls = (!inst.inline ? "<button type='button' class='ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all' data-handler='hide' data-event='click'>" +
9252                         this._get(inst, "closeText") + "</button>" : "");
9254                 buttonPanel = (showButtonPanel) ? "<div class='ui-datepicker-buttonpane ui-widget-content'>" + (isRTL ? controls : "") +
9255                         (this._isInRange(inst, gotoDate) ? "<button type='button' class='ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all' data-handler='today' data-event='click'" +
9256                         ">" + currentText + "</button>" : "") + (isRTL ? "" : controls) + "</div>" : "";
9258                 firstDay = parseInt(this._get(inst, "firstDay"),10);
9259                 firstDay = (isNaN(firstDay) ? 0 : firstDay);
9261                 showWeek = this._get(inst, "showWeek");
9262                 dayNames = this._get(inst, "dayNames");
9263                 dayNamesMin = this._get(inst, "dayNamesMin");
9264                 monthNames = this._get(inst, "monthNames");
9265                 monthNamesShort = this._get(inst, "monthNamesShort");
9266                 beforeShowDay = this._get(inst, "beforeShowDay");
9267                 showOtherMonths = this._get(inst, "showOtherMonths");
9268                 selectOtherMonths = this._get(inst, "selectOtherMonths");
9269                 defaultDate = this._getDefaultDate(inst);
9270                 html = "";
9271                 dow;
9272                 for (row = 0; row < numMonths[0]; row++) {
9273                         group = "";
9274                         this.maxRows = 4;
9275                         for (col = 0; col < numMonths[1]; col++) {
9276                                 selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay));
9277                                 cornerClass = " ui-corner-all";
9278                                 calender = "";
9279                                 if (isMultiMonth) {
9280                                         calender += "<div class='ui-datepicker-group";
9281                                         if (numMonths[1] > 1) {
9282                                                 switch (col) {
9283                                                         case 0: calender += " ui-datepicker-group-first";
9284                                                                 cornerClass = " ui-corner-" + (isRTL ? "right" : "left"); break;
9285                                                         case numMonths[1]-1: calender += " ui-datepicker-group-last";
9286                                                                 cornerClass = " ui-corner-" + (isRTL ? "left" : "right"); break;
9287                                                         default: calender += " ui-datepicker-group-middle"; cornerClass = ""; break;
9288                                                 }
9289                                         }
9290                                         calender += "'>";
9291                                 }
9292                                 calender += "<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix" + cornerClass + "'>" +
9293                                         (/all|left/.test(cornerClass) && row === 0 ? (isRTL ? next : prev) : "") +
9294                                         (/all|right/.test(cornerClass) && row === 0 ? (isRTL ? prev : next) : "") +
9295                                         this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,
9296                                         row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers
9297                                         "</div><table class='ui-datepicker-calendar'><thead>" +
9298                                         "<tr>";
9299                                 thead = (showWeek ? "<th class='ui-datepicker-week-col'>" + this._get(inst, "weekHeader") + "</th>" : "");
9300                                 for (dow = 0; dow < 7; dow++) { // days of the week
9301                                         day = (dow + firstDay) % 7;
9302                                         thead += "<th" + ((dow + firstDay + 6) % 7 >= 5 ? " class='ui-datepicker-week-end'" : "") + ">" +
9303                                                 "<span title='" + dayNames[day] + "'>" + dayNamesMin[day] + "</span></th>";
9304                                 }
9305                                 calender += thead + "</tr></thead><tbody>";
9306                                 daysInMonth = this._getDaysInMonth(drawYear, drawMonth);
9307                                 if (drawYear === inst.selectedYear && drawMonth === inst.selectedMonth) {
9308                                         inst.selectedDay = Math.min(inst.selectedDay, daysInMonth);
9309                                 }
9310                                 leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;
9311                                 curRows = Math.ceil((leadDays + daysInMonth) / 7); // calculate the number of rows to generate
9312                                 numRows = (isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows); //If multiple months, use the higher number of rows (see #7043)
9313                                 this.maxRows = numRows;
9314                                 printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
9315                                 for (dRow = 0; dRow < numRows; dRow++) { // create date picker rows
9316                                         calender += "<tr>";
9317                                         tbody = (!showWeek ? "" : "<td class='ui-datepicker-week-col'>" +
9318                                                 this._get(inst, "calculateWeek")(printDate) + "</td>");
9319                                         for (dow = 0; dow < 7; dow++) { // create date picker days
9320                                                 daySettings = (beforeShowDay ?
9321                                                         beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, ""]);
9322                                                 otherMonth = (printDate.getMonth() !== drawMonth);
9323                                                 unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] ||
9324                                                         (minDate && printDate < minDate) || (maxDate && printDate > maxDate);
9325                                                 tbody += "<td class='" +
9326                                                         ((dow + firstDay + 6) % 7 >= 5 ? " ui-datepicker-week-end" : "") + // highlight weekends
9327                                                         (otherMonth ? " ui-datepicker-other-month" : "") + // highlight days from other months
9328                                                         ((printDate.getTime() === selectedDate.getTime() && drawMonth === inst.selectedMonth && inst._keyEvent) || // user pressed key
9329                                                         (defaultDate.getTime() === printDate.getTime() && defaultDate.getTime() === selectedDate.getTime()) ?
9330                                                         // or defaultDate is current printedDate and defaultDate is selectedDate
9331                                                         " " + this._dayOverClass : "") + // highlight selected day
9332                                                         (unselectable ? " " + this._unselectableClass + " ui-state-disabled": "") +  // highlight unselectable days
9333                                                         (otherMonth && !showOtherMonths ? "" : " " + daySettings[1] + // highlight custom dates
9334                                                         (printDate.getTime() === currentDate.getTime() ? " " + this._currentClass : "") + // highlight selected day
9335                                                         (printDate.getTime() === today.getTime() ? " ui-datepicker-today" : "")) + "'" + // highlight today (if different)
9336                                                         ((!otherMonth || showOtherMonths) && daySettings[2] ? " title='" + daySettings[2].replace(/'/g, "&#39;") + "'" : "") + // cell title
9337                                                         (unselectable ? "" : " data-handler='selectDay' data-event='click' data-month='" + printDate.getMonth() + "' data-year='" + printDate.getFullYear() + "'") + ">" + // actions
9338                                                         (otherMonth && !showOtherMonths ? "&#xa0;" : // display for other months
9339                                                         (unselectable ? "<span class='ui-state-default'>" + printDate.getDate() + "</span>" : "<a class='ui-state-default" +
9340                                                         (printDate.getTime() === today.getTime() ? " ui-state-highlight" : "") +
9341                                                         (printDate.getTime() === currentDate.getTime() ? " ui-state-active" : "") + // highlight selected day
9342                                                         (otherMonth ? " ui-priority-secondary" : "") + // distinguish dates from other months
9343                                                         "' href='#'>" + printDate.getDate() + "</a>")) + "</td>"; // display selectable date
9344                                                 printDate.setDate(printDate.getDate() + 1);
9345                                                 printDate = this._daylightSavingAdjust(printDate);
9346                                         }
9347                                         calender += tbody + "</tr>";
9348                                 }
9349                                 drawMonth++;
9350                                 if (drawMonth > 11) {
9351                                         drawMonth = 0;
9352                                         drawYear++;
9353                                 }
9354                                 calender += "</tbody></table>" + (isMultiMonth ? "</div>" +
9355                                                         ((numMonths[0] > 0 && col === numMonths[1]-1) ? "<div class='ui-datepicker-row-break'></div>" : "") : "");
9356                                 group += calender;
9357                         }
9358                         html += group;
9359                 }
9360                 html += buttonPanel;
9361                 inst._keyEvent = false;
9362                 return html;
9363         },
9365         /* Generate the month and year header. */
9366         _generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate,
9367                         secondary, monthNames, monthNamesShort) {
9369                 var inMinYear, inMaxYear, month, years, thisYear, determineYear, year, endYear,
9370                         changeMonth = this._get(inst, "changeMonth"),
9371                         changeYear = this._get(inst, "changeYear"),
9372                         showMonthAfterYear = this._get(inst, "showMonthAfterYear"),
9373                         html = "<div class='ui-datepicker-title'>",
9374                         monthHtml = "";
9376                 // month selection
9377                 if (secondary || !changeMonth) {
9378                         monthHtml += "<span class='ui-datepicker-month'>" + monthNames[drawMonth] + "</span>";
9379                 } else {
9380                         inMinYear = (minDate && minDate.getFullYear() === drawYear);
9381                         inMaxYear = (maxDate && maxDate.getFullYear() === drawYear);
9382                         monthHtml += "<select class='ui-datepicker-month' data-handler='selectMonth' data-event='change'>";
9383                         for ( month = 0; month < 12; month++) {
9384                                 if ((!inMinYear || month >= minDate.getMonth()) && (!inMaxYear || month <= maxDate.getMonth())) {
9385                                         monthHtml += "<option value='" + month + "'" +
9386                                                 (month === drawMonth ? " selected='selected'" : "") +
9387                                                 ">" + monthNamesShort[month] + "</option>";
9388                                 }
9389                         }
9390                         monthHtml += "</select>";
9391                 }
9393                 if (!showMonthAfterYear) {
9394                         html += monthHtml + (secondary || !(changeMonth && changeYear) ? "&#xa0;" : "");
9395                 }
9397                 // year selection
9398                 if ( !inst.yearshtml ) {
9399                         inst.yearshtml = "";
9400                         if (secondary || !changeYear) {
9401                                 html += "<span class='ui-datepicker-year'>" + drawYear + "</span>";
9402                         } else {
9403                                 // determine range of years to display
9404                                 years = this._get(inst, "yearRange").split(":");
9405                                 thisYear = new Date().getFullYear();
9406                                 determineYear = function(value) {
9407                                         var year = (value.match(/c[+\-].*/) ? drawYear + parseInt(value.substring(1), 10) :
9408                                                 (value.match(/[+\-].*/) ? thisYear + parseInt(value, 10) :
9409                                                 parseInt(value, 10)));
9410                                         return (isNaN(year) ? thisYear : year);
9411                                 };
9412                                 year = determineYear(years[0]);
9413                                 endYear = Math.max(year, determineYear(years[1] || ""));
9414                                 year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
9415                                 endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
9416                                 inst.yearshtml += "<select class='ui-datepicker-year' data-handler='selectYear' data-event='change'>";
9417                                 for (; year <= endYear; year++) {
9418                                         inst.yearshtml += "<option value='" + year + "'" +
9419                                                 (year === drawYear ? " selected='selected'" : "") +
9420                                                 ">" + year + "</option>";
9421                                 }
9422                                 inst.yearshtml += "</select>";
9424                                 html += inst.yearshtml;
9425                                 inst.yearshtml = null;
9426                         }
9427                 }
9429                 html += this._get(inst, "yearSuffix");
9430                 if (showMonthAfterYear) {
9431                         html += (secondary || !(changeMonth && changeYear) ? "&#xa0;" : "") + monthHtml;
9432                 }
9433                 html += "</div>"; // Close datepicker_header
9434                 return html;
9435         },
9437         /* Adjust one of the date sub-fields. */
9438         _adjustInstDate: function(inst, offset, period) {
9439                 var year = inst.drawYear + (period === "Y" ? offset : 0),
9440                         month = inst.drawMonth + (period === "M" ? offset : 0),
9441                         day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) + (period === "D" ? offset : 0),
9442                         date = this._restrictMinMax(inst, this._daylightSavingAdjust(new Date(year, month, day)));
9444                 inst.selectedDay = date.getDate();
9445                 inst.drawMonth = inst.selectedMonth = date.getMonth();
9446                 inst.drawYear = inst.selectedYear = date.getFullYear();
9447                 if (period === "M" || period === "Y") {
9448                         this._notifyChange(inst);
9449                 }
9450         },
9452         /* Ensure a date is within any min/max bounds. */
9453         _restrictMinMax: function(inst, date) {
9454                 var minDate = this._getMinMaxDate(inst, "min"),
9455                         maxDate = this._getMinMaxDate(inst, "max"),
9456                         newDate = (minDate && date < minDate ? minDate : date);
9457                 return (maxDate && newDate > maxDate ? maxDate : newDate);
9458         },
9460         /* Notify change of month/year. */
9461         _notifyChange: function(inst) {
9462                 var onChange = this._get(inst, "onChangeMonthYear");
9463                 if (onChange) {
9464                         onChange.apply((inst.input ? inst.input[0] : null),
9465                                 [inst.selectedYear, inst.selectedMonth + 1, inst]);
9466                 }
9467         },
9469         /* Determine the number of months to show. */
9470         _getNumberOfMonths: function(inst) {
9471                 var numMonths = this._get(inst, "numberOfMonths");
9472                 return (numMonths == null ? [1, 1] : (typeof numMonths === "number" ? [1, numMonths] : numMonths));
9473         },
9475         /* Determine the current maximum date - ensure no time components are set. */
9476         _getMinMaxDate: function(inst, minMax) {
9477                 return this._determineDate(inst, this._get(inst, minMax + "Date"), null);
9478         },
9480         /* Find the number of days in a given month. */
9481         _getDaysInMonth: function(year, month) {
9482                 return 32 - this._daylightSavingAdjust(new Date(year, month, 32)).getDate();
9483         },
9485         /* Find the day of the week of the first of a month. */
9486         _getFirstDayOfMonth: function(year, month) {
9487                 return new Date(year, month, 1).getDay();
9488         },
9490         /* Determines if we should allow a "next/prev" month display change. */
9491         _canAdjustMonth: function(inst, offset, curYear, curMonth) {
9492                 var numMonths = this._getNumberOfMonths(inst),
9493                         date = this._daylightSavingAdjust(new Date(curYear,
9494                         curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1));
9496                 if (offset < 0) {
9497                         date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
9498                 }
9499                 return this._isInRange(inst, date);
9500         },
9502         /* Is the given date in the accepted range? */
9503         _isInRange: function(inst, date) {
9504                 var yearSplit, currentYear,
9505                         minDate = this._getMinMaxDate(inst, "min"),
9506                         maxDate = this._getMinMaxDate(inst, "max"),
9507                         minYear = null,
9508                         maxYear = null,
9509                         years = this._get(inst, "yearRange");
9510                         if (years){
9511                                 yearSplit = years.split(":");
9512                                 currentYear = new Date().getFullYear();
9513                                 minYear = parseInt(yearSplit[0], 10);
9514                                 maxYear = parseInt(yearSplit[1], 10);
9515                                 if ( yearSplit[0].match(/[+\-].*/) ) {
9516                                         minYear += currentYear;
9517                                 }
9518                                 if ( yearSplit[1].match(/[+\-].*/) ) {
9519                                         maxYear += currentYear;
9520                                 }
9521                         }
9523                 return ((!minDate || date.getTime() >= minDate.getTime()) &&
9524                         (!maxDate || date.getTime() <= maxDate.getTime()) &&
9525                         (!minYear || date.getFullYear() >= minYear) &&
9526                         (!maxYear || date.getFullYear() <= maxYear));
9527         },
9529         /* Provide the configuration settings for formatting/parsing. */
9530         _getFormatConfig: function(inst) {
9531                 var shortYearCutoff = this._get(inst, "shortYearCutoff");
9532                 shortYearCutoff = (typeof shortYearCutoff !== "string" ? shortYearCutoff :
9533                         new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
9534                 return {shortYearCutoff: shortYearCutoff,
9535                         dayNamesShort: this._get(inst, "dayNamesShort"), dayNames: this._get(inst, "dayNames"),
9536                         monthNamesShort: this._get(inst, "monthNamesShort"), monthNames: this._get(inst, "monthNames")};
9537         },
9539         /* Format the given date for display. */
9540         _formatDate: function(inst, day, month, year) {
9541                 if (!day) {
9542                         inst.currentDay = inst.selectedDay;
9543                         inst.currentMonth = inst.selectedMonth;
9544                         inst.currentYear = inst.selectedYear;
9545                 }
9546                 var date = (day ? (typeof day === "object" ? day :
9547                         this._daylightSavingAdjust(new Date(year, month, day))) :
9548                         this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
9549                 return this.formatDate(this._get(inst, "dateFormat"), date, this._getFormatConfig(inst));
9550         }
9554  * Bind hover events for datepicker elements.
9555  * Done via delegate so the binding only occurs once in the lifetime of the parent div.
9556  * Global instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker.
9557  */
9558 function bindHover(dpDiv) {
9559         var selector = "button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";
9560         return dpDiv.delegate(selector, "mouseout", function() {
9561                         $(this).removeClass("ui-state-hover");
9562                         if (this.className.indexOf("ui-datepicker-prev") !== -1) {
9563                                 $(this).removeClass("ui-datepicker-prev-hover");
9564                         }
9565                         if (this.className.indexOf("ui-datepicker-next") !== -1) {
9566                                 $(this).removeClass("ui-datepicker-next-hover");
9567                         }
9568                 })
9569                 .delegate(selector, "mouseover", function(){
9570                         if (!$.datepicker._isDisabledDatepicker( instActive.inline ? dpDiv.parent()[0] : instActive.input[0])) {
9571                                 $(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover");
9572                                 $(this).addClass("ui-state-hover");
9573                                 if (this.className.indexOf("ui-datepicker-prev") !== -1) {
9574                                         $(this).addClass("ui-datepicker-prev-hover");
9575                                 }
9576                                 if (this.className.indexOf("ui-datepicker-next") !== -1) {
9577                                         $(this).addClass("ui-datepicker-next-hover");
9578                                 }
9579                         }
9580                 });
9583 /* jQuery extend now ignores nulls! */
9584 function extendRemove(target, props) {
9585         $.extend(target, props);
9586         for (var name in props) {
9587                 if (props[name] == null) {
9588                         target[name] = props[name];
9589                 }
9590         }
9591         return target;
9594 /* Invoke the datepicker functionality.
9595    @param  options  string - a command, optionally followed by additional parameters or
9596                                         Object - settings for attaching new datepicker functionality
9597    @return  jQuery object */
9598 $.fn.datepicker = function(options){
9600         /* Verify an empty collection wasn't passed - Fixes #6976 */
9601         if ( !this.length ) {
9602                 return this;
9603         }
9605         /* Initialise the date picker. */
9606         if (!$.datepicker.initialized) {
9607                 $(document).mousedown($.datepicker._checkExternalClick);
9608                 $.datepicker.initialized = true;
9609         }
9611         /* Append datepicker main container to body if not exist. */
9612         if ($("#"+$.datepicker._mainDivId).length === 0) {
9613                 $("body").append($.datepicker.dpDiv);
9614         }
9616         var otherArgs = Array.prototype.slice.call(arguments, 1);
9617         if (typeof options === "string" && (options === "isDisabled" || options === "getDate" || options === "widget")) {
9618                 return $.datepicker["_" + options + "Datepicker"].
9619                         apply($.datepicker, [this[0]].concat(otherArgs));
9620         }
9621         if (options === "option" && arguments.length === 2 && typeof arguments[1] === "string") {
9622                 return $.datepicker["_" + options + "Datepicker"].
9623                         apply($.datepicker, [this[0]].concat(otherArgs));
9624         }
9625         return this.each(function() {
9626                 typeof options === "string" ?
9627                         $.datepicker["_" + options + "Datepicker"].
9628                                 apply($.datepicker, [this].concat(otherArgs)) :
9629                         $.datepicker._attachDatepicker(this, options);
9630         });
9633 $.datepicker = new Datepicker(); // singleton instance
9634 $.datepicker.initialized = false;
9635 $.datepicker.uuid = new Date().getTime();
9636 $.datepicker.version = "1.10.3";
9638 })(jQuery);
9640 (function( $, undefined ) {
9642 var sizeRelatedOptions = {
9643                 buttons: true,
9644                 height: true,
9645                 maxHeight: true,
9646                 maxWidth: true,
9647                 minHeight: true,
9648                 minWidth: true,
9649                 width: true
9650         },
9651         resizableRelatedOptions = {
9652                 maxHeight: true,
9653                 maxWidth: true,
9654                 minHeight: true,
9655                 minWidth: true
9656         };
9658 $.widget( "ui.dialog", {
9659         version: "1.10.3",
9660         options: {
9661                 appendTo: "body",
9662                 autoOpen: true,
9663                 buttons: [],
9664                 closeOnEscape: true,
9665                 closeText: "close",
9666                 dialogClass: "",
9667                 draggable: true,
9668                 hide: null,
9669                 height: "auto",
9670                 maxHeight: null,
9671                 maxWidth: null,
9672                 minHeight: 150,
9673                 minWidth: 150,
9674                 modal: false,
9675                 position: {
9676                         my: "center",
9677                         at: "center",
9678                         of: window,
9679                         collision: "fit",
9680                         // Ensure the titlebar is always visible
9681                         using: function( pos ) {
9682                                 var topOffset = $( this ).css( pos ).offset().top;
9683                                 if ( topOffset < 0 ) {
9684                                         $( this ).css( "top", pos.top - topOffset );
9685                                 }
9686                         }
9687                 },
9688                 resizable: true,
9689                 show: null,
9690                 title: null,
9691                 width: 300,
9693                 // callbacks
9694                 beforeClose: null,
9695                 close: null,
9696                 drag: null,
9697                 dragStart: null,
9698                 dragStop: null,
9699                 focus: null,
9700                 open: null,
9701                 resize: null,
9702                 resizeStart: null,
9703                 resizeStop: null
9704         },
9706         _create: function() {
9707                 this.originalCss = {
9708                         display: this.element[0].style.display,
9709                         width: this.element[0].style.width,
9710                         minHeight: this.element[0].style.minHeight,
9711                         maxHeight: this.element[0].style.maxHeight,
9712                         height: this.element[0].style.height
9713                 };
9714                 this.originalPosition = {
9715                         parent: this.element.parent(),
9716                         index: this.element.parent().children().index( this.element )
9717                 };
9718                 this.originalTitle = this.element.attr("title");
9719                 this.options.title = this.options.title || this.originalTitle;
9721                 this._createWrapper();
9723                 this.element
9724                         .show()
9725                         .removeAttr("title")
9726                         .addClass("ui-dialog-content ui-widget-content")
9727                         .appendTo( this.uiDialog );
9729                 this._createTitlebar();
9730                 this._createButtonPane();
9732                 if ( this.options.draggable && $.fn.draggable ) {
9733                         this._makeDraggable();
9734                 }
9735                 if ( this.options.resizable && $.fn.resizable ) {
9736                         this._makeResizable();
9737                 }
9739                 this._isOpen = false;
9740         },
9742         _init: function() {
9743                 if ( this.options.autoOpen ) {
9744                         this.open();
9745                 }
9746         },
9748         _appendTo: function() {
9749                 var element = this.options.appendTo;
9750                 if ( element && (element.jquery || element.nodeType) ) {
9751                         return $( element );
9752                 }
9753                 return this.document.find( element || "body" ).eq( 0 );
9754         },
9756         _destroy: function() {
9757                 var next,
9758                         originalPosition = this.originalPosition;
9760                 this._destroyOverlay();
9762                 this.element
9763                         .removeUniqueId()
9764                         .removeClass("ui-dialog-content ui-widget-content")
9765                         .css( this.originalCss )
9766                         // Without detaching first, the following becomes really slow
9767                         .detach();
9769                 this.uiDialog.stop( true, true ).remove();
9771                 if ( this.originalTitle ) {
9772                         this.element.attr( "title", this.originalTitle );
9773                 }
9775                 next = originalPosition.parent.children().eq( originalPosition.index );
9776                 // Don't try to place the dialog next to itself (#8613)
9777                 if ( next.length && next[0] !== this.element[0] ) {
9778                         next.before( this.element );
9779                 } else {
9780                         originalPosition.parent.append( this.element );
9781                 }
9782         },
9784         widget: function() {
9785                 return this.uiDialog;
9786         },
9788         disable: $.noop,
9789         enable: $.noop,
9791         close: function( event ) {
9792                 var that = this;
9794                 if ( !this._isOpen || this._trigger( "beforeClose", event ) === false ) {
9795                         return;
9796                 }
9798                 this._isOpen = false;
9799                 this._destroyOverlay();
9801                 if ( !this.opener.filter(":focusable").focus().length ) {
9802                         // Hiding a focused element doesn't trigger blur in WebKit
9803                         // so in case we have nothing to focus on, explicitly blur the active element
9804                         // https://bugs.webkit.org/show_bug.cgi?id=47182
9805                         $( this.document[0].activeElement ).blur();
9806                 }
9808                 this._hide( this.uiDialog, this.options.hide, function() {
9809                         that._trigger( "close", event );
9810                 });
9811         },
9813         isOpen: function() {
9814                 return this._isOpen;
9815         },
9817         moveToTop: function() {
9818                 this._moveToTop();
9819         },
9821         _moveToTop: function( event, silent ) {
9822                 var moved = !!this.uiDialog.nextAll(":visible").insertBefore( this.uiDialog ).length;
9823                 if ( moved && !silent ) {
9824                         this._trigger( "focus", event );
9825                 }
9826                 return moved;
9827         },
9829         open: function() {
9830                 var that = this;
9831                 if ( this._isOpen ) {
9832                         if ( this._moveToTop() ) {
9833                                 this._focusTabbable();
9834                         }
9835                         return;
9836                 }
9838                 this._isOpen = true;
9839                 this.opener = $( this.document[0].activeElement );
9841                 this._size();
9842                 this._position();
9843                 this._createOverlay();
9844                 this._moveToTop( null, true );
9845                 this._show( this.uiDialog, this.options.show, function() {
9846                         that._focusTabbable();
9847                         that._trigger("focus");
9848                 });
9850                 this._trigger("open");
9851         },
9853         _focusTabbable: function() {
9854                 // Set focus to the first match:
9855                 // 1. First element inside the dialog matching [autofocus]
9856                 // 2. Tabbable element inside the content element
9857                 // 3. Tabbable element inside the buttonpane
9858                 // 4. The close button
9859                 // 5. The dialog itself
9860                 var hasFocus = this.element.find("[autofocus]");
9861                 if ( !hasFocus.length ) {
9862                         hasFocus = this.element.find(":tabbable");
9863                 }
9864                 if ( !hasFocus.length ) {
9865                         hasFocus = this.uiDialogButtonPane.find(":tabbable");
9866                 }
9867                 if ( !hasFocus.length ) {
9868                         hasFocus = this.uiDialogTitlebarClose.filter(":tabbable");
9869                 }
9870                 if ( !hasFocus.length ) {
9871                         hasFocus = this.uiDialog;
9872                 }
9873                 hasFocus.eq( 0 ).focus();
9874         },
9876         _keepFocus: function( event ) {
9877                 function checkFocus() {
9878                         var activeElement = this.document[0].activeElement,
9879                                 isActive = this.uiDialog[0] === activeElement ||
9880                                         $.contains( this.uiDialog[0], activeElement );
9881                         if ( !isActive ) {
9882                                 this._focusTabbable();
9883                         }
9884                 }
9885                 event.preventDefault();
9886                 checkFocus.call( this );
9887                 // support: IE
9888                 // IE <= 8 doesn't prevent moving focus even with event.preventDefault()
9889                 // so we check again later
9890                 this._delay( checkFocus );
9891         },
9893         _createWrapper: function() {
9894                 this.uiDialog = $("<div>")
9895                         .addClass( "ui-dialog ui-widget ui-widget-content ui-corner-all ui-front " +
9896                                 this.options.dialogClass )
9897                         .hide()
9898                         .attr({
9899                                 // Setting tabIndex makes the div focusable
9900                                 tabIndex: -1,
9901                                 role: "dialog"
9902                         })
9903                         .appendTo( this._appendTo() );
9905                 this._on( this.uiDialog, {
9906                         keydown: function( event ) {
9907                                 if ( this.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode &&
9908                                                 event.keyCode === $.ui.keyCode.ESCAPE ) {
9909                                         event.preventDefault();
9910                                         this.close( event );
9911                                         return;
9912                                 }
9914                                 // prevent tabbing out of dialogs
9915                                 if ( event.keyCode !== $.ui.keyCode.TAB ) {
9916                                         return;
9917                                 }
9918                                 var tabbables = this.uiDialog.find(":tabbable"),
9919                                         first = tabbables.filter(":first"),
9920                                         last  = tabbables.filter(":last");
9922                                 if ( ( event.target === last[0] || event.target === this.uiDialog[0] ) && !event.shiftKey ) {
9923                                         first.focus( 1 );
9924                                         event.preventDefault();
9925                                 } else if ( ( event.target === first[0] || event.target === this.uiDialog[0] ) && event.shiftKey ) {
9926                                         last.focus( 1 );
9927                                         event.preventDefault();
9928                                 }
9929                         },
9930                         mousedown: function( event ) {
9931                                 if ( this._moveToTop( event ) ) {
9932                                         this._focusTabbable();
9933                                 }
9934                         }
9935                 });
9937                 // We assume that any existing aria-describedby attribute means
9938                 // that the dialog content is marked up properly
9939                 // otherwise we brute force the content as the description
9940                 if ( !this.element.find("[aria-describedby]").length ) {
9941                         this.uiDialog.attr({
9942                                 "aria-describedby": this.element.uniqueId().attr("id")
9943                         });
9944                 }
9945         },
9947         _createTitlebar: function() {
9948                 var uiDialogTitle;
9950                 this.uiDialogTitlebar = $("<div>")
9951                         .addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix")
9952                         .prependTo( this.uiDialog );
9953                 this._on( this.uiDialogTitlebar, {
9954                         mousedown: function( event ) {
9955                                 // Don't prevent click on close button (#8838)
9956                                 // Focusing a dialog that is partially scrolled out of view
9957                                 // causes the browser to scroll it into view, preventing the click event
9958                                 if ( !$( event.target ).closest(".ui-dialog-titlebar-close") ) {
9959                                         // Dialog isn't getting focus when dragging (#8063)
9960                                         this.uiDialog.focus();
9961                                 }
9962                         }
9963                 });
9965                 this.uiDialogTitlebarClose = $("<button></button>")
9966                         .button({
9967                                 label: this.options.closeText,
9968                                 icons: {
9969                                         primary: "ui-icon-closethick"
9970                                 },
9971                                 text: false
9972                         })
9973                         .addClass("ui-dialog-titlebar-close")
9974                         .appendTo( this.uiDialogTitlebar );
9975                 this._on( this.uiDialogTitlebarClose, {
9976                         click: function( event ) {
9977                                 event.preventDefault();
9978                                 this.close( event );
9979                         }
9980                 });
9982                 uiDialogTitle = $("<span>")
9983                         .uniqueId()
9984                         .addClass("ui-dialog-title")
9985                         .prependTo( this.uiDialogTitlebar );
9986                 this._title( uiDialogTitle );
9988                 this.uiDialog.attr({
9989                         "aria-labelledby": uiDialogTitle.attr("id")
9990                 });
9991         },
9993         _title: function( title ) {
9994                 if ( !this.options.title ) {
9995                         title.html("&#160;");
9996                 }
9997                 title.text( this.options.title );
9998         },
10000         _createButtonPane: function() {
10001                 this.uiDialogButtonPane = $("<div>")
10002                         .addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix");
10004                 this.uiButtonSet = $("<div>")
10005                         .addClass("ui-dialog-buttonset")
10006                         .appendTo( this.uiDialogButtonPane );
10008                 this._createButtons();
10009         },
10011         _createButtons: function() {
10012                 var that = this,
10013                         buttons = this.options.buttons;
10015                 // if we already have a button pane, remove it
10016                 this.uiDialogButtonPane.remove();
10017                 this.uiButtonSet.empty();
10019                 if ( $.isEmptyObject( buttons ) || ($.isArray( buttons ) && !buttons.length) ) {
10020                         this.uiDialog.removeClass("ui-dialog-buttons");
10021                         return;
10022                 }
10024                 $.each( buttons, function( name, props ) {
10025                         var click, buttonOptions;
10026                         props = $.isFunction( props ) ?
10027                                 { click: props, text: name } :
10028                                 props;
10029                         // Default to a non-submitting button
10030                         props = $.extend( { type: "button" }, props );
10031                         // Change the context for the click callback to be the main element
10032                         click = props.click;
10033                         props.click = function() {
10034                                 click.apply( that.element[0], arguments );
10035                         };
10036                         buttonOptions = {
10037                                 icons: props.icons,
10038                                 text: props.showText
10039                         };
10040                         delete props.icons;
10041                         delete props.showText;
10042                         $( "<button></button>", props )
10043                                 .button( buttonOptions )
10044                                 .appendTo( that.uiButtonSet );
10045                 });
10046                 this.uiDialog.addClass("ui-dialog-buttons");
10047                 this.uiDialogButtonPane.appendTo( this.uiDialog );
10048         },
10050         _makeDraggable: function() {
10051                 var that = this,
10052                         options = this.options;
10054                 function filteredUi( ui ) {
10055                         return {
10056                                 position: ui.position,
10057                                 offset: ui.offset
10058                         };
10059                 }
10061                 this.uiDialog.draggable({
10062                         cancel: ".ui-dialog-content, .ui-dialog-titlebar-close",
10063                         handle: ".ui-dialog-titlebar",
10064                         containment: "document",
10065                         start: function( event, ui ) {
10066                                 $( this ).addClass("ui-dialog-dragging");
10067                                 that._blockFrames();
10068                                 that._trigger( "dragStart", event, filteredUi( ui ) );
10069                         },
10070                         drag: function( event, ui ) {
10071                                 that._trigger( "drag", event, filteredUi( ui ) );
10072                         },
10073                         stop: function( event, ui ) {
10074                                 options.position = [
10075                                         ui.position.left - that.document.scrollLeft(),
10076                                         ui.position.top - that.document.scrollTop()
10077                                 ];
10078                                 $( this ).removeClass("ui-dialog-dragging");
10079                                 that._unblockFrames();
10080                                 that._trigger( "dragStop", event, filteredUi( ui ) );
10081                         }
10082                 });
10083         },
10085         _makeResizable: function() {
10086                 var that = this,
10087                         options = this.options,
10088                         handles = options.resizable,
10089                         // .ui-resizable has position: relative defined in the stylesheet
10090                         // but dialogs have to use absolute or fixed positioning
10091                         position = this.uiDialog.css("position"),
10092                         resizeHandles = typeof handles === "string" ?
10093                                 handles :
10094                                 "n,e,s,w,se,sw,ne,nw";
10096                 function filteredUi( ui ) {
10097                         return {
10098                                 originalPosition: ui.originalPosition,
10099                                 originalSize: ui.originalSize,
10100                                 position: ui.position,
10101                                 size: ui.size
10102                         };
10103                 }
10105                 this.uiDialog.resizable({
10106                         cancel: ".ui-dialog-content",
10107                         containment: "document",
10108                         alsoResize: this.element,
10109                         maxWidth: options.maxWidth,
10110                         maxHeight: options.maxHeight,
10111                         minWidth: options.minWidth,
10112                         minHeight: this._minHeight(),
10113                         handles: resizeHandles,
10114                         start: function( event, ui ) {
10115                                 $( this ).addClass("ui-dialog-resizing");
10116                                 that._blockFrames();
10117                                 that._trigger( "resizeStart", event, filteredUi( ui ) );
10118                         },
10119                         resize: function( event, ui ) {
10120                                 that._trigger( "resize", event, filteredUi( ui ) );
10121                         },
10122                         stop: function( event, ui ) {
10123                                 options.height = $( this ).height();
10124                                 options.width = $( this ).width();
10125                                 $( this ).removeClass("ui-dialog-resizing");
10126                                 that._unblockFrames();
10127                                 that._trigger( "resizeStop", event, filteredUi( ui ) );
10128                         }
10129                 })
10130                 .css( "position", position );
10131         },
10133         _minHeight: function() {
10134                 var options = this.options;
10136                 return options.height === "auto" ?
10137                         options.minHeight :
10138                         Math.min( options.minHeight, options.height );
10139         },
10141         _position: function() {
10142                 // Need to show the dialog to get the actual offset in the position plugin
10143                 var isVisible = this.uiDialog.is(":visible");
10144                 if ( !isVisible ) {
10145                         this.uiDialog.show();
10146                 }
10147                 this.uiDialog.position( this.options.position );
10148                 if ( !isVisible ) {
10149                         this.uiDialog.hide();
10150                 }
10151         },
10153         _setOptions: function( options ) {
10154                 var that = this,
10155                         resize = false,
10156                         resizableOptions = {};
10158                 $.each( options, function( key, value ) {
10159                         that._setOption( key, value );
10161                         if ( key in sizeRelatedOptions ) {
10162                                 resize = true;
10163                         }
10164                         if ( key in resizableRelatedOptions ) {
10165                                 resizableOptions[ key ] = value;
10166                         }
10167                 });
10169                 if ( resize ) {
10170                         this._size();
10171                         this._position();
10172                 }
10173                 if ( this.uiDialog.is(":data(ui-resizable)") ) {
10174                         this.uiDialog.resizable( "option", resizableOptions );
10175                 }
10176         },
10178         _setOption: function( key, value ) {
10179                 /*jshint maxcomplexity:15*/
10180                 var isDraggable, isResizable,
10181                         uiDialog = this.uiDialog;
10183                 if ( key === "dialogClass" ) {
10184                         uiDialog
10185                                 .removeClass( this.options.dialogClass )
10186                                 .addClass( value );
10187                 }
10189                 if ( key === "disabled" ) {
10190                         return;
10191                 }
10193                 this._super( key, value );
10195                 if ( key === "appendTo" ) {
10196                         this.uiDialog.appendTo( this._appendTo() );
10197                 }
10199                 if ( key === "buttons" ) {
10200                         this._createButtons();
10201                 }
10203                 if ( key === "closeText" ) {
10204                         this.uiDialogTitlebarClose.button({
10205                                 // Ensure that we always pass a string
10206                                 label: "" + value
10207                         });
10208                 }
10210                 if ( key === "draggable" ) {
10211                         isDraggable = uiDialog.is(":data(ui-draggable)");
10212                         if ( isDraggable && !value ) {
10213                                 uiDialog.draggable("destroy");
10214                         }
10216                         if ( !isDraggable && value ) {
10217                                 this._makeDraggable();
10218                         }
10219                 }
10221                 if ( key === "position" ) {
10222                         this._position();
10223                 }
10225                 if ( key === "resizable" ) {
10226                         // currently resizable, becoming non-resizable
10227                         isResizable = uiDialog.is(":data(ui-resizable)");
10228                         if ( isResizable && !value ) {
10229                                 uiDialog.resizable("destroy");
10230                         }
10232                         // currently resizable, changing handles
10233                         if ( isResizable && typeof value === "string" ) {
10234                                 uiDialog.resizable( "option", "handles", value );
10235                         }
10237                         // currently non-resizable, becoming resizable
10238                         if ( !isResizable && value !== false ) {
10239                                 this._makeResizable();
10240                         }
10241                 }
10243                 if ( key === "title" ) {
10244                         this._title( this.uiDialogTitlebar.find(".ui-dialog-title") );
10245                 }
10246         },
10248         _size: function() {
10249                 // If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
10250                 // divs will both have width and height set, so we need to reset them
10251                 var nonContentHeight, minContentHeight, maxContentHeight,
10252                         options = this.options;
10254                 // Reset content sizing
10255                 this.element.show().css({
10256                         width: "auto",
10257                         minHeight: 0,
10258                         maxHeight: "none",
10259                         height: 0
10260                 });
10262                 if ( options.minWidth > options.width ) {
10263                         options.width = options.minWidth;
10264                 }
10266                 // reset wrapper sizing
10267                 // determine the height of all the non-content elements
10268                 nonContentHeight = this.uiDialog.css({
10269                                 height: "auto",
10270                                 width: options.width
10271                         })
10272                         .outerHeight();
10273                 minContentHeight = Math.max( 0, options.minHeight - nonContentHeight );
10274                 maxContentHeight = typeof options.maxHeight === "number" ?
10275                         Math.max( 0, options.maxHeight - nonContentHeight ) :
10276                         "none";
10278                 if ( options.height === "auto" ) {
10279                         this.element.css({
10280                                 minHeight: minContentHeight,
10281                                 maxHeight: maxContentHeight,
10282                                 height: "auto"
10283                         });
10284                 } else {
10285                         this.element.height( Math.max( 0, options.height - nonContentHeight ) );
10286                 }
10288                 if (this.uiDialog.is(":data(ui-resizable)") ) {
10289                         this.uiDialog.resizable( "option", "minHeight", this._minHeight() );
10290                 }
10291         },
10293         _blockFrames: function() {
10294                 this.iframeBlocks = this.document.find( "iframe" ).map(function() {
10295                         var iframe = $( this );
10297                         return $( "<div>" )
10298                                 .css({
10299                                         position: "absolute",
10300                                         width: iframe.outerWidth(),
10301                                         height: iframe.outerHeight()
10302                                 })
10303                                 .appendTo( iframe.parent() )
10304                                 .offset( iframe.offset() )[0];
10305                 });
10306         },
10308         _unblockFrames: function() {
10309                 if ( this.iframeBlocks ) {
10310                         this.iframeBlocks.remove();
10311                         delete this.iframeBlocks;
10312                 }
10313         },
10315         _allowInteraction: function( event ) {
10316                 if ( $( event.target ).closest(".ui-dialog").length ) {
10317                         return true;
10318                 }
10320                 // TODO: Remove hack when datepicker implements
10321                 // the .ui-front logic (#8989)
10322                 return !!$( event.target ).closest(".ui-datepicker").length;
10323         },
10325         _createOverlay: function() {
10326                 if ( !this.options.modal ) {
10327                         return;
10328                 }
10330                 var that = this,
10331                         widgetFullName = this.widgetFullName;
10332                 if ( !$.ui.dialog.overlayInstances ) {
10333                         // Prevent use of anchors and inputs.
10334                         // We use a delay in case the overlay is created from an
10335                         // event that we're going to be cancelling. (#2804)
10336                         this._delay(function() {
10337                                 // Handle .dialog().dialog("close") (#4065)
10338                                 if ( $.ui.dialog.overlayInstances ) {
10339                                         this.document.bind( "focusin.dialog", function( event ) {
10340                                                 if ( !that._allowInteraction( event ) ) {
10341                                                         event.preventDefault();
10342                                                         $(".ui-dialog:visible:last .ui-dialog-content")
10343                                                                 .data( widgetFullName )._focusTabbable();
10344                                                 }
10345                                         });
10346                                 }
10347                         });
10348                 }
10350                 this.overlay = $("<div>")
10351                         .addClass("ui-widget-overlay ui-front")
10352                         .appendTo( this._appendTo() );
10353                 this._on( this.overlay, {
10354                         mousedown: "_keepFocus"
10355                 });
10356                 $.ui.dialog.overlayInstances++;
10357         },
10359         _destroyOverlay: function() {
10360                 if ( !this.options.modal ) {
10361                         return;
10362                 }
10364                 if ( this.overlay ) {
10365                         $.ui.dialog.overlayInstances--;
10367                         if ( !$.ui.dialog.overlayInstances ) {
10368                                 this.document.unbind( "focusin.dialog" );
10369                         }
10370                         this.overlay.remove();
10371                         this.overlay = null;
10372                 }
10373         }
10376 $.ui.dialog.overlayInstances = 0;
10378 // DEPRECATED
10379 if ( $.uiBackCompat !== false ) {
10380         // position option with array notation
10381         // just override with old implementation
10382         $.widget( "ui.dialog", $.ui.dialog, {
10383                 _position: function() {
10384                         var position = this.options.position,
10385                                 myAt = [],
10386                                 offset = [ 0, 0 ],
10387                                 isVisible;
10389                         if ( position ) {
10390                                 if ( typeof position === "string" || (typeof position === "object" && "0" in position ) ) {
10391                                         myAt = position.split ? position.split(" ") : [ position[0], position[1] ];
10392                                         if ( myAt.length === 1 ) {
10393                                                 myAt[1] = myAt[0];
10394                                         }
10396                                         $.each( [ "left", "top" ], function( i, offsetPosition ) {
10397                                                 if ( +myAt[ i ] === myAt[ i ] ) {
10398                                                         offset[ i ] = myAt[ i ];
10399                                                         myAt[ i ] = offsetPosition;
10400                                                 }
10401                                         });
10403                                         position = {
10404                                                 my: myAt[0] + (offset[0] < 0 ? offset[0] : "+" + offset[0]) + " " +
10405                                                         myAt[1] + (offset[1] < 0 ? offset[1] : "+" + offset[1]),
10406                                                 at: myAt.join(" ")
10407                                         };
10408                                 }
10410                                 position = $.extend( {}, $.ui.dialog.prototype.options.position, position );
10411                         } else {
10412                                 position = $.ui.dialog.prototype.options.position;
10413                         }
10415                         // need to show the dialog to get the actual offset in the position plugin
10416                         isVisible = this.uiDialog.is(":visible");
10417                         if ( !isVisible ) {
10418                                 this.uiDialog.show();
10419                         }
10420                         this.uiDialog.position( position );
10421                         if ( !isVisible ) {
10422                                 this.uiDialog.hide();
10423                         }
10424                 }
10425         });
10428 }( jQuery ) );
10430 (function( $, undefined ) {
10432 var rvertical = /up|down|vertical/,
10433         rpositivemotion = /up|left|vertical|horizontal/;
10435 $.effects.effect.blind = function( o, done ) {
10436         // Create element
10437         var el = $( this ),
10438                 props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
10439                 mode = $.effects.setMode( el, o.mode || "hide" ),
10440                 direction = o.direction || "up",
10441                 vertical = rvertical.test( direction ),
10442                 ref = vertical ? "height" : "width",
10443                 ref2 = vertical ? "top" : "left",
10444                 motion = rpositivemotion.test( direction ),
10445                 animation = {},
10446                 show = mode === "show",
10447                 wrapper, distance, margin;
10449         // if already wrapped, the wrapper's properties are my property. #6245
10450         if ( el.parent().is( ".ui-effects-wrapper" ) ) {
10451                 $.effects.save( el.parent(), props );
10452         } else {
10453                 $.effects.save( el, props );
10454         }
10455         el.show();
10456         wrapper = $.effects.createWrapper( el ).css({
10457                 overflow: "hidden"
10458         });
10460         distance = wrapper[ ref ]();
10461         margin = parseFloat( wrapper.css( ref2 ) ) || 0;
10463         animation[ ref ] = show ? distance : 0;
10464         if ( !motion ) {
10465                 el
10466                         .css( vertical ? "bottom" : "right", 0 )
10467                         .css( vertical ? "top" : "left", "auto" )
10468                         .css({ position: "absolute" });
10470                 animation[ ref2 ] = show ? margin : distance + margin;
10471         }
10473         // start at 0 if we are showing
10474         if ( show ) {
10475                 wrapper.css( ref, 0 );
10476                 if ( ! motion ) {
10477                         wrapper.css( ref2, margin + distance );
10478                 }
10479         }
10481         // Animate
10482         wrapper.animate( animation, {
10483                 duration: o.duration,
10484                 easing: o.easing,
10485                 queue: false,
10486                 complete: function() {
10487                         if ( mode === "hide" ) {
10488                                 el.hide();
10489                         }
10490                         $.effects.restore( el, props );
10491                         $.effects.removeWrapper( el );
10492                         done();
10493                 }
10494         });
10498 })(jQuery);
10500 (function( $, undefined ) {
10502 $.effects.effect.bounce = function( o, done ) {
10503         var el = $( this ),
10504                 props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
10506                 // defaults:
10507                 mode = $.effects.setMode( el, o.mode || "effect" ),
10508                 hide = mode === "hide",
10509                 show = mode === "show",
10510                 direction = o.direction || "up",
10511                 distance = o.distance,
10512                 times = o.times || 5,
10514                 // number of internal animations
10515                 anims = times * 2 + ( show || hide ? 1 : 0 ),
10516                 speed = o.duration / anims,
10517                 easing = o.easing,
10519                 // utility:
10520                 ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
10521                 motion = ( direction === "up" || direction === "left" ),
10522                 i,
10523                 upAnim,
10524                 downAnim,
10526                 // we will need to re-assemble the queue to stack our animations in place
10527                 queue = el.queue(),
10528                 queuelen = queue.length;
10530         // Avoid touching opacity to prevent clearType and PNG issues in IE
10531         if ( show || hide ) {
10532                 props.push( "opacity" );
10533         }
10535         $.effects.save( el, props );
10536         el.show();
10537         $.effects.createWrapper( el ); // Create Wrapper
10539         // default distance for the BIGGEST bounce is the outer Distance / 3
10540         if ( !distance ) {
10541                 distance = el[ ref === "top" ? "outerHeight" : "outerWidth" ]() / 3;
10542         }
10544         if ( show ) {
10545                 downAnim = { opacity: 1 };
10546                 downAnim[ ref ] = 0;
10548                 // if we are showing, force opacity 0 and set the initial position
10549                 // then do the "first" animation
10550                 el.css( "opacity", 0 )
10551                         .css( ref, motion ? -distance * 2 : distance * 2 )
10552                         .animate( downAnim, speed, easing );
10553         }
10555         // start at the smallest distance if we are hiding
10556         if ( hide ) {
10557                 distance = distance / Math.pow( 2, times - 1 );
10558         }
10560         downAnim = {};
10561         downAnim[ ref ] = 0;
10562         // Bounces up/down/left/right then back to 0 -- times * 2 animations happen here
10563         for ( i = 0; i < times; i++ ) {
10564                 upAnim = {};
10565                 upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance;
10567                 el.animate( upAnim, speed, easing )
10568                         .animate( downAnim, speed, easing );
10570                 distance = hide ? distance * 2 : distance / 2;
10571         }
10573         // Last Bounce when Hiding
10574         if ( hide ) {
10575                 upAnim = { opacity: 0 };
10576                 upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance;
10578                 el.animate( upAnim, speed, easing );
10579         }
10581         el.queue(function() {
10582                 if ( hide ) {
10583                         el.hide();
10584                 }
10585                 $.effects.restore( el, props );
10586                 $.effects.removeWrapper( el );
10587                 done();
10588         });
10590         // inject all the animations we just queued to be first in line (after "inprogress")
10591         if ( queuelen > 1) {
10592                 queue.splice.apply( queue,
10593                         [ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) );
10594         }
10595         el.dequeue();
10599 })(jQuery);
10601 (function( $, undefined ) {
10603 $.effects.effect.clip = function( o, done ) {
10604         // Create element
10605         var el = $( this ),
10606                 props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
10607                 mode = $.effects.setMode( el, o.mode || "hide" ),
10608                 show = mode === "show",
10609                 direction = o.direction || "vertical",
10610                 vert = direction === "vertical",
10611                 size = vert ? "height" : "width",
10612                 position = vert ? "top" : "left",
10613                 animation = {},
10614                 wrapper, animate, distance;
10616         // Save & Show
10617         $.effects.save( el, props );
10618         el.show();
10620         // Create Wrapper
10621         wrapper = $.effects.createWrapper( el ).css({
10622                 overflow: "hidden"
10623         });
10624         animate = ( el[0].tagName === "IMG" ) ? wrapper : el;
10625         distance = animate[ size ]();
10627         // Shift
10628         if ( show ) {
10629                 animate.css( size, 0 );
10630                 animate.css( position, distance / 2 );
10631         }
10633         // Create Animation Object:
10634         animation[ size ] = show ? distance : 0;
10635         animation[ position ] = show ? 0 : distance / 2;
10637         // Animate
10638         animate.animate( animation, {
10639                 queue: false,
10640                 duration: o.duration,
10641                 easing: o.easing,
10642                 complete: function() {
10643                         if ( !show ) {
10644                                 el.hide();
10645                         }
10646                         $.effects.restore( el, props );
10647                         $.effects.removeWrapper( el );
10648                         done();
10649                 }
10650         });
10654 })(jQuery);
10656 (function( $, undefined ) {
10658 $.effects.effect.drop = function( o, done ) {
10660         var el = $( this ),
10661                 props = [ "position", "top", "bottom", "left", "right", "opacity", "height", "width" ],
10662                 mode = $.effects.setMode( el, o.mode || "hide" ),
10663                 show = mode === "show",
10664                 direction = o.direction || "left",
10665                 ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
10666                 motion = ( direction === "up" || direction === "left" ) ? "pos" : "neg",
10667                 animation = {
10668                         opacity: show ? 1 : 0
10669                 },
10670                 distance;
10672         // Adjust
10673         $.effects.save( el, props );
10674         el.show();
10675         $.effects.createWrapper( el );
10677         distance = o.distance || el[ ref === "top" ? "outerHeight": "outerWidth" ]( true ) / 2;
10679         if ( show ) {
10680                 el
10681                         .css( "opacity", 0 )
10682                         .css( ref, motion === "pos" ? -distance : distance );
10683         }
10685         // Animation
10686         animation[ ref ] = ( show ?
10687                 ( motion === "pos" ? "+=" : "-=" ) :
10688                 ( motion === "pos" ? "-=" : "+=" ) ) +
10689                 distance;
10691         // Animate
10692         el.animate( animation, {
10693                 queue: false,
10694                 duration: o.duration,
10695                 easing: o.easing,
10696                 complete: function() {
10697                         if ( mode === "hide" ) {
10698                                 el.hide();
10699                         }
10700                         $.effects.restore( el, props );
10701                         $.effects.removeWrapper( el );
10702                         done();
10703                 }
10704         });
10707 })(jQuery);
10709 (function( $, undefined ) {
10711 $.effects.effect.explode = function( o, done ) {
10713         var rows = o.pieces ? Math.round( Math.sqrt( o.pieces ) ) : 3,
10714                 cells = rows,
10715                 el = $( this ),
10716                 mode = $.effects.setMode( el, o.mode || "hide" ),
10717                 show = mode === "show",
10719                 // show and then visibility:hidden the element before calculating offset
10720                 offset = el.show().css( "visibility", "hidden" ).offset(),
10722                 // width and height of a piece
10723                 width = Math.ceil( el.outerWidth() / cells ),
10724                 height = Math.ceil( el.outerHeight() / rows ),
10725                 pieces = [],
10727                 // loop
10728                 i, j, left, top, mx, my;
10730         // children animate complete:
10731         function childComplete() {
10732                 pieces.push( this );
10733                 if ( pieces.length === rows * cells ) {
10734                         animComplete();
10735                 }
10736         }
10738         // clone the element for each row and cell.
10739         for( i = 0; i < rows ; i++ ) { // ===>
10740                 top = offset.top + i * height;
10741                 my = i - ( rows - 1 ) / 2 ;
10743                 for( j = 0; j < cells ; j++ ) { // |||
10744                         left = offset.left + j * width;
10745                         mx = j - ( cells - 1 ) / 2 ;
10747                         // Create a clone of the now hidden main element that will be absolute positioned
10748                         // within a wrapper div off the -left and -top equal to size of our pieces
10749                         el
10750                                 .clone()
10751                                 .appendTo( "body" )
10752                                 .wrap( "<div></div>" )
10753                                 .css({
10754                                         position: "absolute",
10755                                         visibility: "visible",
10756                                         left: -j * width,
10757                                         top: -i * height
10758                                 })
10760                         // select the wrapper - make it overflow: hidden and absolute positioned based on
10761                         // where the original was located +left and +top equal to the size of pieces
10762                                 .parent()
10763                                 .addClass( "ui-effects-explode" )
10764                                 .css({
10765                                         position: "absolute",
10766                                         overflow: "hidden",
10767                                         width: width,
10768                                         height: height,
10769                                         left: left + ( show ? mx * width : 0 ),
10770                                         top: top + ( show ? my * height : 0 ),
10771                                         opacity: show ? 0 : 1
10772                                 }).animate({
10773                                         left: left + ( show ? 0 : mx * width ),
10774                                         top: top + ( show ? 0 : my * height ),
10775                                         opacity: show ? 1 : 0
10776                                 }, o.duration || 500, o.easing, childComplete );
10777                 }
10778         }
10780         function animComplete() {
10781                 el.css({
10782                         visibility: "visible"
10783                 });
10784                 $( pieces ).remove();
10785                 if ( !show ) {
10786                         el.hide();
10787                 }
10788                 done();
10789         }
10792 })(jQuery);
10794 (function( $, undefined ) {
10796 $.effects.effect.fade = function( o, done ) {
10797         var el = $( this ),
10798                 mode = $.effects.setMode( el, o.mode || "toggle" );
10800         el.animate({
10801                 opacity: mode
10802         }, {
10803                 queue: false,
10804                 duration: o.duration,
10805                 easing: o.easing,
10806                 complete: done
10807         });
10810 })( jQuery );
10812 (function( $, undefined ) {
10814 $.effects.effect.fold = function( o, done ) {
10816         // Create element
10817         var el = $( this ),
10818                 props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
10819                 mode = $.effects.setMode( el, o.mode || "hide" ),
10820                 show = mode === "show",
10821                 hide = mode === "hide",
10822                 size = o.size || 15,
10823                 percent = /([0-9]+)%/.exec( size ),
10824                 horizFirst = !!o.horizFirst,
10825                 widthFirst = show !== horizFirst,
10826                 ref = widthFirst ? [ "width", "height" ] : [ "height", "width" ],
10827                 duration = o.duration / 2,
10828                 wrapper, distance,
10829                 animation1 = {},
10830                 animation2 = {};
10832         $.effects.save( el, props );
10833         el.show();
10835         // Create Wrapper
10836         wrapper = $.effects.createWrapper( el ).css({
10837                 overflow: "hidden"
10838         });
10839         distance = widthFirst ?
10840                 [ wrapper.width(), wrapper.height() ] :
10841                 [ wrapper.height(), wrapper.width() ];
10843         if ( percent ) {
10844                 size = parseInt( percent[ 1 ], 10 ) / 100 * distance[ hide ? 0 : 1 ];
10845         }
10846         if ( show ) {
10847                 wrapper.css( horizFirst ? {
10848                         height: 0,
10849                         width: size
10850                 } : {
10851                         height: size,
10852                         width: 0
10853                 });
10854         }
10856         // Animation
10857         animation1[ ref[ 0 ] ] = show ? distance[ 0 ] : size;
10858         animation2[ ref[ 1 ] ] = show ? distance[ 1 ] : 0;
10860         // Animate
10861         wrapper
10862                 .animate( animation1, duration, o.easing )
10863                 .animate( animation2, duration, o.easing, function() {
10864                         if ( hide ) {
10865                                 el.hide();
10866                         }
10867                         $.effects.restore( el, props );
10868                         $.effects.removeWrapper( el );
10869                         done();
10870                 });
10874 })(jQuery);
10876 (function( $, undefined ) {
10878 $.effects.effect.highlight = function( o, done ) {
10879         var elem = $( this ),
10880                 props = [ "backgroundImage", "backgroundColor", "opacity" ],
10881                 mode = $.effects.setMode( elem, o.mode || "show" ),
10882                 animation = {
10883                         backgroundColor: elem.css( "backgroundColor" )
10884                 };
10886         if (mode === "hide") {
10887                 animation.opacity = 0;
10888         }
10890         $.effects.save( elem, props );
10892         elem
10893                 .show()
10894                 .css({
10895                         backgroundImage: "none",
10896                         backgroundColor: o.color || "#ffff99"
10897                 })
10898                 .animate( animation, {
10899                         queue: false,
10900                         duration: o.duration,
10901                         easing: o.easing,
10902                         complete: function() {
10903                                 if ( mode === "hide" ) {
10904                                         elem.hide();
10905                                 }
10906                                 $.effects.restore( elem, props );
10907                                 done();
10908                         }
10909                 });
10912 })(jQuery);
10914 (function( $, undefined ) {
10916 $.effects.effect.pulsate = function( o, done ) {
10917         var elem = $( this ),
10918                 mode = $.effects.setMode( elem, o.mode || "show" ),
10919                 show = mode === "show",
10920                 hide = mode === "hide",
10921                 showhide = ( show || mode === "hide" ),
10923                 // showing or hiding leaves of the "last" animation
10924                 anims = ( ( o.times || 5 ) * 2 ) + ( showhide ? 1 : 0 ),
10925                 duration = o.duration / anims,
10926                 animateTo = 0,
10927                 queue = elem.queue(),
10928                 queuelen = queue.length,
10929                 i;
10931         if ( show || !elem.is(":visible")) {
10932                 elem.css( "opacity", 0 ).show();
10933                 animateTo = 1;
10934         }
10936         // anims - 1 opacity "toggles"
10937         for ( i = 1; i < anims; i++ ) {
10938                 elem.animate({
10939                         opacity: animateTo
10940                 }, duration, o.easing );
10941                 animateTo = 1 - animateTo;
10942         }
10944         elem.animate({
10945                 opacity: animateTo
10946         }, duration, o.easing);
10948         elem.queue(function() {
10949                 if ( hide ) {
10950                         elem.hide();
10951                 }
10952                 done();
10953         });
10955         // We just queued up "anims" animations, we need to put them next in the queue
10956         if ( queuelen > 1 ) {
10957                 queue.splice.apply( queue,
10958                         [ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) );
10959         }
10960         elem.dequeue();
10963 })(jQuery);
10965 (function( $, undefined ) {
10967 $.effects.effect.puff = function( o, done ) {
10968         var elem = $( this ),
10969                 mode = $.effects.setMode( elem, o.mode || "hide" ),
10970                 hide = mode === "hide",
10971                 percent = parseInt( o.percent, 10 ) || 150,
10972                 factor = percent / 100,
10973                 original = {
10974                         height: elem.height(),
10975                         width: elem.width(),
10976                         outerHeight: elem.outerHeight(),
10977                         outerWidth: elem.outerWidth()
10978                 };
10980         $.extend( o, {
10981                 effect: "scale",
10982                 queue: false,
10983                 fade: true,
10984                 mode: mode,
10985                 complete: done,
10986                 percent: hide ? percent : 100,
10987                 from: hide ?
10988                         original :
10989                         {
10990                                 height: original.height * factor,
10991                                 width: original.width * factor,
10992                                 outerHeight: original.outerHeight * factor,
10993                                 outerWidth: original.outerWidth * factor
10994                         }
10995         });
10997         elem.effect( o );
11000 $.effects.effect.scale = function( o, done ) {
11002         // Create element
11003         var el = $( this ),
11004                 options = $.extend( true, {}, o ),
11005                 mode = $.effects.setMode( el, o.mode || "effect" ),
11006                 percent = parseInt( o.percent, 10 ) ||
11007                         ( parseInt( o.percent, 10 ) === 0 ? 0 : ( mode === "hide" ? 0 : 100 ) ),
11008                 direction = o.direction || "both",
11009                 origin = o.origin,
11010                 original = {
11011                         height: el.height(),
11012                         width: el.width(),
11013                         outerHeight: el.outerHeight(),
11014                         outerWidth: el.outerWidth()
11015                 },
11016                 factor = {
11017                         y: direction !== "horizontal" ? (percent / 100) : 1,
11018                         x: direction !== "vertical" ? (percent / 100) : 1
11019                 };
11021         // We are going to pass this effect to the size effect:
11022         options.effect = "size";
11023         options.queue = false;
11024         options.complete = done;
11026         // Set default origin and restore for show/hide
11027         if ( mode !== "effect" ) {
11028                 options.origin = origin || ["middle","center"];
11029                 options.restore = true;
11030         }
11032         options.from = o.from || ( mode === "show" ? {
11033                 height: 0,
11034                 width: 0,
11035                 outerHeight: 0,
11036                 outerWidth: 0
11037         } : original );
11038         options.to = {
11039                 height: original.height * factor.y,
11040                 width: original.width * factor.x,
11041                 outerHeight: original.outerHeight * factor.y,
11042                 outerWidth: original.outerWidth * factor.x
11043         };
11045         // Fade option to support puff
11046         if ( options.fade ) {
11047                 if ( mode === "show" ) {
11048                         options.from.opacity = 0;
11049                         options.to.opacity = 1;
11050                 }
11051                 if ( mode === "hide" ) {
11052                         options.from.opacity = 1;
11053                         options.to.opacity = 0;
11054                 }
11055         }
11057         // Animate
11058         el.effect( options );
11062 $.effects.effect.size = function( o, done ) {
11064         // Create element
11065         var original, baseline, factor,
11066                 el = $( this ),
11067                 props0 = [ "position", "top", "bottom", "left", "right", "width", "height", "overflow", "opacity" ],
11069                 // Always restore
11070                 props1 = [ "position", "top", "bottom", "left", "right", "overflow", "opacity" ],
11072                 // Copy for children
11073                 props2 = [ "width", "height", "overflow" ],
11074                 cProps = [ "fontSize" ],
11075                 vProps = [ "borderTopWidth", "borderBottomWidth", "paddingTop", "paddingBottom" ],
11076                 hProps = [ "borderLeftWidth", "borderRightWidth", "paddingLeft", "paddingRight" ],
11078                 // Set options
11079                 mode = $.effects.setMode( el, o.mode || "effect" ),
11080                 restore = o.restore || mode !== "effect",
11081                 scale = o.scale || "both",
11082                 origin = o.origin || [ "middle", "center" ],
11083                 position = el.css( "position" ),
11084                 props = restore ? props0 : props1,
11085                 zero = {
11086                         height: 0,
11087                         width: 0,
11088                         outerHeight: 0,
11089                         outerWidth: 0
11090                 };
11092         if ( mode === "show" ) {
11093                 el.show();
11094         }
11095         original = {
11096                 height: el.height(),
11097                 width: el.width(),
11098                 outerHeight: el.outerHeight(),
11099                 outerWidth: el.outerWidth()
11100         };
11102         if ( o.mode === "toggle" && mode === "show" ) {
11103                 el.from = o.to || zero;
11104                 el.to = o.from || original;
11105         } else {
11106                 el.from = o.from || ( mode === "show" ? zero : original );
11107                 el.to = o.to || ( mode === "hide" ? zero : original );
11108         }
11110         // Set scaling factor
11111         factor = {
11112                 from: {
11113                         y: el.from.height / original.height,
11114                         x: el.from.width / original.width
11115                 },
11116                 to: {
11117                         y: el.to.height / original.height,
11118                         x: el.to.width / original.width
11119                 }
11120         };
11122         // Scale the css box
11123         if ( scale === "box" || scale === "both" ) {
11125                 // Vertical props scaling
11126                 if ( factor.from.y !== factor.to.y ) {
11127                         props = props.concat( vProps );
11128                         el.from = $.effects.setTransition( el, vProps, factor.from.y, el.from );
11129                         el.to = $.effects.setTransition( el, vProps, factor.to.y, el.to );
11130                 }
11132                 // Horizontal props scaling
11133                 if ( factor.from.x !== factor.to.x ) {
11134                         props = props.concat( hProps );
11135                         el.from = $.effects.setTransition( el, hProps, factor.from.x, el.from );
11136                         el.to = $.effects.setTransition( el, hProps, factor.to.x, el.to );
11137                 }
11138         }
11140         // Scale the content
11141         if ( scale === "content" || scale === "both" ) {
11143                 // Vertical props scaling
11144                 if ( factor.from.y !== factor.to.y ) {
11145                         props = props.concat( cProps ).concat( props2 );
11146                         el.from = $.effects.setTransition( el, cProps, factor.from.y, el.from );
11147                         el.to = $.effects.setTransition( el, cProps, factor.to.y, el.to );
11148                 }
11149         }
11151         $.effects.save( el, props );
11152         el.show();
11153         $.effects.createWrapper( el );
11154         el.css( "overflow", "hidden" ).css( el.from );
11156         // Adjust
11157         if (origin) { // Calculate baseline shifts
11158                 baseline = $.effects.getBaseline( origin, original );
11159                 el.from.top = ( original.outerHeight - el.outerHeight() ) * baseline.y;
11160                 el.from.left = ( original.outerWidth - el.outerWidth() ) * baseline.x;
11161                 el.to.top = ( original.outerHeight - el.to.outerHeight ) * baseline.y;
11162                 el.to.left = ( original.outerWidth - el.to.outerWidth ) * baseline.x;
11163         }
11164         el.css( el.from ); // set top & left
11166         // Animate
11167         if ( scale === "content" || scale === "both" ) { // Scale the children
11169                 // Add margins/font-size
11170                 vProps = vProps.concat([ "marginTop", "marginBottom" ]).concat(cProps);
11171                 hProps = hProps.concat([ "marginLeft", "marginRight" ]);
11172                 props2 = props0.concat(vProps).concat(hProps);
11174                 el.find( "*[width]" ).each( function(){
11175                         var child = $( this ),
11176                                 c_original = {
11177                                         height: child.height(),
11178                                         width: child.width(),
11179                                         outerHeight: child.outerHeight(),
11180                                         outerWidth: child.outerWidth()
11181                                 };
11182                         if (restore) {
11183                                 $.effects.save(child, props2);
11184                         }
11186                         child.from = {
11187                                 height: c_original.height * factor.from.y,
11188                                 width: c_original.width * factor.from.x,
11189                                 outerHeight: c_original.outerHeight * factor.from.y,
11190                                 outerWidth: c_original.outerWidth * factor.from.x
11191                         };
11192                         child.to = {
11193                                 height: c_original.height * factor.to.y,
11194                                 width: c_original.width * factor.to.x,
11195                                 outerHeight: c_original.height * factor.to.y,
11196                                 outerWidth: c_original.width * factor.to.x
11197                         };
11199                         // Vertical props scaling
11200                         if ( factor.from.y !== factor.to.y ) {
11201                                 child.from = $.effects.setTransition( child, vProps, factor.from.y, child.from );
11202                                 child.to = $.effects.setTransition( child, vProps, factor.to.y, child.to );
11203                         }
11205                         // Horizontal props scaling
11206                         if ( factor.from.x !== factor.to.x ) {
11207                                 child.from = $.effects.setTransition( child, hProps, factor.from.x, child.from );
11208                                 child.to = $.effects.setTransition( child, hProps, factor.to.x, child.to );
11209                         }
11211                         // Animate children
11212                         child.css( child.from );
11213                         child.animate( child.to, o.duration, o.easing, function() {
11215                                 // Restore children
11216                                 if ( restore ) {
11217                                         $.effects.restore( child, props2 );
11218                                 }
11219                         });
11220                 });
11221         }
11223         // Animate
11224         el.animate( el.to, {
11225                 queue: false,
11226                 duration: o.duration,
11227                 easing: o.easing,
11228                 complete: function() {
11229                         if ( el.to.opacity === 0 ) {
11230                                 el.css( "opacity", el.from.opacity );
11231                         }
11232                         if( mode === "hide" ) {
11233                                 el.hide();
11234                         }
11235                         $.effects.restore( el, props );
11236                         if ( !restore ) {
11238                                 // we need to calculate our new positioning based on the scaling
11239                                 if ( position === "static" ) {
11240                                         el.css({
11241                                                 position: "relative",
11242                                                 top: el.to.top,
11243                                                 left: el.to.left
11244                                         });
11245                                 } else {
11246                                         $.each([ "top", "left" ], function( idx, pos ) {
11247                                                 el.css( pos, function( _, str ) {
11248                                                         var val = parseInt( str, 10 ),
11249                                                                 toRef = idx ? el.to.left : el.to.top;
11251                                                         // if original was "auto", recalculate the new value from wrapper
11252                                                         if ( str === "auto" ) {
11253                                                                 return toRef + "px";
11254                                                         }
11256                                                         return val + toRef + "px";
11257                                                 });
11258                                         });
11259                                 }
11260                         }
11262                         $.effects.removeWrapper( el );
11263                         done();
11264                 }
11265         });
11269 })(jQuery);
11271 (function( $, undefined ) {
11273 $.effects.effect.shake = function( o, done ) {
11275         var el = $( this ),
11276                 props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
11277                 mode = $.effects.setMode( el, o.mode || "effect" ),
11278                 direction = o.direction || "left",
11279                 distance = o.distance || 20,
11280                 times = o.times || 3,
11281                 anims = times * 2 + 1,
11282                 speed = Math.round(o.duration/anims),
11283                 ref = (direction === "up" || direction === "down") ? "top" : "left",
11284                 positiveMotion = (direction === "up" || direction === "left"),
11285                 animation = {},
11286                 animation1 = {},
11287                 animation2 = {},
11288                 i,
11290                 // we will need to re-assemble the queue to stack our animations in place
11291                 queue = el.queue(),
11292                 queuelen = queue.length;
11294         $.effects.save( el, props );
11295         el.show();
11296         $.effects.createWrapper( el );
11298         // Animation
11299         animation[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance;
11300         animation1[ ref ] = ( positiveMotion ? "+=" : "-=" ) + distance * 2;
11301         animation2[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance * 2;
11303         // Animate
11304         el.animate( animation, speed, o.easing );
11306         // Shakes
11307         for ( i = 1; i < times; i++ ) {
11308                 el.animate( animation1, speed, o.easing ).animate( animation2, speed, o.easing );
11309         }
11310         el
11311                 .animate( animation1, speed, o.easing )
11312                 .animate( animation, speed / 2, o.easing )
11313                 .queue(function() {
11314                         if ( mode === "hide" ) {
11315                                 el.hide();
11316                         }
11317                         $.effects.restore( el, props );
11318                         $.effects.removeWrapper( el );
11319                         done();
11320                 });
11322         // inject all the animations we just queued to be first in line (after "inprogress")
11323         if ( queuelen > 1) {
11324                 queue.splice.apply( queue,
11325                         [ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) );
11326         }
11327         el.dequeue();
11331 })(jQuery);
11333 (function( $, undefined ) {
11335 $.effects.effect.slide = function( o, done ) {
11337         // Create element
11338         var el = $( this ),
11339                 props = [ "position", "top", "bottom", "left", "right", "width", "height" ],
11340                 mode = $.effects.setMode( el, o.mode || "show" ),
11341                 show = mode === "show",
11342                 direction = o.direction || "left",
11343                 ref = (direction === "up" || direction === "down") ? "top" : "left",
11344                 positiveMotion = (direction === "up" || direction === "left"),
11345                 distance,
11346                 animation = {};
11348         // Adjust
11349         $.effects.save( el, props );
11350         el.show();
11351         distance = o.distance || el[ ref === "top" ? "outerHeight" : "outerWidth" ]( true );
11353         $.effects.createWrapper( el ).css({
11354                 overflow: "hidden"
11355         });
11357         if ( show ) {
11358                 el.css( ref, positiveMotion ? (isNaN(distance) ? "-" + distance : -distance) : distance );
11359         }
11361         // Animation
11362         animation[ ref ] = ( show ?
11363                 ( positiveMotion ? "+=" : "-=") :
11364                 ( positiveMotion ? "-=" : "+=")) +
11365                 distance;
11367         // Animate
11368         el.animate( animation, {
11369                 queue: false,
11370                 duration: o.duration,
11371                 easing: o.easing,
11372                 complete: function() {
11373                         if ( mode === "hide" ) {
11374                                 el.hide();
11375                         }
11376                         $.effects.restore( el, props );
11377                         $.effects.removeWrapper( el );
11378                         done();
11379                 }
11380         });
11383 })(jQuery);
11385 (function( $, undefined ) {
11387 $.effects.effect.transfer = function( o, done ) {
11388         var elem = $( this ),
11389                 target = $( o.to ),
11390                 targetFixed = target.css( "position" ) === "fixed",
11391                 body = $("body"),
11392                 fixTop = targetFixed ? body.scrollTop() : 0,
11393                 fixLeft = targetFixed ? body.scrollLeft() : 0,
11394                 endPosition = target.offset(),
11395                 animation = {
11396                         top: endPosition.top - fixTop ,
11397                         left: endPosition.left - fixLeft ,
11398                         height: target.innerHeight(),
11399                         width: target.innerWidth()
11400                 },
11401                 startPosition = elem.offset(),
11402                 transfer = $( "<div class='ui-effects-transfer'></div>" )
11403                         .appendTo( document.body )
11404                         .addClass( o.className )
11405                         .css({
11406                                 top: startPosition.top - fixTop ,
11407                                 left: startPosition.left - fixLeft ,
11408                                 height: elem.innerHeight(),
11409                                 width: elem.innerWidth(),
11410                                 position: targetFixed ? "fixed" : "absolute"
11411                         })
11412                         .animate( animation, o.duration, o.easing, function() {
11413                                 transfer.remove();
11414                                 done();
11415                         });
11418 })(jQuery);
11420 (function( $, undefined ) {
11422 $.widget( "ui.menu", {
11423         version: "1.10.3",
11424         defaultElement: "<ul>",
11425         delay: 300,
11426         options: {
11427                 icons: {
11428                         submenu: "ui-icon-carat-1-e"
11429                 },
11430                 menus: "ul",
11431                 position: {
11432                         my: "left top",
11433                         at: "right top"
11434                 },
11435                 role: "menu",
11437                 // callbacks
11438                 blur: null,
11439                 focus: null,
11440                 select: null
11441         },
11443         _create: function() {
11444                 this.activeMenu = this.element;
11445                 // flag used to prevent firing of the click handler
11446                 // as the event bubbles up through nested menus
11447                 this.mouseHandled = false;
11448                 this.element
11449                         .uniqueId()
11450                         .addClass( "ui-menu ui-widget ui-widget-content ui-corner-all" )
11451                         .toggleClass( "ui-menu-icons", !!this.element.find( ".ui-icon" ).length )
11452                         .attr({
11453                                 role: this.options.role,
11454                                 tabIndex: 0
11455                         })
11456                         // need to catch all clicks on disabled menu
11457                         // not possible through _on
11458                         .bind( "click" + this.eventNamespace, $.proxy(function( event ) {
11459                                 if ( this.options.disabled ) {
11460                                         event.preventDefault();
11461                                 }
11462                         }, this ));
11464                 if ( this.options.disabled ) {
11465                         this.element
11466                                 .addClass( "ui-state-disabled" )
11467                                 .attr( "aria-disabled", "true" );
11468                 }
11470                 this._on({
11471                         // Prevent focus from sticking to links inside menu after clicking
11472                         // them (focus should always stay on UL during navigation).
11473                         "mousedown .ui-menu-item > a": function( event ) {
11474                                 event.preventDefault();
11475                         },
11476                         "click .ui-state-disabled > a": function( event ) {
11477                                 event.preventDefault();
11478                         },
11479                         "click .ui-menu-item:has(a)": function( event ) {
11480                                 var target = $( event.target ).closest( ".ui-menu-item" );
11481                                 if ( !this.mouseHandled && target.not( ".ui-state-disabled" ).length ) {
11482                                         this.mouseHandled = true;
11484                                         this.select( event );
11485                                         // Open submenu on click
11486                                         if ( target.has( ".ui-menu" ).length ) {
11487                                                 this.expand( event );
11488                                         } else if ( !this.element.is( ":focus" ) ) {
11489                                                 // Redirect focus to the menu
11490                                                 this.element.trigger( "focus", [ true ] );
11492                                                 // If the active item is on the top level, let it stay active.
11493                                                 // Otherwise, blur the active item since it is no longer visible.
11494                                                 if ( this.active && this.active.parents( ".ui-menu" ).length === 1 ) {
11495                                                         clearTimeout( this.timer );
11496                                                 }
11497                                         }
11498                                 }
11499                         },
11500                         "mouseenter .ui-menu-item": function( event ) {
11501                                 var target = $( event.currentTarget );
11502                                 // Remove ui-state-active class from siblings of the newly focused menu item
11503                                 // to avoid a jump caused by adjacent elements both having a class with a border
11504                                 target.siblings().children( ".ui-state-active" ).removeClass( "ui-state-active" );
11505                                 this.focus( event, target );
11506                         },
11507                         mouseleave: "collapseAll",
11508                         "mouseleave .ui-menu": "collapseAll",
11509                         focus: function( event, keepActiveItem ) {
11510                                 // If there's already an active item, keep it active
11511                                 // If not, activate the first item
11512                                 var item = this.active || this.element.children( ".ui-menu-item" ).eq( 0 );
11514                                 if ( !keepActiveItem ) {
11515                                         this.focus( event, item );
11516                                 }
11517                         },
11518                         blur: function( event ) {
11519                                 this._delay(function() {
11520                                         if ( !$.contains( this.element[0], this.document[0].activeElement ) ) {
11521                                                 this.collapseAll( event );
11522                                         }
11523                                 });
11524                         },
11525                         keydown: "_keydown"
11526                 });
11528                 this.refresh();
11530                 // Clicks outside of a menu collapse any open menus
11531                 this._on( this.document, {
11532                         click: function( event ) {
11533                                 if ( !$( event.target ).closest( ".ui-menu" ).length ) {
11534                                         this.collapseAll( event );
11535                                 }
11537                                 // Reset the mouseHandled flag
11538                                 this.mouseHandled = false;
11539                         }
11540                 });
11541         },
11543         _destroy: function() {
11544                 // Destroy (sub)menus
11545                 this.element
11546                         .removeAttr( "aria-activedescendant" )
11547                         .find( ".ui-menu" ).addBack()
11548                                 .removeClass( "ui-menu ui-widget ui-widget-content ui-corner-all ui-menu-icons" )
11549                                 .removeAttr( "role" )
11550                                 .removeAttr( "tabIndex" )
11551                                 .removeAttr( "aria-labelledby" )
11552                                 .removeAttr( "aria-expanded" )
11553                                 .removeAttr( "aria-hidden" )
11554                                 .removeAttr( "aria-disabled" )
11555                                 .removeUniqueId()
11556                                 .show();
11558                 // Destroy menu items
11559                 this.element.find( ".ui-menu-item" )
11560                         .removeClass( "ui-menu-item" )
11561                         .removeAttr( "role" )
11562                         .removeAttr( "aria-disabled" )
11563                         .children( "a" )
11564                                 .removeUniqueId()
11565                                 .removeClass( "ui-corner-all ui-state-hover" )
11566                                 .removeAttr( "tabIndex" )
11567                                 .removeAttr( "role" )
11568                                 .removeAttr( "aria-haspopup" )
11569                                 .children().each( function() {
11570                                         var elem = $( this );
11571                                         if ( elem.data( "ui-menu-submenu-carat" ) ) {
11572                                                 elem.remove();
11573                                         }
11574                                 });
11576                 // Destroy menu dividers
11577                 this.element.find( ".ui-menu-divider" ).removeClass( "ui-menu-divider ui-widget-content" );
11578         },
11580         _keydown: function( event ) {
11581                 /*jshint maxcomplexity:20*/
11582                 var match, prev, character, skip, regex,
11583                         preventDefault = true;
11585                 function escape( value ) {
11586                         return value.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" );
11587                 }
11589                 switch ( event.keyCode ) {
11590                 case $.ui.keyCode.PAGE_UP:
11591                         this.previousPage( event );
11592                         break;
11593                 case $.ui.keyCode.PAGE_DOWN:
11594                         this.nextPage( event );
11595                         break;
11596                 case $.ui.keyCode.HOME:
11597                         this._move( "first", "first", event );
11598                         break;
11599                 case $.ui.keyCode.END:
11600                         this._move( "last", "last", event );
11601                         break;
11602                 case $.ui.keyCode.UP:
11603                         this.previous( event );
11604                         break;
11605                 case $.ui.keyCode.DOWN:
11606                         this.next( event );
11607                         break;
11608                 case $.ui.keyCode.LEFT:
11609                         this.collapse( event );
11610                         break;
11611                 case $.ui.keyCode.RIGHT:
11612                         if ( this.active && !this.active.is( ".ui-state-disabled" ) ) {
11613                                 this.expand( event );
11614                         }
11615                         break;
11616                 case $.ui.keyCode.ENTER:
11617                 case $.ui.keyCode.SPACE:
11618                         this._activate( event );
11619                         break;
11620                 case $.ui.keyCode.ESCAPE:
11621                         this.collapse( event );
11622                         break;
11623                 default:
11624                         preventDefault = false;
11625                         prev = this.previousFilter || "";
11626                         character = String.fromCharCode( event.keyCode );
11627                         skip = false;
11629                         clearTimeout( this.filterTimer );
11631                         if ( character === prev ) {
11632                                 skip = true;
11633                         } else {
11634                                 character = prev + character;
11635                         }
11637                         regex = new RegExp( "^" + escape( character ), "i" );
11638                         match = this.activeMenu.children( ".ui-menu-item" ).filter(function() {
11639                                 return regex.test( $( this ).children( "a" ).text() );
11640                         });
11641                         match = skip && match.index( this.active.next() ) !== -1 ?
11642                                 this.active.nextAll( ".ui-menu-item" ) :
11643                                 match;
11645                         // If no matches on the current filter, reset to the last character pressed
11646                         // to move down the menu to the first item that starts with that character
11647                         if ( !match.length ) {
11648                                 character = String.fromCharCode( event.keyCode );
11649                                 regex = new RegExp( "^" + escape( character ), "i" );
11650                                 match = this.activeMenu.children( ".ui-menu-item" ).filter(function() {
11651                                         return regex.test( $( this ).children( "a" ).text() );
11652                                 });
11653                         }
11655                         if ( match.length ) {
11656                                 this.focus( event, match );
11657                                 if ( match.length > 1 ) {
11658                                         this.previousFilter = character;
11659                                         this.filterTimer = this._delay(function() {
11660                                                 delete this.previousFilter;
11661                                         }, 1000 );
11662                                 } else {
11663                                         delete this.previousFilter;
11664                                 }
11665                         } else {
11666                                 delete this.previousFilter;
11667                         }
11668                 }
11670                 if ( preventDefault ) {
11671                         event.preventDefault();
11672                 }
11673         },
11675         _activate: function( event ) {
11676                 if ( !this.active.is( ".ui-state-disabled" ) ) {
11677                         if ( this.active.children( "a[aria-haspopup='true']" ).length ) {
11678                                 this.expand( event );
11679                         } else {
11680                                 this.select( event );
11681                         }
11682                 }
11683         },
11685         refresh: function() {
11686                 var menus,
11687                         icon = this.options.icons.submenu,
11688                         submenus = this.element.find( this.options.menus );
11690                 // Initialize nested menus
11691                 submenus.filter( ":not(.ui-menu)" )
11692                         .addClass( "ui-menu ui-widget ui-widget-content ui-corner-all" )
11693                         .hide()
11694                         .attr({
11695                                 role: this.options.role,
11696                                 "aria-hidden": "true",
11697                                 "aria-expanded": "false"
11698                         })
11699                         .each(function() {
11700                                 var menu = $( this ),
11701                                         item = menu.prev( "a" ),
11702                                         submenuCarat = $( "<span>" )
11703                                                 .addClass( "ui-menu-icon ui-icon " + icon )
11704                                                 .data( "ui-menu-submenu-carat", true );
11706                                 item
11707                                         .attr( "aria-haspopup", "true" )
11708                                         .prepend( submenuCarat );
11709                                 menu.attr( "aria-labelledby", item.attr( "id" ) );
11710                         });
11712                 menus = submenus.add( this.element );
11714                 // Don't refresh list items that are already adapted
11715                 menus.children( ":not(.ui-menu-item):has(a)" )
11716                         .addClass( "ui-menu-item" )
11717                         .attr( "role", "presentation" )
11718                         .children( "a" )
11719                                 .uniqueId()
11720                                 .addClass( "ui-corner-all" )
11721                                 .attr({
11722                                         tabIndex: -1,
11723                                         role: this._itemRole()
11724                                 });
11726                 // Initialize unlinked menu-items containing spaces and/or dashes only as dividers
11727                 menus.children( ":not(.ui-menu-item)" ).each(function() {
11728                         var item = $( this );
11729                         // hyphen, em dash, en dash
11730                         if ( !/[^\-\u2014\u2013\s]/.test( item.text() ) ) {
11731                                 item.addClass( "ui-widget-content ui-menu-divider" );
11732                         }
11733                 });
11735                 // Add aria-disabled attribute to any disabled menu item
11736                 menus.children( ".ui-state-disabled" ).attr( "aria-disabled", "true" );
11738                 // If the active item has been removed, blur the menu
11739                 if ( this.active && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
11740                         this.blur();
11741                 }
11742         },
11744         _itemRole: function() {
11745                 return {
11746                         menu: "menuitem",
11747                         listbox: "option"
11748                 }[ this.options.role ];
11749         },
11751         _setOption: function( key, value ) {
11752                 if ( key === "icons" ) {
11753                         this.element.find( ".ui-menu-icon" )
11754                                 .removeClass( this.options.icons.submenu )
11755                                 .addClass( value.submenu );
11756                 }
11757                 this._super( key, value );
11758         },
11760         focus: function( event, item ) {
11761                 var nested, focused;
11762                 this.blur( event, event && event.type === "focus" );
11764                 this._scrollIntoView( item );
11766                 this.active = item.first();
11767                 focused = this.active.children( "a" ).addClass( "ui-state-focus" );
11768                 // Only update aria-activedescendant if there's a role
11769                 // otherwise we assume focus is managed elsewhere
11770                 if ( this.options.role ) {
11771                         this.element.attr( "aria-activedescendant", focused.attr( "id" ) );
11772                 }
11774                 // Highlight active parent menu item, if any
11775                 this.active
11776                         .parent()
11777                         .closest( ".ui-menu-item" )
11778                         .children( "a:first" )
11779                         .addClass( "ui-state-active" );
11781                 if ( event && event.type === "keydown" ) {
11782                         this._close();
11783                 } else {
11784                         this.timer = this._delay(function() {
11785                                 this._close();
11786                         }, this.delay );
11787                 }
11789                 nested = item.children( ".ui-menu" );
11790                 if ( nested.length && ( /^mouse/.test( event.type ) ) ) {
11791                         this._startOpening(nested);
11792                 }
11793                 this.activeMenu = item.parent();
11795                 this._trigger( "focus", event, { item: item } );
11796         },
11798         _scrollIntoView: function( item ) {
11799                 var borderTop, paddingTop, offset, scroll, elementHeight, itemHeight;
11800                 if ( this._hasScroll() ) {
11801                         borderTop = parseFloat( $.css( this.activeMenu[0], "borderTopWidth" ) ) || 0;
11802                         paddingTop = parseFloat( $.css( this.activeMenu[0], "paddingTop" ) ) || 0;
11803                         offset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop;
11804                         scroll = this.activeMenu.scrollTop();
11805                         elementHeight = this.activeMenu.height();
11806                         itemHeight = item.height();
11808                         if ( offset < 0 ) {
11809                                 this.activeMenu.scrollTop( scroll + offset );
11810                         } else if ( offset + itemHeight > elementHeight ) {
11811                                 this.activeMenu.scrollTop( scroll + offset - elementHeight + itemHeight );
11812                         }
11813                 }
11814         },
11816         blur: function( event, fromFocus ) {
11817                 if ( !fromFocus ) {
11818                         clearTimeout( this.timer );
11819                 }
11821                 if ( !this.active ) {
11822                         return;
11823                 }
11825                 this.active.children( "a" ).removeClass( "ui-state-focus" );
11826                 this.active = null;
11828                 this._trigger( "blur", event, { item: this.active } );
11829         },
11831         _startOpening: function( submenu ) {
11832                 clearTimeout( this.timer );
11834                 // Don't open if already open fixes a Firefox bug that caused a .5 pixel
11835                 // shift in the submenu position when mousing over the carat icon
11836                 if ( submenu.attr( "aria-hidden" ) !== "true" ) {
11837                         return;
11838                 }
11840                 this.timer = this._delay(function() {
11841                         this._close();
11842                         this._open( submenu );
11843                 }, this.delay );
11844         },
11846         _open: function( submenu ) {
11847                 var position = $.extend({
11848                         of: this.active
11849                 }, this.options.position );
11851                 clearTimeout( this.timer );
11852                 this.element.find( ".ui-menu" ).not( submenu.parents( ".ui-menu" ) )
11853                         .hide()
11854                         .attr( "aria-hidden", "true" );
11856                 submenu
11857                         .show()
11858                         .removeAttr( "aria-hidden" )
11859                         .attr( "aria-expanded", "true" )
11860                         .position( position );
11861         },
11863         collapseAll: function( event, all ) {
11864                 clearTimeout( this.timer );
11865                 this.timer = this._delay(function() {
11866                         // If we were passed an event, look for the submenu that contains the event
11867                         var currentMenu = all ? this.element :
11868                                 $( event && event.target ).closest( this.element.find( ".ui-menu" ) );
11870                         // If we found no valid submenu ancestor, use the main menu to close all sub menus anyway
11871                         if ( !currentMenu.length ) {
11872                                 currentMenu = this.element;
11873                         }
11875                         this._close( currentMenu );
11877                         this.blur( event );
11878                         this.activeMenu = currentMenu;
11879                 }, this.delay );
11880         },
11882         // With no arguments, closes the currently active menu - if nothing is active
11883         // it closes all menus.  If passed an argument, it will search for menus BELOW
11884         _close: function( startMenu ) {
11885                 if ( !startMenu ) {
11886                         startMenu = this.active ? this.active.parent() : this.element;
11887                 }
11889                 startMenu
11890                         .find( ".ui-menu" )
11891                                 .hide()
11892                                 .attr( "aria-hidden", "true" )
11893                                 .attr( "aria-expanded", "false" )
11894                         .end()
11895                         .find( "a.ui-state-active" )
11896                                 .removeClass( "ui-state-active" );
11897         },
11899         collapse: function( event ) {
11900                 var newItem = this.active &&
11901                         this.active.parent().closest( ".ui-menu-item", this.element );
11902                 if ( newItem && newItem.length ) {
11903                         this._close();
11904                         this.focus( event, newItem );
11905                 }
11906         },
11908         expand: function( event ) {
11909                 var newItem = this.active &&
11910                         this.active
11911                                 .children( ".ui-menu " )
11912                                 .children( ".ui-menu-item" )
11913                                 .first();
11915                 if ( newItem && newItem.length ) {
11916                         this._open( newItem.parent() );
11918                         // Delay so Firefox will not hide activedescendant change in expanding submenu from AT
11919                         this._delay(function() {
11920                                 this.focus( event, newItem );
11921                         });
11922                 }
11923         },
11925         next: function( event ) {
11926                 this._move( "next", "first", event );
11927         },
11929         previous: function( event ) {
11930                 this._move( "prev", "last", event );
11931         },
11933         isFirstItem: function() {
11934                 return this.active && !this.active.prevAll( ".ui-menu-item" ).length;
11935         },
11937         isLastItem: function() {
11938                 return this.active && !this.active.nextAll( ".ui-menu-item" ).length;
11939         },
11941         _move: function( direction, filter, event ) {
11942                 var next;
11943                 if ( this.active ) {
11944                         if ( direction === "first" || direction === "last" ) {
11945                                 next = this.active
11946                                         [ direction === "first" ? "prevAll" : "nextAll" ]( ".ui-menu-item" )
11947                                         .eq( -1 );
11948                         } else {
11949                                 next = this.active
11950                                         [ direction + "All" ]( ".ui-menu-item" )
11951                                         .eq( 0 );
11952                         }
11953                 }
11954                 if ( !next || !next.length || !this.active ) {
11955                         next = this.activeMenu.children( ".ui-menu-item" )[ filter ]();
11956                 }
11958                 this.focus( event, next );
11959         },
11961         nextPage: function( event ) {
11962                 var item, base, height;
11964                 if ( !this.active ) {
11965                         this.next( event );
11966                         return;
11967                 }
11968                 if ( this.isLastItem() ) {
11969                         return;
11970                 }
11971                 if ( this._hasScroll() ) {
11972                         base = this.active.offset().top;
11973                         height = this.element.height();
11974                         this.active.nextAll( ".ui-menu-item" ).each(function() {
11975                                 item = $( this );
11976                                 return item.offset().top - base - height < 0;
11977                         });
11979                         this.focus( event, item );
11980                 } else {
11981                         this.focus( event, this.activeMenu.children( ".ui-menu-item" )
11982                                 [ !this.active ? "first" : "last" ]() );
11983                 }
11984         },
11986         previousPage: function( event ) {
11987                 var item, base, height;
11988                 if ( !this.active ) {
11989                         this.next( event );
11990                         return;
11991                 }
11992                 if ( this.isFirstItem() ) {
11993                         return;
11994                 }
11995                 if ( this._hasScroll() ) {
11996                         base = this.active.offset().top;
11997                         height = this.element.height();
11998                         this.active.prevAll( ".ui-menu-item" ).each(function() {
11999                                 item = $( this );
12000                                 return item.offset().top - base + height > 0;
12001                         });
12003                         this.focus( event, item );
12004                 } else {
12005                         this.focus( event, this.activeMenu.children( ".ui-menu-item" ).first() );
12006                 }
12007         },
12009         _hasScroll: function() {
12010                 return this.element.outerHeight() < this.element.prop( "scrollHeight" );
12011         },
12013         select: function( event ) {
12014                 // TODO: It should never be possible to not have an active item at this
12015                 // point, but the tests don't trigger mouseenter before click.
12016                 this.active = this.active || $( event.target ).closest( ".ui-menu-item" );
12017                 var ui = { item: this.active };
12018                 if ( !this.active.has( ".ui-menu" ).length ) {
12019                         this.collapseAll( event, true );
12020                 }
12021                 this._trigger( "select", event, ui );
12022         }
12025 }( jQuery ));
12027 (function( $, undefined ) {
12029 $.ui = $.ui || {};
12031 var cachedScrollbarWidth,
12032         max = Math.max,
12033         abs = Math.abs,
12034         round = Math.round,
12035         rhorizontal = /left|center|right/,
12036         rvertical = /top|center|bottom/,
12037         roffset = /[\+\-]\d+(\.[\d]+)?%?/,
12038         rposition = /^\w+/,
12039         rpercent = /%$/,
12040         _position = $.fn.position;
12042 function getOffsets( offsets, width, height ) {
12043         return [
12044                 parseFloat( offsets[ 0 ] ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ),
12045                 parseFloat( offsets[ 1 ] ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 )
12046         ];
12049 function parseCss( element, property ) {
12050         return parseInt( $.css( element, property ), 10 ) || 0;
12053 function getDimensions( elem ) {
12054         var raw = elem[0];
12055         if ( raw.nodeType === 9 ) {
12056                 return {
12057                         width: elem.width(),
12058                         height: elem.height(),
12059                         offset: { top: 0, left: 0 }
12060                 };
12061         }
12062         if ( $.isWindow( raw ) ) {
12063                 return {
12064                         width: elem.width(),
12065                         height: elem.height(),
12066                         offset: { top: elem.scrollTop(), left: elem.scrollLeft() }
12067                 };
12068         }
12069         if ( raw.preventDefault ) {
12070                 return {
12071                         width: 0,
12072                         height: 0,
12073                         offset: { top: raw.pageY, left: raw.pageX }
12074                 };
12075         }
12076         return {
12077                 width: elem.outerWidth(),
12078                 height: elem.outerHeight(),
12079                 offset: elem.offset()
12080         };
12083 $.position = {
12084         scrollbarWidth: function() {
12085                 if ( cachedScrollbarWidth !== undefined ) {
12086                         return cachedScrollbarWidth;
12087                 }
12088                 var w1, w2,
12089                         div = $( "<div style='display:block;width:50px;height:50px;overflow:hidden;'><div style='height:100px;width:auto;'></div></div>" ),
12090                         innerDiv = div.children()[0];
12092                 $( "body" ).append( div );
12093                 w1 = innerDiv.offsetWidth;
12094                 div.css( "overflow", "scroll" );
12096                 w2 = innerDiv.offsetWidth;
12098                 if ( w1 === w2 ) {
12099                         w2 = div[0].clientWidth;
12100                 }
12102                 div.remove();
12104                 return (cachedScrollbarWidth = w1 - w2);
12105         },
12106         getScrollInfo: function( within ) {
12107                 var overflowX = within.isWindow ? "" : within.element.css( "overflow-x" ),
12108                         overflowY = within.isWindow ? "" : within.element.css( "overflow-y" ),
12109                         hasOverflowX = overflowX === "scroll" ||
12110                                 ( overflowX === "auto" && within.width < within.element[0].scrollWidth ),
12111                         hasOverflowY = overflowY === "scroll" ||
12112                                 ( overflowY === "auto" && within.height < within.element[0].scrollHeight );
12113                 return {
12114                         width: hasOverflowY ? $.position.scrollbarWidth() : 0,
12115                         height: hasOverflowX ? $.position.scrollbarWidth() : 0
12116                 };
12117         },
12118         getWithinInfo: function( element ) {
12119                 var withinElement = $( element || window ),
12120                         isWindow = $.isWindow( withinElement[0] );
12121                 return {
12122                         element: withinElement,
12123                         isWindow: isWindow,
12124                         offset: withinElement.offset() || { left: 0, top: 0 },
12125                         scrollLeft: withinElement.scrollLeft(),
12126                         scrollTop: withinElement.scrollTop(),
12127                         width: isWindow ? withinElement.width() : withinElement.outerWidth(),
12128                         height: isWindow ? withinElement.height() : withinElement.outerHeight()
12129                 };
12130         }
12133 $.fn.position = function( options ) {
12134         if ( !options || !options.of ) {
12135                 return _position.apply( this, arguments );
12136         }
12138         // make a copy, we don't want to modify arguments
12139         options = $.extend( {}, options );
12141         var atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions,
12142                 target = $( options.of ),
12143                 within = $.position.getWithinInfo( options.within ),
12144                 scrollInfo = $.position.getScrollInfo( within ),
12145                 collision = ( options.collision || "flip" ).split( " " ),
12146                 offsets = {};
12148         dimensions = getDimensions( target );
12149         if ( target[0].preventDefault ) {
12150                 // force left top to allow flipping
12151                 options.at = "left top";
12152         }
12153         targetWidth = dimensions.width;
12154         targetHeight = dimensions.height;
12155         targetOffset = dimensions.offset;
12156         // clone to reuse original targetOffset later
12157         basePosition = $.extend( {}, targetOffset );
12159         // force my and at to have valid horizontal and vertical positions
12160         // if a value is missing or invalid, it will be converted to center
12161         $.each( [ "my", "at" ], function() {
12162                 var pos = ( options[ this ] || "" ).split( " " ),
12163                         horizontalOffset,
12164                         verticalOffset;
12166                 if ( pos.length === 1) {
12167                         pos = rhorizontal.test( pos[ 0 ] ) ?
12168                                 pos.concat( [ "center" ] ) :
12169                                 rvertical.test( pos[ 0 ] ) ?
12170                                         [ "center" ].concat( pos ) :
12171                                         [ "center", "center" ];
12172                 }
12173                 pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center";
12174                 pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center";
12176                 // calculate offsets
12177                 horizontalOffset = roffset.exec( pos[ 0 ] );
12178                 verticalOffset = roffset.exec( pos[ 1 ] );
12179                 offsets[ this ] = [
12180                         horizontalOffset ? horizontalOffset[ 0 ] : 0,
12181                         verticalOffset ? verticalOffset[ 0 ] : 0
12182                 ];
12184                 // reduce to just the positions without the offsets
12185                 options[ this ] = [
12186                         rposition.exec( pos[ 0 ] )[ 0 ],
12187                         rposition.exec( pos[ 1 ] )[ 0 ]
12188                 ];
12189         });
12191         // normalize collision option
12192         if ( collision.length === 1 ) {
12193                 collision[ 1 ] = collision[ 0 ];
12194         }
12196         if ( options.at[ 0 ] === "right" ) {
12197                 basePosition.left += targetWidth;
12198         } else if ( options.at[ 0 ] === "center" ) {
12199                 basePosition.left += targetWidth / 2;
12200         }
12202         if ( options.at[ 1 ] === "bottom" ) {
12203                 basePosition.top += targetHeight;
12204         } else if ( options.at[ 1 ] === "center" ) {
12205                 basePosition.top += targetHeight / 2;
12206         }
12208         atOffset = getOffsets( offsets.at, targetWidth, targetHeight );
12209         basePosition.left += atOffset[ 0 ];
12210         basePosition.top += atOffset[ 1 ];
12212         return this.each(function() {
12213                 var collisionPosition, using,
12214                         elem = $( this ),
12215                         elemWidth = elem.outerWidth(),
12216                         elemHeight = elem.outerHeight(),
12217                         marginLeft = parseCss( this, "marginLeft" ),
12218                         marginTop = parseCss( this, "marginTop" ),
12219                         collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) + scrollInfo.width,
12220                         collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) + scrollInfo.height,
12221                         position = $.extend( {}, basePosition ),
12222                         myOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() );
12224                 if ( options.my[ 0 ] === "right" ) {
12225                         position.left -= elemWidth;
12226                 } else if ( options.my[ 0 ] === "center" ) {
12227                         position.left -= elemWidth / 2;
12228                 }
12230                 if ( options.my[ 1 ] === "bottom" ) {
12231                         position.top -= elemHeight;
12232                 } else if ( options.my[ 1 ] === "center" ) {
12233                         position.top -= elemHeight / 2;
12234                 }
12236                 position.left += myOffset[ 0 ];
12237                 position.top += myOffset[ 1 ];
12239                 // if the browser doesn't support fractions, then round for consistent results
12240                 if ( !$.support.offsetFractions ) {
12241                         position.left = round( position.left );
12242                         position.top = round( position.top );
12243                 }
12245                 collisionPosition = {
12246                         marginLeft: marginLeft,
12247                         marginTop: marginTop
12248                 };
12250                 $.each( [ "left", "top" ], function( i, dir ) {
12251                         if ( $.ui.position[ collision[ i ] ] ) {
12252                                 $.ui.position[ collision[ i ] ][ dir ]( position, {
12253                                         targetWidth: targetWidth,
12254                                         targetHeight: targetHeight,
12255                                         elemWidth: elemWidth,
12256                                         elemHeight: elemHeight,
12257                                         collisionPosition: collisionPosition,
12258                                         collisionWidth: collisionWidth,
12259                                         collisionHeight: collisionHeight,
12260                                         offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ],
12261                                         my: options.my,
12262                                         at: options.at,
12263                                         within: within,
12264                                         elem : elem
12265                                 });
12266                         }
12267                 });
12269                 if ( options.using ) {
12270                         // adds feedback as second argument to using callback, if present
12271                         using = function( props ) {
12272                                 var left = targetOffset.left - position.left,
12273                                         right = left + targetWidth - elemWidth,
12274                                         top = targetOffset.top - position.top,
12275                                         bottom = top + targetHeight - elemHeight,
12276                                         feedback = {
12277                                                 target: {
12278                                                         element: target,
12279                                                         left: targetOffset.left,
12280                                                         top: targetOffset.top,
12281                                                         width: targetWidth,
12282                                                         height: targetHeight
12283                                                 },
12284                                                 element: {
12285                                                         element: elem,
12286                                                         left: position.left,
12287                                                         top: position.top,
12288                                                         width: elemWidth,
12289                                                         height: elemHeight
12290                                                 },
12291                                                 horizontal: right < 0 ? "left" : left > 0 ? "right" : "center",
12292                                                 vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle"
12293                                         };
12294                                 if ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) {
12295                                         feedback.horizontal = "center";
12296                                 }
12297                                 if ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) {
12298                                         feedback.vertical = "middle";
12299                                 }
12300                                 if ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) {
12301                                         feedback.important = "horizontal";
12302                                 } else {
12303                                         feedback.important = "vertical";
12304                                 }
12305                                 options.using.call( this, props, feedback );
12306                         };
12307                 }
12309                 elem.offset( $.extend( position, { using: using } ) );
12310         });
12313 $.ui.position = {
12314         fit: {
12315                 left: function( position, data ) {
12316                         var within = data.within,
12317                                 withinOffset = within.isWindow ? within.scrollLeft : within.offset.left,
12318                                 outerWidth = within.width,
12319                                 collisionPosLeft = position.left - data.collisionPosition.marginLeft,
12320                                 overLeft = withinOffset - collisionPosLeft,
12321                                 overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset,
12322                                 newOverRight;
12324                         // element is wider than within
12325                         if ( data.collisionWidth > outerWidth ) {
12326                                 // element is initially over the left side of within
12327                                 if ( overLeft > 0 && overRight <= 0 ) {
12328                                         newOverRight = position.left + overLeft + data.collisionWidth - outerWidth - withinOffset;
12329                                         position.left += overLeft - newOverRight;
12330                                 // element is initially over right side of within
12331                                 } else if ( overRight > 0 && overLeft <= 0 ) {
12332                                         position.left = withinOffset;
12333                                 // element is initially over both left and right sides of within
12334                                 } else {
12335                                         if ( overLeft > overRight ) {
12336                                                 position.left = withinOffset + outerWidth - data.collisionWidth;
12337                                         } else {
12338                                                 position.left = withinOffset;
12339                                         }
12340                                 }
12341                         // too far left -> align with left edge
12342                         } else if ( overLeft > 0 ) {
12343                                 position.left += overLeft;
12344                         // too far right -> align with right edge
12345                         } else if ( overRight > 0 ) {
12346                                 position.left -= overRight;
12347                         // adjust based on position and margin
12348                         } else {
12349                                 position.left = max( position.left - collisionPosLeft, position.left );
12350                         }
12351                 },
12352                 top: function( position, data ) {
12353                         var within = data.within,
12354                                 withinOffset = within.isWindow ? within.scrollTop : within.offset.top,
12355                                 outerHeight = data.within.height,
12356                                 collisionPosTop = position.top - data.collisionPosition.marginTop,
12357                                 overTop = withinOffset - collisionPosTop,
12358                                 overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset,
12359                                 newOverBottom;
12361                         // element is taller than within
12362                         if ( data.collisionHeight > outerHeight ) {
12363                                 // element is initially over the top of within
12364                                 if ( overTop > 0 && overBottom <= 0 ) {
12365                                         newOverBottom = position.top + overTop + data.collisionHeight - outerHeight - withinOffset;
12366                                         position.top += overTop - newOverBottom;
12367                                 // element is initially over bottom of within
12368                                 } else if ( overBottom > 0 && overTop <= 0 ) {
12369                                         position.top = withinOffset;
12370                                 // element is initially over both top and bottom of within
12371                                 } else {
12372                                         if ( overTop > overBottom ) {
12373                                                 position.top = withinOffset + outerHeight - data.collisionHeight;
12374                                         } else {
12375                                                 position.top = withinOffset;
12376                                         }
12377                                 }
12378                         // too far up -> align with top
12379                         } else if ( overTop > 0 ) {
12380                                 position.top += overTop;
12381                         // too far down -> align with bottom edge
12382                         } else if ( overBottom > 0 ) {
12383                                 position.top -= overBottom;
12384                         // adjust based on position and margin
12385                         } else {
12386                                 position.top = max( position.top - collisionPosTop, position.top );
12387                         }
12388                 }
12389         },
12390         flip: {
12391                 left: function( position, data ) {
12392                         var within = data.within,
12393                                 withinOffset = within.offset.left + within.scrollLeft,
12394                                 outerWidth = within.width,
12395                                 offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left,
12396                                 collisionPosLeft = position.left - data.collisionPosition.marginLeft,
12397                                 overLeft = collisionPosLeft - offsetLeft,
12398                                 overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft,
12399                                 myOffset = data.my[ 0 ] === "left" ?
12400                                         -data.elemWidth :
12401                                         data.my[ 0 ] === "right" ?
12402                                                 data.elemWidth :
12403                                                 0,
12404                                 atOffset = data.at[ 0 ] === "left" ?
12405                                         data.targetWidth :
12406                                         data.at[ 0 ] === "right" ?
12407                                                 -data.targetWidth :
12408                                                 0,
12409                                 offset = -2 * data.offset[ 0 ],
12410                                 newOverRight,
12411                                 newOverLeft;
12413                         if ( overLeft < 0 ) {
12414                                 newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth - outerWidth - withinOffset;
12415                                 if ( newOverRight < 0 || newOverRight < abs( overLeft ) ) {
12416                                         position.left += myOffset + atOffset + offset;
12417                                 }
12418                         }
12419                         else if ( overRight > 0 ) {
12420                                 newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset + atOffset + offset - offsetLeft;
12421                                 if ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) {
12422                                         position.left += myOffset + atOffset + offset;
12423                                 }
12424                         }
12425                 },
12426                 top: function( position, data ) {
12427                         var within = data.within,
12428                                 withinOffset = within.offset.top + within.scrollTop,
12429                                 outerHeight = within.height,
12430                                 offsetTop = within.isWindow ? within.scrollTop : within.offset.top,
12431                                 collisionPosTop = position.top - data.collisionPosition.marginTop,
12432                                 overTop = collisionPosTop - offsetTop,
12433                                 overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop,
12434                                 top = data.my[ 1 ] === "top",
12435                                 myOffset = top ?
12436                                         -data.elemHeight :
12437                                         data.my[ 1 ] === "bottom" ?
12438                                                 data.elemHeight :
12439                                                 0,
12440                                 atOffset = data.at[ 1 ] === "top" ?
12441                                         data.targetHeight :
12442                                         data.at[ 1 ] === "bottom" ?
12443                                                 -data.targetHeight :
12444                                                 0,
12445                                 offset = -2 * data.offset[ 1 ],
12446                                 newOverTop,
12447                                 newOverBottom;
12448                         if ( overTop < 0 ) {
12449                                 newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight - outerHeight - withinOffset;
12450                                 if ( ( position.top + myOffset + atOffset + offset) > overTop && ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) ) {
12451                                         position.top += myOffset + atOffset + offset;
12452                                 }
12453                         }
12454                         else if ( overBottom > 0 ) {
12455                                 newOverTop = position.top -  data.collisionPosition.marginTop + myOffset + atOffset + offset - offsetTop;
12456                                 if ( ( position.top + myOffset + atOffset + offset) > overBottom && ( newOverTop > 0 || abs( newOverTop ) < overBottom ) ) {
12457                                         position.top += myOffset + atOffset + offset;
12458                                 }
12459                         }
12460                 }
12461         },
12462         flipfit: {
12463                 left: function() {
12464                         $.ui.position.flip.left.apply( this, arguments );
12465                         $.ui.position.fit.left.apply( this, arguments );
12466                 },
12467                 top: function() {
12468                         $.ui.position.flip.top.apply( this, arguments );
12469                         $.ui.position.fit.top.apply( this, arguments );
12470                 }
12471         }
12474 // fraction support test
12475 (function () {
12476         var testElement, testElementParent, testElementStyle, offsetLeft, i,
12477                 body = document.getElementsByTagName( "body" )[ 0 ],
12478                 div = document.createElement( "div" );
12480         //Create a "fake body" for testing based on method used in jQuery.support
12481         testElement = document.createElement( body ? "div" : "body" );
12482         testElementStyle = {
12483                 visibility: "hidden",
12484                 width: 0,
12485                 height: 0,
12486                 border: 0,
12487                 margin: 0,
12488                 background: "none"
12489         };
12490         if ( body ) {
12491                 $.extend( testElementStyle, {
12492                         position: "absolute",
12493                         left: "-1000px",
12494                         top: "-1000px"
12495                 });
12496         }
12497         for ( i in testElementStyle ) {
12498                 testElement.style[ i ] = testElementStyle[ i ];
12499         }
12500         testElement.appendChild( div );
12501         testElementParent = body || document.documentElement;
12502         testElementParent.insertBefore( testElement, testElementParent.firstChild );
12504         div.style.cssText = "position: absolute; left: 10.7432222px;";
12506         offsetLeft = $( div ).offset().left;
12507         $.support.offsetFractions = offsetLeft > 10 && offsetLeft < 11;
12509         testElement.innerHTML = "";
12510         testElementParent.removeChild( testElement );
12511 })();
12513 }( jQuery ) );
12515 (function( $, undefined ) {
12517 $.widget( "ui.progressbar", {
12518         version: "1.10.3",
12519         options: {
12520                 max: 100,
12521                 value: 0,
12523                 change: null,
12524                 complete: null
12525         },
12527         min: 0,
12529         _create: function() {
12530                 // Constrain initial value
12531                 this.oldValue = this.options.value = this._constrainedValue();
12533                 this.element
12534                         .addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
12535                         .attr({
12536                                 // Only set static values, aria-valuenow and aria-valuemax are
12537                                 // set inside _refreshValue()
12538                                 role: "progressbar",
12539                                 "aria-valuemin": this.min
12540                         });
12542                 this.valueDiv = $( "<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>" )
12543                         .appendTo( this.element );
12545                 this._refreshValue();
12546         },
12548         _destroy: function() {
12549                 this.element
12550                         .removeClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
12551                         .removeAttr( "role" )
12552                         .removeAttr( "aria-valuemin" )
12553                         .removeAttr( "aria-valuemax" )
12554                         .removeAttr( "aria-valuenow" );
12556                 this.valueDiv.remove();
12557         },
12559         value: function( newValue ) {
12560                 if ( newValue === undefined ) {
12561                         return this.options.value;
12562                 }
12564                 this.options.value = this._constrainedValue( newValue );
12565                 this._refreshValue();
12566         },
12568         _constrainedValue: function( newValue ) {
12569                 if ( newValue === undefined ) {
12570                         newValue = this.options.value;
12571                 }
12573                 this.indeterminate = newValue === false;
12575                 // sanitize value
12576                 if ( typeof newValue !== "number" ) {
12577                         newValue = 0;
12578                 }
12580                 return this.indeterminate ? false :
12581                         Math.min( this.options.max, Math.max( this.min, newValue ) );
12582         },
12584         _setOptions: function( options ) {
12585                 // Ensure "value" option is set after other values (like max)
12586                 var value = options.value;
12587                 delete options.value;
12589                 this._super( options );
12591                 this.options.value = this._constrainedValue( value );
12592                 this._refreshValue();
12593         },
12595         _setOption: function( key, value ) {
12596                 if ( key === "max" ) {
12597                         // Don't allow a max less than min
12598                         value = Math.max( this.min, value );
12599                 }
12601                 this._super( key, value );
12602         },
12604         _percentage: function() {
12605                 return this.indeterminate ? 100 : 100 * ( this.options.value - this.min ) / ( this.options.max - this.min );
12606         },
12608         _refreshValue: function() {
12609                 var value = this.options.value,
12610                         percentage = this._percentage();
12612                 this.valueDiv
12613                         .toggle( this.indeterminate || value > this.min )
12614                         .toggleClass( "ui-corner-right", value === this.options.max )
12615                         .width( percentage.toFixed(0) + "%" );
12617                 this.element.toggleClass( "ui-progressbar-indeterminate", this.indeterminate );
12619                 if ( this.indeterminate ) {
12620                         this.element.removeAttr( "aria-valuenow" );
12621                         if ( !this.overlayDiv ) {
12622                                 this.overlayDiv = $( "<div class='ui-progressbar-overlay'></div>" ).appendTo( this.valueDiv );
12623                         }
12624                 } else {
12625                         this.element.attr({
12626                                 "aria-valuemax": this.options.max,
12627                                 "aria-valuenow": value
12628                         });
12629                         if ( this.overlayDiv ) {
12630                                 this.overlayDiv.remove();
12631                                 this.overlayDiv = null;
12632                         }
12633                 }
12635                 if ( this.oldValue !== value ) {
12636                         this.oldValue = value;
12637                         this._trigger( "change" );
12638                 }
12639                 if ( value === this.options.max ) {
12640                         this._trigger( "complete" );
12641                 }
12642         }
12645 })( jQuery );
12647 (function( $, undefined ) {
12649 // number of pages in a slider
12650 // (how many times can you page up/down to go through the whole range)
12651 var numPages = 5;
12653 $.widget( "ui.slider", $.ui.mouse, {
12654         version: "1.10.3",
12655         widgetEventPrefix: "slide",
12657         options: {
12658                 animate: false,
12659                 distance: 0,
12660                 max: 100,
12661                 min: 0,
12662                 orientation: "horizontal",
12663                 range: false,
12664                 step: 1,
12665                 value: 0,
12666                 values: null,
12668                 // callbacks
12669                 change: null,
12670                 slide: null,
12671                 start: null,
12672                 stop: null
12673         },
12675         _create: function() {
12676                 this._keySliding = false;
12677                 this._mouseSliding = false;
12678                 this._animateOff = true;
12679                 this._handleIndex = null;
12680                 this._detectOrientation();
12681                 this._mouseInit();
12683                 this.element
12684                         .addClass( "ui-slider" +
12685                                 " ui-slider-" + this.orientation +
12686                                 " ui-widget" +
12687                                 " ui-widget-content" +
12688                                 " ui-corner-all");
12690                 this._refresh();
12691                 this._setOption( "disabled", this.options.disabled );
12693                 this._animateOff = false;
12694         },
12696         _refresh: function() {
12697                 this._createRange();
12698                 this._createHandles();
12699                 this._setupEvents();
12700                 this._refreshValue();
12701         },
12703         _createHandles: function() {
12704                 var i, handleCount,
12705                         options = this.options,
12706                         existingHandles = this.element.find( ".ui-slider-handle" ).addClass( "ui-state-default ui-corner-all" ),
12707                         handle = "<a class='ui-slider-handle ui-state-default ui-corner-all' href='#'></a>",
12708                         handles = [];
12710                 handleCount = ( options.values && options.values.length ) || 1;
12712                 if ( existingHandles.length > handleCount ) {
12713                         existingHandles.slice( handleCount ).remove();
12714                         existingHandles = existingHandles.slice( 0, handleCount );
12715                 }
12717                 for ( i = existingHandles.length; i < handleCount; i++ ) {
12718                         handles.push( handle );
12719                 }
12721                 this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( this.element ) );
12723                 this.handle = this.handles.eq( 0 );
12725                 this.handles.each(function( i ) {
12726                         $( this ).data( "ui-slider-handle-index", i );
12727                 });
12728         },
12730         _createRange: function() {
12731                 var options = this.options,
12732                         classes = "";
12734                 if ( options.range ) {
12735                         if ( options.range === true ) {
12736                                 if ( !options.values ) {
12737                                         options.values = [ this._valueMin(), this._valueMin() ];
12738                                 } else if ( options.values.length && options.values.length !== 2 ) {
12739                                         options.values = [ options.values[0], options.values[0] ];
12740                                 } else if ( $.isArray( options.values ) ) {
12741                                         options.values = options.values.slice(0);
12742                                 }
12743                         }
12745                         if ( !this.range || !this.range.length ) {
12746                                 this.range = $( "<div></div>" )
12747                                         .appendTo( this.element );
12749                                 classes = "ui-slider-range" +
12750                                 // note: this isn't the most fittingly semantic framework class for this element,
12751                                 // but worked best visually with a variety of themes
12752                                 " ui-widget-header ui-corner-all";
12753                         } else {
12754                                 this.range.removeClass( "ui-slider-range-min ui-slider-range-max" )
12755                                         // Handle range switching from true to min/max
12756                                         .css({
12757                                                 "left": "",
12758                                                 "bottom": ""
12759                                         });
12760                         }
12762                         this.range.addClass( classes +
12763                                 ( ( options.range === "min" || options.range === "max" ) ? " ui-slider-range-" + options.range : "" ) );
12764                 } else {
12765                         this.range = $([]);
12766                 }
12767         },
12769         _setupEvents: function() {
12770                 var elements = this.handles.add( this.range ).filter( "a" );
12771                 this._off( elements );
12772                 this._on( elements, this._handleEvents );
12773                 this._hoverable( elements );
12774                 this._focusable( elements );
12775         },
12777         _destroy: function() {
12778                 this.handles.remove();
12779                 this.range.remove();
12781                 this.element
12782                         .removeClass( "ui-slider" +
12783                                 " ui-slider-horizontal" +
12784                                 " ui-slider-vertical" +
12785                                 " ui-widget" +
12786                                 " ui-widget-content" +
12787                                 " ui-corner-all" );
12789                 this._mouseDestroy();
12790         },
12792         _mouseCapture: function( event ) {
12793                 var position, normValue, distance, closestHandle, index, allowed, offset, mouseOverHandle,
12794                         that = this,
12795                         o = this.options;
12797                 if ( o.disabled ) {
12798                         return false;
12799                 }
12801                 this.elementSize = {
12802                         width: this.element.outerWidth(),
12803                         height: this.element.outerHeight()
12804                 };
12805                 this.elementOffset = this.element.offset();
12807                 position = { x: event.pageX, y: event.pageY };
12808                 normValue = this._normValueFromMouse( position );
12809                 distance = this._valueMax() - this._valueMin() + 1;
12810                 this.handles.each(function( i ) {
12811                         var thisDistance = Math.abs( normValue - that.values(i) );
12812                         if (( distance > thisDistance ) ||
12813                                 ( distance === thisDistance &&
12814                                         (i === that._lastChangedValue || that.values(i) === o.min ))) {
12815                                 distance = thisDistance;
12816                                 closestHandle = $( this );
12817                                 index = i;
12818                         }
12819                 });
12821                 allowed = this._start( event, index );
12822                 if ( allowed === false ) {
12823                         return false;
12824                 }
12825                 this._mouseSliding = true;
12827                 this._handleIndex = index;
12829                 closestHandle
12830                         .addClass( "ui-state-active" )
12831                         .focus();
12833                 offset = closestHandle.offset();
12834                 mouseOverHandle = !$( event.target ).parents().addBack().is( ".ui-slider-handle" );
12835                 this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
12836                         left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
12837                         top: event.pageY - offset.top -
12838                                 ( closestHandle.height() / 2 ) -
12839                                 ( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) -
12840                                 ( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) +
12841                                 ( parseInt( closestHandle.css("marginTop"), 10 ) || 0)
12842                 };
12844                 if ( !this.handles.hasClass( "ui-state-hover" ) ) {
12845                         this._slide( event, index, normValue );
12846                 }
12847                 this._animateOff = true;
12848                 return true;
12849         },
12851         _mouseStart: function() {
12852                 return true;
12853         },
12855         _mouseDrag: function( event ) {
12856                 var position = { x: event.pageX, y: event.pageY },
12857                         normValue = this._normValueFromMouse( position );
12859                 this._slide( event, this._handleIndex, normValue );
12861                 return false;
12862         },
12864         _mouseStop: function( event ) {
12865                 this.handles.removeClass( "ui-state-active" );
12866                 this._mouseSliding = false;
12868                 this._stop( event, this._handleIndex );
12869                 this._change( event, this._handleIndex );
12871                 this._handleIndex = null;
12872                 this._clickOffset = null;
12873                 this._animateOff = false;
12875                 return false;
12876         },
12878         _detectOrientation: function() {
12879                 this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
12880         },
12882         _normValueFromMouse: function( position ) {
12883                 var pixelTotal,
12884                         pixelMouse,
12885                         percentMouse,
12886                         valueTotal,
12887                         valueMouse;
12889                 if ( this.orientation === "horizontal" ) {
12890                         pixelTotal = this.elementSize.width;
12891                         pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 );
12892                 } else {
12893                         pixelTotal = this.elementSize.height;
12894                         pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 );
12895                 }
12897                 percentMouse = ( pixelMouse / pixelTotal );
12898                 if ( percentMouse > 1 ) {
12899                         percentMouse = 1;
12900                 }
12901                 if ( percentMouse < 0 ) {
12902                         percentMouse = 0;
12903                 }
12904                 if ( this.orientation === "vertical" ) {
12905                         percentMouse = 1 - percentMouse;
12906                 }
12908                 valueTotal = this._valueMax() - this._valueMin();
12909                 valueMouse = this._valueMin() + percentMouse * valueTotal;
12911                 return this._trimAlignValue( valueMouse );
12912         },
12914         _start: function( event, index ) {
12915                 var uiHash = {
12916                         handle: this.handles[ index ],
12917                         value: this.value()
12918                 };
12919                 if ( this.options.values && this.options.values.length ) {
12920                         uiHash.value = this.values( index );
12921                         uiHash.values = this.values();
12922                 }
12923                 return this._trigger( "start", event, uiHash );
12924         },
12926         _slide: function( event, index, newVal ) {
12927                 var otherVal,
12928                         newValues,
12929                         allowed;
12931                 if ( this.options.values && this.options.values.length ) {
12932                         otherVal = this.values( index ? 0 : 1 );
12934                         if ( ( this.options.values.length === 2 && this.options.range === true ) &&
12935                                         ( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) )
12936                                 ) {
12937                                 newVal = otherVal;
12938                         }
12940                         if ( newVal !== this.values( index ) ) {
12941                                 newValues = this.values();
12942                                 newValues[ index ] = newVal;
12943                                 // A slide can be canceled by returning false from the slide callback
12944                                 allowed = this._trigger( "slide", event, {
12945                                         handle: this.handles[ index ],
12946                                         value: newVal,
12947                                         values: newValues
12948                                 } );
12949                                 otherVal = this.values( index ? 0 : 1 );
12950                                 if ( allowed !== false ) {
12951                                         this.values( index, newVal, true );
12952                                 }
12953                         }
12954                 } else {
12955                         if ( newVal !== this.value() ) {
12956                                 // A slide can be canceled by returning false from the slide callback
12957                                 allowed = this._trigger( "slide", event, {
12958                                         handle: this.handles[ index ],
12959                                         value: newVal
12960                                 } );
12961                                 if ( allowed !== false ) {
12962                                         this.value( newVal );
12963                                 }
12964                         }
12965                 }
12966         },
12968         _stop: function( event, index ) {
12969                 var uiHash = {
12970                         handle: this.handles[ index ],
12971                         value: this.value()
12972                 };
12973                 if ( this.options.values && this.options.values.length ) {
12974                         uiHash.value = this.values( index );
12975                         uiHash.values = this.values();
12976                 }
12978                 this._trigger( "stop", event, uiHash );
12979         },
12981         _change: function( event, index ) {
12982                 if ( !this._keySliding && !this._mouseSliding ) {
12983                         var uiHash = {
12984                                 handle: this.handles[ index ],
12985                                 value: this.value()
12986                         };
12987                         if ( this.options.values && this.options.values.length ) {
12988                                 uiHash.value = this.values( index );
12989                                 uiHash.values = this.values();
12990                         }
12992                         //store the last changed value index for reference when handles overlap
12993                         this._lastChangedValue = index;
12995                         this._trigger( "change", event, uiHash );
12996                 }
12997         },
12999         value: function( newValue ) {
13000                 if ( arguments.length ) {
13001                         this.options.value = this._trimAlignValue( newValue );
13002                         this._refreshValue();
13003                         this._change( null, 0 );
13004                         return;
13005                 }
13007                 return this._value();
13008         },
13010         values: function( index, newValue ) {
13011                 var vals,
13012                         newValues,
13013                         i;
13015                 if ( arguments.length > 1 ) {
13016                         this.options.values[ index ] = this._trimAlignValue( newValue );
13017                         this._refreshValue();
13018                         this._change( null, index );
13019                         return;
13020                 }
13022                 if ( arguments.length ) {
13023                         if ( $.isArray( arguments[ 0 ] ) ) {
13024                                 vals = this.options.values;
13025                                 newValues = arguments[ 0 ];
13026                                 for ( i = 0; i < vals.length; i += 1 ) {
13027                                         vals[ i ] = this._trimAlignValue( newValues[ i ] );
13028                                         this._change( null, i );
13029                                 }
13030                                 this._refreshValue();
13031                         } else {
13032                                 if ( this.options.values && this.options.values.length ) {
13033                                         return this._values( index );
13034                                 } else {
13035                                         return this.value();
13036                                 }
13037                         }
13038                 } else {
13039                         return this._values();
13040                 }
13041         },
13043         _setOption: function( key, value ) {
13044                 var i,
13045                         valsLength = 0;
13047                 if ( key === "range" && this.options.range === true ) {
13048                         if ( value === "min" ) {
13049                                 this.options.value = this._values( 0 );
13050                                 this.options.values = null;
13051                         } else if ( value === "max" ) {
13052                                 this.options.value = this._values( this.options.values.length-1 );
13053                                 this.options.values = null;
13054                         }
13055                 }
13057                 if ( $.isArray( this.options.values ) ) {
13058                         valsLength = this.options.values.length;
13059                 }
13061                 $.Widget.prototype._setOption.apply( this, arguments );
13063                 switch ( key ) {
13064                         case "orientation":
13065                                 this._detectOrientation();
13066                                 this.element
13067                                         .removeClass( "ui-slider-horizontal ui-slider-vertical" )
13068                                         .addClass( "ui-slider-" + this.orientation );
13069                                 this._refreshValue();
13070                                 break;
13071                         case "value":
13072                                 this._animateOff = true;
13073                                 this._refreshValue();
13074                                 this._change( null, 0 );
13075                                 this._animateOff = false;
13076                                 break;
13077                         case "values":
13078                                 this._animateOff = true;
13079                                 this._refreshValue();
13080                                 for ( i = 0; i < valsLength; i += 1 ) {
13081                                         this._change( null, i );
13082                                 }
13083                                 this._animateOff = false;
13084                                 break;
13085                         case "min":
13086                         case "max":
13087                                 this._animateOff = true;
13088                                 this._refreshValue();
13089                                 this._animateOff = false;
13090                                 break;
13091                         case "range":
13092                                 this._animateOff = true;
13093                                 this._refresh();
13094                                 this._animateOff = false;
13095                                 break;
13096                 }
13097         },
13099         //internal value getter
13100         // _value() returns value trimmed by min and max, aligned by step
13101         _value: function() {
13102                 var val = this.options.value;
13103                 val = this._trimAlignValue( val );
13105                 return val;
13106         },
13108         //internal values getter
13109         // _values() returns array of values trimmed by min and max, aligned by step
13110         // _values( index ) returns single value trimmed by min and max, aligned by step
13111         _values: function( index ) {
13112                 var val,
13113                         vals,
13114                         i;
13116                 if ( arguments.length ) {
13117                         val = this.options.values[ index ];
13118                         val = this._trimAlignValue( val );
13120                         return val;
13121                 } else if ( this.options.values && this.options.values.length ) {
13122                         // .slice() creates a copy of the array
13123                         // this copy gets trimmed by min and max and then returned
13124                         vals = this.options.values.slice();
13125                         for ( i = 0; i < vals.length; i+= 1) {
13126                                 vals[ i ] = this._trimAlignValue( vals[ i ] );
13127                         }
13129                         return vals;
13130                 } else {
13131                         return [];
13132                 }
13133         },
13135         // returns the step-aligned value that val is closest to, between (inclusive) min and max
13136         _trimAlignValue: function( val ) {
13137                 if ( val <= this._valueMin() ) {
13138                         return this._valueMin();
13139                 }
13140                 if ( val >= this._valueMax() ) {
13141                         return this._valueMax();
13142                 }
13143                 var step = ( this.options.step > 0 ) ? this.options.step : 1,
13144                         valModStep = (val - this._valueMin()) % step,
13145                         alignValue = val - valModStep;
13147                 if ( Math.abs(valModStep) * 2 >= step ) {
13148                         alignValue += ( valModStep > 0 ) ? step : ( -step );
13149                 }
13151                 // Since JavaScript has problems with large floats, round
13152                 // the final value to 5 digits after the decimal point (see #4124)
13153                 return parseFloat( alignValue.toFixed(5) );
13154         },
13156         _valueMin: function() {
13157                 return this.options.min;
13158         },
13160         _valueMax: function() {
13161                 return this.options.max;
13162         },
13164         _refreshValue: function() {
13165                 var lastValPercent, valPercent, value, valueMin, valueMax,
13166                         oRange = this.options.range,
13167                         o = this.options,
13168                         that = this,
13169                         animate = ( !this._animateOff ) ? o.animate : false,
13170                         _set = {};
13172                 if ( this.options.values && this.options.values.length ) {
13173                         this.handles.each(function( i ) {
13174                                 valPercent = ( that.values(i) - that._valueMin() ) / ( that._valueMax() - that._valueMin() ) * 100;
13175                                 _set[ that.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
13176                                 $( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
13177                                 if ( that.options.range === true ) {
13178                                         if ( that.orientation === "horizontal" ) {
13179                                                 if ( i === 0 ) {
13180                                                         that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate );
13181                                                 }
13182                                                 if ( i === 1 ) {
13183                                                         that.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
13184                                                 }
13185                                         } else {
13186                                                 if ( i === 0 ) {
13187                                                         that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate );
13188                                                 }
13189                                                 if ( i === 1 ) {
13190                                                         that.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
13191                                                 }
13192                                         }
13193                                 }
13194                                 lastValPercent = valPercent;
13195                         });
13196                 } else {
13197                         value = this.value();
13198                         valueMin = this._valueMin();
13199                         valueMax = this._valueMax();
13200                         valPercent = ( valueMax !== valueMin ) ?
13201                                         ( value - valueMin ) / ( valueMax - valueMin ) * 100 :
13202                                         0;
13203                         _set[ this.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
13204                         this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
13206                         if ( oRange === "min" && this.orientation === "horizontal" ) {
13207                                 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate );
13208                         }
13209                         if ( oRange === "max" && this.orientation === "horizontal" ) {
13210                                 this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
13211                         }
13212                         if ( oRange === "min" && this.orientation === "vertical" ) {
13213                                 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate );
13214                         }
13215                         if ( oRange === "max" && this.orientation === "vertical" ) {
13216                                 this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
13217                         }
13218                 }
13219         },
13221         _handleEvents: {
13222                 keydown: function( event ) {
13223                         /*jshint maxcomplexity:25*/
13224                         var allowed, curVal, newVal, step,
13225                                 index = $( event.target ).data( "ui-slider-handle-index" );
13227                         switch ( event.keyCode ) {
13228                                 case $.ui.keyCode.HOME:
13229                                 case $.ui.keyCode.END:
13230                                 case $.ui.keyCode.PAGE_UP:
13231                                 case $.ui.keyCode.PAGE_DOWN:
13232                                 case $.ui.keyCode.UP:
13233                                 case $.ui.keyCode.RIGHT:
13234                                 case $.ui.keyCode.DOWN:
13235                                 case $.ui.keyCode.LEFT:
13236                                         event.preventDefault();
13237                                         if ( !this._keySliding ) {
13238                                                 this._keySliding = true;
13239                                                 $( event.target ).addClass( "ui-state-active" );
13240                                                 allowed = this._start( event, index );
13241                                                 if ( allowed === false ) {
13242                                                         return;
13243                                                 }
13244                                         }
13245                                         break;
13246                         }
13248                         step = this.options.step;
13249                         if ( this.options.values && this.options.values.length ) {
13250                                 curVal = newVal = this.values( index );
13251                         } else {
13252                                 curVal = newVal = this.value();
13253                         }
13255                         switch ( event.keyCode ) {
13256                                 case $.ui.keyCode.HOME:
13257                                         newVal = this._valueMin();
13258                                         break;
13259                                 case $.ui.keyCode.END:
13260                                         newVal = this._valueMax();
13261                                         break;
13262                                 case $.ui.keyCode.PAGE_UP:
13263                                         newVal = this._trimAlignValue( curVal + ( (this._valueMax() - this._valueMin()) / numPages ) );
13264                                         break;
13265                                 case $.ui.keyCode.PAGE_DOWN:
13266                                         newVal = this._trimAlignValue( curVal - ( (this._valueMax() - this._valueMin()) / numPages ) );
13267                                         break;
13268                                 case $.ui.keyCode.UP:
13269                                 case $.ui.keyCode.RIGHT:
13270                                         if ( curVal === this._valueMax() ) {
13271                                                 return;
13272                                         }
13273                                         newVal = this._trimAlignValue( curVal + step );
13274                                         break;
13275                                 case $.ui.keyCode.DOWN:
13276                                 case $.ui.keyCode.LEFT:
13277                                         if ( curVal === this._valueMin() ) {
13278                                                 return;
13279                                         }
13280                                         newVal = this._trimAlignValue( curVal - step );
13281                                         break;
13282                         }
13284                         this._slide( event, index, newVal );
13285                 },
13286                 click: function( event ) {
13287                         event.preventDefault();
13288                 },
13289                 keyup: function( event ) {
13290                         var index = $( event.target ).data( "ui-slider-handle-index" );
13292                         if ( this._keySliding ) {
13293                                 this._keySliding = false;
13294                                 this._stop( event, index );
13295                                 this._change( event, index );
13296                                 $( event.target ).removeClass( "ui-state-active" );
13297                         }
13298                 }
13299         }
13303 }(jQuery));
13305 (function( $ ) {
13307 function modifier( fn ) {
13308         return function() {
13309                 var previous = this.element.val();
13310                 fn.apply( this, arguments );
13311                 this._refresh();
13312                 if ( previous !== this.element.val() ) {
13313                         this._trigger( "change" );
13314                 }
13315         };
13318 $.widget( "ui.spinner", {
13319         version: "1.10.3",
13320         defaultElement: "<input>",
13321         widgetEventPrefix: "spin",
13322         options: {
13323                 culture: null,
13324                 icons: {
13325                         down: "ui-icon-triangle-1-s",
13326                         up: "ui-icon-triangle-1-n"
13327                 },
13328                 incremental: true,
13329                 max: null,
13330                 min: null,
13331                 numberFormat: null,
13332                 page: 10,
13333                 step: 1,
13335                 change: null,
13336                 spin: null,
13337                 start: null,
13338                 stop: null
13339         },
13341         _create: function() {
13342                 // handle string values that need to be parsed
13343                 this._setOption( "max", this.options.max );
13344                 this._setOption( "min", this.options.min );
13345                 this._setOption( "step", this.options.step );
13347                 // format the value, but don't constrain
13348                 this._value( this.element.val(), true );
13350                 this._draw();
13351                 this._on( this._events );
13352                 this._refresh();
13354                 // turning off autocomplete prevents the browser from remembering the
13355                 // value when navigating through history, so we re-enable autocomplete
13356                 // if the page is unloaded before the widget is destroyed. #7790
13357                 this._on( this.window, {
13358                         beforeunload: function() {
13359                                 this.element.removeAttr( "autocomplete" );
13360                         }
13361                 });
13362         },
13364         _getCreateOptions: function() {
13365                 var options = {},
13366                         element = this.element;
13368                 $.each( [ "min", "max", "step" ], function( i, option ) {
13369                         var value = element.attr( option );
13370                         if ( value !== undefined && value.length ) {
13371                                 options[ option ] = value;
13372                         }
13373                 });
13375                 return options;
13376         },
13378         _events: {
13379                 keydown: function( event ) {
13380                         if ( this._start( event ) && this._keydown( event ) ) {
13381                                 event.preventDefault();
13382                         }
13383                 },
13384                 keyup: "_stop",
13385                 focus: function() {
13386                         this.previous = this.element.val();
13387                 },
13388                 blur: function( event ) {
13389                         if ( this.cancelBlur ) {
13390                                 delete this.cancelBlur;
13391                                 return;
13392                         }
13394                         this._stop();
13395                         this._refresh();
13396                         if ( this.previous !== this.element.val() ) {
13397                                 this._trigger( "change", event );
13398                         }
13399                 },
13400                 mousewheel: function( event, delta ) {
13401                         if ( !delta ) {
13402                                 return;
13403                         }
13404                         if ( !this.spinning && !this._start( event ) ) {
13405                                 return false;
13406                         }
13408                         this._spin( (delta > 0 ? 1 : -1) * this.options.step, event );
13409                         clearTimeout( this.mousewheelTimer );
13410                         this.mousewheelTimer = this._delay(function() {
13411                                 if ( this.spinning ) {
13412                                         this._stop( event );
13413                                 }
13414                         }, 100 );
13415                         event.preventDefault();
13416                 },
13417                 "mousedown .ui-spinner-button": function( event ) {
13418                         var previous;
13420                         // We never want the buttons to have focus; whenever the user is
13421                         // interacting with the spinner, the focus should be on the input.
13422                         // If the input is focused then this.previous is properly set from
13423                         // when the input first received focus. If the input is not focused
13424                         // then we need to set this.previous based on the value before spinning.
13425                         previous = this.element[0] === this.document[0].activeElement ?
13426                                 this.previous : this.element.val();
13427                         function checkFocus() {
13428                                 var isActive = this.element[0] === this.document[0].activeElement;
13429                                 if ( !isActive ) {
13430                                         this.element.focus();
13431                                         this.previous = previous;
13432                                         // support: IE
13433                                         // IE sets focus asynchronously, so we need to check if focus
13434                                         // moved off of the input because the user clicked on the button.
13435                                         this._delay(function() {
13436                                                 this.previous = previous;
13437                                         });
13438                                 }
13439                         }
13441                         // ensure focus is on (or stays on) the text field
13442                         event.preventDefault();
13443                         checkFocus.call( this );
13445                         // support: IE
13446                         // IE doesn't prevent moving focus even with event.preventDefault()
13447                         // so we set a flag to know when we should ignore the blur event
13448                         // and check (again) if focus moved off of the input.
13449                         this.cancelBlur = true;
13450                         this._delay(function() {
13451                                 delete this.cancelBlur;
13452                                 checkFocus.call( this );
13453                         });
13455                         if ( this._start( event ) === false ) {
13456                                 return;
13457                         }
13459                         this._repeat( null, $( event.currentTarget ).hasClass( "ui-spinner-up" ) ? 1 : -1, event );
13460                 },
13461                 "mouseup .ui-spinner-button": "_stop",
13462                 "mouseenter .ui-spinner-button": function( event ) {
13463                         // button will add ui-state-active if mouse was down while mouseleave and kept down
13464                         if ( !$( event.currentTarget ).hasClass( "ui-state-active" ) ) {
13465                                 return;
13466                         }
13468                         if ( this._start( event ) === false ) {
13469                                 return false;
13470                         }
13471                         this._repeat( null, $( event.currentTarget ).hasClass( "ui-spinner-up" ) ? 1 : -1, event );
13472                 },
13473                 // TODO: do we really want to consider this a stop?
13474                 // shouldn't we just stop the repeater and wait until mouseup before
13475                 // we trigger the stop event?
13476                 "mouseleave .ui-spinner-button": "_stop"
13477         },
13479         _draw: function() {
13480                 var uiSpinner = this.uiSpinner = this.element
13481                         .addClass( "ui-spinner-input" )
13482                         .attr( "autocomplete", "off" )
13483                         .wrap( this._uiSpinnerHtml() )
13484                         .parent()
13485                                 // add buttons
13486                                 .append( this._buttonHtml() );
13488                 this.element.attr( "role", "spinbutton" );
13490                 // button bindings
13491                 this.buttons = uiSpinner.find( ".ui-spinner-button" )
13492                         .attr( "tabIndex", -1 )
13493                         .button()
13494                         .removeClass( "ui-corner-all" );
13496                 // IE 6 doesn't understand height: 50% for the buttons
13497                 // unless the wrapper has an explicit height
13498                 if ( this.buttons.height() > Math.ceil( uiSpinner.height() * 0.5 ) &&
13499                                 uiSpinner.height() > 0 ) {
13500                         uiSpinner.height( uiSpinner.height() );
13501                 }
13503                 // disable spinner if element was already disabled
13504                 if ( this.options.disabled ) {
13505                         this.disable();
13506                 }
13507         },
13509         _keydown: function( event ) {
13510                 var options = this.options,
13511                         keyCode = $.ui.keyCode;
13513                 switch ( event.keyCode ) {
13514                 case keyCode.UP:
13515                         this._repeat( null, 1, event );
13516                         return true;
13517                 case keyCode.DOWN:
13518                         this._repeat( null, -1, event );
13519                         return true;
13520                 case keyCode.PAGE_UP:
13521                         this._repeat( null, options.page, event );
13522                         return true;
13523                 case keyCode.PAGE_DOWN:
13524                         this._repeat( null, -options.page, event );
13525                         return true;
13526                 }
13528                 return false;
13529         },
13531         _uiSpinnerHtml: function() {
13532                 return "<span class='ui-spinner ui-widget ui-widget-content ui-corner-all'></span>";
13533         },
13535         _buttonHtml: function() {
13536                 return "" +
13537                         "<a class='ui-spinner-button ui-spinner-up ui-corner-tr'>" +
13538                                 "<span class='ui-icon " + this.options.icons.up + "'>&#9650;</span>" +
13539                         "</a>" +
13540                         "<a class='ui-spinner-button ui-spinner-down ui-corner-br'>" +
13541                                 "<span class='ui-icon " + this.options.icons.down + "'>&#9660;</span>" +
13542                         "</a>";
13543         },
13545         _start: function( event ) {
13546                 if ( !this.spinning && this._trigger( "start", event ) === false ) {
13547                         return false;
13548                 }
13550                 if ( !this.counter ) {
13551                         this.counter = 1;
13552                 }
13553                 this.spinning = true;
13554                 return true;
13555         },
13557         _repeat: function( i, steps, event ) {
13558                 i = i || 500;
13560                 clearTimeout( this.timer );
13561                 this.timer = this._delay(function() {
13562                         this._repeat( 40, steps, event );
13563                 }, i );
13565                 this._spin( steps * this.options.step, event );
13566         },
13568         _spin: function( step, event ) {
13569                 var value = this.value() || 0;
13571                 if ( !this.counter ) {
13572                         this.counter = 1;
13573                 }
13575                 value = this._adjustValue( value + step * this._increment( this.counter ) );
13577                 if ( !this.spinning || this._trigger( "spin", event, { value: value } ) !== false) {
13578                         this._value( value );
13579                         this.counter++;
13580                 }
13581         },
13583         _increment: function( i ) {
13584                 var incremental = this.options.incremental;
13586                 if ( incremental ) {
13587                         return $.isFunction( incremental ) ?
13588                                 incremental( i ) :
13589                                 Math.floor( i*i*i/50000 - i*i/500 + 17*i/200 + 1 );
13590                 }
13592                 return 1;
13593         },
13595         _precision: function() {
13596                 var precision = this._precisionOf( this.options.step );
13597                 if ( this.options.min !== null ) {
13598                         precision = Math.max( precision, this._precisionOf( this.options.min ) );
13599                 }
13600                 return precision;
13601         },
13603         _precisionOf: function( num ) {
13604                 var str = num.toString(),
13605                         decimal = str.indexOf( "." );
13606                 return decimal === -1 ? 0 : str.length - decimal - 1;
13607         },
13609         _adjustValue: function( value ) {
13610                 var base, aboveMin,
13611                         options = this.options;
13613                 // make sure we're at a valid step
13614                 // - find out where we are relative to the base (min or 0)
13615                 base = options.min !== null ? options.min : 0;
13616                 aboveMin = value - base;
13617                 // - round to the nearest step
13618                 aboveMin = Math.round(aboveMin / options.step) * options.step;
13619                 // - rounding is based on 0, so adjust back to our base
13620                 value = base + aboveMin;
13622                 // fix precision from bad JS floating point math
13623                 value = parseFloat( value.toFixed( this._precision() ) );
13625                 // clamp the value
13626                 if ( options.max !== null && value > options.max) {
13627                         return options.max;
13628                 }
13629                 if ( options.min !== null && value < options.min ) {
13630                         return options.min;
13631                 }
13633                 return value;
13634         },
13636         _stop: function( event ) {
13637                 if ( !this.spinning ) {
13638                         return;
13639                 }
13641                 clearTimeout( this.timer );
13642                 clearTimeout( this.mousewheelTimer );
13643                 this.counter = 0;
13644                 this.spinning = false;
13645                 this._trigger( "stop", event );
13646         },
13648         _setOption: function( key, value ) {
13649                 if ( key === "culture" || key === "numberFormat" ) {
13650                         var prevValue = this._parse( this.element.val() );
13651                         this.options[ key ] = value;
13652                         this.element.val( this._format( prevValue ) );
13653                         return;
13654                 }
13656                 if ( key === "max" || key === "min" || key === "step" ) {
13657                         if ( typeof value === "string" ) {
13658                                 value = this._parse( value );
13659                         }
13660                 }
13661                 if ( key === "icons" ) {
13662                         this.buttons.first().find( ".ui-icon" )
13663                                 .removeClass( this.options.icons.up )
13664                                 .addClass( value.up );
13665                         this.buttons.last().find( ".ui-icon" )
13666                                 .removeClass( this.options.icons.down )
13667                                 .addClass( value.down );
13668                 }
13670                 this._super( key, value );
13672                 if ( key === "disabled" ) {
13673                         if ( value ) {
13674                                 this.element.prop( "disabled", true );
13675                                 this.buttons.button( "disable" );
13676                         } else {
13677                                 this.element.prop( "disabled", false );
13678                                 this.buttons.button( "enable" );
13679                         }
13680                 }
13681         },
13683         _setOptions: modifier(function( options ) {
13684                 this._super( options );
13685                 this._value( this.element.val() );
13686         }),
13688         _parse: function( val ) {
13689                 if ( typeof val === "string" && val !== "" ) {
13690                         val = window.Globalize && this.options.numberFormat ?
13691                                 Globalize.parseFloat( val, 10, this.options.culture ) : +val;
13692                 }
13693                 return val === "" || isNaN( val ) ? null : val;
13694         },
13696         _format: function( value ) {
13697                 if ( value === "" ) {
13698                         return "";
13699                 }
13700                 return window.Globalize && this.options.numberFormat ?
13701                         Globalize.format( value, this.options.numberFormat, this.options.culture ) :
13702                         value;
13703         },
13705         _refresh: function() {
13706                 this.element.attr({
13707                         "aria-valuemin": this.options.min,
13708                         "aria-valuemax": this.options.max,
13709                         // TODO: what should we do with values that can't be parsed?
13710                         "aria-valuenow": this._parse( this.element.val() )
13711                 });
13712         },
13714         // update the value without triggering change
13715         _value: function( value, allowAny ) {
13716                 var parsed;
13717                 if ( value !== "" ) {
13718                         parsed = this._parse( value );
13719                         if ( parsed !== null ) {
13720                                 if ( !allowAny ) {
13721                                         parsed = this._adjustValue( parsed );
13722                                 }
13723                                 value = this._format( parsed );
13724                         }
13725                 }
13726                 this.element.val( value );
13727                 this._refresh();
13728         },
13730         _destroy: function() {
13731                 this.element
13732                         .removeClass( "ui-spinner-input" )
13733                         .prop( "disabled", false )
13734                         .removeAttr( "autocomplete" )
13735                         .removeAttr( "role" )
13736                         .removeAttr( "aria-valuemin" )
13737                         .removeAttr( "aria-valuemax" )
13738                         .removeAttr( "aria-valuenow" );
13739                 this.uiSpinner.replaceWith( this.element );
13740         },
13742         stepUp: modifier(function( steps ) {
13743                 this._stepUp( steps );
13744         }),
13745         _stepUp: function( steps ) {
13746                 if ( this._start() ) {
13747                         this._spin( (steps || 1) * this.options.step );
13748                         this._stop();
13749                 }
13750         },
13752         stepDown: modifier(function( steps ) {
13753                 this._stepDown( steps );
13754         }),
13755         _stepDown: function( steps ) {
13756                 if ( this._start() ) {
13757                         this._spin( (steps || 1) * -this.options.step );
13758                         this._stop();
13759                 }
13760         },
13762         pageUp: modifier(function( pages ) {
13763                 this._stepUp( (pages || 1) * this.options.page );
13764         }),
13766         pageDown: modifier(function( pages ) {
13767                 this._stepDown( (pages || 1) * this.options.page );
13768         }),
13770         value: function( newVal ) {
13771                 if ( !arguments.length ) {
13772                         return this._parse( this.element.val() );
13773                 }
13774                 modifier( this._value ).call( this, newVal );
13775         },
13777         widget: function() {
13778                 return this.uiSpinner;
13779         }
13782 }( jQuery ) );
13784 (function( $, undefined ) {
13786 var tabId = 0,
13787         rhash = /#.*$/;
13789 function getNextTabId() {
13790         return ++tabId;
13793 function isLocal( anchor ) {
13794         return anchor.hash.length > 1 &&
13795                 decodeURIComponent( anchor.href.replace( rhash, "" ) ) ===
13796                         decodeURIComponent( location.href.replace( rhash, "" ) );
13799 $.widget( "ui.tabs", {
13800         version: "1.10.3",
13801         delay: 300,
13802         options: {
13803                 active: null,
13804                 collapsible: false,
13805                 event: "click",
13806                 heightStyle: "content",
13807                 hide: null,
13808                 show: null,
13810                 // callbacks
13811                 activate: null,
13812                 beforeActivate: null,
13813                 beforeLoad: null,
13814                 load: null
13815         },
13817         _create: function() {
13818                 var that = this,
13819                         options = this.options;
13821                 this.running = false;
13823                 this.element
13824                         .addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" )
13825                         .toggleClass( "ui-tabs-collapsible", options.collapsible )
13826                         // Prevent users from focusing disabled tabs via click
13827                         .delegate( ".ui-tabs-nav > li", "mousedown" + this.eventNamespace, function( event ) {
13828                                 if ( $( this ).is( ".ui-state-disabled" ) ) {
13829                                         event.preventDefault();
13830                                 }
13831                         })
13832                         // support: IE <9
13833                         // Preventing the default action in mousedown doesn't prevent IE
13834                         // from focusing the element, so if the anchor gets focused, blur.
13835                         // We don't have to worry about focusing the previously focused
13836                         // element since clicking on a non-focusable element should focus
13837                         // the body anyway.
13838                         .delegate( ".ui-tabs-anchor", "focus" + this.eventNamespace, function() {
13839                                 if ( $( this ).closest( "li" ).is( ".ui-state-disabled" ) ) {
13840                                         this.blur();
13841                                 }
13842                         });
13844                 this._processTabs();
13845                 options.active = this._initialActive();
13847                 // Take disabling tabs via class attribute from HTML
13848                 // into account and update option properly.
13849                 if ( $.isArray( options.disabled ) ) {
13850                         options.disabled = $.unique( options.disabled.concat(
13851                                 $.map( this.tabs.filter( ".ui-state-disabled" ), function( li ) {
13852                                         return that.tabs.index( li );
13853                                 })
13854                         ) ).sort();
13855                 }
13857                 // check for length avoids error when initializing empty list
13858                 if ( this.options.active !== false && this.anchors.length ) {
13859                         this.active = this._findActive( options.active );
13860                 } else {
13861                         this.active = $();
13862                 }
13864                 this._refresh();
13866                 if ( this.active.length ) {
13867                         this.load( options.active );
13868                 }
13869         },
13871         _initialActive: function() {
13872                 var active = this.options.active,
13873                         collapsible = this.options.collapsible,
13874                         locationHash = location.hash.substring( 1 );
13876                 if ( active === null ) {
13877                         // check the fragment identifier in the URL
13878                         if ( locationHash ) {
13879                                 this.tabs.each(function( i, tab ) {
13880                                         if ( $( tab ).attr( "aria-controls" ) === locationHash ) {
13881                                                 active = i;
13882                                                 return false;
13883                                         }
13884                                 });
13885                         }
13887                         // check for a tab marked active via a class
13888                         if ( active === null ) {
13889                                 active = this.tabs.index( this.tabs.filter( ".ui-tabs-active" ) );
13890                         }
13892                         // no active tab, set to false
13893                         if ( active === null || active === -1 ) {
13894                                 active = this.tabs.length ? 0 : false;
13895                         }
13896                 }
13898                 // handle numbers: negative, out of range
13899                 if ( active !== false ) {
13900                         active = this.tabs.index( this.tabs.eq( active ) );
13901                         if ( active === -1 ) {
13902                                 active = collapsible ? false : 0;
13903                         }
13904                 }
13906                 // don't allow collapsible: false and active: false
13907                 if ( !collapsible && active === false && this.anchors.length ) {
13908                         active = 0;
13909                 }
13911                 return active;
13912         },
13914         _getCreateEventData: function() {
13915                 return {
13916                         tab: this.active,
13917                         panel: !this.active.length ? $() : this._getPanelForTab( this.active )
13918                 };
13919         },
13921         _tabKeydown: function( event ) {
13922                 /*jshint maxcomplexity:15*/
13923                 var focusedTab = $( this.document[0].activeElement ).closest( "li" ),
13924                         selectedIndex = this.tabs.index( focusedTab ),
13925                         goingForward = true;
13927                 if ( this._handlePageNav( event ) ) {
13928                         return;
13929                 }
13931                 switch ( event.keyCode ) {
13932                         case $.ui.keyCode.RIGHT:
13933                         case $.ui.keyCode.DOWN:
13934                                 selectedIndex++;
13935                                 break;
13936                         case $.ui.keyCode.UP:
13937                         case $.ui.keyCode.LEFT:
13938                                 goingForward = false;
13939                                 selectedIndex--;
13940                                 break;
13941                         case $.ui.keyCode.END:
13942                                 selectedIndex = this.anchors.length - 1;
13943                                 break;
13944                         case $.ui.keyCode.HOME:
13945                                 selectedIndex = 0;
13946                                 break;
13947                         case $.ui.keyCode.SPACE:
13948                                 // Activate only, no collapsing
13949                                 event.preventDefault();
13950                                 clearTimeout( this.activating );
13951                                 this._activate( selectedIndex );
13952                                 return;
13953                         case $.ui.keyCode.ENTER:
13954                                 // Toggle (cancel delayed activation, allow collapsing)
13955                                 event.preventDefault();
13956                                 clearTimeout( this.activating );
13957                                 // Determine if we should collapse or activate
13958                                 this._activate( selectedIndex === this.options.active ? false : selectedIndex );
13959                                 return;
13960                         default:
13961                                 return;
13962                 }
13964                 // Focus the appropriate tab, based on which key was pressed
13965                 event.preventDefault();
13966                 clearTimeout( this.activating );
13967                 selectedIndex = this._focusNextTab( selectedIndex, goingForward );
13969                 // Navigating with control key will prevent automatic activation
13970                 if ( !event.ctrlKey ) {
13971                         // Update aria-selected immediately so that AT think the tab is already selected.
13972                         // Otherwise AT may confuse the user by stating that they need to activate the tab,
13973                         // but the tab will already be activated by the time the announcement finishes.
13974                         focusedTab.attr( "aria-selected", "false" );
13975                         this.tabs.eq( selectedIndex ).attr( "aria-selected", "true" );
13977                         this.activating = this._delay(function() {
13978                                 this.option( "active", selectedIndex );
13979                         }, this.delay );
13980                 }
13981         },
13983         _panelKeydown: function( event ) {
13984                 if ( this._handlePageNav( event ) ) {
13985                         return;
13986                 }
13988                 // Ctrl+up moves focus to the current tab
13989                 if ( event.ctrlKey && event.keyCode === $.ui.keyCode.UP ) {
13990                         event.preventDefault();
13991                         this.active.focus();
13992                 }
13993         },
13995         // Alt+page up/down moves focus to the previous/next tab (and activates)
13996         _handlePageNav: function( event ) {
13997                 if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_UP ) {
13998                         this._activate( this._focusNextTab( this.options.active - 1, false ) );
13999                         return true;
14000                 }
14001                 if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_DOWN ) {
14002                         this._activate( this._focusNextTab( this.options.active + 1, true ) );
14003                         return true;
14004                 }
14005         },
14007         _findNextTab: function( index, goingForward ) {
14008                 var lastTabIndex = this.tabs.length - 1;
14010                 function constrain() {
14011                         if ( index > lastTabIndex ) {
14012                                 index = 0;
14013                         }
14014                         if ( index < 0 ) {
14015                                 index = lastTabIndex;
14016                         }
14017                         return index;
14018                 }
14020                 while ( $.inArray( constrain(), this.options.disabled ) !== -1 ) {
14021                         index = goingForward ? index + 1 : index - 1;
14022                 }
14024                 return index;
14025         },
14027         _focusNextTab: function( index, goingForward ) {
14028                 index = this._findNextTab( index, goingForward );
14029                 this.tabs.eq( index ).focus();
14030                 return index;
14031         },
14033         _setOption: function( key, value ) {
14034                 if ( key === "active" ) {
14035                         // _activate() will handle invalid values and update this.options
14036                         this._activate( value );
14037                         return;
14038                 }
14040                 if ( key === "disabled" ) {
14041                         // don't use the widget factory's disabled handling
14042                         this._setupDisabled( value );
14043                         return;
14044                 }
14046                 this._super( key, value);
14048                 if ( key === "collapsible" ) {
14049                         this.element.toggleClass( "ui-tabs-collapsible", value );
14050                         // Setting collapsible: false while collapsed; open first panel
14051                         if ( !value && this.options.active === false ) {
14052                                 this._activate( 0 );
14053                         }
14054                 }
14056                 if ( key === "event" ) {
14057                         this._setupEvents( value );
14058                 }
14060                 if ( key === "heightStyle" ) {
14061                         this._setupHeightStyle( value );
14062                 }
14063         },
14065         _tabId: function( tab ) {
14066                 return tab.attr( "aria-controls" ) || "ui-tabs-" + getNextTabId();
14067         },
14069         _sanitizeSelector: function( hash ) {
14070                 return hash ? hash.replace( /[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g, "\\$&" ) : "";
14071         },
14073         refresh: function() {
14074                 var options = this.options,
14075                         lis = this.tablist.children( ":has(a[href])" );
14077                 // get disabled tabs from class attribute from HTML
14078                 // this will get converted to a boolean if needed in _refresh()
14079                 options.disabled = $.map( lis.filter( ".ui-state-disabled" ), function( tab ) {
14080                         return lis.index( tab );
14081                 });
14083                 this._processTabs();
14085                 // was collapsed or no tabs
14086                 if ( options.active === false || !this.anchors.length ) {
14087                         options.active = false;
14088                         this.active = $();
14089                 // was active, but active tab is gone
14090                 } else if ( this.active.length && !$.contains( this.tablist[ 0 ], this.active[ 0 ] ) ) {
14091                         // all remaining tabs are disabled
14092                         if ( this.tabs.length === options.disabled.length ) {
14093                                 options.active = false;
14094                                 this.active = $();
14095                         // activate previous tab
14096                         } else {
14097                                 this._activate( this._findNextTab( Math.max( 0, options.active - 1 ), false ) );
14098                         }
14099                 // was active, active tab still exists
14100                 } else {
14101                         // make sure active index is correct
14102                         options.active = this.tabs.index( this.active );
14103                 }
14105                 this._refresh();
14106         },
14108         _refresh: function() {
14109                 this._setupDisabled( this.options.disabled );
14110                 this._setupEvents( this.options.event );
14111                 this._setupHeightStyle( this.options.heightStyle );
14113                 this.tabs.not( this.active ).attr({
14114                         "aria-selected": "false",
14115                         tabIndex: -1
14116                 });
14117                 this.panels.not( this._getPanelForTab( this.active ) )
14118                         .hide()
14119                         .attr({
14120                                 "aria-expanded": "false",
14121                                 "aria-hidden": "true"
14122                         });
14124                 // Make sure one tab is in the tab order
14125                 if ( !this.active.length ) {
14126                         this.tabs.eq( 0 ).attr( "tabIndex", 0 );
14127                 } else {
14128                         this.active
14129                                 .addClass( "ui-tabs-active ui-state-active" )
14130                                 .attr({
14131                                         "aria-selected": "true",
14132                                         tabIndex: 0
14133                                 });
14134                         this._getPanelForTab( this.active )
14135                                 .show()
14136                                 .attr({
14137                                         "aria-expanded": "true",
14138                                         "aria-hidden": "false"
14139                                 });
14140                 }
14141         },
14143         _processTabs: function() {
14144                 var that = this;
14146                 this.tablist = this._getList()
14147                         .addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" )
14148                         .attr( "role", "tablist" );
14150                 this.tabs = this.tablist.find( "> li:has(a[href])" )
14151                         .addClass( "ui-state-default ui-corner-top" )
14152                         .attr({
14153                                 role: "tab",
14154                                 tabIndex: -1
14155                         });
14157                 this.anchors = this.tabs.map(function() {
14158                                 return $( "a", this )[ 0 ];
14159                         })
14160                         .addClass( "ui-tabs-anchor" )
14161                         .attr({
14162                                 role: "presentation",
14163                                 tabIndex: -1
14164                         });
14166                 this.panels = $();
14168                 this.anchors.each(function( i, anchor ) {
14169                         var selector, panel, panelId,
14170                                 anchorId = $( anchor ).uniqueId().attr( "id" ),
14171                                 tab = $( anchor ).closest( "li" ),
14172                                 originalAriaControls = tab.attr( "aria-controls" );
14174                         // inline tab
14175                         if ( isLocal( anchor ) ) {
14176                                 selector = anchor.hash;
14177                                 panel = that.element.find( that._sanitizeSelector( selector ) );
14178                         // remote tab
14179                         } else {
14180                                 panelId = that._tabId( tab );
14181                                 selector = "#" + panelId;
14182                                 panel = that.element.find( selector );
14183                                 if ( !panel.length ) {
14184                                         panel = that._createPanel( panelId );
14185                                         panel.insertAfter( that.panels[ i - 1 ] || that.tablist );
14186                                 }
14187                                 panel.attr( "aria-live", "polite" );
14188                         }
14190                         if ( panel.length) {
14191                                 that.panels = that.panels.add( panel );
14192                         }
14193                         if ( originalAriaControls ) {
14194                                 tab.data( "ui-tabs-aria-controls", originalAriaControls );
14195                         }
14196                         tab.attr({
14197                                 "aria-controls": selector.substring( 1 ),
14198                                 "aria-labelledby": anchorId
14199                         });
14200                         panel.attr( "aria-labelledby", anchorId );
14201                 });
14203                 this.panels
14204                         .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
14205                         .attr( "role", "tabpanel" );
14206         },
14208         // allow overriding how to find the list for rare usage scenarios (#7715)
14209         _getList: function() {
14210                 return this.element.find( "ol,ul" ).eq( 0 );
14211         },
14213         _createPanel: function( id ) {
14214                 return $( "<div>" )
14215                         .attr( "id", id )
14216                         .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
14217                         .data( "ui-tabs-destroy", true );
14218         },
14220         _setupDisabled: function( disabled ) {
14221                 if ( $.isArray( disabled ) ) {
14222                         if ( !disabled.length ) {
14223                                 disabled = false;
14224                         } else if ( disabled.length === this.anchors.length ) {
14225                                 disabled = true;
14226                         }
14227                 }
14229                 // disable tabs
14230                 for ( var i = 0, li; ( li = this.tabs[ i ] ); i++ ) {
14231                         if ( disabled === true || $.inArray( i, disabled ) !== -1 ) {
14232                                 $( li )
14233                                         .addClass( "ui-state-disabled" )
14234                                         .attr( "aria-disabled", "true" );
14235                         } else {
14236                                 $( li )
14237                                         .removeClass( "ui-state-disabled" )
14238                                         .removeAttr( "aria-disabled" );
14239                         }
14240                 }
14242                 this.options.disabled = disabled;
14243         },
14245         _setupEvents: function( event ) {
14246                 var events = {
14247                         click: function( event ) {
14248                                 event.preventDefault();
14249                         }
14250                 };
14251                 if ( event ) {
14252                         $.each( event.split(" "), function( index, eventName ) {
14253                                 events[ eventName ] = "_eventHandler";
14254                         });
14255                 }
14257                 this._off( this.anchors.add( this.tabs ).add( this.panels ) );
14258                 this._on( this.anchors, events );
14259                 this._on( this.tabs, { keydown: "_tabKeydown" } );
14260                 this._on( this.panels, { keydown: "_panelKeydown" } );
14262                 this._focusable( this.tabs );
14263                 this._hoverable( this.tabs );
14264         },
14266         _setupHeightStyle: function( heightStyle ) {
14267                 var maxHeight,
14268                         parent = this.element.parent();
14270                 if ( heightStyle === "fill" ) {
14271                         maxHeight = parent.height();
14272                         maxHeight -= this.element.outerHeight() - this.element.height();
14274                         this.element.siblings( ":visible" ).each(function() {
14275                                 var elem = $( this ),
14276                                         position = elem.css( "position" );
14278                                 if ( position === "absolute" || position === "fixed" ) {
14279                                         return;
14280                                 }
14281                                 maxHeight -= elem.outerHeight( true );
14282                         });
14284                         this.element.children().not( this.panels ).each(function() {
14285                                 maxHeight -= $( this ).outerHeight( true );
14286                         });
14288                         this.panels.each(function() {
14289                                 $( this ).height( Math.max( 0, maxHeight -
14290                                         $( this ).innerHeight() + $( this ).height() ) );
14291                         })
14292                         .css( "overflow", "auto" );
14293                 } else if ( heightStyle === "auto" ) {
14294                         maxHeight = 0;
14295                         this.panels.each(function() {
14296                                 maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() );
14297                         }).height( maxHeight );
14298                 }
14299         },
14301         _eventHandler: function( event ) {
14302                 var options = this.options,
14303                         active = this.active,
14304                         anchor = $( event.currentTarget ),
14305                         tab = anchor.closest( "li" ),
14306                         clickedIsActive = tab[ 0 ] === active[ 0 ],
14307                         collapsing = clickedIsActive && options.collapsible,
14308                         toShow = collapsing ? $() : this._getPanelForTab( tab ),
14309                         toHide = !active.length ? $() : this._getPanelForTab( active ),
14310                         eventData = {
14311                                 oldTab: active,
14312                                 oldPanel: toHide,
14313                                 newTab: collapsing ? $() : tab,
14314                                 newPanel: toShow
14315                         };
14317                 event.preventDefault();
14319                 if ( tab.hasClass( "ui-state-disabled" ) ||
14320                                 // tab is already loading
14321                                 tab.hasClass( "ui-tabs-loading" ) ||
14322                                 // can't switch durning an animation
14323                                 this.running ||
14324                                 // click on active header, but not collapsible
14325                                 ( clickedIsActive && !options.collapsible ) ||
14326                                 // allow canceling activation
14327                                 ( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
14328                         return;
14329                 }
14331                 options.active = collapsing ? false : this.tabs.index( tab );
14333                 this.active = clickedIsActive ? $() : tab;
14334                 if ( this.xhr ) {
14335                         this.xhr.abort();
14336                 }
14338                 if ( !toHide.length && !toShow.length ) {
14339                         $.error( "jQuery UI Tabs: Mismatching fragment identifier." );
14340                 }
14342                 if ( toShow.length ) {
14343                         this.load( this.tabs.index( tab ), event );
14344                 }
14345                 this._toggle( event, eventData );
14346         },
14348         // handles show/hide for selecting tabs
14349         _toggle: function( event, eventData ) {
14350                 var that = this,
14351                         toShow = eventData.newPanel,
14352                         toHide = eventData.oldPanel;
14354                 this.running = true;
14356                 function complete() {
14357                         that.running = false;
14358                         that._trigger( "activate", event, eventData );
14359                 }
14361                 function show() {
14362                         eventData.newTab.closest( "li" ).addClass( "ui-tabs-active ui-state-active" );
14364                         if ( toShow.length && that.options.show ) {
14365                                 that._show( toShow, that.options.show, complete );
14366                         } else {
14367                                 toShow.show();
14368                                 complete();
14369                         }
14370                 }
14372                 // start out by hiding, then showing, then completing
14373                 if ( toHide.length && this.options.hide ) {
14374                         this._hide( toHide, this.options.hide, function() {
14375                                 eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" );
14376                                 show();
14377                         });
14378                 } else {
14379                         eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" );
14380                         toHide.hide();
14381                         show();
14382                 }
14384                 toHide.attr({
14385                         "aria-expanded": "false",
14386                         "aria-hidden": "true"
14387                 });
14388                 eventData.oldTab.attr( "aria-selected", "false" );
14389                 // If we're switching tabs, remove the old tab from the tab order.
14390                 // If we're opening from collapsed state, remove the previous tab from the tab order.
14391                 // If we're collapsing, then keep the collapsing tab in the tab order.
14392                 if ( toShow.length && toHide.length ) {
14393                         eventData.oldTab.attr( "tabIndex", -1 );
14394                 } else if ( toShow.length ) {
14395                         this.tabs.filter(function() {
14396                                 return $( this ).attr( "tabIndex" ) === 0;
14397                         })
14398                         .attr( "tabIndex", -1 );
14399                 }
14401                 toShow.attr({
14402                         "aria-expanded": "true",
14403                         "aria-hidden": "false"
14404                 });
14405                 eventData.newTab.attr({
14406                         "aria-selected": "true",
14407                         tabIndex: 0
14408                 });
14409         },
14411         _activate: function( index ) {
14412                 var anchor,
14413                         active = this._findActive( index );
14415                 // trying to activate the already active panel
14416                 if ( active[ 0 ] === this.active[ 0 ] ) {
14417                         return;
14418                 }
14420                 // trying to collapse, simulate a click on the current active header
14421                 if ( !active.length ) {
14422                         active = this.active;
14423                 }
14425                 anchor = active.find( ".ui-tabs-anchor" )[ 0 ];
14426                 this._eventHandler({
14427                         target: anchor,
14428                         currentTarget: anchor,
14429                         preventDefault: $.noop
14430                 });
14431         },
14433         _findActive: function( index ) {
14434                 return index === false ? $() : this.tabs.eq( index );
14435         },
14437         _getIndex: function( index ) {
14438                 // meta-function to give users option to provide a href string instead of a numerical index.
14439                 if ( typeof index === "string" ) {
14440                         index = this.anchors.index( this.anchors.filter( "[href$='" + index + "']" ) );
14441                 }
14443                 return index;
14444         },
14446         _destroy: function() {
14447                 if ( this.xhr ) {
14448                         this.xhr.abort();
14449                 }
14451                 this.element.removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" );
14453                 this.tablist
14454                         .removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" )
14455                         .removeAttr( "role" );
14457                 this.anchors
14458                         .removeClass( "ui-tabs-anchor" )
14459                         .removeAttr( "role" )
14460                         .removeAttr( "tabIndex" )
14461                         .removeUniqueId();
14463                 this.tabs.add( this.panels ).each(function() {
14464                         if ( $.data( this, "ui-tabs-destroy" ) ) {
14465                                 $( this ).remove();
14466                         } else {
14467                                 $( this )
14468                                         .removeClass( "ui-state-default ui-state-active ui-state-disabled " +
14469                                                 "ui-corner-top ui-corner-bottom ui-widget-content ui-tabs-active ui-tabs-panel" )
14470                                         .removeAttr( "tabIndex" )
14471                                         .removeAttr( "aria-live" )
14472                                         .removeAttr( "aria-busy" )
14473                                         .removeAttr( "aria-selected" )
14474                                         .removeAttr( "aria-labelledby" )
14475                                         .removeAttr( "aria-hidden" )
14476                                         .removeAttr( "aria-expanded" )
14477                                         .removeAttr( "role" );
14478                         }
14479                 });
14481                 this.tabs.each(function() {
14482                         var li = $( this ),
14483                                 prev = li.data( "ui-tabs-aria-controls" );
14484                         if ( prev ) {
14485                                 li
14486                                         .attr( "aria-controls", prev )
14487                                         .removeData( "ui-tabs-aria-controls" );
14488                         } else {
14489                                 li.removeAttr( "aria-controls" );
14490                         }
14491                 });
14493                 this.panels.show();
14495                 if ( this.options.heightStyle !== "content" ) {
14496                         this.panels.css( "height", "" );
14497                 }
14498         },
14500         enable: function( index ) {
14501                 var disabled = this.options.disabled;
14502                 if ( disabled === false ) {
14503                         return;
14504                 }
14506                 if ( index === undefined ) {
14507                         disabled = false;
14508                 } else {
14509                         index = this._getIndex( index );
14510                         if ( $.isArray( disabled ) ) {
14511                                 disabled = $.map( disabled, function( num ) {
14512                                         return num !== index ? num : null;
14513                                 });
14514                         } else {
14515                                 disabled = $.map( this.tabs, function( li, num ) {
14516                                         return num !== index ? num : null;
14517                                 });
14518                         }
14519                 }
14520                 this._setupDisabled( disabled );
14521         },
14523         disable: function( index ) {
14524                 var disabled = this.options.disabled;
14525                 if ( disabled === true ) {
14526                         return;
14527                 }
14529                 if ( index === undefined ) {
14530                         disabled = true;
14531                 } else {
14532                         index = this._getIndex( index );
14533                         if ( $.inArray( index, disabled ) !== -1 ) {
14534                                 return;
14535                         }
14536                         if ( $.isArray( disabled ) ) {
14537                                 disabled = $.merge( [ index ], disabled ).sort();
14538                         } else {
14539                                 disabled = [ index ];
14540                         }
14541                 }
14542                 this._setupDisabled( disabled );
14543         },
14545         load: function( index, event ) {
14546                 index = this._getIndex( index );
14547                 var that = this,
14548                         tab = this.tabs.eq( index ),
14549                         anchor = tab.find( ".ui-tabs-anchor" ),
14550                         panel = this._getPanelForTab( tab ),
14551                         eventData = {
14552                                 tab: tab,
14553                                 panel: panel
14554                         };
14556                 // not remote
14557                 if ( isLocal( anchor[ 0 ] ) ) {
14558                         return;
14559                 }
14561                 this.xhr = $.ajax( this._ajaxSettings( anchor, event, eventData ) );
14563                 // support: jQuery <1.8
14564                 // jQuery <1.8 returns false if the request is canceled in beforeSend,
14565                 // but as of 1.8, $.ajax() always returns a jqXHR object.
14566                 if ( this.xhr && this.xhr.statusText !== "canceled" ) {
14567                         tab.addClass( "ui-tabs-loading" );
14568                         panel.attr( "aria-busy", "true" );
14570                         this.xhr
14571                                 .success(function( response ) {
14572                                         // support: jQuery <1.8
14573                                         // http://bugs.jquery.com/ticket/11778
14574                                         setTimeout(function() {
14575                                                 panel.html( response );
14576                                                 that._trigger( "load", event, eventData );
14577                                         }, 1 );
14578                                 })
14579                                 .complete(function( jqXHR, status ) {
14580                                         // support: jQuery <1.8
14581                                         // http://bugs.jquery.com/ticket/11778
14582                                         setTimeout(function() {
14583                                                 if ( status === "abort" ) {
14584                                                         that.panels.stop( false, true );
14585                                                 }
14587                                                 tab.removeClass( "ui-tabs-loading" );
14588                                                 panel.removeAttr( "aria-busy" );
14590                                                 if ( jqXHR === that.xhr ) {
14591                                                         delete that.xhr;
14592                                                 }
14593                                         }, 1 );
14594                                 });
14595                 }
14596         },
14598         _ajaxSettings: function( anchor, event, eventData ) {
14599                 var that = this;
14600                 return {
14601                         url: anchor.attr( "href" ),
14602                         beforeSend: function( jqXHR, settings ) {
14603                                 return that._trigger( "beforeLoad", event,
14604                                         $.extend( { jqXHR : jqXHR, ajaxSettings: settings }, eventData ) );
14605                         }
14606                 };
14607         },
14609         _getPanelForTab: function( tab ) {
14610                 var id = $( tab ).attr( "aria-controls" );
14611                 return this.element.find( this._sanitizeSelector( "#" + id ) );
14612         }
14615 })( jQuery );
14617 (function( $ ) {
14619 var increments = 0;
14621 function addDescribedBy( elem, id ) {
14622         var describedby = (elem.attr( "aria-describedby" ) || "").split( /\s+/ );
14623         describedby.push( id );
14624         elem
14625                 .data( "ui-tooltip-id", id )
14626                 .attr( "aria-describedby", $.trim( describedby.join( " " ) ) );
14629 function removeDescribedBy( elem ) {
14630         var id = elem.data( "ui-tooltip-id" ),
14631                 describedby = (elem.attr( "aria-describedby" ) || "").split( /\s+/ ),
14632                 index = $.inArray( id, describedby );
14633         if ( index !== -1 ) {
14634                 describedby.splice( index, 1 );
14635         }
14637         elem.removeData( "ui-tooltip-id" );
14638         describedby = $.trim( describedby.join( " " ) );
14639         if ( describedby ) {
14640                 elem.attr( "aria-describedby", describedby );
14641         } else {
14642                 elem.removeAttr( "aria-describedby" );
14643         }
14646 $.widget( "ui.tooltip", {
14647         version: "1.10.3",
14648         options: {
14649                 content: function() {
14650                         // support: IE<9, Opera in jQuery <1.7
14651                         // .text() can't accept undefined, so coerce to a string
14652                         var title = $( this ).attr( "title" ) || "";
14653                         // Escape title, since we're going from an attribute to raw HTML
14654                         return $( "<a>" ).text( title ).html();
14655                 },
14656                 hide: true,
14657                 // Disabled elements have inconsistent behavior across browsers (#8661)
14658                 items: "[title]:not([disabled])",
14659                 position: {
14660                         my: "left top+15",
14661                         at: "left bottom",
14662                         collision: "flipfit flip"
14663                 },
14664                 show: true,
14665                 tooltipClass: null,
14666                 track: false,
14668                 // callbacks
14669                 close: null,
14670                 open: null
14671         },
14673         _create: function() {
14674                 this._on({
14675                         mouseover: "open",
14676                         focusin: "open"
14677                 });
14679                 // IDs of generated tooltips, needed for destroy
14680                 this.tooltips = {};
14681                 // IDs of parent tooltips where we removed the title attribute
14682                 this.parents = {};
14684                 if ( this.options.disabled ) {
14685                         this._disable();
14686                 }
14687         },
14689         _setOption: function( key, value ) {
14690                 var that = this;
14692                 if ( key === "disabled" ) {
14693                         this[ value ? "_disable" : "_enable" ]();
14694                         this.options[ key ] = value;
14695                         // disable element style changes
14696                         return;
14697                 }
14699                 this._super( key, value );
14701                 if ( key === "content" ) {
14702                         $.each( this.tooltips, function( id, element ) {
14703                                 that._updateContent( element );
14704                         });
14705                 }
14706         },
14708         _disable: function() {
14709                 var that = this;
14711                 // close open tooltips
14712                 $.each( this.tooltips, function( id, element ) {
14713                         var event = $.Event( "blur" );
14714                         event.target = event.currentTarget = element[0];
14715                         that.close( event, true );
14716                 });
14718                 // remove title attributes to prevent native tooltips
14719                 this.element.find( this.options.items ).addBack().each(function() {
14720                         var element = $( this );
14721                         if ( element.is( "[title]" ) ) {
14722                                 element
14723                                         .data( "ui-tooltip-title", element.attr( "title" ) )
14724                                         .attr( "title", "" );
14725                         }
14726                 });
14727         },
14729         _enable: function() {
14730                 // restore title attributes
14731                 this.element.find( this.options.items ).addBack().each(function() {
14732                         var element = $( this );
14733                         if ( element.data( "ui-tooltip-title" ) ) {
14734                                 element.attr( "title", element.data( "ui-tooltip-title" ) );
14735                         }
14736                 });
14737         },
14739         open: function( event ) {
14740                 var that = this,
14741                         target = $( event ? event.target : this.element )
14742                                 // we need closest here due to mouseover bubbling,
14743                                 // but always pointing at the same event target
14744                                 .closest( this.options.items );
14746                 // No element to show a tooltip for or the tooltip is already open
14747                 if ( !target.length || target.data( "ui-tooltip-id" ) ) {
14748                         return;
14749                 }
14751                 if ( target.attr( "title" ) ) {
14752                         target.data( "ui-tooltip-title", target.attr( "title" ) );
14753                 }
14755                 target.data( "ui-tooltip-open", true );
14757                 // kill parent tooltips, custom or native, for hover
14758                 if ( event && event.type === "mouseover" ) {
14759                         target.parents().each(function() {
14760                                 var parent = $( this ),
14761                                         blurEvent;
14762                                 if ( parent.data( "ui-tooltip-open" ) ) {
14763                                         blurEvent = $.Event( "blur" );
14764                                         blurEvent.target = blurEvent.currentTarget = this;
14765                                         that.close( blurEvent, true );
14766                                 }
14767                                 if ( parent.attr( "title" ) ) {
14768                                         parent.uniqueId();
14769                                         that.parents[ this.id ] = {
14770                                                 element: this,
14771                                                 title: parent.attr( "title" )
14772                                         };
14773                                         parent.attr( "title", "" );
14774                                 }
14775                         });
14776                 }
14778                 this._updateContent( target, event );
14779         },
14781         _updateContent: function( target, event ) {
14782                 var content,
14783                         contentOption = this.options.content,
14784                         that = this,
14785                         eventType = event ? event.type : null;
14787                 if ( typeof contentOption === "string" ) {
14788                         return this._open( event, target, contentOption );
14789                 }
14791                 content = contentOption.call( target[0], function( response ) {
14792                         // ignore async response if tooltip was closed already
14793                         if ( !target.data( "ui-tooltip-open" ) ) {
14794                                 return;
14795                         }
14796                         // IE may instantly serve a cached response for ajax requests
14797                         // delay this call to _open so the other call to _open runs first
14798                         that._delay(function() {
14799                                 // jQuery creates a special event for focusin when it doesn't
14800                                 // exist natively. To improve performance, the native event
14801                                 // object is reused and the type is changed. Therefore, we can't
14802                                 // rely on the type being correct after the event finished
14803                                 // bubbling, so we set it back to the previous value. (#8740)
14804                                 if ( event ) {
14805                                         event.type = eventType;
14806                                 }
14807                                 this._open( event, target, response );
14808                         });
14809                 });
14810                 if ( content ) {
14811                         this._open( event, target, content );
14812                 }
14813         },
14815         _open: function( event, target, content ) {
14816                 var tooltip, events, delayedShow,
14817                         positionOption = $.extend( {}, this.options.position );
14819                 if ( !content ) {
14820                         return;
14821                 }
14823                 // Content can be updated multiple times. If the tooltip already
14824                 // exists, then just update the content and bail.
14825                 tooltip = this._find( target );
14826                 if ( tooltip.length ) {
14827                         tooltip.find( ".ui-tooltip-content" ).html( content );
14828                         return;
14829                 }
14831                 // if we have a title, clear it to prevent the native tooltip
14832                 // we have to check first to avoid defining a title if none exists
14833                 // (we don't want to cause an element to start matching [title])
14834                 //
14835                 // We use removeAttr only for key events, to allow IE to export the correct
14836                 // accessible attributes. For mouse events, set to empty string to avoid
14837                 // native tooltip showing up (happens only when removing inside mouseover).
14838                 if ( target.is( "[title]" ) ) {
14839                         if ( event && event.type === "mouseover" ) {
14840                                 target.attr( "title", "" );
14841                         } else {
14842                                 target.removeAttr( "title" );
14843                         }
14844                 }
14846                 tooltip = this._tooltip( target );
14847                 addDescribedBy( target, tooltip.attr( "id" ) );
14848                 tooltip.find( ".ui-tooltip-content" ).html( content );
14850                 function position( event ) {
14851                         positionOption.of = event;
14852                         if ( tooltip.is( ":hidden" ) ) {
14853                                 return;
14854                         }
14855                         tooltip.position( positionOption );
14856                 }
14857                 if ( this.options.track && event && /^mouse/.test( event.type ) ) {
14858                         this._on( this.document, {
14859                                 mousemove: position
14860                         });
14861                         // trigger once to override element-relative positioning
14862                         position( event );
14863                 } else {
14864                         tooltip.position( $.extend({
14865                                 of: target
14866                         }, this.options.position ) );
14867                 }
14869                 tooltip.hide();
14871                 this._show( tooltip, this.options.show );
14872                 // Handle tracking tooltips that are shown with a delay (#8644). As soon
14873                 // as the tooltip is visible, position the tooltip using the most recent
14874                 // event.
14875                 if ( this.options.show && this.options.show.delay ) {
14876                         delayedShow = this.delayedShow = setInterval(function() {
14877                                 if ( tooltip.is( ":visible" ) ) {
14878                                         position( positionOption.of );
14879                                         clearInterval( delayedShow );
14880                                 }
14881                         }, $.fx.interval );
14882                 }
14884                 this._trigger( "open", event, { tooltip: tooltip } );
14886                 events = {
14887                         keyup: function( event ) {
14888                                 if ( event.keyCode === $.ui.keyCode.ESCAPE ) {
14889                                         var fakeEvent = $.Event(event);
14890                                         fakeEvent.currentTarget = target[0];
14891                                         this.close( fakeEvent, true );
14892                                 }
14893                         },
14894                         remove: function() {
14895                                 this._removeTooltip( tooltip );
14896                         }
14897                 };
14898                 if ( !event || event.type === "mouseover" ) {
14899                         events.mouseleave = "close";
14900                 }
14901                 if ( !event || event.type === "focusin" ) {
14902                         events.focusout = "close";
14903                 }
14904                 this._on( true, target, events );
14905         },
14907         close: function( event ) {
14908                 var that = this,
14909                         target = $( event ? event.currentTarget : this.element ),
14910                         tooltip = this._find( target );
14912                 // disabling closes the tooltip, so we need to track when we're closing
14913                 // to avoid an infinite loop in case the tooltip becomes disabled on close
14914                 if ( this.closing ) {
14915                         return;
14916                 }
14918                 // Clear the interval for delayed tracking tooltips
14919                 clearInterval( this.delayedShow );
14921                 // only set title if we had one before (see comment in _open())
14922                 if ( target.data( "ui-tooltip-title" ) ) {
14923                         target.attr( "title", target.data( "ui-tooltip-title" ) );
14924                 }
14926                 removeDescribedBy( target );
14928                 tooltip.stop( true );
14929                 this._hide( tooltip, this.options.hide, function() {
14930                         that._removeTooltip( $( this ) );
14931                 });
14933                 target.removeData( "ui-tooltip-open" );
14934                 this._off( target, "mouseleave focusout keyup" );
14935                 // Remove 'remove' binding only on delegated targets
14936                 if ( target[0] !== this.element[0] ) {
14937                         this._off( target, "remove" );
14938                 }
14939                 this._off( this.document, "mousemove" );
14941                 if ( event && event.type === "mouseleave" ) {
14942                         $.each( this.parents, function( id, parent ) {
14943                                 $( parent.element ).attr( "title", parent.title );
14944                                 delete that.parents[ id ];
14945                         });
14946                 }
14948                 this.closing = true;
14949                 this._trigger( "close", event, { tooltip: tooltip } );
14950                 this.closing = false;
14951         },
14953         _tooltip: function( element ) {
14954                 var id = "ui-tooltip-" + increments++,
14955                         tooltip = $( "<div>" )
14956                                 .attr({
14957                                         id: id,
14958                                         role: "tooltip"
14959                                 })
14960                                 .addClass( "ui-tooltip ui-widget ui-corner-all ui-widget-content " +
14961                                         ( this.options.tooltipClass || "" ) );
14962                 $( "<div>" )
14963                         .addClass( "ui-tooltip-content" )
14964                         .appendTo( tooltip );
14965                 tooltip.appendTo( this.document[0].body );
14966                 this.tooltips[ id ] = element;
14967                 return tooltip;
14968         },
14970         _find: function( target ) {
14971                 var id = target.data( "ui-tooltip-id" );
14972                 return id ? $( "#" + id ) : $();
14973         },
14975         _removeTooltip: function( tooltip ) {
14976                 tooltip.remove();
14977                 delete this.tooltips[ tooltip.attr( "id" ) ];
14978         },
14980         _destroy: function() {
14981                 var that = this;
14983                 // close open tooltips
14984                 $.each( this.tooltips, function( id, element ) {
14985                         // Delegate to close method to handle common cleanup
14986                         var event = $.Event( "blur" );
14987                         event.target = event.currentTarget = element[0];
14988                         that.close( event, true );
14990                         // Remove immediately; destroying an open tooltip doesn't use the
14991                         // hide animation
14992                         $( "#" + id ).remove();
14994                         // Restore the title
14995                         if ( element.data( "ui-tooltip-title" ) ) {
14996                                 element.attr( "title", element.data( "ui-tooltip-title" ) );
14997                                 element.removeData( "ui-tooltip-title" );
14998                         }
14999                 });
15000         }
15003 }( jQuery ) );