/[svn]/doc/tmpl/js/jquery-ui.js
ViewVC logotype

Annotation of /doc/tmpl/js/jquery-ui.js

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3275 - (hide annotations) (download) (as text)
Mon Jun 5 15:08:11 2017 UTC (6 years, 10 months ago) by schoenebeck
File MIME type: application/javascript
File size: 471449 byte(s)
* Site Template: Visual corrections of tooltips.

1 schoenebeck 2732 /*! jQuery UI - v1.11.4 - 2015-03-11
2     * http://jqueryui.com
3     * Includes: core.js, widget.js, mouse.js, position.js, accordion.js, autocomplete.js, button.js, datepicker.js, dialog.js, draggable.js, droppable.js, effect.js, effect-blind.js, effect-bounce.js, effect-clip.js, effect-drop.js, effect-explode.js, effect-fade.js, effect-fold.js, effect-highlight.js, effect-puff.js, effect-pulsate.js, effect-scale.js, effect-shake.js, effect-size.js, effect-slide.js, effect-transfer.js, menu.js, progressbar.js, resizable.js, selectable.js, selectmenu.js, slider.js, sortable.js, spinner.js, tabs.js, tooltip.js
4     * Copyright 2015 jQuery Foundation and other contributors; Licensed MIT */
5    
6     /*
7     * Modifications by Christian Schoenebeck:
8     *
9     * 2015-04-05: Collision detection algorithm now adds a respective
10     * 'ui-collision-*' CSS class to the element, so one can write
11     * separate CSS rules if some widget got flipped.
12     *
13     * 2015-04-06: Tooltips: Added support for HTML markup to "title" attribute.
14     */
15    
16     (function( factory ) {
17     if ( typeof define === "function" && define.amd ) {
18    
19     // AMD. Register as an anonymous module.
20     define([ "jquery" ], factory );
21     } else {
22    
23     // Browser globals
24     factory( jQuery );
25     }
26     }(function( $ ) {
27     /*!
28     * jQuery UI Core 1.11.4
29     * http://jqueryui.com
30     *
31     * Copyright jQuery Foundation and other contributors
32     * Released under the MIT license.
33     * http://jquery.org/license
34     *
35     * http://api.jqueryui.com/category/ui-core/
36     */
37    
38    
39     // $.ui might exist from components with no dependencies, e.g., $.ui.position
40     $.ui = $.ui || {};
41    
42     $.extend( $.ui, {
43     version: "1.11.4",
44    
45     keyCode: {
46     BACKSPACE: 8,
47     COMMA: 188,
48     DELETE: 46,
49     DOWN: 40,
50     END: 35,
51     ENTER: 13,
52     ESCAPE: 27,
53     HOME: 36,
54     LEFT: 37,
55     PAGE_DOWN: 34,
56     PAGE_UP: 33,
57     PERIOD: 190,
58     RIGHT: 39,
59     SPACE: 32,
60     TAB: 9,
61     UP: 38
62     }
63     });
64    
65     // plugins
66     $.fn.extend({
67     scrollParent: function( includeHidden ) {
68     var position = this.css( "position" ),
69     excludeStaticParent = position === "absolute",
70     overflowRegex = includeHidden ? /(auto|scroll|hidden)/ : /(auto|scroll)/,
71     scrollParent = this.parents().filter( function() {
72     var parent = $( this );
73     if ( excludeStaticParent && parent.css( "position" ) === "static" ) {
74     return false;
75     }
76     return overflowRegex.test( parent.css( "overflow" ) + parent.css( "overflow-y" ) + parent.css( "overflow-x" ) );
77     }).eq( 0 );
78    
79     return position === "fixed" || !scrollParent.length ? $( this[ 0 ].ownerDocument || document ) : scrollParent;
80     },
81    
82     uniqueId: (function() {
83     var uuid = 0;
84    
85     return function() {
86     return this.each(function() {
87     if ( !this.id ) {
88     this.id = "ui-id-" + ( ++uuid );
89     }
90     });
91     };
92     })(),
93    
94     removeUniqueId: function() {
95     return this.each(function() {
96     if ( /^ui-id-\d+$/.test( this.id ) ) {
97     $( this ).removeAttr( "id" );
98     }
99     });
100     }
101     });
102    
103     // selectors
104     function focusable( element, isTabIndexNotNaN ) {
105     var map, mapName, img,
106     nodeName = element.nodeName.toLowerCase();
107     if ( "area" === nodeName ) {
108     map = element.parentNode;
109     mapName = map.name;
110     if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
111     return false;
112     }
113     img = $( "img[usemap='#" + mapName + "']" )[ 0 ];
114     return !!img && visible( img );
115     }
116     return ( /^(input|select|textarea|button|object)$/.test( nodeName ) ?
117     !element.disabled :
118     "a" === nodeName ?
119     element.href || isTabIndexNotNaN :
120     isTabIndexNotNaN) &&
121     // the element and all of its ancestors must be visible
122     visible( element );
123     }
124    
125     function visible( element ) {
126     return $.expr.filters.visible( element ) &&
127     !$( element ).parents().addBack().filter(function() {
128     return $.css( this, "visibility" ) === "hidden";
129     }).length;
130     }
131    
132     $.extend( $.expr[ ":" ], {
133     data: $.expr.createPseudo ?
134     $.expr.createPseudo(function( dataName ) {
135     return function( elem ) {
136     return !!$.data( elem, dataName );
137     };
138     }) :
139     // support: jQuery <1.8
140     function( elem, i, match ) {
141     return !!$.data( elem, match[ 3 ] );
142     },
143    
144     focusable: function( element ) {
145     return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) );
146     },
147    
148     tabbable: function( element ) {
149     var tabIndex = $.attr( element, "tabindex" ),
150     isTabIndexNaN = isNaN( tabIndex );
151     return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN );
152     }
153     });
154    
155     // support: jQuery <1.8
156     if ( !$( "<a>" ).outerWidth( 1 ).jquery ) {
157     $.each( [ "Width", "Height" ], function( i, name ) {
158     var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
159     type = name.toLowerCase(),
160     orig = {
161     innerWidth: $.fn.innerWidth,
162     innerHeight: $.fn.innerHeight,
163     outerWidth: $.fn.outerWidth,
164     outerHeight: $.fn.outerHeight
165     };
166    
167     function reduce( elem, size, border, margin ) {
168     $.each( side, function() {
169     size -= parseFloat( $.css( elem, "padding" + this ) ) || 0;
170     if ( border ) {
171     size -= parseFloat( $.css( elem, "border" + this + "Width" ) ) || 0;
172     }
173     if ( margin ) {
174     size -= parseFloat( $.css( elem, "margin" + this ) ) || 0;
175     }
176     });
177     return size;
178     }
179    
180     $.fn[ "inner" + name ] = function( size ) {
181     if ( size === undefined ) {
182     return orig[ "inner" + name ].call( this );
183     }
184    
185     return this.each(function() {
186     $( this ).css( type, reduce( this, size ) + "px" );
187     });
188     };
189    
190     $.fn[ "outer" + name] = function( size, margin ) {
191     if ( typeof size !== "number" ) {
192     return orig[ "outer" + name ].call( this, size );
193     }
194    
195     return this.each(function() {
196     $( this).css( type, reduce( this, size, true, margin ) + "px" );
197     });
198     };
199     });
200     }
201    
202     // support: jQuery <1.8
203     if ( !$.fn.addBack ) {
204     $.fn.addBack = function( selector ) {
205     return this.add( selector == null ?
206     this.prevObject : this.prevObject.filter( selector )
207     );
208     };
209     }
210    
211     // support: jQuery 1.6.1, 1.6.2 (http://bugs.jquery.com/ticket/9413)
212     if ( $( "<a>" ).data( "a-b", "a" ).removeData( "a-b" ).data( "a-b" ) ) {
213     $.fn.removeData = (function( removeData ) {
214     return function( key ) {
215     if ( arguments.length ) {
216     return removeData.call( this, $.camelCase( key ) );
217     } else {
218     return removeData.call( this );
219     }
220     };
221     })( $.fn.removeData );
222     }
223    
224     // deprecated
225     $.ui.ie = !!/msie [\w.]+/.exec( navigator.userAgent.toLowerCase() );
226    
227     $.fn.extend({
228     focus: (function( orig ) {
229     return function( delay, fn ) {
230     return typeof delay === "number" ?
231     this.each(function() {
232     var elem = this;
233     setTimeout(function() {
234     $( elem ).focus();
235     if ( fn ) {
236     fn.call( elem );
237     }
238     }, delay );
239     }) :
240     orig.apply( this, arguments );
241     };
242     })( $.fn.focus ),
243    
244     disableSelection: (function() {
245     var eventType = "onselectstart" in document.createElement( "div" ) ?
246     "selectstart" :
247     "mousedown";
248    
249     return function() {
250     return this.bind( eventType + ".ui-disableSelection", function( event ) {
251     event.preventDefault();
252     });
253     };
254     })(),
255    
256     enableSelection: function() {
257     return this.unbind( ".ui-disableSelection" );
258     },
259    
260     zIndex: function( zIndex ) {
261     if ( zIndex !== undefined ) {
262     return this.css( "zIndex", zIndex );
263     }
264    
265     if ( this.length ) {
266     var elem = $( this[ 0 ] ), position, value;
267     while ( elem.length && elem[ 0 ] !== document ) {
268     // Ignore z-index if position is set to a value where z-index is ignored by the browser
269     // This makes behavior of this function consistent across browsers
270     // WebKit always returns auto if the element is positioned
271     position = elem.css( "position" );
272     if ( position === "absolute" || position === "relative" || position === "fixed" ) {
273     // IE returns 0 when zIndex is not specified
274     // other browsers return a string
275     // we ignore the case of nested elements with an explicit value of 0
276     // <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
277     value = parseInt( elem.css( "zIndex" ), 10 );
278     if ( !isNaN( value ) && value !== 0 ) {
279     return value;
280     }
281     }
282     elem = elem.parent();
283     }
284     }
285    
286     return 0;
287     }
288     });
289    
290     // $.ui.plugin is deprecated. Use $.widget() extensions instead.
291     $.ui.plugin = {
292     add: function( module, option, set ) {
293     var i,
294     proto = $.ui[ module ].prototype;
295     for ( i in set ) {
296     proto.plugins[ i ] = proto.plugins[ i ] || [];
297     proto.plugins[ i ].push( [ option, set[ i ] ] );
298     }
299     },
300     call: function( instance, name, args, allowDisconnected ) {
301     var i,
302     set = instance.plugins[ name ];
303    
304     if ( !set ) {
305     return;
306     }
307    
308     if ( !allowDisconnected && ( !instance.element[ 0 ].parentNode || instance.element[ 0 ].parentNode.nodeType === 11 ) ) {
309     return;
310     }
311    
312     for ( i = 0; i < set.length; i++ ) {
313     if ( instance.options[ set[ i ][ 0 ] ] ) {
314     set[ i ][ 1 ].apply( instance.element, args );
315     }
316     }
317     }
318     };
319    
320    
321     /*!
322     * jQuery UI Widget 1.11.4
323     * http://jqueryui.com
324     *
325     * Copyright jQuery Foundation and other contributors
326     * Released under the MIT license.
327     * http://jquery.org/license
328     *
329     * http://api.jqueryui.com/jQuery.widget/
330     */
331    
332    
333     var widget_uuid = 0,
334     widget_slice = Array.prototype.slice;
335    
336     $.cleanData = (function( orig ) {
337     return function( elems ) {
338     var events, elem, i;
339     for ( i = 0; (elem = elems[i]) != null; i++ ) {
340     try {
341    
342     // Only trigger remove when necessary to save time
343     events = $._data( elem, "events" );
344     if ( events && events.remove ) {
345     $( elem ).triggerHandler( "remove" );
346     }
347    
348     // http://bugs.jquery.com/ticket/8235
349     } catch ( e ) {}
350     }
351     orig( elems );
352     };
353     })( $.cleanData );
354    
355     $.widget = function( name, base, prototype ) {
356     var fullName, existingConstructor, constructor, basePrototype,
357     // proxiedPrototype allows the provided prototype to remain unmodified
358     // so that it can be used as a mixin for multiple widgets (#8876)
359     proxiedPrototype = {},
360     namespace = name.split( "." )[ 0 ];
361    
362     name = name.split( "." )[ 1 ];
363     fullName = namespace + "-" + name;
364    
365     if ( !prototype ) {
366     prototype = base;
367     base = $.Widget;
368     }
369    
370     // create selector for plugin
371     $.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) {
372     return !!$.data( elem, fullName );
373     };
374    
375     $[ namespace ] = $[ namespace ] || {};
376     existingConstructor = $[ namespace ][ name ];
377     constructor = $[ namespace ][ name ] = function( options, element ) {
378     // allow instantiation without "new" keyword
379     if ( !this._createWidget ) {
380     return new constructor( options, element );
381     }
382    
383     // allow instantiation without initializing for simple inheritance
384     // must use "new" keyword (the code above always passes args)
385     if ( arguments.length ) {
386     this._createWidget( options, element );
387     }
388     };
389     // extend with the existing constructor to carry over any static properties
390     $.extend( constructor, existingConstructor, {
391     version: prototype.version,
392     // copy the object used to create the prototype in case we need to
393     // redefine the widget later
394     _proto: $.extend( {}, prototype ),
395     // track widgets that inherit from this widget in case this widget is
396     // redefined after a widget inherits from it
397     _childConstructors: []
398     });
399    
400     basePrototype = new base();
401     // we need to make the options hash a property directly on the new instance
402     // otherwise we'll modify the options hash on the prototype that we're
403     // inheriting from
404     basePrototype.options = $.widget.extend( {}, basePrototype.options );
405     $.each( prototype, function( prop, value ) {
406     if ( !$.isFunction( value ) ) {
407     proxiedPrototype[ prop ] = value;
408     return;
409     }
410     proxiedPrototype[ prop ] = (function() {
411     var _super = function() {
412     return base.prototype[ prop ].apply( this, arguments );
413     },
414     _superApply = function( args ) {
415     return base.prototype[ prop ].apply( this, args );
416     };
417     return function() {
418     var __super = this._super,
419     __superApply = this._superApply,
420     returnValue;
421    
422     this._super = _super;
423     this._superApply = _superApply;
424    
425     returnValue = value.apply( this, arguments );
426    
427     this._super = __super;
428     this._superApply = __superApply;
429    
430     return returnValue;
431     };
432     })();
433     });
434     constructor.prototype = $.widget.extend( basePrototype, {
435     // TODO: remove support for widgetEventPrefix
436     // always use the name + a colon as the prefix, e.g., draggable:start
437     // don't prefix for widgets that aren't DOM-based
438     widgetEventPrefix: existingConstructor ? (basePrototype.widgetEventPrefix || name) : name
439     }, proxiedPrototype, {
440     constructor: constructor,
441     namespace: namespace,
442     widgetName: name,
443     widgetFullName: fullName
444     });
445    
446     // If this widget is being redefined then we need to find all widgets that
447     // are inheriting from it and redefine all of them so that they inherit from
448     // the new version of this widget. We're essentially trying to replace one
449     // level in the prototype chain.
450     if ( existingConstructor ) {
451     $.each( existingConstructor._childConstructors, function( i, child ) {
452     var childPrototype = child.prototype;
453    
454     // redefine the child widget using the same prototype that was
455     // originally used, but inherit from the new version of the base
456     $.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, child._proto );
457     });
458     // remove the list of existing child constructors from the old constructor
459     // so the old child constructors can be garbage collected
460     delete existingConstructor._childConstructors;
461     } else {
462     base._childConstructors.push( constructor );
463     }
464    
465     $.widget.bridge( name, constructor );
466    
467     return constructor;
468     };
469    
470     $.widget.extend = function( target ) {
471     var input = widget_slice.call( arguments, 1 ),
472     inputIndex = 0,
473     inputLength = input.length,
474     key,
475     value;
476     for ( ; inputIndex < inputLength; inputIndex++ ) {
477     for ( key in input[ inputIndex ] ) {
478     value = input[ inputIndex ][ key ];
479     if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) {
480     // Clone objects
481     if ( $.isPlainObject( value ) ) {
482     target[ key ] = $.isPlainObject( target[ key ] ) ?
483     $.widget.extend( {}, target[ key ], value ) :
484     // Don't extend strings, arrays, etc. with objects
485     $.widget.extend( {}, value );
486     // Copy everything else by reference
487     } else {
488     target[ key ] = value;
489     }
490     }
491     }
492     }
493     return target;
494     };
495    
496     $.widget.bridge = function( name, object ) {
497     var fullName = object.prototype.widgetFullName || name;
498     $.fn[ name ] = function( options ) {
499     var isMethodCall = typeof options === "string",
500     args = widget_slice.call( arguments, 1 ),
501     returnValue = this;
502    
503     if ( isMethodCall ) {
504     this.each(function() {
505     var methodValue,
506     instance = $.data( this, fullName );
507     if ( options === "instance" ) {
508     returnValue = instance;
509     return false;
510     }
511     if ( !instance ) {
512     return $.error( "cannot call methods on " + name + " prior to initialization; " +
513     "attempted to call method '" + options + "'" );
514     }
515     if ( !$.isFunction( instance[options] ) || options.charAt( 0 ) === "_" ) {
516     return $.error( "no such method '" + options + "' for " + name + " widget instance" );
517     }
518     methodValue = instance[ options ].apply( instance, args );
519     if ( methodValue !== instance && methodValue !== undefined ) {
520     returnValue = methodValue && methodValue.jquery ?
521     returnValue.pushStack( methodValue.get() ) :
522     methodValue;
523     return false;
524     }
525     });
526     } else {
527    
528     // Allow multiple hashes to be passed on init
529     if ( args.length ) {
530     options = $.widget.extend.apply( null, [ options ].concat(args) );
531     }
532    
533     this.each(function() {
534     var instance = $.data( this, fullName );
535     if ( instance ) {
536     instance.option( options || {} );
537     if ( instance._init ) {
538     instance._init();
539     }
540     } else {
541     $.data( this, fullName, new object( options, this ) );
542     }
543     });
544     }
545    
546     return returnValue;
547     };
548     };
549    
550     $.Widget = function( /* options, element */ ) {};
551     $.Widget._childConstructors = [];
552    
553     $.Widget.prototype = {
554     widgetName: "widget",
555     widgetEventPrefix: "",
556     defaultElement: "<div>",
557     options: {
558     disabled: false,
559    
560     // callbacks
561     create: null
562     },
563     _createWidget: function( options, element ) {
564     element = $( element || this.defaultElement || this )[ 0 ];
565     this.element = $( element );
566     this.uuid = widget_uuid++;
567     this.eventNamespace = "." + this.widgetName + this.uuid;
568    
569     this.bindings = $();
570     this.hoverable = $();
571     this.focusable = $();
572    
573     if ( element !== this ) {
574     $.data( element, this.widgetFullName, this );
575     this._on( true, this.element, {
576     remove: function( event ) {
577     if ( event.target === element ) {
578     this.destroy();
579     }
580     }
581     });
582     this.document = $( element.style ?
583     // element within the document
584     element.ownerDocument :
585     // element is window or document
586     element.document || element );
587     this.window = $( this.document[0].defaultView || this.document[0].parentWindow );
588     }
589    
590     this.options = $.widget.extend( {},
591     this.options,
592     this._getCreateOptions(),
593     options );
594    
595     this._create();
596     this._trigger( "create", null, this._getCreateEventData() );
597     this._init();
598     },
599     _getCreateOptions: $.noop,
600     _getCreateEventData: $.noop,
601     _create: $.noop,
602     _init: $.noop,
603    
604     destroy: function() {
605     this._destroy();
606     // we can probably remove the unbind calls in 2.0
607     // all event bindings should go through this._on()
608     this.element
609     .unbind( this.eventNamespace )
610     .removeData( this.widgetFullName )
611     // support: jquery <1.6.3
612     // http://bugs.jquery.com/ticket/9413
613     .removeData( $.camelCase( this.widgetFullName ) );
614     this.widget()
615     .unbind( this.eventNamespace )
616     .removeAttr( "aria-disabled" )
617     .removeClass(
618     this.widgetFullName + "-disabled " +
619     "ui-state-disabled" );
620    
621     // clean up events and states
622     this.bindings.unbind( this.eventNamespace );
623     this.hoverable.removeClass( "ui-state-hover" );
624     this.focusable.removeClass( "ui-state-focus" );
625     },
626     _destroy: $.noop,
627    
628     widget: function() {
629     return this.element;
630     },
631    
632     option: function( key, value ) {
633     var options = key,
634     parts,
635     curOption,
636     i;
637    
638     if ( arguments.length === 0 ) {
639     // don't return a reference to the internal hash
640     return $.widget.extend( {}, this.options );
641     }
642    
643     if ( typeof key === "string" ) {
644     // handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
645     options = {};
646     parts = key.split( "." );
647     key = parts.shift();
648     if ( parts.length ) {
649     curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );
650     for ( i = 0; i < parts.length - 1; i++ ) {
651     curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};
652     curOption = curOption[ parts[ i ] ];
653     }
654     key = parts.pop();
655     if ( arguments.length === 1 ) {
656     return curOption[ key ] === undefined ? null : curOption[ key ];
657     }
658     curOption[ key ] = value;
659     } else {
660     if ( arguments.length === 1 ) {
661     return this.options[ key ] === undefined ? null : this.options[ key ];
662     }
663     options[ key ] = value;
664     }
665     }
666    
667     this._setOptions( options );
668    
669     return this;
670     },
671     _setOptions: function( options ) {
672     var key;
673    
674     for ( key in options ) {
675     this._setOption( key, options[ key ] );
676     }
677    
678     return this;
679     },
680     _setOption: function( key, value ) {
681     this.options[ key ] = value;
682    
683     if ( key === "disabled" ) {
684     this.widget()
685     .toggleClass( this.widgetFullName + "-disabled", !!value );
686    
687     // If the widget is becoming disabled, then nothing is interactive
688     if ( value ) {
689     this.hoverable.removeClass( "ui-state-hover" );
690     this.focusable.removeClass( "ui-state-focus" );
691     }
692     }
693    
694     return this;
695     },
696    
697     enable: function() {
698     return this._setOptions({ disabled: false });
699     },
700     disable: function() {
701     return this._setOptions({ disabled: true });
702     },
703    
704     _on: function( suppressDisabledCheck, element, handlers ) {
705     var delegateElement,
706     instance = this;
707    
708     // no suppressDisabledCheck flag, shuffle arguments
709     if ( typeof suppressDisabledCheck !== "boolean" ) {
710     handlers = element;
711     element = suppressDisabledCheck;
712     suppressDisabledCheck = false;
713     }
714    
715     // no element argument, shuffle and use this.element
716     if ( !handlers ) {
717     handlers = element;
718     element = this.element;
719     delegateElement = this.widget();
720     } else {
721     element = delegateElement = $( element );
722     this.bindings = this.bindings.add( element );
723     }
724    
725     $.each( handlers, function( event, handler ) {
726     function handlerProxy() {
727     // allow widgets to customize the disabled handling
728     // - disabled as an array instead of boolean
729     // - disabled class as method for disabling individual parts
730     if ( !suppressDisabledCheck &&
731     ( instance.options.disabled === true ||
732     $( this ).hasClass( "ui-state-disabled" ) ) ) {
733     return;
734     }
735     return ( typeof handler === "string" ? instance[ handler ] : handler )
736     .apply( instance, arguments );
737     }
738    
739     // copy the guid so direct unbinding works
740     if ( typeof handler !== "string" ) {
741     handlerProxy.guid = handler.guid =
742     handler.guid || handlerProxy.guid || $.guid++;
743     }
744    
745     var match = event.match( /^([\w:-]*)\s*(.*)$/ ),
746     eventName = match[1] + instance.eventNamespace,
747     selector = match[2];
748     if ( selector ) {
749     delegateElement.delegate( selector, eventName, handlerProxy );
750     } else {
751     element.bind( eventName, handlerProxy );
752     }
753     });
754     },
755    
756     _off: function( element, eventName ) {
757     eventName = (eventName || "").split( " " ).join( this.eventNamespace + " " ) +
758     this.eventNamespace;
759     element.unbind( eventName ).undelegate( eventName );
760    
761     // Clear the stack to avoid memory leaks (#10056)
762     this.bindings = $( this.bindings.not( element ).get() );
763     this.focusable = $( this.focusable.not( element ).get() );
764     this.hoverable = $( this.hoverable.not( element ).get() );
765     },
766    
767     _delay: function( handler, delay ) {
768     function handlerProxy() {
769     return ( typeof handler === "string" ? instance[ handler ] : handler )
770     .apply( instance, arguments );
771     }
772     var instance = this;
773     return setTimeout( handlerProxy, delay || 0 );
774     },
775    
776     _hoverable: function( element ) {
777     this.hoverable = this.hoverable.add( element );
778     this._on( element, {
779     mouseenter: function( event ) {
780     $( event.currentTarget ).addClass( "ui-state-hover" );
781     },
782     mouseleave: function( event ) {
783     $( event.currentTarget ).removeClass( "ui-state-hover" );
784     }
785     });
786     },
787    
788     _focusable: function( element ) {
789     this.focusable = this.focusable.add( element );
790     this._on( element, {
791     focusin: function( event ) {
792     $( event.currentTarget ).addClass( "ui-state-focus" );
793     },
794     focusout: function( event ) {
795     $( event.currentTarget ).removeClass( "ui-state-focus" );
796     }
797     });
798     },
799    
800     _trigger: function( type, event, data ) {
801     var prop, orig,
802     callback = this.options[ type ];
803    
804     data = data || {};
805     event = $.Event( event );
806     event.type = ( type === this.widgetEventPrefix ?
807     type :
808     this.widgetEventPrefix + type ).toLowerCase();
809     // the original event may come from any element
810     // so we need to reset the target on the new event
811     event.target = this.element[ 0 ];
812    
813     // copy original event properties over to the new event
814     orig = event.originalEvent;
815     if ( orig ) {
816     for ( prop in orig ) {
817     if ( !( prop in event ) ) {
818     event[ prop ] = orig[ prop ];
819     }
820     }
821     }
822    
823     this.element.trigger( event, data );
824     return !( $.isFunction( callback ) &&
825     callback.apply( this.element[0], [ event ].concat( data ) ) === false ||
826     event.isDefaultPrevented() );
827     }
828     };
829    
830     $.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {
831     $.Widget.prototype[ "_" + method ] = function( element, options, callback ) {
832     if ( typeof options === "string" ) {
833     options = { effect: options };
834     }
835     var hasOptions,
836     effectName = !options ?
837     method :
838     options === true || typeof options === "number" ?
839     defaultEffect :
840     options.effect || defaultEffect;
841     options = options || {};
842     if ( typeof options === "number" ) {
843     options = { duration: options };
844     }
845     hasOptions = !$.isEmptyObject( options );
846     options.complete = callback;
847     if ( options.delay ) {
848     element.delay( options.delay );
849     }
850     if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) {
851     element[ method ]( options );
852     } else if ( effectName !== method && element[ effectName ] ) {
853     element[ effectName ]( options.duration, options.easing, callback );
854     } else {
855     element.queue(function( next ) {
856     $( this )[ method ]();
857     if ( callback ) {
858     callback.call( element[ 0 ] );
859     }
860     next();
861     });
862     }
863     };
864     });
865    
866     var widget = $.widget;
867    
868    
869     /*!
870     * jQuery UI Mouse 1.11.4
871     * http://jqueryui.com
872     *
873     * Copyright jQuery Foundation and other contributors
874     * Released under the MIT license.
875     * http://jquery.org/license
876     *
877     * http://api.jqueryui.com/mouse/
878     */
879    
880    
881     var mouseHandled = false;
882     $( document ).mouseup( function() {
883     mouseHandled = false;
884     });
885    
886     var mouse = $.widget("ui.mouse", {
887     version: "1.11.4",
888     options: {
889     cancel: "input,textarea,button,select,option",
890     distance: 1,
891     delay: 0
892     },
893     _mouseInit: function() {
894     var that = this;
895    
896     this.element
897     .bind("mousedown." + this.widgetName, function(event) {
898     return that._mouseDown(event);
899     })
900     .bind("click." + this.widgetName, function(event) {
901     if (true === $.data(event.target, that.widgetName + ".preventClickEvent")) {
902     $.removeData(event.target, that.widgetName + ".preventClickEvent");
903     event.stopImmediatePropagation();
904     return false;
905     }
906     });
907    
908     this.started = false;
909     },
910    
911     // TODO: make sure destroying one instance of mouse doesn't mess with
912     // other instances of mouse
913     _mouseDestroy: function() {
914     this.element.unbind("." + this.widgetName);
915     if ( this._mouseMoveDelegate ) {
916     this.document
917     .unbind("mousemove." + this.widgetName, this._mouseMoveDelegate)
918     .unbind("mouseup." + this.widgetName, this._mouseUpDelegate);
919     }
920     },
921    
922     _mouseDown: function(event) {
923     // don't let more than one widget handle mouseStart
924     if ( mouseHandled ) {
925     return;
926     }
927    
928     this._mouseMoved = false;
929    
930     // we may have missed mouseup (out of window)
931     (this._mouseStarted && this._mouseUp(event));
932    
933     this._mouseDownEvent = event;
934    
935     var that = this,
936     btnIsLeft = (event.which === 1),
937     // event.target.nodeName works around a bug in IE 8 with
938     // disabled inputs (#7620)
939     elIsCancel = (typeof this.options.cancel === "string" && event.target.nodeName ? $(event.target).closest(this.options.cancel).length : false);
940     if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
941     return true;
942     }
943    
944     this.mouseDelayMet = !this.options.delay;
945     if (!this.mouseDelayMet) {
946     this._mouseDelayTimer = setTimeout(function() {
947     that.mouseDelayMet = true;
948     }, this.options.delay);
949     }
950    
951     if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
952     this._mouseStarted = (this._mouseStart(event) !== false);
953     if (!this._mouseStarted) {
954     event.preventDefault();
955     return true;
956     }
957     }
958    
959     // Click event may never have fired (Gecko & Opera)
960     if (true === $.data(event.target, this.widgetName + ".preventClickEvent")) {
961     $.removeData(event.target, this.widgetName + ".preventClickEvent");
962     }
963    
964     // these delegates are required to keep context
965     this._mouseMoveDelegate = function(event) {
966     return that._mouseMove(event);
967     };
968     this._mouseUpDelegate = function(event) {
969     return that._mouseUp(event);
970     };
971    
972     this.document
973     .bind( "mousemove." + this.widgetName, this._mouseMoveDelegate )
974     .bind( "mouseup." + this.widgetName, this._mouseUpDelegate );
975    
976     event.preventDefault();
977    
978     mouseHandled = true;
979     return true;
980     },
981    
982     _mouseMove: function(event) {
983     // Only check for mouseups outside the document if you've moved inside the document
984     // at least once. This prevents the firing of mouseup in the case of IE<9, which will
985     // fire a mousemove event if content is placed under the cursor. See #7778
986     // Support: IE <9
987     if ( this._mouseMoved ) {
988     // IE mouseup check - mouseup happened when mouse was out of window
989     if ($.ui.ie && ( !document.documentMode || document.documentMode < 9 ) && !event.button) {
990     return this._mouseUp(event);
991    
992     // Iframe mouseup check - mouseup occurred in another document
993     } else if ( !event.which ) {
994     return this._mouseUp( event );
995     }
996     }
997    
998     if ( event.which || event.button ) {
999     this._mouseMoved = true;
1000     }
1001    
1002     if (this._mouseStarted) {
1003     this._mouseDrag(event);
1004     return event.preventDefault();
1005     }
1006    
1007     if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
1008     this._mouseStarted =
1009     (this._mouseStart(this._mouseDownEvent, event) !== false);
1010     (this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
1011     }
1012    
1013     return !this._mouseStarted;
1014     },
1015    
1016     _mouseUp: function(event) {
1017     this.document
1018     .unbind( "mousemove." + this.widgetName, this._mouseMoveDelegate )
1019     .unbind( "mouseup." + this.widgetName, this._mouseUpDelegate );
1020    
1021     if (this._mouseStarted) {
1022     this._mouseStarted = false;
1023    
1024     if (event.target === this._mouseDownEvent.target) {
1025     $.data(event.target, this.widgetName + ".preventClickEvent", true);
1026     }
1027    
1028     this._mouseStop(event);
1029     }
1030    
1031     mouseHandled = false;
1032     return false;
1033     },
1034    
1035     _mouseDistanceMet: function(event) {
1036     return (Math.max(
1037     Math.abs(this._mouseDownEvent.pageX - event.pageX),
1038     Math.abs(this._mouseDownEvent.pageY - event.pageY)
1039     ) >= this.options.distance
1040     );
1041     },
1042    
1043     _mouseDelayMet: function(/* event */) {
1044     return this.mouseDelayMet;
1045     },
1046    
1047     // These are placeholder methods, to be overriden by extending plugin
1048     _mouseStart: function(/* event */) {},
1049     _mouseDrag: function(/* event */) {},
1050     _mouseStop: function(/* event */) {},
1051     _mouseCapture: function(/* event */) { return true; }
1052     });
1053    
1054    
1055     /*!
1056     * jQuery UI Position 1.11.4
1057     * http://jqueryui.com
1058     *
1059     * Copyright jQuery Foundation and other contributors
1060     * Released under the MIT license.
1061     * http://jquery.org/license
1062     *
1063     * http://api.jqueryui.com/position/
1064     */
1065    
1066     (function() {
1067    
1068     $.ui = $.ui || {};
1069    
1070     var cachedScrollbarWidth, supportsOffsetFractions,
1071     max = Math.max,
1072     abs = Math.abs,
1073     round = Math.round,
1074     rhorizontal = /left|center|right/,
1075     rvertical = /top|center|bottom/,
1076     roffset = /[\+\-]\d+(\.[\d]+)?%?/,
1077     rposition = /^\w+/,
1078     rpercent = /%$/,
1079     _position = $.fn.position;
1080    
1081     function getOffsets( offsets, width, height ) {
1082     return [
1083     parseFloat( offsets[ 0 ] ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ),
1084     parseFloat( offsets[ 1 ] ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 )
1085     ];
1086     }
1087    
1088     function parseCss( element, property ) {
1089     return parseInt( $.css( element, property ), 10 ) || 0;
1090     }
1091    
1092     function getDimensions( elem ) {
1093     var raw = elem[0];
1094     if ( raw.nodeType === 9 ) {
1095     return {
1096     width: elem.width(),
1097     height: elem.height(),
1098     offset: { top: 0, left: 0 }
1099     };
1100     }
1101     if ( $.isWindow( raw ) ) {
1102     return {
1103     width: elem.width(),
1104     height: elem.height(),
1105     offset: { top: elem.scrollTop(), left: elem.scrollLeft() }
1106     };
1107     }
1108     if ( raw.preventDefault ) {
1109     return {
1110     width: 0,
1111     height: 0,
1112     offset: { top: raw.pageY, left: raw.pageX }
1113     };
1114     }
1115     return {
1116     width: elem.outerWidth(),
1117     height: elem.outerHeight(),
1118     offset: elem.offset()
1119     };
1120     }
1121    
1122     $.position = {
1123     scrollbarWidth: function() {
1124     if ( cachedScrollbarWidth !== undefined ) {
1125     return cachedScrollbarWidth;
1126     }
1127     var w1, w2,
1128     div = $( "<div style='display:block;position:absolute;width:50px;height:50px;overflow:hidden;'><div style='height:100px;width:auto;'></div></div>" ),
1129     innerDiv = div.children()[0];
1130    
1131     $( "body" ).append( div );
1132     w1 = innerDiv.offsetWidth;
1133     div.css( "overflow", "scroll" );
1134    
1135     w2 = innerDiv.offsetWidth;
1136    
1137     if ( w1 === w2 ) {
1138     w2 = div[0].clientWidth;
1139     }
1140    
1141     div.remove();
1142    
1143     return (cachedScrollbarWidth = w1 - w2);
1144     },
1145     getScrollInfo: function( within ) {
1146     var overflowX = within.isWindow || within.isDocument ? "" :
1147     within.element.css( "overflow-x" ),
1148     overflowY = within.isWindow || within.isDocument ? "" :
1149     within.element.css( "overflow-y" ),
1150     hasOverflowX = overflowX === "scroll" ||
1151     ( overflowX === "auto" && within.width < within.element[0].scrollWidth ),
1152     hasOverflowY = overflowY === "scroll" ||
1153     ( overflowY === "auto" && within.height < within.element[0].scrollHeight );
1154     return {
1155     width: hasOverflowY ? $.position.scrollbarWidth() : 0,
1156     height: hasOverflowX ? $.position.scrollbarWidth() : 0
1157     };
1158     },
1159     getWithinInfo: function( element ) {
1160     var withinElement = $( element || window ),
1161     isWindow = $.isWindow( withinElement[0] ),
1162     isDocument = !!withinElement[ 0 ] && withinElement[ 0 ].nodeType === 9;
1163     return {
1164     element: withinElement,
1165     isWindow: isWindow,
1166     isDocument: isDocument,
1167     offset: withinElement.offset() || { left: 0, top: 0 },
1168     scrollLeft: withinElement.scrollLeft(),
1169     scrollTop: withinElement.scrollTop(),
1170    
1171     // support: jQuery 1.6.x
1172     // jQuery 1.6 doesn't support .outerWidth/Height() on documents or windows
1173     width: isWindow || isDocument ? withinElement.width() : withinElement.outerWidth(),
1174     height: isWindow || isDocument ? withinElement.height() : withinElement.outerHeight()
1175     };
1176     }
1177     };
1178    
1179     $.fn.position = function( options ) {
1180     if ( !options || !options.of ) {
1181     return _position.apply( this, arguments );
1182     }
1183    
1184     // make a copy, we don't want to modify arguments
1185     options = $.extend( {}, options );
1186    
1187     var atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions,
1188     target = $( options.of ),
1189     within = $.position.getWithinInfo( options.within ),
1190     scrollInfo = $.position.getScrollInfo( within ),
1191     collision = ( options.collision || "flip" ).split( " " ),
1192     offsets = {};
1193    
1194     dimensions = getDimensions( target );
1195     if ( target[0].preventDefault ) {
1196     // force left top to allow flipping
1197     options.at = "left top";
1198     }
1199     targetWidth = dimensions.width;
1200     targetHeight = dimensions.height;
1201     targetOffset = dimensions.offset;
1202     // clone to reuse original targetOffset later
1203     basePosition = $.extend( {}, targetOffset );
1204    
1205     // force my and at to have valid horizontal and vertical positions
1206     // if a value is missing or invalid, it will be converted to center
1207     $.each( [ "my", "at" ], function() {
1208     var pos = ( options[ this ] || "" ).split( " " ),
1209     horizontalOffset,
1210     verticalOffset;
1211    
1212     if ( pos.length === 1) {
1213     pos = rhorizontal.test( pos[ 0 ] ) ?
1214     pos.concat( [ "center" ] ) :
1215     rvertical.test( pos[ 0 ] ) ?
1216     [ "center" ].concat( pos ) :
1217     [ "center", "center" ];
1218     }
1219     pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center";
1220     pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center";
1221    
1222     // calculate offsets
1223     horizontalOffset = roffset.exec( pos[ 0 ] );
1224     verticalOffset = roffset.exec( pos[ 1 ] );
1225     offsets[ this ] = [
1226     horizontalOffset ? horizontalOffset[ 0 ] : 0,
1227     verticalOffset ? verticalOffset[ 0 ] : 0
1228     ];
1229    
1230     // reduce to just the positions without the offsets
1231     options[ this ] = [
1232     rposition.exec( pos[ 0 ] )[ 0 ],
1233     rposition.exec( pos[ 1 ] )[ 0 ]
1234     ];
1235     });
1236    
1237     // normalize collision option
1238     if ( collision.length === 1 ) {
1239     collision[ 1 ] = collision[ 0 ];
1240     }
1241    
1242     if ( options.at[ 0 ] === "right" ) {
1243     basePosition.left += targetWidth;
1244     } else if ( options.at[ 0 ] === "center" ) {
1245     basePosition.left += targetWidth / 2;
1246     }
1247    
1248     if ( options.at[ 1 ] === "bottom" ) {
1249     basePosition.top += targetHeight;
1250     } else if ( options.at[ 1 ] === "center" ) {
1251     basePosition.top += targetHeight / 2;
1252     }
1253    
1254     atOffset = getOffsets( offsets.at, targetWidth, targetHeight );
1255     basePosition.left += atOffset[ 0 ];
1256     basePosition.top += atOffset[ 1 ];
1257    
1258     return this.each(function() {
1259     var collisionPosition, using,
1260     elem = $( this ),
1261     elemWidth = elem.outerWidth(),
1262     elemHeight = elem.outerHeight(),
1263     marginLeft = parseCss( this, "marginLeft" ),
1264     marginTop = parseCss( this, "marginTop" ),
1265     collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) + scrollInfo.width,
1266     collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) + scrollInfo.height,
1267     position = $.extend( {}, basePosition ),
1268     myOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() );
1269    
1270     if ( options.my[ 0 ] === "right" ) {
1271     position.left -= elemWidth;
1272     } else if ( options.my[ 0 ] === "center" ) {
1273     position.left -= elemWidth / 2;
1274     }
1275    
1276     if ( options.my[ 1 ] === "bottom" ) {
1277     position.top -= elemHeight;
1278     } else if ( options.my[ 1 ] === "center" ) {
1279     position.top -= elemHeight / 2;
1280     }
1281    
1282     position.left += myOffset[ 0 ];
1283     position.top += myOffset[ 1 ];
1284    
1285     // if the browser doesn't support fractions, then round for consistent results
1286     if ( !supportsOffsetFractions ) {
1287     position.left = round( position.left );
1288     position.top = round( position.top );
1289     }
1290    
1291     collisionPosition = {
1292     marginLeft: marginLeft,
1293     marginTop: marginTop
1294     };
1295    
1296     $.each( [ "left", "top" ], function( i, dir ) {
1297     if ( $.ui.position[ collision[ i ] ] ) {
1298     $.ui.position[ collision[ i ] ][ dir ]( position, {
1299     targetWidth: targetWidth,
1300     targetHeight: targetHeight,
1301     elemWidth: elemWidth,
1302     elemHeight: elemHeight,
1303     collisionPosition: collisionPosition,
1304     collisionWidth: collisionWidth,
1305     collisionHeight: collisionHeight,
1306     offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ],
1307     my: options.my,
1308     at: options.at,
1309     within: within,
1310     elem: elem
1311     });
1312     }
1313     });
1314    
1315     if ( options.using ) {
1316     // adds feedback as second argument to using callback, if present
1317     using = function( props ) {
1318     var left = targetOffset.left - position.left,
1319     right = left + targetWidth - elemWidth,
1320     top = targetOffset.top - position.top,
1321     bottom = top + targetHeight - elemHeight,
1322     feedback = {
1323     target: {
1324     element: target,
1325     left: targetOffset.left,
1326     top: targetOffset.top,
1327     width: targetWidth,
1328     height: targetHeight
1329     },
1330     element: {
1331     element: elem,
1332     left: position.left,
1333     top: position.top,
1334     width: elemWidth,
1335     height: elemHeight
1336     },
1337     horizontal: right < 0 ? "left" : left > 0 ? "right" : "center",
1338     vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle"
1339     };
1340     if ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) {
1341     feedback.horizontal = "center";
1342     }
1343     if ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) {
1344     feedback.vertical = "middle";
1345     }
1346     if ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) {
1347     feedback.important = "horizontal";
1348     } else {
1349     feedback.important = "vertical";
1350     }
1351     options.using.call( this, props, feedback );
1352     };
1353     }
1354    
1355     elem.offset( $.extend( position, { using: using } ) );
1356     });
1357     };
1358    
1359     $.ui.position = {
1360     fit: {
1361     left: function( position, data ) {
1362     var within = data.within,
1363     withinOffset = within.isWindow ? within.scrollLeft : within.offset.left,
1364     outerWidth = within.width,
1365     collisionPosLeft = position.left - data.collisionPosition.marginLeft,
1366     overLeft = withinOffset - collisionPosLeft,
1367     overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset,
1368     newOverRight;
1369    
1370     // element is wider than within
1371     if ( data.collisionWidth > outerWidth ) {
1372     // element is initially over the left side of within
1373     if ( overLeft > 0 && overRight <= 0 ) {
1374     newOverRight = position.left + overLeft + data.collisionWidth - outerWidth - withinOffset;
1375     position.left += overLeft - newOverRight;
1376     // element is initially over right side of within
1377     } else if ( overRight > 0 && overLeft <= 0 ) {
1378     position.left = withinOffset;
1379     // element is initially over both left and right sides of within
1380     } else {
1381     if ( overLeft > overRight ) {
1382     position.left = withinOffset + outerWidth - data.collisionWidth;
1383     } else {
1384     position.left = withinOffset;
1385     }
1386     }
1387     // too far left -> align with left edge
1388     } else if ( overLeft > 0 ) {
1389     position.left += overLeft;
1390     // too far right -> align with right edge
1391     } else if ( overRight > 0 ) {
1392     position.left -= overRight;
1393     // adjust based on position and margin
1394     } else {
1395     position.left = max( position.left - collisionPosLeft, position.left );
1396     }
1397     },
1398     top: function( position, data ) {
1399     var within = data.within,
1400     withinOffset = within.isWindow ? within.scrollTop : within.offset.top,
1401     outerHeight = data.within.height,
1402     collisionPosTop = position.top - data.collisionPosition.marginTop,
1403     overTop = withinOffset - collisionPosTop,
1404     overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset,
1405     newOverBottom;
1406    
1407     // element is taller than within
1408     if ( data.collisionHeight > outerHeight ) {
1409     // element is initially over the top of within
1410     if ( overTop > 0 && overBottom <= 0 ) {
1411     newOverBottom = position.top + overTop + data.collisionHeight - outerHeight - withinOffset;
1412     position.top += overTop - newOverBottom;
1413     // element is initially over bottom of within
1414     } else if ( overBottom > 0 && overTop <= 0 ) {
1415     position.top = withinOffset;
1416     // element is initially over both top and bottom of within
1417     } else {
1418     if ( overTop > overBottom ) {
1419     position.top = withinOffset + outerHeight - data.collisionHeight;
1420     } else {
1421     position.top = withinOffset;
1422     }
1423     }
1424     // too far up -> align with top
1425     } else if ( overTop > 0 ) {
1426     position.top += overTop;
1427     // too far down -> align with bottom edge
1428     } else if ( overBottom > 0 ) {
1429     position.top -= overBottom;
1430     // adjust based on position and margin
1431     } else {
1432     position.top = max( position.top - collisionPosTop, position.top );
1433     }
1434     }
1435     },
1436     flip: {
1437     left: function( position, data ) {
1438     var within = data.within,
1439     withinOffset = within.offset.left + within.scrollLeft,
1440     outerWidth = within.width,
1441     offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left,
1442     collisionPosLeft = position.left - data.collisionPosition.marginLeft,
1443     overLeft = collisionPosLeft - offsetLeft,
1444     overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft,
1445     myOffset = data.my[ 0 ] === "left" ?
1446     -data.elemWidth :
1447     data.my[ 0 ] === "right" ?
1448     data.elemWidth :
1449     0,
1450     atOffset = data.at[ 0 ] === "left" ?
1451     data.targetWidth :
1452     data.at[ 0 ] === "right" ?
1453     -data.targetWidth :
1454     0,
1455     offset = -2 * data.offset[ 0 ],
1456     newOverRight,
1457     newOverLeft;
1458    
1459     if ( overLeft < 0 ) {
1460     newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth - outerWidth - withinOffset;
1461     if ( newOverRight < 0 || newOverRight < abs( overLeft ) ) {
1462     position.left += myOffset + atOffset + offset;
1463     }
1464     $(data.elem).addClass('ui-collision-left');
1465     } else if ( overRight > 0 ) {
1466     newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset + atOffset + offset - offsetLeft;
1467     if ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) {
1468     position.left += myOffset + atOffset + offset;
1469     }
1470     $(data.elem).addClass('ui-collision-right');
1471     } else {
1472     $(data.elem).addClass('ui-no-horizontal-collision');
1473     }
1474     },
1475     top: function( position, data ) {
1476     var within = data.within,
1477     withinOffset = within.offset.top + within.scrollTop,
1478     outerHeight = within.height,
1479     offsetTop = within.isWindow ? within.scrollTop : within.offset.top,
1480     collisionPosTop = position.top - data.collisionPosition.marginTop,
1481     overTop = collisionPosTop - offsetTop,
1482     overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop,
1483     top = data.my[ 1 ] === "top",
1484     myOffset = top ?
1485     -data.elemHeight :
1486     data.my[ 1 ] === "bottom" ?
1487     data.elemHeight :
1488     0,
1489     atOffset = data.at[ 1 ] === "top" ?
1490     data.targetHeight :
1491     data.at[ 1 ] === "bottom" ?
1492     -data.targetHeight :
1493     0,
1494     offset = -2 * data.offset[ 1 ],
1495     newOverTop,
1496     newOverBottom;
1497     if ( overTop < 0 ) {
1498     newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight - outerHeight - withinOffset;
1499     if ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) {
1500     position.top += myOffset + atOffset + offset;
1501     }
1502     $(data.elem).addClass('ui-collision-top');
1503     } else if ( overBottom > 0 ) {
1504     newOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset + offset - offsetTop;
1505     if ( newOverTop > 0 || abs( newOverTop ) < overBottom ) {
1506     position.top += myOffset + atOffset + offset;
1507     }
1508     $(data.elem).addClass('ui-collision-bottom');
1509     } else {
1510     $(data.elem).addClass('ui-no-vertical-collision');
1511     }
1512     }
1513     },
1514     flipfit: {
1515     left: function() {
1516     $.ui.position.flip.left.apply( this, arguments );
1517     $.ui.position.fit.left.apply( this, arguments );
1518     },
1519     top: function() {
1520     $.ui.position.flip.top.apply( this, arguments );
1521     $.ui.position.fit.top.apply( this, arguments );
1522     }
1523     }
1524     };
1525    
1526     // fraction support test
1527     (function() {
1528     var testElement, testElementParent, testElementStyle, offsetLeft, i,
1529     body = document.getElementsByTagName( "body" )[ 0 ],
1530     div = document.createElement( "div" );
1531    
1532     //Create a "fake body" for testing based on method used in jQuery.support
1533     testElement = document.createElement( body ? "div" : "body" );
1534     testElementStyle = {
1535     visibility: "hidden",
1536     width: 0,
1537     height: 0,
1538     border: 0,
1539     margin: 0,
1540     background: "none"
1541     };
1542     if ( body ) {
1543     $.extend( testElementStyle, {
1544     position: "absolute",
1545     left: "-1000px",
1546     top: "-1000px"
1547     });
1548     }
1549     for ( i in testElementStyle ) {
1550     testElement.style[ i ] = testElementStyle[ i ];
1551     }
1552     testElement.appendChild( div );
1553     testElementParent = body || document.documentElement;
1554     testElementParent.insertBefore( testElement, testElementParent.firstChild );
1555    
1556     div.style.cssText = "position: absolute; left: 10.7432222px;";
1557    
1558     offsetLeft = $( div ).offset().left;
1559     supportsOffsetFractions = offsetLeft > 10 && offsetLeft < 11;
1560    
1561     testElement.innerHTML = "";
1562     testElementParent.removeChild( testElement );
1563     })();
1564    
1565     })();
1566    
1567     var position = $.ui.position;
1568    
1569    
1570     /*!
1571     * jQuery UI Accordion 1.11.4
1572     * http://jqueryui.com
1573     *
1574     * Copyright jQuery Foundation and other contributors
1575     * Released under the MIT license.
1576     * http://jquery.org/license
1577     *
1578     * http://api.jqueryui.com/accordion/
1579     */
1580    
1581    
1582     var accordion = $.widget( "ui.accordion", {
1583     version: "1.11.4",
1584     options: {
1585     active: 0,
1586     animate: {},
1587     collapsible: false,
1588     event: "click",
1589     header: "> li > :first-child,> :not(li):even",
1590     heightStyle: "auto",
1591     icons: {
1592     activeHeader: "ui-icon-triangle-1-s",
1593     header: "ui-icon-triangle-1-e"
1594     },
1595    
1596     // callbacks
1597     activate: null,
1598     beforeActivate: null
1599     },
1600    
1601     hideProps: {
1602     borderTopWidth: "hide",
1603     borderBottomWidth: "hide",
1604     paddingTop: "hide",
1605     paddingBottom: "hide",
1606     height: "hide"
1607     },
1608    
1609     showProps: {
1610     borderTopWidth: "show",
1611     borderBottomWidth: "show",
1612     paddingTop: "show",
1613     paddingBottom: "show",
1614     height: "show"
1615     },
1616    
1617     _create: function() {
1618     var options = this.options;
1619     this.prevShow = this.prevHide = $();
1620     this.element.addClass( "ui-accordion ui-widget ui-helper-reset" )
1621     // ARIA
1622     .attr( "role", "tablist" );
1623    
1624     // don't allow collapsible: false and active: false / null
1625     if ( !options.collapsible && (options.active === false || options.active == null) ) {
1626     options.active = 0;
1627     }
1628    
1629     this._processPanels();
1630     // handle negative values
1631     if ( options.active < 0 ) {
1632     options.active += this.headers.length;
1633     }
1634     this._refresh();
1635     },
1636    
1637     _getCreateEventData: function() {
1638     return {
1639     header: this.active,
1640     panel: !this.active.length ? $() : this.active.next()
1641     };
1642     },
1643    
1644     _createIcons: function() {
1645     var icons = this.options.icons;
1646     if ( icons ) {
1647     $( "<span>" )
1648     .addClass( "ui-accordion-header-icon ui-icon " + icons.header )
1649     .prependTo( this.headers );
1650     this.active.children( ".ui-accordion-header-icon" )
1651     .removeClass( icons.header )
1652     .addClass( icons.activeHeader );
1653     this.headers.addClass( "ui-accordion-icons" );
1654     }
1655     },
1656    
1657     _destroyIcons: function() {
1658     this.headers
1659     .removeClass( "ui-accordion-icons" )
1660     .children( ".ui-accordion-header-icon" )
1661     .remove();
1662     },
1663    
1664     _destroy: function() {
1665     var contents;
1666    
1667     // clean up main element
1668     this.element
1669     .removeClass( "ui-accordion ui-widget ui-helper-reset" )
1670     .removeAttr( "role" );
1671    
1672     // clean up headers
1673     this.headers
1674     .removeClass( "ui-accordion-header ui-accordion-header-active ui-state-default " +
1675     "ui-corner-all ui-state-active ui-state-disabled ui-corner-top" )
1676     .removeAttr( "role" )
1677     .removeAttr( "aria-expanded" )
1678     .removeAttr( "aria-selected" )
1679     .removeAttr( "aria-controls" )
1680     .removeAttr( "tabIndex" )
1681     .removeUniqueId();
1682    
1683     this._destroyIcons();
1684    
1685     // clean up content panels
1686     contents = this.headers.next()
1687     .removeClass( "ui-helper-reset ui-widget-content ui-corner-bottom " +
1688     "ui-accordion-content ui-accordion-content-active ui-state-disabled" )
1689     .css( "display", "" )
1690     .removeAttr( "role" )
1691     .removeAttr( "aria-hidden" )
1692     .removeAttr( "aria-labelledby" )
1693     .removeUniqueId();
1694    
1695     if ( this.options.heightStyle !== "content" ) {
1696     contents.css( "height", "" );
1697     }
1698     },
1699    
1700     _setOption: function( key, value ) {
1701     if ( key === "active" ) {
1702     // _activate() will handle invalid values and update this.options
1703     this._activate( value );
1704     return;
1705     }
1706    
1707     if ( key === "event" ) {
1708     if ( this.options.event ) {
1709     this._off( this.headers, this.options.event );
1710     }
1711     this._setupEvents( value );
1712     }
1713    
1714     this._super( key, value );
1715    
1716     // setting collapsible: false while collapsed; open first panel
1717     if ( key === "collapsible" && !value && this.options.active === false ) {
1718     this._activate( 0 );
1719     }
1720    
1721     if ( key === "icons" ) {
1722     this._destroyIcons();
1723     if ( value ) {
1724     this._createIcons();
1725     }
1726     }
1727    
1728     // #5332 - opacity doesn't cascade to positioned elements in IE
1729     // so we need to add the disabled class to the headers and panels
1730     if ( key === "disabled" ) {
1731     this.element
1732     .toggleClass( "ui-state-disabled", !!value )
1733     .attr( "aria-disabled", value );
1734     this.headers.add( this.headers.next() )
1735     .toggleClass( "ui-state-disabled", !!value );
1736     }
1737     },
1738    
1739     _keydown: function( event ) {
1740     if ( event.altKey || event.ctrlKey ) {
1741     return;
1742     }
1743    
1744     var keyCode = $.ui.keyCode,
1745     length = this.headers.length,
1746     currentIndex = this.headers.index( event.target ),
1747     toFocus = false;
1748    
1749     switch ( event.keyCode ) {
1750     case keyCode.RIGHT:
1751     case keyCode.DOWN:
1752     toFocus = this.headers[ ( currentIndex + 1 ) % length ];
1753     break;
1754     case keyCode.LEFT:
1755     case keyCode.UP:
1756     toFocus = this.headers[ ( currentIndex - 1 + length ) % length ];
1757     break;
1758     case keyCode.SPACE:
1759     case keyCode.ENTER:
1760     this._eventHandler( event );
1761     break;
1762     case keyCode.HOME:
1763     toFocus = this.headers[ 0 ];
1764     break;
1765     case keyCode.END:
1766     toFocus = this.headers[ length - 1 ];
1767     break;
1768     }
1769    
1770     if ( toFocus ) {
1771     $( event.target ).attr( "tabIndex", -1 );
1772     $( toFocus ).attr( "tabIndex", 0 );
1773     toFocus.focus();
1774     event.preventDefault();
1775     }
1776     },
1777    
1778     _panelKeyDown: function( event ) {
1779     if ( event.keyCode === $.ui.keyCode.UP && event.ctrlKey ) {
1780     $( event.currentTarget ).prev().focus();
1781     }
1782     },
1783    
1784     refresh: function() {
1785     var options = this.options;
1786     this._processPanels();
1787    
1788     // was collapsed or no panel
1789     if ( ( options.active === false && options.collapsible === true ) || !this.headers.length ) {
1790     options.active = false;
1791     this.active = $();
1792     // active false only when collapsible is true
1793     } else if ( options.active === false ) {
1794     this._activate( 0 );
1795     // was active, but active panel is gone
1796     } else if ( this.active.length && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
1797     // all remaining panel are disabled
1798     if ( this.headers.length === this.headers.find(".ui-state-disabled").length ) {
1799     options.active = false;
1800     this.active = $();
1801     // activate previous panel
1802     } else {
1803     this._activate( Math.max( 0, options.active - 1 ) );
1804     }
1805     // was active, active panel still exists
1806     } else {
1807     // make sure active index is correct
1808     options.active = this.headers.index( this.active );
1809     }
1810    
1811     this._destroyIcons();
1812    
1813     this._refresh();
1814     },
1815    
1816     _processPanels: function() {
1817     var prevHeaders = this.headers,
1818     prevPanels = this.panels;
1819    
1820     this.headers = this.element.find( this.options.header )
1821     .addClass( "ui-accordion-header ui-state-default ui-corner-all" );
1822    
1823     this.panels = this.headers.next()
1824     .addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" )
1825     .filter( ":not(.ui-accordion-content-active)" )
1826     .hide();
1827    
1828     // Avoid memory leaks (#10056)
1829     if ( prevPanels ) {
1830     this._off( prevHeaders.not( this.headers ) );
1831     this._off( prevPanels.not( this.panels ) );
1832     }
1833     },
1834    
1835     _refresh: function() {
1836     var maxHeight,
1837     options = this.options,
1838     heightStyle = options.heightStyle,
1839     parent = this.element.parent();
1840    
1841     this.active = this._findActive( options.active )
1842     .addClass( "ui-accordion-header-active ui-state-active ui-corner-top" )
1843     .removeClass( "ui-corner-all" );
1844     this.active.next()
1845     .addClass( "ui-accordion-content-active" )
1846     .show();
1847    
1848     this.headers
1849     .attr( "role", "tab" )
1850     .each(function() {
1851     var header = $( this ),
1852     headerId = header.uniqueId().attr( "id" ),
1853     panel = header.next(),
1854     panelId = panel.uniqueId().attr( "id" );
1855     header.attr( "aria-controls", panelId );
1856     panel.attr( "aria-labelledby", headerId );
1857     })
1858     .next()
1859     .attr( "role", "tabpanel" );
1860    
1861     this.headers
1862     .not( this.active )
1863     .attr({
1864     "aria-selected": "false",
1865     "aria-expanded": "false",
1866     tabIndex: -1
1867     })
1868     .next()
1869     .attr({
1870     "aria-hidden": "true"
1871     })
1872     .hide();
1873    
1874     // make sure at least one header is in the tab order
1875     if ( !this.active.length ) {
1876     this.headers.eq( 0 ).attr( "tabIndex", 0 );
1877     } else {
1878     this.active.attr({
1879     "aria-selected": "true",
1880     "aria-expanded": "true",
1881     tabIndex: 0
1882     })
1883     .next()
1884     .attr({
1885     "aria-hidden": "false"
1886     });
1887     }
1888    
1889     this._createIcons();
1890    
1891     this._setupEvents( options.event );
1892    
1893     if ( heightStyle === "fill" ) {
1894     maxHeight = parent.height();
1895     this.element.siblings( ":visible" ).each(function() {
1896     var elem = $( this ),
1897     position = elem.css( "position" );
1898    
1899     if ( position === "absolute" || position === "fixed" ) {
1900     return;
1901     }
1902     maxHeight -= elem.outerHeight( true );
1903     });
1904    
1905     this.headers.each(function() {
1906     maxHeight -= $( this ).outerHeight( true );
1907     });
1908    
1909     this.headers.next()
1910     .each(function() {
1911     $( this ).height( Math.max( 0, maxHeight -
1912     $( this ).innerHeight() + $( this ).height() ) );
1913     })
1914     .css( "overflow", "auto" );
1915     } else if ( heightStyle === "auto" ) {
1916     maxHeight = 0;
1917     this.headers.next()
1918     .each(function() {
1919     maxHeight = Math.max( maxHeight, $( this ).css( "height", "" ).height() );
1920     })
1921     .height( maxHeight );
1922     }
1923     },
1924    
1925     _activate: function( index ) {
1926     var active = this._findActive( index )[ 0 ];
1927    
1928     // trying to activate the already active panel
1929     if ( active === this.active[ 0 ] ) {
1930     return;
1931     }
1932    
1933     // trying to collapse, simulate a click on the currently active header
1934     active = active || this.active[ 0 ];
1935    
1936     this._eventHandler({
1937     target: active,
1938     currentTarget: active,
1939     preventDefault: $.noop
1940     });
1941     },
1942    
1943     _findActive: function( selector ) {
1944     return typeof selector === "number" ? this.headers.eq( selector ) : $();
1945     },
1946    
1947     _setupEvents: function( event ) {
1948     var events = {
1949     keydown: "_keydown"
1950     };
1951     if ( event ) {
1952     $.each( event.split( " " ), function( index, eventName ) {
1953     events[ eventName ] = "_eventHandler";
1954     });
1955     }
1956    
1957     this._off( this.headers.add( this.headers.next() ) );
1958     this._on( this.headers, events );
1959     this._on( this.headers.next(), { keydown: "_panelKeyDown" });
1960     this._hoverable( this.headers );
1961     this._focusable( this.headers );
1962     },
1963    
1964     _eventHandler: function( event ) {
1965     var options = this.options,
1966     active = this.active,
1967     clicked = $( event.currentTarget ),
1968     clickedIsActive = clicked[ 0 ] === active[ 0 ],
1969     collapsing = clickedIsActive && options.collapsible,
1970     toShow = collapsing ? $() : clicked.next(),
1971     toHide = active.next(),
1972     eventData = {
1973     oldHeader: active,
1974     oldPanel: toHide,
1975     newHeader: collapsing ? $() : clicked,
1976     newPanel: toShow
1977     };
1978    
1979     event.preventDefault();
1980    
1981     if (
1982     // click on active header, but not collapsible
1983     ( clickedIsActive && !options.collapsible ) ||
1984     // allow canceling activation
1985     ( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
1986     return;
1987     }
1988    
1989     options.active = collapsing ? false : this.headers.index( clicked );
1990    
1991     // when the call to ._toggle() comes after the class changes
1992     // it causes a very odd bug in IE 8 (see #6720)
1993     this.active = clickedIsActive ? $() : clicked;
1994     this._toggle( eventData );
1995    
1996     // switch classes
1997     // corner classes on the previously active header stay after the animation
1998     active.removeClass( "ui-accordion-header-active ui-state-active" );
1999     if ( options.icons ) {
2000     active.children( ".ui-accordion-header-icon" )
2001     .removeClass( options.icons.activeHeader )
2002     .addClass( options.icons.header );
2003     }
2004    
2005     if ( !clickedIsActive ) {
2006     clicked
2007     .removeClass( "ui-corner-all" )
2008     .addClass( "ui-accordion-header-active ui-state-active ui-corner-top" );
2009     if ( options.icons ) {
2010     clicked.children( ".ui-accordion-header-icon" )
2011     .removeClass( options.icons.header )
2012     .addClass( options.icons.activeHeader );
2013     }
2014    
2015     clicked
2016     .next()
2017     .addClass( "ui-accordion-content-active" );
2018     }
2019     },
2020    
2021     _toggle: function( data ) {
2022     var toShow = data.newPanel,
2023     toHide = this.prevShow.length ? this.prevShow : data.oldPanel;
2024    
2025     // handle activating a panel during the animation for another activation
2026     this.prevShow.add( this.prevHide ).stop( true, true );
2027     this.prevShow = toShow;
2028     this.prevHide = toHide;
2029    
2030     if ( this.options.animate ) {
2031     this._animate( toShow, toHide, data );
2032     } else {
2033     toHide.hide();
2034     toShow.show();
2035     this._toggleComplete( data );
2036     }
2037    
2038     toHide.attr({
2039     "aria-hidden": "true"
2040     });
2041     toHide.prev().attr({
2042     "aria-selected": "false",
2043     "aria-expanded": "false"
2044     });
2045     // if we're switching panels, remove the old header from the tab order
2046     // if we're opening from collapsed state, remove the previous header from the tab order
2047     // if we're collapsing, then keep the collapsing header in the tab order
2048     if ( toShow.length && toHide.length ) {
2049     toHide.prev().attr({
2050     "tabIndex": -1,
2051     "aria-expanded": "false"
2052     });
2053     } else if ( toShow.length ) {
2054     this.headers.filter(function() {
2055     return parseInt( $( this ).attr( "tabIndex" ), 10 ) === 0;
2056     })
2057     .attr( "tabIndex", -1 );
2058     }
2059    
2060     toShow
2061     .attr( "aria-hidden", "false" )
2062     .prev()
2063     .attr({
2064     "aria-selected": "true",
2065     "aria-expanded": "true",
2066     tabIndex: 0
2067     });
2068     },
2069    
2070     _animate: function( toShow, toHide, data ) {
2071     var total, easing, duration,
2072     that = this,
2073     adjust = 0,
2074     boxSizing = toShow.css( "box-sizing" ),
2075     down = toShow.length &&
2076     ( !toHide.length || ( toShow.index() < toHide.index() ) ),
2077     animate = this.options.animate || {},
2078     options = down && animate.down || animate,
2079     complete = function() {
2080     that._toggleComplete( data );
2081     };
2082    
2083     if ( typeof options === "number" ) {
2084     duration = options;
2085     }
2086     if ( typeof options === "string" ) {
2087     easing = options;
2088     }
2089     // fall back from options to animation in case of partial down settings
2090     easing = easing || options.easing || animate.easing;
2091     duration = duration || options.duration || animate.duration;
2092    
2093     if ( !toHide.length ) {
2094     return toShow.animate( this.showProps, duration, easing, complete );
2095     }
2096     if ( !toShow.length ) {
2097     return toHide.animate( this.hideProps, duration, easing, complete );
2098     }
2099    
2100     total = toShow.show().outerHeight();
2101     toHide.animate( this.hideProps, {
2102     duration: duration,
2103     easing: easing,
2104     step: function( now, fx ) {
2105     fx.now = Math.round( now );
2106     }
2107     });
2108     toShow
2109     .hide()
2110     .animate( this.showProps, {
2111     duration: duration,
2112     easing: easing,
2113     complete: complete,
2114     step: function( now, fx ) {
2115     fx.now = Math.round( now );
2116     if ( fx.prop !== "height" ) {
2117     if ( boxSizing === "content-box" ) {
2118     adjust += fx.now;
2119     }
2120     } else if ( that.options.heightStyle !== "content" ) {
2121     fx.now = Math.round( total - toHide.outerHeight() - adjust );
2122     adjust = 0;
2123     }
2124     }
2125     });
2126     },
2127    
2128     _toggleComplete: function( data ) {
2129     var toHide = data.oldPanel;
2130    
2131     toHide
2132     .removeClass( "ui-accordion-content-active" )
2133     .prev()
2134     .removeClass( "ui-corner-top" )
2135     .addClass( "ui-corner-all" );
2136    
2137     // Work around for rendering bug in IE (#5421)
2138     if ( toHide.length ) {
2139     toHide.parent()[ 0 ].className = toHide.parent()[ 0 ].className;
2140     }
2141     this._trigger( "activate", null, data );
2142     }
2143     });
2144    
2145    
2146     /*!
2147     * jQuery UI Menu 1.11.4
2148     * http://jqueryui.com
2149     *
2150     * Copyright jQuery Foundation and other contributors
2151     * Released under the MIT license.
2152     * http://jquery.org/license
2153     *
2154     * http://api.jqueryui.com/menu/
2155     */
2156    
2157    
2158     var menu = $.widget( "ui.menu", {
2159     version: "1.11.4",
2160     defaultElement: "<ul>",
2161     delay: 300,
2162     options: {
2163     icons: {
2164     submenu: "ui-icon-carat-1-e"
2165     },
2166     items: "> *",
2167     menus: "ul",
2168     position: {
2169     my: "left-1 top",
2170     at: "right top"
2171     },
2172     role: "menu",
2173    
2174     // callbacks
2175     blur: null,
2176     focus: null,
2177     select: null
2178     },
2179    
2180     _create: function() {
2181     this.activeMenu = this.element;
2182    
2183     // Flag used to prevent firing of the click handler
2184     // as the event bubbles up through nested menus
2185     this.mouseHandled = false;
2186     this.element
2187     .uniqueId()
2188     .addClass( "ui-menu ui-widget ui-widget-content" )
2189     .toggleClass( "ui-menu-icons", !!this.element.find( ".ui-icon" ).length )
2190     .attr({
2191     role: this.options.role,
2192     tabIndex: 0
2193     });
2194    
2195     if ( this.options.disabled ) {
2196     this.element
2197     .addClass( "ui-state-disabled" )
2198     .attr( "aria-disabled", "true" );
2199     }
2200    
2201     this._on({
2202     // Prevent focus from sticking to links inside menu after clicking
2203     // them (focus should always stay on UL during navigation).
2204     "mousedown .ui-menu-item": function( event ) {
2205     event.preventDefault();
2206     },
2207     "click .ui-menu-item": function( event ) {
2208     var target = $( event.target );
2209     if ( !this.mouseHandled && target.not( ".ui-state-disabled" ).length ) {
2210     this.select( event );
2211    
2212     // Only set the mouseHandled flag if the event will bubble, see #9469.
2213     if ( !event.isPropagationStopped() ) {
2214     this.mouseHandled = true;
2215     }
2216    
2217     // Open submenu on click
2218     if ( target.has( ".ui-menu" ).length ) {
2219     this.expand( event );
2220     } else if ( !this.element.is( ":focus" ) && $( this.document[ 0 ].activeElement ).closest( ".ui-menu" ).length ) {
2221    
2222     // Redirect focus to the menu
2223     this.element.trigger( "focus", [ true ] );
2224    
2225     // If the active item is on the top level, let it stay active.
2226     // Otherwise, blur the active item since it is no longer visible.
2227     if ( this.active && this.active.parents( ".ui-menu" ).length === 1 ) {
2228     clearTimeout( this.timer );
2229     }
2230     }
2231     }
2232     },
2233     "mouseenter .ui-menu-item": function( event ) {
2234     // Ignore mouse events while typeahead is active, see #10458.
2235     // Prevents focusing the wrong item when typeahead causes a scroll while the mouse
2236     // is over an item in the menu
2237     if ( this.previousFilter ) {
2238     return;
2239     }
2240     var target = $( event.currentTarget );
2241     // Remove ui-state-active class from siblings of the newly focused menu item
2242     // to avoid a jump caused by adjacent elements both having a class with a border
2243     target.siblings( ".ui-state-active" ).removeClass( "ui-state-active" );
2244     this.focus( event, target );
2245     },
2246     mouseleave: "collapseAll",
2247     "mouseleave .ui-menu": "collapseAll",
2248     focus: function( event, keepActiveItem ) {
2249     // If there's already an active item, keep it active
2250     // If not, activate the first item
2251     var item = this.active || this.element.find( this.options.items ).eq( 0 );
2252    
2253     if ( !keepActiveItem ) {
2254     this.focus( event, item );
2255     }
2256     },
2257     blur: function( event ) {
2258     this._delay(function() {
2259     if ( !$.contains( this.element[0], this.document[0].activeElement ) ) {
2260     this.collapseAll( event );
2261     }
2262     });
2263     },
2264     keydown: "_keydown"
2265     });
2266    
2267     this.refresh();
2268    
2269     // Clicks outside of a menu collapse any open menus
2270     this._on( this.document, {
2271     click: function( event ) {
2272     if ( this._closeOnDocumentClick( event ) ) {
2273     this.collapseAll( event );
2274     }
2275    
2276     // Reset the mouseHandled flag
2277     this.mouseHandled = false;
2278     }
2279     });
2280     },
2281    
2282     _destroy: function() {
2283     // Destroy (sub)menus
2284     this.element
2285     .removeAttr( "aria-activedescendant" )
2286     .find( ".ui-menu" ).addBack()
2287     .removeClass( "ui-menu ui-widget ui-widget-content ui-menu-icons ui-front" )
2288     .removeAttr( "role" )
2289     .removeAttr( "tabIndex" )
2290     .removeAttr( "aria-labelledby" )
2291     .removeAttr( "aria-expanded" )
2292     .removeAttr( "aria-hidden" )
2293     .removeAttr( "aria-disabled" )
2294     .removeUniqueId()
2295     .show();
2296    
2297     // Destroy menu items
2298     this.element.find( ".ui-menu-item" )
2299     .removeClass( "ui-menu-item" )
2300     .removeAttr( "role" )
2301     .removeAttr( "aria-disabled" )
2302     .removeUniqueId()
2303     .removeClass( "ui-state-hover" )
2304     .removeAttr( "tabIndex" )
2305     .removeAttr( "role" )
2306     .removeAttr( "aria-haspopup" )
2307     .children().each( function() {
2308     var elem = $( this );
2309     if ( elem.data( "ui-menu-submenu-carat" ) ) {
2310     elem.remove();
2311     }
2312     });
2313    
2314     // Destroy menu dividers
2315     this.element.find( ".ui-menu-divider" ).removeClass( "ui-menu-divider ui-widget-content" );
2316     },
2317    
2318     _keydown: function( event ) {
2319     var match, prev, character, skip,
2320     preventDefault = true;
2321    
2322     switch ( event.keyCode ) {
2323     case $.ui.keyCode.PAGE_UP:
2324     this.previousPage( event );
2325     break;
2326     case $.ui.keyCode.PAGE_DOWN:
2327     this.nextPage( event );
2328     break;
2329     case $.ui.keyCode.HOME:
2330     this._move( "first", "first", event );
2331     break;
2332     case $.ui.keyCode.END:
2333     this._move( "last", "last", event );
2334     break;
2335     case $.ui.keyCode.UP:
2336     this.previous( event );
2337     break;
2338     case $.ui.keyCode.DOWN:
2339     this.next( event );
2340     break;
2341     case $.ui.keyCode.LEFT:
2342     this.collapse( event );
2343     break;
2344     case $.ui.keyCode.RIGHT:
2345     if ( this.active && !this.active.is( ".ui-state-disabled" ) ) {
2346     this.expand( event );
2347     }
2348     break;
2349     case $.ui.keyCode.ENTER:
2350     case $.ui.keyCode.SPACE:
2351     this._activate( event );
2352     break;
2353     case $.ui.keyCode.ESCAPE:
2354     this.collapse( event );
2355     break;
2356     default:
2357     preventDefault = false;
2358     prev = this.previousFilter || "";
2359     character = String.fromCharCode( event.keyCode );
2360     skip = false;
2361    
2362     clearTimeout( this.filterTimer );
2363    
2364     if ( character === prev ) {
2365     skip = true;
2366     } else {
2367     character = prev + character;
2368     }
2369    
2370     match = this._filterMenuItems( character );
2371     match = skip && match.index( this.active.next() ) !== -1 ?
2372     this.active.nextAll( ".ui-menu-item" ) :
2373     match;
2374    
2375     // If no matches on the current filter, reset to the last character pressed
2376     // to move down the menu to the first item that starts with that character
2377     if ( !match.length ) {
2378     character = String.fromCharCode( event.keyCode );
2379     match = this._filterMenuItems( character );
2380     }
2381    
2382     if ( match.length ) {
2383     this.focus( event, match );
2384     this.previousFilter = character;
2385     this.filterTimer = this._delay(function() {
2386     delete this.previousFilter;
2387     }, 1000 );
2388     } else {
2389     delete this.previousFilter;
2390     }
2391     }
2392    
2393     if ( preventDefault ) {
2394     event.preventDefault();
2395     }
2396     },
2397    
2398     _activate: function( event ) {
2399     if ( !this.active.is( ".ui-state-disabled" ) ) {
2400     if ( this.active.is( "[aria-haspopup='true']" ) ) {
2401     this.expand( event );
2402     } else {
2403     this.select( event );
2404     }
2405     }
2406     },
2407    
2408     refresh: function() {
2409     var menus, items,
2410     that = this,
2411     icon = this.options.icons.submenu,
2412     submenus = this.element.find( this.options.menus );
2413    
2414     this.element.toggleClass( "ui-menu-icons", !!this.element.find( ".ui-icon" ).length );
2415    
2416     // Initialize nested menus
2417     submenus.filter( ":not(.ui-menu)" )
2418     .addClass( "ui-menu ui-widget ui-widget-content ui-front" )
2419     .hide()
2420     .attr({
2421     role: this.options.role,
2422     "aria-hidden": "true",
2423     "aria-expanded": "false"
2424     })
2425     .each(function() {
2426     var menu = $( this ),
2427     item = menu.parent(),
2428     submenuCarat = $( "<span>" )
2429     .addClass( "ui-menu-icon ui-icon " + icon )
2430     .data( "ui-menu-submenu-carat", true );
2431    
2432     item
2433     .attr( "aria-haspopup", "true" )
2434     .prepend( submenuCarat );
2435     menu.attr( "aria-labelledby", item.attr( "id" ) );
2436     });
2437    
2438     menus = submenus.add( this.element );
2439     items = menus.find( this.options.items );
2440    
2441     // Initialize menu-items containing spaces and/or dashes only as dividers
2442     items.not( ".ui-menu-item" ).each(function() {
2443     var item = $( this );
2444     if ( that._isDivider( item ) ) {
2445     item.addClass( "ui-widget-content ui-menu-divider" );
2446     }
2447     });
2448    
2449     // Don't refresh list items that are already adapted
2450     items.not( ".ui-menu-item, .ui-menu-divider" )
2451     .addClass( "ui-menu-item" )
2452     .uniqueId()
2453     .attr({
2454     tabIndex: -1,
2455     role: this._itemRole()
2456     });
2457    
2458     // Add aria-disabled attribute to any disabled menu item
2459     items.filter( ".ui-state-disabled" ).attr( "aria-disabled", "true" );
2460    
2461     // If the active item has been removed, blur the menu
2462     if ( this.active && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
2463     this.blur();
2464     }
2465     },
2466    
2467     _itemRole: function() {
2468     return {
2469     menu: "menuitem",
2470     listbox: "option"
2471     }[ this.options.role ];
2472     },
2473    
2474     _setOption: function( key, value ) {
2475     if ( key === "icons" ) {
2476     this.element.find( ".ui-menu-icon" )
2477     .removeClass( this.options.icons.submenu )
2478     .addClass( value.submenu );
2479     }
2480     if ( key === "disabled" ) {
2481     this.element
2482     .toggleClass( "ui-state-disabled", !!value )
2483     .attr( "aria-disabled", value );
2484     }
2485     this._super( key, value );
2486     },
2487    
2488     focus: function( event, item ) {
2489     var nested, focused;
2490     this.blur( event, event && event.type === "focus" );
2491    
2492     this._scrollIntoView( item );
2493    
2494     this.active = item.first();
2495     focused = this.active.addClass( "ui-state-focus" ).removeClass( "ui-state-active" );
2496     // Only update aria-activedescendant if there's a role
2497     // otherwise we assume focus is managed elsewhere
2498     if ( this.options.role ) {
2499     this.element.attr( "aria-activedescendant", focused.attr( "id" ) );
2500     }
2501    
2502     // Highlight active parent menu item, if any
2503     this.active
2504     .parent()
2505     .closest( ".ui-menu-item" )
2506     .addClass( "ui-state-active" );
2507    
2508     if ( event && event.type === "keydown" ) {
2509     this._close();
2510     } else {
2511     this.timer = this._delay(function() {
2512     this._close();
2513     }, this.delay );
2514     }
2515    
2516     nested = item.children( ".ui-menu" );
2517     if ( nested.length && event && ( /^mouse/.test( event.type ) ) ) {
2518     this._startOpening(nested);
2519     }
2520     this.activeMenu = item.parent();
2521    
2522     this._trigger( "focus", event, { item: item } );
2523     },
2524    
2525     _scrollIntoView: function( item ) {
2526     var borderTop, paddingTop, offset, scroll, elementHeight, itemHeight;
2527     if ( this._hasScroll() ) {
2528     borderTop = parseFloat( $.css( this.activeMenu[0], "borderTopWidth" ) ) || 0;
2529     paddingTop = parseFloat( $.css( this.activeMenu[0], "paddingTop" ) ) || 0;
2530     offset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop;
2531     scroll = this.activeMenu.scrollTop();
2532     elementHeight = this.activeMenu.height();
2533     itemHeight = item.outerHeight();
2534    
2535     if ( offset < 0 ) {
2536     this.activeMenu.scrollTop( scroll + offset );
2537     } else if ( offset + itemHeight > elementHeight ) {
2538     this.activeMenu.scrollTop( scroll + offset - elementHeight + itemHeight );
2539     }
2540     }
2541     },
2542    
2543     blur: function( event, fromFocus ) {
2544     if ( !fromFocus ) {
2545     clearTimeout( this.timer );
2546     }
2547    
2548     if ( !this.active ) {
2549     return;
2550     }
2551    
2552     this.active.removeClass( "ui-state-focus" );
2553     this.active = null;
2554    
2555     this._trigger( "blur", event, { item: this.active } );
2556     },
2557    
2558     _startOpening: function( submenu ) {
2559     clearTimeout( this.timer );
2560    
2561     // Don't open if already open fixes a Firefox bug that caused a .5 pixel
2562     // shift in the submenu position when mousing over the carat icon
2563     if ( submenu.attr( "aria-hidden" ) !== "true" ) {
2564     return;
2565     }
2566    
2567     this.timer = this._delay(function() {
2568     this._close();
2569     this._open( submenu );
2570     }, this.delay );
2571     },
2572    
2573     _open: function( submenu ) {
2574     var position = $.extend({
2575     of: this.active
2576     }, this.options.position );
2577    
2578     clearTimeout( this.timer );
2579     this.element.find( ".ui-menu" ).not( submenu.parents( ".ui-menu" ) )
2580     .hide()
2581     .attr( "aria-hidden", "true" );
2582    
2583     submenu
2584     .show()
2585     .removeAttr( "aria-hidden" )
2586     .attr( "aria-expanded", "true" )
2587     .position( position );
2588     },
2589    
2590     collapseAll: function( event, all ) {
2591     clearTimeout( this.timer );
2592     this.timer = this._delay(function() {
2593     // If we were passed an event, look for the submenu that contains the event
2594     var currentMenu = all ? this.element :
2595     $( event && event.target ).closest( this.element.find( ".ui-menu" ) );
2596    
2597     // If we found no valid submenu ancestor, use the main menu to close all sub menus anyway
2598     if ( !currentMenu.length ) {
2599     currentMenu = this.element;
2600     }
2601    
2602     this._close( currentMenu );
2603    
2604     this.blur( event );
2605     this.activeMenu = currentMenu;
2606     }, this.delay );
2607     },
2608    
2609     // With no arguments, closes the currently active menu - if nothing is active
2610     // it closes all menus. If passed an argument, it will search for menus BELOW
2611     _close: function( startMenu ) {
2612     if ( !startMenu ) {
2613     startMenu = this.active ? this.active.parent() : this.element;
2614     }
2615    
2616     startMenu
2617     .find( ".ui-menu" )
2618     .hide()
2619     .attr( "aria-hidden", "true" )
2620     .attr( "aria-expanded", "false" )
2621     .end()
2622     .find( ".ui-state-active" ).not( ".ui-state-focus" )
2623     .removeClass( "ui-state-active" );
2624     },
2625    
2626     _closeOnDocumentClick: function( event ) {
2627     return !$( event.target ).closest( ".ui-menu" ).length;
2628     },
2629    
2630     _isDivider: function( item ) {
2631    
2632     // Match hyphen, em dash, en dash
2633     return !/[^\-\u2014\u2013\s]/.test( item.text() );
2634     },
2635    
2636     collapse: function( event ) {
2637     var newItem = this.active &&
2638     this.active.parent().closest( ".ui-menu-item", this.element );
2639     if ( newItem && newItem.length ) {
2640     this._close();
2641     this.focus( event, newItem );
2642     }
2643     },
2644    
2645     expand: function( event ) {
2646     var newItem = this.active &&
2647     this.active
2648     .children( ".ui-menu " )
2649     .find( this.options.items )
2650     .first();
2651    
2652     if ( newItem && newItem.length ) {
2653     this._open( newItem.parent() );
2654    
2655     // Delay so Firefox will not hide activedescendant change in expanding submenu from AT
2656     this._delay(function() {
2657     this.focus( event, newItem );
2658     });
2659     }
2660     },
2661    
2662     next: function( event ) {
2663     this._move( "next", "first", event );
2664     },
2665    
2666     previous: function( event ) {
2667     this._move( "prev", "last", event );
2668     },
2669    
2670     isFirstItem: function() {
2671     return this.active && !this.active.prevAll( ".ui-menu-item" ).length;
2672     },
2673    
2674     isLastItem: function() {
2675     return this.active && !this.active.nextAll( ".ui-menu-item" ).length;
2676     },
2677    
2678     _move: function( direction, filter, event ) {
2679     var next;
2680     if ( this.active ) {
2681     if ( direction === "first" || direction === "last" ) {
2682     next = this.active
2683     [ direction === "first" ? "prevAll" : "nextAll" ]( ".ui-menu-item" )
2684     .eq( -1 );
2685     } else {
2686     next = this.active
2687     [ direction + "All" ]( ".ui-menu-item" )
2688     .eq( 0 );
2689     }
2690     }
2691     if ( !next || !next.length || !this.active ) {
2692     next = this.activeMenu.find( this.options.items )[ filter ]();
2693     }
2694    
2695     this.focus( event, next );
2696     },
2697    
2698     nextPage: function( event ) {
2699     var item, base, height;
2700    
2701     if ( !this.active ) {
2702     this.next( event );
2703     return;
2704     }
2705     if ( this.isLastItem() ) {
2706     return;
2707     }
2708     if ( this._hasScroll() ) {
2709     base = this.active.offset().top;
2710     height = this.element.height();
2711     this.active.nextAll( ".ui-menu-item" ).each(function() {
2712     item = $( this );
2713     return item.offset().top - base - height < 0;
2714     });
2715    
2716     this.focus( event, item );
2717     } else {
2718     this.focus( event, this.activeMenu.find( this.options.items )
2719     [ !this.active ? "first" : "last" ]() );
2720     }
2721     },
2722    
2723     previousPage: function( event ) {
2724     var item, base, height;
2725     if ( !this.active ) {
2726     this.next( event );
2727     return;
2728     }
2729     if ( this.isFirstItem() ) {
2730     return;
2731     }
2732     if ( this._hasScroll() ) {
2733     base = this.active.offset().top;
2734     height = this.element.height();
2735     this.active.prevAll( ".ui-menu-item" ).each(function() {
2736     item = $( this );
2737     return item.offset().top - base + height > 0;
2738     });
2739    
2740     this.focus( event, item );
2741     } else {
2742     this.focus( event, this.activeMenu.find( this.options.items ).first() );
2743     }
2744     },
2745    
2746     _hasScroll: function() {
2747     return this.element.outerHeight() < this.element.prop( "scrollHeight" );
2748     },
2749    
2750     select: function( event ) {
2751     // TODO: It should never be possible to not have an active item at this
2752     // point, but the tests don't trigger mouseenter before click.
2753     this.active = this.active || $( event.target ).closest( ".ui-menu-item" );
2754     var ui = { item: this.active };
2755     if ( !this.active.has( ".ui-menu" ).length ) {
2756     this.collapseAll( event, true );
2757     }
2758     this._trigger( "select", event, ui );
2759     },
2760    
2761     _filterMenuItems: function(character) {
2762     var escapedCharacter = character.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" ),
2763     regex = new RegExp( "^" + escapedCharacter, "i" );
2764    
2765     return this.activeMenu
2766     .find( this.options.items )
2767    
2768     // Only match on items, not dividers or other content (#10571)
2769     .filter( ".ui-menu-item" )
2770     .filter(function() {
2771     return regex.test( $.trim( $( this ).text() ) );
2772     });
2773     }
2774     });
2775    
2776    
2777     /*!
2778     * jQuery UI Autocomplete 1.11.4
2779     * http://jqueryui.com
2780     *
2781     * Copyright jQuery Foundation and other contributors
2782     * Released under the MIT license.
2783     * http://jquery.org/license
2784     *
2785     * http://api.jqueryui.com/autocomplete/
2786     */
2787    
2788    
2789     $.widget( "ui.autocomplete", {
2790     version: "1.11.4",
2791     defaultElement: "<input>",
2792     options: {
2793     appendTo: null,
2794     autoFocus: false,
2795     delay: 300,
2796     minLength: 1,
2797     position: {
2798     my: "left top",
2799     at: "left bottom",
2800     collision: "none"
2801     },
2802     source: null,
2803    
2804     // callbacks
2805     change: null,
2806     close: null,
2807     focus: null,
2808     open: null,
2809     response: null,
2810     search: null,
2811     select: null
2812     },
2813    
2814     requestIndex: 0,
2815     pending: 0,
2816    
2817     _create: function() {
2818     // Some browsers only repeat keydown events, not keypress events,
2819     // so we use the suppressKeyPress flag to determine if we've already
2820     // handled the keydown event. #7269
2821     // Unfortunately the code for & in keypress is the same as the up arrow,
2822     // so we use the suppressKeyPressRepeat flag to avoid handling keypress
2823     // events when we know the keydown event was used to modify the
2824     // search term. #7799
2825     var suppressKeyPress, suppressKeyPressRepeat, suppressInput,
2826     nodeName = this.element[ 0 ].nodeName.toLowerCase(),
2827     isTextarea = nodeName === "textarea",
2828     isInput = nodeName === "input";
2829    
2830     this.isMultiLine =
2831     // Textareas are always multi-line
2832     isTextarea ? true :
2833     // Inputs are always single-line, even if inside a contentEditable element
2834     // IE also treats inputs as contentEditable
2835     isInput ? false :
2836     // All other element types are determined by whether or not they're contentEditable
2837     this.element.prop( "isContentEditable" );
2838    
2839     this.valueMethod = this.element[ isTextarea || isInput ? "val" : "text" ];
2840     this.isNewMenu = true;
2841    
2842     this.element
2843     .addClass( "ui-autocomplete-input" )
2844     .attr( "autocomplete", "off" );
2845    
2846     this._on( this.element, {
2847     keydown: function( event ) {
2848     if ( this.element.prop( "readOnly" ) ) {
2849     suppressKeyPress = true;
2850     suppressInput = true;
2851     suppressKeyPressRepeat = true;
2852     return;
2853     }
2854    
2855     suppressKeyPress = false;
2856     suppressInput = false;
2857     suppressKeyPressRepeat = false;
2858     var keyCode = $.ui.keyCode;
2859     switch ( event.keyCode ) {
2860     case keyCode.PAGE_UP:
2861     suppressKeyPress = true;
2862     this._move( "previousPage", event );
2863     break;
2864     case keyCode.PAGE_DOWN:
2865     suppressKeyPress = true;
2866     this._move( "nextPage", event );
2867     break;
2868     case keyCode.UP:
2869     suppressKeyPress = true;
2870     this._keyEvent( "previous", event );
2871     break;
2872     case keyCode.DOWN:
2873     suppressKeyPress = true;
2874     this._keyEvent( "next", event );
2875     break;
2876     case keyCode.ENTER:
2877     // when menu is open and has focus
2878     if ( this.menu.active ) {
2879     // #6055 - Opera still allows the keypress to occur
2880     // which causes forms to submit
2881     suppressKeyPress = true;
2882     event.preventDefault();
2883     this.menu.select( event );
2884     }
2885     break;
2886     case keyCode.TAB:
2887     if ( this.menu.active ) {
2888     this.menu.select( event );
2889     }
2890     break;
2891     case keyCode.ESCAPE:
2892     if ( this.menu.element.is( ":visible" ) ) {
2893     if ( !this.isMultiLine ) {
2894     this._value( this.term );
2895     }
2896     this.close( event );
2897     // Different browsers have different default behavior for escape
2898     // Single press can mean undo or clear
2899     // Double press in IE means clear the whole form
2900     event.preventDefault();
2901     }
2902     break;
2903     default:
2904     suppressKeyPressRepeat = true;
2905     // search timeout should be triggered before the input value is changed
2906     this._searchTimeout( event );
2907     break;
2908     }
2909     },
2910     keypress: function( event ) {
2911     if ( suppressKeyPress ) {
2912     suppressKeyPress = false;
2913     if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
2914     event.preventDefault();
2915     }
2916     return;
2917     }
2918     if ( suppressKeyPressRepeat ) {
2919     return;
2920     }
2921    
2922     // replicate some key handlers to allow them to repeat in Firefox and Opera
2923     var keyCode = $.ui.keyCode;
2924     switch ( event.keyCode ) {
2925     case keyCode.PAGE_UP:
2926     this._move( "previousPage", event );
2927     break;
2928     case keyCode.PAGE_DOWN:
2929     this._move( "nextPage", event );
2930     break;
2931     case keyCode.UP:
2932     this._keyEvent( "previous", event );
2933     break;
2934     case keyCode.DOWN:
2935     this._keyEvent( "next", event );
2936     break;
2937     }
2938     },
2939     input: function( event ) {
2940     if ( suppressInput ) {
2941     suppressInput = false;
2942     event.preventDefault();
2943     return;
2944     }
2945     this._searchTimeout( event );
2946     },
2947     focus: function() {
2948     this.selectedItem = null;
2949     this.previous = this._value();
2950     },
2951     blur: function( event ) {
2952     if ( this.cancelBlur ) {
2953     delete this.cancelBlur;
2954     return;
2955     }
2956    
2957     clearTimeout( this.searching );
2958     this.close( event );
2959     this._change( event );
2960     }
2961     });
2962    
2963     this._initSource();
2964     this.menu = $( "<ul>" )
2965     .addClass( "ui-autocomplete ui-front" )
2966     .appendTo( this._appendTo() )
2967     .menu({
2968     // disable ARIA support, the live region takes care of that
2969     role: null
2970     })
2971     .hide()
2972     .menu( "instance" );
2973    
2974     this._on( this.menu.element, {
2975     mousedown: function( event ) {
2976     // prevent moving focus out of the text field
2977     event.preventDefault();
2978    
2979     // IE doesn't prevent moving focus even with event.preventDefault()
2980     // so we set a flag to know when we should ignore the blur event
2981     this.cancelBlur = true;
2982     this._delay(function() {
2983     delete this.cancelBlur;
2984     });
2985    
2986     // clicking on the scrollbar causes focus to shift to the body
2987     // but we can't detect a mouseup or a click immediately afterward
2988     // so we have to track the next mousedown and close the menu if
2989     // the user clicks somewhere outside of the autocomplete
2990     var menuElement = this.menu.element[ 0 ];
2991     if ( !$( event.target ).closest( ".ui-menu-item" ).length ) {
2992     this._delay(function() {
2993     var that = this;
2994     this.document.one( "mousedown", function( event ) {
2995     if ( event.target !== that.element[ 0 ] &&
2996     event.target !== menuElement &&
2997     !$.contains( menuElement, event.target ) ) {
2998     that.close();
2999     }
3000     });
3001     });
3002     }
3003     },
3004     menufocus: function( event, ui ) {
3005     var label, item;
3006     // support: Firefox
3007     // Prevent accidental activation of menu items in Firefox (#7024 #9118)
3008     if ( this.isNewMenu ) {
3009     this.isNewMenu = false;
3010     if ( event.originalEvent && /^mouse/.test( event.originalEvent.type ) ) {
3011     this.menu.blur();
3012    
3013     this.document.one( "mousemove", function() {
3014     $( event.target ).trigger( event.originalEvent );
3015     });
3016    
3017     return;
3018     }
3019     }
3020    
3021     item = ui.item.data( "ui-autocomplete-item" );
3022     if ( false !== this._trigger( "focus", event, { item: item } ) ) {
3023     // use value to match what will end up in the input, if it was a key event
3024     if ( event.originalEvent && /^key/.test( event.originalEvent.type ) ) {
3025     this._value( item.value );
3026     }
3027     }
3028    
3029     // Announce the value in the liveRegion
3030     label = ui.item.attr( "aria-label" ) || item.value;
3031     if ( label && $.trim( label ).length ) {
3032     this.liveRegion.children().hide();
3033     $( "<div>" ).text( label ).appendTo( this.liveRegion );
3034     }
3035     },
3036     menuselect: function( event, ui ) {
3037     var item = ui.item.data( "ui-autocomplete-item" ),
3038     previous = this.previous;
3039    
3040     // only trigger when focus was lost (click on menu)
3041     if ( this.element[ 0 ] !== this.document[ 0 ].activeElement ) {
3042     this.element.focus();
3043     this.previous = previous;
3044     // #6109 - IE triggers two focus events and the second
3045     // is asynchronous, so we need to reset the previous
3046     // term synchronously and asynchronously :-(
3047     this._delay(function() {
3048     this.previous = previous;
3049     this.selectedItem = item;
3050     });
3051     }
3052    
3053     if ( false !== this._trigger( "select", event, { item: item } ) ) {
3054     this._value( item.value );
3055     }
3056     // reset the term after the select event
3057     // this allows custom select handling to work properly
3058     this.term = this._value();
3059    
3060     this.close( event );
3061     this.selectedItem = item;
3062     }
3063     });
3064    
3065     this.liveRegion = $( "<span>", {
3066     role: "status",
3067     "aria-live": "assertive",
3068     "aria-relevant": "additions"
3069     })
3070     .addClass( "ui-helper-hidden-accessible" )
3071     .appendTo( this.document[ 0 ].body );
3072    
3073     // turning off autocomplete prevents the browser from remembering the
3074     // value when navigating through history, so we re-enable autocomplete
3075     // if the page is unloaded before the widget is destroyed. #7790
3076     this._on( this.window, {
3077     beforeunload: function() {
3078     this.element.removeAttr( "autocomplete" );
3079     }
3080     });
3081     },
3082    
3083     _destroy: function() {
3084     clearTimeout( this.searching );
3085     this.element
3086     .removeClass( "ui-autocomplete-input" )
3087     .removeAttr( "autocomplete" );
3088     this.menu.element.remove();
3089     this.liveRegion.remove();
3090     },
3091    
3092     _setOption: function( key, value ) {
3093     this._super( key, value );
3094     if ( key === "source" ) {
3095     this._initSource();
3096     }
3097     if ( key === "appendTo" ) {
3098     this.menu.element.appendTo( this._appendTo() );
3099     }
3100     if ( key === "disabled" && value && this.xhr ) {
3101     this.xhr.abort();
3102     }
3103     },
3104    
3105     _appendTo: function() {
3106     var element = this.options.appendTo;
3107    
3108     if ( element ) {
3109     element = element.jquery || element.nodeType ?
3110     $( element ) :
3111     this.document.find( element ).eq( 0 );
3112     }
3113    
3114     if ( !element || !element[ 0 ] ) {
3115     element = this.element.closest( ".ui-front" );
3116     }
3117    
3118     if ( !element.length ) {
3119     element = this.document[ 0 ].body;
3120     }
3121    
3122     return element;
3123     },
3124    
3125     _initSource: function() {
3126     var array, url,
3127     that = this;
3128     if ( $.isArray( this.options.source ) ) {
3129     array = this.options.source;
3130     this.source = function( request, response ) {
3131     response( $.ui.autocomplete.filter( array, request.term ) );
3132     };
3133     } else if ( typeof this.options.source === "string" ) {
3134     url = this.options.source;
3135     this.source = function( request, response ) {
3136     if ( that.xhr ) {
3137     that.xhr.abort();
3138     }
3139     that.xhr = $.ajax({
3140     url: url,
3141     data: request,
3142     dataType: "json",
3143     success: function( data ) {
3144     response( data );
3145     },
3146     error: function() {
3147     response([]);
3148     }
3149     });
3150     };
3151     } else {
3152     this.source = this.options.source;
3153     }
3154     },
3155    
3156     _searchTimeout: function( event ) {
3157     clearTimeout( this.searching );
3158     this.searching = this._delay(function() {
3159    
3160     // Search if the value has changed, or if the user retypes the same value (see #7434)
3161     var equalValues = this.term === this._value(),
3162     menuVisible = this.menu.element.is( ":visible" ),
3163     modifierKey = event.altKey || event.ctrlKey || event.metaKey || event.shiftKey;
3164    
3165     if ( !equalValues || ( equalValues && !menuVisible && !modifierKey ) ) {
3166     this.selectedItem = null;
3167     this.search( null, event );
3168     }
3169     }, this.options.delay );
3170     },
3171    
3172     search: function( value, event ) {
3173     value = value != null ? value : this._value();
3174    
3175     // always save the actual value, not the one passed as an argument
3176     this.term = this._value();
3177    
3178     if ( value.length < this.options.minLength ) {
3179     return this.close( event );
3180     }
3181    
3182     if ( this._trigger( "search", event ) === false ) {
3183     return;
3184     }
3185    
3186     return this._search( value );
3187     },
3188    
3189     _search: function( value ) {
3190     this.pending++;
3191     this.element.addClass( "ui-autocomplete-loading" );
3192     this.cancelSearch = false;
3193    
3194     this.source( { term: value }, this._response() );
3195     },
3196    
3197     _response: function() {
3198     var index = ++this.requestIndex;
3199    
3200     return $.proxy(function( content ) {
3201     if ( index === this.requestIndex ) {
3202     this.__response( content );
3203     }
3204    
3205     this.pending--;
3206     if ( !this.pending ) {
3207     this.element.removeClass( "ui-autocomplete-loading" );
3208     }
3209     }, this );
3210     },
3211    
3212     __response: function( content ) {
3213     if ( content ) {
3214     content = this._normalize( content );
3215     }
3216     this._trigger( "response", null, { content: content } );
3217     if ( !this.options.disabled && content && content.length && !this.cancelSearch ) {
3218     this._suggest( content );
3219     this._trigger( "open" );
3220     } else {
3221     // use ._close() instead of .close() so we don't cancel future searches
3222     this._close();
3223     }
3224     },
3225    
3226     close: function( event ) {
3227     this.cancelSearch = true;
3228     this._close( event );
3229     },
3230    
3231     _close: function( event ) {
3232     if ( this.menu.element.is( ":visible" ) ) {
3233     this.menu.element.hide();
3234     this.menu.blur();
3235     this.isNewMenu = true;
3236     this._trigger( "close", event );
3237     }
3238     },
3239    
3240     _change: function( event ) {
3241     if ( this.previous !== this._value() ) {
3242     this._trigger( "change", event, { item: this.selectedItem } );
3243     }
3244     },
3245    
3246     _normalize: function( items ) {
3247     // assume all items have the right format when the first item is complete
3248     if ( items.length && items[ 0 ].label && items[ 0 ].value ) {
3249     return items;
3250     }
3251     return $.map( items, function( item ) {
3252     if ( typeof item === "string" ) {
3253     return {
3254     label: item,
3255     value: item
3256     };
3257     }
3258     return $.extend( {}, item, {
3259     label: item.label || item.value,
3260     value: item.value || item.label
3261     });
3262     });
3263     },
3264    
3265     _suggest: function( items ) {
3266     var ul = this.menu.element.empty();
3267     this._renderMenu( ul, items );
3268     this.isNewMenu = true;
3269     this.menu.refresh();
3270    
3271     // size and position menu
3272     ul.show();
3273     this._resizeMenu();
3274     ul.position( $.extend({
3275     of: this.element
3276     }, this.options.position ) );
3277    
3278     if ( this.options.autoFocus ) {
3279     this.menu.next();
3280     }
3281     },
3282    
3283     _resizeMenu: function() {
3284     var ul = this.menu.element;
3285     ul.outerWidth( Math.max(
3286     // Firefox wraps long text (possibly a rounding bug)
3287     // so we add 1px to avoid the wrapping (#7513)
3288     ul.width( "" ).outerWidth() + 1,
3289     this.element.outerWidth()
3290     ) );
3291     },
3292    
3293     _renderMenu: function( ul, items ) {
3294     var that = this;
3295     $.each( items, function( index, item ) {
3296     that._renderItemData( ul, item );
3297     });
3298     },
3299    
3300     _renderItemData: function( ul, item ) {
3301     return this._renderItem( ul, item ).data( "ui-autocomplete-item", item );
3302     },
3303    
3304     _renderItem: function( ul, item ) {
3305     return $( "<li>" ).text( item.label ).appendTo( ul );
3306     },
3307    
3308     _move: function( direction, event ) {
3309     if ( !this.menu.element.is( ":visible" ) ) {
3310     this.search( null, event );
3311     return;
3312     }
3313     if ( this.menu.isFirstItem() && /^previous/.test( direction ) ||
3314     this.menu.isLastItem() && /^next/.test( direction ) ) {
3315    
3316     if ( !this.isMultiLine ) {
3317     this._value( this.term );
3318     }
3319    
3320     this.menu.blur();
3321     return;
3322     }
3323     this.menu[ direction ]( event );
3324     },
3325    
3326     widget: function() {
3327     return this.menu.element;
3328     },
3329    
3330     _value: function() {
3331     return this.valueMethod.apply( this.element, arguments );
3332     },
3333    
3334     _keyEvent: function( keyEvent, event ) {
3335     if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
3336     this._move( keyEvent, event );
3337    
3338     // prevents moving cursor to beginning/end of the text field in some browsers
3339     event.preventDefault();
3340     }
3341     }
3342     });
3343    
3344     $.extend( $.ui.autocomplete, {
3345     escapeRegex: function( value ) {
3346     return value.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" );
3347     },
3348     filter: function( array, term ) {
3349     var matcher = new RegExp( $.ui.autocomplete.escapeRegex( term ), "i" );
3350     return $.grep( array, function( value ) {
3351     return matcher.test( value.label || value.value || value );
3352     });
3353     }
3354     });
3355    
3356     // live region extension, adding a `messages` option
3357     // NOTE: This is an experimental API. We are still investigating
3358     // a full solution for string manipulation and internationalization.
3359     $.widget( "ui.autocomplete", $.ui.autocomplete, {
3360     options: {
3361     messages: {
3362     noResults: "No search results.",
3363     results: function( amount ) {
3364     return amount + ( amount > 1 ? " results are" : " result is" ) +
3365     " available, use up and down arrow keys to navigate.";
3366     }
3367     }
3368     },
3369    
3370     __response: function( content ) {
3371     var message;
3372     this._superApply( arguments );
3373     if ( this.options.disabled || this.cancelSearch ) {
3374     return;
3375     }
3376     if ( content && content.length ) {
3377     message = this.options.messages.results( content.length );
3378     } else {
3379     message = this.options.messages.noResults;
3380     }
3381     this.liveRegion.children().hide();
3382     $( "<div>" ).text( message ).appendTo( this.liveRegion );
3383     }
3384     });
3385    
3386     var autocomplete = $.ui.autocomplete;
3387    
3388    
3389     /*!
3390     * jQuery UI Button 1.11.4
3391     * http://jqueryui.com
3392     *
3393     * Copyright jQuery Foundation and other contributors
3394     * Released under the MIT license.
3395     * http://jquery.org/license
3396     *
3397     * http://api.jqueryui.com/button/
3398     */
3399    
3400    
3401     var lastActive,
3402     baseClasses = "ui-button ui-widget ui-state-default ui-corner-all",
3403     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",
3404     formResetHandler = function() {
3405     var form = $( this );
3406     setTimeout(function() {
3407     form.find( ":ui-button" ).button( "refresh" );
3408     }, 1 );
3409     },
3410     radioGroup = function( radio ) {
3411     var name = radio.name,
3412     form = radio.form,
3413     radios = $( [] );
3414     if ( name ) {
3415     name = name.replace( /'/g, "\\'" );
3416     if ( form ) {
3417     radios = $( form ).find( "[name='" + name + "'][type=radio]" );
3418     } else {
3419     radios = $( "[name='" + name + "'][type=radio]", radio.ownerDocument )
3420     .filter(function() {
3421     return !this.form;
3422     });
3423     }
3424     }
3425     return radios;
3426     };
3427    
3428     $.widget( "ui.button", {
3429     version: "1.11.4",
3430     defaultElement: "<button>",
3431     options: {
3432     disabled: null,
3433     text: true,
3434     label: null,
3435     icons: {
3436     primary: null,
3437     secondary: null
3438     }
3439     },
3440     _create: function() {
3441     this.element.closest( "form" )
3442     .unbind( "reset" + this.eventNamespace )
3443     .bind( "reset" + this.eventNamespace, formResetHandler );
3444    
3445     if ( typeof this.options.disabled !== "boolean" ) {
3446     this.options.disabled = !!this.element.prop( "disabled" );
3447     } else {
3448     this.element.prop( "disabled", this.options.disabled );
3449     }
3450    
3451     this._determineButtonType();
3452     this.hasTitle = !!this.buttonElement.attr( "title" );
3453    
3454     var that = this,
3455     options = this.options,
3456     toggleButton = this.type === "checkbox" || this.type === "radio",
3457     activeClass = !toggleButton ? "ui-state-active" : "";
3458    
3459     if ( options.label === null ) {
3460     options.label = (this.type === "input" ? this.buttonElement.val() : this.buttonElement.html());
3461     }
3462    
3463     this._hoverable( this.buttonElement );
3464    
3465     this.buttonElement
3466     .addClass( baseClasses )
3467     .attr( "role", "button" )
3468     .bind( "mouseenter" + this.eventNamespace, function() {
3469     if ( options.disabled ) {
3470     return;
3471     }
3472     if ( this === lastActive ) {
3473     $( this ).addClass( "ui-state-active" );
3474     }
3475     })
3476     .bind( "mouseleave" + this.eventNamespace, function() {
3477     if ( options.disabled ) {
3478     return;
3479     }
3480     $( this ).removeClass( activeClass );
3481     })
3482     .bind( "click" + this.eventNamespace, function( event ) {
3483     if ( options.disabled ) {
3484     event.preventDefault();
3485     event.stopImmediatePropagation();
3486     }
3487     });
3488    
3489     // Can't use _focusable() because the element that receives focus
3490     // and the element that gets the ui-state-focus class are different
3491     this._on({
3492     focus: function() {
3493     this.buttonElement.addClass( "ui-state-focus" );
3494     },
3495     blur: function() {
3496     this.buttonElement.removeClass( "ui-state-focus" );
3497     }
3498     });
3499    
3500     if ( toggleButton ) {
3501     this.element.bind( "change" + this.eventNamespace, function() {
3502     that.refresh();
3503     });
3504     }
3505    
3506     if ( this.type === "checkbox" ) {
3507     this.buttonElement.bind( "click" + this.eventNamespace, function() {
3508     if ( options.disabled ) {
3509     return false;
3510     }
3511     });
3512     } else if ( this.type === "radio" ) {
3513     this.buttonElement.bind( "click" + this.eventNamespace, function() {
3514     if ( options.disabled ) {
3515     return false;
3516     }
3517     $( this ).addClass( "ui-state-active" );
3518     that.buttonElement.attr( "aria-pressed", "true" );
3519    
3520     var radio = that.element[ 0 ];
3521     radioGroup( radio )
3522     .not( radio )
3523     .map(function() {
3524     return $( this ).button( "widget" )[ 0 ];
3525     })
3526     .removeClass( "ui-state-active" )
3527     .attr( "aria-pressed", "false" );
3528     });
3529     } else {
3530     this.buttonElement
3531     .bind( "mousedown" + this.eventNamespace, function() {
3532     if ( options.disabled ) {
3533     return false;
3534     }
3535     $( this ).addClass( "ui-state-active" );
3536     lastActive = this;
3537     that.document.one( "mouseup", function() {
3538     lastActive = null;
3539     });
3540     })
3541     .bind( "mouseup" + this.eventNamespace, function() {
3542     if ( options.disabled ) {
3543     return false;
3544     }
3545     $( this ).removeClass( "ui-state-active" );
3546     })
3547     .bind( "keydown" + this.eventNamespace, function(event) {
3548     if ( options.disabled ) {
3549     return false;
3550     }
3551     if ( event.keyCode === $.ui.keyCode.SPACE || event.keyCode === $.ui.keyCode.ENTER ) {
3552     $( this ).addClass( "ui-state-active" );
3553     }
3554     })
3555     // see #8559, we bind to blur here in case the button element loses
3556     // focus between keydown and keyup, it would be left in an "active" state
3557     .bind( "keyup" + this.eventNamespace + " blur" + this.eventNamespace, function() {
3558     $( this ).removeClass( "ui-state-active" );
3559     });
3560    
3561     if ( this.buttonElement.is("a") ) {
3562     this.buttonElement.keyup(function(event) {
3563     if ( event.keyCode === $.ui.keyCode.SPACE ) {
3564     // TODO pass through original event correctly (just as 2nd argument doesn't work)
3565     $( this ).click();
3566     }
3567     });
3568     }
3569     }
3570    
3571     this._setOption( "disabled", options.disabled );
3572     this._resetButton();
3573     },
3574    
3575     _determineButtonType: function() {
3576     var ancestor, labelSelector, checked;
3577    
3578     if ( this.element.is("[type=checkbox]") ) {
3579     this.type = "checkbox";
3580     } else if ( this.element.is("[type=radio]") ) {
3581     this.type = "radio";
3582     } else if ( this.element.is("input") ) {
3583     this.type = "input";
3584     } else {
3585     this.type = "button";
3586     }
3587    
3588     if ( this.type === "checkbox" || this.type === "radio" ) {
3589     // we don't search against the document in case the element
3590     // is disconnected from the DOM
3591     ancestor = this.element.parents().last();
3592     labelSelector = "label[for='" + this.element.attr("id") + "']";
3593     this.buttonElement = ancestor.find( labelSelector );
3594     if ( !this.buttonElement.length ) {
3595     ancestor = ancestor.length ? ancestor.siblings() : this.element.siblings();
3596     this.buttonElement = ancestor.filter( labelSelector );
3597     if ( !this.buttonElement.length ) {
3598     this.buttonElement = ancestor.find( labelSelector );
3599     }
3600     }
3601     this.element.addClass( "ui-helper-hidden-accessible" );
3602    
3603     checked = this.element.is( ":checked" );
3604     if ( checked ) {
3605     this.buttonElement.addClass( "ui-state-active" );
3606     }
3607     this.buttonElement.prop( "aria-pressed", checked );
3608     } else {
3609     this.buttonElement = this.element;
3610     }
3611     },
3612    
3613     widget: function() {
3614     return this.buttonElement;
3615     },
3616    
3617     _destroy: function() {
3618     this.element
3619     .removeClass( "ui-helper-hidden-accessible" );
3620     this.buttonElement
3621     .removeClass( baseClasses + " ui-state-active " + typeClasses )
3622     .removeAttr( "role" )
3623     .removeAttr( "aria-pressed" )
3624     .html( this.buttonElement.find(".ui-button-text").html() );
3625    
3626     if ( !this.hasTitle ) {
3627     this.buttonElement.removeAttr( "title" );
3628     }
3629     },
3630    
3631     _setOption: function( key, value ) {
3632     this._super( key, value );
3633     if ( key === "disabled" ) {
3634     this.widget().toggleClass( "ui-state-disabled", !!value );
3635     this.element.prop( "disabled", !!value );
3636     if ( value ) {
3637     if ( this.type === "checkbox" || this.type === "radio" ) {
3638     this.buttonElement.removeClass( "ui-state-focus" );
3639     } else {
3640     this.buttonElement.removeClass( "ui-state-focus ui-state-active" );
3641     }
3642     }
3643     return;
3644     }
3645     this._resetButton();
3646     },
3647    
3648     refresh: function() {
3649     //See #8237 & #8828
3650     var isDisabled = this.element.is( "input, button" ) ? this.element.is( ":disabled" ) : this.element.hasClass( "ui-button-disabled" );
3651    
3652     if ( isDisabled !== this.options.disabled ) {
3653     this._setOption( "disabled", isDisabled );
3654     }
3655     if ( this.type === "radio" ) {
3656     radioGroup( this.element[0] ).each(function() {
3657     if ( $( this ).is( ":checked" ) ) {
3658     $( this ).button( "widget" )
3659     .addClass( "ui-state-active" )
3660     .attr( "aria-pressed", "true" );
3661     } else {
3662     $( this ).button( "widget" )
3663     .removeClass( "ui-state-active" )
3664     .attr( "aria-pressed", "false" );
3665     }
3666     });
3667     } else if ( this.type === "checkbox" ) {
3668     if ( this.element.is( ":checked" ) ) {
3669     this.buttonElement
3670     .addClass( "ui-state-active" )
3671     .attr( "aria-pressed", "true" );
3672     } else {
3673     this.buttonElement
3674     .removeClass( "ui-state-active" )
3675     .attr( "aria-pressed", "false" );
3676     }
3677     }
3678     },
3679    
3680     _resetButton: function() {
3681     if ( this.type === "input" ) {
3682     if ( this.options.label ) {
3683     this.element.val( this.options.label );
3684     }
3685     return;
3686     }
3687     var buttonElement = this.buttonElement.removeClass( typeClasses ),
3688     buttonText = $( "<span></span>", this.document[0] )
3689     .addClass( "ui-button-text" )
3690     .html( this.options.label )
3691     .appendTo( buttonElement.empty() )
3692     .text(),
3693     icons = this.options.icons,
3694     multipleIcons = icons.primary && icons.secondary,
3695     buttonClasses = [];
3696    
3697     if ( icons.primary || icons.secondary ) {
3698     if ( this.options.text ) {
3699     buttonClasses.push( "ui-button-text-icon" + ( multipleIcons ? "s" : ( icons.primary ? "-primary" : "-secondary" ) ) );
3700     }
3701    
3702     if ( icons.primary ) {
3703     buttonElement.prepend( "<span class='ui-button-icon-primary ui-icon " + icons.primary + "'></span>" );
3704     }
3705    
3706     if ( icons.secondary ) {
3707     buttonElement.append( "<span class='ui-button-icon-secondary ui-icon " + icons.secondary + "'></span>" );
3708     }
3709    
3710     if ( !this.options.text ) {
3711     buttonClasses.push( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" );
3712    
3713     if ( !this.hasTitle ) {
3714     buttonElement.attr( "title", $.trim( buttonText ) );
3715     }
3716     }
3717     } else {
3718     buttonClasses.push( "ui-button-text-only" );
3719     }
3720     buttonElement.addClass( buttonClasses.join( " " ) );
3721     }
3722     });
3723    
3724     $.widget( "ui.buttonset", {
3725     version: "1.11.4",
3726     options: {
3727     items: "button, input[type=button], input[type=submit], input[type=reset], input[type=checkbox], input[type=radio], a, :data(ui-button)"
3728     },
3729    
3730     _create: function() {
3731     this.element.addClass( "ui-buttonset" );
3732     },
3733    
3734     _init: function() {
3735     this.refresh();
3736     },
3737    
3738     _setOption: function( key, value ) {
3739     if ( key === "disabled" ) {
3740     this.buttons.button( "option", key, value );
3741     }
3742    
3743     this._super( key, value );
3744     },
3745    
3746     refresh: function() {
3747     var rtl = this.element.css( "direction" ) === "rtl",
3748     allButtons = this.element.find( this.options.items ),
3749     existingButtons = allButtons.filter( ":ui-button" );
3750    
3751     // Initialize new buttons
3752     allButtons.not( ":ui-button" ).button();
3753    
3754     // Refresh existing buttons
3755     existingButtons.button( "refresh" );
3756    
3757     this.buttons = allButtons
3758     .map(function() {
3759     return $( this ).button( "widget" )[ 0 ];
3760     })
3761     .removeClass( "ui-corner-all ui-corner-left ui-corner-right" )
3762     .filter( ":first" )
3763     .addClass( rtl ? "ui-corner-right" : "ui-corner-left" )
3764     .end()
3765     .filter( ":last" )
3766     .addClass( rtl ? "ui-corner-left" : "ui-corner-right" )
3767     .end()
3768     .end();
3769     },
3770    
3771     _destroy: function() {
3772     this.element.removeClass( "ui-buttonset" );
3773     this.buttons
3774     .map(function() {
3775     return $( this ).button( "widget" )[ 0 ];
3776     })
3777     .removeClass( "ui-corner-left ui-corner-right" )
3778     .end()
3779     .button( "destroy" );
3780     }
3781     });
3782    
3783     var button = $.ui.button;
3784    
3785    
3786     /*!
3787     * jQuery UI Datepicker 1.11.4
3788     * http://jqueryui.com
3789     *
3790     * Copyright jQuery Foundation and other contributors
3791     * Released under the MIT license.
3792     * http://jquery.org/license
3793     *
3794     * http://api.jqueryui.com/datepicker/
3795     */
3796    
3797    
3798     $.extend($.ui, { datepicker: { version: "1.11.4" } });
3799    
3800     var datepicker_instActive;
3801    
3802     function datepicker_getZindex( elem ) {
3803     var position, value;
3804     while ( elem.length && elem[ 0 ] !== document ) {
3805     // Ignore z-index if position is set to a value where z-index is ignored by the browser
3806     // This makes behavior of this function consistent across browsers
3807     // WebKit always returns auto if the element is positioned
3808     position = elem.css( "position" );
3809     if ( position === "absolute" || position === "relative" || position === "fixed" ) {
3810     // IE returns 0 when zIndex is not specified
3811     // other browsers return a string
3812     // we ignore the case of nested elements with an explicit value of 0
3813     // <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
3814     value = parseInt( elem.css( "zIndex" ), 10 );
3815     if ( !isNaN( value ) && value !== 0 ) {
3816     return value;
3817     }
3818     }
3819     elem = elem.parent();
3820     }
3821    
3822     return 0;
3823     }
3824     /* Date picker manager.
3825     Use the singleton instance of this class, $.datepicker, to interact with the date picker.
3826     Settings for (groups of) date pickers are maintained in an instance object,
3827     allowing multiple different settings on the same page. */
3828    
3829     function Datepicker() {
3830     this._curInst = null; // The current instance in use
3831     this._keyEvent = false; // If the last event was a key event
3832     this._disabledInputs = []; // List of date picker inputs that have been disabled
3833     this._datepickerShowing = false; // True if the popup picker is showing , false if not
3834     this._inDialog = false; // True if showing within a "dialog", false if not
3835     this._mainDivId = "ui-datepicker-div"; // The ID of the main datepicker division
3836     this._inlineClass = "ui-datepicker-inline"; // The name of the inline marker class
3837     this._appendClass = "ui-datepicker-append"; // The name of the append marker class
3838     this._triggerClass = "ui-datepicker-trigger"; // The name of the trigger marker class
3839     this._dialogClass = "ui-datepicker-dialog"; // The name of the dialog marker class
3840     this._disableClass = "ui-datepicker-disabled"; // The name of the disabled covering marker class
3841     this._unselectableClass = "ui-datepicker-unselectable"; // The name of the unselectable cell marker class
3842     this._currentClass = "ui-datepicker-current-day"; // The name of the current day marker class
3843     this._dayOverClass = "ui-datepicker-days-cell-over"; // The name of the day hover marker class
3844     this.regional = []; // Available regional settings, indexed by language code
3845     this.regional[""] = { // Default regional settings
3846     closeText: "Done", // Display text for close link
3847     prevText: "Prev", // Display text for previous month link
3848     nextText: "Next", // Display text for next month link
3849     currentText: "Today", // Display text for current month link
3850     monthNames: ["January","February","March","April","May","June",
3851     "July","August","September","October","November","December"], // Names of months for drop-down and formatting
3852     monthNamesShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], // For formatting
3853     dayNames: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], // For formatting
3854     dayNamesShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], // For formatting
3855     dayNamesMin: ["Su","Mo","Tu","We","Th","Fr","Sa"], // Column headings for days starting at Sunday
3856     weekHeader: "Wk", // Column header for week of the year
3857     dateFormat: "mm/dd/yy", // See format options on parseDate
3858     firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
3859     isRTL: false, // True if right-to-left language, false if left-to-right
3860     showMonthAfterYear: false, // True if the year select precedes month, false for month then year
3861     yearSuffix: "" // Additional text to append to the year in the month headers
3862     };
3863     this._defaults = { // Global defaults for all the date picker instances
3864     showOn: "focus", // "focus" for popup on focus,
3865     // "button" for trigger button, or "both" for either
3866     showAnim: "fadeIn", // Name of jQuery animation for popup
3867     showOptions: {}, // Options for enhanced animations
3868     defaultDate: null, // Used when field is blank: actual date,
3869     // +/-number for offset from today, null for today
3870     appendText: "", // Display text following the input box, e.g. showing the format
3871     buttonText: "...", // Text for trigger button
3872     buttonImage: "", // URL for trigger button image
3873     buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
3874     hideIfNoPrevNext: false, // True to hide next/previous month links
3875     // if not applicable, false to just disable them
3876     navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
3877     gotoCurrent: false, // True if today link goes back to current selection instead
3878     changeMonth: false, // True if month can be selected directly, false if only prev/next
3879     changeYear: false, // True if year can be selected directly, false if only prev/next
3880     yearRange: "c-10:c+10", // Range of years to display in drop-down,
3881     // either relative to today's year (-nn:+nn), relative to currently displayed year
3882     // (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
3883     showOtherMonths: false, // True to show dates in other months, false to leave blank
3884     selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
3885     showWeek: false, // True to show week of the year, false to not show it
3886     calculateWeek: this.iso8601Week, // How to calculate the week of the year,
3887     // takes a Date and returns the number of the week for it
3888     shortYearCutoff: "+10", // Short year values < this are in the current century,
3889     // > this are in the previous century,
3890     // string value starting with "+" for current year + value
3891     minDate: null, // The earliest selectable date, or null for no limit
3892     maxDate: null, // The latest selectable date, or null for no limit
3893     duration: "fast", // Duration of display/closure
3894     beforeShowDay: null, // Function that takes a date and returns an array with
3895     // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or "",
3896     // [2] = cell title (optional), e.g. $.datepicker.noWeekends
3897     beforeShow: null, // Function that takes an input field and
3898     // returns a set of custom settings for the date picker
3899     onSelect: null, // Define a callback function when a date is selected
3900     onChangeMonthYear: null, // Define a callback function when the month or year is changed
3901     onClose: null, // Define a callback function when the datepicker is closed
3902     numberOfMonths: 1, // Number of months to show at a time
3903     showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
3904     stepMonths: 1, // Number of months to step back/forward
3905     stepBigMonths: 12, // Number of months to step back/forward for the big links
3906     altField: "", // Selector for an alternate field to store selected dates into
3907     altFormat: "", // The date format to use for the alternate field
3908     constrainInput: true, // The input is constrained by the current date format
3909     showButtonPanel: false, // True to show button panel, false to not show it
3910     autoSize: false, // True to size the input for the date format, false to leave as is
3911     disabled: false // The initial disabled state
3912     };
3913     $.extend(this._defaults, this.regional[""]);
3914     this.regional.en = $.extend( true, {}, this.regional[ "" ]);
3915     this.regional[ "en-US" ] = $.extend( true, {}, this.regional.en );
3916     this.dpDiv = datepicker_bindHover($("<div id='" + this._mainDivId + "' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>"));
3917     }
3918    
3919     $.extend(Datepicker.prototype, {
3920     /* Class name added to elements to indicate already configured with a date picker. */
3921     markerClassName: "hasDatepicker",
3922    
3923     //Keep track of the maximum number of rows displayed (see #7043)
3924     maxRows: 4,
3925    
3926     // TODO rename to "widget" when switching to widget factory
3927     _widgetDatepicker: function() {
3928     return this.dpDiv;
3929     },
3930    
3931     /* Override the default settings for all instances of the date picker.
3932     * @param settings object - the new settings to use as defaults (anonymous object)
3933     * @return the manager object
3934     */
3935     setDefaults: function(settings) {
3936     datepicker_extendRemove(this._defaults, settings || {});
3937     return this;
3938     },
3939    
3940     /* Attach the date picker to a jQuery selection.
3941     * @param target element - the target input field or division or span
3942     * @param settings object - the new settings to use for this date picker instance (anonymous)
3943     */
3944     _attachDatepicker: function(target, settings) {
3945     var nodeName, inline, inst;
3946     nodeName = target.nodeName.toLowerCase();
3947     inline = (nodeName === "div" || nodeName === "span");
3948     if (!target.id) {
3949     this.uuid += 1;
3950     target.id = "dp" + this.uuid;
3951     }
3952     inst = this._newInst($(target), inline);
3953     inst.settings = $.extend({}, settings || {});
3954     if (nodeName === "input") {
3955     this._connectDatepicker(target, inst);
3956     } else if (inline) {
3957     this._inlineDatepicker(target, inst);
3958     }
3959     },
3960    
3961     /* Create a new instance object. */
3962     _newInst: function(target, inline) {
3963     var id = target[0].id.replace(/([^A-Za-z0-9_\-])/g, "\\\\$1"); // escape jQuery meta chars
3964     return {id: id, input: target, // associated target
3965     selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
3966     drawMonth: 0, drawYear: 0, // month being drawn
3967     inline: inline, // is datepicker inline or not
3968     dpDiv: (!inline ? this.dpDiv : // presentation div
3969     datepicker_bindHover($("<div class='" + this._inlineClass + " ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>")))};
3970     },
3971    
3972     /* Attach the date picker to an input field. */
3973     _connectDatepicker: function(target, inst) {
3974     var input = $(target);
3975     inst.append = $([]);
3976     inst.trigger = $([]);
3977     if (input.hasClass(this.markerClassName)) {
3978     return;
3979     }
3980     this._attachments(input, inst);
3981     input.addClass(this.markerClassName).keydown(this._doKeyDown).
3982     keypress(this._doKeyPress).keyup(this._doKeyUp);
3983     this._autoSize(inst);
3984     $.data(target, "datepicker", inst);
3985     //If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665)
3986     if( inst.settings.disabled ) {
3987     this._disableDatepicker( target );
3988     }
3989     },
3990    
3991     /* Make attachments based on settings. */
3992     _attachments: function(input, inst) {
3993     var showOn, buttonText, buttonImage,
3994     appendText = this._get(inst, "appendText"),
3995     isRTL = this._get(inst, "isRTL");
3996    
3997     if (inst.append) {
3998     inst.append.remove();
3999     }
4000     if (appendText) {
4001     inst.append = $("<span class='" + this._appendClass + "'>" + appendText + "</span>");
4002     input[isRTL ? "before" : "after"](inst.append);
4003     }
4004    
4005     input.unbind("focus", this._showDatepicker);
4006    
4007     if (inst.trigger) {
4008     inst.trigger.remove();
4009     }
4010    
4011     showOn = this._get(inst, "showOn");
4012     if (showOn === "focus" || showOn === "both") { // pop-up date picker when in the marked field
4013     input.focus(this._showDatepicker);
4014     }
4015     if (showOn === "button" || showOn === "both") { // pop-up date picker when button clicked
4016     buttonText = this._get(inst, "buttonText");
4017     buttonImage = this._get(inst, "buttonImage");
4018     inst.trigger = $(this._get(inst, "buttonImageOnly") ?
4019     $("<img/>").addClass(this._triggerClass).
4020     attr({ src: buttonImage, alt: buttonText, title: buttonText }) :
4021     $("<button type='button'></button>").addClass(this._triggerClass).
4022     html(!buttonImage ? buttonText : $("<img/>").attr(
4023     { src:buttonImage, alt:buttonText, title:buttonText })));
4024     input[isRTL ? "before" : "after"](inst.trigger);
4025     inst.trigger.click(function() {
4026     if ($.datepicker._datepickerShowing && $.datepicker._lastInput === input[0]) {
4027     $.datepicker._hideDatepicker();
4028     } else if ($.datepicker._datepickerShowing && $.datepicker._lastInput !== input[0]) {
4029     $.datepicker._hideDatepicker();
4030     $.datepicker._showDatepicker(input[0]);
4031     } else {
4032     $.datepicker._showDatepicker(input[0]);
4033     }
4034     return false;
4035     });
4036     }
4037     },
4038    
4039     /* Apply the maximum length for the date format. */
4040     _autoSize: function(inst) {
4041     if (this._get(inst, "autoSize") && !inst.inline) {
4042     var findMax, max, maxI, i,
4043     date = new Date(2009, 12 - 1, 20), // Ensure double digits
4044     dateFormat = this._get(inst, "dateFormat");
4045    
4046     if (dateFormat.match(/[DM]/)) {
4047     findMax = function(names) {
4048     max = 0;
4049     maxI = 0;
4050     for (i = 0; i < names.length; i++) {
4051     if (names[i].length > max) {
4052     max = names[i].length;
4053     maxI = i;
4054     }
4055     }
4056     return maxI;
4057     };
4058     date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ?
4059     "monthNames" : "monthNamesShort"))));
4060     date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ?
4061     "dayNames" : "dayNamesShort"))) + 20 - date.getDay());
4062     }
4063     inst.input.attr("size", this._formatDate(inst, date).length);
4064     }
4065     },
4066    
4067     /* Attach an inline date picker to a div. */
4068     _inlineDatepicker: function(target, inst) {
4069     var divSpan = $(target);
4070     if (divSpan.hasClass(this.markerClassName)) {
4071     return;
4072     }
4073     divSpan.addClass(this.markerClassName).append(inst.dpDiv);
4074     $.data(target, "datepicker", inst);
4075     this._setDate(inst, this._getDefaultDate(inst), true);
4076     this._updateDatepicker(inst);
4077     this._updateAlternate(inst);
4078     //If disabled option is true, disable the datepicker before showing it (see ticket #5665)
4079     if( inst.settings.disabled ) {
4080     this._disableDatepicker( target );
4081     }
4082     // Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements
4083     // http://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height
4084     inst.dpDiv.css( "display", "block" );
4085     },
4086    
4087     /* Pop-up the date picker in a "dialog" box.
4088     * @param input element - ignored
4089     * @param date string or Date - the initial date to display
4090     * @param onSelect function - the function to call when a date is selected
4091     * @param settings object - update the dialog date picker instance's settings (anonymous object)
4092     * @param pos int[2] - coordinates for the dialog's position within the screen or
4093     * event - with x/y coordinates or
4094     * leave empty for default (screen centre)
4095     * @return the manager object
4096     */
4097     _dialogDatepicker: function(input, date, onSelect, settings, pos) {
4098     var id, browserWidth, browserHeight, scrollX, scrollY,
4099     inst = this._dialogInst; // internal instance
4100    
4101     if (!inst) {
4102     this.uuid += 1;
4103     id = "dp" + this.uuid;
4104     this._dialogInput = $("<input type='text' id='" + id +
4105     "' style='position: absolute; top: -100px; width: 0px;'/>");
4106     this._dialogInput.keydown(this._doKeyDown);
4107     $("body").append(this._dialogInput);
4108     inst = this._dialogInst = this._newInst(this._dialogInput, false);
4109     inst.settings = {};
4110     $.data(this._dialogInput[0], "datepicker", inst);
4111     }
4112     datepicker_extendRemove(inst.settings, settings || {});
4113     date = (date && date.constructor === Date ? this._formatDate(inst, date) : date);
4114     this._dialogInput.val(date);
4115    
4116     this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);
4117     if (!this._pos) {
4118     browserWidth = document.documentElement.clientWidth;
4119     browserHeight = document.documentElement.clientHeight;
4120     scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
4121     scrollY = document.documentElement.scrollTop || document.body.scrollTop;
4122     this._pos = // should use actual width/height below
4123     [(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY];
4124     }
4125    
4126     // move input on screen for focus, but hidden behind dialog
4127     this._dialogInput.css("left", (this._pos[0] + 20) + "px").css("top", this._pos[1] + "px");
4128     inst.settings.onSelect = onSelect;
4129     this._inDialog = true;
4130     this.dpDiv.addClass(this._dialogClass);
4131     this._showDatepicker(this._dialogInput[0]);
4132     if ($.blockUI) {
4133     $.blockUI(this.dpDiv);
4134     }
4135     $.data(this._dialogInput[0], "datepicker", inst);
4136     return this;
4137     },
4138    
4139     /* Detach a datepicker from its control.
4140     * @param target element - the target input field or division or span
4141     */
4142     _destroyDatepicker: function(target) {
4143     var nodeName,
4144     $target = $(target),
4145     inst = $.data(target, "datepicker");
4146    
4147     if (!$target.hasClass(this.markerClassName)) {
4148     return;
4149     }
4150    
4151     nodeName = target.nodeName.toLowerCase();
4152     $.removeData(target, "datepicker");
4153     if (nodeName === "input") {
4154     inst.append.remove();
4155     inst.trigger.remove();
4156     $target.removeClass(this.markerClassName).
4157     unbind("focus", this._showDatepicker).
4158     unbind("keydown", this._doKeyDown).
4159     unbind("keypress", this._doKeyPress).
4160     unbind("keyup", this._doKeyUp);
4161     } else if (nodeName === "div" || nodeName === "span") {
4162     $target.removeClass(this.markerClassName).empty();
4163     }
4164    
4165     if ( datepicker_instActive === inst ) {
4166     datepicker_instActive = null;
4167     }
4168     },
4169    
4170     /* Enable the date picker to a jQuery selection.
4171     * @param target element - the target input field or division or span
4172     */
4173     _enableDatepicker: function(target) {
4174     var nodeName, inline,
4175     $target = $(target),
4176     inst = $.data(target, "datepicker");
4177    
4178     if (!$target.hasClass(this.markerClassName)) {
4179     return;
4180     }
4181    
4182     nodeName = target.nodeName.toLowerCase();
4183     if (nodeName === "input") {
4184     target.disabled = false;
4185     inst.trigger.filter("button").
4186     each(function() { this.disabled = false; }).end().
4187     filter("img").css({opacity: "1.0", cursor: ""});
4188     } else if (nodeName === "div" || nodeName === "span") {
4189     inline = $target.children("." + this._inlineClass);
4190     inline.children().removeClass("ui-state-disabled");
4191     inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
4192     prop("disabled", false);
4193     }
4194     this._disabledInputs = $.map(this._disabledInputs,
4195     function(value) { return (value === target ? null : value); }); // delete entry
4196     },
4197    
4198     /* Disable the date picker to a jQuery selection.
4199     * @param target element - the target input field or division or span
4200     */
4201     _disableDatepicker: function(target) {
4202     var nodeName, inline,
4203     $target = $(target),
4204     inst = $.data(target, "datepicker");
4205    
4206     if (!$target.hasClass(this.markerClassName)) {
4207     return;
4208     }
4209    
4210     nodeName = target.nodeName.toLowerCase();
4211     if (nodeName === "input") {
4212     target.disabled = true;
4213     inst.trigger.filter("button").
4214     each(function() { this.disabled = true; }).end().
4215     filter("img").css({opacity: "0.5", cursor: "default"});
4216     } else if (nodeName === "div" || nodeName === "span") {
4217     inline = $target.children("." + this._inlineClass);
4218     inline.children().addClass("ui-state-disabled");
4219     inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
4220     prop("disabled", true);
4221     }
4222     this._disabledInputs = $.map(this._disabledInputs,
4223     function(value) { return (value === target ? null : value); }); // delete entry
4224     this._disabledInputs[this._disabledInputs.length] = target;
4225     },
4226    
4227     /* Is the first field in a jQuery collection disabled as a datepicker?
4228     * @param target element - the target input field or division or span
4229     * @return boolean - true if disabled, false if enabled
4230     */
4231     _isDisabledDatepicker: function(target) {
4232     if (!target) {
4233     return false;
4234     }
4235     for (var i = 0; i < this._disabledInputs.length; i++) {
4236     if (this._disabledInputs[i] === target) {
4237     return true;
4238     }
4239     }
4240     return false;
4241     },
4242    
4243     /* Retrieve the instance data for the target control.
4244     * @param target element - the target input field or division or span
4245     * @return object - the associated instance data
4246     * @throws error if a jQuery problem getting data
4247     */
4248     _getInst: function(target) {
4249     try {
4250     return $.data(target, "datepicker");
4251     }
4252     catch (err) {
4253     throw "Missing instance data for this datepicker";
4254     }
4255     },
4256    
4257     /* Update or retrieve the settings for a date picker attached to an input field or division.
4258     * @param target element - the target input field or division or span
4259     * @param name object - the new settings to update or
4260     * string - the name of the setting to change or retrieve,
4261     * when retrieving also "all" for all instance settings or
4262     * "defaults" for all global defaults
4263     * @param value any - the new value for the setting
4264     * (omit if above is an object or to retrieve a value)
4265     */
4266     _optionDatepicker: function(target, name, value) {
4267     var settings, date, minDate, maxDate,
4268     inst = this._getInst(target);
4269    
4270     if (arguments.length === 2 && typeof name === "string") {
4271     return (name === "defaults" ? $.extend({}, $.datepicker._defaults) :
4272     (inst ? (name === "all" ? $.extend({}, inst.settings) :
4273     this._get(inst, name)) : null));
4274     }
4275    
4276     settings = name || {};
4277     if (typeof name === "string") {
4278     settings = {};
4279     settings[name] = value;
4280     }
4281    
4282     if (inst) {
4283     if (this._curInst === inst) {
4284     this._hideDatepicker();
4285     }
4286    
4287     date = this._getDateDatepicker(target, true);
4288     minDate = this._getMinMaxDate(inst, "min");
4289     maxDate = this._getMinMaxDate(inst, "max");
4290     datepicker_extendRemove(inst.settings, settings);
4291     // reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided
4292     if (minDate !== null && settings.dateFormat !== undefined && settings.minDate === undefined) {
4293     inst.settings.minDate = this._formatDate(inst, minDate);
4294     }
4295     if (maxDate !== null && settings.dateFormat !== undefined && settings.maxDate === undefined) {
4296     inst.settings.maxDate = this._formatDate(inst, maxDate);
4297     }
4298     if ( "disabled" in settings ) {
4299     if ( settings.disabled ) {
4300     this._disableDatepicker(target);
4301     } else {
4302     this._enableDatepicker(target);
4303     }
4304     }
4305     this._attachments($(target), inst);
4306     this._autoSize(inst);
4307     this._setDate(inst, date);
4308     this._updateAlternate(inst);
4309     this._updateDatepicker(inst);
4310     }
4311     },
4312    
4313     // change method deprecated
4314     _changeDatepicker: function(target, name, value) {
4315     this._optionDatepicker(target, name, value);
4316     },
4317    
4318     /* Redraw the date picker attached to an input field or division.
4319     * @param target element - the target input field or division or span
4320     */
4321     _refreshDatepicker: function(target) {
4322     var inst = this._getInst(target);
4323     if (inst) {
4324     this._updateDatepicker(inst);
4325     }
4326     },
4327    
4328     /* Set the dates for a jQuery selection.
4329     * @param target element - the target input field or division or span
4330     * @param date Date - the new date
4331     */
4332     _setDateDatepicker: function(target, date) {
4333     var inst = this._getInst(target);
4334     if (inst) {
4335     this._setDate(inst, date);
4336     this._updateDatepicker(inst);
4337     this._updateAlternate(inst);
4338     }
4339     },
4340    
4341     /* Get the date(s) for the first entry in a jQuery selection.
4342     * @param target element - the target input field or division or span
4343     * @param noDefault boolean - true if no default date is to be used
4344     * @return Date - the current date
4345     */
4346     _getDateDatepicker: function(target, noDefault) {
4347     var inst = this._getInst(target);
4348     if (inst && !inst.inline) {
4349     this._setDateFromField(inst, noDefault);
4350     }
4351     return (inst ? this._getDate(inst) : null);
4352     },
4353    
4354     /* Handle keystrokes. */
4355     _doKeyDown: function(event) {
4356     var onSelect, dateStr, sel,
4357     inst = $.datepicker._getInst(event.target),
4358     handled = true,
4359     isRTL = inst.dpDiv.is(".ui-datepicker-rtl");
4360    
4361     inst._keyEvent = true;
4362     if ($.datepicker._datepickerShowing) {
4363     switch (event.keyCode) {
4364     case 9: $.datepicker._hideDatepicker();
4365     handled = false;
4366     break; // hide on tab out
4367     case 13: sel = $("td." + $.datepicker._dayOverClass + ":not(." +
4368     $.datepicker._currentClass + ")", inst.dpDiv);
4369     if (sel[0]) {
4370     $.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);
4371     }
4372    
4373     onSelect = $.datepicker._get(inst, "onSelect");
4374     if (onSelect) {
4375     dateStr = $.datepicker._formatDate(inst);
4376    
4377     // trigger custom callback
4378     onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);
4379     } else {
4380     $.datepicker._hideDatepicker();
4381     }
4382    
4383     return false; // don't submit the form
4384     case 27: $.datepicker._hideDatepicker();
4385     break; // hide on escape
4386     case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
4387     -$.datepicker._get(inst, "stepBigMonths") :
4388     -$.datepicker._get(inst, "stepMonths")), "M");
4389     break; // previous month/year on page up/+ ctrl
4390     case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
4391     +$.datepicker._get(inst, "stepBigMonths") :
4392     +$.datepicker._get(inst, "stepMonths")), "M");
4393     break; // next month/year on page down/+ ctrl
4394     case 35: if (event.ctrlKey || event.metaKey) {
4395     $.datepicker._clearDate(event.target);
4396     }
4397     handled = event.ctrlKey || event.metaKey;
4398     break; // clear on ctrl or command +end
4399     case 36: if (event.ctrlKey || event.metaKey) {
4400     $.datepicker._gotoToday(event.target);
4401     }
4402     handled = event.ctrlKey || event.metaKey;
4403     break; // current on ctrl or command +home
4404     case 37: if (event.ctrlKey || event.metaKey) {
4405     $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), "D");
4406     }
4407     handled = event.ctrlKey || event.metaKey;
4408     // -1 day on ctrl or command +left
4409     if (event.originalEvent.altKey) {
4410     $.datepicker._adjustDate(event.target, (event.ctrlKey ?
4411     -$.datepicker._get(inst, "stepBigMonths") :
4412     -$.datepicker._get(inst, "stepMonths")), "M");
4413     }
4414     // next month/year on alt +left on Mac
4415     break;
4416     case 38: if (event.ctrlKey || event.metaKey) {
4417     $.datepicker._adjustDate(event.target, -7, "D");
4418     }
4419     handled = event.ctrlKey || event.metaKey;
4420     break; // -1 week on ctrl or command +up
4421     case 39: if (event.ctrlKey || event.metaKey) {
4422     $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), "D");
4423     }
4424     handled = event.ctrlKey || event.metaKey;
4425     // +1 day on ctrl or command +right
4426     if (event.originalEvent.altKey) {
4427     $.datepicker._adjustDate(event.target, (event.ctrlKey ?
4428     +$.datepicker._get(inst, "stepBigMonths") :
4429     +$.datepicker._get(inst, "stepMonths")), "M");
4430     }
4431     // next month/year on alt +right
4432     break;
4433     case 40: if (event.ctrlKey || event.metaKey) {
4434     $.datepicker._adjustDate(event.target, +7, "D");
4435     }
4436     handled = event.ctrlKey || event.metaKey;
4437     break; // +1 week on ctrl or command +down
4438     default: handled = false;
4439     }
4440     } else if (event.keyCode === 36 && event.ctrlKey) { // display the date picker on ctrl+home
4441     $.datepicker._showDatepicker(this);
4442     } else {
4443     handled = false;
4444     }
4445    
4446     if (handled) {
4447     event.preventDefault();
4448     event.stopPropagation();
4449     }
4450     },
4451    
4452     /* Filter entered characters - based on date format. */
4453     _doKeyPress: function(event) {
4454     var chars, chr,
4455     inst = $.datepicker._getInst(event.target);
4456    
4457     if ($.datepicker._get(inst, "constrainInput")) {
4458     chars = $.datepicker._possibleChars($.datepicker._get(inst, "dateFormat"));
4459     chr = String.fromCharCode(event.charCode == null ? event.keyCode : event.charCode);
4460     return event.ctrlKey || event.metaKey || (chr < " " || !chars || chars.indexOf(chr) > -1);
4461     }
4462     },
4463    
4464     /* Synchronise manual entry and field/alternate field. */
4465     _doKeyUp: function(event) {
4466     var date,
4467     inst = $.datepicker._getInst(event.target);
4468    
4469     if (inst.input.val() !== inst.lastVal) {
4470     try {
4471     date = $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"),
4472     (inst.input ? inst.input.val() : null),
4473     $.datepicker._getFormatConfig(inst));
4474    
4475     if (date) { // only if valid
4476     $.datepicker._setDateFromField(inst);
4477     $.datepicker._updateAlternate(inst);
4478     $.datepicker._updateDatepicker(inst);
4479     }
4480     }
4481     catch (err) {
4482     }
4483     }
4484     return true;
4485     },
4486    
4487     /* Pop-up the date picker for a given input field.
4488     * If false returned from beforeShow event handler do not show.
4489     * @param input element - the input field attached to the date picker or
4490     * event - if triggered by focus
4491     */
4492     _showDatepicker: function(input) {
4493     input = input.target || input;
4494     if (input.nodeName.toLowerCase() !== "input") { // find from button/image trigger
4495     input = $("input", input.parentNode)[0];
4496     }
4497    
4498     if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput === input) { // already here
4499     return;
4500     }
4501    
4502     var inst, beforeShow, beforeShowSettings, isFixed,
4503     offset, showAnim, duration;
4504    
4505     inst = $.datepicker._getInst(input);
4506     if ($.datepicker._curInst && $.datepicker._curInst !== inst) {
4507     $.datepicker._curInst.dpDiv.stop(true, true);
4508     if ( inst && $.datepicker._datepickerShowing ) {
4509     $.datepicker._hideDatepicker( $.datepicker._curInst.input[0] );
4510     }
4511     }
4512    
4513     beforeShow = $.datepicker._get(inst, "beforeShow");
4514     beforeShowSettings = beforeShow ? beforeShow.apply(input, [input, inst]) : {};
4515     if(beforeShowSettings === false){
4516     return;
4517     }
4518     datepicker_extendRemove(inst.settings, beforeShowSettings);
4519    
4520     inst.lastVal = null;
4521     $.datepicker._lastInput = input;
4522     $.datepicker._setDateFromField(inst);
4523    
4524     if ($.datepicker._inDialog) { // hide cursor
4525     input.value = "";
4526     }
4527     if (!$.datepicker._pos) { // position below input
4528     $.datepicker._pos = $.datepicker._findPos(input);
4529     $.datepicker._pos[1] += input.offsetHeight; // add the height
4530     }
4531    
4532     isFixed = false;
4533     $(input).parents().each(function() {
4534     isFixed |= $(this).css("position") === "fixed";
4535     return !isFixed;
4536     });
4537    
4538     offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]};
4539     $.datepicker._pos = null;
4540     //to avoid flashes on Firefox
4541     inst.dpDiv.empty();
4542     // determine sizing offscreen
4543     inst.dpDiv.css({position: "absolute", display: "block", top: "-1000px"});
4544     $.datepicker._updateDatepicker(inst);
4545     // fix width for dynamic number of date pickers
4546     // and adjust position before showing
4547     offset = $.datepicker._checkOffset(inst, offset, isFixed);
4548     inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ?
4549     "static" : (isFixed ? "fixed" : "absolute")), display: "none",
4550     left: offset.left + "px", top: offset.top + "px"});
4551    
4552     if (!inst.inline) {
4553     showAnim = $.datepicker._get(inst, "showAnim");
4554     duration = $.datepicker._get(inst, "duration");
4555     inst.dpDiv.css( "z-index", datepicker_getZindex( $( input ) ) + 1 );
4556     $.datepicker._datepickerShowing = true;
4557    
4558     if ( $.effects && $.effects.effect[ showAnim ] ) {
4559     inst.dpDiv.show(showAnim, $.datepicker._get(inst, "showOptions"), duration);
4560     } else {
4561     inst.dpDiv[showAnim || "show"](showAnim ? duration : null);
4562     }
4563    
4564     if ( $.datepicker._shouldFocusInput( inst ) ) {
4565     inst.input.focus();
4566     }
4567    
4568     $.datepicker._curInst = inst;
4569     }
4570     },
4571    
4572     /* Generate the date picker content. */
4573     _updateDatepicker: function(inst) {
4574     this.maxRows = 4; //Reset the max number of rows being displayed (see #7043)
4575     datepicker_instActive = inst; // for delegate hover events
4576     inst.dpDiv.empty().append(this._generateHTML(inst));
4577     this._attachHandlers(inst);
4578    
4579     var origyearshtml,
4580     numMonths = this._getNumberOfMonths(inst),
4581     cols = numMonths[1],
4582     width = 17,
4583     activeCell = inst.dpDiv.find( "." + this._dayOverClass + " a" );
4584    
4585     if ( activeCell.length > 0 ) {
4586     datepicker_handleMouseover.apply( activeCell.get( 0 ) );
4587     }
4588    
4589     inst.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width("");
4590     if (cols > 1) {
4591     inst.dpDiv.addClass("ui-datepicker-multi-" + cols).css("width", (width * cols) + "em");
4592     }
4593     inst.dpDiv[(numMonths[0] !== 1 || numMonths[1] !== 1 ? "add" : "remove") +
4594     "Class"]("ui-datepicker-multi");
4595     inst.dpDiv[(this._get(inst, "isRTL") ? "add" : "remove") +
4596     "Class"]("ui-datepicker-rtl");
4597    
4598     if (inst === $.datepicker._curInst && $.datepicker._datepickerShowing && $.datepicker._shouldFocusInput( inst ) ) {
4599     inst.input.focus();
4600     }
4601    
4602     // deffered render of the years select (to avoid flashes on Firefox)
4603     if( inst.yearshtml ){
4604     origyearshtml = inst.yearshtml;
4605     setTimeout(function(){
4606     //assure that inst.yearshtml didn't change.
4607     if( origyearshtml === inst.yearshtml && inst.yearshtml ){
4608     inst.dpDiv.find("select.ui-datepicker-year:first").replaceWith(inst.yearshtml);
4609     }
4610     origyearshtml = inst.yearshtml = null;
4611     }, 0);
4612     }
4613     },
4614    
4615     // #6694 - don't focus the input if it's already focused
4616     // this breaks the change event in IE
4617     // Support: IE and jQuery <1.9
4618     _shouldFocusInput: function( inst ) {
4619     return inst.input && inst.input.is( ":visible" ) && !inst.input.is( ":disabled" ) && !inst.input.is( ":focus" );
4620     },
4621    
4622     /* Check positioning to remain on screen. */
4623     _checkOffset: function(inst, offset, isFixed) {
4624     var dpWidth = inst.dpDiv.outerWidth(),
4625     dpHeight = inst.dpDiv.outerHeight(),
4626     inputWidth = inst.input ? inst.input.outerWidth() : 0,
4627     inputHeight = inst.input ? inst.input.outerHeight() : 0,
4628     viewWidth = document.documentElement.clientWidth + (isFixed ? 0 : $(document).scrollLeft()),
4629     viewHeight = document.documentElement.clientHeight + (isFixed ? 0 : $(document).scrollTop());
4630    
4631     offset.left -= (this._get(inst, "isRTL") ? (dpWidth - inputWidth) : 0);
4632     offset.left -= (isFixed && offset.left === inst.input.offset().left) ? $(document).scrollLeft() : 0;
4633     offset.top -= (isFixed && offset.top === (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;
4634    
4635     // now check if datepicker is showing outside window viewport - move to a better place if so.
4636     offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?
4637     Math.abs(offset.left + dpWidth - viewWidth) : 0);
4638     offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?
4639     Math.abs(dpHeight + inputHeight) : 0);
4640    
4641     return offset;
4642     },
4643    
4644     /* Find an object's position on the screen. */
4645     _findPos: function(obj) {
4646     var position,
4647     inst = this._getInst(obj),
4648     isRTL = this._get(inst, "isRTL");
4649    
4650     while (obj && (obj.type === "hidden" || obj.nodeType !== 1 || $.expr.filters.hidden(obj))) {
4651     obj = obj[isRTL ? "previousSibling" : "nextSibling"];
4652     }
4653    
4654     position = $(obj).offset();
4655     return [position.left, position.top];
4656     },
4657    
4658     /* Hide the date picker from view.
4659     * @param input element - the input field attached to the date picker
4660     */
4661     _hideDatepicker: function(input) {
4662     var showAnim, duration, postProcess, onClose,
4663     inst = this._curInst;
4664    
4665     if (!inst || (input && inst !== $.data(input, "datepicker"))) {
4666     return;
4667     }
4668    
4669     if (this._datepickerShowing) {
4670     showAnim = this._get(inst, "showAnim");
4671     duration = this._get(inst, "duration");
4672     postProcess = function() {
4673     $.datepicker._tidyDialog(inst);
4674     };
4675    
4676     // DEPRECATED: after BC for 1.8.x $.effects[ showAnim ] is not needed
4677     if ( $.effects && ( $.effects.effect[ showAnim ] || $.effects[ showAnim ] ) ) {
4678     inst.dpDiv.hide(showAnim, $.datepicker._get(inst, "showOptions"), duration, postProcess);
4679     } else {
4680     inst.dpDiv[(showAnim === "slideDown" ? "slideUp" :
4681     (showAnim === "fadeIn" ? "fadeOut" : "hide"))]((showAnim ? duration : null), postProcess);
4682     }
4683    
4684     if (!showAnim) {
4685     postProcess();
4686     }
4687     this._datepickerShowing = false;
4688    
4689     onClose = this._get(inst, "onClose");
4690     if (onClose) {
4691     onClose.apply((inst.input ? inst.input[0] : null), [(inst.input ? inst.input.val() : ""), inst]);
4692     }
4693    
4694     this._lastInput = null;
4695     if (this._inDialog) {
4696     this._dialogInput.css({ position: "absolute", left: "0", top: "-100px" });
4697     if ($.blockUI) {
4698     $.unblockUI();
4699     $("body").append(this.dpDiv);
4700     }
4701     }
4702     this._inDialog = false;
4703     }
4704     },
4705    
4706     /* Tidy up after a dialog display. */
4707     _tidyDialog: function(inst) {
4708     inst.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar");
4709     },
4710    
4711     /* Close date picker if clicked elsewhere. */
4712     _checkExternalClick: function(event) {
4713     if (!$.datepicker._curInst) {
4714     return;
4715     }
4716    
4717     var $target = $(event.target),
4718     inst = $.datepicker._getInst($target[0]);
4719    
4720     if ( ( ( $target[0].id !== $.datepicker._mainDivId &&
4721     $target.parents("#" + $.datepicker._mainDivId).length === 0 &&
4722     !$target.hasClass($.datepicker.markerClassName) &&
4723     !$target.closest("." + $.datepicker._triggerClass).length &&
4724     $.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI) ) ) ||
4725     ( $target.hasClass($.datepicker.markerClassName) && $.datepicker._curInst !== inst ) ) {
4726     $.datepicker._hideDatepicker();
4727     }
4728     },
4729    
4730     /* Adjust one of the date sub-fields. */
4731     _adjustDate: function(id, offset, period) {
4732     var target = $(id),
4733     inst = this._getInst(target[0]);
4734    
4735     if (this._isDisabledDatepicker(target[0])) {
4736     return;
4737     }
4738     this._adjustInstDate(inst, offset +
4739     (period === "M" ? this._get(inst, "showCurrentAtPos") : 0), // undo positioning
4740     period);
4741     this._updateDatepicker(inst);
4742     },
4743    
4744     /* Action for current link. */
4745     _gotoToday: function(id) {
4746     var date,
4747     target = $(id),
4748     inst = this._getInst(target[0]);
4749    
4750     if (this._get(inst, "gotoCurrent") && inst.currentDay) {
4751     inst.selectedDay = inst.currentDay;
4752     inst.drawMonth = inst.selectedMonth = inst.currentMonth;
4753     inst.drawYear = inst.selectedYear = inst.currentYear;
4754     } else {
4755     date = new Date();
4756     inst.selectedDay = date.getDate();
4757     inst.drawMonth = inst.selectedMonth = date.getMonth();
4758     inst.drawYear = inst.selectedYear = date.getFullYear();
4759     }
4760     this._notifyChange(inst);
4761     this._adjustDate(target);
4762     },
4763    
4764     /* Action for selecting a new month/year. */
4765     _selectMonthYear: function(id, select, period) {
4766     var target = $(id),
4767     inst = this._getInst(target[0]);
4768    
4769     inst["selected" + (period === "M" ? "Month" : "Year")] =
4770     inst["draw" + (period === "M" ? "Month" : "Year")] =
4771     parseInt(select.options[select.selectedIndex].value,10);
4772    
4773     this._notifyChange(inst);
4774     this._adjustDate(target);
4775     },
4776    
4777     /* Action for selecting a day. */
4778     _selectDay: function(id, month, year, td) {
4779     var inst,
4780     target = $(id);
4781    
4782     if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) {
4783     return;
4784     }
4785    
4786     inst = this._getInst(target[0]);
4787     inst.selectedDay = inst.currentDay = $("a", td).html();
4788     inst.selectedMonth = inst.currentMonth = month;
4789     inst.selectedYear = inst.currentYear = year;
4790     this._selectDate(id, this._formatDate(inst,
4791     inst.currentDay, inst.currentMonth, inst.currentYear));
4792     },
4793    
4794     /* Erase the input field and hide the date picker. */
4795     _clearDate: function(id) {
4796     var target = $(id);
4797     this._selectDate(target, "");
4798     },
4799    
4800     /* Update the input field with the selected date. */
4801     _selectDate: function(id, dateStr) {
4802     var onSelect,
4803     target = $(id),
4804     inst = this._getInst(target[0]);
4805    
4806     dateStr = (dateStr != null ? dateStr : this._formatDate(inst));
4807     if (inst.input) {
4808     inst.input.val(dateStr);
4809     }
4810     this._updateAlternate(inst);
4811    
4812     onSelect = this._get(inst, "onSelect");
4813     if (onSelect) {
4814     onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); // trigger custom callback
4815     } else if (inst.input) {
4816     inst.input.trigger("change"); // fire the change event
4817     }
4818    
4819     if (inst.inline){
4820     this._updateDatepicker(inst);
4821     } else {
4822     this._hideDatepicker();
4823     this._lastInput = inst.input[0];
4824     if (typeof(inst.input[0]) !== "object") {
4825     inst.input.focus(); // restore focus
4826     }
4827     this._lastInput = null;
4828     }
4829     },
4830    
4831     /* Update any alternate field to synchronise with the main field. */
4832     _updateAlternate: function(inst) {
4833     var altFormat, date, dateStr,
4834     altField = this._get(inst, "altField");
4835    
4836     if (altField) { // update alternate field too
4837     altFormat = this._get(inst, "altFormat") || this._get(inst, "dateFormat");
4838     date = this._getDate(inst);
4839     dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst));
4840     $(altField).each(function() { $(this).val(dateStr); });
4841     }
4842     },
4843    
4844     /* Set as beforeShowDay function to prevent selection of weekends.
4845     * @param date Date - the date to customise
4846     * @return [boolean, string] - is this date selectable?, what is its CSS class?
4847     */
4848     noWeekends: function(date) {
4849     var day = date.getDay();
4850     return [(day > 0 && day < 6), ""];
4851     },
4852    
4853     /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
4854     * @param date Date - the date to get the week for
4855     * @return number - the number of the week within the year that contains this date
4856     */
4857     iso8601Week: function(date) {
4858     var time,
4859     checkDate = new Date(date.getTime());
4860    
4861     // Find Thursday of this week starting on Monday
4862     checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7));
4863    
4864     time = checkDate.getTime();
4865     checkDate.setMonth(0); // Compare with Jan 1
4866     checkDate.setDate(1);
4867     return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
4868     },
4869    
4870     /* Parse a string value into a date object.
4871     * See formatDate below for the possible formats.
4872     *
4873     * @param format string - the expected format of the date
4874     * @param value string - the date in the above format
4875     * @param settings Object - attributes include:
4876     * shortYearCutoff number - the cutoff year for determining the century (optional)
4877     * dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
4878     * dayNames string[7] - names of the days from Sunday (optional)
4879     * monthNamesShort string[12] - abbreviated names of the months (optional)
4880     * monthNames string[12] - names of the months (optional)
4881     * @return Date - the extracted date value or null if value is blank
4882     */
4883     parseDate: function (format, value, settings) {
4884     if (format == null || value == null) {
4885     throw "Invalid arguments";
4886     }
4887    
4888     value = (typeof value === "object" ? value.toString() : value + "");
4889     if (value === "") {
4890     return null;
4891     }
4892    
4893     var iFormat, dim, extra,
4894     iValue = 0,
4895     shortYearCutoffTemp = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff,
4896     shortYearCutoff = (typeof shortYearCutoffTemp !== "string" ? shortYearCutoffTemp :
4897     new Date().getFullYear() % 100 + parseInt(shortYearCutoffTemp, 10)),
4898     dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort,
4899     dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames,
4900     monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort,
4901     monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames,
4902     year = -1,
4903     month = -1,
4904     day = -1,
4905     doy = -1,
4906     literal = false,
4907     date,
4908     // Check whether a format character is doubled
4909     lookAhead = function(match) {
4910     var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match);
4911     if (matches) {
4912     iFormat++;
4913     }
4914     return matches;
4915     },
4916     // Extract a number from the string value
4917     getNumber = function(match) {
4918     var isDoubled = lookAhead(match),
4919     size = (match === "@" ? 14 : (match === "!" ? 20 :
4920     (match === "y" && isDoubled ? 4 : (match === "o" ? 3 : 2)))),
4921     minSize = (match === "y" ? size : 1),
4922     digits = new RegExp("^\\d{" + minSize + "," + size + "}"),
4923     num = value.substring(iValue).match(digits);
4924     if (!num) {
4925     throw "Missing number at position " + iValue;
4926     }
4927     iValue += num[0].length;
4928     return parseInt(num[0], 10);
4929     },
4930     // Extract a name from the string value and convert to an index
4931     getName = function(match, shortNames, longNames) {
4932     var index = -1,
4933     names = $.map(lookAhead(match) ? longNames : shortNames, function (v, k) {
4934     return [ [k, v] ];
4935     }).sort(function (a, b) {
4936     return -(a[1].length - b[1].length);
4937     });
4938    
4939     $.each(names, function (i, pair) {
4940     var name = pair[1];
4941     if (value.substr(iValue, name.length).toLowerCase() === name.toLowerCase()) {
4942     index = pair[0];
4943     iValue += name.length;
4944     return false;
4945     }
4946     });
4947     if (index !== -1) {
4948     return index + 1;
4949     } else {
4950     throw "Unknown name at position " + iValue;
4951     }
4952     },
4953     // Confirm that a literal character matches the string value
4954     checkLiteral = function() {
4955     if (value.charAt(iValue) !== format.charAt(iFormat)) {
4956     throw "Unexpected literal at position " + iValue;
4957     }
4958     iValue++;
4959     };
4960    
4961     for (iFormat = 0; iFormat < format.length; iFormat++) {
4962     if (literal) {
4963     if (format.charAt(iFormat) === "'" && !lookAhead("'")) {
4964     literal = false;
4965     } else {
4966     checkLiteral();
4967     }
4968     } else {
4969     switch (format.charAt(iFormat)) {
4970     case "d":
4971     day = getNumber("d");
4972     break;
4973     case "D":
4974     getName("D", dayNamesShort, dayNames);
4975     break;
4976     case "o":
4977     doy = getNumber("o");
4978     break;
4979     case "m":
4980     month = getNumber("m");
4981     break;
4982     case "M":
4983     month = getName("M", monthNamesShort, monthNames);
4984     break;
4985     case "y":
4986     year = getNumber("y");
4987     break;
4988     case "@":
4989     date = new Date(getNumber("@"));
4990     year = date.getFullYear();
4991     month = date.getMonth() + 1;
4992     day = date.getDate();
4993     break;
4994     case "!":
4995     date = new Date((getNumber("!") - this._ticksTo1970) / 10000);
4996     year = date.getFullYear();
4997     month = date.getMonth() + 1;
4998     day = date.getDate();
4999     break;
5000     case "'":
5001     if (lookAhead("'")){
5002     checkLiteral();
5003     } else {
5004     literal = true;
5005     }
5006     break;
5007     default:
5008     checkLiteral();
5009     }
5010     }
5011     }
5012    
5013     if (iValue < value.length){
5014     extra = value.substr(iValue);
5015     if (!/^\s+/.test(extra)) {
5016     throw "Extra/unparsed characters found in date: " + extra;
5017     }
5018     }
5019    
5020     if (year === -1) {
5021     year = new Date().getFullYear();
5022     } else if (year < 100) {
5023     year += new Date().getFullYear() - new Date().getFullYear() % 100 +
5024     (year <= shortYearCutoff ? 0 : -100);
5025     }
5026    
5027     if (doy > -1) {
5028     month = 1;
5029     day = doy;
5030     do {
5031     dim = this._getDaysInMonth(year, month - 1);
5032     if (day <= dim) {
5033     break;
5034     }
5035     month++;
5036     day -= dim;
5037     } while (true);
5038     }
5039    
5040     date = this._daylightSavingAdjust(new Date(year, month - 1, day));
5041     if (date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day) {
5042     throw "Invalid date"; // E.g. 31/02/00
5043     }
5044     return date;
5045     },
5046    
5047     /* Standard date formats. */
5048     ATOM: "yy-mm-dd", // RFC 3339 (ISO 8601)
5049     COOKIE: "D, dd M yy",
5050     ISO_8601: "yy-mm-dd",
5051     RFC_822: "D, d M y",
5052     RFC_850: "DD, dd-M-y",
5053     RFC_1036: "D, d M y",
5054     RFC_1123: "D, d M yy",
5055     RFC_2822: "D, d M yy",
5056     RSS: "D, d M y", // RFC 822
5057     TICKS: "!",
5058     TIMESTAMP: "@",
5059     W3C: "yy-mm-dd", // ISO 8601
5060    
5061     _ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) +
5062     Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000),
5063    
5064     /* Format a date object into a string value.
5065     * The format can be combinations of the following:
5066     * d - day of month (no leading zero)
5067     * dd - day of month (two digit)
5068     * o - day of year (no leading zeros)
5069     * oo - day of year (three digit)
5070     * D - day name short
5071     * DD - day name long
5072     * m - month of year (no leading zero)
5073     * mm - month of year (two digit)
5074     * M - month name short
5075     * MM - month name long
5076     * y - year (two digit)
5077     * yy - year (four digit)
5078     * @ - Unix timestamp (ms since 01/01/1970)
5079     * ! - Windows ticks (100ns since 01/01/0001)
5080     * "..." - literal text
5081     * '' - single quote
5082     *
5083     * @param format string - the desired format of the date
5084     * @param date Date - the date value to format
5085     * @param settings Object - attributes include:
5086     * dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
5087     * dayNames string[7] - names of the days from Sunday (optional)
5088     * monthNamesShort string[12] - abbreviated names of the months (optional)
5089     * monthNames string[12] - names of the months (optional)
5090     * @return string - the date in the above format
5091     */
5092     formatDate: function (format, date, settings) {
5093     if (!date) {
5094     return "";
5095     }
5096    
5097     var iFormat,
5098     dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort,
5099     dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames,
5100     monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort,
5101     monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames,
5102     // Check whether a format character is doubled
5103     lookAhead = function(match) {
5104     var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match);
5105     if (matches) {
5106     iFormat++;
5107     }
5108     return matches;
5109     },
5110     // Format a number, with leading zero if necessary
5111     formatNumber = function(match, value, len) {
5112     var num = "" + value;
5113     if (lookAhead(match)) {
5114     while (num.length < len) {
5115     num = "0" + num;
5116     }
5117     }
5118     return num;
5119     },
5120     // Format a name, short or long as requested
5121     formatName = function(match, value, shortNames, longNames) {
5122     return (lookAhead(match) ? longNames[value] : shortNames[value]);
5123     },
5124     output = "",
5125     literal = false;
5126    
5127     if (date) {
5128     for (iFormat = 0; iFormat < format.length; iFormat++) {
5129     if (literal) {
5130     if (format.charAt(iFormat) === "'" && !lookAhead("'")) {
5131     literal = false;
5132     } else {
5133     output += format.charAt(iFormat);
5134     }
5135     } else {
5136     switch (format.charAt(iFormat)) {
5137     case "d":
5138     output += formatNumber("d", date.getDate(), 2);
5139     break;
5140     case "D":
5141     output += formatName("D", date.getDay(), dayNamesShort, dayNames);
5142     break;
5143     case "o":
5144     output += formatNumber("o",
5145     Math.round((new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000), 3);
5146     break;
5147     case "m":
5148     output += formatNumber("m", date.getMonth() + 1, 2);
5149     break;
5150     case "M":
5151     output += formatName("M", date.getMonth(), monthNamesShort, monthNames);
5152     break;
5153     case "y":
5154     output += (lookAhead("y") ? date.getFullYear() :
5155     (date.getYear() % 100 < 10 ? "0" : "") + date.getYear() % 100);
5156     break;
5157     case "@":
5158     output += date.getTime();
5159     break;
5160     case "!":
5161     output += date.getTime() * 10000 + this._ticksTo1970;
5162     break;
5163     case "'":
5164     if (lookAhead("'")) {
5165     output += "'";
5166     } else {
5167     literal = true;
5168     }
5169     break;
5170     default:
5171     output += format.charAt(iFormat);
5172     }
5173     }
5174     }
5175     }
5176     return output;
5177     },
5178    
5179     /* Extract all possible characters from the date format. */
5180     _possibleChars: function (format) {
5181     var iFormat,
5182     chars = "",
5183     literal = false,
5184     // Check whether a format character is doubled
5185     lookAhead = function(match) {
5186     var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match);
5187     if (matches) {
5188     iFormat++;
5189     }
5190     return matches;
5191     };
5192    
5193     for (iFormat = 0; iFormat < format.length; iFormat++) {
5194     if (literal) {
5195     if (format.charAt(iFormat) === "'" && !lookAhead("'")) {
5196     literal = false;
5197     } else {
5198     chars += format.charAt(iFormat);
5199     }
5200     } else {
5201     switch (format.charAt(iFormat)) {
5202     case "d": case "m": case "y": case "@":
5203     chars += "0123456789";
5204     break;
5205     case "D": case "M":
5206     return null; // Accept anything
5207     case "'":
5208     if (lookAhead("'")) {
5209     chars += "'";
5210     } else {
5211     literal = true;
5212     }
5213     break;
5214     default:
5215     chars += format.charAt(iFormat);
5216     }
5217     }
5218     }
5219     return chars;
5220     },
5221    
5222     /* Get a setting value, defaulting if necessary. */
5223     _get: function(inst, name) {
5224     return inst.settings[name] !== undefined ?
5225     inst.settings[name] : this._defaults[name];
5226     },
5227    
5228     /* Parse existing date and initialise date picker. */
5229     _setDateFromField: function(inst, noDefault) {
5230     if (inst.input.val() === inst.lastVal) {
5231     return;
5232     }
5233    
5234     var dateFormat = this._get(inst, "dateFormat"),
5235     dates = inst.lastVal = inst.input ? inst.input.val() : null,
5236     defaultDate = this._getDefaultDate(inst),
5237     date = defaultDate,
5238     settings = this._getFormatConfig(inst);
5239    
5240     try {
5241     date = this.parseDate(dateFormat, dates, settings) || defaultDate;
5242     } catch (event) {
5243     dates = (noDefault ? "" : dates);
5244     }
5245     inst.selectedDay = date.getDate();
5246     inst.drawMonth = inst.selectedMonth = date.getMonth();
5247     inst.drawYear = inst.selectedYear = date.getFullYear();
5248     inst.currentDay = (dates ? date.getDate() : 0);
5249     inst.currentMonth = (dates ? date.getMonth() : 0);
5250     inst.currentYear = (dates ? date.getFullYear() : 0);
5251     this._adjustInstDate(inst);
5252     },
5253    
5254     /* Retrieve the default date shown on opening. */
5255     _getDefaultDate: function(inst) {
5256     return this._restrictMinMax(inst,
5257     this._determineDate(inst, this._get(inst, "defaultDate"), new Date()));
5258     },
5259    
5260     /* A date may be specified as an exact value or a relative one. */
5261     _determineDate: function(inst, date, defaultDate) {
5262     var offsetNumeric = function(offset) {
5263     var date = new Date();
5264     date.setDate(date.getDate() + offset);
5265     return date;
5266     },
5267     offsetString = function(offset) {
5268     try {
5269     return $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"),
5270     offset, $.datepicker._getFormatConfig(inst));
5271     }
5272     catch (e) {
5273     // Ignore
5274     }
5275    
5276     var date = (offset.toLowerCase().match(/^c/) ?
5277     $.datepicker._getDate(inst) : null) || new Date(),
5278     year = date.getFullYear(),
5279     month = date.getMonth(),
5280     day = date.getDate(),
5281     pattern = /([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,
5282     matches = pattern.exec(offset);
5283    
5284     while (matches) {
5285     switch (matches[2] || "d") {
5286     case "d" : case "D" :
5287     day += parseInt(matches[1],10); break;
5288     case "w" : case "W" :
5289     day += parseInt(matches[1],10) * 7; break;
5290     case "m" : case "M" :
5291     month += parseInt(matches[1],10);
5292     day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
5293     break;
5294     case "y": case "Y" :
5295     year += parseInt(matches[1],10);
5296     day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
5297     break;
5298     }
5299     matches = pattern.exec(offset);
5300     }
5301     return new Date(year, month, day);
5302     },
5303     newDate = (date == null || date === "" ? defaultDate : (typeof date === "string" ? offsetString(date) :
5304     (typeof date === "number" ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : new Date(date.getTime()))));
5305    
5306     newDate = (newDate && newDate.toString() === "Invalid Date" ? defaultDate : newDate);
5307     if (newDate) {
5308     newDate.setHours(0);
5309     newDate.setMinutes(0);
5310     newDate.setSeconds(0);
5311     newDate.setMilliseconds(0);
5312     }
5313     return this._daylightSavingAdjust(newDate);
5314     },
5315    
5316     /* Handle switch to/from daylight saving.
5317     * Hours may be non-zero on daylight saving cut-over:
5318     * > 12 when midnight changeover, but then cannot generate
5319     * midnight datetime, so jump to 1AM, otherwise reset.
5320     * @param date (Date) the date to check
5321     * @return (Date) the corrected date
5322     */
5323     _daylightSavingAdjust: function(date) {
5324     if (!date) {
5325     return null;
5326     }
5327     date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
5328     return date;
5329     },
5330    
5331     /* Set the date(s) directly. */
5332     _setDate: function(inst, date, noChange) {
5333     var clear = !date,
5334     origMonth = inst.selectedMonth,
5335     origYear = inst.selectedYear,
5336     newDate = this._restrictMinMax(inst, this._determineDate(inst, date, new Date()));
5337    
5338     inst.selectedDay = inst.currentDay = newDate.getDate();
5339     inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth();
5340     inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear();
5341     if ((origMonth !== inst.selectedMonth || origYear !== inst.selectedYear) && !noChange) {
5342     this._notifyChange(inst);
5343     }
5344     this._adjustInstDate(inst);
5345     if (inst.input) {
5346     inst.input.val(clear ? "" : this._formatDate(inst));
5347     }
5348     },
5349    
5350     /* Retrieve the date(s) directly. */
5351     _getDate: function(inst) {
5352     var startDate = (!inst.currentYear || (inst.input && inst.input.val() === "") ? null :
5353     this._daylightSavingAdjust(new Date(
5354     inst.currentYear, inst.currentMonth, inst.currentDay)));
5355     return startDate;
5356     },
5357    
5358     /* Attach the onxxx handlers. These are declared statically so
5359     * they work with static code transformers like Caja.
5360     */
5361     _attachHandlers: function(inst) {
5362     var stepMonths = this._get(inst, "stepMonths"),
5363     id = "#" + inst.id.replace( /\\\\/g, "\\" );
5364     inst.dpDiv.find("[data-handler]").map(function () {
5365     var handler = {
5366     prev: function () {
5367     $.datepicker._adjustDate(id, -stepMonths, "M");
5368     },
5369     next: function () {
5370     $.datepicker._adjustDate(id, +stepMonths, "M");
5371     },
5372     hide: function () {
5373     $.datepicker._hideDatepicker();
5374     },
5375     today: function () {
5376     $.datepicker._gotoToday(id);
5377     },
5378     selectDay: function () {
5379     $.datepicker._selectDay(id, +this.getAttribute("data-month"), +this.getAttribute("data-year"), this);
5380     return false;
5381     },
5382     selectMonth: function () {
5383     $.datepicker._selectMonthYear(id, this, "M");
5384     return false;
5385     },
5386     selectYear: function () {
5387     $.datepicker._selectMonthYear(id, this, "Y");
5388     return false;
5389     }
5390     };
5391     $(this).bind(this.getAttribute("data-event"), handler[this.getAttribute("data-handler")]);
5392     });
5393     },
5394    
5395     /* Generate the HTML for the current state of the date picker. */
5396     _generateHTML: function(inst) {
5397     var maxDraw, prevText, prev, nextText, next, currentText, gotoDate,
5398     controls, buttonPanel, firstDay, showWeek, dayNames, dayNamesMin,
5399     monthNames, monthNamesShort, beforeShowDay, showOtherMonths,
5400     selectOtherMonths, defaultDate, html, dow, row, group, col, selectedDate,
5401     cornerClass, calender, thead, day, daysInMonth, leadDays, curRows, numRows,
5402     printDate, dRow, tbody, daySettings, otherMonth, unselectable,
5403     tempDate = new Date(),
5404     today = this._daylightSavingAdjust(
5405     new Date(tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate())), // clear time
5406     isRTL = this._get(inst, "isRTL"),
5407     showButtonPanel = this._get(inst, "showButtonPanel"),
5408     hideIfNoPrevNext = this._get(inst, "hideIfNoPrevNext"),
5409     navigationAsDateFormat = this._get(inst, "navigationAsDateFormat"),
5410     numMonths = this._getNumberOfMonths(inst),
5411     showCurrentAtPos = this._get(inst, "showCurrentAtPos"),
5412     stepMonths = this._get(inst, "stepMonths"),
5413     isMultiMonth = (numMonths[0] !== 1 || numMonths[1] !== 1),
5414     currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) :
5415     new Date(inst.currentYear, inst.currentMonth, inst.currentDay))),
5416     minDate = this._getMinMaxDate(inst, "min"),
5417     maxDate = this._getMinMaxDate(inst, "max"),
5418     drawMonth = inst.drawMonth - showCurrentAtPos,
5419     drawYear = inst.drawYear;
5420    
5421     if (drawMonth < 0) {
5422     drawMonth += 12;
5423     drawYear--;
5424     }
5425     if (maxDate) {
5426     maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),
5427     maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate()));
5428     maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);
5429     while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {
5430     drawMonth--;
5431     if (drawMonth < 0) {
5432     drawMonth = 11;
5433     drawYear--;
5434     }
5435     }
5436     }
5437     inst.drawMonth = drawMonth;
5438     inst.drawYear = drawYear;
5439    
5440     prevText = this._get(inst, "prevText");
5441     prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText,
5442     this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),
5443     this._getFormatConfig(inst)));
5444    
5445     prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?
5446     "<a class='ui-datepicker-prev ui-corner-all' data-handler='prev' data-event='click'" +
5447     " title='" + prevText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "e" : "w") + "'>" + prevText + "</span></a>" :
5448     (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>"));
5449    
5450     nextText = this._get(inst, "nextText");
5451     nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText,
5452     this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),
5453     this._getFormatConfig(inst)));
5454    
5455     next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?
5456     "<a class='ui-datepicker-next ui-corner-all' data-handler='next' data-event='click'" +
5457     " title='" + nextText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "w" : "e") + "'>" + nextText + "</span></a>" :
5458     (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>"));
5459    
5460     currentText = this._get(inst, "currentText");
5461     gotoDate = (this._get(inst, "gotoCurrent") && inst.currentDay ? currentDate : today);
5462     currentText = (!navigationAsDateFormat ? currentText :
5463     this.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));
5464    
5465     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'>" +
5466     this._get(inst, "closeText") + "</button>" : "");
5467    
5468     buttonPanel = (showButtonPanel) ? "<div class='ui-datepicker-buttonpane ui-widget-content'>" + (isRTL ? controls : "") +
5469     (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'" +
5470     ">" + currentText + "</button>" : "") + (isRTL ? "" : controls) + "</div>" : "";
5471    
5472     firstDay = parseInt(this._get(inst, "firstDay"),10);
5473     firstDay = (isNaN(firstDay) ? 0 : firstDay);
5474    
5475     showWeek = this._get(inst, "showWeek");
5476     dayNames = this._get(inst, "dayNames");
5477     dayNamesMin = this._get(inst, "dayNamesMin");
5478     monthNames = this._get(inst, "monthNames");
5479     monthNamesShort = this._get(inst, "monthNamesShort");
5480     beforeShowDay = this._get(inst, "beforeShowDay");
5481     showOtherMonths = this._get(inst, "showOtherMonths");
5482     selectOtherMonths = this._get(inst, "selectOtherMonths");
5483     defaultDate = this._getDefaultDate(inst);
5484     html = "";
5485     dow;
5486     for (row = 0; row < numMonths[0]; row++) {
5487     group = "";
5488     this.maxRows = 4;
5489     for (col = 0; col < numMonths[1]; col++) {
5490     selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay));
5491     cornerClass = " ui-corner-all";
5492     calender = "";
5493     if (isMultiMonth) {
5494     calender += "<div class='ui-datepicker-group";
5495     if (numMonths[1] > 1) {
5496     switch (col) {
5497     case 0: calender += " ui-datepicker-group-first";
5498     cornerClass = " ui-corner-" + (isRTL ? "right" : "left"); break;
5499     case numMonths[1]-1: calender += " ui-datepicker-group-last";
5500     cornerClass = " ui-corner-" + (isRTL ? "left" : "right"); break;
5501     default: calender += " ui-datepicker-group-middle"; cornerClass = ""; break;
5502     }
5503     }
5504     calender += "'>";
5505     }
5506     calender += "<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix" + cornerClass + "'>" +
5507     (/all|left/.test(cornerClass) && row === 0 ? (isRTL ? next : prev) : "") +
5508     (/all|right/.test(cornerClass) && row === 0 ? (isRTL ? prev : next) : "") +
5509     this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,
5510     row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers
5511     "</div><table class='ui-datepicker-calendar'><thead>" +
5512     "<tr>";
5513     thead = (showWeek ? "<th class='ui-datepicker-week-col'>" + this._get(inst, "weekHeader") + "</th>" : "");
5514     for (dow = 0; dow < 7; dow++) { // days of the week
5515     day = (dow + firstDay) % 7;
5516     thead += "<th scope='col'" + ((dow + firstDay + 6) % 7 >= 5 ? " class='ui-datepicker-week-end'" : "") + ">" +
5517     "<span title='" + dayNames[day] + "'>" + dayNamesMin[day] + "</span></th>";
5518     }
5519     calender += thead + "</tr></thead><tbody>";
5520     daysInMonth = this._getDaysInMonth(drawYear, drawMonth);
5521     if (drawYear === inst.selectedYear && drawMonth === inst.selectedMonth) {
5522     inst.selectedDay = Math.min(inst.selectedDay, daysInMonth);
5523     }
5524     leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;
5525     curRows = Math.ceil((leadDays + daysInMonth) / 7); // calculate the number of rows to generate
5526     numRows = (isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows); //If multiple months, use the higher number of rows (see #7043)
5527     this.maxRows = numRows;
5528     printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
5529     for (dRow = 0; dRow < numRows; dRow++) { // create date picker rows
5530     calender += "<tr>";
5531     tbody = (!showWeek ? "" : "<td class='ui-datepicker-week-col'>" +
5532     this._get(inst, "calculateWeek")(printDate) + "</td>");
5533     for (dow = 0; dow < 7; dow++) { // create date picker days
5534     daySettings = (beforeShowDay ?
5535     beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, ""]);
5536     otherMonth = (printDate.getMonth() !== drawMonth);
5537     unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] ||
5538     (minDate && printDate < minDate) || (maxDate && printDate > maxDate);
5539     tbody += "<td class='" +
5540     ((dow + firstDay + 6) % 7 >= 5 ? " ui-datepicker-week-end" : "") + // highlight weekends
5541     (otherMonth ? " ui-datepicker-other-month" : "") + // highlight days from other months
5542     ((printDate.getTime() === selectedDate.getTime() && drawMonth === inst.selectedMonth && inst._keyEvent) || // user pressed key
5543     (defaultDate.getTime() === printDate.getTime() && defaultDate.getTime() === selectedDate.getTime()) ?
5544     // or defaultDate is current printedDate and defaultDate is selectedDate
5545     " " + this._dayOverClass : "") + // highlight selected day
5546     (unselectable ? " " + this._unselectableClass + " ui-state-disabled": "") + // highlight unselectable days
5547     (otherMonth && !showOtherMonths ? "" : " " + daySettings[1] + // highlight custom dates
5548     (printDate.getTime() === currentDate.getTime() ? " " + this._currentClass : "") + // highlight selected day
5549     (printDate.getTime() === today.getTime() ? " ui-datepicker-today" : "")) + "'" + // highlight today (if different)
5550     ((!otherMonth || showOtherMonths) && daySettings[2] ? " title='" + daySettings[2].replace(/'/g, "&#39;") + "'" : "") + // cell title
5551     (unselectable ? "" : " data-handler='selectDay' data-event='click' data-month='" + printDate.getMonth() + "' data-year='" + printDate.getFullYear() + "'") + ">" + // actions
5552     (otherMonth && !showOtherMonths ? "&#xa0;" : // display for other months
5553     (unselectable ? "<span class='ui-state-default'>" + printDate.getDate() + "</span>" : "<a class='ui-state-default" +
5554     (printDate.getTime() === today.getTime() ? " ui-state-highlight" : "") +
5555     (printDate.getTime() === currentDate.getTime() ? " ui-state-active" : "") + // highlight selected day
5556     (otherMonth ? " ui-priority-secondary" : "") + // distinguish dates from other months
5557     "' href='#'>" + printDate.getDate() + "</a>")) + "</td>"; // display selectable date
5558     printDate.setDate(printDate.getDate() + 1);
5559     printDate = this._daylightSavingAdjust(printDate);
5560     }
5561     calender += tbody + "</tr>";
5562     }
5563     drawMonth++;
5564     if (drawMonth > 11) {
5565     drawMonth = 0;
5566     drawYear++;
5567     }
5568     calender += "</tbody></table>" + (isMultiMonth ? "</div>" +
5569     ((numMonths[0] > 0 && col === numMonths[1]-1) ? "<div class='ui-datepicker-row-break'></div>" : "") : "");
5570     group += calender;
5571     }
5572     html += group;
5573     }
5574     html += buttonPanel;
5575     inst._keyEvent = false;
5576     return html;
5577     },
5578    
5579     /* Generate the month and year header. */
5580     _generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate,
5581     secondary, monthNames, monthNamesShort) {
5582    
5583     var inMinYear, inMaxYear, month, years, thisYear, determineYear, year, endYear,
5584     changeMonth = this._get(inst, "changeMonth"),
5585     changeYear = this._get(inst, "changeYear"),
5586     showMonthAfterYear = this._get(inst, "showMonthAfterYear"),
5587     html = "<div class='ui-datepicker-title'>",
5588     monthHtml = "";
5589    
5590     // month selection
5591     if (secondary || !changeMonth) {
5592     monthHtml += "<span class='ui-datepicker-month'>" + monthNames[drawMonth] + "</span>";
5593     } else {
5594     inMinYear = (minDate && minDate.getFullYear() === drawYear);
5595     inMaxYear = (maxDate && maxDate.getFullYear() === drawYear);
5596     monthHtml += "<select class='ui-datepicker-month' data-handler='selectMonth' data-event='change'>";
5597     for ( month = 0; month < 12; month++) {
5598     if ((!inMinYear || month >= minDate.getMonth()) && (!inMaxYear || month <= maxDate.getMonth())) {
5599     monthHtml += "<option value='" + month + "'" +
5600     (month === drawMonth ? " selected='selected'" : "") +
5601     ">" + monthNamesShort[month] + "</option>";
5602     }
5603     }
5604     monthHtml += "</select>";
5605     }
5606    
5607     if (!showMonthAfterYear) {
5608     html += monthHtml + (secondary || !(changeMonth && changeYear) ? "&#xa0;" : "");
5609     }
5610    
5611     // year selection
5612     if ( !inst.yearshtml ) {
5613     inst.yearshtml = "";
5614     if (secondary || !changeYear) {
5615     html += "<span class='ui-datepicker-year'>" + drawYear + "</span>";
5616     } else {
5617     // determine range of years to display
5618     years = this._get(inst, "yearRange").split(":");
5619     thisYear = new Date().getFullYear();
5620     determineYear = function(value) {
5621     var year = (value.match(/c[+\-].*/) ? drawYear + parseInt(value.substring(1), 10) :
5622     (value.match(/[+\-].*/) ? thisYear + parseInt(value, 10) :
5623     parseInt(value, 10)));
5624     return (isNaN(year) ? thisYear : year);
5625     };
5626     year = determineYear(years[0]);
5627     endYear = Math.max(year, determineYear(years[1] || ""));
5628     year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
5629     endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
5630     inst.yearshtml += "<select class='ui-datepicker-year' data-handler='selectYear' data-event='change'>";
5631     for (; year <= endYear; year++) {
5632     inst.yearshtml += "<option value='" + year + "'" +
5633     (year === drawYear ? " selected='selected'" : "") +
5634     ">" + year + "</option>";
5635     }
5636     inst.yearshtml += "</select>";
5637    
5638     html += inst.yearshtml;
5639     inst.yearshtml = null;
5640     }
5641     }
5642    
5643     html += this._get(inst, "yearSuffix");
5644     if (showMonthAfterYear) {
5645     html += (secondary || !(changeMonth && changeYear) ? "&#xa0;" : "") + monthHtml;
5646     }
5647     html += "</div>"; // Close datepicker_header
5648     return html;
5649     },
5650    
5651     /* Adjust one of the date sub-fields. */
5652     _adjustInstDate: function(inst, offset, period) {
5653     var year = inst.drawYear + (period === "Y" ? offset : 0),
5654     month = inst.drawMonth + (period === "M" ? offset : 0),
5655     day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) + (period === "D" ? offset : 0),
5656     date = this._restrictMinMax(inst, this._daylightSavingAdjust(new Date(year, month, day)));
5657    
5658     inst.selectedDay = date.getDate();
5659     inst.drawMonth = inst.selectedMonth = date.getMonth();
5660     inst.drawYear = inst.selectedYear = date.getFullYear();
5661     if (period === "M" || period === "Y") {
5662     this._notifyChange(inst);
5663     }
5664     },
5665    
5666     /* Ensure a date is within any min/max bounds. */
5667     _restrictMinMax: function(inst, date) {
5668     var minDate = this._getMinMaxDate(inst, "min"),
5669     maxDate = this._getMinMaxDate(inst, "max"),
5670     newDate = (minDate && date < minDate ? minDate : date);
5671     return (maxDate && newDate > maxDate ? maxDate : newDate);
5672     },
5673    
5674     /* Notify change of month/year. */
5675     _notifyChange: function(inst) {
5676     var onChange = this._get(inst, "onChangeMonthYear");
5677     if (onChange) {
5678     onChange.apply((inst.input ? inst.input[0] : null),
5679     [inst.selectedYear, inst.selectedMonth + 1, inst]);
5680     }
5681     },
5682    
5683     /* Determine the number of months to show. */
5684     _getNumberOfMonths: function(inst) {
5685     var numMonths = this._get(inst, "numberOfMonths");
5686     return (numMonths == null ? [1, 1] : (typeof numMonths === "number" ? [1, numMonths] : numMonths));
5687     },
5688    
5689     /* Determine the current maximum date - ensure no time components are set. */
5690     _getMinMaxDate: function(inst, minMax) {
5691     return this._determineDate(inst, this._get(inst, minMax + "Date"), null);
5692     },
5693    
5694     /* Find the number of days in a given month. */
5695     _getDaysInMonth: function(year, month) {
5696     return 32 - this._daylightSavingAdjust(new Date(year, month, 32)).getDate();
5697     },
5698    
5699     /* Find the day of the week of the first of a month. */
5700     _getFirstDayOfMonth: function(year, month) {
5701     return new Date(year, month, 1).getDay();
5702     },
5703    
5704     /* Determines if we should allow a "next/prev" month display change. */
5705     _canAdjustMonth: function(inst, offset, curYear, curMonth) {
5706     var numMonths = this._getNumberOfMonths(inst),
5707     date = this._daylightSavingAdjust(new Date(curYear,
5708     curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1));
5709    
5710     if (offset < 0) {
5711     date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
5712     }
5713     return this._isInRange(inst, date);
5714     },
5715    
5716     /* Is the given date in the accepted range? */
5717     _isInRange: function(inst, date) {
5718     var yearSplit, currentYear,
5719     minDate = this._getMinMaxDate(inst, "min"),
5720     maxDate = this._getMinMaxDate(inst, "max"),
5721     minYear = null,
5722     maxYear = null,
5723     years = this._get(inst, "yearRange");
5724     if (years){
5725     yearSplit = years.split(":");
5726     currentYear = new Date().getFullYear();
5727     minYear = parseInt(yearSplit[0], 10);
5728     maxYear = parseInt(yearSplit[1], 10);
5729     if ( yearSplit[0].match(/[+\-].*/) ) {
5730     minYear += currentYear;
5731     }
5732     if ( yearSplit[1].match(/[+\-].*/) ) {
5733     maxYear += currentYear;
5734     }
5735     }
5736    
5737     return ((!minDate || date.getTime() >= minDate.getTime()) &&
5738     (!maxDate || date.getTime() <= maxDate.getTime()) &&
5739     (!minYear || date.getFullYear() >= minYear) &&
5740     (!maxYear || date.getFullYear() <= maxYear));
5741     },
5742    
5743     /* Provide the configuration settings for formatting/parsing. */
5744     _getFormatConfig: function(inst) {
5745     var shortYearCutoff = this._get(inst, "shortYearCutoff");
5746     shortYearCutoff = (typeof shortYearCutoff !== "string" ? shortYearCutoff :
5747     new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
5748     return {shortYearCutoff: shortYearCutoff,
5749     dayNamesShort: this._get(inst, "dayNamesShort"), dayNames: this._get(inst, "dayNames"),
5750     monthNamesShort: this._get(inst, "monthNamesShort"), monthNames: this._get(inst, "monthNames")};
5751     },
5752    
5753     /* Format the given date for display. */
5754     _formatDate: function(inst, day, month, year) {
5755     if (!day) {
5756     inst.currentDay = inst.selectedDay;
5757     inst.currentMonth = inst.selectedMonth;
5758     inst.currentYear = inst.selectedYear;
5759     }
5760     var date = (day ? (typeof day === "object" ? day :
5761     this._daylightSavingAdjust(new Date(year, month, day))) :
5762     this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
5763     return this.formatDate(this._get(inst, "dateFormat"), date, this._getFormatConfig(inst));
5764     }
5765     });
5766    
5767     /*
5768     * Bind hover events for datepicker elements.
5769     * Done via delegate so the binding only occurs once in the lifetime of the parent div.
5770     * Global datepicker_instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker.
5771     */
5772     function datepicker_bindHover(dpDiv) {
5773     var selector = "button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";
5774     return dpDiv.delegate(selector, "mouseout", function() {
5775     $(this).removeClass("ui-state-hover");
5776     if (this.className.indexOf("ui-datepicker-prev") !== -1) {
5777     $(this).removeClass("ui-datepicker-prev-hover");
5778     }
5779     if (this.className.indexOf("ui-datepicker-next") !== -1) {
5780     $(this).removeClass("ui-datepicker-next-hover");
5781     }
5782     })
5783     .delegate( selector, "mouseover", datepicker_handleMouseover );
5784     }
5785    
5786     function datepicker_handleMouseover() {
5787     if (!$.datepicker._isDisabledDatepicker( datepicker_instActive.inline? datepicker_instActive.dpDiv.parent()[0] : datepicker_instActive.input[0])) {
5788     $(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover");
5789     $(this).addClass("ui-state-hover");
5790     if (this.className.indexOf("ui-datepicker-prev") !== -1) {
5791     $(this).addClass("ui-datepicker-prev-hover");
5792     }
5793     if (this.className.indexOf("ui-datepicker-next") !== -1) {
5794     $(this).addClass("ui-datepicker-next-hover");
5795     }
5796     }
5797     }
5798    
5799     /* jQuery extend now ignores nulls! */
5800     function datepicker_extendRemove(target, props) {
5801     $.extend(target, props);
5802     for (var name in props) {
5803     if (props[name] == null) {
5804     target[name] = props[name];
5805     }
5806     }
5807     return target;
5808     }
5809    
5810     /* Invoke the datepicker functionality.
5811     @param options string - a command, optionally followed by additional parameters or
5812     Object - settings for attaching new datepicker functionality
5813     @return jQuery object */
5814     $.fn.datepicker = function(options){
5815    
5816     /* Verify an empty collection wasn't passed - Fixes #6976 */
5817     if ( !this.length ) {
5818     return this;
5819     }
5820    
5821     /* Initialise the date picker. */
5822     if (!$.datepicker.initialized) {
5823     $(document).mousedown($.datepicker._checkExternalClick);
5824     $.datepicker.initialized = true;
5825     }
5826    
5827     /* Append datepicker main container to body if not exist. */
5828     if ($("#"+$.datepicker._mainDivId).length === 0) {
5829     $("body").append($.datepicker.dpDiv);
5830     }
5831    
5832     var otherArgs = Array.prototype.slice.call(arguments, 1);
5833     if (typeof options === "string" && (options === "isDisabled" || options === "getDate" || options === "widget")) {
5834     return $.datepicker["_" + options + "Datepicker"].
5835     apply($.datepicker, [this[0]].concat(otherArgs));
5836     }
5837     if (options === "option" && arguments.length === 2 && typeof arguments[1] === "string") {
5838     return $.datepicker["_" + options + "Datepicker"].
5839     apply($.datepicker, [this[0]].concat(otherArgs));
5840     }
5841     return this.each(function() {
5842     typeof options === "string" ?
5843     $.datepicker["_" + options + "Datepicker"].
5844     apply($.datepicker, [this].concat(otherArgs)) :
5845     $.datepicker._attachDatepicker(this, options);
5846     });
5847     };
5848    
5849     $.datepicker = new Datepicker(); // singleton instance
5850     $.datepicker.initialized = false;
5851     $.datepicker.uuid = new Date().getTime();
5852     $.datepicker.version = "1.11.4";
5853    
5854     var datepicker = $.datepicker;
5855    
5856    
5857     /*!
5858     * jQuery UI Draggable 1.11.4
5859     * http://jqueryui.com
5860     *
5861     * Copyright jQuery Foundation and other contributors
5862     * Released under the MIT license.
5863     * http://jquery.org/license
5864     *
5865     * http://api.jqueryui.com/draggable/
5866     */
5867    
5868    
5869     $.widget("ui.draggable", $.ui.mouse, {
5870     version: "1.11.4",
5871     widgetEventPrefix: "drag",
5872     options: {
5873     addClasses: true,
5874     appendTo: "parent",
5875     axis: false,
5876     connectToSortable: false,
5877     containment: false,
5878     cursor: "auto",
5879     cursorAt: false,
5880     grid: false,
5881     handle: false,
5882     helper: "original",
5883     iframeFix: false,
5884     opacity: false,
5885     refreshPositions: false,
5886     revert: false,
5887     revertDuration: 500,
5888     scope: "default",
5889     scroll: true,
5890     scrollSensitivity: 20,
5891     scrollSpeed: 20,
5892     snap: false,
5893     snapMode: "both",
5894     snapTolerance: 20,
5895     stack: false,
5896     zIndex: false,
5897    
5898     // callbacks
5899     drag: null,
5900     start: null,
5901     stop: null
5902     },
5903     _create: function() {
5904    
5905     if ( this.options.helper === "original" ) {
5906     this._setPositionRelative();
5907     }
5908     if (this.options.addClasses){
5909     this.element.addClass("ui-draggable");
5910     }
5911     if (this.options.disabled){
5912     this.element.addClass("ui-draggable-disabled");
5913     }
5914     this._setHandleClassName();
5915    
5916     this._mouseInit();
5917     },
5918    
5919     _setOption: function( key, value ) {
5920     this._super( key, value );
5921     if ( key === "handle" ) {
5922     this._removeHandleClassName();
5923     this._setHandleClassName();
5924     }
5925     },
5926    
5927     _destroy: function() {
5928     if ( ( this.helper || this.element ).is( ".ui-draggable-dragging" ) ) {
5929     this.destroyOnClear = true;
5930     return;
5931     }
5932     this.element.removeClass( "ui-draggable ui-draggable-dragging ui-draggable-disabled" );
5933     this._removeHandleClassName();
5934     this._mouseDestroy();
5935     },
5936    
5937     _mouseCapture: function(event) {
5938     var o = this.options;
5939    
5940     this._blurActiveElement( event );
5941    
5942     // among others, prevent a drag on a resizable-handle
5943     if (this.helper || o.disabled || $(event.target).closest(".ui-resizable-handle").length > 0) {
5944     return false;
5945     }
5946    
5947     //Quit if we're not on a valid handle
5948     this.handle = this._getHandle(event);
5949     if (!this.handle) {
5950     return false;
5951     }
5952    
5953     this._blockFrames( o.iframeFix === true ? "iframe" : o.iframeFix );
5954    
5955     return true;
5956    
5957     },
5958    
5959     _blockFrames: function( selector ) {
5960     this.iframeBlocks = this.document.find( selector ).map(function() {
5961     var iframe = $( this );
5962    
5963     return $( "<div>" )
5964     .css( "position", "absolute" )
5965     .appendTo( iframe.parent() )
5966     .outerWidth( iframe.outerWidth() )
5967     .outerHeight( iframe.outerHeight() )
5968     .offset( iframe.offset() )[ 0 ];
5969     });
5970     },
5971    
5972     _unblockFrames: function() {
5973     if ( this.iframeBlocks ) {
5974     this.iframeBlocks.remove();
5975     delete this.iframeBlocks;
5976     }
5977     },
5978    
5979     _blurActiveElement: function( event ) {
5980     var document = this.document[ 0 ];
5981    
5982     // Only need to blur if the event occurred on the draggable itself, see #10527
5983     if ( !this.handleElement.is( event.target ) ) {
5984     return;
5985     }
5986    
5987     // support: IE9
5988     // IE9 throws an "Unspecified error" accessing document.activeElement from an <iframe>
5989     try {
5990    
5991     // Support: IE9, IE10
5992     // If the <body> is blurred, IE will switch windows, see #9520
5993     if ( document.activeElement && document.activeElement.nodeName.toLowerCase() !== "body" ) {
5994    
5995     // Blur any element that currently has focus, see #4261
5996     $( document.activeElement ).blur();
5997     }
5998     } catch ( error ) {}
5999     },
6000    
6001     _mouseStart: function(event) {
6002    
6003     var o = this.options;
6004    
6005     //Create and append the visible helper
6006     this.helper = this._createHelper(event);
6007    
6008     this.helper.addClass("ui-draggable-dragging");
6009    
6010     //Cache the helper size
6011     this._cacheHelperProportions();
6012    
6013     //If ddmanager is used for droppables, set the global draggable
6014     if ($.ui.ddmanager) {
6015     $.ui.ddmanager.current = this;
6016     }
6017    
6018     /*
6019     * - Position generation -
6020     * This block generates everything position related - it's the core of draggables.
6021     */
6022    
6023     //Cache the margins of the original element
6024     this._cacheMargins();
6025    
6026     //Store the helper's css position
6027     this.cssPosition = this.helper.css( "position" );
6028     this.scrollParent = this.helper.scrollParent( true );
6029     this.offsetParent = this.helper.offsetParent();
6030     this.hasFixedAncestor = this.helper.parents().filter(function() {
6031     return $( this ).css( "position" ) === "fixed";
6032     }).length > 0;
6033    
6034     //The element's absolute position on the page minus margins
6035     this.positionAbs = this.element.offset();
6036     this._refreshOffsets( event );
6037    
6038     //Generate the original position
6039     this.originalPosition = this.position = this._generatePosition( event, false );
6040     this.originalPageX = event.pageX;
6041     this.originalPageY = event.pageY;
6042    
6043     //Adjust the mouse offset relative to the helper if "cursorAt" is supplied
6044     (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
6045    
6046     //Set a containment if given in the options
6047     this._setContainment();
6048    
6049     //Trigger event + callbacks
6050     if (this._trigger("start", event) === false) {
6051     this._clear();
6052     return false;
6053     }
6054    
6055     //Recache the helper size
6056     this._cacheHelperProportions();
6057    
6058     //Prepare the droppable offsets
6059     if ($.ui.ddmanager && !o.dropBehaviour) {
6060     $.ui.ddmanager.prepareOffsets(this, event);
6061     }
6062    
6063     // Reset helper's right/bottom css if they're set and set explicit width/height instead
6064     // as this prevents resizing of elements with right/bottom set (see #7772)
6065     this._normalizeRightBottom();
6066    
6067     this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position
6068    
6069     //If the ddmanager is used for droppables, inform the manager that dragging has started (see #5003)
6070     if ( $.ui.ddmanager ) {
6071     $.ui.ddmanager.dragStart(this, event);
6072     }
6073    
6074     return true;
6075     },
6076    
6077     _refreshOffsets: function( event ) {
6078     this.offset = {
6079     top: this.positionAbs.top - this.margins.top,
6080     left: this.positionAbs.left - this.margins.left,
6081     scroll: false,
6082     parent: this._getParentOffset(),
6083     relative: this._getRelativeOffset()
6084     };
6085    
6086     this.offset.click = {
6087     left: event.pageX - this.offset.left,
6088     top: event.pageY - this.offset.top
6089     };
6090     },
6091    
6092     _mouseDrag: function(event, noPropagation) {
6093     // reset any necessary cached properties (see #5009)
6094     if ( this.hasFixedAncestor ) {
6095     this.offset.parent = this._getParentOffset();
6096     }
6097    
6098     //Compute the helpers position
6099     this.position = this._generatePosition( event, true );
6100     this.positionAbs = this._convertPositionTo("absolute");
6101    
6102     //Call plugins and callbacks and use the resulting position if something is returned
6103     if (!noPropagation) {
6104     var ui = this._uiHash();
6105     if (this._trigger("drag", event, ui) === false) {
6106     this._mouseUp({});
6107     return false;
6108     }
6109     this.position = ui.position;
6110     }
6111    
6112     this.helper[ 0 ].style.left = this.position.left + "px";
6113     this.helper[ 0 ].style.top = this.position.top + "px";
6114    
6115     if ($.ui.ddmanager) {
6116     $.ui.ddmanager.drag(this, event);
6117     }
6118    
6119     return false;
6120     },
6121    
6122     _mouseStop: function(event) {
6123    
6124     //If we are using droppables, inform the manager about the drop
6125     var that = this,
6126     dropped = false;
6127     if ($.ui.ddmanager && !this.options.dropBehaviour) {
6128     dropped = $.ui.ddmanager.drop(this, event);
6129     }
6130    
6131     //if a drop comes from outside (a sortable)
6132     if (this.dropped) {
6133     dropped = this.dropped;
6134     this.dropped = false;
6135     }
6136    
6137     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))) {
6138     $(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() {
6139     if (that._trigger("stop", event) !== false) {
6140     that._clear();
6141     }
6142     });
6143     } else {
6144     if (this._trigger("stop", event) !== false) {
6145     this._clear();
6146     }
6147     }
6148    
6149     return false;
6150     },
6151    
6152     _mouseUp: function( event ) {
6153     this._unblockFrames();
6154    
6155     //If the ddmanager is used for droppables, inform the manager that dragging has stopped (see #5003)
6156     if ( $.ui.ddmanager ) {
6157     $.ui.ddmanager.dragStop(this, event);
6158     }
6159    
6160     // Only need to focus if the event occurred on the draggable itself, see #10527
6161     if ( this.handleElement.is( event.target ) ) {
6162     // The interaction is over; whether or not the click resulted in a drag, focus the element
6163     this.element.focus();
6164     }
6165    
6166     return $.ui.mouse.prototype._mouseUp.call(this, event);
6167     },
6168    
6169     cancel: function() {
6170    
6171     if (this.helper.is(".ui-draggable-dragging")) {
6172     this._mouseUp({});
6173     } else {
6174     this._clear();
6175     }
6176    
6177     return this;
6178    
6179     },
6180    
6181     _getHandle: function(event) {
6182     return this.options.handle ?
6183     !!$( event.target ).closest( this.element.find( this.options.handle ) ).length :
6184     true;
6185     },
6186    
6187     _setHandleClassName: function() {
6188     this.handleElement = this.options.handle ?
6189     this.element.find( this.options.handle ) : this.element;
6190     this.handleElement.addClass( "ui-draggable-handle" );
6191     },
6192    
6193     _removeHandleClassName: function() {
6194     this.handleElement.removeClass( "ui-draggable-handle" );
6195     },
6196    
6197     _createHelper: function(event) {
6198    
6199     var o = this.options,
6200     helperIsFunction = $.isFunction( o.helper ),
6201     helper = helperIsFunction ?
6202     $( o.helper.apply( this.element[ 0 ], [ event ] ) ) :
6203     ( o.helper === "clone" ?
6204     this.element.clone().removeAttr( "id" ) :
6205     this.element );
6206    
6207     if (!helper.parents("body").length) {
6208     helper.appendTo((o.appendTo === "parent" ? this.element[0].parentNode : o.appendTo));
6209     }
6210    
6211     // http://bugs.jqueryui.com/ticket/9446
6212     // a helper function can return the original element
6213     // which wouldn't have been set to relative in _create
6214     if ( helperIsFunction && helper[ 0 ] === this.element[ 0 ] ) {
6215     this._setPositionRelative();
6216     }
6217    
6218     if (helper[0] !== this.element[0] && !(/(fixed|absolute)/).test(helper.css("position"))) {
6219     helper.css("position", "absolute");
6220     }
6221    
6222     return helper;
6223    
6224     },
6225    
6226     _setPositionRelative: function() {
6227     if ( !( /^(?:r|a|f)/ ).test( this.element.css( "position" ) ) ) {
6228     this.element[ 0 ].style.position = "relative";
6229     }
6230     },
6231    
6232     _adjustOffsetFromHelper: function(obj) {
6233     if (typeof obj === "string") {
6234     obj = obj.split(" ");
6235     }
6236     if ($.isArray(obj)) {
6237     obj = { left: +obj[0], top: +obj[1] || 0 };
6238     }
6239     if ("left" in obj) {
6240     this.offset.click.left = obj.left + this.margins.left;
6241     }
6242     if ("right" in obj) {
6243     this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
6244     }
6245     if ("top" in obj) {
6246     this.offset.click.top = obj.top + this.margins.top;
6247     }
6248     if ("bottom" in obj) {
6249     this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
6250     }
6251     },
6252    
6253     _isRootNode: function( element ) {
6254     return ( /(html|body)/i ).test( element.tagName ) || element === this.document[ 0 ];
6255     },
6256    
6257     _getParentOffset: function() {
6258    
6259     //Get the offsetParent and cache its position
6260     var po = this.offsetParent.offset(),
6261     document = this.document[ 0 ];
6262    
6263     // This is a special case where we need to modify a offset calculated on start, since the following happened:
6264     // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
6265     // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
6266     // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
6267     if (this.cssPosition === "absolute" && this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) {
6268     po.left += this.scrollParent.scrollLeft();
6269     po.top += this.scrollParent.scrollTop();
6270     }
6271    
6272     if ( this._isRootNode( this.offsetParent[ 0 ] ) ) {
6273     po = { top: 0, left: 0 };
6274     }
6275    
6276     return {
6277     top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"), 10) || 0),
6278     left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"), 10) || 0)
6279     };
6280    
6281     },
6282    
6283     _getRelativeOffset: function() {
6284     if ( this.cssPosition !== "relative" ) {
6285     return { top: 0, left: 0 };
6286     }
6287    
6288     var p = this.element.position(),
6289     scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] );
6290    
6291     return {
6292     top: p.top - ( parseInt(this.helper.css( "top" ), 10) || 0 ) + ( !scrollIsRootNode ? this.scrollParent.scrollTop() : 0 ),
6293     left: p.left - ( parseInt(this.helper.css( "left" ), 10) || 0 ) + ( !scrollIsRootNode ? this.scrollParent.scrollLeft() : 0 )
6294     };
6295    
6296     },
6297    
6298     _cacheMargins: function() {
6299     this.margins = {
6300     left: (parseInt(this.element.css("marginLeft"), 10) || 0),
6301     top: (parseInt(this.element.css("marginTop"), 10) || 0),
6302     right: (parseInt(this.element.css("marginRight"), 10) || 0),
6303     bottom: (parseInt(this.element.css("marginBottom"), 10) || 0)
6304     };
6305     },
6306    
6307     _cacheHelperProportions: function() {
6308     this.helperProportions = {
6309     width: this.helper.outerWidth(),
6310     height: this.helper.outerHeight()
6311     };
6312     },
6313    
6314     _setContainment: function() {
6315    
6316     var isUserScrollable, c, ce,
6317     o = this.options,
6318     document = this.document[ 0 ];
6319    
6320     this.relativeContainer = null;
6321    
6322     if ( !o.containment ) {
6323     this.containment = null;
6324     return;
6325     }
6326    
6327     if ( o.containment === "window" ) {
6328     this.containment = [
6329     $( window ).scrollLeft() - this.offset.relative.left - this.offset.parent.left,
6330     $( window ).scrollTop() - this.offset.relative.top - this.offset.parent.top,
6331     $( window ).scrollLeft() + $( window ).width() - this.helperProportions.width - this.margins.left,
6332     $( window ).scrollTop() + ( $( window ).height() || document.body.parentNode.scrollHeight ) - this.helperProportions.height - this.margins.top
6333     ];
6334     return;
6335     }
6336    
6337     if ( o.containment === "document") {
6338     this.containment = [
6339     0,
6340     0,
6341     $( document ).width() - this.helperProportions.width - this.margins.left,
6342     ( $( document ).height() || document.body.parentNode.scrollHeight ) - this.helperProportions.height - this.margins.top
6343     ];
6344     return;
6345     }
6346    
6347     if ( o.containment.constructor === Array ) {
6348     this.containment = o.containment;
6349     return;
6350     }
6351    
6352     if ( o.containment === "parent" ) {
6353     o.containment = this.helper[ 0 ].parentNode;
6354     }
6355    
6356     c = $( o.containment );
6357     ce = c[ 0 ];
6358    
6359     if ( !ce ) {
6360     return;
6361     }
6362    
6363     isUserScrollable = /(scroll|auto)/.test( c.css( "overflow" ) );
6364    
6365     this.containment = [
6366     ( parseInt( c.css( "borderLeftWidth" ), 10 ) || 0 ) + ( parseInt( c.css( "paddingLeft" ), 10 ) || 0 ),
6367     ( parseInt( c.css( "borderTopWidth" ), 10 ) || 0 ) + ( parseInt( c.css( "paddingTop" ), 10 ) || 0 ),
6368     ( isUserScrollable ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) -
6369     ( parseInt( c.css( "borderRightWidth" ), 10 ) || 0 ) -
6370     ( parseInt( c.css( "paddingRight" ), 10 ) || 0 ) -
6371     this.helperProportions.width -
6372     this.margins.left -
6373     this.margins.right,
6374     ( isUserScrollable ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) -
6375     ( parseInt( c.css( "borderBottomWidth" ), 10 ) || 0 ) -
6376     ( parseInt( c.css( "paddingBottom" ), 10 ) || 0 ) -
6377     this.helperProportions.height -
6378     this.margins.top -
6379     this.margins.bottom
6380     ];
6381     this.relativeContainer = c;
6382     },
6383    
6384     _convertPositionTo: function(d, pos) {
6385    
6386     if (!pos) {
6387     pos = this.position;
6388     }
6389    
6390     var mod = d === "absolute" ? 1 : -1,
6391     scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] );
6392    
6393     return {
6394     top: (
6395     pos.top + // The absolute mouse position
6396     this.offset.relative.top * mod + // Only for relative positioned nodes: Relative offset from element to offset parent
6397     this.offset.parent.top * mod - // The offsetParent's offset without borders (offset + border)
6398     ( ( this.cssPosition === "fixed" ? -this.offset.scroll.top : ( scrollIsRootNode ? 0 : this.offset.scroll.top ) ) * mod)
6399     ),
6400     left: (
6401     pos.left + // The absolute mouse position
6402     this.offset.relative.left * mod + // Only for relative positioned nodes: Relative offset from element to offset parent
6403     this.offset.parent.left * mod - // The offsetParent's offset without borders (offset + border)
6404     ( ( this.cssPosition === "fixed" ? -this.offset.scroll.left : ( scrollIsRootNode ? 0 : this.offset.scroll.left ) ) * mod)
6405     )
6406     };
6407    
6408     },
6409    
6410     _generatePosition: function( event, constrainPosition ) {
6411    
6412     var containment, co, top, left,
6413     o = this.options,
6414     scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] ),
6415     pageX = event.pageX,
6416     pageY = event.pageY;
6417    
6418     // Cache the scroll
6419     if ( !scrollIsRootNode || !this.offset.scroll ) {
6420     this.offset.scroll = {
6421     top: this.scrollParent.scrollTop(),
6422     left: this.scrollParent.scrollLeft()
6423     };
6424     }
6425    
6426     /*
6427     * - Position constraining -
6428     * Constrain the position to a mix of grid, containment.
6429     */
6430    
6431     // If we are not dragging yet, we won't check for options
6432     if ( constrainPosition ) {
6433     if ( this.containment ) {
6434     if ( this.relativeContainer ){
6435     co = this.relativeContainer.offset();
6436     containment = [
6437     this.containment[ 0 ] + co.left,
6438     this.containment[ 1 ] + co.top,
6439     this.containment[ 2 ] + co.left,
6440     this.containment[ 3 ] + co.top
6441     ];
6442     } else {
6443     containment = this.containment;
6444     }
6445    
6446     if (event.pageX - this.offset.click.left < containment[0]) {
6447     pageX = containment[0] + this.offset.click.left;
6448     }
6449     if (event.pageY - this.offset.click.top < containment[1]) {
6450     pageY = containment[1] + this.offset.click.top;
6451     }
6452     if (event.pageX - this.offset.click.left > containment[2]) {
6453     pageX = containment[2] + this.offset.click.left;
6454     }
6455     if (event.pageY - this.offset.click.top > containment[3]) {
6456     pageY = containment[3] + this.offset.click.top;
6457     }
6458     }
6459    
6460     if (o.grid) {
6461     //Check for grid elements set to 0 to prevent divide by 0 error causing invalid argument errors in IE (see ticket #6950)
6462     top = o.grid[1] ? this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1] : this.originalPageY;
6463     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;
6464    
6465     left = o.grid[0] ? this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0] : this.originalPageX;
6466     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;
6467     }
6468    
6469     if ( o.axis === "y" ) {
6470     pageX = this.originalPageX;
6471     }
6472    
6473     if ( o.axis === "x" ) {
6474     pageY = this.originalPageY;
6475     }
6476     }
6477    
6478     return {
6479     top: (
6480     pageY - // The absolute mouse position
6481     this.offset.click.top - // Click offset (relative to the element)
6482     this.offset.relative.top - // Only for relative positioned nodes: Relative offset from element to offset parent
6483     this.offset.parent.top + // The offsetParent's offset without borders (offset + border)
6484     ( this.cssPosition === "fixed" ? -this.offset.scroll.top : ( scrollIsRootNode ? 0 : this.offset.scroll.top ) )
6485     ),
6486     left: (
6487     pageX - // The absolute mouse position
6488     this.offset.click.left - // Click offset (relative to the element)
6489     this.offset.relative.left - // Only for relative positioned nodes: Relative offset from element to offset parent
6490     this.offset.parent.left + // The offsetParent's offset without borders (offset + border)
6491     ( this.cssPosition === "fixed" ? -this.offset.scroll.left : ( scrollIsRootNode ? 0 : this.offset.scroll.left ) )
6492     )
6493     };
6494    
6495     },
6496    
6497     _clear: function() {
6498     this.helper.removeClass("ui-draggable-dragging");
6499     if (this.helper[0] !== this.element[0] && !this.cancelHelperRemoval) {
6500     this.helper.remove();
6501     }
6502     this.helper = null;
6503     this.cancelHelperRemoval = false;
6504     if ( this.destroyOnClear ) {
6505     this.destroy();
6506     }
6507     },
6508    
6509     _normalizeRightBottom: function() {
6510     if ( this.options.axis !== "y" && this.helper.css( "right" ) !== "auto" ) {
6511     this.helper.width( this.helper.width() );
6512     this.helper.css( "right", "auto" );
6513     }
6514     if ( this.options.axis !== "x" && this.helper.css( "bottom" ) !== "auto" ) {
6515     this.helper.height( this.helper.height() );
6516     this.helper.css( "bottom", "auto" );
6517     }
6518     },
6519    
6520     // From now on bulk stuff - mainly helpers
6521    
6522     _trigger: function( type, event, ui ) {
6523     ui = ui || this._uiHash();
6524     $.ui.plugin.call( this, type, [ event, ui, this ], true );
6525    
6526     // Absolute position and offset (see #6884 ) have to be recalculated after plugins
6527     if ( /^(drag|start|stop)/.test( type ) ) {
6528     this.positionAbs = this._convertPositionTo( "absolute" );
6529     ui.offset = this.positionAbs;
6530     }
6531     return $.Widget.prototype._trigger.call( this, type, event, ui );
6532     },
6533    
6534     plugins: {},
6535    
6536     _uiHash: function() {
6537     return {
6538     helper: this.helper,
6539     position: this.position,
6540     originalPosition: this.originalPosition,
6541     offset: this.positionAbs
6542     };
6543     }
6544    
6545     });
6546    
6547     $.ui.plugin.add( "draggable", "connectToSortable", {
6548     start: function( event, ui, draggable ) {
6549     var uiSortable = $.extend( {}, ui, {
6550     item: draggable.element
6551     });
6552    
6553     draggable.sortables = [];
6554     $( draggable.options.connectToSortable ).each(function() {
6555     var sortable = $( this ).sortable( "instance" );
6556    
6557     if ( sortable && !sortable.options.disabled ) {
6558     draggable.sortables.push( sortable );
6559    
6560     // refreshPositions is called at drag start to refresh the containerCache
6561     // which is used in drag. This ensures it's initialized and synchronized
6562     // with any changes that might have happened on the page since initialization.
6563     sortable.refreshPositions();
6564     sortable._trigger("activate", event, uiSortable);
6565     }
6566     });
6567     },
6568     stop: function( event, ui, draggable ) {
6569     var uiSortable = $.extend( {}, ui, {
6570     item: draggable.element
6571     });
6572    
6573     draggable.cancelHelperRemoval = false;
6574    
6575     $.each( draggable.sortables, function() {
6576     var sortable = this;
6577    
6578     if ( sortable.isOver ) {
6579     sortable.isOver = 0;
6580    
6581     // Allow this sortable to handle removing the helper
6582     draggable.cancelHelperRemoval = true;
6583     sortable.cancelHelperRemoval = false;
6584    
6585     // Use _storedCSS To restore properties in the sortable,
6586     // as this also handles revert (#9675) since the draggable
6587     // may have modified them in unexpected ways (#8809)
6588     sortable._storedCSS = {
6589     position: sortable.placeholder.css( "position" ),
6590     top: sortable.placeholder.css( "top" ),
6591     left: sortable.placeholder.css( "left" )
6592     };
6593    
6594     sortable._mouseStop(event);
6595    
6596     // Once drag has ended, the sortable should return to using
6597     // its original helper, not the shared helper from draggable
6598     sortable.options.helper = sortable.options._helper;
6599     } else {
6600     // Prevent this Sortable from removing the helper.
6601     // However, don't set the draggable to remove the helper
6602     // either as another connected Sortable may yet handle the removal.
6603     sortable.cancelHelperRemoval = true;
6604    
6605     sortable._trigger( "deactivate", event, uiSortable );
6606     }
6607     });
6608     },
6609     drag: function( event, ui, draggable ) {
6610     $.each( draggable.sortables, function() {
6611     var innermostIntersecting = false,
6612     sortable = this;
6613    
6614     // Copy over variables that sortable's _intersectsWith uses
6615     sortable.positionAbs = draggable.positionAbs;
6616     sortable.helperProportions = draggable.helperProportions;
6617     sortable.offset.click = draggable.offset.click;
6618    
6619     if ( sortable._intersectsWith( sortable.containerCache ) ) {
6620     innermostIntersecting = true;
6621    
6622     $.each( draggable.sortables, function() {
6623     // Copy over variables that sortable's _intersectsWith uses
6624     this.positionAbs = draggable.positionAbs;
6625     this.helperProportions = draggable.helperProportions;
6626     this.offset.click = draggable.offset.click;
6627    
6628     if ( this !== sortable &&
6629     this._intersectsWith( this.containerCache ) &&
6630     $.contains( sortable.element[ 0 ], this.element[ 0 ] ) ) {
6631     innermostIntersecting = false;
6632     }
6633    
6634     return innermostIntersecting;
6635     });
6636     }
6637    
6638     if ( innermostIntersecting ) {
6639     // If it intersects, we use a little isOver variable and set it once,
6640     // so that the move-in stuff gets fired only once.
6641     if ( !sortable.isOver ) {
6642     sortable.isOver = 1;
6643    
6644     // Store draggable's parent in case we need to reappend to it later.
6645     draggable._parent = ui.helper.parent();
6646    
6647     sortable.currentItem = ui.helper
6648     .appendTo( sortable.element )
6649     .data( "ui-sortable-item", true );
6650    
6651     // Store helper option to later restore it
6652     sortable.options._helper = sortable.options.helper;
6653    
6654     sortable.options.helper = function() {
6655     return ui.helper[ 0 ];
6656     };
6657    
6658     // Fire the start events of the sortable with our passed browser event,
6659     // and our own helper (so it doesn't create a new one)
6660     event.target = sortable.currentItem[ 0 ];
6661     sortable._mouseCapture( event, true );
6662     sortable._mouseStart( event, true, true );
6663    
6664     // Because the browser event is way off the new appended portlet,
6665     // modify necessary variables to reflect the changes
6666     sortable.offset.click.top = draggable.offset.click.top;
6667     sortable.offset.click.left = draggable.offset.click.left;
6668     sortable.offset.parent.left -= draggable.offset.parent.left -
6669     sortable.offset.parent.left;
6670     sortable.offset.parent.top -= draggable.offset.parent.top -
6671     sortable.offset.parent.top;
6672    
6673     draggable._trigger( "toSortable", event );
6674    
6675     // Inform draggable that the helper is in a valid drop zone,
6676     // used solely in the revert option to handle "valid/invalid".
6677     draggable.dropped = sortable.element;
6678    
6679     // Need to refreshPositions of all sortables in the case that
6680     // adding to one sortable changes the location of the other sortables (#9675)
6681     $.each( draggable.sortables, function() {
6682     this.refreshPositions();
6683     });
6684    
6685     // hack so receive/update callbacks work (mostly)
6686     draggable.currentItem = draggable.element;
6687     sortable.fromOutside = draggable;
6688     }
6689    
6690     if ( sortable.currentItem ) {
6691     sortable._mouseDrag( event );
6692     // Copy the sortable's position because the draggable's can potentially reflect
6693     // a relative position, while sortable is always absolute, which the dragged
6694     // element has now become. (#8809)
6695     ui.position = sortable.position;
6696     }
6697     } else {
6698     // If it doesn't intersect with the sortable, and it intersected before,
6699     // we fake the drag stop of the sortable, but make sure it doesn't remove
6700     // the helper by using cancelHelperRemoval.
6701     if ( sortable.isOver ) {
6702    
6703     sortable.isOver = 0;
6704     sortable.cancelHelperRemoval = true;
6705    
6706     // Calling sortable's mouseStop would trigger a revert,
6707     // so revert must be temporarily false until after mouseStop is called.
6708     sortable.options._revert = sortable.options.revert;
6709     sortable.options.revert = false;
6710    
6711     sortable._trigger( "out", event, sortable._uiHash( sortable ) );
6712     sortable._mouseStop( event, true );
6713    
6714     // restore sortable behaviors that were modfied
6715     // when the draggable entered the sortable area (#9481)
6716     sortable.options.revert = sortable.options._revert;
6717     sortable.options.helper = sortable.options._helper;
6718    
6719     if ( sortable.placeholder ) {
6720     sortable.placeholder.remove();
6721     }
6722    
6723     // Restore and recalculate the draggable's offset considering the sortable
6724     // may have modified them in unexpected ways. (#8809, #10669)
6725     ui.helper.appendTo( draggable._parent );
6726     draggable._refreshOffsets( event );
6727     ui.position = draggable._generatePosition( event, true );
6728    
6729     draggable._trigger( "fromSortable", event );
6730    
6731     // Inform draggable that the helper is no longer in a valid drop zone
6732     draggable.dropped = false;
6733    
6734     // Need to refreshPositions of all sortables just in case removing
6735     // from one sortable changes the location of other sortables (#9675)
6736     $.each( draggable.sortables, function() {
6737     this.refreshPositions();
6738     });
6739     }
6740     }
6741     });
6742     }
6743     });
6744    
6745     $.ui.plugin.add("draggable", "cursor", {
6746     start: function( event, ui, instance ) {
6747     var t = $( "body" ),
6748     o = instance.options;
6749    
6750     if (t.css("cursor")) {
6751     o._cursor = t.css("cursor");
6752     }
6753     t.css("cursor", o.cursor);
6754     },
6755     stop: function( event, ui, instance ) {
6756     var o = instance.options;
6757     if (o._cursor) {
6758     $("body").css("cursor", o._cursor);
6759     }
6760     }
6761     });
6762    
6763     $.ui.plugin.add("draggable", "opacity", {
6764     start: function( event, ui, instance ) {
6765     var t = $( ui.helper ),
6766     o = instance.options;
6767     if (t.css("opacity")) {
6768     o._opacity = t.css("opacity");
6769     }
6770     t.css("opacity", o.opacity);
6771     },
6772     stop: function( event, ui, instance ) {
6773     var o = instance.options;
6774     if (o._opacity) {
6775     $(ui.helper).css("opacity", o._opacity);
6776     }
6777     }
6778     });
6779    
6780     $.ui.plugin.add("draggable", "scroll", {
6781     start: function( event, ui, i ) {
6782     if ( !i.scrollParentNotHidden ) {
6783     i.scrollParentNotHidden = i.helper.scrollParent( false );
6784     }
6785    
6786     if ( i.scrollParentNotHidden[ 0 ] !== i.document[ 0 ] && i.scrollParentNotHidden[ 0 ].tagName !== "HTML" ) {
6787     i.overflowOffset = i.scrollParentNotHidden.offset();
6788     }
6789     },
6790     drag: function( event, ui, i ) {
6791    
6792     var o = i.options,
6793     scrolled = false,
6794     scrollParent = i.scrollParentNotHidden[ 0 ],
6795     document = i.document[ 0 ];
6796    
6797     if ( scrollParent !== document && scrollParent.tagName !== "HTML" ) {
6798     if ( !o.axis || o.axis !== "x" ) {
6799     if ( ( i.overflowOffset.top + scrollParent.offsetHeight ) - event.pageY < o.scrollSensitivity ) {
6800     scrollParent.scrollTop = scrolled = scrollParent.scrollTop + o.scrollSpeed;
6801     } else if ( event.pageY - i.overflowOffset.top < o.scrollSensitivity ) {
6802     scrollParent.scrollTop = scrolled = scrollParent.scrollTop - o.scrollSpeed;
6803     }
6804     }
6805    
6806     if ( !o.axis || o.axis !== "y" ) {
6807     if ( ( i.overflowOffset.left + scrollParent.offsetWidth ) - event.pageX < o.scrollSensitivity ) {
6808     scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft + o.scrollSpeed;
6809     } else if ( event.pageX - i.overflowOffset.left < o.scrollSensitivity ) {
6810     scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft - o.scrollSpeed;
6811     }
6812     }
6813    
6814     } else {
6815    
6816     if (!o.axis || o.axis !== "x") {
6817     if (event.pageY - $(document).scrollTop() < o.scrollSensitivity) {
6818     scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
6819     } else if ($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) {
6820     scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
6821     }
6822     }
6823    
6824     if (!o.axis || o.axis !== "y") {
6825     if (event.pageX - $(document).scrollLeft() < o.scrollSensitivity) {
6826     scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
6827     } else if ($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) {
6828     scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
6829     }
6830     }
6831    
6832     }
6833    
6834     if (scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) {
6835     $.ui.ddmanager.prepareOffsets(i, event);
6836     }
6837    
6838     }
6839     });
6840    
6841     $.ui.plugin.add("draggable", "snap", {
6842     start: function( event, ui, i ) {
6843    
6844     var o = i.options;
6845    
6846     i.snapElements = [];
6847    
6848     $(o.snap.constructor !== String ? ( o.snap.items || ":data(ui-draggable)" ) : o.snap).each(function() {
6849     var $t = $(this),
6850     $o = $t.offset();
6851     if (this !== i.element[0]) {
6852     i.snapElements.push({
6853     item: this,
6854     width: $t.outerWidth(), height: $t.outerHeight(),
6855     top: $o.top, left: $o.left
6856     });
6857     }
6858     });
6859    
6860     },
6861     drag: function( event, ui, inst ) {
6862    
6863     var ts, bs, ls, rs, l, r, t, b, i, first,
6864     o = inst.options,
6865     d = o.snapTolerance,
6866     x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
6867     y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
6868    
6869     for (i = inst.snapElements.length - 1; i >= 0; i--){
6870    
6871     l = inst.snapElements[i].left - inst.margins.left;
6872     r = l + inst.snapElements[i].width;
6873     t = inst.snapElements[i].top - inst.margins.top;
6874     b = t + inst.snapElements[i].height;
6875    
6876     if ( x2 < l - d || x1 > r + d || y2 < t - d || y1 > b + d || !$.contains( inst.snapElements[ i ].item.ownerDocument, inst.snapElements[ i ].item ) ) {
6877     if (inst.snapElements[i].snapping) {
6878     (inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
6879     }
6880     inst.snapElements[i].snapping = false;
6881     continue;
6882     }
6883    
6884     if (o.snapMode !== "inner") {
6885     ts = Math.abs(t - y2) <= d;
6886     bs = Math.abs(b - y1) <= d;
6887     ls = Math.abs(l - x2) <= d;
6888     rs = Math.abs(r - x1) <= d;
6889     if (ts) {
6890     ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top;
6891     }
6892     if (bs) {
6893     ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top;
6894     }
6895     if (ls) {
6896     ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left;
6897     }
6898     if (rs) {
6899     ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left;
6900     }
6901     }
6902    
6903     first = (ts || bs || ls || rs);
6904    
6905     if (o.snapMode !== "outer") {
6906     ts = Math.abs(t - y1) <= d;
6907     bs = Math.abs(b - y2) <= d;
6908     ls = Math.abs(l - x1) <= d;
6909     rs = Math.abs(r - x2) <= d;
6910     if (ts) {
6911     ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top;
6912     }
6913     if (bs) {
6914     ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top;
6915     }
6916     if (ls) {
6917     ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left;
6918     }
6919     if (rs) {
6920     ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left;
6921     }
6922     }
6923    
6924     if (!inst.snapElements[i].snapping && (ts || bs || ls || rs || first)) {
6925     (inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
6926     }
6927     inst.snapElements[i].snapping = (ts || bs || ls || rs || first);
6928    
6929     }
6930    
6931     }
6932     });
6933    
6934     $.ui.plugin.add("draggable", "stack", {
6935     start: function( event, ui, instance ) {
6936     var min,
6937     o = instance.options,
6938     group = $.makeArray($(o.stack)).sort(function(a, b) {
6939     return (parseInt($(a).css("zIndex"), 10) || 0) - (parseInt($(b).css("zIndex"), 10) || 0);
6940     });
6941    
6942     if (!group.length) { return; }
6943    
6944     min = parseInt($(group[0]).css("zIndex"), 10) || 0;
6945     $(group).each(function(i) {
6946     $(this).css("zIndex", min + i);
6947     });
6948     this.css("zIndex", (min + group.length));
6949     }
6950     });
6951    
6952     $.ui.plugin.add("draggable", "zIndex", {
6953     start: function( event, ui, instance ) {
6954     var t = $( ui.helper ),
6955     o = instance.options;
6956    
6957     if (t.css("zIndex")) {
6958     o._zIndex = t.css("zIndex");
6959     }
6960     t.css("zIndex", o.zIndex);
6961     },
6962     stop: function( event, ui, instance ) {
6963     var o = instance.options;
6964    
6965     if (o._zIndex) {
6966     $(ui.helper).css("zIndex", o._zIndex);
6967     }
6968     }
6969     });
6970    
6971     var draggable = $.ui.draggable;
6972    
6973    
6974     /*!
6975     * jQuery UI Resizable 1.11.4
6976     * http://jqueryui.com
6977     *
6978     * Copyright jQuery Foundation and other contributors
6979     * Released under the MIT license.
6980     * http://jquery.org/license
6981     *
6982     * http://api.jqueryui.com/resizable/
6983     */
6984    
6985    
6986     $.widget("ui.resizable", $.ui.mouse, {
6987     version: "1.11.4",
6988     widgetEventPrefix: "resize",
6989     options: {
6990     alsoResize: false,
6991     animate: false,
6992     animateDuration: "slow",
6993     animateEasing: "swing",
6994     aspectRatio: false,
6995     autoHide: false,
6996     containment: false,
6997     ghost: false,
6998     grid: false,
6999     handles: "e,s,se",
7000     helper: false,
7001     maxHeight: null,
7002     maxWidth: null,
7003     minHeight: 10,
7004     minWidth: 10,
7005     // See #7960
7006     zIndex: 90,
7007    
7008     // callbacks
7009     resize: null,
7010     start: null,
7011     stop: null
7012     },
7013    
7014     _num: function( value ) {
7015     return parseInt( value, 10 ) || 0;
7016     },
7017    
7018     _isNumber: function( value ) {
7019     return !isNaN( parseInt( value, 10 ) );
7020     },
7021    
7022     _hasScroll: function( el, a ) {
7023    
7024     if ( $( el ).css( "overflow" ) === "hidden") {
7025     return false;
7026     }
7027    
7028     var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
7029     has = false;
7030    
7031     if ( el[ scroll ] > 0 ) {
7032     return true;
7033     }
7034    
7035     // TODO: determine which cases actually cause this to happen
7036     // if the element doesn't have the scroll set, see if it's possible to
7037     // set the scroll
7038     el[ scroll ] = 1;
7039     has = ( el[ scroll ] > 0 );
7040     el[ scroll ] = 0;
7041     return has;
7042     },
7043    
7044     _create: function() {
7045    
7046     var n, i, handle, axis, hname,
7047     that = this,
7048     o = this.options;
7049     this.element.addClass("ui-resizable");
7050    
7051     $.extend(this, {
7052     _aspectRatio: !!(o.aspectRatio),
7053     aspectRatio: o.aspectRatio,
7054     originalElement: this.element,
7055     _proportionallyResizeElements: [],
7056     _helper: o.helper || o.ghost || o.animate ? o.helper || "ui-resizable-helper" : null
7057     });
7058    
7059     // Wrap the element if it cannot hold child nodes
7060     if (this.element[0].nodeName.match(/^(canvas|textarea|input|select|button|img)$/i)) {
7061    
7062     this.element.wrap(
7063     $("<div class='ui-wrapper' style='overflow: hidden;'></div>").css({
7064     position: this.element.css("position"),
7065     width: this.element.outerWidth(),
7066     height: this.element.outerHeight(),
7067     top: this.element.css("top"),
7068     left: this.element.css("left")
7069     })
7070     );
7071    
7072     this.element = this.element.parent().data(
7073     "ui-resizable", this.element.resizable( "instance" )
7074     );
7075    
7076     this.elementIsWrapper = true;
7077    
7078     this.element.css({
7079     marginLeft: this.originalElement.css("marginLeft"),
7080     marginTop: this.originalElement.css("marginTop"),
7081     marginRight: this.originalElement.css("marginRight"),
7082     marginBottom: this.originalElement.css("marginBottom")
7083     });
7084     this.originalElement.css({
7085     marginLeft: 0,
7086     marginTop: 0,
7087     marginRight: 0,
7088     marginBottom: 0
7089     });
7090     // support: Safari
7091     // Prevent Safari textarea resize
7092     this.originalResizeStyle = this.originalElement.css("resize");
7093     this.originalElement.css("resize", "none");
7094    
7095     this._proportionallyResizeElements.push( this.originalElement.css({
7096     position: "static",
7097     zoom: 1,
7098     display: "block"
7099     }) );
7100    
7101     // support: IE9
7102     // avoid IE jump (hard set the margin)
7103     this.originalElement.css({ margin: this.originalElement.css("margin") });
7104    
7105     this._proportionallyResize();
7106     }
7107    
7108     this.handles = o.handles ||
7109     ( !$(".ui-resizable-handle", this.element).length ?
7110     "e,s,se" : {
7111     n: ".ui-resizable-n",
7112     e: ".ui-resizable-e",
7113     s: ".ui-resizable-s",
7114     w: ".ui-resizable-w",
7115     se: ".ui-resizable-se",
7116     sw: ".ui-resizable-sw",
7117     ne: ".ui-resizable-ne",
7118     nw: ".ui-resizable-nw"
7119     } );
7120    
7121     this._handles = $();
7122     if ( this.handles.constructor === String ) {
7123    
7124     if ( this.handles === "all") {
7125     this.handles = "n,e,s,w,se,sw,ne,nw";
7126     }
7127    
7128     n = this.handles.split(",");
7129     this.handles = {};
7130    
7131     for (i = 0; i < n.length; i++) {
7132    
7133     handle = $.trim(n[i]);
7134     hname = "ui-resizable-" + handle;
7135     axis = $("<div class='ui-resizable-handle " + hname + "'></div>");
7136    
7137     axis.css({ zIndex: o.zIndex });
7138    
7139     // TODO : What's going on here?
7140     if ("se" === handle) {
7141     axis.addClass("ui-icon ui-icon-gripsmall-diagonal-se");
7142     }
7143    
7144     this.handles[handle] = ".ui-resizable-" + handle;
7145     this.element.append(axis);
7146     }
7147    
7148     }
7149    
7150     this._renderAxis = function(target) {
7151    
7152     var i, axis, padPos, padWrapper;
7153    
7154     target = target || this.element;
7155    
7156     for (i in this.handles) {
7157    
7158     if (this.handles[i].constructor === String) {
7159     this.handles[i] = this.element.children( this.handles[ i ] ).first().show();
7160     } else if ( this.handles[ i ].jquery || this.handles[ i ].nodeType ) {
7161     this.handles[ i ] = $( this.handles[ i ] );
7162     this._on( this.handles[ i ], { "mousedown": that._mouseDown });
7163     }
7164    
7165     if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/^(textarea|input|select|button)$/i)) {
7166    
7167     axis = $(this.handles[i], this.element);
7168    
7169     padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth();
7170    
7171     padPos = [ "padding",
7172     /ne|nw|n/.test(i) ? "Top" :
7173     /se|sw|s/.test(i) ? "Bottom" :
7174     /^e$/.test(i) ? "Right" : "Left" ].join("");
7175    
7176     target.css(padPos, padWrapper);
7177    
7178     this._proportionallyResize();
7179     }
7180    
7181     this._handles = this._handles.add( this.handles[ i ] );
7182     }
7183     };
7184    
7185     // TODO: make renderAxis a prototype function
7186     this._renderAxis(this.element);
7187    
7188     this._handles = this._handles.add( this.element.find( ".ui-resizable-handle" ) );
7189     this._handles.disableSelection();
7190    
7191     this._handles.mouseover(function() {
7192     if (!that.resizing) {
7193     if (this.className) {
7194     axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);
7195     }
7196     that.axis = axis && axis[1] ? axis[1] : "se";
7197     }
7198     });
7199    
7200     if (o.autoHide) {
7201     this._handles.hide();
7202     $(this.element)
7203     .addClass("ui-resizable-autohide")
7204     .mouseenter(function() {
7205     if (o.disabled) {
7206     return;
7207     }
7208     $(this).removeClass("ui-resizable-autohide");
7209     that._handles.show();
7210     })
7211     .mouseleave(function() {
7212     if (o.disabled) {
7213     return;
7214     }
7215     if (!that.resizing) {
7216     $(this).addClass("ui-resizable-autohide");
7217     that._handles.hide();
7218     }
7219     });
7220     }
7221    
7222     this._mouseInit();
7223     },
7224    
7225     _destroy: function() {
7226    
7227     this._mouseDestroy();
7228    
7229     var wrapper,
7230     _destroy = function(exp) {
7231     $(exp)
7232     .removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing")
7233     .removeData("resizable")
7234     .removeData("ui-resizable")
7235     .unbind(".resizable")
7236     .find(".ui-resizable-handle")
7237     .remove();
7238     };
7239    
7240     // TODO: Unwrap at same DOM position
7241     if (this.elementIsWrapper) {
7242     _destroy(this.element);
7243     wrapper = this.element;
7244     this.originalElement.css({
7245     position: wrapper.css("position"),
7246     width: wrapper.outerWidth(),
7247     height: wrapper.outerHeight(),
7248     top: wrapper.css("top"),
7249     left: wrapper.css("left")
7250     }).insertAfter( wrapper );
7251     wrapper.remove();
7252     }
7253    
7254     this.originalElement.css("resize", this.originalResizeStyle);
7255     _destroy(this.originalElement);
7256    
7257     return this;
7258     },
7259    
7260     _mouseCapture: function(event) {
7261     var i, handle,
7262     capture = false;
7263    
7264     for (i in this.handles) {
7265     handle = $(this.handles[i])[0];
7266     if (handle === event.target || $.contains(handle, event.target)) {
7267     capture = true;
7268     }
7269     }
7270    
7271     return !this.options.disabled && capture;
7272     },
7273    
7274     _mouseStart: function(event) {
7275    
7276     var curleft, curtop, cursor,
7277     o = this.options,
7278     el = this.element;
7279    
7280     this.resizing = true;
7281    
7282     this._renderProxy();
7283    
7284     curleft = this._num(this.helper.css("left"));
7285     curtop = this._num(this.helper.css("top"));
7286    
7287     if (o.containment) {
7288     curleft += $(o.containment).scrollLeft() || 0;
7289     curtop += $(o.containment).scrollTop() || 0;
7290     }
7291    
7292     this.offset = this.helper.offset();
7293     this.position = { left: curleft, top: curtop };
7294    
7295     this.size = this._helper ? {
7296     width: this.helper.width(),
7297     height: this.helper.height()
7298     } : {
7299     width: el.width(),
7300     height: el.height()
7301     };
7302    
7303     this.originalSize = this._helper ? {
7304     width: el.outerWidth(),
7305     height: el.outerHeight()
7306     } : {
7307     width: el.width(),
7308     height: el.height()
7309     };
7310    
7311     this.sizeDiff = {
7312     width: el.outerWidth() - el.width(),
7313     height: el.outerHeight() - el.height()
7314     };
7315    
7316     this.originalPosition = { left: curleft, top: curtop };
7317     this.originalMousePosition = { left: event.pageX, top: event.pageY };
7318    
7319     this.aspectRatio = (typeof o.aspectRatio === "number") ?
7320     o.aspectRatio :
7321     ((this.originalSize.width / this.originalSize.height) || 1);
7322    
7323     cursor = $(".ui-resizable-" + this.axis).css("cursor");
7324     $("body").css("cursor", cursor === "auto" ? this.axis + "-resize" : cursor);
7325    
7326     el.addClass("ui-resizable-resizing");
7327     this._propagate("start", event);
7328     return true;
7329     },
7330    
7331     _mouseDrag: function(event) {
7332    
7333     var data, props,
7334     smp = this.originalMousePosition,
7335     a = this.axis,
7336     dx = (event.pageX - smp.left) || 0,
7337     dy = (event.pageY - smp.top) || 0,
7338     trigger = this._change[a];
7339    
7340     this._updatePrevProperties();
7341    
7342     if (!trigger) {
7343     return false;
7344     }
7345    
7346     data = trigger.apply(this, [ event, dx, dy ]);
7347    
7348     this._updateVirtualBoundaries(event.shiftKey);
7349     if (this._aspectRatio || event.shiftKey) {
7350     data = this._updateRatio(data, event);
7351     }
7352    
7353     data = this._respectSize(data, event);
7354    
7355     this._updateCache(data);
7356    
7357     this._propagate("resize", event);
7358    
7359     props = this._applyChanges();
7360    
7361     if ( !this._helper && this._proportionallyResizeElements.length ) {
7362     this._proportionallyResize();
7363     }
7364    
7365     if ( !$.isEmptyObject( props ) ) {
7366     this._updatePrevProperties();
7367     this._trigger( "resize", event, this.ui() );
7368     this._applyChanges();
7369     }
7370    
7371     return false;
7372     },
7373    
7374     _mouseStop: function(event) {
7375    
7376     this.resizing = false;
7377     var pr, ista, soffseth, soffsetw, s, left, top,
7378     o = this.options, that = this;
7379    
7380     if (this._helper) {
7381    
7382     pr = this._proportionallyResizeElements;
7383     ista = pr.length && (/textarea/i).test(pr[0].nodeName);
7384     soffseth = ista && this._hasScroll(pr[0], "left") ? 0 : that.sizeDiff.height;
7385     soffsetw = ista ? 0 : that.sizeDiff.width;
7386    
7387     s = {
7388     width: (that.helper.width() - soffsetw),
7389     height: (that.helper.height() - soffseth)
7390     };
7391     left = (parseInt(that.element.css("left"), 10) +
7392     (that.position.left - that.originalPosition.left)) || null;
7393     top = (parseInt(that.element.css("top"), 10) +
7394     (that.position.top - that.originalPosition.top)) || null;
7395    
7396     if (!o.animate) {
7397     this.element.css($.extend(s, { top: top, left: left }));
7398     }
7399    
7400     that.helper.height(that.size.height);
7401     that.helper.width(that.size.width);
7402    
7403     if (this._helper && !o.animate) {
7404     this._proportionallyResize();
7405     }
7406     }
7407    
7408     $("body").css("cursor", "auto");
7409    
7410     this.element.removeClass("ui-resizable-resizing");
7411    
7412     this._propagate("stop", event);
7413    
7414     if (this._helper) {
7415     this.helper.remove();
7416     }
7417    
7418     return false;
7419    
7420     },
7421    
7422     _updatePrevProperties: function() {
7423     this.prevPosition = {
7424     top: this.position.top,
7425     left: this.position.left
7426     };
7427     this.prevSize = {
7428     width: this.size.width,
7429     height: this.size.height
7430     };
7431     },
7432    
7433     _applyChanges: function() {
7434     var props = {};
7435    
7436     if ( this.position.top !== this.prevPosition.top ) {
7437     props.top = this.position.top + "px";
7438     }
7439     if ( this.position.left !== this.prevPosition.left ) {
7440     props.left = this.position.left + "px";
7441     }
7442     if ( this.size.width !== this.prevSize.width ) {
7443     props.width = this.size.width + "px";
7444     }
7445     if ( this.size.height !== this.prevSize.height ) {
7446     props.height = this.size.height + "px";
7447     }
7448    
7449     this.helper.css( props );
7450    
7451     return props;
7452     },
7453    
7454     _updateVirtualBoundaries: function(forceAspectRatio) {
7455     var pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b,
7456     o = this.options;
7457    
7458     b = {
7459     minWidth: this._isNumber(o.minWidth) ? o.minWidth : 0,
7460     maxWidth: this._isNumber(o.maxWidth) ? o.maxWidth : Infinity,
7461     minHeight: this._isNumber(o.minHeight) ? o.minHeight : 0,
7462     maxHeight: this._isNumber(o.maxHeight) ? o.maxHeight : Infinity
7463     };
7464    
7465     if (this._aspectRatio || forceAspectRatio) {
7466     pMinWidth = b.minHeight * this.aspectRatio;
7467     pMinHeight = b.minWidth / this.aspectRatio;
7468     pMaxWidth = b.maxHeight * this.aspectRatio;
7469     pMaxHeight = b.maxWidth / this.aspectRatio;
7470    
7471     if (pMinWidth > b.minWidth) {
7472     b.minWidth = pMinWidth;
7473     }
7474     if (pMinHeight > b.minHeight) {
7475     b.minHeight = pMinHeight;
7476     }
7477     if (pMaxWidth < b.maxWidth) {
7478     b.maxWidth = pMaxWidth;
7479     }
7480     if (pMaxHeight < b.maxHeight) {
7481     b.maxHeight = pMaxHeight;
7482     }
7483     }
7484     this._vBoundaries = b;
7485     },
7486    
7487     _updateCache: function(data) {
7488     this.offset = this.helper.offset();
7489     if (this._isNumber(data.left)) {
7490     this.position.left = data.left;
7491     }
7492     if (this._isNumber(data.top)) {
7493     this.position.top = data.top;
7494     }
7495     if (this._isNumber(data.height)) {
7496     this.size.height = data.height;
7497     }
7498     if (this._isNumber(data.width)) {
7499     this.size.width = data.width;
7500     }
7501     },
7502    
7503     _updateRatio: function( data ) {
7504    
7505     var cpos = this.position,
7506     csize = this.size,
7507     a = this.axis;
7508    
7509     if (this._isNumber(data.height)) {
7510     data.width = (data.height * this.aspectRatio);
7511     } else if (this._isNumber(data.width)) {
7512     data.height = (data.width / this.aspectRatio);
7513     }
7514    
7515     if (a === "sw") {
7516     data.left = cpos.left + (csize.width - data.width);
7517     data.top = null;
7518     }
7519     if (a === "nw") {
7520     data.top = cpos.top + (csize.height - data.height);
7521     data.left = cpos.left + (csize.width - data.width);
7522     }
7523    
7524     return data;
7525     },
7526    
7527     _respectSize: function( data ) {
7528    
7529     var o = this._vBoundaries,
7530     a = this.axis,
7531     ismaxw = this._isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width),
7532     ismaxh = this._isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height),
7533     isminw = this._isNumber(data.width) && o.minWidth && (o.minWidth > data.width),
7534     isminh = this._isNumber(data.height) && o.minHeight && (o.minHeight > data.height),
7535     dw = this.originalPosition.left + this.originalSize.width,
7536     dh = this.position.top + this.size.height,
7537     cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a);
7538     if (isminw) {
7539     data.width = o.minWidth;
7540     }
7541     if (isminh) {
7542     data.height = o.minHeight;
7543     }
7544     if (ismaxw) {
7545     data.width = o.maxWidth;
7546     }
7547     if (ismaxh) {
7548     data.height = o.maxHeight;
7549     }
7550    
7551     if (isminw && cw) {
7552     data.left = dw - o.minWidth;
7553     }
7554     if (ismaxw && cw) {
7555     data.left = dw - o.maxWidth;
7556     }
7557     if (isminh && ch) {
7558     data.top = dh - o.minHeight;
7559     }
7560     if (ismaxh && ch) {
7561     data.top = dh - o.maxHeight;
7562     }
7563    
7564     // Fixing jump error on top/left - bug #2330
7565     if (!data.width && !data.height && !data.left && data.top) {
7566     data.top = null;
7567     } else if (!data.width && !data.height && !data.top && data.left) {
7568     data.left = null;
7569     }
7570    
7571     return data;
7572     },
7573    
7574     _getPaddingPlusBorderDimensions: function( element ) {
7575     var i = 0,
7576     widths = [],
7577     borders = [
7578     element.css( "borderTopWidth" ),
7579     element.css( "borderRightWidth" ),
7580     element.css( "borderBottomWidth" ),
7581     element.css( "borderLeftWidth" )
7582     ],
7583     paddings = [
7584     element.css( "paddingTop" ),
7585     element.css( "paddingRight" ),
7586     element.css( "paddingBottom" ),
7587     element.css( "paddingLeft" )
7588     ];
7589    
7590     for ( ; i < 4; i++ ) {
7591     widths[ i ] = ( parseInt( borders[ i ], 10 ) || 0 );
7592     widths[ i ] += ( parseInt( paddings[ i ], 10 ) || 0 );
7593     }
7594    
7595     return {
7596     height: widths[ 0 ] + widths[ 2 ],
7597     width: widths[ 1 ] + widths[ 3 ]
7598     };
7599     },
7600    
7601     _proportionallyResize: function() {
7602    
7603     if (!this._proportionallyResizeElements.length) {
7604     return;
7605     }
7606    
7607     var prel,
7608     i = 0,
7609     element = this.helper || this.element;
7610    
7611     for ( ; i < this._proportionallyResizeElements.length; i++) {
7612    
7613     prel = this._proportionallyResizeElements[i];
7614    
7615     // TODO: Seems like a bug to cache this.outerDimensions
7616     // considering that we are in a loop.
7617     if (!this.outerDimensions) {
7618     this.outerDimensions = this._getPaddingPlusBorderDimensions( prel );
7619     }
7620    
7621     prel.css({
7622     height: (element.height() - this.outerDimensions.height) || 0,
7623     width: (element.width() - this.outerDimensions.width) || 0
7624     });
7625    
7626     }
7627    
7628     },
7629    
7630     _renderProxy: function() {
7631    
7632     var el = this.element, o = this.options;
7633     this.elementOffset = el.offset();
7634    
7635     if (this._helper) {
7636    
7637     this.helper = this.helper || $("<div style='overflow:hidden;'></div>");
7638    
7639     this.helper.addClass(this._helper).css({
7640     width: this.element.outerWidth() - 1,
7641     height: this.element.outerHeight() - 1,
7642     position: "absolute",
7643     left: this.elementOffset.left + "px",
7644     top: this.elementOffset.top + "px",
7645     zIndex: ++o.zIndex //TODO: Don't modify option
7646     });
7647    
7648     this.helper
7649     .appendTo("body")
7650     .disableSelection();
7651    
7652     } else {
7653     this.helper = this.element;
7654     }
7655    
7656     },
7657    
7658     _change: {
7659     e: function(event, dx) {
7660     return { width: this.originalSize.width + dx };
7661     },
7662     w: function(event, dx) {
7663     var cs = this.originalSize, sp = this.originalPosition;
7664     return { left: sp.left + dx, width: cs.width - dx };
7665     },
7666     n: function(event, dx, dy) {
7667     var cs = this.originalSize, sp = this.originalPosition;
7668     return { top: sp.top + dy, height: cs.height - dy };
7669     },
7670     s: function(event, dx, dy) {
7671     return { height: this.originalSize.height + dy };
7672     },
7673     se: function(event, dx, dy) {
7674     return $.extend(this._change.s.apply(this, arguments),
7675     this._change.e.apply(this, [ event, dx, dy ]));
7676     },
7677     sw: function(event, dx, dy) {
7678     return $.extend(this._change.s.apply(this, arguments),
7679     this._change.w.apply(this, [ event, dx, dy ]));
7680     },
7681     ne: function(event, dx, dy) {
7682     return $.extend(this._change.n.apply(this, arguments),
7683     this._change.e.apply(this, [ event, dx, dy ]));
7684     },
7685     nw: function(event, dx, dy) {
7686     return $.extend(this._change.n.apply(this, arguments),
7687     this._change.w.apply(this, [ event, dx, dy ]));
7688     }
7689     },
7690    
7691     _propagate: function(n, event) {
7692     $.ui.plugin.call(this, n, [ event, this.ui() ]);
7693     (n !== "resize" && this._trigger(n, event, this.ui()));
7694     },
7695    
7696     plugins: {},
7697    
7698     ui: function() {
7699     return {
7700     originalElement: this.originalElement,
7701     element: this.element,
7702     helper: this.helper,
7703     position: this.position,
7704     size: this.size,
7705     originalSize: this.originalSize,
7706     originalPosition: this.originalPosition
7707     };
7708     }
7709    
7710     });
7711    
7712     /*
7713     * Resizable Extensions
7714     */
7715    
7716     $.ui.plugin.add("resizable", "animate", {
7717    
7718     stop: function( event ) {
7719     var that = $(this).resizable( "instance" ),
7720     o = that.options,
7721     pr = that._proportionallyResizeElements,
7722     ista = pr.length && (/textarea/i).test(pr[0].nodeName),
7723     soffseth = ista && that._hasScroll(pr[0], "left") ? 0 : that.sizeDiff.height,
7724     soffsetw = ista ? 0 : that.sizeDiff.width,
7725     style = { width: (that.size.width - soffsetw), height: (that.size.height - soffseth) },
7726     left = (parseInt(that.element.css("left"), 10) +
7727     (that.position.left - that.originalPosition.left)) || null,
7728     top = (parseInt(that.element.css("top"), 10) +
7729     (that.position.top - that.originalPosition.top)) || null;
7730    
7731     that.element.animate(
7732     $.extend(style, top && left ? { top: top, left: left } : {}), {
7733     duration: o.animateDuration,
7734     easing: o.animateEasing,
7735     step: function() {
7736    
7737     var data = {
7738     width: parseInt(that.element.css("width"), 10),
7739     height: parseInt(that.element.css("height"), 10),
7740     top: parseInt(that.element.css("top"), 10),
7741     left: parseInt(that.element.css("left"), 10)
7742     };
7743    
7744     if (pr && pr.length) {
7745     $(pr[0]).css({ width: data.width, height: data.height });
7746     }
7747    
7748     // propagating resize, and updating values for each animation step
7749     that._updateCache(data);
7750     that._propagate("resize", event);
7751    
7752     }
7753     }
7754     );
7755     }
7756    
7757     });
7758    
7759     $.ui.plugin.add( "resizable", "containment", {
7760    
7761     start: function() {
7762     var element, p, co, ch, cw, width, height,
7763     that = $( this ).resizable( "instance" ),
7764     o = that.options,
7765     el = that.element,
7766     oc = o.containment,
7767     ce = ( oc instanceof $ ) ? oc.get( 0 ) : ( /parent/.test( oc ) ) ? el.parent().get( 0 ) : oc;
7768    
7769     if ( !ce ) {
7770     return;
7771     }
7772    
7773     that.containerElement = $( ce );
7774    
7775     if ( /document/.test( oc ) || oc === document ) {
7776     that.containerOffset = {
7777     left: 0,
7778     top: 0
7779     };
7780     that.containerPosition = {
7781     left: 0,
7782     top: 0
7783     };
7784    
7785     that.parentData = {
7786     element: $( document ),
7787     left: 0,
7788     top: 0,
7789     width: $( document ).width(),
7790     height: $( document ).height() || document.body.parentNode.scrollHeight
7791     };
7792     } else {
7793     element = $( ce );
7794     p = [];
7795     $([ "Top", "Right", "Left", "Bottom" ]).each(function( i, name ) {
7796     p[ i ] = that._num( element.css( "padding" + name ) );
7797     });
7798    
7799     that.containerOffset = element.offset();
7800     that.containerPosition = element.position();
7801     that.containerSize = {
7802     height: ( element.innerHeight() - p[ 3 ] ),
7803     width: ( element.innerWidth() - p[ 1 ] )
7804     };
7805    
7806     co = that.containerOffset;
7807     ch = that.containerSize.height;
7808     cw = that.containerSize.width;
7809     width = ( that._hasScroll ( ce, "left" ) ? ce.scrollWidth : cw );
7810     height = ( that._hasScroll ( ce ) ? ce.scrollHeight : ch ) ;
7811    
7812     that.parentData = {
7813     element: ce,
7814     left: co.left,
7815     top: co.top,
7816     width: width,
7817     height: height
7818     };
7819     }
7820     },
7821    
7822     resize: function( event ) {
7823     var woset, hoset, isParent, isOffsetRelative,
7824     that = $( this ).resizable( "instance" ),
7825     o = that.options,
7826     co = that.containerOffset,
7827     cp = that.position,
7828     pRatio = that._aspectRatio || event.shiftKey,
7829     cop = {
7830     top: 0,
7831     left: 0
7832     },
7833     ce = that.containerElement,
7834     continueResize = true;
7835    
7836     if ( ce[ 0 ] !== document && ( /static/ ).test( ce.css( "position" ) ) ) {
7837     cop = co;
7838     }
7839    
7840     if ( cp.left < ( that._helper ? co.left : 0 ) ) {
7841     that.size.width = that.size.width +
7842     ( that._helper ?
7843     ( that.position.left - co.left ) :
7844     ( that.position.left - cop.left ) );
7845    
7846     if ( pRatio ) {
7847     that.size.height = that.size.width / that.aspectRatio;
7848     continueResize = false;
7849     }
7850     that.position.left = o.helper ? co.left : 0;
7851     }
7852    
7853     if ( cp.top < ( that._helper ? co.top : 0 ) ) {
7854     that.size.height = that.size.height +
7855     ( that._helper ?
7856     ( that.position.top - co.top ) :
7857     that.position.top );
7858    
7859     if ( pRatio ) {
7860     that.size.width = that.size.height * that.aspectRatio;
7861     continueResize = false;
7862     }
7863     that.position.top = that._helper ? co.top : 0;
7864     }
7865    
7866     isParent = that.containerElement.get( 0 ) === that.element.parent().get( 0 );
7867     isOffsetRelative = /relative|absolute/.test( that.containerElement.css( "position" ) );
7868    
7869     if ( isParent && isOffsetRelative ) {
7870     that.offset.left = that.parentData.left + that.position.left;
7871     that.offset.top = that.parentData.top + that.position.top;
7872     } else {
7873     that.offset.left = that.element.offset().left;
7874     that.offset.top = that.element.offset().top;
7875     }
7876    
7877     woset = Math.abs( that.sizeDiff.width +
7878     (that._helper ?
7879     that.offset.left - cop.left :
7880     (that.offset.left - co.left)) );
7881    
7882     hoset = Math.abs( that.sizeDiff.height +
7883     (that._helper ?
7884     that.offset.top - cop.top :
7885     (that.offset.top - co.top)) );
7886    
7887     if ( woset + that.size.width >= that.parentData.width ) {
7888     that.size.width = that.parentData.width - woset;
7889     if ( pRatio ) {
7890     that.size.height = that.size.width / that.aspectRatio;
7891     continueResize = false;
7892     }
7893     }
7894    
7895     if ( hoset + that.size.height >= that.parentData.height ) {
7896     that.size.height = that.parentData.height - hoset;
7897     if ( pRatio ) {
7898     that.size.width = that.size.height * that.aspectRatio;
7899     continueResize = false;
7900     }
7901     }
7902    
7903     if ( !continueResize ) {
7904     that.position.left = that.prevPosition.left;
7905     that.position.top = that.prevPosition.top;
7906     that.size.width = that.prevSize.width;
7907     that.size.height = that.prevSize.height;
7908     }
7909     },
7910    
7911     stop: function() {
7912     var that = $( this ).resizable( "instance" ),
7913     o = that.options,
7914     co = that.containerOffset,
7915     cop = that.containerPosition,
7916     ce = that.containerElement,
7917     helper = $( that.helper ),
7918     ho = helper.offset(),
7919     w = helper.outerWidth() - that.sizeDiff.width,
7920     h = helper.outerHeight() - that.sizeDiff.height;
7921    
7922     if ( that._helper && !o.animate && ( /relative/ ).test( ce.css( "position" ) ) ) {
7923     $( this ).css({
7924     left: ho.left - cop.left - co.left,
7925     width: w,
7926     height: h
7927     });
7928     }
7929    
7930     if ( that._helper && !o.animate && ( /static/ ).test( ce.css( "position" ) ) ) {
7931     $( this ).css({
7932     left: ho.left - cop.left - co.left,
7933     width: w,
7934     height: h
7935     });
7936     }
7937     }
7938     });
7939    
7940     $.ui.plugin.add("resizable", "alsoResize", {
7941    
7942     start: function() {
7943     var that = $(this).resizable( "instance" ),
7944     o = that.options;
7945    
7946     $(o.alsoResize).each(function() {
7947     var el = $(this);
7948     el.data("ui-resizable-alsoresize", {
7949     width: parseInt(el.width(), 10), height: parseInt(el.height(), 10),
7950     left: parseInt(el.css("left"), 10), top: parseInt(el.css("top"), 10)
7951     });
7952     });
7953     },
7954    
7955     resize: function(event, ui) {
7956     var that = $(this).resizable( "instance" ),
7957     o = that.options,
7958     os = that.originalSize,
7959     op = that.originalPosition,
7960     delta = {
7961     height: (that.size.height - os.height) || 0,
7962     width: (that.size.width - os.width) || 0,
7963     top: (that.position.top - op.top) || 0,
7964     left: (that.position.left - op.left) || 0
7965     };
7966    
7967     $(o.alsoResize).each(function() {
7968     var el = $(this), start = $(this).data("ui-resizable-alsoresize"), style = {},
7969     css = el.parents(ui.originalElement[0]).length ?
7970     [ "width", "height" ] :
7971     [ "width", "height", "top", "left" ];
7972    
7973     $.each(css, function(i, prop) {
7974     var sum = (start[prop] || 0) + (delta[prop] || 0);
7975     if (sum && sum >= 0) {
7976     style[prop] = sum || null;
7977     }
7978     });
7979    
7980     el.css(style);
7981     });
7982     },
7983    
7984     stop: function() {
7985     $(this).removeData("resizable-alsoresize");
7986     }
7987     });
7988    
7989     $.ui.plugin.add("resizable", "ghost", {
7990    
7991     start: function() {
7992    
7993     var that = $(this).resizable( "instance" ), o = that.options, cs = that.size;
7994    
7995     that.ghost = that.originalElement.clone();
7996     that.ghost
7997     .css({
7998     opacity: 0.25,
7999     display: "block",
8000     position: "relative",
8001     height: cs.height,
8002     width: cs.width,
8003     margin: 0,
8004     left: 0,
8005     top: 0
8006     })
8007     .addClass("ui-resizable-ghost")
8008     .addClass(typeof o.ghost === "string" ? o.ghost : "");
8009    
8010     that.ghost.appendTo(that.helper);
8011    
8012     },
8013    
8014     resize: function() {
8015     var that = $(this).resizable( "instance" );
8016     if (that.ghost) {
8017     that.ghost.css({
8018     position: "relative",
8019     height: that.size.height,
8020     width: that.size.width
8021     });
8022     }
8023     },
8024    
8025     stop: function() {
8026     var that = $(this).resizable( "instance" );
8027     if (that.ghost && that.helper) {
8028     that.helper.get(0).removeChild(that.ghost.get(0));
8029     }
8030     }
8031    
8032     });
8033    
8034     $.ui.plugin.add("resizable", "grid", {
8035    
8036     resize: function() {
8037     var outerDimensions,
8038     that = $(this).resizable( "instance" ),
8039     o = that.options,
8040     cs = that.size,
8041     os = that.originalSize,
8042     op = that.originalPosition,
8043     a = that.axis,
8044     grid = typeof o.grid === "number" ? [ o.grid, o.grid ] : o.grid,
8045     gridX = (grid[0] || 1),
8046     gridY = (grid[1] || 1),
8047     ox = Math.round((cs.width - os.width) / gridX) * gridX,
8048     oy = Math.round((cs.height - os.height) / gridY) * gridY,
8049     newWidth = os.width + ox,
8050     newHeight = os.height + oy,
8051     isMaxWidth = o.maxWidth && (o.maxWidth < newWidth),
8052     isMaxHeight = o.maxHeight && (o.maxHeight < newHeight),
8053     isMinWidth = o.minWidth && (o.minWidth > newWidth),
8054     isMinHeight = o.minHeight && (o.minHeight > newHeight);
8055    
8056     o.grid = grid;
8057    
8058     if (isMinWidth) {
8059     newWidth += gridX;
8060     }
8061     if (isMinHeight) {
8062     newHeight += gridY;
8063     }
8064     if (isMaxWidth) {
8065     newWidth -= gridX;
8066     }
8067     if (isMaxHeight) {
8068     newHeight -= gridY;
8069     }
8070    
8071     if (/^(se|s|e)$/.test(a)) {
8072     that.size.width = newWidth;
8073     that.size.height = newHeight;
8074     } else if (/^(ne)$/.test(a)) {
8075     that.size.width = newWidth;
8076     that.size.height = newHeight;
8077     that.position.top = op.top - oy;
8078     } else if (/^(sw)$/.test(a)) {
8079     that.size.width = newWidth;
8080     that.size.height = newHeight;
8081     that.position.left = op.left - ox;
8082     } else {
8083     if ( newHeight - gridY <= 0 || newWidth - gridX <= 0) {
8084     outerDimensions = that._getPaddingPlusBorderDimensions( this );
8085     }
8086    
8087     if ( newHeight - gridY > 0 ) {
8088     that.size.height = newHeight;
8089     that.position.top = op.top - oy;
8090     } else {
8091     newHeight = gridY - outerDimensions.height;
8092     that.size.height = newHeight;
8093     that.position.top = op.top + os.height - newHeight;
8094     }
8095     if ( newWidth - gridX > 0 ) {
8096     that.size.width = newWidth;
8097     that.position.left = op.left - ox;
8098     } else {
8099     newWidth = gridX - outerDimensions.width;
8100     that.size.width = newWidth;
8101     that.position.left = op.left + os.width - newWidth;
8102     }
8103     }
8104     }
8105    
8106     });
8107    
8108     var resizable = $.ui.resizable;
8109    
8110    
8111     /*!
8112     * jQuery UI Dialog 1.11.4
8113     * http://jqueryui.com
8114     *
8115     * Copyright jQuery Foundation and other contributors
8116     * Released under the MIT license.
8117     * http://jquery.org/license
8118     *
8119     * http://api.jqueryui.com/dialog/
8120     */
8121    
8122    
8123     var dialog = $.widget( "ui.dialog", {
8124     version: "1.11.4",
8125     options: {
8126     appendTo: "body",
8127     autoOpen: true,
8128     buttons: [],
8129     closeOnEscape: true,
8130     closeText: "Close",
8131     dialogClass: "",
8132     draggable: true,
8133     hide: null,
8134     height: "auto",
8135     maxHeight: null,
8136     maxWidth: null,
8137     minHeight: 150,
8138     minWidth: 150,
8139     modal: false,
8140     position: {
8141     my: "center",
8142     at: "center",
8143     of: window,
8144     collision: "fit",
8145     // Ensure the titlebar is always visible
8146     using: function( pos ) {
8147     var topOffset = $( this ).css( pos ).offset().top;
8148     if ( topOffset < 0 ) {
8149     $( this ).css( "top", pos.top - topOffset );
8150     }
8151     }
8152     },
8153     resizable: true,
8154     show: null,
8155     title: null,
8156     width: 300,
8157    
8158     // callbacks
8159     beforeClose: null,
8160     close: null,
8161     drag: null,
8162     dragStart: null,
8163     dragStop: null,
8164     focus: null,
8165     open: null,
8166     resize: null,
8167     resizeStart: null,
8168     resizeStop: null
8169     },
8170    
8171     sizeRelatedOptions: {
8172     buttons: true,
8173     height: true,
8174     maxHeight: true,
8175     maxWidth: true,
8176     minHeight: true,
8177     minWidth: true,
8178     width: true
8179     },
8180    
8181     resizableRelatedOptions: {
8182     maxHeight: true,
8183     maxWidth: true,
8184     minHeight: true,
8185     minWidth: true
8186     },
8187    
8188     _create: function() {
8189     this.originalCss = {
8190     display: this.element[ 0 ].style.display,
8191     width: this.element[ 0 ].style.width,
8192     minHeight: this.element[ 0 ].style.minHeight,
8193     maxHeight: this.element[ 0 ].style.maxHeight,
8194     height: this.element[ 0 ].style.height
8195     };
8196     this.originalPosition = {
8197     parent: this.element.parent(),
8198     index: this.element.parent().children().index( this.element )
8199     };
8200     this.originalTitle = this.element.attr( "title" );
8201     this.options.title = this.options.title || this.originalTitle;
8202    
8203     this._createWrapper();
8204    
8205     this.element
8206     .show()
8207     .removeAttr( "title" )
8208     .addClass( "ui-dialog-content ui-widget-content" )
8209     .appendTo( this.uiDialog );
8210    
8211     this._createTitlebar();
8212     this._createButtonPane();
8213    
8214     if ( this.options.draggable && $.fn.draggable ) {
8215     this._makeDraggable();
8216     }
8217     if ( this.options.resizable && $.fn.resizable ) {
8218     this._makeResizable();
8219     }
8220    
8221     this._isOpen = false;
8222    
8223     this._trackFocus();
8224     },
8225    
8226     _init: function() {
8227     if ( this.options.autoOpen ) {
8228     this.open();
8229     }
8230     },
8231    
8232     _appendTo: function() {
8233     var element = this.options.appendTo;
8234     if ( element && (element.jquery || element.nodeType) ) {
8235     return $( element );
8236     }
8237     return this.document.find( element || "body" ).eq( 0 );
8238     },
8239    
8240     _destroy: function() {
8241     var next,
8242     originalPosition = this.originalPosition;
8243    
8244     this._untrackInstance();
8245     this._destroyOverlay();
8246    
8247     this.element
8248     .removeUniqueId()
8249     .removeClass( "ui-dialog-content ui-widget-content" )
8250     .css( this.originalCss )
8251     // Without detaching first, the following becomes really slow
8252     .detach();
8253    
8254     this.uiDialog.stop( true, true ).remove();
8255    
8256     if ( this.originalTitle ) {
8257     this.element.attr( "title", this.originalTitle );
8258     }
8259    
8260     next = originalPosition.parent.children().eq( originalPosition.index );
8261     // Don't try to place the dialog next to itself (#8613)
8262     if ( next.length && next[ 0 ] !== this.element[ 0 ] ) {
8263     next.before( this.element );
8264     } else {
8265     originalPosition.parent.append( this.element );
8266     }
8267     },
8268    
8269     widget: function() {
8270     return this.uiDialog;
8271     },
8272    
8273     disable: $.noop,
8274     enable: $.noop,
8275    
8276     close: function( event ) {
8277     var activeElement,
8278     that = this;
8279    
8280     if ( !this._isOpen || this._trigger( "beforeClose", event ) === false ) {
8281     return;
8282     }
8283    
8284     this._isOpen = false;
8285     this._focusedElement = null;
8286     this._destroyOverlay();
8287     this._untrackInstance();
8288    
8289     if ( !this.opener.filter( ":focusable" ).focus().length ) {
8290    
8291     // support: IE9
8292     // IE9 throws an "Unspecified error" accessing document.activeElement from an <iframe>
8293     try {
8294     activeElement = this.document[ 0 ].activeElement;
8295    
8296     // Support: IE9, IE10
8297     // If the <body> is blurred, IE will switch windows, see #4520
8298     if ( activeElement && activeElement.nodeName.toLowerCase() !== "body" ) {
8299    
8300     // Hiding a focused element doesn't trigger blur in WebKit
8301     // so in case we have nothing to focus on, explicitly blur the active element
8302     // https://bugs.webkit.org/show_bug.cgi?id=47182
8303     $( activeElement ).blur();
8304     }
8305     } catch ( error ) {}
8306     }
8307    
8308     this._hide( this.uiDialog, this.options.hide, function() {
8309     that._trigger( "close", event );
8310     });
8311     },
8312    
8313     isOpen: function() {
8314     return this._isOpen;
8315     },
8316    
8317     moveToTop: function() {
8318     this._moveToTop();
8319     },
8320    
8321     _moveToTop: function( event, silent ) {
8322     var moved = false,
8323     zIndices = this.uiDialog.siblings( ".ui-front:visible" ).map(function() {
8324     return +$( this ).css( "z-index" );
8325     }).get(),
8326     zIndexMax = Math.max.apply( null, zIndices );
8327    
8328     if ( zIndexMax >= +this.uiDialog.css( "z-index" ) ) {
8329     this.uiDialog.css( "z-index", zIndexMax + 1 );
8330     moved = true;
8331     }
8332    
8333     if ( moved && !silent ) {
8334     this._trigger( "focus", event );
8335     }
8336     return moved;
8337     },
8338    
8339     open: function() {
8340     var that = this;
8341     if ( this._isOpen ) {
8342     if ( this._moveToTop() ) {
8343     this._focusTabbable();
8344     }
8345     return;
8346     }
8347    
8348     this._isOpen = true;
8349     this.opener = $( this.document[ 0 ].activeElement );
8350    
8351     this._size();
8352     this._position();
8353     this._createOverlay();
8354     this._moveToTop( null, true );
8355    
8356     // Ensure the overlay is moved to the top with the dialog, but only when
8357     // opening. The overlay shouldn't move after the dialog is open so that
8358     // modeless dialogs opened after the modal dialog stack properly.
8359     if ( this.overlay ) {
8360     this.overlay.css( "z-index", this.uiDialog.css( "z-index" ) - 1 );
8361     }
8362    
8363     this._show( this.uiDialog, this.options.show, function() {
8364     that._focusTabbable();
8365     that._trigger( "focus" );
8366     });
8367    
8368     // Track the dialog immediately upon openening in case a focus event
8369     // somehow occurs outside of the dialog before an element inside the
8370     // dialog is focused (#10152)
8371     this._makeFocusTarget();
8372    
8373     this._trigger( "open" );
8374     },
8375    
8376     _focusTabbable: function() {
8377     // Set focus to the first match:
8378     // 1. An element that was focused previously
8379     // 2. First element inside the dialog matching [autofocus]
8380     // 3. Tabbable element inside the content element
8381     // 4. Tabbable element inside the buttonpane
8382     // 5. The close button
8383     // 6. The dialog itself
8384     var hasFocus = this._focusedElement;
8385     if ( !hasFocus ) {
8386     hasFocus = this.element.find( "[autofocus]" );
8387     }
8388     if ( !hasFocus.length ) {
8389     hasFocus = this.element.find( ":tabbable" );
8390     }
8391     if ( !hasFocus.length ) {
8392     hasFocus = this.uiDialogButtonPane.find( ":tabbable" );
8393     }
8394     if ( !hasFocus.length ) {
8395     hasFocus = this.uiDialogTitlebarClose.filter( ":tabbable" );
8396     }
8397     if ( !hasFocus.length ) {
8398     hasFocus = this.uiDialog;
8399     }
8400     hasFocus.eq( 0 ).focus();
8401     },
8402    
8403     _keepFocus: function( event ) {
8404     function checkFocus() {
8405     var activeElement = this.document[0].activeElement,
8406     isActive = this.uiDialog[0] === activeElement ||
8407     $.contains( this.uiDialog[0], activeElement );
8408     if ( !isActive ) {
8409     this._focusTabbable();
8410     }
8411     }
8412     event.preventDefault();
8413     checkFocus.call( this );
8414     // support: IE
8415     // IE <= 8 doesn't prevent moving focus even with event.preventDefault()
8416     // so we check again later
8417     this._delay( checkFocus );
8418     },
8419    
8420     _createWrapper: function() {
8421     this.uiDialog = $("<div>")
8422     .addClass( "ui-dialog ui-widget ui-widget-content ui-corner-all ui-front " +
8423     this.options.dialogClass )
8424     .hide()
8425     .attr({
8426     // Setting tabIndex makes the div focusable
8427     tabIndex: -1,
8428     role: "dialog"
8429     })
8430     .appendTo( this._appendTo() );
8431    
8432     this._on( this.uiDialog, {
8433     keydown: function( event ) {
8434     if ( this.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode &&
8435     event.keyCode === $.ui.keyCode.ESCAPE ) {
8436     event.preventDefault();
8437     this.close( event );
8438     return;
8439     }
8440    
8441     // prevent tabbing out of dialogs
8442     if ( event.keyCode !== $.ui.keyCode.TAB || event.isDefaultPrevented() ) {
8443     return;
8444     }
8445     var tabbables = this.uiDialog.find( ":tabbable" ),
8446     first = tabbables.filter( ":first" ),
8447     last = tabbables.filter( ":last" );
8448    
8449     if ( ( event.target === last[0] || event.target === this.uiDialog[0] ) && !event.shiftKey ) {
8450     this._delay(function() {
8451     first.focus();
8452     });
8453     event.preventDefault();
8454     } else if ( ( event.target === first[0] || event.target === this.uiDialog[0] ) && event.shiftKey ) {
8455     this._delay(function() {
8456     last.focus();
8457     });
8458     event.preventDefault();
8459     }
8460     },
8461     mousedown: function( event ) {
8462     if ( this._moveToTop( event ) ) {
8463     this._focusTabbable();
8464     }
8465     }
8466     });
8467    
8468     // We assume that any existing aria-describedby attribute means
8469     // that the dialog content is marked up properly
8470     // otherwise we brute force the content as the description
8471     if ( !this.element.find( "[aria-describedby]" ).length ) {
8472     this.uiDialog.attr({
8473     "aria-describedby": this.element.uniqueId().attr( "id" )
8474     });
8475     }
8476     },
8477    
8478     _createTitlebar: function() {
8479     var uiDialogTitle;
8480    
8481     this.uiDialogTitlebar = $( "<div>" )
8482     .addClass( "ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix" )
8483     .prependTo( this.uiDialog );
8484     this._on( this.uiDialogTitlebar, {
8485     mousedown: function( event ) {
8486     // Don't prevent click on close button (#8838)
8487     // Focusing a dialog that is partially scrolled out of view
8488     // causes the browser to scroll it into view, preventing the click event
8489     if ( !$( event.target ).closest( ".ui-dialog-titlebar-close" ) ) {
8490     // Dialog isn't getting focus when dragging (#8063)
8491     this.uiDialog.focus();
8492     }
8493     }
8494     });
8495    
8496     // support: IE
8497     // Use type="button" to prevent enter keypresses in textboxes from closing the
8498     // dialog in IE (#9312)
8499     this.uiDialogTitlebarClose = $( "<button type='button'></button>" )
8500     .button({
8501     label: this.options.closeText,
8502     icons: {
8503     primary: "ui-icon-closethick"
8504     },
8505     text: false
8506     })
8507     .addClass( "ui-dialog-titlebar-close" )
8508     .appendTo( this.uiDialogTitlebar );
8509     this._on( this.uiDialogTitlebarClose, {
8510     click: function( event ) {
8511     event.preventDefault();
8512     this.close( event );
8513     }
8514     });
8515    
8516     uiDialogTitle = $( "<span>" )
8517     .uniqueId()
8518     .addClass( "ui-dialog-title" )
8519     .prependTo( this.uiDialogTitlebar );
8520     this._title( uiDialogTitle );
8521    
8522     this.uiDialog.attr({
8523     "aria-labelledby": uiDialogTitle.attr( "id" )
8524     });
8525     },
8526    
8527     _title: function( title ) {
8528     if ( !this.options.title ) {
8529     title.html( "&#160;" );
8530     }
8531     title.text( this.options.title );
8532     },
8533    
8534     _createButtonPane: function() {
8535     this.uiDialogButtonPane = $( "<div>" )
8536     .addClass( "ui-dialog-buttonpane ui-widget-content ui-helper-clearfix" );
8537    
8538     this.uiButtonSet = $( "<div>" )
8539     .addClass( "ui-dialog-buttonset" )
8540     .appendTo( this.uiDialogButtonPane );
8541    
8542     this._createButtons();
8543     },
8544    
8545     _createButtons: function() {
8546     var that = this,
8547     buttons = this.options.buttons;
8548    
8549     // if we already have a button pane, remove it
8550     this.uiDialogButtonPane.remove();
8551     this.uiButtonSet.empty();
8552    
8553     if ( $.isEmptyObject( buttons ) || ($.isArray( buttons ) && !buttons.length) ) {
8554     this.uiDialog.removeClass( "ui-dialog-buttons" );
8555     return;
8556     }
8557    
8558     $.each( buttons, function( name, props ) {
8559     var click, buttonOptions;
8560     props = $.isFunction( props ) ?
8561     { click: props, text: name } :
8562     props;
8563     // Default to a non-submitting button
8564     props = $.extend( { type: "button" }, props );
8565     // Change the context for the click callback to be the main element
8566     click = props.click;
8567     props.click = function() {
8568     click.apply( that.element[ 0 ], arguments );
8569     };
8570     buttonOptions = {
8571     icons: props.icons,
8572     text: props.showText
8573     };
8574     delete props.icons;
8575     delete props.showText;
8576     $( "<button></button>", props )
8577     .button( buttonOptions )
8578     .appendTo( that.uiButtonSet );
8579     });
8580     this.uiDialog.addClass( "ui-dialog-buttons" );
8581     this.uiDialogButtonPane.appendTo( this.uiDialog );
8582     },
8583    
8584     _makeDraggable: function() {
8585     var that = this,
8586     options = this.options;
8587    
8588     function filteredUi( ui ) {
8589     return {
8590     position: ui.position,
8591     offset: ui.offset
8592     };
8593     }
8594    
8595     this.uiDialog.draggable({
8596     cancel: ".ui-dialog-content, .ui-dialog-titlebar-close",
8597     handle: ".ui-dialog-titlebar",
8598     containment: "document",
8599     start: function( event, ui ) {
8600     $( this ).addClass( "ui-dialog-dragging" );
8601     that._blockFrames();
8602     that._trigger( "dragStart", event, filteredUi( ui ) );
8603     },
8604     drag: function( event, ui ) {
8605     that._trigger( "drag", event, filteredUi( ui ) );
8606     },
8607     stop: function( event, ui ) {
8608     var left = ui.offset.left - that.document.scrollLeft(),
8609     top = ui.offset.top - that.document.scrollTop();
8610    
8611     options.position = {
8612     my: "left top",
8613     at: "left" + (left >= 0 ? "+" : "") + left + " " +
8614     "top" + (top >= 0 ? "+" : "") + top,
8615     of: that.window
8616     };
8617     $( this ).removeClass( "ui-dialog-dragging" );
8618     that._unblockFrames();
8619     that._trigger( "dragStop", event, filteredUi( ui ) );
8620     }
8621     });
8622     },
8623    
8624     _makeResizable: function() {
8625     var that = this,
8626     options = this.options,
8627     handles = options.resizable,
8628     // .ui-resizable has position: relative defined in the stylesheet
8629     // but dialogs have to use absolute or fixed positioning
8630     position = this.uiDialog.css("position"),
8631     resizeHandles = typeof handles === "string" ?
8632     handles :
8633     "n,e,s,w,se,sw,ne,nw";
8634    
8635     function filteredUi( ui ) {
8636     return {
8637     originalPosition: ui.originalPosition,
8638     originalSize: ui.originalSize,
8639     position: ui.position,
8640     size: ui.size
8641     };
8642     }
8643    
8644     this.uiDialog.resizable({
8645     cancel: ".ui-dialog-content",
8646     containment: "document",
8647     alsoResize: this.element,
8648     maxWidth: options.maxWidth,
8649     maxHeight: options.maxHeight,
8650     minWidth: options.minWidth,
8651     minHeight: this._minHeight(),
8652     handles: resizeHandles,
8653     start: function( event, ui ) {
8654     $( this ).addClass( "ui-dialog-resizing" );
8655     that._blockFrames();
8656     that._trigger( "resizeStart", event, filteredUi( ui ) );
8657     },
8658     resize: function( event, ui ) {
8659     that._trigger( "resize", event, filteredUi( ui ) );
8660     },
8661     stop: function( event, ui ) {
8662     var offset = that.uiDialog.offset(),
8663     left = offset.left - that.document.scrollLeft(),
8664     top = offset.top - that.document.scrollTop();
8665    
8666     options.height = that.uiDialog.height();
8667     options.width = that.uiDialog.width();
8668     options.position = {
8669     my: "left top",
8670     at: "left" + (left >= 0 ? "+" : "") + left + " " +
8671     "top" + (top >= 0 ? "+" : "") + top,
8672     of: that.window
8673     };
8674     $( this ).removeClass( "ui-dialog-resizing" );
8675     that._unblockFrames();
8676     that._trigger( "resizeStop", event, filteredUi( ui ) );
8677     }
8678     })
8679     .css( "position", position );
8680     },
8681    
8682     _trackFocus: function() {
8683     this._on( this.widget(), {
8684     focusin: function( event ) {
8685     this._makeFocusTarget();
8686     this._focusedElement = $( event.target );
8687     }
8688     });
8689     },
8690    
8691     _makeFocusTarget: function() {
8692     this._untrackInstance();
8693     this._trackingInstances().unshift( this );
8694     },
8695    
8696     _untrackInstance: function() {
8697     var instances = this._trackingInstances(),
8698     exists = $.inArray( this, instances );
8699     if ( exists !== -1 ) {
8700     instances.splice( exists, 1 );
8701     }
8702     },
8703    
8704     _trackingInstances: function() {
8705     var instances = this.document.data( "ui-dialog-instances" );
8706     if ( !instances ) {
8707     instances = [];
8708     this.document.data( "ui-dialog-instances", instances );
8709     }
8710     return instances;
8711     },
8712    
8713     _minHeight: function() {
8714     var options = this.options;
8715    
8716     return options.height === "auto" ?
8717     options.minHeight :
8718     Math.min( options.minHeight, options.height );
8719     },
8720    
8721     _position: function() {
8722     // Need to show the dialog to get the actual offset in the position plugin
8723     var isVisible = this.uiDialog.is( ":visible" );
8724     if ( !isVisible ) {
8725     this.uiDialog.show();
8726     }
8727     this.uiDialog.position( this.options.position );
8728     if ( !isVisible ) {
8729     this.uiDialog.hide();
8730     }
8731     },
8732    
8733     _setOptions: function( options ) {
8734     var that = this,
8735     resize = false,
8736     resizableOptions = {};
8737    
8738     $.each( options, function( key, value ) {
8739     that._setOption( key, value );
8740    
8741     if ( key in that.sizeRelatedOptions ) {
8742     resize = true;
8743     }
8744     if ( key in that.resizableRelatedOptions ) {
8745     resizableOptions[ key ] = value;
8746     }
8747     });
8748    
8749     if ( resize ) {
8750     this._size();
8751     this._position();
8752     }
8753     if ( this.uiDialog.is( ":data(ui-resizable)" ) ) {
8754     this.uiDialog.resizable( "option", resizableOptions );
8755     }
8756     },
8757    
8758     _setOption: function( key, value ) {
8759     var isDraggable, isResizable,
8760     uiDialog = this.uiDialog;
8761    
8762     if ( key === "dialogClass" ) {
8763     uiDialog
8764     .removeClass( this.options.dialogClass )
8765     .addClass( value );
8766     }
8767    
8768     if ( key === "disabled" ) {
8769     return;
8770     }
8771    
8772     this._super( key, value );
8773    
8774     if ( key === "appendTo" ) {
8775     this.uiDialog.appendTo( this._appendTo() );
8776     }
8777    
8778     if ( key === "buttons" ) {
8779     this._createButtons();
8780     }
8781    
8782     if ( key === "closeText" ) {
8783     this.uiDialogTitlebarClose.button({
8784     // Ensure that we always pass a string
8785     label: "" + value
8786     });
8787     }
8788    
8789     if ( key === "draggable" ) {
8790     isDraggable = uiDialog.is( ":data(ui-draggable)" );
8791     if ( isDraggable && !value ) {
8792     uiDialog.draggable( "destroy" );
8793     }
8794    
8795     if ( !isDraggable && value ) {
8796     this._makeDraggable();
8797     }
8798     }
8799    
8800     if ( key === "position" ) {
8801     this._position();
8802     }
8803    
8804     if ( key === "resizable" ) {
8805     // currently resizable, becoming non-resizable
8806     isResizable = uiDialog.is( ":data(ui-resizable)" );
8807     if ( isResizable && !value ) {
8808     uiDialog.resizable( "destroy" );
8809     }
8810    
8811     // currently resizable, changing handles
8812     if ( isResizable && typeof value === "string" ) {
8813     uiDialog.resizable( "option", "handles", value );
8814     }
8815    
8816     // currently non-resizable, becoming resizable
8817     if ( !isResizable && value !== false ) {
8818     this._makeResizable();
8819     }
8820     }
8821    
8822     if ( key === "title" ) {
8823     this._title( this.uiDialogTitlebar.find( ".ui-dialog-title" ) );
8824     }
8825     },
8826    
8827     _size: function() {
8828     // If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
8829     // divs will both have width and height set, so we need to reset them
8830     var nonContentHeight, minContentHeight, maxContentHeight,
8831     options = this.options;
8832    
8833     // Reset content sizing
8834     this.element.show().css({
8835     width: "auto",
8836     minHeight: 0,
8837     maxHeight: "none",
8838     height: 0
8839     });
8840    
8841     if ( options.minWidth > options.width ) {
8842     options.width = options.minWidth;
8843     }
8844    
8845     // reset wrapper sizing
8846     // determine the height of all the non-content elements
8847     nonContentHeight = this.uiDialog.css({
8848     height: "auto",
8849     width: options.width
8850     })
8851     .outerHeight();
8852     minContentHeight = Math.max( 0, options.minHeight - nonContentHeight );
8853     maxContentHeight = typeof options.maxHeight === "number" ?
8854     Math.max( 0, options.maxHeight - nonContentHeight ) :
8855     "none";
8856    
8857     if ( options.height === "auto" ) {
8858     this.element.css({
8859     minHeight: minContentHeight,
8860     maxHeight: maxContentHeight,
8861     height: "auto"
8862     });
8863     } else {
8864     this.element.height( Math.max( 0, options.height - nonContentHeight ) );
8865     }
8866    
8867     if ( this.uiDialog.is( ":data(ui-resizable)" ) ) {
8868     this.uiDialog.resizable( "option", "minHeight", this._minHeight() );
8869     }
8870     },
8871    
8872     _blockFrames: function() {
8873     this.iframeBlocks = this.document.find( "iframe" ).map(function() {
8874     var iframe = $( this );
8875    
8876     return $( "<div>" )
8877     .css({
8878     position: "absolute",
8879     width: iframe.outerWidth(),
8880     height: iframe.outerHeight()
8881     })
8882     .appendTo( iframe.parent() )
8883     .offset( iframe.offset() )[0];
8884     });
8885     },
8886    
8887     _unblockFrames: function() {
8888     if ( this.iframeBlocks ) {
8889     this.iframeBlocks.remove();
8890     delete this.iframeBlocks;
8891     }
8892     },
8893    
8894     _allowInteraction: function( event ) {
8895     if ( $( event.target ).closest( ".ui-dialog" ).length ) {
8896     return true;
8897     }
8898    
8899     // TODO: Remove hack when datepicker implements
8900     // the .ui-front logic (#8989)
8901     return !!$( event.target ).closest( ".ui-datepicker" ).length;
8902     },
8903    
8904     _createOverlay: function() {
8905     if ( !this.options.modal ) {
8906     return;
8907     }
8908    
8909     // We use a delay in case the overlay is created from an
8910     // event that we're going to be cancelling (#2804)
8911     var isOpening = true;
8912     this._delay(function() {
8913     isOpening = false;
8914     });
8915    
8916     if ( !this.document.data( "ui-dialog-overlays" ) ) {
8917    
8918     // Prevent use of anchors and inputs
8919     // Using _on() for an event handler shared across many instances is
8920     // safe because the dialogs stack and must be closed in reverse order
8921     this._on( this.document, {
8922     focusin: function( event ) {
8923     if ( isOpening ) {
8924     return;
8925     }
8926    
8927     if ( !this._allowInteraction( event ) ) {
8928     event.preventDefault();
8929     this._trackingInstances()[ 0 ]._focusTabbable();
8930     }
8931     }
8932     });
8933     }
8934    
8935     this.overlay = $( "<div>" )
8936     .addClass( "ui-widget-overlay ui-front" )
8937     .appendTo( this._appendTo() );
8938     this._on( this.overlay, {
8939     mousedown: "_keepFocus"
8940     });
8941     this.document.data( "ui-dialog-overlays",
8942     (this.document.data( "ui-dialog-overlays" ) || 0) + 1 );
8943     },
8944    
8945     _destroyOverlay: function() {
8946     if ( !this.options.modal ) {
8947     return;
8948     }
8949    
8950     if ( this.overlay ) {
8951     var overlays = this.document.data( "ui-dialog-overlays" ) - 1;
8952    
8953     if ( !overlays ) {
8954     this.document
8955     .unbind( "focusin" )
8956     .removeData( "ui-dialog-overlays" );
8957     } else {
8958     this.document.data( "ui-dialog-overlays", overlays );
8959     }
8960    
8961     this.overlay.remove();
8962     this.overlay = null;
8963     }
8964     }
8965     });
8966    
8967    
8968     /*!
8969     * jQuery UI Droppable 1.11.4
8970     * http://jqueryui.com
8971     *
8972     * Copyright jQuery Foundation and other contributors
8973     * Released under the MIT license.
8974     * http://jquery.org/license
8975     *
8976     * http://api.jqueryui.com/droppable/
8977     */
8978    
8979    
8980     $.widget( "ui.droppable", {
8981     version: "1.11.4",
8982     widgetEventPrefix: "drop",
8983     options: {
8984     accept: "*",
8985     activeClass: false,
8986     addClasses: true,
8987     greedy: false,
8988     hoverClass: false,
8989     scope: "default",
8990     tolerance: "intersect",
8991    
8992     // callbacks
8993     activate: null,
8994     deactivate: null,
8995     drop: null,
8996     out: null,
8997     over: null
8998     },
8999     _create: function() {
9000    
9001     var proportions,
9002     o = this.options,
9003     accept = o.accept;
9004    
9005     this.isover = false;
9006     this.isout = true;
9007    
9008     this.accept = $.isFunction( accept ) ? accept : function( d ) {
9009     return d.is( accept );
9010     };
9011    
9012     this.proportions = function( /* valueToWrite */ ) {
9013     if ( arguments.length ) {
9014     // Store the droppable's proportions
9015     proportions = arguments[ 0 ];
9016     } else {
9017     // Retrieve or derive the droppable's proportions
9018     return proportions ?
9019     proportions :
9020     proportions = {
9021     width: this.element[ 0 ].offsetWidth,
9022     height: this.element[ 0 ].offsetHeight
9023     };
9024     }
9025     };
9026    
9027     this._addToManager( o.scope );
9028    
9029     o.addClasses && this.element.addClass( "ui-droppable" );
9030    
9031     },
9032    
9033     _addToManager: function( scope ) {
9034     // Add the reference and positions to the manager
9035     $.ui.ddmanager.droppables[ scope ] = $.ui.ddmanager.droppables[ scope ] || [];
9036     $.ui.ddmanager.droppables[ scope ].push( this );
9037     },
9038    
9039     _splice: function( drop ) {
9040     var i = 0;
9041     for ( ; i < drop.length; i++ ) {
9042     if ( drop[ i ] === this ) {
9043     drop.splice( i, 1 );
9044     }
9045     }
9046     },
9047    
9048     _destroy: function() {
9049     var drop = $.ui.ddmanager.droppables[ this.options.scope ];
9050    
9051     this._splice( drop );
9052    
9053     this.element.removeClass( "ui-droppable ui-droppable-disabled" );
9054     },
9055    
9056     _setOption: function( key, value ) {
9057    
9058     if ( key === "accept" ) {
9059     this.accept = $.isFunction( value ) ? value : function( d ) {
9060     return d.is( value );
9061     };
9062     } else if ( key === "scope" ) {
9063     var drop = $.ui.ddmanager.droppables[ this.options.scope ];
9064    
9065     this._splice( drop );
9066     this._addToManager( value );
9067     }
9068    
9069     this._super( key, value );
9070     },
9071    
9072     _activate: function( event ) {
9073     var draggable = $.ui.ddmanager.current;
9074     if ( this.options.activeClass ) {
9075     this.element.addClass( this.options.activeClass );
9076     }
9077     if ( draggable ){
9078     this._trigger( "activate", event, this.ui( draggable ) );
9079     }
9080     },
9081    
9082     _deactivate: function( event ) {
9083     var draggable = $.ui.ddmanager.current;
9084     if ( this.options.activeClass ) {
9085     this.element.removeClass( this.options.activeClass );
9086     }
9087     if ( draggable ){
9088     this._trigger( "deactivate", event, this.ui( draggable ) );
9089     }
9090     },
9091    
9092     _over: function( event ) {
9093    
9094     var draggable = $.ui.ddmanager.current;
9095    
9096     // Bail if draggable and droppable are same element
9097     if ( !draggable || ( draggable.currentItem || draggable.element )[ 0 ] === this.element[ 0 ] ) {
9098     return;
9099     }
9100    
9101     if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem || draggable.element ) ) ) {
9102     if ( this.options.hoverClass ) {
9103     this.element.addClass( this.options.hoverClass );
9104     }
9105     this._trigger( "over", event, this.ui( draggable ) );
9106     }
9107    
9108     },
9109    
9110     _out: function( event ) {
9111    
9112     var draggable = $.ui.ddmanager.current;
9113    
9114     // Bail if draggable and droppable are same element
9115     if ( !draggable || ( draggable.currentItem || draggable.element )[ 0 ] === this.element[ 0 ] ) {
9116     return;
9117     }
9118    
9119     if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem || draggable.element ) ) ) {
9120     if ( this.options.hoverClass ) {
9121     this.element.removeClass( this.options.hoverClass );
9122     }
9123     this._trigger( "out", event, this.ui( draggable ) );
9124     }
9125    
9126     },
9127    
9128     _drop: function( event, custom ) {
9129    
9130     var draggable = custom || $.ui.ddmanager.current,
9131     childrenIntersection = false;
9132    
9133     // Bail if draggable and droppable are same element
9134     if ( !draggable || ( draggable.currentItem || draggable.element )[ 0 ] === this.element[ 0 ] ) {
9135     return false;
9136     }
9137    
9138     this.element.find( ":data(ui-droppable)" ).not( ".ui-draggable-dragging" ).each(function() {
9139     var inst = $( this ).droppable( "instance" );
9140     if (
9141     inst.options.greedy &&
9142     !inst.options.disabled &&
9143     inst.options.scope === draggable.options.scope &&
9144     inst.accept.call( inst.element[ 0 ], ( draggable.currentItem || draggable.element ) ) &&
9145     $.ui.intersect( draggable, $.extend( inst, { offset: inst.element.offset() } ), inst.options.tolerance, event )
9146     ) { childrenIntersection = true; return false; }
9147     });
9148     if ( childrenIntersection ) {
9149     return false;
9150     }
9151    
9152     if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem || draggable.element ) ) ) {
9153     if ( this.options.activeClass ) {
9154     this.element.removeClass( this.options.activeClass );
9155     }
9156     if ( this.options.hoverClass ) {
9157     this.element.removeClass( this.options.hoverClass );
9158     }
9159     this._trigger( "drop", event, this.ui( draggable ) );
9160     return this.element;
9161     }
9162    
9163     return false;
9164    
9165     },
9166    
9167     ui: function( c ) {
9168     return {
9169     draggable: ( c.currentItem || c.element ),
9170     helper: c.helper,
9171     position: c.position,
9172     offset: c.positionAbs
9173     };
9174     }
9175    
9176     });
9177    
9178     $.ui.intersect = (function() {
9179     function isOverAxis( x, reference, size ) {
9180     return ( x >= reference ) && ( x < ( reference + size ) );
9181     }
9182    
9183     return function( draggable, droppable, toleranceMode, event ) {
9184    
9185     if ( !droppable.offset ) {
9186     return false;
9187     }
9188    
9189     var x1 = ( draggable.positionAbs || draggable.position.absolute ).left + draggable.margins.left,
9190     y1 = ( draggable.positionAbs || draggable.position.absolute ).top + draggable.margins.top,
9191     x2 = x1 + draggable.helperProportions.width,
9192     y2 = y1 + draggable.helperProportions.height,
9193     l = droppable.offset.left,
9194     t = droppable.offset.top,
9195     r = l + droppable.proportions().width,
9196     b = t + droppable.proportions().height;
9197    
9198     switch ( toleranceMode ) {
9199     case "fit":
9200     return ( l <= x1 && x2 <= r && t <= y1 && y2 <= b );
9201     case "intersect":
9202     return ( l < x1 + ( draggable.helperProportions.width / 2 ) && // Right Half
9203     x2 - ( draggable.helperProportions.width / 2 ) < r && // Left Half
9204     t < y1 + ( draggable.helperProportions.height / 2 ) && // Bottom Half
9205     y2 - ( draggable.helperProportions.height / 2 ) < b ); // Top Half
9206     case "pointer":
9207     return isOverAxis( event.pageY, t, droppable.proportions().height ) && isOverAxis( event.pageX, l, droppable.proportions().width );
9208     case "touch":
9209     return (
9210     ( y1 >= t && y1 <= b ) || // Top edge touching
9211     ( y2 >= t && y2 <= b ) || // Bottom edge touching
9212     ( y1 < t && y2 > b ) // Surrounded vertically
9213     ) && (
9214     ( x1 >= l && x1 <= r ) || // Left edge touching
9215     ( x2 >= l && x2 <= r ) || // Right edge touching
9216     ( x1 < l && x2 > r ) // Surrounded horizontally
9217     );
9218     default:
9219     return false;
9220     }
9221     };
9222     })();
9223    
9224     /*
9225     This manager tracks offsets of draggables and droppables
9226     */
9227     $.ui.ddmanager = {
9228     current: null,
9229     droppables: { "default": [] },
9230     prepareOffsets: function( t, event ) {
9231    
9232     var i, j,
9233     m = $.ui.ddmanager.droppables[ t.options.scope ] || [],
9234     type = event ? event.type : null, // workaround for #2317
9235     list = ( t.currentItem || t.element ).find( ":data(ui-droppable)" ).addBack();
9236    
9237     droppablesLoop: for ( i = 0; i < m.length; i++ ) {
9238    
9239     // No disabled and non-accepted
9240     if ( m[ i ].options.disabled || ( t && !m[ i ].accept.call( m[ i ].element[ 0 ], ( t.currentItem || t.element ) ) ) ) {
9241     continue;
9242     }
9243    
9244     // Filter out elements in the current dragged item
9245     for ( j = 0; j < list.length; j++ ) {
9246     if ( list[ j ] === m[ i ].element[ 0 ] ) {
9247     m[ i ].proportions().height = 0;
9248     continue droppablesLoop;
9249     }
9250     }
9251    
9252     m[ i ].visible = m[ i ].element.css( "display" ) !== "none";
9253     if ( !m[ i ].visible ) {
9254     continue;
9255     }
9256    
9257     // Activate the droppable if used directly from draggables
9258     if ( type === "mousedown" ) {
9259     m[ i ]._activate.call( m[ i ], event );
9260     }
9261    
9262     m[ i ].offset = m[ i ].element.offset();
9263     m[ i ].proportions({ width: m[ i ].element[ 0 ].offsetWidth, height: m[ i ].element[ 0 ].offsetHeight });
9264    
9265     }
9266    
9267     },
9268     drop: function( draggable, event ) {
9269    
9270     var dropped = false;
9271     // Create a copy of the droppables in case the list changes during the drop (#9116)
9272     $.each( ( $.ui.ddmanager.droppables[ draggable.options.scope ] || [] ).slice(), function() {
9273    
9274     if ( !this.options ) {
9275     return;
9276     }
9277     if ( !this.options.disabled && this.visible && $.ui.intersect( draggable, this, this.options.tolerance, event ) ) {
9278     dropped = this._drop.call( this, event ) || dropped;
9279     }
9280    
9281     if ( !this.options.disabled && this.visible && this.accept.call( this.element[ 0 ], ( draggable.currentItem || draggable.element ) ) ) {
9282     this.isout = true;
9283     this.isover = false;
9284     this._deactivate.call( this, event );
9285     }
9286    
9287     });
9288     return dropped;
9289    
9290     },
9291     dragStart: function( draggable, event ) {
9292     // Listen for scrolling so that if the dragging causes scrolling the position of the droppables can be recalculated (see #5003)
9293     draggable.element.parentsUntil( "body" ).bind( "scroll.droppable", function() {
9294     if ( !draggable.options.refreshPositions ) {
9295     $.ui.ddmanager.prepareOffsets( draggable, event );
9296     }
9297     });
9298     },
9299     drag: function( draggable, event ) {
9300    
9301     // If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse.
9302     if ( draggable.options.refreshPositions ) {
9303     $.ui.ddmanager.prepareOffsets( draggable, event );
9304     }
9305    
9306     // Run through all droppables and check their positions based on specific tolerance options
9307     $.each( $.ui.ddmanager.droppables[ draggable.options.scope ] || [], function() {
9308    
9309     if ( this.options.disabled || this.greedyChild || !this.visible ) {
9310     return;
9311     }
9312    
9313     var parentInstance, scope, parent,
9314     intersects = $.ui.intersect( draggable, this, this.options.tolerance, event ),
9315     c = !intersects && this.isover ? "isout" : ( intersects && !this.isover ? "isover" : null );
9316     if ( !c ) {
9317     return;
9318     }
9319    
9320     if ( this.options.greedy ) {
9321     // find droppable parents with same scope
9322     scope = this.options.scope;
9323     parent = this.element.parents( ":data(ui-droppable)" ).filter(function() {
9324     return $( this ).droppable( "instance" ).options.scope === scope;
9325     });
9326    
9327     if ( parent.length ) {
9328     parentInstance = $( parent[ 0 ] ).droppable( "instance" );
9329     parentInstance.greedyChild = ( c === "isover" );
9330     }
9331     }
9332    
9333     // we just moved into a greedy child
9334     if ( parentInstance && c === "isover" ) {
9335     parentInstance.isover = false;
9336     parentInstance.isout = true;
9337     parentInstance._out.call( parentInstance, event );
9338     }
9339    
9340     this[ c ] = true;
9341     this[c === "isout" ? "isover" : "isout"] = false;
9342     this[c === "isover" ? "_over" : "_out"].call( this, event );
9343    
9344     // we just moved out of a greedy child
9345     if ( parentInstance && c === "isout" ) {
9346     parentInstance.isout = false;
9347     parentInstance.isover = true;
9348     parentInstance._over.call( parentInstance, event );
9349     }
9350     });
9351    
9352     },
9353     dragStop: function( draggable, event ) {
9354     draggable.element.parentsUntil( "body" ).unbind( "scroll.droppable" );
9355     // Call prepareOffsets one final time since IE does not fire return scroll events when overflow was caused by drag (see #5003)
9356     if ( !draggable.options.refreshPositions ) {
9357     $.ui.ddmanager.prepareOffsets( draggable, event );
9358     }
9359     }
9360     };
9361    
9362     var droppable = $.ui.droppable;
9363    
9364    
9365     /*!
9366     * jQuery UI Effects 1.11.4
9367     * http://jqueryui.com
9368     *
9369     * Copyright jQuery Foundation and other contributors
9370     * Released under the MIT license.
9371     * http://jquery.org/license
9372     *
9373     * http://api.jqueryui.com/category/effects-core/
9374     */
9375    
9376    
9377     var dataSpace = "ui-effects-",
9378    
9379     // Create a local jQuery because jQuery Color relies on it and the
9380     // global may not exist with AMD and a custom build (#10199)
9381     jQuery = $;
9382    
9383     $.effects = {
9384     effect: {}
9385     };
9386    
9387     /*!
9388     * jQuery Color Animations v2.1.2
9389     * https://github.com/jquery/jquery-color
9390     *
9391     * Copyright 2014 jQuery Foundation and other contributors
9392     * Released under the MIT license.
9393     * http://jquery.org/license
9394     *
9395     * Date: Wed Jan 16 08:47:09 2013 -0600
9396     */
9397     (function( jQuery, undefined ) {
9398    
9399     var stepHooks = "backgroundColor borderBottomColor borderLeftColor borderRightColor borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor",
9400    
9401     // plusequals test for += 100 -= 100
9402     rplusequals = /^([\-+])=\s*(\d+\.?\d*)/,
9403     // a set of RE's that can match strings and generate color tuples.
9404     stringParsers = [ {
9405     re: /rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
9406     parse: function( execResult ) {
9407     return [
9408     execResult[ 1 ],
9409     execResult[ 2 ],
9410     execResult[ 3 ],
9411     execResult[ 4 ]
9412     ];
9413     }
9414     }, {
9415     re: /rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
9416     parse: function( execResult ) {
9417     return [
9418     execResult[ 1 ] * 2.55,
9419     execResult[ 2 ] * 2.55,
9420     execResult[ 3 ] * 2.55,
9421     execResult[ 4 ]
9422     ];
9423     }
9424     }, {
9425     // this regex ignores A-F because it's compared against an already lowercased string
9426     re: /#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/,
9427     parse: function( execResult ) {
9428     return [
9429     parseInt( execResult[ 1 ], 16 ),
9430     parseInt( execResult[ 2 ], 16 ),
9431     parseInt( execResult[ 3 ], 16 )
9432     ];
9433     }
9434     }, {
9435     // this regex ignores A-F because it's compared against an already lowercased string
9436     re: /#([a-f0-9])([a-f0-9])([a-f0-9])/,
9437     parse: function( execResult ) {
9438     return [
9439     parseInt( execResult[ 1 ] + execResult[ 1 ], 16 ),
9440     parseInt( execResult[ 2 ] + execResult[ 2 ], 16 ),
9441     parseInt( execResult[ 3 ] + execResult[ 3 ], 16 )
9442     ];
9443     }
9444     }, {
9445     re: /hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
9446     space: "hsla",
9447     parse: function( execResult ) {
9448     return [
9449     execResult[ 1 ],
9450     execResult[ 2 ] / 100,
9451     execResult[ 3 ] / 100,
9452     execResult[ 4 ]
9453     ];
9454     }
9455     } ],
9456    
9457     // jQuery.Color( )
9458     color = jQuery.Color = function( color, green, blue, alpha ) {
9459     return new jQuery.Color.fn.parse( color, green, blue, alpha );
9460     },
9461     spaces = {
9462     rgba: {
9463     props: {
9464     red: {
9465     idx: 0,
9466     type: "byte"
9467     },
9468     green: {
9469     idx: 1,
9470     type: "byte"
9471     },
9472     blue: {
9473     idx: 2,
9474     type: "byte"
9475     }
9476     }
9477     },
9478    
9479     hsla: {
9480     props: {
9481     hue: {
9482     idx: 0,
9483     type: "degrees"
9484     },
9485     saturation: {
9486     idx: 1,
9487     type: "percent"
9488     },
9489     lightness: {
9490     idx: 2,
9491     type: "percent"
9492     }
9493     }
9494     }
9495     },
9496     propTypes = {
9497     "byte": {
9498     floor: true,
9499     max: 255
9500     },
9501     "percent": {
9502     max: 1
9503     },
9504     "degrees": {
9505     mod: 360,
9506     floor: true
9507     }
9508     },
9509     support = color.support = {},
9510    
9511     // element for support tests
9512     supportElem = jQuery( "<p>" )[ 0 ],
9513    
9514     // colors = jQuery.Color.names
9515     colors,
9516    
9517     // local aliases of functions called often
9518     each = jQuery.each;
9519    
9520     // determine rgba support immediately
9521     supportElem.style.cssText = "background-color:rgba(1,1,1,.5)";
9522     support.rgba = supportElem.style.backgroundColor.indexOf( "rgba" ) > -1;
9523    
9524     // define cache name and alpha properties
9525     // for rgba and hsla spaces
9526     each( spaces, function( spaceName, space ) {
9527     space.cache = "_" + spaceName;
9528     space.props.alpha = {
9529     idx: 3,
9530     type: "percent",
9531     def: 1
9532     };
9533     });
9534    
9535     function clamp( value, prop, allowEmpty ) {
9536     var type = propTypes[ prop.type ] || {};
9537    
9538     if ( value == null ) {
9539     return (allowEmpty || !prop.def) ? null : prop.def;
9540     }
9541    
9542     // ~~ is an short way of doing floor for positive numbers
9543     value = type.floor ? ~~value : parseFloat( value );
9544    
9545     // IE will pass in empty strings as value for alpha,
9546     // which will hit this case
9547     if ( isNaN( value ) ) {
9548     return prop.def;
9549     }
9550    
9551     if ( type.mod ) {
9552     // we add mod before modding to make sure that negatives values
9553     // get converted properly: -10 -> 350
9554     return (value + type.mod) % type.mod;
9555     }
9556    
9557     // for now all property types without mod have min and max
9558     return 0 > value ? 0 : type.max < value ? type.max : value;
9559     }
9560    
9561     function stringParse( string ) {
9562     var inst = color(),
9563     rgba = inst._rgba = [];
9564    
9565     string = string.toLowerCase();
9566    
9567     each( stringParsers, function( i, parser ) {
9568     var parsed,
9569     match = parser.re.exec( string ),
9570     values = match && parser.parse( match ),
9571     spaceName = parser.space || "rgba";
9572    
9573     if ( values ) {
9574     parsed = inst[ spaceName ]( values );
9575    
9576     // if this was an rgba parse the assignment might happen twice
9577     // oh well....
9578     inst[ spaces[ spaceName ].cache ] = parsed[ spaces[ spaceName ].cache ];
9579     rgba = inst._rgba = parsed._rgba;
9580    
9581     // exit each( stringParsers ) here because we matched
9582     return false;
9583     }
9584     });
9585    
9586     // Found a stringParser that handled it
9587     if ( rgba.length ) {
9588    
9589     // if this came from a parsed string, force "transparent" when alpha is 0
9590     // chrome, (and maybe others) return "transparent" as rgba(0,0,0,0)
9591     if ( rgba.join() === "0,0,0,0" ) {
9592     jQuery.extend( rgba, colors.transparent );
9593     }
9594     return inst;
9595     }
9596    
9597     // named colors
9598     return colors[ string ];
9599     }
9600    
9601     color.fn = jQuery.extend( color.prototype, {
9602     parse: function( red, green, blue, alpha ) {
9603     if ( red === undefined ) {
9604     this._rgba = [ null, null, null, null ];
9605     return this;
9606     }
9607     if ( red.jquery || red.nodeType ) {
9608     red = jQuery( red ).css( green );
9609     green = undefined;
9610     }
9611    
9612     var inst = this,
9613     type = jQuery.type( red ),
9614     rgba = this._rgba = [];
9615    
9616     // more than 1 argument specified - assume ( red, green, blue, alpha )
9617     if ( green !== undefined ) {
9618     red = [ red, green, blue, alpha ];
9619     type = "array";
9620     }
9621    
9622     if ( type === "string" ) {
9623     return this.parse( stringParse( red ) || colors._default );
9624     }
9625    
9626     if ( type === "array" ) {
9627     each( spaces.rgba.props, function( key, prop ) {
9628     rgba[ prop.idx ] = clamp( red[ prop.idx ], prop );
9629     });
9630     return this;
9631     }
9632    
9633     if ( type === "object" ) {
9634     if ( red instanceof color ) {
9635     each( spaces, function( spaceName, space ) {
9636     if ( red[ space.cache ] ) {
9637     inst[ space.cache ] = red[ space.cache ].slice();
9638     }
9639     });
9640     } else {
9641     each( spaces, function( spaceName, space ) {
9642     var cache = space.cache;
9643     each( space.props, function( key, prop ) {
9644    
9645     // if the cache doesn't exist, and we know how to convert
9646     if ( !inst[ cache ] && space.to ) {
9647    
9648     // if the value was null, we don't need to copy it
9649     // if the key was alpha, we don't need to copy it either
9650     if ( key === "alpha" || red[ key ] == null ) {
9651     return;
9652     }
9653     inst[ cache ] = space.to( inst._rgba );
9654     }
9655    
9656     // this is the only case where we allow nulls for ALL properties.
9657     // call clamp with alwaysAllowEmpty
9658     inst[ cache ][ prop.idx ] = clamp( red[ key ], prop, true );
9659     });
9660    
9661     // everything defined but alpha?
9662     if ( inst[ cache ] && jQuery.inArray( null, inst[ cache ].slice( 0, 3 ) ) < 0 ) {
9663     // use the default of 1
9664     inst[ cache ][ 3 ] = 1;
9665     if ( space.from ) {
9666     inst._rgba = space.from( inst[ cache ] );
9667     }
9668     }
9669     });
9670     }
9671     return this;
9672     }
9673     },
9674     is: function( compare ) {
9675     var is = color( compare ),
9676     same = true,
9677     inst = this;
9678    
9679     each( spaces, function( _, space ) {
9680     var localCache,
9681     isCache = is[ space.cache ];
9682     if (isCache) {
9683     localCache = inst[ space.cache ] || space.to && space.to( inst._rgba ) || [];
9684     each( space.props, function( _, prop ) {
9685     if ( isCache[ prop.idx ] != null ) {
9686     same = ( isCache[ prop.idx ] === localCache[ prop.idx ] );
9687     return same;
9688     }
9689     });
9690     }
9691     return same;
9692     });
9693     return same;
9694     },
9695     _space: function() {
9696     var used = [],
9697     inst = this;
9698     each( spaces, function( spaceName, space ) {
9699     if ( inst[ space.cache ] ) {
9700     used.push( spaceName );
9701     }
9702     });
9703     return used.pop();
9704     },
9705     transition: function( other, distance ) {
9706     var end = color( other ),
9707     spaceName = end._space(),
9708     space = spaces[ spaceName ],
9709     startColor = this.alpha() === 0 ? color( "transparent" ) : this,
9710     start = startColor[ space.cache ] || space.to( startColor._rgba ),
9711     result = start.slice();
9712    
9713     end = end[ space.cache ];
9714     each( space.props, function( key, prop ) {
9715     var index = prop.idx,
9716     startValue = start[ index ],
9717     endValue = end[ index ],
9718     type = propTypes[ prop.type ] || {};
9719    
9720     // if null, don't override start value
9721     if ( endValue === null ) {
9722     return;
9723     }
9724     // if null - use end
9725     if ( startValue === null ) {
9726     result[ index ] = endValue;
9727     } else {
9728     if ( type.mod ) {
9729     if ( endValue - startValue > type.mod / 2 ) {
9730     startValue += type.mod;
9731     } else if ( startValue - endValue > type.mod / 2 ) {
9732     startValue -= type.mod;
9733     }
9734     }
9735     result[ index ] = clamp( ( endValue - startValue ) * distance + startValue, prop );
9736     }
9737     });
9738     return this[ spaceName ]( result );
9739     },
9740     blend: function( opaque ) {
9741     // if we are already opaque - return ourself
9742     if ( this._rgba[ 3 ] === 1 ) {
9743     return this;
9744     }
9745    
9746     var rgb = this._rgba.slice(),
9747     a = rgb.pop(),
9748     blend = color( opaque )._rgba;
9749    
9750     return color( jQuery.map( rgb, function( v, i ) {
9751     return ( 1 - a ) * blend[ i ] + a * v;
9752     }));
9753     },
9754     toRgbaString: function() {
9755     var prefix = "rgba(",
9756     rgba = jQuery.map( this._rgba, function( v, i ) {
9757     return v == null ? ( i > 2 ? 1 : 0 ) : v;
9758     });
9759    
9760     if ( rgba[ 3 ] === 1 ) {
9761     rgba.pop();
9762     prefix = "rgb(";
9763     }
9764    
9765     return prefix + rgba.join() + ")";
9766     },
9767     toHslaString: function() {
9768     var prefix = "hsla(",
9769     hsla = jQuery.map( this.hsla(), function( v, i ) {
9770     if ( v == null ) {
9771     v = i > 2 ? 1 : 0;
9772     }
9773    
9774     // catch 1 and 2
9775     if ( i && i < 3 ) {
9776     v = Math.round( v * 100 ) + "%";
9777     }
9778     return v;
9779     });
9780    
9781     if ( hsla[ 3 ] === 1 ) {
9782     hsla.pop();
9783     prefix = "hsl(";
9784     }
9785     return prefix + hsla.join() + ")";
9786     },
9787     toHexString: function( includeAlpha ) {
9788     var rgba = this._rgba.slice(),
9789     alpha = rgba.pop();
9790    
9791     if ( includeAlpha ) {
9792     rgba.push( ~~( alpha * 255 ) );
9793     }
9794    
9795     return "#" + jQuery.map( rgba, function( v ) {
9796    
9797     // default to 0 when nulls exist
9798     v = ( v || 0 ).toString( 16 );
9799     return v.length === 1 ? "0" + v : v;
9800     }).join("");
9801     },
9802     toString: function() {
9803     return this._rgba[ 3 ] === 0 ? "transparent" : this.toRgbaString();
9804     }
9805     });
9806     color.fn.parse.prototype = color.fn;
9807    
9808     // hsla conversions adapted from:
9809     // https://code.google.com/p/maashaack/source/browse/packages/graphics/trunk/src/graphics/colors/HUE2RGB.as?r=5021
9810    
9811     function hue2rgb( p, q, h ) {
9812     h = ( h + 1 ) % 1;
9813     if ( h * 6 < 1 ) {
9814     return p + ( q - p ) * h * 6;
9815     }
9816     if ( h * 2 < 1) {
9817     return q;
9818     }
9819     if ( h * 3 < 2 ) {
9820     return p + ( q - p ) * ( ( 2 / 3 ) - h ) * 6;
9821     }
9822     return p;
9823     }
9824    
9825     spaces.hsla.to = function( rgba ) {
9826     if ( rgba[ 0 ] == null || rgba[ 1 ] == null || rgba[ 2 ] == null ) {
9827     return [ null, null, null, rgba[ 3 ] ];
9828     }
9829     var r = rgba[ 0 ] / 255,
9830     g = rgba[ 1 ] / 255,
9831     b = rgba[ 2 ] / 255,
9832     a = rgba[ 3 ],
9833     max = Math.max( r, g, b ),
9834     min = Math.min( r, g, b ),
9835     diff = max - min,
9836     add = max + min,
9837     l = add * 0.5,
9838     h, s;
9839    
9840     if ( min === max ) {
9841     h = 0;
9842     } else if ( r === max ) {
9843     h = ( 60 * ( g - b ) / diff ) + 360;
9844     } else if ( g === max ) {
9845     h = ( 60 * ( b - r ) / diff ) + 120;
9846     } else {
9847     h = ( 60 * ( r - g ) / diff ) + 240;
9848     }
9849    
9850     // chroma (diff) == 0 means greyscale which, by definition, saturation = 0%
9851     // otherwise, saturation is based on the ratio of chroma (diff) to lightness (add)
9852     if ( diff === 0 ) {
9853     s = 0;
9854     } else if ( l <= 0.5 ) {
9855     s = diff / add;
9856     } else {
9857     s = diff / ( 2 - add );
9858     }
9859     return [ Math.round(h) % 360, s, l, a == null ? 1 : a ];
9860     };
9861    
9862     spaces.hsla.from = function( hsla ) {
9863     if ( hsla[ 0 ] == null || hsla[ 1 ] == null || hsla[ 2 ] == null ) {
9864     return [ null, null, null, hsla[ 3 ] ];
9865     }
9866     var h = hsla[ 0 ] / 360,
9867     s = hsla[ 1 ],
9868     l = hsla[ 2 ],
9869     a = hsla[ 3 ],
9870     q = l <= 0.5 ? l * ( 1 + s ) : l + s - l * s,
9871     p = 2 * l - q;
9872    
9873     return [
9874     Math.round( hue2rgb( p, q, h + ( 1 / 3 ) ) * 255 ),
9875     Math.round( hue2rgb( p, q, h ) * 255 ),
9876     Math.round( hue2rgb( p, q, h - ( 1 / 3 ) ) * 255 ),
9877     a
9878     ];
9879     };
9880    
9881     each( spaces, function( spaceName, space ) {
9882     var props = space.props,
9883     cache = space.cache,
9884     to = space.to,
9885     from = space.from;
9886    
9887     // makes rgba() and hsla()
9888     color.fn[ spaceName ] = function( value ) {
9889    
9890     // generate a cache for this space if it doesn't exist
9891     if ( to && !this[ cache ] ) {
9892     this[ cache ] = to( this._rgba );
9893     }
9894     if ( value === undefined ) {
9895     return this[ cache ].slice();
9896     }
9897    
9898     var ret,
9899     type = jQuery.type( value ),
9900     arr = ( type === "array" || type === "object" ) ? value : arguments,
9901     local = this[ cache ].slice();
9902    
9903     each( props, function( key, prop ) {
9904     var val = arr[ type === "object" ? key : prop.idx ];
9905     if ( val == null ) {
9906     val = local[ prop.idx ];
9907     }
9908     local[ prop.idx ] = clamp( val, prop );
9909     });
9910    
9911     if ( from ) {
9912     ret = color( from( local ) );
9913     ret[ cache ] = local;
9914     return ret;
9915     } else {
9916     return color( local );
9917     }
9918     };
9919    
9920     // makes red() green() blue() alpha() hue() saturation() lightness()
9921     each( props, function( key, prop ) {
9922     // alpha is included in more than one space
9923     if ( color.fn[ key ] ) {
9924     return;
9925     }
9926     color.fn[ key ] = function( value ) {
9927     var vtype = jQuery.type( value ),
9928     fn = ( key === "alpha" ? ( this._hsla ? "hsla" : "rgba" ) : spaceName ),
9929     local = this[ fn ](),
9930     cur = local[ prop.idx ],
9931     match;
9932    
9933     if ( vtype === "undefined" ) {
9934     return cur;
9935     }
9936    
9937     if ( vtype === "function" ) {
9938     value = value.call( this, cur );
9939     vtype = jQuery.type( value );
9940     }
9941     if ( value == null && prop.empty ) {
9942     return this;
9943     }
9944     if ( vtype === "string" ) {
9945     match = rplusequals.exec( value );
9946     if ( match ) {
9947     value = cur + parseFloat( match[ 2 ] ) * ( match[ 1 ] === "+" ? 1 : -1 );
9948     }
9949     }
9950     local[ prop.idx ] = value;
9951     return this[ fn ]( local );
9952     };
9953     });
9954     });
9955    
9956     // add cssHook and .fx.step function for each named hook.
9957     // accept a space separated string of properties
9958     color.hook = function( hook ) {
9959     var hooks = hook.split( " " );
9960     each( hooks, function( i, hook ) {
9961     jQuery.cssHooks[ hook ] = {
9962     set: function( elem, value ) {
9963     var parsed, curElem,
9964     backgroundColor = "";
9965    
9966     if ( value !== "transparent" && ( jQuery.type( value ) !== "string" || ( parsed = stringParse( value ) ) ) ) {
9967     value = color( parsed || value );
9968     if ( !support.rgba && value._rgba[ 3 ] !== 1 ) {
9969     curElem = hook === "backgroundColor" ? elem.parentNode : elem;
9970     while (
9971     (backgroundColor === "" || backgroundColor === "transparent") &&
9972     curElem && curElem.style
9973     ) {
9974     try {
9975     backgroundColor = jQuery.css( curElem, "backgroundColor" );
9976     curElem = curElem.parentNode;
9977     } catch ( e ) {
9978     }
9979     }
9980    
9981     value = value.blend( backgroundColor && backgroundColor !== "transparent" ?
9982     backgroundColor :
9983     "_default" );
9984     }
9985    
9986     value = value.toRgbaString();
9987     }
9988     try {
9989     elem.style[ hook ] = value;
9990     } catch ( e ) {
9991     // wrapped to prevent IE from throwing errors on "invalid" values like 'auto' or 'inherit'
9992     }
9993     }
9994     };
9995     jQuery.fx.step[ hook ] = function( fx ) {
9996     if ( !fx.colorInit ) {
9997     fx.start = color( fx.elem, hook );
9998     fx.end = color( fx.end );
9999     fx.colorInit = true;
10000     }
10001     jQuery.cssHooks[ hook ].set( fx.elem, fx.start.transition( fx.end, fx.pos ) );
10002     };
10003     });
10004    
10005     };
10006    
10007     color.hook( stepHooks );
10008    
10009     jQuery.cssHooks.borderColor = {
10010     expand: function( value ) {
10011     var expanded = {};
10012    
10013     each( [ "Top", "Right", "Bottom", "Left" ], function( i, part ) {
10014     expanded[ "border" + part + "Color" ] = value;
10015     });
10016     return expanded;
10017     }
10018     };
10019    
10020     // Basic color names only.
10021     // Usage of any of the other color names requires adding yourself or including
10022     // jquery.color.svg-names.js.
10023     colors = jQuery.Color.names = {
10024     // 4.1. Basic color keywords
10025     aqua: "#00ffff",
10026     black: "#000000",
10027     blue: "#0000ff",
10028     fuchsia: "#ff00ff",
10029     gray: "#808080",
10030     green: "#008000",
10031     lime: "#00ff00",
10032     maroon: "#800000",
10033     navy: "#000080",
10034     olive: "#808000",
10035     purple: "#800080",
10036     red: "#ff0000",
10037     silver: "#c0c0c0",
10038     teal: "#008080",
10039     white: "#ffffff",
10040     yellow: "#ffff00",
10041    
10042     // 4.2.3. "transparent" color keyword
10043     transparent: [ null, null, null, 0 ],
10044    
10045     _default: "#ffffff"
10046     };
10047    
10048     })( jQuery );
10049    
10050     /******************************************************************************/
10051     /****************************** CLASS ANIMATIONS ******************************/
10052     /******************************************************************************/
10053     (function() {
10054    
10055     var classAnimationActions = [ "add", "remove", "toggle" ],
10056     shorthandStyles = {
10057     border: 1,
10058     borderBottom: 1,
10059     borderColor: 1,
10060     borderLeft: 1,
10061     borderRight: 1,
10062     borderTop: 1,
10063     borderWidth: 1,
10064     margin: 1,
10065     padding: 1
10066     };
10067    
10068     $.each([ "borderLeftStyle", "borderRightStyle", "borderBottomStyle", "borderTopStyle" ], function( _, prop ) {
10069     $.fx.step[ prop ] = function( fx ) {
10070     if ( fx.end !== "none" && !fx.setAttr || fx.pos === 1 && !fx.setAttr ) {
10071     jQuery.style( fx.elem, prop, fx.end );
10072     fx.setAttr = true;
10073     }
10074     };
10075     });
10076    
10077     function getElementStyles( elem ) {
10078     var key, len,
10079     style = elem.ownerDocument.defaultView ?
10080     elem.ownerDocument.defaultView.getComputedStyle( elem, null ) :
10081     elem.currentStyle,
10082     styles = {};
10083    
10084     if ( style && style.length && style[ 0 ] && style[ style[ 0 ] ] ) {
10085     len = style.length;
10086     while ( len-- ) {
10087     key = style[ len ];
10088     if ( typeof style[ key ] === "string" ) {
10089     styles[ $.camelCase( key ) ] = style[ key ];
10090     }
10091     }
10092     // support: Opera, IE <9
10093     } else {
10094     for ( key in style ) {
10095     if ( typeof style[ key ] === "string" ) {
10096     styles[ key ] = style[ key ];
10097     }
10098     }
10099     }
10100    
10101     return styles;
10102     }
10103    
10104     function styleDifference( oldStyle, newStyle ) {
10105     var diff = {},
10106     name, value;
10107    
10108     for ( name in newStyle ) {
10109     value = newStyle[ name ];
10110     if ( oldStyle[ name ] !== value ) {
10111     if ( !shorthandStyles[ name ] ) {
10112     if ( $.fx.step[ name ] || !isNaN( parseFloat( value ) ) ) {
10113     diff[ name ] = value;
10114     }
10115     }
10116     }
10117     }
10118    
10119     return diff;
10120     }
10121    
10122     // support: jQuery <1.8
10123     if ( !$.fn.addBack ) {
10124     $.fn.addBack = function( selector ) {
10125     return this.add( selector == null ?
10126     this.prevObject : this.prevObject.filter( selector )
10127     );
10128     };
10129     }
10130    
10131     $.effects.animateClass = function( value, duration, easing, callback ) {
10132     var o = $.speed( duration, easing, callback );
10133    
10134     return this.queue( function() {
10135     var animated = $( this ),
10136     baseClass = animated.attr( "class" ) || "",
10137     applyClassChange,
10138     allAnimations = o.children ? animated.find( "*" ).addBack() : animated;
10139    
10140     // map the animated objects to store the original styles.
10141     allAnimations = allAnimations.map(function() {
10142     var el = $( this );
10143     return {
10144     el: el,
10145     start: getElementStyles( this )
10146     };
10147     });
10148    
10149     // apply class change
10150     applyClassChange = function() {
10151     $.each( classAnimationActions, function(i, action) {
10152     if ( value[ action ] ) {
10153     animated[ action + "Class" ]( value[ action ] );
10154     }
10155     });
10156     };
10157     applyClassChange();
10158    
10159     // map all animated objects again - calculate new styles and diff
10160     allAnimations = allAnimations.map(function() {
10161     this.end = getElementStyles( this.el[ 0 ] );
10162     this.diff = styleDifference( this.start, this.end );
10163     return this;
10164     });
10165    
10166     // apply original class
10167     animated.attr( "class", baseClass );
10168    
10169     // map all animated objects again - this time collecting a promise
10170     allAnimations = allAnimations.map(function() {
10171     var styleInfo = this,
10172     dfd = $.Deferred(),
10173     opts = $.extend({}, o, {
10174     queue: false,
10175     complete: function() {
10176     dfd.resolve( styleInfo );
10177     }
10178     });
10179    
10180     this.el.animate( this.diff, opts );
10181     return dfd.promise();
10182     });
10183    
10184     // once all animations have completed:
10185     $.when.apply( $, allAnimations.get() ).done(function() {
10186    
10187     // set the final class
10188     applyClassChange();
10189    
10190     // for each animated element,
10191     // clear all css properties that were animated
10192     $.each( arguments, function() {
10193     var el = this.el;
10194     $.each( this.diff, function(key) {
10195     el.css( key, "" );
10196     });
10197     });
10198    
10199     // this is guarnteed to be there if you use jQuery.speed()
10200     // it also handles dequeuing the next anim...
10201     o.complete.call( animated[ 0 ] );
10202     });
10203     });
10204     };
10205    
10206     $.fn.extend({
10207     addClass: (function( orig ) {
10208     return function( classNames, speed, easing, callback ) {
10209     return speed ?
10210     $.effects.animateClass.call( this,
10211     { add: classNames }, speed, easing, callback ) :
10212     orig.apply( this, arguments );
10213     };
10214     })( $.fn.addClass ),
10215    
10216     removeClass: (function( orig ) {
10217     return function( classNames, speed, easing, callback ) {
10218     return arguments.length > 1 ?
10219     $.effects.animateClass.call( this,
10220     { remove: classNames }, speed, easing, callback ) :
10221     orig.apply( this, arguments );
10222     };
10223     })( $.fn.removeClass ),
10224    
10225     toggleClass: (function( orig ) {
10226     return function( classNames, force, speed, easing, callback ) {
10227     if ( typeof force === "boolean" || force === undefined ) {
10228     if ( !speed ) {
10229     // without speed parameter
10230     return orig.apply( this, arguments );
10231     } else {
10232     return $.effects.animateClass.call( this,
10233     (force ? { add: classNames } : { remove: classNames }),
10234     speed, easing, callback );
10235     }
10236     } else {
10237     // without force parameter
10238     return $.effects.animateClass.call( this,
10239     { toggle: classNames }, force, speed, easing );
10240     }
10241     };
10242     })( $.fn.toggleClass ),
10243    
10244     switchClass: function( remove, add, speed, easing, callback) {
10245     return $.effects.animateClass.call( this, {
10246     add: add,
10247     remove: remove
10248     }, speed, easing, callback );
10249     }
10250     });
10251    
10252     })();
10253    
10254     /******************************************************************************/
10255     /*********************************** EFFECTS **********************************/
10256     /******************************************************************************/
10257    
10258     (function() {
10259    
10260     $.extend( $.effects, {
10261     version: "1.11.4",
10262    
10263     // Saves a set of properties in a data storage
10264     save: function( element, set ) {
10265     for ( var i = 0; i < set.length; i++ ) {
10266     if ( set[ i ] !== null ) {
10267     element.data( dataSpace + set[ i ], element[ 0 ].style[ set[ i ] ] );
10268     }
10269     }
10270     },
10271    
10272     // Restores a set of previously saved properties from a data storage
10273     restore: function( element, set ) {
10274     var val, i;
10275     for ( i = 0; i < set.length; i++ ) {
10276     if ( set[ i ] !== null ) {
10277     val = element.data( dataSpace + set[ i ] );
10278     // support: jQuery 1.6.2
10279     // http://bugs.jquery.com/ticket/9917
10280     // jQuery 1.6.2 incorrectly returns undefined for any falsy value.
10281     // We can't differentiate between "" and 0 here, so we just assume
10282     // empty string since it's likely to be a more common value...
10283     if ( val === undefined ) {
10284     val = "";
10285     }
10286     element.css( set[ i ], val );
10287     }
10288     }
10289     },
10290    
10291     setMode: function( el, mode ) {
10292     if (mode === "toggle") {
10293     mode = el.is( ":hidden" ) ? "show" : "hide";
10294     }
10295     return mode;
10296     },
10297    
10298     // Translates a [top,left] array into a baseline value
10299     // this should be a little more flexible in the future to handle a string & hash
10300     getBaseline: function( origin, original ) {
10301     var y, x;
10302     switch ( origin[ 0 ] ) {
10303     case "top": y = 0; break;
10304     case "middle": y = 0.5; break;
10305     case "bottom": y = 1; break;
10306     default: y = origin[ 0 ] / original.height;
10307     }
10308     switch ( origin[ 1 ] ) {
10309     case "left": x = 0; break;
10310     case "center": x = 0.5; break;
10311     case "right": x = 1; break;
10312     default: x = origin[ 1 ] / original.width;
10313     }
10314     return {
10315     x: x,
10316     y: y
10317     };
10318     },
10319    
10320     // Wraps the element around a wrapper that copies position properties
10321     createWrapper: function( element ) {
10322    
10323     // if the element is already wrapped, return it
10324     if ( element.parent().is( ".ui-effects-wrapper" )) {
10325     return element.parent();
10326     }
10327    
10328     // wrap the element
10329     var props = {
10330     width: element.outerWidth(true),
10331     height: element.outerHeight(true),
10332     "float": element.css( "float" )
10333     },
10334     wrapper = $( "<div></div>" )
10335     .addClass( "ui-effects-wrapper" )
10336     .css({
10337     fontSize: "100%",
10338     background: "transparent",
10339     border: "none",
10340     margin: 0,
10341     padding: 0
10342     }),
10343     // Store the size in case width/height are defined in % - Fixes #5245
10344     size = {
10345     width: element.width(),
10346     height: element.height()
10347     },
10348     active = document.activeElement;
10349    
10350     // support: Firefox
10351     // Firefox incorrectly exposes anonymous content
10352     // https://bugzilla.mozilla.org/show_bug.cgi?id=561664
10353     try {
10354     active.id;
10355     } catch ( e ) {
10356     active = document.body;
10357     }
10358    
10359     element.wrap( wrapper );
10360    
10361     // Fixes #7595 - Elements lose focus when wrapped.
10362     if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
10363     $( active ).focus();
10364     }
10365    
10366     wrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually lose the reference to the wrapped element
10367    
10368     // transfer positioning properties to the wrapper
10369     if ( element.css( "position" ) === "static" ) {
10370     wrapper.css({ position: "relative" });
10371     element.css({ position: "relative" });
10372     } else {
10373     $.extend( props, {
10374     position: element.css( "position" ),
10375     zIndex: element.css( "z-index" )
10376     });
10377     $.each([ "top", "left", "bottom", "right" ], function(i, pos) {
10378     props[ pos ] = element.css( pos );
10379     if ( isNaN( parseInt( props[ pos ], 10 ) ) ) {
10380     props[ pos ] = "auto";
10381     }
10382     });
10383     element.css({
10384     position: "relative",
10385     top: 0,
10386     left: 0,
10387     right: "auto",
10388     bottom: "auto"
10389     });
10390     }
10391     element.css(size);
10392    
10393     return wrapper.css( props ).show();
10394     },
10395    
10396     removeWrapper: function( element ) {
10397     var active = document.activeElement;
10398    
10399     if ( element.parent().is( ".ui-effects-wrapper" ) ) {
10400     element.parent().replaceWith( element );
10401    
10402     // Fixes #7595 - Elements lose focus when wrapped.
10403     if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
10404     $( active ).focus();
10405     }
10406     }
10407    
10408     return element;
10409     },
10410    
10411     setTransition: function( element, list, factor, value ) {
10412     value = value || {};
10413     $.each( list, function( i, x ) {
10414     var unit = element.cssUnit( x );
10415     if ( unit[ 0 ] > 0 ) {
10416     value[ x ] = unit[ 0 ] * factor + unit[ 1 ];
10417     }
10418     });
10419     return value;
10420     }
10421     });
10422    
10423     // return an effect options object for the given parameters:
10424     function _normalizeArguments( effect, options, speed, callback ) {
10425    
10426     // allow passing all options as the first parameter
10427     if ( $.isPlainObject( effect ) ) {
10428     options = effect;
10429     effect = effect.effect;
10430     }
10431    
10432     // convert to an object
10433     effect = { effect: effect };
10434    
10435     // catch (effect, null, ...)
10436     if ( options == null ) {
10437     options = {};
10438     }
10439    
10440     // catch (effect, callback)
10441     if ( $.isFunction( options ) ) {
10442     callback = options;
10443     speed = null;
10444     options = {};
10445     }
10446    
10447     // catch (effect, speed, ?)
10448     if ( typeof options === "number" || $.fx.speeds[ options ] ) {
10449     callback = speed;
10450     speed = options;
10451     options = {};
10452     }
10453    
10454     // catch (effect, options, callback)
10455     if ( $.isFunction( speed ) ) {
10456     callback = speed;
10457     speed = null;
10458     }
10459    
10460     // add options to effect
10461     if ( options ) {
10462     $.extend( effect, options );
10463     }
10464    
10465     speed = speed || options.duration;
10466     effect.duration = $.fx.off ? 0 :
10467     typeof speed === "number" ? speed :
10468     speed in $.fx.speeds ? $.fx.speeds[ speed ] :
10469     $.fx.speeds._default;
10470    
10471     effect.complete = callback || options.complete;
10472    
10473     return effect;
10474     }
10475    
10476     function standardAnimationOption( option ) {
10477     // Valid standard speeds (nothing, number, named speed)
10478     if ( !option || typeof option === "number" || $.fx.speeds[ option ] ) {
10479     return true;
10480     }
10481    
10482     // Invalid strings - treat as "normal" speed
10483     if ( typeof option === "string" && !$.effects.effect[ option ] ) {
10484     return true;
10485     }
10486    
10487     // Complete callback
10488     if ( $.isFunction( option ) ) {
10489     return true;
10490     }
10491    
10492     // Options hash (but not naming an effect)
10493     if ( typeof option === "object" && !option.effect ) {
10494     return true;
10495     }
10496    
10497     // Didn't match any standard API
10498     return false;
10499     }
10500    
10501     $.fn.extend({
10502     effect: function( /* effect, options, speed, callback */ ) {
10503     var args = _normalizeArguments.apply( this, arguments ),
10504     mode = args.mode,
10505     queue = args.queue,
10506     effectMethod = $.effects.effect[ args.effect ];
10507    
10508     if ( $.fx.off || !effectMethod ) {
10509     // delegate to the original method (e.g., .show()) if possible
10510     if ( mode ) {
10511     return this[ mode ]( args.duration, args.complete );
10512     } else {
10513     return this.each( function() {
10514     if ( args.complete ) {
10515     args.complete.call( this );
10516     }
10517     });
10518     }
10519     }
10520    
10521     function run( next ) {
10522     var elem = $( this ),
10523     complete = args.complete,
10524     mode = args.mode;
10525    
10526     function done() {
10527     if ( $.isFunction( complete ) ) {
10528     complete.call( elem[0] );
10529     }
10530     if ( $.isFunction( next ) ) {
10531     next();
10532     }
10533     }
10534    
10535     // If the element already has the correct final state, delegate to
10536     // the core methods so the internal tracking of "olddisplay" works.
10537     if ( elem.is( ":hidden" ) ? mode === "hide" : mode === "show" ) {
10538     elem[ mode ]();
10539     done();
10540     } else {
10541     effectMethod.call( elem[0], args, done );
10542     }
10543     }
10544    
10545     return queue === false ? this.each( run ) : this.queue( queue || "fx", run );
10546     },
10547    
10548     show: (function( orig ) {
10549     return function( option ) {
10550     if ( standardAnimationOption( option ) ) {
10551     return orig.apply( this, arguments );
10552     } else {
10553     var args = _normalizeArguments.apply( this, arguments );
10554     args.mode = "show";
10555     return this.effect.call( this, args );
10556     }
10557     };
10558     })( $.fn.show ),
10559    
10560     hide: (function( orig ) {
10561     return function( option ) {
10562     if ( standardAnimationOption( option ) ) {
10563     return orig.apply( this, arguments );
10564     } else {
10565     var args = _normalizeArguments.apply( this, arguments );
10566     args.mode = "hide";
10567     return this.effect.call( this, args );
10568     }
10569     };
10570     })( $.fn.hide ),
10571    
10572     toggle: (function( orig ) {
10573     return function( option ) {
10574     if ( standardAnimationOption( option ) || typeof option === "boolean" ) {
10575     return orig.apply( this, arguments );
10576     } else {
10577     var args = _normalizeArguments.apply( this, arguments );
10578     args.mode = "toggle";
10579     return this.effect.call( this, args );
10580     }
10581     };
10582     })( $.fn.toggle ),
10583    
10584     // helper functions
10585     cssUnit: function(key) {
10586     var style = this.css( key ),
10587     val = [];
10588    
10589     $.each( [ "em", "px", "%", "pt" ], function( i, unit ) {
10590     if ( style.indexOf( unit ) > 0 ) {
10591     val = [ parseFloat( style ), unit ];
10592     }
10593     });
10594     return val;
10595     }
10596     });
10597    
10598     })();
10599    
10600     /******************************************************************************/
10601     /*********************************** EASING ***********************************/
10602     /******************************************************************************/
10603    
10604     (function() {
10605    
10606     // based on easing equations from Robert Penner (http://www.robertpenner.com/easing)
10607    
10608     var baseEasings = {};
10609    
10610     $.each( [ "Quad", "Cubic", "Quart", "Quint", "Expo" ], function( i, name ) {
10611     baseEasings[ name ] = function( p ) {
10612     return Math.pow( p, i + 2 );
10613     };
10614     });
10615    
10616     $.extend( baseEasings, {
10617     Sine: function( p ) {
10618     return 1 - Math.cos( p * Math.PI / 2 );
10619     },
10620     Circ: function( p ) {
10621     return 1 - Math.sqrt( 1 - p * p );
10622     },
10623     Elastic: function( p ) {
10624     return p === 0 || p === 1 ? p :
10625     -Math.pow( 2, 8 * (p - 1) ) * Math.sin( ( (p - 1) * 80 - 7.5 ) * Math.PI / 15 );
10626     },
10627     Back: function( p ) {
10628     return p * p * ( 3 * p - 2 );
10629     },
10630     Bounce: function( p ) {
10631     var pow2,
10632     bounce = 4;
10633    
10634     while ( p < ( ( pow2 = Math.pow( 2, --bounce ) ) - 1 ) / 11 ) {}
10635     return 1 / Math.pow( 4, 3 - bounce ) - 7.5625 * Math.pow( ( pow2 * 3 - 2 ) / 22 - p, 2 );
10636     }
10637     });
10638    
10639     $.each( baseEasings, function( name, easeIn ) {
10640     $.easing[ "easeIn" + name ] = easeIn;
10641     $.easing[ "easeOut" + name ] = function( p ) {
10642     return 1 - easeIn( 1 - p );
10643     };
10644     $.easing[ "easeInOut" + name ] = function( p ) {
10645     return p < 0.5 ?
10646     easeIn( p * 2 ) / 2 :
10647     1 - easeIn( p * -2 + 2 ) / 2;
10648     };
10649     });
10650    
10651     })();
10652    
10653     var effect = $.effects;
10654    
10655    
10656     /*!
10657     * jQuery UI Effects Blind 1.11.4
10658     * http://jqueryui.com
10659     *
10660     * Copyright jQuery Foundation and other contributors
10661     * Released under the MIT license.
10662     * http://jquery.org/license
10663     *
10664     * http://api.jqueryui.com/blind-effect/
10665     */
10666    
10667    
10668     var effectBlind = $.effects.effect.blind = function( o, done ) {
10669     // Create element
10670     var el = $( this ),
10671     rvertical = /up|down|vertical/,
10672     rpositivemotion = /up|left|vertical|horizontal/,
10673     props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
10674     mode = $.effects.setMode( el, o.mode || "hide" ),
10675     direction = o.direction || "up",
10676     vertical = rvertical.test( direction ),
10677     ref = vertical ? "height" : "width",
10678     ref2 = vertical ? "top" : "left",
10679     motion = rpositivemotion.test( direction ),
10680     animation = {},
10681     show = mode === "show",
10682     wrapper, distance, margin;
10683    
10684     // if already wrapped, the wrapper's properties are my property. #6245
10685     if ( el.parent().is( ".ui-effects-wrapper" ) ) {
10686     $.effects.save( el.parent(), props );
10687     } else {
10688     $.effects.save( el, props );
10689     }
10690     el.show();
10691     wrapper = $.effects.createWrapper( el ).css({
10692     overflow: "hidden"
10693     });
10694    
10695     distance = wrapper[ ref ]();
10696     margin = parseFloat( wrapper.css( ref2 ) ) || 0;
10697    
10698     animation[ ref ] = show ? distance : 0;
10699     if ( !motion ) {
10700     el
10701     .css( vertical ? "bottom" : "right", 0 )
10702     .css( vertical ? "top" : "left", "auto" )
10703     .css({ position: "absolute" });
10704    
10705     animation[ ref2 ] = show ? margin : distance + margin;
10706     }
10707    
10708     // start at 0 if we are showing
10709     if ( show ) {
10710     wrapper.css( ref, 0 );
10711     if ( !motion ) {
10712     wrapper.css( ref2, margin + distance );
10713     }
10714     }
10715    
10716     // Animate
10717     wrapper.animate( animation, {
10718     duration: o.duration,
10719     easing: o.easing,
10720     queue: false,
10721     complete: function() {
10722     if ( mode === "hide" ) {
10723     el.hide();
10724     }
10725     $.effects.restore( el, props );
10726     $.effects.removeWrapper( el );
10727     done();
10728     }
10729     });
10730     };
10731    
10732    
10733     /*!
10734     * jQuery UI Effects Bounce 1.11.4
10735     * http://jqueryui.com
10736     *
10737     * Copyright jQuery Foundation and other contributors
10738     * Released under the MIT license.
10739     * http://jquery.org/license
10740     *
10741     * http://api.jqueryui.com/bounce-effect/
10742     */
10743    
10744    
10745     var effectBounce = $.effects.effect.bounce = function( o, done ) {
10746     var el = $( this ),
10747     props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
10748    
10749     // defaults:
10750     mode = $.effects.setMode( el, o.mode || "effect" ),
10751     hide = mode === "hide",
10752     show = mode === "show",
10753     direction = o.direction || "up",
10754     distance = o.distance,
10755     times = o.times || 5,
10756    
10757     // number of internal animations
10758     anims = times * 2 + ( show || hide ? 1 : 0 ),
10759     speed = o.duration / anims,
10760     easing = o.easing,
10761    
10762     // utility:
10763     ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
10764     motion = ( direction === "up" || direction === "left" ),
10765     i,
10766     upAnim,
10767     downAnim,
10768    
10769     // we will need to re-assemble the queue to stack our animations in place
10770     queue = el.queue(),
10771     queuelen = queue.length;
10772    
10773     // Avoid touching opacity to prevent clearType and PNG issues in IE
10774     if ( show || hide ) {
10775     props.push( "opacity" );
10776     }
10777    
10778     $.effects.save( el, props );
10779     el.show();
10780     $.effects.createWrapper( el ); // Create Wrapper
10781    
10782     // default distance for the BIGGEST bounce is the outer Distance / 3
10783     if ( !distance ) {
10784     distance = el[ ref === "top" ? "outerHeight" : "outerWidth" ]() / 3;
10785     }
10786    
10787     if ( show ) {
10788     downAnim = { opacity: 1 };
10789     downAnim[ ref ] = 0;
10790    
10791     // if we are showing, force opacity 0 and set the initial position
10792     // then do the "first" animation
10793     el.css( "opacity", 0 )
10794     .css( ref, motion ? -distance * 2 : distance * 2 )
10795     .animate( downAnim, speed, easing );
10796     }
10797    
10798     // start at the smallest distance if we are hiding
10799     if ( hide ) {
10800     distance = distance / Math.pow( 2, times - 1 );
10801     }
10802    
10803     downAnim = {};
10804     downAnim[ ref ] = 0;
10805     // Bounces up/down/left/right then back to 0 -- times * 2 animations happen here
10806     for ( i = 0; i < times; i++ ) {
10807     upAnim = {};
10808     upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance;
10809    
10810     el.animate( upAnim, speed, easing )
10811     .animate( downAnim, speed, easing );
10812    
10813     distance = hide ? distance * 2 : distance / 2;
10814     }
10815    
10816     // Last Bounce when Hiding
10817     if ( hide ) {
10818     upAnim = { opacity: 0 };
10819     upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance;
10820    
10821     el.animate( upAnim, speed, easing );
10822     }
10823    
10824     el.queue(function() {
10825     if ( hide ) {
10826     el.hide();
10827     }
10828     $.effects.restore( el, props );
10829     $.effects.removeWrapper( el );
10830     done();
10831     });
10832    
10833     // inject all the animations we just queued to be first in line (after "inprogress")
10834     if ( queuelen > 1) {
10835     queue.splice.apply( queue,
10836     [ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) );
10837     }
10838     el.dequeue();
10839    
10840     };
10841    
10842    
10843     /*!
10844     * jQuery UI Effects Clip 1.11.4
10845     * http://jqueryui.com
10846     *
10847     * Copyright jQuery Foundation and other contributors
10848     * Released under the MIT license.
10849     * http://jquery.org/license
10850     *
10851     * http://api.jqueryui.com/clip-effect/
10852     */
10853    
10854    
10855     var effectClip = $.effects.effect.clip = function( o, done ) {
10856     // Create element
10857     var el = $( this ),
10858     props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
10859     mode = $.effects.setMode( el, o.mode || "hide" ),
10860     show = mode === "show",
10861     direction = o.direction || "vertical",
10862     vert = direction === "vertical",
10863     size = vert ? "height" : "width",
10864     position = vert ? "top" : "left",
10865     animation = {},
10866     wrapper, animate, distance;
10867    
10868     // Save & Show
10869     $.effects.save( el, props );
10870     el.show();
10871    
10872     // Create Wrapper
10873     wrapper = $.effects.createWrapper( el ).css({
10874     overflow: "hidden"
10875     });
10876     animate = ( el[0].tagName === "IMG" ) ? wrapper : el;
10877     distance = animate[ size ]();
10878    
10879     // Shift
10880     if ( show ) {
10881     animate.css( size, 0 );
10882     animate.css( position, distance / 2 );
10883     }
10884    
10885     // Create Animation Object:
10886     animation[ size ] = show ? distance : 0;
10887     animation[ position ] = show ? 0 : distance / 2;
10888    
10889     // Animate
10890     animate.animate( animation, {
10891     queue: false,
10892     duration: o.duration,
10893     easing: o.easing,
10894     complete: function() {
10895     if ( !show ) {
10896     el.hide();
10897     }
10898     $.effects.restore( el, props );
10899     $.effects.removeWrapper( el );
10900     done();
10901     }
10902     });
10903    
10904     };
10905    
10906    
10907     /*!
10908     * jQuery UI Effects Drop 1.11.4
10909     * http://jqueryui.com
10910     *
10911     * Copyright jQuery Foundation and other contributors
10912     * Released under the MIT license.
10913     * http://jquery.org/license
10914     *
10915     * http://api.jqueryui.com/drop-effect/
10916     */
10917    
10918    
10919     var effectDrop = $.effects.effect.drop = function( o, done ) {
10920    
10921     var el = $( this ),
10922     props = [ "position", "top", "bottom", "left", "right", "opacity", "height", "width" ],
10923     mode = $.effects.setMode( el, o.mode || "hide" ),
10924     show = mode === "show",
10925     direction = o.direction || "left",
10926     ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
10927     motion = ( direction === "up" || direction === "left" ) ? "pos" : "neg",
10928     animation = {
10929     opacity: show ? 1 : 0
10930     },
10931     distance;
10932    
10933     // Adjust
10934     $.effects.save( el, props );
10935     el.show();
10936     $.effects.createWrapper( el );
10937    
10938     distance = o.distance || el[ ref === "top" ? "outerHeight" : "outerWidth" ]( true ) / 2;
10939    
10940     if ( show ) {
10941     el
10942     .css( "opacity", 0 )
10943     .css( ref, motion === "pos" ? -distance : distance );
10944     }
10945    
10946     // Animation
10947     animation[ ref ] = ( show ?
10948     ( motion === "pos" ? "+=" : "-=" ) :
10949     ( motion === "pos" ? "-=" : "+=" ) ) +
10950     distance;
10951    
10952     // Animate
10953     el.animate( animation, {
10954     queue: false,
10955     duration: o.duration,
10956     easing: o.easing,
10957     complete: function() {
10958     if ( mode === "hide" ) {
10959     el.hide();
10960     }
10961     $.effects.restore( el, props );
10962     $.effects.removeWrapper( el );
10963     done();
10964     }
10965     });
10966     };
10967    
10968    
10969     /*!
10970     * jQuery UI Effects Explode 1.11.4
10971     * http://jqueryui.com
10972     *
10973     * Copyright jQuery Foundation and other contributors
10974     * Released under the MIT license.
10975     * http://jquery.org/license
10976     *
10977     * http://api.jqueryui.com/explode-effect/
10978     */
10979    
10980    
10981     var effectExplode = $.effects.effect.explode = function( o, done ) {
10982    
10983     var rows = o.pieces ? Math.round( Math.sqrt( o.pieces ) ) : 3,
10984     cells = rows,
10985     el = $( this ),
10986     mode = $.effects.setMode( el, o.mode || "hide" ),
10987     show = mode === "show",
10988    
10989     // show and then visibility:hidden the element before calculating offset
10990     offset = el.show().css( "visibility", "hidden" ).offset(),
10991    
10992     // width and height of a piece
10993     width = Math.ceil( el.outerWidth() / cells ),
10994     height = Math.ceil( el.outerHeight() / rows ),
10995     pieces = [],
10996    
10997     // loop
10998     i, j, left, top, mx, my;
10999    
11000     // children animate complete:
11001     function childComplete() {
11002     pieces.push( this );
11003     if ( pieces.length === rows * cells ) {
11004     animComplete();
11005     }
11006     }
11007    
11008     // clone the element for each row and cell.
11009     for ( i = 0; i < rows ; i++ ) { // ===>
11010     top = offset.top + i * height;
11011     my = i - ( rows - 1 ) / 2 ;
11012    
11013     for ( j = 0; j < cells ; j++ ) { // |||
11014     left = offset.left + j * width;
11015     mx = j - ( cells - 1 ) / 2 ;
11016    
11017     // Create a clone of the now hidden main element that will be absolute positioned
11018     // within a wrapper div off the -left and -top equal to size of our pieces
11019     el
11020     .clone()
11021     .appendTo( "body" )
11022     .wrap( "<div></div>" )
11023     .css({
11024     position: "absolute",
11025     visibility: "visible",
11026     left: -j * width,
11027     top: -i * height
11028     })
11029    
11030     // select the wrapper - make it overflow: hidden and absolute positioned based on
11031     // where the original was located +left and +top equal to the size of pieces
11032     .parent()
11033     .addClass( "ui-effects-explode" )
11034     .css({
11035     position: "absolute",
11036     overflow: "hidden",
11037     width: width,
11038     height: height,
11039     left: left + ( show ? mx * width : 0 ),
11040     top: top + ( show ? my * height : 0 ),
11041     opacity: show ? 0 : 1
11042     }).animate({
11043     left: left + ( show ? 0 : mx * width ),
11044     top: top + ( show ? 0 : my * height ),
11045     opacity: show ? 1 : 0
11046     }, o.duration || 500, o.easing, childComplete );
11047     }
11048     }
11049    
11050     function animComplete() {
11051     el.css({
11052     visibility: "visible"
11053     });
11054     $( pieces ).remove();
11055     if ( !show ) {
11056     el.hide();
11057     }
11058     done();
11059     }
11060     };
11061    
11062    
11063     /*!
11064     * jQuery UI Effects Fade 1.11.4
11065     * http://jqueryui.com
11066     *
11067     * Copyright jQuery Foundation and other contributors
11068     * Released under the MIT license.
11069     * http://jquery.org/license
11070     *
11071     * http://api.jqueryui.com/fade-effect/
11072     */
11073    
11074    
11075     var effectFade = $.effects.effect.fade = function( o, done ) {
11076     var el = $( this ),
11077     mode = $.effects.setMode( el, o.mode || "toggle" );
11078    
11079     el.animate({
11080     opacity: mode
11081     }, {
11082     queue: false,
11083     duration: o.duration,
11084     easing: o.easing,
11085     complete: done
11086     });
11087     };
11088    
11089    
11090     /*!
11091     * jQuery UI Effects Fold 1.11.4
11092     * http://jqueryui.com
11093     *
11094     * Copyright jQuery Foundation and other contributors
11095     * Released under the MIT license.
11096     * http://jquery.org/license
11097     *
11098     * http://api.jqueryui.com/fold-effect/
11099     */
11100    
11101    
11102     var effectFold = $.effects.effect.fold = function( o, done ) {
11103    
11104     // Create element
11105     var el = $( this ),
11106     props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
11107     mode = $.effects.setMode( el, o.mode || "hide" ),
11108     show = mode === "show",
11109     hide = mode === "hide",
11110     size = o.size || 15,
11111     percent = /([0-9]+)%/.exec( size ),
11112     horizFirst = !!o.horizFirst,
11113     widthFirst = show !== horizFirst,
11114     ref = widthFirst ? [ "width", "height" ] : [ "height", "width" ],
11115     duration = o.duration / 2,
11116     wrapper, distance,
11117     animation1 = {},
11118     animation2 = {};
11119    
11120     $.effects.save( el, props );
11121     el.show();
11122    
11123     // Create Wrapper
11124     wrapper = $.effects.createWrapper( el ).css({
11125     overflow: "hidden"
11126     });
11127     distance = widthFirst ?
11128     [ wrapper.width(), wrapper.height() ] :
11129     [ wrapper.height(), wrapper.width() ];
11130    
11131     if ( percent ) {
11132     size = parseInt( percent[ 1 ], 10 ) / 100 * distance[ hide ? 0 : 1 ];
11133     }
11134     if ( show ) {
11135     wrapper.css( horizFirst ? {
11136     height: 0,
11137     width: size
11138     } : {
11139     height: size,
11140     width: 0
11141     });
11142     }
11143    
11144     // Animation
11145     animation1[ ref[ 0 ] ] = show ? distance[ 0 ] : size;
11146     animation2[ ref[ 1 ] ] = show ? distance[ 1 ] : 0;
11147    
11148     // Animate
11149     wrapper
11150     .animate( animation1, duration, o.easing )
11151     .animate( animation2, duration, o.easing, function() {
11152     if ( hide ) {
11153     el.hide();
11154     }
11155     $.effects.restore( el, props );
11156     $.effects.removeWrapper( el );
11157     done();
11158     });
11159    
11160     };
11161    
11162    
11163     /*!
11164     * jQuery UI Effects Highlight 1.11.4
11165     * http://jqueryui.com
11166     *
11167     * Copyright jQuery Foundation and other contributors
11168     * Released under the MIT license.
11169     * http://jquery.org/license
11170     *
11171     * http://api.jqueryui.com/highlight-effect/
11172     */
11173    
11174    
11175     var effectHighlight = $.effects.effect.highlight = function( o, done ) {
11176     var elem = $( this ),
11177     props = [ "backgroundImage", "backgroundColor", "opacity" ],
11178     mode = $.effects.setMode( elem, o.mode || "show" ),
11179     animation = {
11180     backgroundColor: elem.css( "backgroundColor" )
11181     };
11182    
11183     if (mode === "hide") {
11184     animation.opacity = 0;
11185     }
11186    
11187     $.effects.save( elem, props );
11188    
11189     elem
11190     .show()
11191     .css({
11192     backgroundImage: "none",
11193     backgroundColor: o.color || "#ffff99"
11194     })
11195     .animate( animation, {
11196     queue: false,
11197     duration: o.duration,
11198     easing: o.easing,
11199     complete: function() {
11200     if ( mode === "hide" ) {
11201     elem.hide();
11202     }
11203     $.effects.restore( elem, props );
11204     done();
11205     }
11206     });
11207     };
11208    
11209    
11210     /*!
11211     * jQuery UI Effects Size 1.11.4
11212     * http://jqueryui.com
11213     *
11214     * Copyright jQuery Foundation and other contributors
11215     * Released under the MIT license.
11216     * http://jquery.org/license
11217     *
11218     * http://api.jqueryui.com/size-effect/
11219     */
11220    
11221    
11222     var effectSize = $.effects.effect.size = function( o, done ) {
11223    
11224     // Create element
11225     var original, baseline, factor,
11226     el = $( this ),
11227     props0 = [ "position", "top", "bottom", "left", "right", "width", "height", "overflow", "opacity" ],
11228    
11229     // Always restore
11230     props1 = [ "position", "top", "bottom", "left", "right", "overflow", "opacity" ],
11231    
11232     // Copy for children
11233     props2 = [ "width", "height", "overflow" ],
11234     cProps = [ "fontSize" ],
11235     vProps = [ "borderTopWidth", "borderBottomWidth", "paddingTop", "paddingBottom" ],
11236     hProps = [ "borderLeftWidth", "borderRightWidth", "paddingLeft", "paddingRight" ],
11237    
11238     // Set options
11239     mode = $.effects.setMode( el, o.mode || "effect" ),
11240     restore = o.restore || mode !== "effect",
11241     scale = o.scale || "both",
11242     origin = o.origin || [ "middle", "center" ],
11243     position = el.css( "position" ),
11244     props = restore ? props0 : props1,
11245     zero = {
11246     height: 0,
11247     width: 0,
11248     outerHeight: 0,
11249     outerWidth: 0
11250     };
11251    
11252     if ( mode === "show" ) {
11253     el.show();
11254     }
11255     original = {
11256     height: el.height(),
11257     width: el.width(),
11258     outerHeight: el.outerHeight(),
11259     outerWidth: el.outerWidth()
11260     };
11261    
11262     if ( o.mode === "toggle" && mode === "show" ) {
11263     el.from = o.to || zero;
11264     el.to = o.from || original;
11265     } else {
11266     el.from = o.from || ( mode === "show" ? zero : original );
11267     el.to = o.to || ( mode === "hide" ? zero : original );
11268     }
11269    
11270     // Set scaling factor
11271     factor = {
11272     from: {
11273     y: el.from.height / original.height,
11274     x: el.from.width / original.width
11275     },
11276     to: {
11277     y: el.to.height / original.height,
11278     x: el.to.width / original.width
11279     }
11280     };
11281    
11282     // Scale the css box
11283     if ( scale === "box" || scale === "both" ) {
11284    
11285     // Vertical props scaling
11286     if ( factor.from.y !== factor.to.y ) {
11287     props = props.concat( vProps );
11288     el.from = $.effects.setTransition( el, vProps, factor.from.y, el.from );
11289     el.to = $.effects.setTransition( el, vProps, factor.to.y, el.to );
11290     }
11291    
11292     // Horizontal props scaling
11293     if ( factor.from.x !== factor.to.x ) {
11294     props = props.concat( hProps );
11295     el.from = $.effects.setTransition( el, hProps, factor.from.x, el.from );
11296     el.to = $.effects.setTransition( el, hProps, factor.to.x, el.to );
11297     }
11298     }
11299    
11300     // Scale the content
11301     if ( scale === "content" || scale === "both" ) {
11302    
11303     // Vertical props scaling
11304     if ( factor.from.y !== factor.to.y ) {
11305     props = props.concat( cProps ).concat( props2 );
11306     el.from = $.effects.setTransition( el, cProps, factor.from.y, el.from );
11307     el.to = $.effects.setTransition( el, cProps, factor.to.y, el.to );
11308     }
11309     }
11310    
11311     $.effects.save( el, props );
11312     el.show();
11313     $.effects.createWrapper( el );
11314     el.css( "overflow", "hidden" ).css( el.from );
11315    
11316     // Adjust
11317     if (origin) { // Calculate baseline shifts
11318     baseline = $.effects.getBaseline( origin, original );
11319     el.from.top = ( original.outerHeight - el.outerHeight() ) * baseline.y;
11320     el.from.left = ( original.outerWidth - el.outerWidth() ) * baseline.x;
11321     el.to.top = ( original.outerHeight - el.to.outerHeight ) * baseline.y;
11322     el.to.left = ( original.outerWidth - el.to.outerWidth ) * baseline.x;
11323     }
11324     el.css( el.from ); // set top & left
11325    
11326     // Animate
11327     if ( scale === "content" || scale === "both" ) { // Scale the children
11328    
11329     // Add margins/font-size
11330     vProps = vProps.concat([ "marginTop", "marginBottom" ]).concat(cProps);
11331     hProps = hProps.concat([ "marginLeft", "marginRight" ]);
11332     props2 = props0.concat(vProps).concat(hProps);
11333    
11334     el.find( "*[width]" ).each( function() {
11335     var child = $( this ),
11336     c_original = {
11337     height: child.height(),
11338     width: child.width(),
11339     outerHeight: child.outerHeight(),
11340     outerWidth: child.outerWidth()
11341     };
11342     if (restore) {
11343     $.effects.save(child, props2);
11344     }
11345    
11346     child.from = {
11347     height: c_original.height * factor.from.y,
11348     width: c_original.width * factor.from.x,
11349     outerHeight: c_original.outerHeight * factor.from.y,
11350     outerWidth: c_original.outerWidth * factor.from.x
11351     };
11352     child.to = {
11353     height: c_original.height * factor.to.y,
11354     width: c_original.width * factor.to.x,
11355     outerHeight: c_original.height * factor.to.y,
11356     outerWidth: c_original.width * factor.to.x
11357     };
11358    
11359     // Vertical props scaling
11360     if ( factor.from.y !== factor.to.y ) {
11361     child.from = $.effects.setTransition( child, vProps, factor.from.y, child.from );
11362     child.to = $.effects.setTransition( child, vProps, factor.to.y, child.to );
11363     }
11364    
11365     // Horizontal props scaling
11366     if ( factor.from.x !== factor.to.x ) {
11367     child.from = $.effects.setTransition( child, hProps, factor.from.x, child.from );
11368     child.to = $.effects.setTransition( child, hProps, factor.to.x, child.to );
11369     }
11370    
11371     // Animate children
11372     child.css( child.from );
11373     child.animate( child.to, o.duration, o.easing, function() {
11374    
11375     // Restore children
11376     if ( restore ) {
11377     $.effects.restore( child, props2 );
11378     }
11379     });
11380     });
11381     }
11382    
11383     // Animate
11384     el.animate( el.to, {
11385     queue: false,
11386     duration: o.duration,
11387     easing: o.easing,
11388     complete: function() {
11389     if ( el.to.opacity === 0 ) {
11390     el.css( "opacity", el.from.opacity );
11391     }
11392     if ( mode === "hide" ) {
11393     el.hide();
11394     }
11395     $.effects.restore( el, props );
11396     if ( !restore ) {
11397    
11398     // we need to calculate our new positioning based on the scaling
11399     if ( position === "static" ) {
11400     el.css({
11401     position: "relative",
11402     top: el.to.top,
11403     left: el.to.left
11404     });
11405     } else {
11406     $.each([ "top", "left" ], function( idx, pos ) {
11407     el.css( pos, function( _, str ) {
11408     var val = parseInt( str, 10 ),
11409     toRef = idx ? el.to.left : el.to.top;
11410    
11411     // if original was "auto", recalculate the new value from wrapper
11412     if ( str === "auto" ) {
11413     return toRef + "px";
11414     }
11415    
11416     return val + toRef + "px";
11417     });
11418     });
11419     }
11420     }
11421    
11422     $.effects.removeWrapper( el );
11423     done();
11424     }
11425     });
11426    
11427     };
11428    
11429    
11430     /*!
11431     * jQuery UI Effects Scale 1.11.4
11432     * http://jqueryui.com
11433     *
11434     * Copyright jQuery Foundation and other contributors
11435     * Released under the MIT license.
11436     * http://jquery.org/license
11437     *
11438     * http://api.jqueryui.com/scale-effect/
11439     */
11440    
11441    
11442     var effectScale = $.effects.effect.scale = function( o, done ) {
11443    
11444     // Create element
11445     var el = $( this ),
11446     options = $.extend( true, {}, o ),
11447     mode = $.effects.setMode( el, o.mode || "effect" ),
11448     percent = parseInt( o.percent, 10 ) ||
11449     ( parseInt( o.percent, 10 ) === 0 ? 0 : ( mode === "hide" ? 0 : 100 ) ),
11450     direction = o.direction || "both",
11451     origin = o.origin,
11452     original = {
11453     height: el.height(),
11454     width: el.width(),
11455     outerHeight: el.outerHeight(),
11456     outerWidth: el.outerWidth()
11457     },
11458     factor = {
11459     y: direction !== "horizontal" ? (percent / 100) : 1,
11460     x: direction !== "vertical" ? (percent / 100) : 1
11461     };
11462    
11463     // We are going to pass this effect to the size effect:
11464     options.effect = "size";
11465     options.queue = false;
11466     options.complete = done;
11467    
11468     // Set default origin and restore for show/hide
11469     if ( mode !== "effect" ) {
11470     options.origin = origin || [ "middle", "center" ];
11471     options.restore = true;
11472     }
11473    
11474     options.from = o.from || ( mode === "show" ? {
11475     height: 0,
11476     width: 0,
11477     outerHeight: 0,
11478     outerWidth: 0
11479     } : original );
11480     options.to = {
11481     height: original.height * factor.y,
11482     width: original.width * factor.x,
11483     outerHeight: original.outerHeight * factor.y,
11484     outerWidth: original.outerWidth * factor.x
11485     };
11486    
11487     // Fade option to support puff
11488     if ( options.fade ) {
11489     if ( mode === "show" ) {
11490     options.from.opacity = 0;
11491     options.to.opacity = 1;
11492     }
11493     if ( mode === "hide" ) {
11494     options.from.opacity = 1;
11495     options.to.opacity = 0;
11496     }
11497     }
11498    
11499     // Animate
11500     el.effect( options );
11501    
11502     };
11503    
11504    
11505     /*!
11506     * jQuery UI Effects Puff 1.11.4
11507     * http://jqueryui.com
11508     *
11509     * Copyright jQuery Foundation and other contributors
11510     * Released under the MIT license.
11511     * http://jquery.org/license
11512     *
11513     * http://api.jqueryui.com/puff-effect/
11514     */
11515    
11516    
11517     var effectPuff = $.effects.effect.puff = function( o, done ) {
11518     var elem = $( this ),
11519     mode = $.effects.setMode( elem, o.mode || "hide" ),
11520     hide = mode === "hide",
11521     percent = parseInt( o.percent, 10 ) || 150,
11522     factor = percent / 100,
11523     original = {
11524     height: elem.height(),
11525     width: elem.width(),
11526     outerHeight: elem.outerHeight(),
11527     outerWidth: elem.outerWidth()
11528     };
11529    
11530     $.extend( o, {
11531     effect: "scale",
11532     queue: false,
11533     fade: true,
11534     mode: mode,
11535     complete: done,
11536     percent: hide ? percent : 100,
11537     from: hide ?
11538     original :
11539     {
11540     height: original.height * factor,
11541     width: original.width * factor,
11542     outerHeight: original.outerHeight * factor,
11543     outerWidth: original.outerWidth * factor
11544     }
11545     });
11546    
11547     elem.effect( o );
11548     };
11549    
11550    
11551     /*!
11552     * jQuery UI Effects Pulsate 1.11.4
11553     * http://jqueryui.com
11554     *
11555     * Copyright jQuery Foundation and other contributors
11556     * Released under the MIT license.
11557     * http://jquery.org/license
11558     *
11559     * http://api.jqueryui.com/pulsate-effect/
11560     */
11561    
11562    
11563     var effectPulsate = $.effects.effect.pulsate = function( o, done ) {
11564     var elem = $( this ),
11565     mode = $.effects.setMode( elem, o.mode || "show" ),
11566     show = mode === "show",
11567     hide = mode === "hide",
11568     showhide = ( show || mode === "hide" ),
11569    
11570     // showing or hiding leaves of the "last" animation
11571     anims = ( ( o.times || 5 ) * 2 ) + ( showhide ? 1 : 0 ),
11572     duration = o.duration / anims,
11573     animateTo = 0,
11574     queue = elem.queue(),
11575     queuelen = queue.length,
11576     i;
11577    
11578     if ( show || !elem.is(":visible")) {
11579     elem.css( "opacity", 0 ).show();
11580     animateTo = 1;
11581     }
11582    
11583     // anims - 1 opacity "toggles"
11584     for ( i = 1; i < anims; i++ ) {
11585     elem.animate({
11586     opacity: animateTo
11587     }, duration, o.easing );
11588     animateTo = 1 - animateTo;
11589     }
11590    
11591     elem.animate({
11592     opacity: animateTo
11593     }, duration, o.easing);
11594    
11595     elem.queue(function() {
11596     if ( hide ) {
11597     elem.hide();
11598     }
11599     done();
11600     });
11601    
11602     // We just queued up "anims" animations, we need to put them next in the queue
11603     if ( queuelen > 1 ) {
11604     queue.splice.apply( queue,
11605     [ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) );
11606     }
11607     elem.dequeue();
11608     };
11609    
11610    
11611     /*!
11612     * jQuery UI Effects Shake 1.11.4
11613     * http://jqueryui.com
11614     *
11615     * Copyright jQuery Foundation and other contributors
11616     * Released under the MIT license.
11617     * http://jquery.org/license
11618     *
11619     * http://api.jqueryui.com/shake-effect/
11620     */
11621    
11622    
11623     var effectShake = $.effects.effect.shake = function( o, done ) {
11624    
11625     var el = $( this ),
11626     props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
11627     mode = $.effects.setMode( el, o.mode || "effect" ),
11628     direction = o.direction || "left",
11629     distance = o.distance || 20,
11630     times = o.times || 3,
11631     anims = times * 2 + 1,
11632     speed = Math.round( o.duration / anims ),
11633     ref = (direction === "up" || direction === "down") ? "top" : "left",
11634     positiveMotion = (direction === "up" || direction === "left"),
11635     animation = {},
11636     animation1 = {},
11637     animation2 = {},
11638     i,
11639    
11640     // we will need to re-assemble the queue to stack our animations in place
11641     queue = el.queue(),
11642     queuelen = queue.length;
11643    
11644     $.effects.save( el, props );
11645     el.show();
11646     $.effects.createWrapper( el );
11647    
11648     // Animation
11649     animation[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance;
11650     animation1[ ref ] = ( positiveMotion ? "+=" : "-=" ) + distance * 2;
11651     animation2[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance * 2;
11652    
11653     // Animate
11654     el.animate( animation, speed, o.easing );
11655    
11656     // Shakes
11657     for ( i = 1; i < times; i++ ) {
11658     el.animate( animation1, speed, o.easing ).animate( animation2, speed, o.easing );
11659     }
11660     el
11661     .animate( animation1, speed, o.easing )
11662     .animate( animation, speed / 2, o.easing )
11663     .queue(function() {
11664     if ( mode === "hide" ) {
11665     el.hide();
11666     }
11667     $.effects.restore( el, props );
11668     $.effects.removeWrapper( el );
11669     done();
11670     });
11671    
11672     // inject all the animations we just queued to be first in line (after "inprogress")
11673     if ( queuelen > 1) {
11674     queue.splice.apply( queue,
11675     [ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) );
11676     }
11677     el.dequeue();
11678    
11679     };
11680    
11681    
11682     /*!
11683     * jQuery UI Effects Slide 1.11.4
11684     * http://jqueryui.com
11685     *
11686     * Copyright jQuery Foundation and other contributors
11687     * Released under the MIT license.
11688     * http://jquery.org/license
11689     *
11690     * http://api.jqueryui.com/slide-effect/
11691     */
11692    
11693    
11694     var effectSlide = $.effects.effect.slide = function( o, done ) {
11695    
11696     // Create element
11697     var el = $( this ),
11698     props = [ "position", "top", "bottom", "left", "right", "width", "height" ],
11699     mode = $.effects.setMode( el, o.mode || "show" ),
11700     show = mode === "show",
11701     direction = o.direction || "left",
11702     ref = (direction === "up" || direction === "down") ? "top" : "left",
11703     positiveMotion = (direction === "up" || direction === "left"),
11704     distance,
11705     animation = {};
11706    
11707     // Adjust
11708     $.effects.save( el, props );
11709     el.show();
11710     distance = o.distance || el[ ref === "top" ? "outerHeight" : "outerWidth" ]( true );
11711    
11712     $.effects.createWrapper( el ).css({
11713     overflow: "hidden"
11714     });
11715    
11716     if ( show ) {
11717     el.css( ref, positiveMotion ? (isNaN(distance) ? "-" + distance : -distance) : distance );
11718     }
11719    
11720     // Animation
11721     animation[ ref ] = ( show ?
11722     ( positiveMotion ? "+=" : "-=") :
11723     ( positiveMotion ? "-=" : "+=")) +
11724     distance;
11725    
11726     // Animate
11727     el.animate( animation, {
11728     queue: false,
11729     duration: o.duration,
11730     easing: o.easing,
11731     complete: function() {
11732     if ( mode === "hide" ) {
11733     el.hide();
11734     }
11735     $.effects.restore( el, props );
11736     $.effects.removeWrapper( el );
11737     done();
11738     }
11739     });
11740     };
11741    
11742    
11743     /*!
11744     * jQuery UI Effects Transfer 1.11.4
11745     * http://jqueryui.com
11746     *
11747     * Copyright jQuery Foundation and other contributors
11748     * Released under the MIT license.
11749     * http://jquery.org/license
11750     *
11751     * http://api.jqueryui.com/transfer-effect/
11752     */
11753    
11754    
11755     var effectTransfer = $.effects.effect.transfer = function( o, done ) {
11756     var elem = $( this ),
11757     target = $( o.to ),
11758     targetFixed = target.css( "position" ) === "fixed",
11759     body = $("body"),
11760     fixTop = targetFixed ? body.scrollTop() : 0,
11761     fixLeft = targetFixed ? body.scrollLeft() : 0,
11762     endPosition = target.offset(),
11763     animation = {
11764     top: endPosition.top - fixTop,
11765     left: endPosition.left - fixLeft,
11766     height: target.innerHeight(),
11767     width: target.innerWidth()
11768     },
11769     startPosition = elem.offset(),
11770     transfer = $( "<div class='ui-effects-transfer'></div>" )
11771     .appendTo( document.body )
11772     .addClass( o.className )
11773     .css({
11774     top: startPosition.top - fixTop,
11775     left: startPosition.left - fixLeft,
11776     height: elem.innerHeight(),
11777     width: elem.innerWidth(),
11778     position: targetFixed ? "fixed" : "absolute"
11779     })
11780     .animate( animation, o.duration, o.easing, function() {
11781     transfer.remove();
11782     done();
11783     });
11784     };
11785    
11786    
11787     /*!
11788     * jQuery UI Progressbar 1.11.4
11789     * http://jqueryui.com
11790     *
11791     * Copyright jQuery Foundation and other contributors
11792     * Released under the MIT license.
11793     * http://jquery.org/license
11794     *
11795     * http://api.jqueryui.com/progressbar/
11796     */
11797    
11798    
11799     var progressbar = $.widget( "ui.progressbar", {
11800     version: "1.11.4",
11801     options: {
11802     max: 100,
11803     value: 0,
11804    
11805     change: null,
11806     complete: null
11807     },
11808    
11809     min: 0,
11810    
11811     _create: function() {
11812     // Constrain initial value
11813     this.oldValue = this.options.value = this._constrainedValue();
11814    
11815     this.element
11816     .addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
11817     .attr({
11818     // Only set static values, aria-valuenow and aria-valuemax are
11819     // set inside _refreshValue()
11820     role: "progressbar",
11821     "aria-valuemin": this.min
11822     });
11823    
11824     this.valueDiv = $( "<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>" )
11825     .appendTo( this.element );
11826    
11827     this._refreshValue();
11828     },
11829    
11830     _destroy: function() {
11831     this.element
11832     .removeClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
11833     .removeAttr( "role" )
11834     .removeAttr( "aria-valuemin" )
11835     .removeAttr( "aria-valuemax" )
11836     .removeAttr( "aria-valuenow" );
11837    
11838     this.valueDiv.remove();
11839     },
11840    
11841     value: function( newValue ) {
11842     if ( newValue === undefined ) {
11843     return this.options.value;
11844     }
11845    
11846     this.options.value = this._constrainedValue( newValue );
11847     this._refreshValue();
11848     },
11849    
11850     _constrainedValue: function( newValue ) {
11851     if ( newValue === undefined ) {
11852     newValue = this.options.value;
11853     }
11854    
11855     this.indeterminate = newValue === false;
11856    
11857     // sanitize value
11858     if ( typeof newValue !== "number" ) {
11859     newValue = 0;
11860     }
11861    
11862     return this.indeterminate ? false :
11863     Math.min( this.options.max, Math.max( this.min, newValue ) );
11864     },
11865    
11866     _setOptions: function( options ) {
11867     // Ensure "value" option is set after other values (like max)
11868     var value = options.value;
11869     delete options.value;
11870    
11871     this._super( options );
11872    
11873     this.options.value = this._constrainedValue( value );
11874     this._refreshValue();
11875     },
11876    
11877     _setOption: function( key, value ) {
11878     if ( key === "max" ) {
11879     // Don't allow a max less than min
11880     value = Math.max( this.min, value );
11881     }
11882     if ( key === "disabled" ) {
11883     this.element
11884     .toggleClass( "ui-state-disabled", !!value )
11885     .attr( "aria-disabled", value );
11886     }
11887     this._super( key, value );
11888     },
11889    
11890     _percentage: function() {
11891     return this.indeterminate ? 100 : 100 * ( this.options.value - this.min ) / ( this.options.max - this.min );
11892     },
11893    
11894     _refreshValue: function() {
11895     var value = this.options.value,
11896     percentage = this._percentage();
11897    
11898     this.valueDiv
11899     .toggle( this.indeterminate || value > this.min )
11900     .toggleClass( "ui-corner-right", value === this.options.max )
11901     .width( percentage.toFixed(0) + "%" );
11902    
11903     this.element.toggleClass( "ui-progressbar-indeterminate", this.indeterminate );
11904    
11905     if ( this.indeterminate ) {
11906     this.element.removeAttr( "aria-valuenow" );
11907     if ( !this.overlayDiv ) {
11908     this.overlayDiv = $( "<div class='ui-progressbar-overlay'></div>" ).appendTo( this.valueDiv );
11909     }
11910     } else {
11911     this.element.attr({
11912     "aria-valuemax": this.options.max,
11913     "aria-valuenow": value
11914     });
11915     if ( this.overlayDiv ) {
11916     this.overlayDiv.remove();
11917     this.overlayDiv = null;
11918     }
11919     }
11920    
11921     if ( this.oldValue !== value ) {
11922     this.oldValue = value;
11923     this._trigger( "change" );
11924     }
11925     if ( value === this.options.max ) {
11926     this._trigger( "complete" );
11927     }
11928     }
11929     });
11930    
11931    
11932     /*!
11933     * jQuery UI Selectable 1.11.4
11934     * http://jqueryui.com
11935     *
11936     * Copyright jQuery Foundation and other contributors
11937     * Released under the MIT license.
11938     * http://jquery.org/license
11939     *
11940     * http://api.jqueryui.com/selectable/
11941     */
11942    
11943    
11944     var selectable = $.widget("ui.selectable", $.ui.mouse, {
11945     version: "1.11.4",
11946     options: {
11947     appendTo: "body",
11948     autoRefresh: true,
11949     distance: 0,
11950     filter: "*",
11951     tolerance: "touch",
11952    
11953     // callbacks
11954     selected: null,
11955     selecting: null,
11956     start: null,
11957     stop: null,
11958     unselected: null,
11959     unselecting: null
11960     },
11961     _create: function() {
11962     var selectees,
11963     that = this;
11964    
11965     this.element.addClass("ui-selectable");
11966    
11967     this.dragged = false;
11968    
11969     // cache selectee children based on filter
11970     this.refresh = function() {
11971     selectees = $(that.options.filter, that.element[0]);
11972     selectees.addClass("ui-selectee");
11973     selectees.each(function() {
11974     var $this = $(this),
11975     pos = $this.offset();
11976     $.data(this, "selectable-item", {
11977     element: this,
11978     $element: $this,
11979     left: pos.left,
11980     top: pos.top,
11981     right: pos.left + $this.outerWidth(),
11982     bottom: pos.top + $this.outerHeight(),
11983     startselected: false,
11984     selected: $this.hasClass("ui-selected"),
11985     selecting: $this.hasClass("ui-selecting"),
11986     unselecting: $this.hasClass("ui-unselecting")
11987     });
11988     });
11989     };
11990     this.refresh();
11991    
11992     this.selectees = selectees.addClass("ui-selectee");
11993    
11994     this._mouseInit();
11995    
11996     this.helper = $("<div class='ui-selectable-helper'></div>");
11997     },
11998    
11999     _destroy: function() {
12000     this.selectees
12001     .removeClass("ui-selectee")
12002     .removeData("selectable-item");
12003     this.element
12004     .removeClass("ui-selectable ui-selectable-disabled");
12005     this._mouseDestroy();
12006     },
12007    
12008     _mouseStart: function(event) {
12009     var that = this,
12010     options = this.options;
12011    
12012     this.opos = [ event.pageX, event.pageY ];
12013    
12014     if (this.options.disabled) {
12015     return;
12016     }
12017    
12018     this.selectees = $(options.filter, this.element[0]);
12019    
12020     this._trigger("start", event);
12021    
12022     $(options.appendTo).append(this.helper);
12023     // position helper (lasso)
12024     this.helper.css({
12025     "left": event.pageX,
12026     "top": event.pageY,
12027     "width": 0,
12028     "height": 0
12029     });
12030    
12031     if (options.autoRefresh) {
12032     this.refresh();
12033     }
12034    
12035     this.selectees.filter(".ui-selected").each(function() {
12036     var selectee = $.data(this, "selectable-item");
12037     selectee.startselected = true;
12038     if (!event.metaKey && !event.ctrlKey) {
12039     selectee.$element.removeClass("ui-selected");
12040     selectee.selected = false;
12041     selectee.$element.addClass("ui-unselecting");
12042     selectee.unselecting = true;
12043     // selectable UNSELECTING callback
12044     that._trigger("unselecting", event, {
12045     unselecting: selectee.element
12046     });
12047     }
12048     });
12049    
12050     $(event.target).parents().addBack().each(function() {
12051     var doSelect,
12052     selectee = $.data(this, "selectable-item");
12053     if (selectee) {
12054     doSelect = (!event.metaKey && !event.ctrlKey) || !selectee.$element.hasClass("ui-selected");
12055     selectee.$element
12056     .removeClass(doSelect ? "ui-unselecting" : "ui-selected")
12057     .addClass(doSelect ? "ui-selecting" : "ui-unselecting");
12058     selectee.unselecting = !doSelect;
12059     selectee.selecting = doSelect;
12060     selectee.selected = doSelect;
12061     // selectable (UN)SELECTING callback
12062     if (doSelect) {
12063     that._trigger("selecting", event, {
12064     selecting: selectee.element
12065     });
12066     } else {
12067     that._trigger("unselecting", event, {
12068     unselecting: selectee.element
12069     });
12070     }
12071     return false;
12072     }
12073     });
12074    
12075     },
12076    
12077     _mouseDrag: function(event) {
12078    
12079     this.dragged = true;
12080    
12081     if (this.options.disabled) {
12082     return;
12083     }
12084    
12085     var tmp,
12086     that = this,
12087     options = this.options,
12088     x1 = this.opos[0],
12089     y1 = this.opos[1],
12090     x2 = event.pageX,
12091     y2 = event.pageY;
12092    
12093     if (x1 > x2) { tmp = x2; x2 = x1; x1 = tmp; }
12094     if (y1 > y2) { tmp = y2; y2 = y1; y1 = tmp; }
12095     this.helper.css({ left: x1, top: y1, width: x2 - x1, height: y2 - y1 });
12096    
12097     this.selectees.each(function() {
12098     var selectee = $.data(this, "selectable-item"),
12099     hit = false;
12100    
12101     //prevent helper from being selected if appendTo: selectable
12102     if (!selectee || selectee.element === that.element[0]) {
12103     return;
12104     }
12105    
12106     if (options.tolerance === "touch") {
12107     hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) );
12108     } else if (options.tolerance === "fit") {
12109     hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2);
12110     }
12111    
12112     if (hit) {
12113     // SELECT
12114     if (selectee.selected) {
12115     selectee.$element.removeClass("ui-selected");
12116     selectee.selected = false;
12117     }
12118     if (selectee.unselecting) {
12119     selectee.$element.removeClass("ui-unselecting");
12120     selectee.unselecting = false;
12121     }
12122     if (!selectee.selecting) {
12123     selectee.$element.addClass("ui-selecting");
12124     selectee.selecting = true;
12125     // selectable SELECTING callback
12126     that._trigger("selecting", event, {
12127     selecting: selectee.element
12128     });
12129     }
12130     } else {
12131     // UNSELECT
12132     if (selectee.selecting) {
12133     if ((event.metaKey || event.ctrlKey) && selectee.startselected) {
12134     selectee.$element.removeClass("ui-selecting");
12135     selectee.selecting = false;
12136     selectee.$element.addClass("ui-selected");
12137     selectee.selected = true;
12138     } else {
12139     selectee.$element.removeClass("ui-selecting");
12140     selectee.selecting = false;
12141     if (selectee.startselected) {
12142     selectee.$element.addClass("ui-unselecting");
12143     selectee.unselecting = true;
12144     }
12145     // selectable UNSELECTING callback
12146     that._trigger("unselecting", event, {
12147     unselecting: selectee.element
12148     });
12149     }
12150     }
12151     if (selectee.selected) {
12152     if (!event.metaKey && !event.ctrlKey && !selectee.startselected) {
12153     selectee.$element.removeClass("ui-selected");
12154     selectee.selected = false;
12155    
12156     selectee.$element.addClass("ui-unselecting");
12157     selectee.unselecting = true;
12158     // selectable UNSELECTING callback
12159     that._trigger("unselecting", event, {
12160     unselecting: selectee.element
12161     });
12162     }
12163     }
12164     }
12165     });
12166    
12167     return false;
12168     },
12169    
12170     _mouseStop: function(event) {
12171     var that = this;
12172    
12173     this.dragged = false;
12174    
12175     $(".ui-unselecting", this.element[0]).each(function() {
12176     var selectee = $.data(this, "selectable-item");
12177     selectee.$element.removeClass("ui-unselecting");
12178     selectee.unselecting = false;
12179     selectee.startselected = false;
12180     that._trigger("unselected", event, {
12181     unselected: selectee.element
12182     });
12183     });
12184     $(".ui-selecting", this.element[0]).each(function() {
12185     var selectee = $.data(this, "selectable-item");
12186     selectee.$element.removeClass("ui-selecting").addClass("ui-selected");
12187     selectee.selecting = false;
12188     selectee.selected = true;
12189     selectee.startselected = true;
12190     that._trigger("selected", event, {
12191     selected: selectee.element
12192     });
12193     });
12194     this._trigger("stop", event);
12195    
12196     this.helper.remove();
12197    
12198     return false;
12199     }
12200    
12201     });
12202    
12203    
12204     /*!
12205     * jQuery UI Selectmenu 1.11.4
12206     * http://jqueryui.com
12207     *
12208     * Copyright jQuery Foundation and other contributors
12209     * Released under the MIT license.
12210     * http://jquery.org/license
12211     *
12212     * http://api.jqueryui.com/selectmenu
12213     */
12214    
12215    
12216     var selectmenu = $.widget( "ui.selectmenu", {
12217     version: "1.11.4",
12218     defaultElement: "<select>",
12219     options: {
12220     appendTo: null,
12221     disabled: null,
12222     icons: {
12223     button: "ui-icon-triangle-1-s"
12224     },
12225     position: {
12226     my: "left top",
12227     at: "left bottom",
12228     collision: "none"
12229     },
12230     width: null,
12231    
12232     // callbacks
12233     change: null,
12234     close: null,
12235     focus: null,
12236     open: null,
12237     select: null
12238     },
12239    
12240     _create: function() {
12241     var selectmenuId = this.element.uniqueId().attr( "id" );
12242     this.ids = {
12243     element: selectmenuId,
12244     button: selectmenuId + "-button",
12245     menu: selectmenuId + "-menu"
12246     };
12247    
12248     this._drawButton();
12249     this._drawMenu();
12250    
12251     if ( this.options.disabled ) {
12252     this.disable();
12253     }
12254     },
12255    
12256     _drawButton: function() {
12257     var that = this;
12258    
12259     // Associate existing label with the new button
12260     this.label = $( "label[for='" + this.ids.element + "']" ).attr( "for", this.ids.button );
12261     this._on( this.label, {
12262     click: function( event ) {
12263     this.button.focus();
12264     event.preventDefault();
12265     }
12266     });
12267    
12268     // Hide original select element
12269     this.element.hide();
12270    
12271     // Create button
12272     this.button = $( "<span>", {
12273     "class": "ui-selectmenu-button ui-widget ui-state-default ui-corner-all",
12274     tabindex: this.options.disabled ? -1 : 0,
12275     id: this.ids.button,
12276     role: "combobox",
12277     "aria-expanded": "false",
12278     "aria-autocomplete": "list",
12279     "aria-owns": this.ids.menu,
12280     "aria-haspopup": "true"
12281     })
12282     .insertAfter( this.element );
12283    
12284     $( "<span>", {
12285     "class": "ui-icon " + this.options.icons.button
12286     })
12287     .prependTo( this.button );
12288    
12289     this.buttonText = $( "<span>", {
12290     "class": "ui-selectmenu-text"
12291     })
12292     .appendTo( this.button );
12293    
12294     this._setText( this.buttonText, this.element.find( "option:selected" ).text() );
12295     this._resizeButton();
12296    
12297     this._on( this.button, this._buttonEvents );
12298     this.button.one( "focusin", function() {
12299    
12300     // Delay rendering the menu items until the button receives focus.
12301     // The menu may have already been rendered via a programmatic open.
12302     if ( !that.menuItems ) {
12303     that._refreshMenu();
12304     }
12305     });
12306     this._hoverable( this.button );
12307     this._focusable( this.button );
12308     },
12309    
12310     _drawMenu: function() {
12311     var that = this;
12312    
12313     // Create menu
12314     this.menu = $( "<ul>", {
12315     "aria-hidden": "true",
12316     "aria-labelledby": this.ids.button,
12317     id: this.ids.menu
12318     });
12319    
12320     // Wrap menu
12321     this.menuWrap = $( "<div>", {
12322     "class": "ui-selectmenu-menu ui-front"
12323     })
12324     .append( this.menu )
12325     .appendTo( this._appendTo() );
12326    
12327     // Initialize menu widget
12328     this.menuInstance = this.menu
12329     .menu({
12330     role: "listbox",
12331     select: function( event, ui ) {
12332     event.preventDefault();
12333    
12334     // support: IE8
12335     // If the item was selected via a click, the text selection
12336     // will be destroyed in IE
12337     that._setSelection();
12338    
12339     that._select( ui.item.data( "ui-selectmenu-item" ), event );
12340     },
12341     focus: function( event, ui ) {
12342     var item = ui.item.data( "ui-selectmenu-item" );
12343    
12344     // Prevent inital focus from firing and check if its a newly focused item
12345     if ( that.focusIndex != null && item.index !== that.focusIndex ) {
12346     that._trigger( "focus", event, { item: item } );
12347     if ( !that.isOpen ) {
12348     that._select( item, event );
12349     }
12350     }
12351     that.focusIndex = item.index;
12352    
12353     that.button.attr( "aria-activedescendant",
12354     that.menuItems.eq( item.index ).attr( "id" ) );
12355     }
12356     })
12357     .menu( "instance" );
12358    
12359     // Adjust menu styles to dropdown
12360     this.menu
12361     .addClass( "ui-corner-bottom" )
12362     .removeClass( "ui-corner-all" );
12363    
12364     // Don't close the menu on mouseleave
12365     this.menuInstance._off( this.menu, "mouseleave" );
12366    
12367     // Cancel the menu's collapseAll on document click
12368     this.menuInstance._closeOnDocumentClick = function() {
12369     return false;
12370     };
12371    
12372     // Selects often contain empty items, but never contain dividers
12373     this.menuInstance._isDivider = function() {
12374     return false;
12375     };
12376     },
12377    
12378     refresh: function() {
12379     this._refreshMenu();
12380     this._setText( this.buttonText, this._getSelectedItem().text() );
12381     if ( !this.options.width ) {
12382     this._resizeButton();
12383     }
12384     },
12385    
12386     _refreshMenu: function() {
12387     this.menu.empty();
12388    
12389     var item,
12390     options = this.element.find( "option" );
12391    
12392     if ( !options.length ) {
12393     return;
12394     }
12395    
12396     this._parseOptions( options );
12397     this._renderMenu( this.menu, this.items );
12398    
12399     this.menuInstance.refresh();
12400     this.menuItems = this.menu.find( "li" ).not( ".ui-selectmenu-optgroup" );
12401    
12402     item = this._getSelectedItem();
12403    
12404     // Update the menu to have the correct item focused
12405     this.menuInstance.focus( null, item );
12406     this._setAria( item.data( "ui-selectmenu-item" ) );
12407    
12408     // Set disabled state
12409     this._setOption( "disabled", this.element.prop( "disabled" ) );
12410     },
12411    
12412     open: function( event ) {
12413     if ( this.options.disabled ) {
12414     return;
12415     }
12416    
12417     // If this is the first time the menu is being opened, render the items
12418     if ( !this.menuItems ) {
12419     this._refreshMenu();
12420     } else {
12421    
12422     // Menu clears focus on close, reset focus to selected item
12423     this.menu.find( ".ui-state-focus" ).removeClass( "ui-state-focus" );
12424     this.menuInstance.focus( null, this._getSelectedItem() );
12425     }
12426    
12427     this.isOpen = true;
12428     this._toggleAttr();
12429     this._resizeMenu();
12430     this._position();
12431    
12432     this._on( this.document, this._documentClick );
12433    
12434     this._trigger( "open", event );
12435     },
12436    
12437     _position: function() {
12438     this.menuWrap.position( $.extend( { of: this.button }, this.options.position ) );
12439     },
12440    
12441     close: function( event ) {
12442     if ( !this.isOpen ) {
12443     return;
12444     }
12445    
12446     this.isOpen = false;
12447     this._toggleAttr();
12448    
12449     this.range = null;
12450     this._off( this.document );
12451    
12452     this._trigger( "close", event );
12453     },
12454    
12455     widget: function() {
12456     return this.button;
12457     },
12458    
12459     menuWidget: function() {
12460     return this.menu;
12461     },
12462    
12463     _renderMenu: function( ul, items ) {
12464     var that = this,
12465     currentOptgroup = "";
12466    
12467     $.each( items, function( index, item ) {
12468     if ( item.optgroup !== currentOptgroup ) {
12469     $( "<li>", {
12470     "class": "ui-selectmenu-optgroup ui-menu-divider" +
12471     ( item.element.parent( "optgroup" ).prop( "disabled" ) ?
12472     " ui-state-disabled" :
12473     "" ),
12474     text: item.optgroup
12475     })
12476     .appendTo( ul );
12477    
12478     currentOptgroup = item.optgroup;
12479     }
12480    
12481     that._renderItemData( ul, item );
12482     });
12483     },
12484    
12485     _renderItemData: function( ul, item ) {
12486     return this._renderItem( ul, item ).data( "ui-selectmenu-item", item );
12487     },
12488    
12489     _renderItem: function( ul, item ) {
12490     var li = $( "<li>" );
12491    
12492     if ( item.disabled ) {
12493     li.addClass( "ui-state-disabled" );
12494     }
12495     this._setText( li, item.label );
12496    
12497     return li.appendTo( ul );
12498     },
12499    
12500     _setText: function( element, value ) {
12501     if ( value ) {
12502     element.text( value );
12503     } else {
12504     element.html( "&#160;" );
12505     }
12506     },
12507    
12508     _move: function( direction, event ) {
12509     var item, next,
12510     filter = ".ui-menu-item";
12511    
12512     if ( this.isOpen ) {
12513     item = this.menuItems.eq( this.focusIndex );
12514     } else {
12515     item = this.menuItems.eq( this.element[ 0 ].selectedIndex );
12516     filter += ":not(.ui-state-disabled)";
12517     }
12518    
12519     if ( direction === "first" || direction === "last" ) {
12520     next = item[ direction === "first" ? "prevAll" : "nextAll" ]( filter ).eq( -1 );
12521     } else {
12522     next = item[ direction + "All" ]( filter ).eq( 0 );
12523     }
12524    
12525     if ( next.length ) {
12526     this.menuInstance.focus( event, next );
12527     }
12528     },
12529    
12530     _getSelectedItem: function() {
12531     return this.menuItems.eq( this.element[ 0 ].selectedIndex );
12532     },
12533    
12534     _toggle: function( event ) {
12535     this[ this.isOpen ? "close" : "open" ]( event );
12536     },
12537    
12538     _setSelection: function() {
12539     var selection;
12540    
12541     if ( !this.range ) {
12542     return;
12543     }
12544    
12545     if ( window.getSelection ) {
12546     selection = window.getSelection();
12547     selection.removeAllRanges();
12548     selection.addRange( this.range );
12549    
12550     // support: IE8
12551     } else {
12552     this.range.select();
12553     }
12554    
12555     // support: IE
12556     // Setting the text selection kills the button focus in IE, but
12557     // restoring the focus doesn't kill the selection.
12558     this.button.focus();
12559     },
12560    
12561     _documentClick: {
12562     mousedown: function( event ) {
12563     if ( !this.isOpen ) {
12564     return;
12565     }
12566    
12567     if ( !$( event.target ).closest( ".ui-selectmenu-menu, #" + this.ids.button ).length ) {
12568     this.close( event );
12569     }
12570     }
12571     },
12572    
12573     _buttonEvents: {
12574    
12575     // Prevent text selection from being reset when interacting with the selectmenu (#10144)
12576     mousedown: function() {
12577     var selection;
12578    
12579     if ( window.getSelection ) {
12580     selection = window.getSelection();
12581     if ( selection.rangeCount ) {
12582     this.range = selection.getRangeAt( 0 );
12583     }
12584    
12585     // support: IE8
12586     } else {
12587     this.range = document.selection.createRange();
12588     }
12589     },
12590    
12591     click: function( event ) {
12592     this._setSelection();
12593     this._toggle( event );
12594     },
12595    
12596     keydown: function( event ) {
12597     var preventDefault = true;
12598     switch ( event.keyCode ) {
12599     case $.ui.keyCode.TAB:
12600     case $.ui.keyCode.ESCAPE:
12601     this.close( event );
12602     preventDefault = false;
12603     break;
12604     case $.ui.keyCode.ENTER:
12605     if ( this.isOpen ) {
12606     this._selectFocusedItem( event );
12607     }
12608     break;
12609     case $.ui.keyCode.UP:
12610     if ( event.altKey ) {
12611     this._toggle( event );
12612     } else {
12613     this._move( "prev", event );
12614     }
12615     break;
12616     case $.ui.keyCode.DOWN:
12617     if ( event.altKey ) {
12618     this._toggle( event );
12619     } else {
12620     this._move( "next", event );
12621     }
12622     break;
12623     case $.ui.keyCode.SPACE:
12624     if ( this.isOpen ) {
12625     this._selectFocusedItem( event );
12626     } else {
12627     this._toggle( event );
12628     }
12629     break;
12630     case $.ui.keyCode.LEFT:
12631     this._move( "prev", event );
12632     break;
12633     case $.ui.keyCode.RIGHT:
12634     this._move( "next", event );
12635     break;
12636     case $.ui.keyCode.HOME:
12637     case $.ui.keyCode.PAGE_UP:
12638     this._move( "first", event );
12639     break;
12640     case $.ui.keyCode.END:
12641     case $.ui.keyCode.PAGE_DOWN:
12642     this._move( "last", event );
12643     break;
12644     default:
12645     this.menu.trigger( event );
12646     preventDefault = false;
12647     }
12648    
12649     if ( preventDefault ) {
12650     event.preventDefault();
12651     }
12652     }
12653     },
12654    
12655     _selectFocusedItem: function( event ) {
12656     var item = this.menuItems.eq( this.focusIndex );
12657     if ( !item.hasClass( "ui-state-disabled" ) ) {
12658     this._select( item.data( "ui-selectmenu-item" ), event );
12659     }
12660     },
12661    
12662     _select: function( item, event ) {
12663     var oldIndex = this.element[ 0 ].selectedIndex;
12664    
12665     // Change native select element
12666     this.element[ 0 ].selectedIndex = item.index;
12667     this._setText( this.buttonText, item.label );
12668     this._setAria( item );
12669     this._trigger( "select", event, { item: item } );
12670    
12671     if ( item.index !== oldIndex ) {
12672     this._trigger( "change", event, { item: item } );
12673     }
12674    
12675     this.close( event );
12676     },
12677    
12678     _setAria: function( item ) {
12679     var id = this.menuItems.eq( item.index ).attr( "id" );
12680    
12681     this.button.attr({
12682     "aria-labelledby": id,
12683     "aria-activedescendant": id
12684     });
12685     this.menu.attr( "aria-activedescendant", id );
12686     },
12687    
12688     _setOption: function( key, value ) {
12689     if ( key === "icons" ) {
12690     this.button.find( "span.ui-icon" )
12691     .removeClass( this.options.icons.button )
12692     .addClass( value.button );
12693     }
12694    
12695     this._super( key, value );
12696    
12697     if ( key === "appendTo" ) {
12698     this.menuWrap.appendTo( this._appendTo() );
12699     }
12700    
12701     if ( key === "disabled" ) {
12702     this.menuInstance.option( "disabled", value );
12703     this.button
12704     .toggleClass( "ui-state-disabled", value )
12705     .attr( "aria-disabled", value );
12706    
12707     this.element.prop( "disabled", value );
12708     if ( value ) {
12709     this.button.attr( "tabindex", -1 );
12710     this.close();
12711     } else {
12712     this.button.attr( "tabindex", 0 );
12713     }
12714     }
12715    
12716     if ( key === "width" ) {
12717     this._resizeButton();
12718     }
12719     },
12720    
12721     _appendTo: function() {
12722     var element = this.options.appendTo;
12723    
12724     if ( element ) {
12725     element = element.jquery || element.nodeType ?
12726     $( element ) :
12727     this.document.find( element ).eq( 0 );
12728     }
12729    
12730     if ( !element || !element[ 0 ] ) {
12731     element = this.element.closest( ".ui-front" );
12732     }
12733    
12734     if ( !element.length ) {
12735     element = this.document[ 0 ].body;
12736     }
12737    
12738     return element;
12739     },
12740    
12741     _toggleAttr: function() {
12742     this.button
12743     .toggleClass( "ui-corner-top", this.isOpen )
12744     .toggleClass( "ui-corner-all", !this.isOpen )
12745     .attr( "aria-expanded", this.isOpen );
12746     this.menuWrap.toggleClass( "ui-selectmenu-open", this.isOpen );
12747     this.menu.attr( "aria-hidden", !this.isOpen );
12748     },
12749    
12750     _resizeButton: function() {
12751     var width = this.options.width;
12752    
12753     if ( !width ) {
12754     width = this.element.show().outerWidth();
12755     this.element.hide();
12756     }
12757    
12758     this.button.outerWidth( width );
12759     },
12760    
12761     _resizeMenu: function() {
12762     this.menu.outerWidth( Math.max(
12763     this.button.outerWidth(),
12764    
12765     // support: IE10
12766     // IE10 wraps long text (possibly a rounding bug)
12767     // so we add 1px to avoid the wrapping
12768     this.menu.width( "" ).outerWidth() + 1
12769     ) );
12770     },
12771    
12772     _getCreateOptions: function() {
12773     return { disabled: this.element.prop( "disabled" ) };
12774     },
12775    
12776     _parseOptions: function( options ) {
12777     var data = [];
12778     options.each(function( index, item ) {
12779     var option = $( item ),
12780     optgroup = option.parent( "optgroup" );
12781     data.push({
12782     element: option,
12783     index: index,
12784     value: option.val(),
12785     label: option.text(),
12786     optgroup: optgroup.attr( "label" ) || "",
12787     disabled: optgroup.prop( "disabled" ) || option.prop( "disabled" )
12788     });
12789     });
12790     this.items = data;
12791     },
12792    
12793     _destroy: function() {
12794     this.menuWrap.remove();
12795     this.button.remove();
12796     this.element.show();
12797     this.element.removeUniqueId();
12798     this.label.attr( "for", this.ids.element );
12799     }
12800     });
12801    
12802    
12803     /*!
12804     * jQuery UI Slider 1.11.4
12805     * http://jqueryui.com
12806     *
12807     * Copyright jQuery Foundation and other contributors
12808     * Released under the MIT license.
12809     * http://jquery.org/license
12810     *
12811     * http://api.jqueryui.com/slider/
12812     */
12813    
12814    
12815     var slider = $.widget( "ui.slider", $.ui.mouse, {
12816     version: "1.11.4",
12817     widgetEventPrefix: "slide",
12818    
12819     options: {
12820     animate: false,
12821     distance: 0,
12822     max: 100,
12823     min: 0,
12824     orientation: "horizontal",
12825     range: false,
12826     step: 1,
12827     value: 0,
12828     values: null,
12829    
12830     // callbacks
12831     change: null,
12832     slide: null,
12833     start: null,
12834     stop: null
12835     },
12836    
12837     // number of pages in a slider
12838     // (how many times can you page up/down to go through the whole range)
12839     numPages: 5,
12840    
12841     _create: function() {
12842     this._keySliding = false;
12843     this._mouseSliding = false;
12844     this._animateOff = true;
12845     this._handleIndex = null;
12846     this._detectOrientation();
12847     this._mouseInit();
12848     this._calculateNewMax();
12849    
12850     this.element
12851     .addClass( "ui-slider" +
12852     " ui-slider-" + this.orientation +
12853     " ui-widget" +
12854     " ui-widget-content" +
12855     " ui-corner-all");
12856    
12857     this._refresh();
12858     this._setOption( "disabled", this.options.disabled );
12859    
12860     this._animateOff = false;
12861     },
12862    
12863     _refresh: function() {
12864     this._createRange();
12865     this._createHandles();
12866     this._setupEvents();
12867     this._refreshValue();
12868     },
12869    
12870     _createHandles: function() {
12871     var i, handleCount,
12872     options = this.options,
12873     existingHandles = this.element.find( ".ui-slider-handle" ).addClass( "ui-state-default ui-corner-all" ),
12874     handle = "<span class='ui-slider-handle ui-state-default ui-corner-all' tabindex='0'></span>",
12875     handles = [];
12876    
12877     handleCount = ( options.values && options.values.length ) || 1;
12878    
12879     if ( existingHandles.length > handleCount ) {
12880     existingHandles.slice( handleCount ).remove();
12881     existingHandles = existingHandles.slice( 0, handleCount );
12882     }
12883    
12884     for ( i = existingHandles.length; i < handleCount; i++ ) {
12885     handles.push( handle );
12886     }
12887    
12888     this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( this.element ) );
12889    
12890     this.handle = this.handles.eq( 0 );
12891    
12892     this.handles.each(function( i ) {
12893     $( this ).data( "ui-slider-handle-index", i );
12894     });
12895     },
12896    
12897     _createRange: function() {
12898     var options = this.options,
12899     classes = "";
12900    
12901     if ( options.range ) {
12902     if ( options.range === true ) {
12903     if ( !options.values ) {
12904     options.values = [ this._valueMin(), this._valueMin() ];
12905     } else if ( options.values.length && options.values.length !== 2 ) {
12906     options.values = [ options.values[0], options.values[0] ];
12907     } else if ( $.isArray( options.values ) ) {
12908     options.values = options.values.slice(0);
12909     }
12910     }
12911    
12912     if ( !this.range || !this.range.length ) {
12913     this.range = $( "<div></div>" )
12914     .appendTo( this.element );
12915    
12916     classes = "ui-slider-range" +
12917     // note: this isn't the most fittingly semantic framework class for this element,
12918     // but worked best visually with a variety of themes
12919     " ui-widget-header ui-corner-all";
12920     } else {
12921     this.range.removeClass( "ui-slider-range-min ui-slider-range-max" )
12922     // Handle range switching from true to min/max
12923     .css({
12924     "left": "",
12925     "bottom": ""
12926     });
12927     }
12928    
12929     this.range.addClass( classes +
12930     ( ( options.range === "min" || options.range === "max" ) ? " ui-slider-range-" + options.range : "" ) );
12931     } else {
12932     if ( this.range ) {
12933     this.range.remove();
12934     }
12935     this.range = null;
12936     }
12937     },
12938    
12939     _setupEvents: function() {
12940     this._off( this.handles );
12941     this._on( this.handles, this._handleEvents );
12942     this._hoverable( this.handles );
12943     this._focusable( this.handles );
12944     },
12945    
12946     _destroy: function() {
12947     this.handles.remove();
12948     if ( this.range ) {
12949     this.range.remove();
12950     }
12951    
12952     this.element
12953     .removeClass( "ui-slider" +
12954     " ui-slider-horizontal" +
12955     " ui-slider-vertical" +
12956     " ui-widget" +
12957     " ui-widget-content" +
12958     " ui-corner-all" );
12959    
12960     this._mouseDestroy();
12961     },
12962    
12963     _mouseCapture: function( event ) {
12964     var position, normValue, distance, closestHandle, index, allowed, offset, mouseOverHandle,
12965     that = this,
12966     o = this.options;
12967    
12968     if ( o.disabled ) {
12969     return false;
12970     }
12971    
12972     this.elementSize = {
12973     width: this.element.outerWidth(),
12974     height: this.element.outerHeight()
12975     };
12976     this.elementOffset = this.element.offset();
12977    
12978     position = { x: event.pageX, y: event.pageY };
12979     normValue = this._normValueFromMouse( position );
12980     distance = this._valueMax() - this._valueMin() + 1;
12981     this.handles.each(function( i ) {
12982     var thisDistance = Math.abs( normValue - that.values(i) );
12983     if (( distance > thisDistance ) ||
12984     ( distance === thisDistance &&
12985     (i === that._lastChangedValue || that.values(i) === o.min ))) {
12986     distance = thisDistance;
12987     closestHandle = $( this );
12988     index = i;
12989     }
12990     });
12991    
12992     allowed = this._start( event, index );
12993     if ( allowed === false ) {
12994     return false;
12995     }
12996     this._mouseSliding = true;
12997    
12998     this._handleIndex = index;
12999    
13000     closestHandle
13001     .addClass( "ui-state-active" )
13002     .focus();
13003    
13004     offset = closestHandle.offset();
13005     mouseOverHandle = !$( event.target ).parents().addBack().is( ".ui-slider-handle" );
13006     this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
13007     left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
13008     top: event.pageY - offset.top -
13009     ( closestHandle.height() / 2 ) -
13010     ( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) -
13011     ( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) +
13012     ( parseInt( closestHandle.css("marginTop"), 10 ) || 0)
13013     };
13014    
13015     if ( !this.handles.hasClass( "ui-state-hover" ) ) {
13016     this._slide( event, index, normValue );
13017     }
13018     this._animateOff = true;
13019     return true;
13020     },
13021    
13022     _mouseStart: function() {
13023     return true;
13024     },
13025    
13026     _mouseDrag: function( event ) {
13027     var position = { x: event.pageX, y: event.pageY },
13028     normValue = this._normValueFromMouse( position );
13029    
13030     this._slide( event, this._handleIndex, normValue );
13031    
13032     return false;
13033     },
13034    
13035     _mouseStop: function( event ) {
13036     this.handles.removeClass( "ui-state-active" );
13037     this._mouseSliding = false;
13038    
13039     this._stop( event, this._handleIndex );
13040     this._change( event, this._handleIndex );
13041    
13042     this._handleIndex = null;
13043     this._clickOffset = null;
13044     this._animateOff = false;
13045    
13046     return false;
13047     },
13048    
13049     _detectOrientation: function() {
13050     this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
13051     },
13052    
13053     _normValueFromMouse: function( position ) {
13054     var pixelTotal,
13055     pixelMouse,
13056     percentMouse,
13057     valueTotal,
13058     valueMouse;
13059    
13060     if ( this.orientation === "horizontal" ) {
13061     pixelTotal = this.elementSize.width;
13062     pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 );
13063     } else {
13064     pixelTotal = this.elementSize.height;
13065     pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 );
13066     }
13067    
13068     percentMouse = ( pixelMouse / pixelTotal );
13069     if ( percentMouse > 1 ) {
13070     percentMouse = 1;
13071     }
13072     if ( percentMouse < 0 ) {
13073     percentMouse = 0;
13074     }
13075     if ( this.orientation === "vertical" ) {
13076     percentMouse = 1 - percentMouse;
13077     }
13078    
13079     valueTotal = this._valueMax() - this._valueMin();
13080     valueMouse = this._valueMin() + percentMouse * valueTotal;
13081    
13082     return this._trimAlignValue( valueMouse );
13083     },
13084    
13085     _start: function( event, index ) {
13086     var uiHash = {
13087     handle: this.handles[ index ],
13088     value: this.value()
13089     };
13090     if ( this.options.values && this.options.values.length ) {
13091     uiHash.value = this.values( index );
13092     uiHash.values = this.values();
13093     }
13094     return this._trigger( "start", event, uiHash );
13095     },
13096    
13097     _slide: function( event, index, newVal ) {
13098     var otherVal,
13099     newValues,
13100     allowed;
13101    
13102     if ( this.options.values && this.options.values.length ) {
13103     otherVal = this.values( index ? 0 : 1 );
13104    
13105     if ( ( this.options.values.length === 2 && this.options.range === true ) &&
13106     ( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) )
13107     ) {
13108     newVal = otherVal;
13109     }
13110    
13111     if ( newVal !== this.values( index ) ) {
13112     newValues = this.values();
13113     newValues[ index ] = newVal;
13114     // A slide can be canceled by returning false from the slide callback
13115     allowed = this._trigger( "slide", event, {
13116     handle: this.handles[ index ],
13117     value: newVal,
13118     values: newValues
13119     } );
13120     otherVal = this.values( index ? 0 : 1 );
13121     if ( allowed !== false ) {
13122     this.values( index, newVal );
13123     }
13124     }
13125     } else {
13126     if ( newVal !== this.value() ) {
13127     // A slide can be canceled by returning false from the slide callback
13128     allowed = this._trigger( "slide", event, {
13129     handle: this.handles[ index ],
13130     value: newVal
13131     } );
13132     if ( allowed !== false ) {
13133     this.value( newVal );
13134     }
13135     }
13136     }
13137     },
13138    
13139     _stop: function( event, index ) {
13140     var uiHash = {
13141     handle: this.handles[ index ],
13142     value: this.value()
13143     };
13144     if ( this.options.values && this.options.values.length ) {
13145     uiHash.value = this.values( index );
13146     uiHash.values = this.values();
13147     }
13148    
13149     this._trigger( "stop", event, uiHash );
13150     },
13151    
13152     _change: function( event, index ) {
13153     if ( !this._keySliding && !this._mouseSliding ) {
13154     var uiHash = {
13155     handle: this.handles[ index ],
13156     value: this.value()
13157     };
13158     if ( this.options.values && this.options.values.length ) {
13159     uiHash.value = this.values( index );
13160     uiHash.values = this.values();
13161     }
13162    
13163     //store the last changed value index for reference when handles overlap
13164     this._lastChangedValue = index;
13165    
13166     this._trigger( "change", event, uiHash );
13167     }
13168     },
13169    
13170     value: function( newValue ) {
13171     if ( arguments.length ) {
13172     this.options.value = this._trimAlignValue( newValue );
13173     this._refreshValue();
13174     this._change( null, 0 );
13175     return;
13176     }
13177    
13178     return this._value();
13179     },
13180    
13181     values: function( index, newValue ) {
13182     var vals,
13183     newValues,
13184     i;
13185    
13186     if ( arguments.length > 1 ) {
13187     this.options.values[ index ] = this._trimAlignValue( newValue );
13188     this._refreshValue();
13189     this._change( null, index );
13190     return;
13191     }
13192    
13193     if ( arguments.length ) {
13194     if ( $.isArray( arguments[ 0 ] ) ) {
13195     vals = this.options.values;
13196     newValues = arguments[ 0 ];
13197     for ( i = 0; i < vals.length; i += 1 ) {
13198     vals[ i ] = this._trimAlignValue( newValues[ i ] );
13199     this._change( null, i );
13200     }
13201     this._refreshValue();
13202     } else {
13203     if ( this.options.values && this.options.values.length ) {
13204     return this._values( index );
13205     } else {
13206     return this.value();
13207     }
13208     }
13209     } else {
13210     return this._values();
13211     }
13212     },
13213    
13214     _setOption: function( key, value ) {
13215     var i,
13216     valsLength = 0;
13217    
13218     if ( key === "range" && this.options.range === true ) {
13219     if ( value === "min" ) {
13220     this.options.value = this._values( 0 );
13221     this.options.values = null;
13222     } else if ( value === "max" ) {
13223     this.options.value = this._values( this.options.values.length - 1 );
13224     this.options.values = null;
13225     }
13226     }
13227    
13228     if ( $.isArray( this.options.values ) ) {
13229     valsLength = this.options.values.length;
13230     }
13231    
13232     if ( key === "disabled" ) {
13233     this.element.toggleClass( "ui-state-disabled", !!value );
13234     }
13235    
13236     this._super( key, value );
13237    
13238     switch ( key ) {
13239     case "orientation":
13240     this._detectOrientation();
13241     this.element
13242     .removeClass( "ui-slider-horizontal ui-slider-vertical" )
13243     .addClass( "ui-slider-" + this.orientation );
13244     this._refreshValue();
13245    
13246     // Reset positioning from previous orientation
13247     this.handles.css( value === "horizontal" ? "bottom" : "left", "" );
13248     break;
13249     case "value":
13250     this._animateOff = true;
13251     this._refreshValue();
13252     this._change( null, 0 );
13253     this._animateOff = false;
13254     break;
13255     case "values":
13256     this._animateOff = true;
13257     this._refreshValue();
13258     for ( i = 0; i < valsLength; i += 1 ) {
13259     this._change( null, i );
13260     }
13261     this._animateOff = false;
13262     break;
13263     case "step":
13264     case "min":
13265     case "max":
13266     this._animateOff = true;
13267     this._calculateNewMax();
13268     this._refreshValue();
13269     this._animateOff = false;
13270     break;
13271     case "range":
13272     this._animateOff = true;
13273     this._refresh();
13274     this._animateOff = false;
13275     break;
13276     }
13277     },
13278    
13279     //internal value getter
13280     // _value() returns value trimmed by min and max, aligned by step
13281     _value: function() {
13282     var val = this.options.value;
13283     val = this._trimAlignValue( val );
13284    
13285     return val;
13286     },
13287    
13288     //internal values getter
13289     // _values() returns array of values trimmed by min and max, aligned by step
13290     // _values( index ) returns single value trimmed by min and max, aligned by step
13291     _values: function( index ) {
13292     var val,
13293     vals,
13294     i;
13295    
13296     if ( arguments.length ) {
13297     val = this.options.values[ index ];
13298     val = this._trimAlignValue( val );
13299    
13300     return val;
13301     } else if ( this.options.values && this.options.values.length ) {
13302     // .slice() creates a copy of the array
13303     // this copy gets trimmed by min and max and then returned
13304     vals = this.options.values.slice();
13305     for ( i = 0; i < vals.length; i += 1) {
13306     vals[ i ] = this._trimAlignValue( vals[ i ] );
13307     }
13308    
13309     return vals;
13310     } else {
13311     return [];
13312     }
13313     },
13314    
13315     // returns the step-aligned value that val is closest to, between (inclusive) min and max
13316     _trimAlignValue: function( val ) {
13317     if ( val <= this._valueMin() ) {
13318     return this._valueMin();
13319     }
13320     if ( val >= this._valueMax() ) {
13321     return this._valueMax();
13322     }
13323     var step = ( this.options.step > 0 ) ? this.options.step : 1,
13324     valModStep = (val - this._valueMin()) % step,
13325     alignValue = val - valModStep;
13326    
13327     if ( Math.abs(valModStep) * 2 >= step ) {
13328     alignValue += ( valModStep > 0 ) ? step : ( -step );
13329     }
13330    
13331     // Since JavaScript has problems with large floats, round
13332     // the final value to 5 digits after the decimal point (see #4124)
13333     return parseFloat( alignValue.toFixed(5) );
13334     },
13335    
13336     _calculateNewMax: function() {
13337     var max = this.options.max,
13338     min = this._valueMin(),
13339     step = this.options.step,
13340     aboveMin = Math.floor( ( +( max - min ).toFixed( this._precision() ) ) / step ) * step;
13341     max = aboveMin + min;
13342     this.max = parseFloat( max.toFixed( this._precision() ) );
13343     },
13344    
13345     _precision: function() {
13346     var precision = this._precisionOf( this.options.step );
13347     if ( this.options.min !== null ) {
13348     precision = Math.max( precision, this._precisionOf( this.options.min ) );
13349     }
13350     return precision;
13351     },
13352    
13353     _precisionOf: function( num ) {
13354     var str = num.toString(),
13355     decimal = str.indexOf( "." );
13356     return decimal === -1 ? 0 : str.length - decimal - 1;
13357     },
13358    
13359     _valueMin: function() {
13360     return this.options.min;
13361     },
13362    
13363     _valueMax: function() {
13364     return this.max;
13365     },
13366    
13367     _refreshValue: function() {
13368     var lastValPercent, valPercent, value, valueMin, valueMax,
13369     oRange = this.options.range,
13370     o = this.options,
13371     that = this,
13372     animate = ( !this._animateOff ) ? o.animate : false,
13373     _set = {};
13374    
13375     if ( this.options.values && this.options.values.length ) {
13376     this.handles.each(function( i ) {
13377     valPercent = ( that.values(i) - that._valueMin() ) / ( that._valueMax() - that._valueMin() ) * 100;
13378     _set[ that.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
13379     $( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
13380     if ( that.options.range === true ) {
13381     if ( that.orientation === "horizontal" ) {
13382     if ( i === 0 ) {
13383     that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate );
13384     }
13385     if ( i === 1 ) {
13386     that.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
13387     }
13388     } else {
13389     if ( i === 0 ) {
13390     that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate );
13391     }
13392     if ( i === 1 ) {
13393     that.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
13394     }
13395     }
13396     }
13397     lastValPercent = valPercent;
13398     });
13399     } else {
13400     value = this.value();
13401     valueMin = this._valueMin();
13402     valueMax = this._valueMax();
13403     valPercent = ( valueMax !== valueMin ) ?
13404     ( value - valueMin ) / ( valueMax - valueMin ) * 100 :
13405     0;
13406     _set[ this.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
13407     this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
13408    
13409     if ( oRange === "min" && this.orientation === "horizontal" ) {
13410     this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate );
13411     }
13412     if ( oRange === "max" && this.orientation === "horizontal" ) {
13413     this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
13414     }
13415     if ( oRange === "min" && this.orientation === "vertical" ) {
13416     this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate );
13417     }
13418     if ( oRange === "max" && this.orientation === "vertical" ) {
13419     this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
13420     }
13421     }
13422     },
13423    
13424     _handleEvents: {
13425     keydown: function( event ) {
13426     var allowed, curVal, newVal, step,
13427     index = $( event.target ).data( "ui-slider-handle-index" );
13428    
13429     switch ( event.keyCode ) {
13430     case $.ui.keyCode.HOME:
13431     case $.ui.keyCode.END:
13432     case $.ui.keyCode.PAGE_UP:
13433     case $.ui.keyCode.PAGE_DOWN:
13434     case $.ui.keyCode.UP:
13435     case $.ui.keyCode.RIGHT:
13436     case $.ui.keyCode.DOWN:
13437     case $.ui.keyCode.LEFT:
13438     event.preventDefault();
13439     if ( !this._keySliding ) {
13440     this._keySliding = true;
13441     $( event.target ).addClass( "ui-state-active" );
13442     allowed = this._start( event, index );
13443     if ( allowed === false ) {
13444     return;
13445     }
13446     }
13447     break;
13448     }
13449    
13450     step = this.options.step;
13451     if ( this.options.values && this.options.values.length ) {
13452     curVal = newVal = this.values( index );
13453     } else {
13454     curVal = newVal = this.value();
13455     }
13456    
13457     switch ( event.keyCode ) {
13458     case $.ui.keyCode.HOME:
13459     newVal = this._valueMin();
13460     break;
13461     case $.ui.keyCode.END:
13462     newVal = this._valueMax();
13463     break;
13464     case $.ui.keyCode.PAGE_UP:
13465     newVal = this._trimAlignValue(
13466     curVal + ( ( this._valueMax() - this._valueMin() ) / this.numPages )
13467     );
13468     break;
13469     case $.ui.keyCode.PAGE_DOWN:
13470     newVal = this._trimAlignValue(
13471     curVal - ( (this._valueMax() - this._valueMin()) / this.numPages ) );
13472     break;
13473     case $.ui.keyCode.UP:
13474     case $.ui.keyCode.RIGHT:
13475     if ( curVal === this._valueMax() ) {
13476     return;
13477     }
13478     newVal = this._trimAlignValue( curVal + step );
13479     break;
13480     case $.ui.keyCode.DOWN:
13481     case $.ui.keyCode.LEFT:
13482     if ( curVal === this._valueMin() ) {
13483     return;
13484     }
13485     newVal = this._trimAlignValue( curVal - step );
13486     break;
13487     }
13488    
13489     this._slide( event, index, newVal );
13490     },
13491     keyup: function( event ) {
13492     var index = $( event.target ).data( "ui-slider-handle-index" );
13493    
13494     if ( this._keySliding ) {
13495     this._keySliding = false;
13496     this._stop( event, index );
13497     this._change( event, index );
13498     $( event.target ).removeClass( "ui-state-active" );
13499     }
13500     }
13501     }
13502     });
13503    
13504    
13505     /*!
13506     * jQuery UI Sortable 1.11.4
13507     * http://jqueryui.com
13508     *
13509     * Copyright jQuery Foundation and other contributors
13510     * Released under the MIT license.
13511     * http://jquery.org/license
13512     *
13513     * http://api.jqueryui.com/sortable/
13514     */
13515    
13516    
13517     var sortable = $.widget("ui.sortable", $.ui.mouse, {
13518     version: "1.11.4",
13519     widgetEventPrefix: "sort",
13520     ready: false,
13521     options: {
13522     appendTo: "parent",
13523     axis: false,
13524     connectWith: false,
13525     containment: false,
13526     cursor: "auto",
13527     cursorAt: false,
13528     dropOnEmpty: true,
13529     forcePlaceholderSize: false,
13530     forceHelperSize: false,
13531     grid: false,
13532     handle: false,
13533     helper: "original",
13534     items: "> *",
13535     opacity: false,
13536     placeholder: false,
13537     revert: false,
13538     scroll: true,
13539     scrollSensitivity: 20,
13540     scrollSpeed: 20,
13541     scope: "default",
13542     tolerance: "intersect",
13543     zIndex: 1000,
13544    
13545     // callbacks
13546     activate: null,
13547     beforeStop: null,
13548     change: null,
13549     deactivate: null,
13550     out: null,
13551     over: null,
13552     receive: null,
13553     remove: null,
13554     sort: null,
13555     start: null,
13556     stop: null,
13557     update: null
13558     },
13559    
13560     _isOverAxis: function( x, reference, size ) {
13561     return ( x >= reference ) && ( x < ( reference + size ) );
13562     },
13563    
13564     _isFloating: function( item ) {
13565     return (/left|right/).test(item.css("float")) || (/inline|table-cell/).test(item.css("display"));
13566     },
13567    
13568     _create: function() {
13569     this.containerCache = {};
13570     this.element.addClass("ui-sortable");
13571    
13572     //Get the items
13573     this.refresh();
13574    
13575     //Let's determine the parent's offset
13576     this.offset = this.element.offset();
13577    
13578     //Initialize mouse events for interaction
13579     this._mouseInit();
13580    
13581     this._setHandleClassName();
13582    
13583     //We're ready to go
13584     this.ready = true;
13585    
13586     },
13587    
13588     _setOption: function( key, value ) {
13589     this._super( key, value );
13590    
13591     if ( key === "handle" ) {
13592     this._setHandleClassName();
13593     }
13594     },
13595    
13596     _setHandleClassName: function() {
13597     this.element.find( ".ui-sortable-handle" ).removeClass( "ui-sortable-handle" );
13598     $.each( this.items, function() {
13599     ( this.instance.options.handle ?
13600     this.item.find( this.instance.options.handle ) : this.item )
13601     .addClass( "ui-sortable-handle" );
13602     });
13603     },
13604    
13605     _destroy: function() {
13606     this.element
13607     .removeClass( "ui-sortable ui-sortable-disabled" )
13608     .find( ".ui-sortable-handle" )
13609     .removeClass( "ui-sortable-handle" );
13610     this._mouseDestroy();
13611    
13612     for ( var i = this.items.length - 1; i >= 0; i-- ) {
13613     this.items[i].item.removeData(this.widgetName + "-item");
13614     }
13615    
13616     return this;
13617     },
13618    
13619     _mouseCapture: function(event, overrideHandle) {
13620     var currentItem = null,
13621     validHandle = false,
13622     that = this;
13623    
13624     if (this.reverting) {
13625     return false;
13626     }
13627    
13628     if(this.options.disabled || this.options.type === "static") {
13629     return false;
13630     }
13631    
13632     //We have to refresh the items data once first
13633     this._refreshItems(event);
13634    
13635     //Find out if the clicked node (or one of its parents) is a actual item in this.items
13636     $(event.target).parents().each(function() {
13637     if($.data(this, that.widgetName + "-item") === that) {
13638     currentItem = $(this);
13639     return false;
13640     }
13641     });
13642     if($.data(event.target, that.widgetName + "-item") === that) {
13643     currentItem = $(event.target);
13644     }
13645    
13646     if(!currentItem) {
13647     return false;
13648     }
13649     if(this.options.handle && !overrideHandle) {
13650     $(this.options.handle, currentItem).find("*").addBack().each(function() {
13651     if(this === event.target) {
13652     validHandle = true;
13653     }
13654     });
13655     if(!validHandle) {
13656     return false;
13657     }
13658     }
13659    
13660     this.currentItem = currentItem;
13661     this._removeCurrentsFromItems();
13662     return true;
13663    
13664     },
13665    
13666     _mouseStart: function(event, overrideHandle, noActivation) {
13667    
13668     var i, body,
13669     o = this.options;
13670    
13671     this.currentContainer = this;
13672    
13673     //We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture
13674     this.refreshPositions();
13675    
13676     //Create and append the visible helper
13677     this.helper = this._createHelper(event);
13678    
13679     //Cache the helper size
13680     this._cacheHelperProportions();
13681    
13682     /*
13683     * - Position generation -
13684     * This block generates everything position related - it's the core of draggables.
13685     */
13686    
13687     //Cache the margins of the original element
13688     this._cacheMargins();
13689    
13690     //Get the next scrolling parent
13691     this.scrollParent = this.helper.scrollParent();
13692    
13693     //The element's absolute position on the page minus margins
13694     this.offset = this.currentItem.offset();
13695     this.offset = {
13696     top: this.offset.top - this.margins.top,
13697     left: this.offset.left - this.margins.left
13698     };
13699    
13700     $.extend(this.offset, {
13701     click: { //Where the click happened, relative to the element
13702     left: event.pageX - this.offset.left,
13703     top: event.pageY - this.offset.top
13704     },
13705     parent: this._getParentOffset(),
13706     relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
13707     });
13708    
13709     // Only after we got the offset, we can change the helper's position to absolute
13710     // TODO: Still need to figure out a way to make relative sorting possible
13711     this.helper.css("position", "absolute");
13712     this.cssPosition = this.helper.css("position");
13713    
13714     //Generate the original position
13715     this.originalPosition = this._generatePosition(event);
13716     this.originalPageX = event.pageX;
13717     this.originalPageY = event.pageY;
13718    
13719     //Adjust the mouse offset relative to the helper if "cursorAt" is supplied
13720     (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
13721    
13722     //Cache the former DOM position
13723     this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] };
13724    
13725     //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
13726     if(this.helper[0] !== this.currentItem[0]) {
13727     this.currentItem.hide();
13728     }
13729    
13730     //Create the placeholder
13731     this._createPlaceholder();
13732    
13733     //Set a containment if given in the options
13734     if(o.containment) {
13735     this._setContainment();
13736     }
13737    
13738     if( o.cursor && o.cursor !== "auto" ) { // cursor option
13739     body = this.document.find( "body" );
13740    
13741     // support: IE
13742     this.storedCursor = body.css( "cursor" );
13743     body.css( "cursor", o.cursor );
13744    
13745     this.storedStylesheet = $( "<style>*{ cursor: "+o.cursor+" !important; }</style>" ).appendTo( body );
13746     }
13747    
13748     if(o.opacity) { // opacity option
13749     if (this.helper.css("opacity")) {
13750     this._storedOpacity = this.helper.css("opacity");
13751     }
13752     this.helper.css("opacity", o.opacity);
13753     }
13754    
13755     if(o.zIndex) { // zIndex option
13756     if (this.helper.css("zIndex")) {
13757     this._storedZIndex = this.helper.css("zIndex");
13758     }
13759     this.helper.css("zIndex", o.zIndex);
13760     }
13761    
13762     //Prepare scrolling
13763     if(this.scrollParent[0] !== this.document[0] && this.scrollParent[0].tagName !== "HTML") {
13764     this.overflowOffset = this.scrollParent.offset();
13765     }
13766    
13767     //Call callbacks
13768     this._trigger("start", event, this._uiHash());
13769    
13770     //Recache the helper size
13771     if(!this._preserveHelperProportions) {
13772     this._cacheHelperProportions();
13773     }
13774    
13775    
13776     //Post "activate" events to possible containers
13777     if( !noActivation ) {
13778     for ( i = this.containers.length - 1; i >= 0; i-- ) {
13779     this.containers[ i ]._trigger( "activate", event, this._uiHash( this ) );
13780     }
13781     }
13782    
13783     //Prepare possible droppables
13784     if($.ui.ddmanager) {
13785     $.ui.ddmanager.current = this;
13786     }
13787    
13788     if ($.ui.ddmanager && !o.dropBehaviour) {
13789     $.ui.ddmanager.prepareOffsets(this, event);
13790     }
13791    
13792     this.dragging = true;
13793    
13794     this.helper.addClass("ui-sortable-helper");
13795     this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position
13796     return true;
13797    
13798     },
13799    
13800     _mouseDrag: function(event) {
13801     var i, item, itemElement, intersection,
13802     o = this.options,
13803     scrolled = false;
13804    
13805     //Compute the helpers position
13806     this.position = this._generatePosition(event);
13807     this.positionAbs = this._convertPositionTo("absolute");
13808    
13809     if (!this.lastPositionAbs) {
13810     this.lastPositionAbs = this.positionAbs;
13811     }
13812    
13813     //Do scrolling
13814     if(this.options.scroll) {
13815     if(this.scrollParent[0] !== this.document[0] && this.scrollParent[0].tagName !== "HTML") {
13816    
13817     if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) {
13818     this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed;
13819     } else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity) {
13820     this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed;
13821     }
13822    
13823     if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) {
13824     this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed;
13825     } else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity) {
13826     this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed;
13827     }
13828    
13829     } else {
13830    
13831     if(event.pageY - this.document.scrollTop() < o.scrollSensitivity) {
13832     scrolled = this.document.scrollTop(this.document.scrollTop() - o.scrollSpeed);
13833     } else if(this.window.height() - (event.pageY - this.document.scrollTop()) < o.scrollSensitivity) {
13834     scrolled = this.document.scrollTop(this.document.scrollTop() + o.scrollSpeed);
13835     }
13836    
13837     if(event.pageX - this.document.scrollLeft() < o.scrollSensitivity) {
13838     scrolled = this.document.scrollLeft(this.document.scrollLeft() - o.scrollSpeed);
13839     } else if(this.window.width() - (event.pageX - this.document.scrollLeft()) < o.scrollSensitivity) {
13840     scrolled = this.document.scrollLeft(this.document.scrollLeft() + o.scrollSpeed);
13841     }
13842    
13843     }
13844    
13845     if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) {
13846     $.ui.ddmanager.prepareOffsets(this, event);
13847     }
13848     }
13849    
13850     //Regenerate the absolute position used for position checks
13851     this.positionAbs = this._convertPositionTo("absolute");
13852    
13853     //Set the helper position
13854     if(!this.options.axis || this.options.axis !== "y") {
13855     this.helper[0].style.left = this.position.left+"px";
13856     }
13857     if(!this.options.axis || this.options.axis !== "x") {
13858     this.helper[0].style.top = this.position.top+"px";
13859     }
13860    
13861     //Rearrange
13862     for (i = this.items.length - 1; i >= 0; i--) {
13863    
13864     //Cache variables and intersection, continue if no intersection
13865     item = this.items[i];
13866     itemElement = item.item[0];
13867     intersection = this._intersectsWithPointer(item);
13868     if (!intersection) {
13869     continue;
13870     }
13871    
13872     // Only put the placeholder inside the current Container, skip all
13873     // items from other containers. This works because when moving
13874     // an item from one container to another the
13875     // currentContainer is switched before the placeholder is moved.
13876     //
13877     // Without this, moving items in "sub-sortables" can cause
13878     // the placeholder to jitter between the outer and inner container.
13879     if (item.instance !== this.currentContainer) {
13880     continue;
13881     }
13882    
13883     // cannot intersect with itself
13884     // no useless actions that have been done before
13885     // no action if the item moved is the parent of the item checked
13886     if (itemElement !== this.currentItem[0] &&
13887     this.placeholder[intersection === 1 ? "next" : "prev"]()[0] !== itemElement &&
13888     !$.contains(this.placeholder[0], itemElement) &&
13889     (this.options.type === "semi-dynamic" ? !$.contains(this.element[0], itemElement) : true)
13890     ) {
13891    
13892     this.direction = intersection === 1 ? "down" : "up";
13893    
13894     if (this.options.tolerance === "pointer" || this._intersectsWithSides(item)) {
13895     this._rearrange(event, item);
13896     } else {
13897     break;
13898     }
13899    
13900     this._trigger("change", event, this._uiHash());
13901     break;
13902     }
13903     }
13904    
13905     //Post events to containers
13906     this._contactContainers(event);
13907    
13908     //Interconnect with droppables
13909     if($.ui.ddmanager) {
13910     $.ui.ddmanager.drag(this, event);
13911     }
13912    
13913     //Call callbacks
13914     this._trigger("sort", event, this._uiHash());
13915    
13916     this.lastPositionAbs = this.positionAbs;
13917     return false;
13918    
13919     },
13920    
13921     _mouseStop: function(event, noPropagation) {
13922    
13923     if(!event) {
13924     return;
13925     }
13926    
13927     //If we are using droppables, inform the manager about the drop
13928     if ($.ui.ddmanager && !this.options.dropBehaviour) {
13929     $.ui.ddmanager.drop(this, event);
13930     }
13931    
13932     if(this.options.revert) {
13933     var that = this,
13934     cur = this.placeholder.offset(),
13935     axis = this.options.axis,
13936     animation = {};
13937    
13938     if ( !axis || axis === "x" ) {
13939     animation.left = cur.left - this.offset.parent.left - this.margins.left + (this.offsetParent[0] === this.document[0].body ? 0 : this.offsetParent[0].scrollLeft);
13940     }
13941     if ( !axis || axis === "y" ) {
13942     animation.top = cur.top - this.offset.parent.top - this.margins.top + (this.offsetParent[0] === this.document[0].body ? 0 : this.offsetParent[0].scrollTop);
13943     }
13944     this.reverting = true;
13945     $(this.helper).animate( animation, parseInt(this.options.revert, 10) || 500, function() {
13946     that._clear(event);
13947     });
13948     } else {
13949     this._clear(event, noPropagation);
13950     }
13951    
13952     return false;
13953    
13954     },
13955    
13956     cancel: function() {
13957    
13958     if(this.dragging) {
13959    
13960     this._mouseUp({ target: null });
13961    
13962     if(this.options.helper === "original") {
13963     this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
13964     } else {
13965     this.currentItem.show();
13966     }
13967    
13968     //Post deactivating events to containers
13969     for (var i = this.containers.length - 1; i >= 0; i--){
13970     this.containers[i]._trigger("deactivate", null, this._uiHash(this));
13971     if(this.containers[i].containerCache.over) {
13972     this.containers[i]._trigger("out", null, this._uiHash(this));
13973     this.containers[i].containerCache.over = 0;
13974     }
13975     }
13976    
13977     }
13978    
13979     if (this.placeholder) {
13980     //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
13981     if(this.placeholder[0].parentNode) {
13982     this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
13983     }
13984     if(this.options.helper !== "original" && this.helper && this.helper[0].parentNode) {
13985     this.helper.remove();
13986     }
13987    
13988     $.extend(this, {
13989     helper: null,
13990     dragging: false,
13991     reverting: false,
13992     _noFinalSort: null
13993     });
13994    
13995     if(this.domPosition.prev) {
13996     $(this.domPosition.prev).after(this.currentItem);
13997     } else {
13998     $(this.domPosition.parent).prepend(this.currentItem);
13999     }
14000     }
14001    
14002     return this;
14003    
14004     },
14005    
14006     serialize: function(o) {
14007    
14008     var items = this._getItemsAsjQuery(o && o.connected),
14009     str = [];
14010     o = o || {};
14011    
14012     $(items).each(function() {
14013     var res = ($(o.item || this).attr(o.attribute || "id") || "").match(o.expression || (/(.+)[\-=_](.+)/));
14014     if (res) {
14015     str.push((o.key || res[1]+"[]")+"="+(o.key && o.expression ? res[1] : res[2]));
14016     }
14017     });
14018    
14019     if(!str.length && o.key) {
14020     str.push(o.key + "=");
14021     }
14022    
14023     return str.join("&");
14024    
14025     },
14026    
14027     toArray: function(o) {
14028    
14029     var items = this._getItemsAsjQuery(o && o.connected),
14030     ret = [];
14031    
14032     o = o || {};
14033    
14034     items.each(function() { ret.push($(o.item || this).attr(o.attribute || "id") || ""); });
14035     return ret;
14036    
14037     },
14038    
14039     /* Be careful with the following core functions */
14040     _intersectsWith: function(item) {
14041    
14042     var x1 = this.positionAbs.left,
14043     x2 = x1 + this.helperProportions.width,
14044     y1 = this.positionAbs.top,
14045     y2 = y1 + this.helperProportions.height,
14046     l = item.left,
14047     r = l + item.width,
14048     t = item.top,
14049     b = t + item.height,
14050     dyClick = this.offset.click.top,
14051     dxClick = this.offset.click.left,
14052     isOverElementHeight = ( this.options.axis === "x" ) || ( ( y1 + dyClick ) > t && ( y1 + dyClick ) < b ),
14053     isOverElementWidth = ( this.options.axis === "y" ) || ( ( x1 + dxClick ) > l && ( x1 + dxClick ) < r ),
14054     isOverElement = isOverElementHeight && isOverElementWidth;
14055    
14056     if ( this.options.tolerance === "pointer" ||
14057     this.options.forcePointerForContainers ||
14058     (this.options.tolerance !== "pointer" && this.helperProportions[this.floating ? "width" : "height"] > item[this.floating ? "width" : "height"])
14059     ) {
14060     return isOverElement;
14061     } else {
14062    
14063     return (l < x1 + (this.helperProportions.width / 2) && // Right Half
14064     x2 - (this.helperProportions.width / 2) < r && // Left Half
14065     t < y1 + (this.helperProportions.height / 2) && // Bottom Half
14066     y2 - (this.helperProportions.height / 2) < b ); // Top Half
14067    
14068     }
14069     },
14070    
14071     _intersectsWithPointer: function(item) {
14072    
14073     var isOverElementHeight = (this.options.axis === "x") || this._isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height),
14074     isOverElementWidth = (this.options.axis === "y") || this._isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width),
14075     isOverElement = isOverElementHeight && isOverElementWidth,
14076     verticalDirection = this._getDragVerticalDirection(),
14077     horizontalDirection = this._getDragHorizontalDirection();
14078    
14079     if (!isOverElement) {
14080     return false;
14081     }
14082    
14083     return this.floating ?
14084     ( ((horizontalDirection && horizontalDirection === "right") || verticalDirection === "down") ? 2 : 1 )
14085     : ( verticalDirection && (verticalDirection === "down" ? 2 : 1) );
14086    
14087     },
14088    
14089     _intersectsWithSides: function(item) {
14090    
14091     var isOverBottomHalf = this._isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height),
14092     isOverRightHalf = this._isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width),
14093     verticalDirection = this._getDragVerticalDirection(),
14094     horizontalDirection = this._getDragHorizontalDirection();
14095    
14096     if (this.floating && horizontalDirection) {
14097     return ((horizontalDirection === "right" && isOverRightHalf) || (horizontalDirection === "left" && !isOverRightHalf));
14098     } else {
14099     return verticalDirection && ((verticalDirection === "down" && isOverBottomHalf) || (verticalDirection === "up" && !isOverBottomHalf));
14100     }
14101    
14102     },
14103    
14104     _getDragVerticalDirection: function() {
14105     var delta = this.positionAbs.top - this.lastPositionAbs.top;
14106     return delta !== 0 && (delta > 0 ? "down" : "up");
14107     },
14108    
14109     _getDragHorizontalDirection: function() {
14110     var delta = this.positionAbs.left - this.lastPositionAbs.left;
14111     return delta !== 0 && (delta > 0 ? "right" : "left");
14112     },
14113    
14114     refresh: function(event) {
14115     this._refreshItems(event);
14116     this._setHandleClassName();
14117     this.refreshPositions();
14118     return this;
14119     },
14120    
14121     _connectWith: function() {
14122     var options = this.options;
14123     return options.connectWith.constructor === String ? [options.connectWith] : options.connectWith;
14124     },
14125    
14126     _getItemsAsjQuery: function(connected) {
14127    
14128     var i, j, cur, inst,
14129     items = [],
14130     queries = [],
14131     connectWith = this._connectWith();
14132    
14133     if(connectWith && connected) {
14134     for (i = connectWith.length - 1; i >= 0; i--){
14135     cur = $(connectWith[i], this.document[0]);
14136     for ( j = cur.length - 1; j >= 0; j--){
14137     inst = $.data(cur[j], this.widgetFullName);
14138     if(inst && inst !== this && !inst.options.disabled) {
14139     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]);
14140     }
14141     }
14142     }
14143     }
14144    
14145     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]);
14146    
14147     function addItems() {
14148     items.push( this );
14149     }
14150     for (i = queries.length - 1; i >= 0; i--){
14151     queries[i][0].each( addItems );
14152     }
14153    
14154     return $(items);
14155    
14156     },
14157    
14158     _removeCurrentsFromItems: function() {
14159    
14160     var list = this.currentItem.find(":data(" + this.widgetName + "-item)");
14161    
14162     this.items = $.grep(this.items, function (item) {
14163     for (var j=0; j < list.length; j++) {
14164     if(list[j] === item.item[0]) {
14165     return false;
14166     }
14167     }
14168     return true;
14169     });
14170    
14171     },
14172    
14173     _refreshItems: function(event) {
14174    
14175     this.items = [];
14176     this.containers = [this];
14177    
14178     var i, j, cur, inst, targetData, _queries, item, queriesLength,
14179     items = this.items,
14180     queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]],
14181     connectWith = this._connectWith();
14182    
14183     if(connectWith && this.ready) { //Shouldn't be run the first time through due to massive slow-down
14184     for (i = connectWith.length - 1; i >= 0; i--){
14185     cur = $(connectWith[i], this.document[0]);
14186     for (j = cur.length - 1; j >= 0; j--){
14187     inst = $.data(cur[j], this.widgetFullName);
14188     if(inst && inst !== this && !inst.options.disabled) {
14189     queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]);
14190     this.containers.push(inst);
14191     }
14192     }
14193     }
14194     }
14195    
14196     for (i = queries.length - 1; i >= 0; i--) {
14197     targetData = queries[i][1];
14198     _queries = queries[i][0];
14199    
14200     for (j=0, queriesLength = _queries.length; j < queriesLength; j++) {
14201     item = $(_queries[j]);
14202    
14203     item.data(this.widgetName + "-item", targetData); // Data for target checking (mouse manager)
14204    
14205     items.push({
14206     item: item,
14207     instance: targetData,
14208     width: 0, height: 0,
14209     left: 0, top: 0
14210     });
14211     }
14212     }
14213    
14214     },
14215    
14216     refreshPositions: function(fast) {
14217    
14218     // Determine whether items are being displayed horizontally
14219     this.floating = this.items.length ?
14220     this.options.axis === "x" || this._isFloating( this.items[ 0 ].item ) :
14221     false;
14222    
14223     //This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change
14224     if(this.offsetParent && this.helper) {
14225     this.offset.parent = this._getParentOffset();
14226     }
14227    
14228     var i, item, t, p;
14229    
14230     for (i = this.items.length - 1; i >= 0; i--){
14231     item = this.items[i];
14232    
14233     //We ignore calculating positions of all connected containers when we're not over them
14234     if(item.instance !== this.currentContainer && this.currentContainer && item.item[0] !== this.currentItem[0]) {
14235     continue;
14236     }
14237    
14238     t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item;
14239    
14240     if (!fast) {
14241     item.width = t.outerWidth();
14242     item.height = t.outerHeight();
14243     }
14244    
14245     p = t.offset();
14246     item.left = p.left;
14247     item.top = p.top;
14248     }
14249    
14250     if(this.options.custom && this.options.custom.refreshContainers) {
14251     this.options.custom.refreshContainers.call(this);
14252     } else {
14253     for (i = this.containers.length - 1; i >= 0; i--){
14254     p = this.containers[i].element.offset();
14255     this.containers[i].containerCache.left = p.left;
14256     this.containers[i].containerCache.top = p.top;
14257     this.containers[i].containerCache.width = this.containers[i].element.outerWidth();
14258     this.containers[i].containerCache.height = this.containers[i].element.outerHeight();
14259     }
14260     }
14261    
14262     return this;
14263     },
14264    
14265     _createPlaceholder: function(that) {
14266     that = that || this;
14267     var className,
14268     o = that.options;
14269    
14270     if(!o.placeholder || o.placeholder.constructor === String) {
14271     className = o.placeholder;
14272     o.placeholder = {
14273     element: function() {
14274    
14275     var nodeName = that.currentItem[0].nodeName.toLowerCase(),
14276     element = $( "<" + nodeName + ">", that.document[0] )
14277     .addClass(className || that.currentItem[0].className+" ui-sortable-placeholder")
14278     .removeClass("ui-sortable-helper");
14279    
14280     if ( nodeName === "tbody" ) {
14281     that._createTrPlaceholder(
14282     that.currentItem.find( "tr" ).eq( 0 ),
14283     $( "<tr>", that.document[ 0 ] ).appendTo( element )
14284     );
14285     } else if ( nodeName === "tr" ) {
14286     that._createTrPlaceholder( that.currentItem, element );
14287     } else if ( nodeName === "img" ) {
14288     element.attr( "src", that.currentItem.attr( "src" ) );
14289     }
14290    
14291     if ( !className ) {
14292     element.css( "visibility", "hidden" );
14293     }
14294    
14295     return element;
14296     },
14297     update: function(container, p) {
14298    
14299     // 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that
14300     // 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified
14301     if(className && !o.forcePlaceholderSize) {
14302     return;
14303     }
14304    
14305     //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
14306     if(!p.height()) { p.height(that.currentItem.innerHeight() - parseInt(that.currentItem.css("paddingTop")||0, 10) - parseInt(that.currentItem.css("paddingBottom")||0, 10)); }
14307     if(!p.width()) { p.width(that.currentItem.innerWidth() - parseInt(that.currentItem.css("paddingLeft")||0, 10) - parseInt(that.currentItem.css("paddingRight")||0, 10)); }
14308     }
14309     };
14310     }
14311    
14312     //Create the placeholder
14313     that.placeholder = $(o.placeholder.element.call(that.element, that.currentItem));
14314    
14315     //Append it after the actual current item
14316     that.currentItem.after(that.placeholder);
14317    
14318     //Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
14319     o.placeholder.update(that, that.placeholder);
14320    
14321     },
14322    
14323     _createTrPlaceholder: function( sourceTr, targetTr ) {
14324     var that = this;
14325    
14326     sourceTr.children().each(function() {
14327     $( "<td>&#160;</td>", that.document[ 0 ] )
14328     .attr( "colspan", $( this ).attr( "colspan" ) || 1 )
14329     .appendTo( targetTr );
14330     });
14331     },
14332    
14333     _contactContainers: function(event) {
14334     var i, j, dist, itemWithLeastDistance, posProperty, sizeProperty, cur, nearBottom, floating, axis,
14335     innermostContainer = null,
14336     innermostIndex = null;
14337    
14338     // get innermost container that intersects with item
14339     for (i = this.containers.length - 1; i >= 0; i--) {
14340    
14341     // never consider a container that's located within the item itself
14342     if($.contains(this.currentItem[0], this.containers[i].element[0])) {
14343     continue;
14344     }
14345    
14346     if(this._intersectsWith(this.containers[i].containerCache)) {
14347    
14348     // if we've already found a container and it's more "inner" than this, then continue
14349     if(innermostContainer && $.contains(this.containers[i].element[0], innermostContainer.element[0])) {
14350     continue;
14351     }
14352    
14353     innermostContainer = this.containers[i];
14354     innermostIndex = i;
14355    
14356     } else {
14357     // container doesn't intersect. trigger "out" event if necessary
14358     if(this.containers[i].containerCache.over) {
14359     this.containers[i]._trigger("out", event, this._uiHash(this));
14360     this.containers[i].containerCache.over = 0;
14361     }
14362     }
14363    
14364     }
14365    
14366     // if no intersecting containers found, return
14367     if(!innermostContainer) {
14368     return;
14369     }
14370    
14371     // move the item into the container if it's not there already
14372     if(this.containers.length === 1) {
14373     if (!this.containers[innermostIndex].containerCache.over) {
14374     this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
14375     this.containers[innermostIndex].containerCache.over = 1;
14376     }
14377     } else {
14378    
14379     //When entering a new container, we will find the item with the least distance and append our item near it
14380     dist = 10000;
14381     itemWithLeastDistance = null;
14382     floating = innermostContainer.floating || this._isFloating(this.currentItem);
14383     posProperty = floating ? "left" : "top";
14384     sizeProperty = floating ? "width" : "height";
14385     axis = floating ? "clientX" : "clientY";
14386    
14387     for (j = this.items.length - 1; j >= 0; j--) {
14388     if(!$.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) {
14389     continue;
14390     }
14391     if(this.items[j].item[0] === this.currentItem[0]) {
14392     continue;
14393     }
14394    
14395     cur = this.items[j].item.offset()[posProperty];
14396     nearBottom = false;
14397     if ( event[ axis ] - cur > this.items[ j ][ sizeProperty ] / 2 ) {
14398     nearBottom = true;
14399     }
14400    
14401     if ( Math.abs( event[ axis ] - cur ) < dist ) {
14402     dist = Math.abs( event[ axis ] - cur );
14403     itemWithLeastDistance = this.items[ j ];
14404     this.direction = nearBottom ? "up": "down";
14405     }
14406     }
14407    
14408     //Check if dropOnEmpty is enabled
14409     if(!itemWithLeastDistance && !this.options.dropOnEmpty) {
14410     return;
14411     }
14412    
14413     if(this.currentContainer === this.containers[innermostIndex]) {
14414     if ( !this.currentContainer.containerCache.over ) {
14415     this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash() );
14416     this.currentContainer.containerCache.over = 1;
14417     }
14418     return;
14419     }
14420    
14421     itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true);
14422     this._trigger("change", event, this._uiHash());
14423     this.containers[innermostIndex]._trigger("change", event, this._uiHash(this));
14424     this.currentContainer = this.containers[innermostIndex];
14425    
14426     //Update the placeholder
14427     this.options.placeholder.update(this.currentContainer, this.placeholder);
14428    
14429     this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
14430     this.containers[innermostIndex].containerCache.over = 1;
14431     }
14432    
14433    
14434     },
14435    
14436     _createHelper: function(event) {
14437    
14438     var o = this.options,
14439     helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper === "clone" ? this.currentItem.clone() : this.currentItem);
14440    
14441     //Add the helper to the DOM if that didn't happen already
14442     if(!helper.parents("body").length) {
14443     $(o.appendTo !== "parent" ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]);
14444     }
14445    
14446     if(helper[0] === this.currentItem[0]) {
14447     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") };
14448     }
14449    
14450     if(!helper[0].style.width || o.forceHelperSize) {
14451     helper.width(this.currentItem.width());
14452     }
14453     if(!helper[0].style.height || o.forceHelperSize) {
14454     helper.height(this.currentItem.height());
14455     }
14456    
14457     return helper;
14458    
14459     },
14460    
14461     _adjustOffsetFromHelper: function(obj) {
14462     if (typeof obj === "string") {
14463     obj = obj.split(" ");
14464     }
14465     if ($.isArray(obj)) {
14466     obj = {left: +obj[0], top: +obj[1] || 0};
14467     }
14468     if ("left" in obj) {
14469     this.offset.click.left = obj.left + this.margins.left;
14470     }
14471     if ("right" in obj) {
14472     this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
14473     }
14474     if ("top" in obj) {
14475     this.offset.click.top = obj.top + this.margins.top;
14476     }
14477     if ("bottom" in obj) {
14478     this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
14479     }
14480     },
14481    
14482     _getParentOffset: function() {
14483    
14484    
14485     //Get the offsetParent and cache its position
14486     this.offsetParent = this.helper.offsetParent();
14487     var po = this.offsetParent.offset();
14488    
14489     // This is a special case where we need to modify a offset calculated on start, since the following happened:
14490     // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
14491     // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
14492     // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
14493     if(this.cssPosition === "absolute" && this.scrollParent[0] !== this.document[0] && $.contains(this.scrollParent[0], this.offsetParent[0])) {
14494     po.left += this.scrollParent.scrollLeft();
14495     po.top += this.scrollParent.scrollTop();
14496     }
14497    
14498     // This needs to be actually done for all browsers, since pageX/pageY includes this information
14499     // with an ugly IE fix
14500     if( this.offsetParent[0] === this.document[0].body || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() === "html" && $.ui.ie)) {
14501     po = { top: 0, left: 0 };
14502     }
14503    
14504     return {
14505     top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
14506     left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
14507     };
14508    
14509     },
14510    
14511     _getRelativeOffset: function() {
14512    
14513     if(this.cssPosition === "relative") {
14514     var p = this.currentItem.position();
14515     return {
14516     top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
14517     left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
14518     };
14519     } else {
14520     return { top: 0, left: 0 };
14521     }
14522    
14523     },
14524    
14525     _cacheMargins: function() {
14526     this.margins = {
14527     left: (parseInt(this.currentItem.css("marginLeft"),10) || 0),
14528     top: (parseInt(this.currentItem.css("marginTop"),10) || 0)
14529     };
14530     },
14531    
14532     _cacheHelperProportions: function() {
14533     this.helperProportions = {
14534     width: this.helper.outerWidth(),
14535     height: this.helper.outerHeight()
14536     };
14537     },
14538    
14539     _setContainment: function() {
14540    
14541     var ce, co, over,
14542     o = this.options;
14543     if(o.containment === "parent") {
14544     o.containment = this.helper[0].parentNode;
14545     }
14546     if(o.containment === "document" || o.containment === "window") {
14547     this.containment = [
14548     0 - this.offset.relative.left - this.offset.parent.left,
14549     0 - this.offset.relative.top - this.offset.parent.top,
14550     o.containment === "document" ? this.document.width() : this.window.width() - this.helperProportions.width - this.margins.left,
14551     (o.containment === "document" ? this.document.width() : this.window.height() || this.document[0].body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
14552     ];
14553     }
14554    
14555     if(!(/^(document|window|parent)$/).test(o.containment)) {
14556     ce = $(o.containment)[0];
14557     co = $(o.containment).offset();
14558     over = ($(ce).css("overflow") !== "hidden");
14559    
14560     this.containment = [
14561     co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
14562     co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
14563     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,
14564     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
14565     ];
14566     }
14567    
14568     },
14569    
14570     _convertPositionTo: function(d, pos) {
14571    
14572     if(!pos) {
14573     pos = this.position;
14574     }
14575     var mod = d === "absolute" ? 1 : -1,
14576     scroll = this.cssPosition === "absolute" && !(this.scrollParent[0] !== this.document[0] && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent,
14577     scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
14578    
14579     return {
14580     top: (
14581     pos.top + // The absolute mouse position
14582     this.offset.relative.top * mod + // Only for relative positioned nodes: Relative offset from element to offset parent
14583     this.offset.parent.top * mod - // The offsetParent's offset without borders (offset + border)
14584     ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
14585     ),
14586     left: (
14587     pos.left + // The absolute mouse position
14588     this.offset.relative.left * mod + // Only for relative positioned nodes: Relative offset from element to offset parent
14589     this.offset.parent.left * mod - // The offsetParent's offset without borders (offset + border)
14590     ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
14591     )
14592     };
14593    
14594     },
14595    
14596     _generatePosition: function(event) {
14597    
14598     var top, left,
14599     o = this.options,
14600     pageX = event.pageX,
14601     pageY = event.pageY,
14602     scroll = this.cssPosition === "absolute" && !(this.scrollParent[0] !== this.document[0] && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
14603    
14604     // This is another very weird special case that only happens for relative elements:
14605     // 1. If the css position is relative
14606     // 2. and the scroll parent is the document or similar to the offset parent
14607     // we have to refresh the relative offset during the scroll so there are no jumps
14608     if(this.cssPosition === "relative" && !(this.scrollParent[0] !== this.document[0] && this.scrollParent[0] !== this.offsetParent[0])) {
14609     this.offset.relative = this._getRelativeOffset();
14610     }
14611    
14612     /*
14613     * - Position constraining -
14614     * Constrain the position to a mix of grid, containment.
14615     */
14616    
14617     if(this.originalPosition) { //If we are not dragging yet, we won't check for options
14618    
14619     if(this.containment) {
14620     if(event.pageX - this.offset.click.left < this.containment[0]) {
14621     pageX = this.containment[0] + this.offset.click.left;
14622     }
14623     if(event.pageY - this.offset.click.top < this.containment[1]) {
14624     pageY = this.containment[1] + this.offset.click.top;
14625     }
14626     if(event.pageX - this.offset.click.left > this.containment[2]) {
14627     pageX = this.containment[2] + this.offset.click.left;
14628     }
14629     if(event.pageY - this.offset.click.top > this.containment[3]) {
14630     pageY = this.containment[3] + this.offset.click.top;
14631     }
14632     }
14633    
14634     if(o.grid) {
14635     top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
14636     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;
14637    
14638     left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
14639     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;
14640     }
14641    
14642     }
14643    
14644     return {
14645     top: (
14646     pageY - // The absolute mouse position
14647     this.offset.click.top - // Click offset (relative to the element)
14648     this.offset.relative.top - // Only for relative positioned nodes: Relative offset from element to offset parent
14649     this.offset.parent.top + // The offsetParent's offset without borders (offset + border)
14650     ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
14651     ),
14652     left: (
14653     pageX - // The absolute mouse position
14654     this.offset.click.left - // Click offset (relative to the element)
14655     this.offset.relative.left - // Only for relative positioned nodes: Relative offset from element to offset parent
14656     this.offset.parent.left + // The offsetParent's offset without borders (offset + border)
14657     ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
14658     )
14659     };
14660    
14661     },
14662    
14663     _rearrange: function(event, i, a, hardRefresh) {
14664    
14665     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));
14666    
14667     //Various things done here to improve the performance:
14668     // 1. we create a setTimeout, that calls refreshPositions
14669     // 2. on the instance, we have a counter variable, that get's higher after every append
14670     // 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same
14671     // 4. this lets only the last addition to the timeout stack through
14672     this.counter = this.counter ? ++this.counter : 1;
14673     var counter = this.counter;
14674    
14675     this._delay(function() {
14676     if(counter === this.counter) {
14677     this.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove
14678     }
14679     });
14680    
14681     },
14682    
14683     _clear: function(event, noPropagation) {
14684    
14685     this.reverting = false;
14686     // We delay all events that have to be triggered to after the point where the placeholder has been removed and
14687     // everything else normalized again
14688     var i,
14689     delayedTriggers = [];
14690    
14691     // We first have to update the dom position of the actual currentItem
14692     // Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088)
14693     if(!this._noFinalSort && this.currentItem.parent().length) {
14694     this.placeholder.before(this.currentItem);
14695     }
14696     this._noFinalSort = null;
14697    
14698     if(this.helper[0] === this.currentItem[0]) {
14699     for(i in this._storedCSS) {
14700     if(this._storedCSS[i] === "auto" || this._storedCSS[i] === "static") {
14701     this._storedCSS[i] = "";
14702     }
14703     }
14704     this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
14705     } else {
14706     this.currentItem.show();
14707     }
14708    
14709     if(this.fromOutside && !noPropagation) {
14710     delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); });
14711     }
14712     if((this.fromOutside || this.domPosition.prev !== this.currentItem.prev().not(".ui-sortable-helper")[0] || this.domPosition.parent !== this.currentItem.parent()[0]) && !noPropagation) {
14713     delayedTriggers.push(function(event) { this._trigger("update", event, this._uiHash()); }); //Trigger update callback if the DOM position has changed
14714     }
14715    
14716     // Check if the items Container has Changed and trigger appropriate
14717     // events.
14718     if (this !== this.currentContainer) {
14719     if(!noPropagation) {
14720     delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); });
14721     delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); }; }).call(this, this.currentContainer));
14722     delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this)); }; }).call(this, this.currentContainer));
14723     }
14724     }
14725    
14726    
14727     //Post events to containers
14728     function delayEvent( type, instance, container ) {
14729     return function( event ) {
14730     container._trigger( type, event, instance._uiHash( instance ) );
14731     };
14732     }
14733     for (i = this.containers.length - 1; i >= 0; i--){
14734     if (!noPropagation) {
14735     delayedTriggers.push( delayEvent( "deactivate", this, this.containers[ i ] ) );
14736     }
14737     if(this.containers[i].containerCache.over) {
14738     delayedTriggers.push( delayEvent( "out", this, this.containers[ i ] ) );
14739     this.containers[i].containerCache.over = 0;
14740     }
14741     }
14742    
14743     //Do what was originally in plugins
14744     if ( this.storedCursor ) {
14745     this.document.find( "body" ).css( "cursor", this.storedCursor );
14746     this.storedStylesheet.remove();
14747     }
14748     if(this._storedOpacity) {
14749     this.helper.css("opacity", this._storedOpacity);
14750     }
14751     if(this._storedZIndex) {
14752     this.helper.css("zIndex", this._storedZIndex === "auto" ? "" : this._storedZIndex);
14753     }
14754    
14755     this.dragging = false;
14756    
14757     if(!noPropagation) {
14758     this._trigger("beforeStop", event, this._uiHash());
14759     }
14760    
14761     //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
14762     this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
14763    
14764     if ( !this.cancelHelperRemoval ) {
14765     if ( this.helper[ 0 ] !== this.currentItem[ 0 ] ) {
14766     this.helper.remove();
14767     }
14768     this.helper = null;
14769     }
14770    
14771     if(!noPropagation) {
14772     for (i=0; i < delayedTriggers.length; i++) {
14773     delayedTriggers[i].call(this, event);
14774     } //Trigger all delayed events
14775     this._trigger("stop", event, this._uiHash());
14776     }
14777    
14778     this.fromOutside = false;
14779     return !this.cancelHelperRemoval;
14780    
14781     },
14782    
14783     _trigger: function() {
14784     if ($.Widget.prototype._trigger.apply(this, arguments) === false) {
14785     this.cancel();
14786     }
14787     },
14788    
14789     _uiHash: function(_inst) {
14790     var inst = _inst || this;
14791     return {
14792     helper: inst.helper,
14793     placeholder: inst.placeholder || $([]),
14794     position: inst.position,
14795     originalPosition: inst.originalPosition,
14796     offset: inst.positionAbs,
14797     item: inst.currentItem,
14798     sender: _inst ? _inst.element : null
14799     };
14800     }
14801    
14802     });
14803    
14804    
14805     /*!
14806     * jQuery UI Spinner 1.11.4
14807     * http://jqueryui.com
14808     *
14809     * Copyright jQuery Foundation and other contributors
14810     * Released under the MIT license.
14811     * http://jquery.org/license
14812     *
14813     * http://api.jqueryui.com/spinner/
14814     */
14815    
14816    
14817     function spinner_modifier( fn ) {
14818     return function() {
14819     var previous = this.element.val();
14820     fn.apply( this, arguments );
14821     this._refresh();
14822     if ( previous !== this.element.val() ) {
14823     this._trigger( "change" );
14824     }
14825     };
14826     }
14827    
14828     var spinner = $.widget( "ui.spinner", {
14829     version: "1.11.4",
14830     defaultElement: "<input>",
14831     widgetEventPrefix: "spin",
14832     options: {
14833     culture: null,
14834     icons: {
14835     down: "ui-icon-triangle-1-s",
14836     up: "ui-icon-triangle-1-n"
14837     },
14838     incremental: true,
14839     max: null,
14840     min: null,
14841     numberFormat: null,
14842     page: 10,
14843     step: 1,
14844    
14845     change: null,
14846     spin: null,
14847     start: null,
14848     stop: null
14849     },
14850    
14851     _create: function() {
14852     // handle string values that need to be parsed
14853     this._setOption( "max", this.options.max );
14854     this._setOption( "min", this.options.min );
14855     this._setOption( "step", this.options.step );
14856    
14857     // Only format if there is a value, prevents the field from being marked
14858     // as invalid in Firefox, see #9573.
14859     if ( this.value() !== "" ) {
14860     // Format the value, but don't constrain.
14861     this._value( this.element.val(), true );
14862     }
14863    
14864     this._draw();
14865     this._on( this._events );
14866     this._refresh();
14867    
14868     // turning off autocomplete prevents the browser from remembering the
14869     // value when navigating through history, so we re-enable autocomplete
14870     // if the page is unloaded before the widget is destroyed. #7790
14871     this._on( this.window, {
14872     beforeunload: function() {
14873     this.element.removeAttr( "autocomplete" );
14874     }
14875     });
14876     },
14877    
14878     _getCreateOptions: function() {
14879     var options = {},
14880     element = this.element;
14881    
14882     $.each( [ "min", "max", "step" ], function( i, option ) {
14883     var value = element.attr( option );
14884     if ( value !== undefined && value.length ) {
14885     options[ option ] = value;
14886     }
14887     });
14888    
14889     return options;
14890     },
14891    
14892     _events: {
14893     keydown: function( event ) {
14894     if ( this._start( event ) && this._keydown( event ) ) {
14895     event.preventDefault();
14896     }
14897     },
14898     keyup: "_stop",
14899     focus: function() {
14900     this.previous = this.element.val();
14901     },
14902     blur: function( event ) {
14903     if ( this.cancelBlur ) {
14904     delete this.cancelBlur;
14905     return;
14906     }
14907    
14908     this._stop();
14909     this._refresh();
14910     if ( this.previous !== this.element.val() ) {
14911     this._trigger( "change", event );
14912     }
14913     },
14914     mousewheel: function( event, delta ) {
14915     if ( !delta ) {
14916     return;
14917     }
14918     if ( !this.spinning && !this._start( event ) ) {
14919     return false;
14920     }
14921    
14922     this._spin( (delta > 0 ? 1 : -1) * this.options.step, event );
14923     clearTimeout( this.mousewheelTimer );
14924     this.mousewheelTimer = this._delay(function() {
14925     if ( this.spinning ) {
14926     this._stop( event );
14927     }
14928     }, 100 );
14929     event.preventDefault();
14930     },
14931     "mousedown .ui-spinner-button": function( event ) {
14932     var previous;
14933    
14934     // We never want the buttons to have focus; whenever the user is
14935     // interacting with the spinner, the focus should be on the input.
14936     // If the input is focused then this.previous is properly set from
14937     // when the input first received focus. If the input is not focused
14938     // then we need to set this.previous based on the value before spinning.
14939     previous = this.element[0] === this.document[0].activeElement ?
14940     this.previous : this.element.val();
14941     function checkFocus() {
14942     var isActive = this.element[0] === this.document[0].activeElement;
14943     if ( !isActive ) {
14944     this.element.focus();
14945     this.previous = previous;
14946     // support: IE
14947     // IE sets focus asynchronously, so we need to check if focus
14948     // moved off of the input because the user clicked on the button.
14949     this._delay(function() {
14950     this.previous = previous;
14951     });
14952     }
14953     }
14954    
14955     // ensure focus is on (or stays on) the text field
14956     event.preventDefault();
14957     checkFocus.call( this );
14958    
14959     // support: IE
14960     // IE doesn't prevent moving focus even with event.preventDefault()
14961     // so we set a flag to know when we should ignore the blur event
14962     // and check (again) if focus moved off of the input.
14963     this.cancelBlur = true;
14964     this._delay(function() {
14965     delete this.cancelBlur;
14966     checkFocus.call( this );
14967     });
14968    
14969     if ( this._start( event ) === false ) {
14970     return;
14971     }
14972    
14973     this._repeat( null, $( event.currentTarget ).hasClass( "ui-spinner-up" ) ? 1 : -1, event );
14974     },
14975     "mouseup .ui-spinner-button": "_stop",
14976     "mouseenter .ui-spinner-button": function( event ) {
14977     // button will add ui-state-active if mouse was down while mouseleave and kept down
14978     if ( !$( event.currentTarget ).hasClass( "ui-state-active" ) ) {
14979     return;
14980     }
14981    
14982     if ( this._start( event ) === false ) {
14983     return false;
14984     }
14985     this._repeat( null, $( event.currentTarget ).hasClass( "ui-spinner-up" ) ? 1 : -1, event );
14986     },
14987     // TODO: do we really want to consider this a stop?
14988     // shouldn't we just stop the repeater and wait until mouseup before
14989     // we trigger the stop event?
14990     "mouseleave .ui-spinner-button": "_stop"
14991     },
14992    
14993     _draw: function() {
14994     var uiSpinner = this.uiSpinner = this.element
14995     .addClass( "ui-spinner-input" )
14996     .attr( "autocomplete", "off" )
14997     .wrap( this._uiSpinnerHtml() )
14998     .parent()
14999     // add buttons
15000     .append( this._buttonHtml() );
15001    
15002     this.element.attr( "role", "spinbutton" );
15003    
15004     // button bindings
15005     this.buttons = uiSpinner.find( ".ui-spinner-button" )
15006     .attr( "tabIndex", -1 )
15007     .button()
15008     .removeClass( "ui-corner-all" );
15009    
15010     // IE 6 doesn't understand height: 50% for the buttons
15011     // unless the wrapper has an explicit height
15012     if ( this.buttons.height() > Math.ceil( uiSpinner.height() * 0.5 ) &&
15013     uiSpinner.height() > 0 ) {
15014     uiSpinner.height( uiSpinner.height() );
15015     }
15016    
15017     // disable spinner if element was already disabled
15018     if ( this.options.disabled ) {
15019     this.disable();
15020     }
15021     },
15022    
15023     _keydown: function( event ) {
15024     var options = this.options,
15025     keyCode = $.ui.keyCode;
15026    
15027     switch ( event.keyCode ) {
15028     case keyCode.UP:
15029     this._repeat( null, 1, event );
15030     return true;
15031     case keyCode.DOWN:
15032     this._repeat( null, -1, event );
15033     return true;
15034     case keyCode.PAGE_UP:
15035     this._repeat( null, options.page, event );
15036     return true;
15037     case keyCode.PAGE_DOWN:
15038     this._repeat( null, -options.page, event );
15039     return true;
15040     }
15041    
15042     return false;
15043     },
15044    
15045     _uiSpinnerHtml: function() {
15046     return "<span class='ui-spinner ui-widget ui-widget-content ui-corner-all'></span>";
15047     },
15048    
15049     _buttonHtml: function() {
15050     return "" +
15051     "<a class='ui-spinner-button ui-spinner-up ui-corner-tr'>" +
15052     "<span class='ui-icon " + this.options.icons.up + "'>&#9650;</span>" +
15053     "</a>" +
15054     "<a class='ui-spinner-button ui-spinner-down ui-corner-br'>" +
15055     "<span class='ui-icon " + this.options.icons.down + "'>&#9660;</span>" +
15056     "</a>";
15057     },
15058    
15059     _start: function( event ) {
15060     if ( !this.spinning && this._trigger( "start", event ) === false ) {
15061     return false;
15062     }
15063    
15064     if ( !this.counter ) {
15065     this.counter = 1;
15066     }
15067     this.spinning = true;
15068     return true;
15069     },
15070    
15071     _repeat: function( i, steps, event ) {
15072     i = i || 500;
15073    
15074     clearTimeout( this.timer );
15075     this.timer = this._delay(function() {
15076     this._repeat( 40, steps, event );
15077     }, i );
15078    
15079     this._spin( steps * this.options.step, event );
15080     },
15081    
15082     _spin: function( step, event ) {
15083     var value = this.value() || 0;
15084    
15085     if ( !this.counter ) {
15086     this.counter = 1;
15087     }
15088    
15089     value = this._adjustValue( value + step * this._increment( this.counter ) );
15090    
15091     if ( !this.spinning || this._trigger( "spin", event, { value: value } ) !== false) {
15092     this._value( value );
15093     this.counter++;
15094     }
15095     },
15096    
15097     _increment: function( i ) {
15098     var incremental = this.options.incremental;
15099    
15100     if ( incremental ) {
15101     return $.isFunction( incremental ) ?
15102     incremental( i ) :
15103     Math.floor( i * i * i / 50000 - i * i / 500 + 17 * i / 200 + 1 );
15104     }
15105    
15106     return 1;
15107     },
15108    
15109     _precision: function() {
15110     var precision = this._precisionOf( this.options.step );
15111     if ( this.options.min !== null ) {
15112     precision = Math.max( precision, this._precisionOf( this.options.min ) );
15113     }
15114     return precision;
15115     },
15116    
15117     _precisionOf: function( num ) {
15118     var str = num.toString(),
15119     decimal = str.indexOf( "." );
15120     return decimal === -1 ? 0 : str.length - decimal - 1;
15121     },
15122    
15123     _adjustValue: function( value ) {
15124     var base, aboveMin,
15125     options = this.options;
15126    
15127     // make sure we're at a valid step
15128     // - find out where we are relative to the base (min or 0)
15129     base = options.min !== null ? options.min : 0;
15130     aboveMin = value - base;
15131     // - round to the nearest step
15132     aboveMin = Math.round(aboveMin / options.step) * options.step;
15133     // - rounding is based on 0, so adjust back to our base
15134     value = base + aboveMin;
15135    
15136     // fix precision from bad JS floating point math
15137     value = parseFloat( value.toFixed( this._precision() ) );
15138    
15139     // clamp the value
15140     if ( options.max !== null && value > options.max) {
15141     return options.max;
15142     }
15143     if ( options.min !== null && value < options.min ) {
15144     return options.min;
15145     }
15146    
15147     return value;
15148     },
15149    
15150     _stop: function( event ) {
15151     if ( !this.spinning ) {
15152     return;
15153     }
15154    
15155     clearTimeout( this.timer );
15156     clearTimeout( this.mousewheelTimer );
15157     this.counter = 0;
15158     this.spinning = false;
15159     this._trigger( "stop", event );
15160     },
15161    
15162     _setOption: function( key, value ) {
15163     if ( key === "culture" || key === "numberFormat" ) {
15164     var prevValue = this._parse( this.element.val() );
15165     this.options[ key ] = value;
15166     this.element.val( this._format( prevValue ) );
15167     return;
15168     }
15169    
15170     if ( key === "max" || key === "min" || key === "step" ) {
15171     if ( typeof value === "string" ) {
15172     value = this._parse( value );
15173     }
15174     }
15175     if ( key === "icons" ) {
15176     this.buttons.first().find( ".ui-icon" )
15177     .removeClass( this.options.icons.up )
15178     .addClass( value.up );
15179     this.buttons.last().find( ".ui-icon" )
15180     .removeClass( this.options.icons.down )
15181     .addClass( value.down );
15182     }
15183    
15184     this._super( key, value );
15185    
15186     if ( key === "disabled" ) {
15187     this.widget().toggleClass( "ui-state-disabled", !!value );
15188     this.element.prop( "disabled", !!value );
15189     this.buttons.button( value ? "disable" : "enable" );
15190     }
15191     },
15192    
15193     _setOptions: spinner_modifier(function( options ) {
15194     this._super( options );
15195     }),
15196    
15197     _parse: function( val ) {
15198     if ( typeof val === "string" && val !== "" ) {
15199     val = window.Globalize && this.options.numberFormat ?
15200     Globalize.parseFloat( val, 10, this.options.culture ) : +val;
15201     }
15202     return val === "" || isNaN( val ) ? null : val;
15203     },
15204    
15205     _format: function( value ) {
15206     if ( value === "" ) {
15207     return "";
15208     }
15209     return window.Globalize && this.options.numberFormat ?
15210     Globalize.format( value, this.options.numberFormat, this.options.culture ) :
15211     value;
15212     },
15213    
15214     _refresh: function() {
15215     this.element.attr({
15216     "aria-valuemin": this.options.min,
15217     "aria-valuemax": this.options.max,
15218     // TODO: what should we do with values that can't be parsed?
15219     "aria-valuenow": this._parse( this.element.val() )
15220     });
15221     },
15222    
15223     isValid: function() {
15224     var value = this.value();
15225    
15226     // null is invalid
15227     if ( value === null ) {
15228     return false;
15229     }
15230    
15231     // if value gets adjusted, it's invalid
15232     return value === this._adjustValue( value );
15233     },
15234    
15235     // update the value without triggering change
15236     _value: function( value, allowAny ) {
15237     var parsed;
15238     if ( value !== "" ) {
15239     parsed = this._parse( value );
15240     if ( parsed !== null ) {
15241     if ( !allowAny ) {
15242     parsed = this._adjustValue( parsed );
15243     }
15244     value = this._format( parsed );
15245     }
15246     }
15247     this.element.val( value );
15248     this._refresh();
15249     },
15250    
15251     _destroy: function() {
15252     this.element
15253     .removeClass( "ui-spinner-input" )
15254     .prop( "disabled", false )
15255     .removeAttr( "autocomplete" )
15256     .removeAttr( "role" )
15257     .removeAttr( "aria-valuemin" )
15258     .removeAttr( "aria-valuemax" )
15259     .removeAttr( "aria-valuenow" );
15260     this.uiSpinner.replaceWith( this.element );
15261     },
15262    
15263     stepUp: spinner_modifier(function( steps ) {
15264     this._stepUp( steps );
15265     }),
15266     _stepUp: function( steps ) {
15267     if ( this._start() ) {
15268     this._spin( (steps || 1) * this.options.step );
15269     this._stop();
15270     }
15271     },
15272    
15273     stepDown: spinner_modifier(function( steps ) {
15274     this._stepDown( steps );
15275     }),
15276     _stepDown: function( steps ) {
15277     if ( this._start() ) {
15278     this._spin( (steps || 1) * -this.options.step );
15279     this._stop();
15280     }
15281     },
15282    
15283     pageUp: spinner_modifier(function( pages ) {
15284     this._stepUp( (pages || 1) * this.options.page );
15285     }),
15286    
15287     pageDown: spinner_modifier(function( pages ) {
15288     this._stepDown( (pages || 1) * this.options.page );
15289     }),
15290    
15291     value: function( newVal ) {
15292     if ( !arguments.length ) {
15293     return this._parse( this.element.val() );
15294     }
15295     spinner_modifier( this._value ).call( this, newVal );
15296     },
15297    
15298     widget: function() {
15299     return this.uiSpinner;
15300     }
15301     });
15302    
15303    
15304     /*!
15305     * jQuery UI Tabs 1.11.4
15306     * http://jqueryui.com
15307     *
15308     * Copyright jQuery Foundation and other contributors
15309     * Released under the MIT license.
15310     * http://jquery.org/license
15311     *
15312     * http://api.jqueryui.com/tabs/
15313     */
15314    
15315    
15316     var tabs = $.widget( "ui.tabs", {
15317     version: "1.11.4",
15318     delay: 300,
15319     options: {
15320     active: null,
15321     collapsible: false,
15322     event: "click",
15323     heightStyle: "content",
15324     hide: null,
15325     show: null,
15326    
15327     // callbacks
15328     activate: null,
15329     beforeActivate: null,
15330     beforeLoad: null,
15331     load: null
15332     },
15333    
15334     _isLocal: (function() {
15335     var rhash = /#.*$/;
15336    
15337     return function( anchor ) {
15338     var anchorUrl, locationUrl;
15339    
15340     // support: IE7
15341     // IE7 doesn't normalize the href property when set via script (#9317)
15342     anchor = anchor.cloneNode( false );
15343    
15344     anchorUrl = anchor.href.replace( rhash, "" );
15345     locationUrl = location.href.replace( rhash, "" );
15346    
15347     // decoding may throw an error if the URL isn't UTF-8 (#9518)
15348     try {
15349     anchorUrl = decodeURIComponent( anchorUrl );
15350     } catch ( error ) {}
15351     try {
15352     locationUrl = decodeURIComponent( locationUrl );
15353     } catch ( error ) {}
15354    
15355     return anchor.hash.length > 1 && anchorUrl === locationUrl;
15356     };
15357     })(),
15358    
15359     _create: function() {
15360     var that = this,
15361     options = this.options;
15362    
15363     this.running = false;
15364    
15365     this.element
15366     .addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" )
15367     .toggleClass( "ui-tabs-collapsible", options.collapsible );
15368    
15369     this._processTabs();
15370     options.active = this._initialActive();
15371    
15372     // Take disabling tabs via class attribute from HTML
15373     // into account and update option properly.
15374     if ( $.isArray( options.disabled ) ) {
15375     options.disabled = $.unique( options.disabled.concat(
15376     $.map( this.tabs.filter( ".ui-state-disabled" ), function( li ) {
15377     return that.tabs.index( li );
15378     })
15379     ) ).sort();
15380     }
15381    
15382     // check for length avoids error when initializing empty list
15383     if ( this.options.active !== false && this.anchors.length ) {
15384     this.active = this._findActive( options.active );
15385     } else {
15386     this.active = $();
15387     }
15388    
15389     this._refresh();
15390    
15391     if ( this.active.length ) {
15392     this.load( options.active );
15393     }
15394     },
15395    
15396     _initialActive: function() {
15397     var active = this.options.active,
15398     collapsible = this.options.collapsible,
15399     locationHash = location.hash.substring( 1 );
15400    
15401     if ( active === null ) {
15402     // check the fragment identifier in the URL
15403     if ( locationHash ) {
15404     this.tabs.each(function( i, tab ) {
15405     if ( $( tab ).attr( "aria-controls" ) === locationHash ) {
15406     active = i;
15407     return false;
15408     }
15409     });
15410     }
15411    
15412     // check for a tab marked active via a class
15413     if ( active === null ) {
15414     active = this.tabs.index( this.tabs.filter( ".ui-tabs-active" ) );
15415     }
15416    
15417     // no active tab, set to false
15418     if ( active === null || active === -1 ) {
15419     active = this.tabs.length ? 0 : false;
15420     }
15421     }
15422    
15423     // handle numbers: negative, out of range
15424     if ( active !== false ) {
15425     active = this.tabs.index( this.tabs.eq( active ) );
15426     if ( active === -1 ) {
15427     active = collapsible ? false : 0;
15428     }
15429     }
15430    
15431     // don't allow collapsible: false and active: false
15432     if ( !collapsible && active === false && this.anchors.length ) {
15433     active = 0;
15434     }
15435    
15436     return active;
15437     },
15438    
15439     _getCreateEventData: function() {
15440     return {
15441     tab: this.active,
15442     panel: !this.active.length ? $() : this._getPanelForTab( this.active )
15443     };
15444     },
15445    
15446     _tabKeydown: function( event ) {
15447     var focusedTab = $( this.document[0].activeElement ).closest( "li" ),
15448     selectedIndex = this.tabs.index( focusedTab ),
15449     goingForward = true;
15450    
15451     if ( this._handlePageNav( event ) ) {
15452     return;
15453     }
15454    
15455     switch ( event.keyCode ) {
15456     case $.ui.keyCode.RIGHT:
15457     case $.ui.keyCode.DOWN:
15458     selectedIndex++;
15459     break;
15460     case $.ui.keyCode.UP:
15461     case $.ui.keyCode.LEFT:
15462     goingForward = false;
15463     selectedIndex--;
15464     break;
15465     case $.ui.keyCode.END:
15466     selectedIndex = this.anchors.length - 1;
15467     break;
15468     case $.ui.keyCode.HOME:
15469     selectedIndex = 0;
15470     break;
15471     case $.ui.keyCode.SPACE:
15472     // Activate only, no collapsing
15473     event.preventDefault();
15474     clearTimeout( this.activating );
15475     this._activate( selectedIndex );
15476     return;
15477     case $.ui.keyCode.ENTER:
15478     // Toggle (cancel delayed activation, allow collapsing)
15479     event.preventDefault();
15480     clearTimeout( this.activating );
15481     // Determine if we should collapse or activate
15482     this._activate( selectedIndex === this.options.active ? false : selectedIndex );
15483     return;
15484     default:
15485     return;
15486     }
15487    
15488     // Focus the appropriate tab, based on which key was pressed
15489     event.preventDefault();
15490     clearTimeout( this.activating );
15491     selectedIndex = this._focusNextTab( selectedIndex, goingForward );
15492    
15493     // Navigating with control/command key will prevent automatic activation
15494     if ( !event.ctrlKey && !event.metaKey ) {
15495    
15496     // Update aria-selected immediately so that AT think the tab is already selected.
15497     // Otherwise AT may confuse the user by stating that they need to activate the tab,
15498     // but the tab will already be activated by the time the announcement finishes.
15499     focusedTab.attr( "aria-selected", "false" );
15500     this.tabs.eq( selectedIndex ).attr( "aria-selected", "true" );
15501    
15502     this.activating = this._delay(function() {
15503     this.option( "active", selectedIndex );
15504     }, this.delay );
15505     }
15506     },
15507    
15508     _panelKeydown: function( event ) {
15509     if ( this._handlePageNav( event ) ) {
15510     return;
15511     }
15512    
15513     // Ctrl+up moves focus to the current tab
15514     if ( event.ctrlKey && event.keyCode === $.ui.keyCode.UP ) {
15515     event.preventDefault();
15516     this.active.focus();
15517     }
15518     },
15519    
15520     // Alt+page up/down moves focus to the previous/next tab (and activates)
15521     _handlePageNav: function( event ) {
15522     if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_UP ) {
15523     this._activate( this._focusNextTab( this.options.active - 1, false ) );
15524     return true;
15525     }
15526     if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_DOWN ) {
15527     this._activate( this._focusNextTab( this.options.active + 1, true ) );
15528     return true;
15529     }
15530     },
15531    
15532     _findNextTab: function( index, goingForward ) {
15533     var lastTabIndex = this.tabs.length - 1;
15534    
15535     function constrain() {
15536     if ( index > lastTabIndex ) {
15537     index = 0;
15538     }
15539     if ( index < 0 ) {
15540     index = lastTabIndex;
15541     }
15542     return index;
15543     }
15544    
15545     while ( $.inArray( constrain(), this.options.disabled ) !== -1 ) {
15546     index = goingForward ? index + 1 : index - 1;
15547     }
15548    
15549     return index;
15550     },
15551    
15552     _focusNextTab: function( index, goingForward ) {
15553     index = this._findNextTab( index, goingForward );
15554     this.tabs.eq( index ).focus();
15555     return index;
15556     },
15557    
15558     _setOption: function( key, value ) {
15559     if ( key === "active" ) {
15560     // _activate() will handle invalid values and update this.options
15561     this._activate( value );
15562     return;
15563     }
15564    
15565     if ( key === "disabled" ) {
15566     // don't use the widget factory's disabled handling
15567     this._setupDisabled( value );
15568     return;
15569     }
15570    
15571     this._super( key, value);
15572    
15573     if ( key === "collapsible" ) {
15574     this.element.toggleClass( "ui-tabs-collapsible", value );
15575     // Setting collapsible: false while collapsed; open first panel
15576     if ( !value && this.options.active === false ) {
15577     this._activate( 0 );
15578     }
15579     }
15580    
15581     if ( key === "event" ) {
15582     this._setupEvents( value );
15583     }
15584    
15585     if ( key === "heightStyle" ) {
15586     this._setupHeightStyle( value );
15587     }
15588     },
15589    
15590     _sanitizeSelector: function( hash ) {
15591     return hash ? hash.replace( /[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g, "\\$&" ) : "";
15592     },
15593    
15594     refresh: function() {
15595     var options = this.options,
15596     lis = this.tablist.children( ":has(a[href])" );
15597    
15598     // get disabled tabs from class attribute from HTML
15599     // this will get converted to a boolean if needed in _refresh()
15600     options.disabled = $.map( lis.filter( ".ui-state-disabled" ), function( tab ) {
15601     return lis.index( tab );
15602     });
15603    
15604     this._processTabs();
15605    
15606     // was collapsed or no tabs
15607     if ( options.active === false || !this.anchors.length ) {
15608     options.active = false;
15609     this.active = $();
15610     // was active, but active tab is gone
15611     } else if ( this.active.length && !$.contains( this.tablist[ 0 ], this.active[ 0 ] ) ) {
15612     // all remaining tabs are disabled
15613     if ( this.tabs.length === options.disabled.length ) {
15614     options.active = false;
15615     this.active = $();
15616     // activate previous tab
15617     } else {
15618     this._activate( this._findNextTab( Math.max( 0, options.active - 1 ), false ) );
15619     }
15620     // was active, active tab still exists
15621     } else {
15622     // make sure active index is correct
15623     options.active = this.tabs.index( this.active );
15624     }
15625    
15626     this._refresh();
15627     },
15628    
15629     _refresh: function() {
15630     this._setupDisabled( this.options.disabled );
15631     this._setupEvents( this.options.event );
15632     this._setupHeightStyle( this.options.heightStyle );
15633    
15634     this.tabs.not( this.active ).attr({
15635     "aria-selected": "false",
15636     "aria-expanded": "false",
15637     tabIndex: -1
15638     });
15639     this.panels.not( this._getPanelForTab( this.active ) )
15640     .hide()
15641     .attr({
15642     "aria-hidden": "true"
15643     });
15644    
15645     // Make sure one tab is in the tab order
15646     if ( !this.active.length ) {
15647     this.tabs.eq( 0 ).attr( "tabIndex", 0 );
15648     } else {
15649     this.active
15650     .addClass( "ui-tabs-active ui-state-active" )
15651     .attr({
15652     "aria-selected": "true",
15653     "aria-expanded": "true",
15654     tabIndex: 0
15655     });
15656     this._getPanelForTab( this.active )
15657     .show()
15658     .attr({
15659     "aria-hidden": "false"
15660     });
15661     }
15662     },
15663    
15664     _processTabs: function() {
15665     var that = this,
15666     prevTabs = this.tabs,
15667     prevAnchors = this.anchors,
15668     prevPanels = this.panels;
15669    
15670     this.tablist = this._getList()
15671     .addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" )
15672     .attr( "role", "tablist" )
15673    
15674     // Prevent users from focusing disabled tabs via click
15675     .delegate( "> li", "mousedown" + this.eventNamespace, function( event ) {
15676     if ( $( this ).is( ".ui-state-disabled" ) ) {
15677     event.preventDefault();
15678     }
15679     })
15680    
15681     // support: IE <9
15682     // Preventing the default action in mousedown doesn't prevent IE
15683     // from focusing the element, so if the anchor gets focused, blur.
15684     // We don't have to worry about focusing the previously focused
15685     // element since clicking on a non-focusable element should focus
15686     // the body anyway.
15687     .delegate( ".ui-tabs-anchor", "focus" + this.eventNamespace, function() {
15688     if ( $( this ).closest( "li" ).is( ".ui-state-disabled" ) ) {
15689     this.blur();
15690     }
15691     });
15692    
15693     this.tabs = this.tablist.find( "> li:has(a[href])" )
15694     .addClass( "ui-state-default ui-corner-top" )
15695     .attr({
15696     role: "tab",
15697     tabIndex: -1
15698     });
15699    
15700     this.anchors = this.tabs.map(function() {
15701     return $( "a", this )[ 0 ];
15702     })
15703     .addClass( "ui-tabs-anchor" )
15704     .attr({
15705     role: "presentation",
15706     tabIndex: -1
15707     });
15708    
15709     this.panels = $();
15710    
15711     this.anchors.each(function( i, anchor ) {
15712     var selector, panel, panelId,
15713     anchorId = $( anchor ).uniqueId().attr( "id" ),
15714     tab = $( anchor ).closest( "li" ),
15715     originalAriaControls = tab.attr( "aria-controls" );
15716    
15717     // inline tab
15718     if ( that._isLocal( anchor ) ) {
15719     selector = anchor.hash;
15720     panelId = selector.substring( 1 );
15721     panel = that.element.find( that._sanitizeSelector( selector ) );
15722     // remote tab
15723     } else {
15724     // If the tab doesn't already have aria-controls,
15725     // generate an id by using a throw-away element
15726     panelId = tab.attr( "aria-controls" ) || $( {} ).uniqueId()[ 0 ].id;
15727     selector = "#" + panelId;
15728     panel = that.element.find( selector );
15729     if ( !panel.length ) {
15730     panel = that._createPanel( panelId );
15731     panel.insertAfter( that.panels[ i - 1 ] || that.tablist );
15732     }
15733     panel.attr( "aria-live", "polite" );
15734     }
15735    
15736     if ( panel.length) {
15737     that.panels = that.panels.add( panel );
15738     }
15739     if ( originalAriaControls ) {
15740     tab.data( "ui-tabs-aria-controls", originalAriaControls );
15741     }
15742     tab.attr({
15743     "aria-controls": panelId,
15744     "aria-labelledby": anchorId
15745     });
15746     panel.attr( "aria-labelledby", anchorId );
15747     });
15748    
15749     this.panels
15750     .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
15751     .attr( "role", "tabpanel" );
15752    
15753     // Avoid memory leaks (#10056)
15754     if ( prevTabs ) {
15755     this._off( prevTabs.not( this.tabs ) );
15756     this._off( prevAnchors.not( this.anchors ) );
15757     this._off( prevPanels.not( this.panels ) );
15758     }
15759     },
15760    
15761     // allow overriding how to find the list for rare usage scenarios (#7715)
15762     _getList: function() {
15763     return this.tablist || this.element.find( "ol,ul" ).eq( 0 );
15764     },
15765    
15766     _createPanel: function( id ) {
15767     return $( "<div>" )
15768     .attr( "id", id )
15769     .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
15770     .data( "ui-tabs-destroy", true );
15771     },
15772    
15773     _setupDisabled: function( disabled ) {
15774     if ( $.isArray( disabled ) ) {
15775     if ( !disabled.length ) {
15776     disabled = false;
15777     } else if ( disabled.length === this.anchors.length ) {
15778     disabled = true;
15779     }
15780     }
15781    
15782     // disable tabs
15783     for ( var i = 0, li; ( li = this.tabs[ i ] ); i++ ) {
15784     if ( disabled === true || $.inArray( i, disabled ) !== -1 ) {
15785     $( li )
15786     .addClass( "ui-state-disabled" )
15787     .attr( "aria-disabled", "true" );
15788     } else {
15789     $( li )
15790     .removeClass( "ui-state-disabled" )
15791     .removeAttr( "aria-disabled" );
15792     }
15793     }
15794    
15795     this.options.disabled = disabled;
15796     },
15797    
15798     _setupEvents: function( event ) {
15799     var events = {};
15800     if ( event ) {
15801     $.each( event.split(" "), function( index, eventName ) {
15802     events[ eventName ] = "_eventHandler";
15803     });
15804     }
15805    
15806     this._off( this.anchors.add( this.tabs ).add( this.panels ) );
15807     // Always prevent the default action, even when disabled
15808     this._on( true, this.anchors, {
15809     click: function( event ) {
15810     event.preventDefault();
15811     }
15812     });
15813     this._on( this.anchors, events );
15814     this._on( this.tabs, { keydown: "_tabKeydown" } );
15815     this._on( this.panels, { keydown: "_panelKeydown" } );
15816    
15817     this._focusable( this.tabs );
15818     this._hoverable( this.tabs );
15819     },
15820    
15821     _setupHeightStyle: function( heightStyle ) {
15822     var maxHeight,
15823     parent = this.element.parent();
15824    
15825     if ( heightStyle === "fill" ) {
15826     maxHeight = parent.height();
15827     maxHeight -= this.element.outerHeight() - this.element.height();
15828    
15829     this.element.siblings( ":visible" ).each(function() {
15830     var elem = $( this ),
15831     position = elem.css( "position" );
15832    
15833     if ( position === "absolute" || position === "fixed" ) {
15834     return;
15835     }
15836     maxHeight -= elem.outerHeight( true );
15837     });
15838    
15839     this.element.children().not( this.panels ).each(function() {
15840     maxHeight -= $( this ).outerHeight( true );
15841     });
15842    
15843     this.panels.each(function() {
15844     $( this ).height( Math.max( 0, maxHeight -
15845     $( this ).innerHeight() + $( this ).height() ) );
15846     })
15847     .css( "overflow", "auto" );
15848     } else if ( heightStyle === "auto" ) {
15849     maxHeight = 0;
15850     this.panels.each(function() {
15851     maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() );
15852     }).height( maxHeight );
15853     }
15854     },
15855    
15856     _eventHandler: function( event ) {
15857     var options = this.options,
15858     active = this.active,
15859     anchor = $( event.currentTarget ),
15860     tab = anchor.closest( "li" ),
15861     clickedIsActive = tab[ 0 ] === active[ 0 ],
15862     collapsing = clickedIsActive && options.collapsible,
15863     toShow = collapsing ? $() : this._getPanelForTab( tab ),
15864     toHide = !active.length ? $() : this._getPanelForTab( active ),
15865     eventData = {
15866     oldTab: active,
15867     oldPanel: toHide,
15868     newTab: collapsing ? $() : tab,
15869     newPanel: toShow
15870     };
15871    
15872     event.preventDefault();
15873    
15874     if ( tab.hasClass( "ui-state-disabled" ) ||
15875     // tab is already loading
15876     tab.hasClass( "ui-tabs-loading" ) ||
15877     // can't switch durning an animation
15878     this.running ||
15879     // click on active header, but not collapsible
15880     ( clickedIsActive && !options.collapsible ) ||
15881     // allow canceling activation
15882     ( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
15883     return;
15884     }
15885    
15886     options.active = collapsing ? false : this.tabs.index( tab );
15887    
15888     this.active = clickedIsActive ? $() : tab;
15889     if ( this.xhr ) {
15890     this.xhr.abort();
15891     }
15892    
15893     if ( !toHide.length && !toShow.length ) {
15894     $.error( "jQuery UI Tabs: Mismatching fragment identifier." );
15895     }
15896    
15897     if ( toShow.length ) {
15898     this.load( this.tabs.index( tab ), event );
15899     }
15900     this._toggle( event, eventData );
15901     },
15902    
15903     // handles show/hide for selecting tabs
15904     _toggle: function( event, eventData ) {
15905     var that = this,
15906     toShow = eventData.newPanel,
15907     toHide = eventData.oldPanel;
15908    
15909     this.running = true;
15910    
15911     function complete() {
15912     that.running = false;
15913     that._trigger( "activate", event, eventData );
15914     }
15915    
15916     function show() {
15917     eventData.newTab.closest( "li" ).addClass( "ui-tabs-active ui-state-active" );
15918    
15919     if ( toShow.length && that.options.show ) {
15920     that._show( toShow, that.options.show, complete );
15921     } else {
15922     toShow.show();
15923     complete();
15924     }
15925     }
15926    
15927     // start out by hiding, then showing, then completing
15928     if ( toHide.length && this.options.hide ) {
15929     this._hide( toHide, this.options.hide, function() {
15930     eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" );
15931     show();
15932     });
15933     } else {
15934     eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" );
15935     toHide.hide();
15936     show();
15937     }
15938    
15939     toHide.attr( "aria-hidden", "true" );
15940     eventData.oldTab.attr({
15941     "aria-selected": "false",
15942     "aria-expanded": "false"
15943     });
15944     // If we're switching tabs, remove the old tab from the tab order.
15945     // If we're opening from collapsed state, remove the previous tab from the tab order.
15946     // If we're collapsing, then keep the collapsing tab in the tab order.
15947     if ( toShow.length && toHide.length ) {
15948     eventData.oldTab.attr( "tabIndex", -1 );
15949     } else if ( toShow.length ) {
15950     this.tabs.filter(function() {
15951     return $( this ).attr( "tabIndex" ) === 0;
15952     })
15953     .attr( "tabIndex", -1 );
15954     }
15955    
15956     toShow.attr( "aria-hidden", "false" );
15957     eventData.newTab.attr({
15958     "aria-selected": "true",
15959     "aria-expanded": "true",
15960     tabIndex: 0
15961     });
15962     },
15963    
15964     _activate: function( index ) {
15965     var anchor,
15966     active = this._findActive( index );
15967    
15968     // trying to activate the already active panel
15969     if ( active[ 0 ] === this.active[ 0 ] ) {
15970     return;
15971     }
15972    
15973     // trying to collapse, simulate a click on the current active header
15974     if ( !active.length ) {
15975     active = this.active;
15976     }
15977    
15978     anchor = active.find( ".ui-tabs-anchor" )[ 0 ];
15979     this._eventHandler({
15980     target: anchor,
15981     currentTarget: anchor,
15982     preventDefault: $.noop
15983     });
15984     },
15985    
15986     _findActive: function( index ) {
15987     return index === false ? $() : this.tabs.eq( index );
15988     },
15989    
15990     _getIndex: function( index ) {
15991     // meta-function to give users option to provide a href string instead of a numerical index.
15992     if ( typeof index === "string" ) {
15993     index = this.anchors.index( this.anchors.filter( "[href$='" + index + "']" ) );
15994     }
15995    
15996     return index;
15997     },
15998    
15999     _destroy: function() {
16000     if ( this.xhr ) {
16001     this.xhr.abort();
16002     }
16003    
16004     this.element.removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" );
16005    
16006     this.tablist
16007     .removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" )
16008     .removeAttr( "role" );
16009    
16010     this.anchors
16011     .removeClass( "ui-tabs-anchor" )
16012     .removeAttr( "role" )
16013     .removeAttr( "tabIndex" )
16014     .removeUniqueId();
16015    
16016     this.tablist.unbind( this.eventNamespace );
16017    
16018     this.tabs.add( this.panels ).each(function() {
16019     if ( $.data( this, "ui-tabs-destroy" ) ) {
16020     $( this ).remove();
16021     } else {
16022     $( this )
16023     .removeClass( "ui-state-default ui-state-active ui-state-disabled " +
16024     "ui-corner-top ui-corner-bottom ui-widget-content ui-tabs-active ui-tabs-panel" )
16025     .removeAttr( "tabIndex" )
16026     .removeAttr( "aria-live" )
16027     .removeAttr( "aria-busy" )
16028     .removeAttr( "aria-selected" )
16029     .removeAttr( "aria-labelledby" )
16030     .removeAttr( "aria-hidden" )
16031     .removeAttr( "aria-expanded" )
16032     .removeAttr( "role" );
16033     }
16034     });
16035    
16036     this.tabs.each(function() {
16037     var li = $( this ),
16038     prev = li.data( "ui-tabs-aria-controls" );
16039     if ( prev ) {
16040     li
16041     .attr( "aria-controls", prev )
16042     .removeData( "ui-tabs-aria-controls" );
16043     } else {
16044     li.removeAttr( "aria-controls" );
16045     }
16046     });
16047    
16048     this.panels.show();
16049    
16050     if ( this.options.heightStyle !== "content" ) {
16051     this.panels.css( "height", "" );
16052     }
16053     },
16054    
16055     enable: function( index ) {
16056     var disabled = this.options.disabled;
16057     if ( disabled === false ) {
16058     return;
16059     }
16060    
16061     if ( index === undefined ) {
16062     disabled = false;
16063     } else {
16064     index = this._getIndex( index );
16065     if ( $.isArray( disabled ) ) {
16066     disabled = $.map( disabled, function( num ) {
16067     return num !== index ? num : null;
16068     });
16069     } else {
16070     disabled = $.map( this.tabs, function( li, num ) {
16071     return num !== index ? num : null;
16072     });
16073     }
16074     }
16075     this._setupDisabled( disabled );
16076     },
16077    
16078     disable: function( index ) {
16079     var disabled = this.options.disabled;
16080     if ( disabled === true ) {
16081     return;
16082     }
16083    
16084     if ( index === undefined ) {
16085     disabled = true;
16086     } else {
16087     index = this._getIndex( index );
16088     if ( $.inArray( index, disabled ) !== -1 ) {
16089     return;
16090     }
16091     if ( $.isArray( disabled ) ) {
16092     disabled = $.merge( [ index ], disabled ).sort();
16093     } else {
16094     disabled = [ index ];
16095     }
16096     }
16097     this._setupDisabled( disabled );
16098     },
16099    
16100     load: function( index, event ) {
16101     index = this._getIndex( index );
16102     var that = this,
16103     tab = this.tabs.eq( index ),
16104     anchor = tab.find( ".ui-tabs-anchor" ),
16105     panel = this._getPanelForTab( tab ),
16106     eventData = {
16107     tab: tab,
16108     panel: panel
16109     },
16110     complete = function( jqXHR, status ) {
16111     if ( status === "abort" ) {
16112     that.panels.stop( false, true );
16113     }
16114    
16115     tab.removeClass( "ui-tabs-loading" );
16116     panel.removeAttr( "aria-busy" );
16117    
16118     if ( jqXHR === that.xhr ) {
16119     delete that.xhr;
16120     }
16121     };
16122    
16123     // not remote
16124     if ( this._isLocal( anchor[ 0 ] ) ) {
16125     return;
16126     }
16127    
16128     this.xhr = $.ajax( this._ajaxSettings( anchor, event, eventData ) );
16129    
16130     // support: jQuery <1.8
16131     // jQuery <1.8 returns false if the request is canceled in beforeSend,
16132     // but as of 1.8, $.ajax() always returns a jqXHR object.
16133     if ( this.xhr && this.xhr.statusText !== "canceled" ) {
16134     tab.addClass( "ui-tabs-loading" );
16135     panel.attr( "aria-busy", "true" );
16136    
16137     this.xhr
16138     .done(function( response, status, jqXHR ) {
16139     // support: jQuery <1.8
16140     // http://bugs.jquery.com/ticket/11778
16141     setTimeout(function() {
16142     panel.html( response );
16143     that._trigger( "load", event, eventData );
16144    
16145     complete( jqXHR, status );
16146     }, 1 );
16147     })
16148     .fail(function( jqXHR, status ) {
16149     // support: jQuery <1.8
16150     // http://bugs.jquery.com/ticket/11778
16151     setTimeout(function() {
16152     complete( jqXHR, status );
16153     }, 1 );
16154     });
16155     }
16156     },
16157    
16158     _ajaxSettings: function( anchor, event, eventData ) {
16159     var that = this;
16160     return {
16161     url: anchor.attr( "href" ),
16162     beforeSend: function( jqXHR, settings ) {
16163     return that._trigger( "beforeLoad", event,
16164     $.extend( { jqXHR: jqXHR, ajaxSettings: settings }, eventData ) );
16165     }
16166     };
16167     },
16168    
16169     _getPanelForTab: function( tab ) {
16170     var id = $( tab ).attr( "aria-controls" );
16171     return this.element.find( this._sanitizeSelector( "#" + id ) );
16172     }
16173     });
16174    
16175    
16176     /*!
16177     * jQuery UI Tooltip 1.11.4
16178     * http://jqueryui.com
16179     *
16180     * Copyright jQuery Foundation and other contributors
16181     * Released under the MIT license.
16182     * http://jquery.org/license
16183     *
16184     * http://api.jqueryui.com/tooltip/
16185     */
16186    
16187    
16188     var tooltip = $.widget( "ui.tooltip", {
16189     version: "1.11.4",
16190     options: {
16191     content: function() {
16192     // support: IE<9, Opera in jQuery <1.7
16193     // .text() can't accept undefined, so coerce to a string
16194     var title = $( this ).attr( "title" ) || "";
16195     // Escape title, since we're going from an attribute to raw HTML
16196     //return $( "<a>" ).text( title ).html();
16197     // Christian Schoenebeck: don't escape, interpret as HTML so we can add markup in the "title" attribte
16198     var html = $.parseHTML(title);
16199     return $( "<a>" ).append( html );
16200     },
16201     hide: true,
16202     // Disabled elements have inconsistent behavior across browsers (#8661)
16203     items: "[title]:not([disabled])",
16204     position: {
16205 schoenebeck 3275 my: "left-40 top+9",
16206     at: "center bottom",
16207 schoenebeck 2732 collision: "flipfit flip"
16208     },
16209     show: true,
16210     tooltipClass: null,
16211     track: false,
16212    
16213     // callbacks
16214     close: null,
16215     open: null
16216     },
16217    
16218     _addDescribedBy: function( elem, id ) {
16219     var describedby = (elem.attr( "aria-describedby" ) || "").split( /\s+/ );
16220     describedby.push( id );
16221     elem
16222     .data( "ui-tooltip-id", id )
16223     .attr( "aria-describedby", $.trim( describedby.join( " " ) ) );
16224     },
16225    
16226     _removeDescribedBy: function( elem ) {
16227     var id = elem.data( "ui-tooltip-id" ),
16228     describedby = (elem.attr( "aria-describedby" ) || "").split( /\s+/ ),
16229     index = $.inArray( id, describedby );
16230    
16231     if ( index !== -1 ) {
16232     describedby.splice( index, 1 );
16233     }
16234    
16235     elem.removeData( "ui-tooltip-id" );
16236     describedby = $.trim( describedby.join( " " ) );
16237     if ( describedby ) {
16238     elem.attr( "aria-describedby", describedby );
16239     } else {
16240     elem.removeAttr( "aria-describedby" );
16241     }
16242     },
16243    
16244     _create: function() {
16245     this._on({
16246     mouseover: "open",
16247     focusin: "open"
16248     });
16249    
16250     // IDs of generated tooltips, needed for destroy
16251     this.tooltips = {};
16252    
16253     // IDs of parent tooltips where we removed the title attribute
16254     this.parents = {};
16255    
16256     if ( this.options.disabled ) {
16257     this._disable();
16258     }
16259    
16260     // Append the aria-live region so tooltips announce correctly
16261     this.liveRegion = $( "<div>" )
16262     .attr({
16263     role: "log",
16264     "aria-live": "assertive",
16265     "aria-relevant": "additions"
16266     })
16267     .addClass( "ui-helper-hidden-accessible" )
16268     .appendTo( this.document[ 0 ].body );
16269     },
16270    
16271     _setOption: function( key, value ) {
16272     var that = this;
16273    
16274     if ( key === "disabled" ) {
16275     this[ value ? "_disable" : "_enable" ]();
16276     this.options[ key ] = value;
16277     // disable element style changes
16278     return;
16279     }
16280    
16281     this._super( key, value );
16282    
16283     if ( key === "content" ) {
16284     $.each( this.tooltips, function( id, tooltipData ) {
16285     that._updateContent( tooltipData.element );
16286     });
16287     }
16288     },
16289    
16290     _disable: function() {
16291     var that = this;
16292    
16293     // close open tooltips
16294     $.each( this.tooltips, function( id, tooltipData ) {
16295     var event = $.Event( "blur" );
16296     event.target = event.currentTarget = tooltipData.element[ 0 ];
16297     that.close( event, true );
16298     });
16299    
16300     // remove title attributes to prevent native tooltips
16301     this.element.find( this.options.items ).addBack().each(function() {
16302     var element = $( this );
16303     if ( element.is( "[title]" ) ) {
16304     element
16305     .data( "ui-tooltip-title", element.attr( "title" ) )
16306     .removeAttr( "title" );
16307     }
16308     });
16309     },
16310    
16311     _enable: function() {
16312     // restore title attributes
16313     this.element.find( this.options.items ).addBack().each(function() {
16314     var element = $( this );
16315     if ( element.data( "ui-tooltip-title" ) ) {
16316     element.attr( "title", element.data( "ui-tooltip-title" ) );
16317     }
16318     });
16319     },
16320    
16321     open: function( event ) {
16322     var that = this,
16323     target = $( event ? event.target : this.element )
16324     // we need closest here due to mouseover bubbling,
16325     // but always pointing at the same event target
16326     .closest( this.options.items );
16327    
16328     // No element to show a tooltip for or the tooltip is already open
16329     if ( !target.length || target.data( "ui-tooltip-id" ) ) {
16330     return;
16331     }
16332    
16333     if ( target.attr( "title" ) ) {
16334     target.data( "ui-tooltip-title", target.attr( "title" ) );
16335     }
16336    
16337     target.data( "ui-tooltip-open", true );
16338    
16339     // kill parent tooltips, custom or native, for hover
16340     if ( event && event.type === "mouseover" ) {
16341     target.parents().each(function() {
16342     var parent = $( this ),
16343     blurEvent;
16344     if ( parent.data( "ui-tooltip-open" ) ) {
16345     blurEvent = $.Event( "blur" );
16346     blurEvent.target = blurEvent.currentTarget = this;
16347     that.close( blurEvent, true );
16348     }
16349     if ( parent.attr( "title" ) ) {
16350     parent.uniqueId();
16351     that.parents[ this.id ] = {
16352     element: this,
16353     title: parent.attr( "title" )
16354     };
16355     parent.attr( "title", "" );
16356     }
16357     });
16358     }
16359    
16360     this._registerCloseHandlers( event, target );
16361     this._updateContent( target, event );
16362     },
16363    
16364     _updateContent: function( target, event ) {
16365     var content,
16366     contentOption = this.options.content,
16367     that = this,
16368     eventType = event ? event.type : null;
16369    
16370     if ( typeof contentOption === "string" ) {
16371     return this._open( event, target, contentOption );
16372     }
16373    
16374     content = contentOption.call( target[0], function( response ) {
16375    
16376     // IE may instantly serve a cached response for ajax requests
16377     // delay this call to _open so the other call to _open runs first
16378     that._delay(function() {
16379    
16380     // Ignore async response if tooltip was closed already
16381     if ( !target.data( "ui-tooltip-open" ) ) {
16382     return;
16383     }
16384    
16385     // jQuery creates a special event for focusin when it doesn't
16386     // exist natively. To improve performance, the native event
16387     // object is reused and the type is changed. Therefore, we can't
16388     // rely on the type being correct after the event finished
16389     // bubbling, so we set it back to the previous value. (#8740)
16390     if ( event ) {
16391     event.type = eventType;
16392     }
16393     this._open( event, target, response );
16394     });
16395     });
16396     if ( content ) {
16397     this._open( event, target, content );
16398     }
16399     },
16400    
16401     _open: function( event, target, content ) {
16402     var tooltipData, tooltip, delayedShow, a11yContent,
16403     positionOption = $.extend( {}, this.options.position );
16404    
16405     if ( !content ) {
16406     return;
16407     }
16408    
16409     // Content can be updated multiple times. If the tooltip already
16410     // exists, then just update the content and bail.
16411     tooltipData = this._find( target );
16412     if ( tooltipData ) {
16413     tooltipData.tooltip.find( ".ui-tooltip-content" ).html( content );
16414     return;
16415     }
16416    
16417     // if we have a title, clear it to prevent the native tooltip
16418     // we have to check first to avoid defining a title if none exists
16419     // (we don't want to cause an element to start matching [title])
16420     //
16421     // We use removeAttr only for key events, to allow IE to export the correct
16422     // accessible attributes. For mouse events, set to empty string to avoid
16423     // native tooltip showing up (happens only when removing inside mouseover).
16424     if ( target.is( "[title]" ) ) {
16425     if ( event && event.type === "mouseover" ) {
16426     target.attr( "title", "" );
16427     } else {
16428     target.removeAttr( "title" );
16429     }
16430     }
16431    
16432     tooltipData = this._tooltip( target );
16433     tooltip = tooltipData.tooltip;
16434     this._addDescribedBy( target, tooltip.attr( "id" ) );
16435     tooltip.find( ".ui-tooltip-content" ).html( content );
16436    
16437     // Support: Voiceover on OS X, JAWS on IE <= 9
16438     // JAWS announces deletions even when aria-relevant="additions"
16439     // Voiceover will sometimes re-read the entire log region's contents from the beginning
16440     this.liveRegion.children().hide();
16441     if ( content.clone ) {
16442     a11yContent = content.clone();
16443     a11yContent.removeAttr( "id" ).find( "[id]" ).removeAttr( "id" );
16444     } else {
16445     a11yContent = content;
16446     }
16447     $( "<div>" ).html( a11yContent ).appendTo( this.liveRegion );
16448    
16449     function position( event ) {
16450     positionOption.of = event;
16451     if ( tooltip.is( ":hidden" ) ) {
16452     return;
16453     }
16454     tooltip.position( positionOption );
16455     }
16456     if ( this.options.track && event && /^mouse/.test( event.type ) ) {
16457     this._on( this.document, {
16458     mousemove: position
16459     });
16460     // trigger once to override element-relative positioning
16461     position( event );
16462     } else {
16463     tooltip.position( $.extend({
16464     of: target
16465     }, this.options.position ) );
16466     }
16467    
16468     tooltip.hide();
16469    
16470     this._show( tooltip, this.options.show );
16471     // Handle tracking tooltips that are shown with a delay (#8644). As soon
16472     // as the tooltip is visible, position the tooltip using the most recent
16473     // event.
16474     if ( this.options.show && this.options.show.delay ) {
16475     delayedShow = this.delayedShow = setInterval(function() {
16476     if ( tooltip.is( ":visible" ) ) {
16477     position( positionOption.of );
16478     clearInterval( delayedShow );
16479     }
16480     }, $.fx.interval );
16481     }
16482    
16483     this._trigger( "open", event, { tooltip: tooltip } );
16484     },
16485    
16486     _registerCloseHandlers: function( event, target ) {
16487     var events = {
16488     keyup: function( event ) {
16489     if ( event.keyCode === $.ui.keyCode.ESCAPE ) {
16490     var fakeEvent = $.Event(event);
16491     fakeEvent.currentTarget = target[0];
16492     this.close( fakeEvent, true );
16493     }
16494     }
16495     };
16496    
16497     // Only bind remove handler for delegated targets. Non-delegated
16498     // tooltips will handle this in destroy.
16499     if ( target[ 0 ] !== this.element[ 0 ] ) {
16500     events.remove = function() {
16501     this._removeTooltip( this._find( target ).tooltip );
16502     };
16503     }
16504    
16505     if ( !event || event.type === "mouseover" ) {
16506     events.mouseleave = "close";
16507     }
16508     if ( !event || event.type === "focusin" ) {
16509     events.focusout = "close";
16510     }
16511     this._on( true, target, events );
16512     },
16513    
16514     close: function( event ) {
16515     var tooltip,
16516     that = this,
16517     target = $( event ? event.currentTarget : this.element ),
16518     tooltipData = this._find( target );
16519    
16520     // The tooltip may already be closed
16521     if ( !tooltipData ) {
16522    
16523     // We set ui-tooltip-open immediately upon open (in open()), but only set the
16524     // additional data once there's actually content to show (in _open()). So even if the
16525     // tooltip doesn't have full data, we always remove ui-tooltip-open in case we're in
16526     // the period between open() and _open().
16527     target.removeData( "ui-tooltip-open" );
16528     return;
16529     }
16530    
16531     tooltip = tooltipData.tooltip;
16532    
16533     // disabling closes the tooltip, so we need to track when we're closing
16534     // to avoid an infinite loop in case the tooltip becomes disabled on close
16535     if ( tooltipData.closing ) {
16536     return;
16537     }
16538    
16539     // Clear the interval for delayed tracking tooltips
16540     clearInterval( this.delayedShow );
16541    
16542     // only set title if we had one before (see comment in _open())
16543     // If the title attribute has changed since open(), don't restore
16544     if ( target.data( "ui-tooltip-title" ) && !target.attr( "title" ) ) {
16545     target.attr( "title", target.data( "ui-tooltip-title" ) );
16546     }
16547    
16548     this._removeDescribedBy( target );
16549    
16550     tooltipData.hiding = true;
16551     tooltip.stop( true );
16552     this._hide( tooltip, this.options.hide, function() {
16553     that._removeTooltip( $( this ) );
16554     });
16555    
16556     target.removeData( "ui-tooltip-open" );
16557     this._off( target, "mouseleave focusout keyup" );
16558    
16559     // Remove 'remove' binding only on delegated targets
16560     if ( target[ 0 ] !== this.element[ 0 ] ) {
16561     this._off( target, "remove" );
16562     }
16563     this._off( this.document, "mousemove" );
16564    
16565     if ( event && event.type === "mouseleave" ) {
16566     $.each( this.parents, function( id, parent ) {
16567     $( parent.element ).attr( "title", parent.title );
16568     delete that.parents[ id ];
16569     });
16570     }
16571    
16572     tooltipData.closing = true;
16573     this._trigger( "close", event, { tooltip: tooltip } );
16574     if ( !tooltipData.hiding ) {
16575     tooltipData.closing = false;
16576     }
16577     },
16578    
16579     _tooltip: function( element ) {
16580     var tooltip = $( "<div>" )
16581     .attr( "role", "tooltip" )
16582     .addClass( "ui-tooltip ui-widget ui-corner-all ui-widget-content " +
16583     ( this.options.tooltipClass || "" ) ),
16584     id = tooltip.uniqueId().attr( "id" );
16585    
16586     $( "<div>" )
16587     .addClass( "ui-tooltip-content" )
16588     .appendTo( tooltip );
16589    
16590     tooltip.appendTo( this.document[0].body );
16591    
16592     return this.tooltips[ id ] = {
16593     element: element,
16594     tooltip: tooltip
16595     };
16596     },
16597    
16598     _find: function( target ) {
16599     var id = target.data( "ui-tooltip-id" );
16600     return id ? this.tooltips[ id ] : null;
16601     },
16602    
16603     _removeTooltip: function( tooltip ) {
16604     tooltip.remove();
16605     delete this.tooltips[ tooltip.attr( "id" ) ];
16606     },
16607    
16608     _destroy: function() {
16609     var that = this;
16610    
16611     // close open tooltips
16612     $.each( this.tooltips, function( id, tooltipData ) {
16613     // Delegate to close method to handle common cleanup
16614     var event = $.Event( "blur" ),
16615     element = tooltipData.element;
16616     event.target = event.currentTarget = element[ 0 ];
16617     that.close( event, true );
16618    
16619     // Remove immediately; destroying an open tooltip doesn't use the
16620     // hide animation
16621     $( "#" + id ).remove();
16622    
16623     // Restore the title
16624     if ( element.data( "ui-tooltip-title" ) ) {
16625     // If the title attribute has changed since open(), don't restore
16626     if ( !element.attr( "title" ) ) {
16627     element.attr( "title", element.data( "ui-tooltip-title" ) );
16628     }
16629     element.removeData( "ui-tooltip-title" );
16630     }
16631     });
16632     this.liveRegion.remove();
16633     }
16634     });
16635    
16636    
16637    
16638     }));

  ViewVC Help
Powered by ViewVC