1 /*! jQuery UI - v1.11.0 - 2014-06-26
3 * Includes: core.js, widget.js, mouse.js, position.js, draggable.js, droppable.js, resizable.js, selectable.js, sortable.js, accordion.js, autocomplete.js, button.js, datepicker.js, dialog.js, menu.js, progressbar.js, selectmenu.js, slider.js, spinner.js, tabs.js, tooltip.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
4 * Copyright 2014 jQuery Foundation and other contributors; Licensed MIT */
7 if ( typeof define === "function" && define.amd ) {
9 // AMD. Register as an anonymous module.
10 define([ "jquery" ], factory );
18 * jQuery UI Core 1.11.0
21 * Copyright 2014 jQuery Foundation and other contributors
22 * Released under the MIT license.
23 * http://jquery.org/license
25 * http://api.jqueryui.com/category/ui-core/
29 // $.ui might exist from components with no dependencies, e.g., $.ui.position
57 scrollParent: function() {
58 var position = this.css( "position" ),
59 excludeStaticParent = position === "absolute",
60 scrollParent = this.parents().filter( function() {
61 var parent = $( this );
62 if ( excludeStaticParent && parent.css( "position" ) === "static" ) {
65 return (/(auto|scroll)/).test( parent.css( "overflow" ) + parent.css( "overflow-y" ) + parent.css( "overflow-x" ) );
68 return position === "fixed" || !scrollParent.length ? $( this[ 0 ].ownerDocument || document ) : scrollParent;
71 uniqueId: (function() {
75 return this.each(function() {
77 this.id = "ui-id-" + ( ++uuid );
83 removeUniqueId: function() {
84 return this.each(function() {
85 if ( /^ui-id-\d+$/.test( this.id ) ) {
86 $( this ).removeAttr( "id" );
93 function focusable( element, isTabIndexNotNaN ) {
94 var map, mapName, img,
95 nodeName = element.nodeName.toLowerCase();
96 if ( "area" === nodeName ) {
97 map = element.parentNode;
99 if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
102 img = $( "img[usemap=#" + mapName + "]" )[0];
103 return !!img && visible( img );
105 return ( /input|select|textarea|button|object/.test( nodeName ) ?
108 element.href || isTabIndexNotNaN :
110 // the element and all of its ancestors must be visible
114 function visible( element ) {
115 return $.expr.filters.visible( element ) &&
116 !$( element ).parents().addBack().filter(function() {
117 return $.css( this, "visibility" ) === "hidden";
121 $.extend( $.expr[ ":" ], {
122 data: $.expr.createPseudo ?
123 $.expr.createPseudo(function( dataName ) {
124 return function( elem ) {
125 return !!$.data( elem, dataName );
128 // support: jQuery <1.8
129 function( elem, i, match ) {
130 return !!$.data( elem, match[ 3 ] );
133 focusable: function( element ) {
134 return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) );
137 tabbable: function( element ) {
138 var tabIndex = $.attr( element, "tabindex" ),
139 isTabIndexNaN = isNaN( tabIndex );
140 return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN );
144 // support: jQuery <1.8
145 if ( !$( "<a>" ).outerWidth( 1 ).jquery ) {
146 $.each( [ "Width", "Height" ], function( i, name ) {
147 var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
148 type = name.toLowerCase(),
150 innerWidth: $.fn.innerWidth,
151 innerHeight: $.fn.innerHeight,
152 outerWidth: $.fn.outerWidth,
153 outerHeight: $.fn.outerHeight
156 function reduce( elem, size, border, margin ) {
157 $.each( side, function() {
158 size -= parseFloat( $.css( elem, "padding" + this ) ) || 0;
160 size -= parseFloat( $.css( elem, "border" + this + "Width" ) ) || 0;
163 size -= parseFloat( $.css( elem, "margin" + this ) ) || 0;
169 $.fn[ "inner" + name ] = function( size ) {
170 if ( size === undefined ) {
171 return orig[ "inner" + name ].call( this );
174 return this.each(function() {
175 $( this ).css( type, reduce( this, size ) + "px" );
179 $.fn[ "outer" + name] = function( size, margin ) {
180 if ( typeof size !== "number" ) {
181 return orig[ "outer" + name ].call( this, size );
184 return this.each(function() {
185 $( this).css( type, reduce( this, size, true, margin ) + "px" );
191 // support: jQuery <1.8
192 if ( !$.fn.addBack ) {
193 $.fn.addBack = function( selector ) {
194 return this.add( selector == null ?
195 this.prevObject : this.prevObject.filter( selector )
200 // support: jQuery 1.6.1, 1.6.2 (http://bugs.jquery.com/ticket/9413)
201 if ( $( "<a>" ).data( "a-b", "a" ).removeData( "a-b" ).data( "a-b" ) ) {
202 $.fn.removeData = (function( removeData ) {
203 return function( key ) {
204 if ( arguments.length ) {
205 return removeData.call( this, $.camelCase( key ) );
207 return removeData.call( this );
210 })( $.fn.removeData );
214 $.ui.ie = !!/msie [\w.]+/.exec( navigator.userAgent.toLowerCase() );
217 focus: (function( orig ) {
218 return function( delay, fn ) {
219 return typeof delay === "number" ?
220 this.each(function() {
222 setTimeout(function() {
229 orig.apply( this, arguments );
233 disableSelection: (function() {
234 var eventType = "onselectstart" in document.createElement( "div" ) ?
239 return this.bind( eventType + ".ui-disableSelection", function( event ) {
240 event.preventDefault();
245 enableSelection: function() {
246 return this.unbind( ".ui-disableSelection" );
249 zIndex: function( zIndex ) {
250 if ( zIndex !== undefined ) {
251 return this.css( "zIndex", zIndex );
255 var elem = $( this[ 0 ] ), position, value;
256 while ( elem.length && elem[ 0 ] !== document ) {
257 // Ignore z-index if position is set to a value where z-index is ignored by the browser
258 // This makes behavior of this function consistent across browsers
259 // WebKit always returns auto if the element is positioned
260 position = elem.css( "position" );
261 if ( position === "absolute" || position === "relative" || position === "fixed" ) {
262 // IE returns 0 when zIndex is not specified
263 // other browsers return a string
264 // we ignore the case of nested elements with an explicit value of 0
265 // <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
266 value = parseInt( elem.css( "zIndex" ), 10 );
267 if ( !isNaN( value ) && value !== 0 ) {
271 elem = elem.parent();
279 // $.ui.plugin is deprecated. Use $.widget() extensions instead.
281 add: function( module, option, set ) {
283 proto = $.ui[ module ].prototype;
285 proto.plugins[ i ] = proto.plugins[ i ] || [];
286 proto.plugins[ i ].push( [ option, set[ i ] ] );
289 call: function( instance, name, args, allowDisconnected ) {
291 set = instance.plugins[ name ];
297 if ( !allowDisconnected && ( !instance.element[ 0 ].parentNode || instance.element[ 0 ].parentNode.nodeType === 11 ) ) {
301 for ( i = 0; i < set.length; i++ ) {
302 if ( instance.options[ set[ i ][ 0 ] ] ) {
303 set[ i ][ 1 ].apply( instance.element, args );
311 * jQuery UI Widget 1.11.0
312 * http://jqueryui.com
314 * Copyright 2014 jQuery Foundation and other contributors
315 * Released under the MIT license.
316 * http://jquery.org/license
318 * http://api.jqueryui.com/jQuery.widget/
323 widget_slice = Array.prototype.slice;
325 $.cleanData = (function( orig ) {
326 return function( elems ) {
327 for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
329 $( elem ).triggerHandler( "remove" );
330 // http://bugs.jquery.com/ticket/8235
337 $.widget = function( name, base, prototype ) {
338 var fullName, existingConstructor, constructor, basePrototype,
339 // proxiedPrototype allows the provided prototype to remain unmodified
340 // so that it can be used as a mixin for multiple widgets (#8876)
341 proxiedPrototype = {},
342 namespace = name.split( "." )[ 0 ];
344 name = name.split( "." )[ 1 ];
345 fullName = namespace + "-" + name;
352 // create selector for plugin
353 $.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) {
354 return !!$.data( elem, fullName );
357 $[ namespace ] = $[ namespace ] || {};
358 existingConstructor = $[ namespace ][ name ];
359 constructor = $[ namespace ][ name ] = function( options, element ) {
360 // allow instantiation without "new" keyword
361 if ( !this._createWidget ) {
362 return new constructor( options, element );
365 // allow instantiation without initializing for simple inheritance
366 // must use "new" keyword (the code above always passes args)
367 if ( arguments.length ) {
368 this._createWidget( options, element );
371 // extend with the existing constructor to carry over any static properties
372 $.extend( constructor, existingConstructor, {
373 version: prototype.version,
374 // copy the object used to create the prototype in case we need to
375 // redefine the widget later
376 _proto: $.extend( {}, prototype ),
377 // track widgets that inherit from this widget in case this widget is
378 // redefined after a widget inherits from it
379 _childConstructors: []
382 basePrototype = new base();
383 // we need to make the options hash a property directly on the new instance
384 // otherwise we'll modify the options hash on the prototype that we're
386 basePrototype.options = $.widget.extend( {}, basePrototype.options );
387 $.each( prototype, function( prop, value ) {
388 if ( !$.isFunction( value ) ) {
389 proxiedPrototype[ prop ] = value;
392 proxiedPrototype[ prop ] = (function() {
393 var _super = function() {
394 return base.prototype[ prop ].apply( this, arguments );
396 _superApply = function( args ) {
397 return base.prototype[ prop ].apply( this, args );
400 var __super = this._super,
401 __superApply = this._superApply,
404 this._super = _super;
405 this._superApply = _superApply;
407 returnValue = value.apply( this, arguments );
409 this._super = __super;
410 this._superApply = __superApply;
416 constructor.prototype = $.widget.extend( basePrototype, {
417 // TODO: remove support for widgetEventPrefix
418 // always use the name + a colon as the prefix, e.g., draggable:start
419 // don't prefix for widgets that aren't DOM-based
420 widgetEventPrefix: existingConstructor ? (basePrototype.widgetEventPrefix || name) : name
421 }, proxiedPrototype, {
422 constructor: constructor,
423 namespace: namespace,
425 widgetFullName: fullName
428 // If this widget is being redefined then we need to find all widgets that
429 // are inheriting from it and redefine all of them so that they inherit from
430 // the new version of this widget. We're essentially trying to replace one
431 // level in the prototype chain.
432 if ( existingConstructor ) {
433 $.each( existingConstructor._childConstructors, function( i, child ) {
434 var childPrototype = child.prototype;
436 // redefine the child widget using the same prototype that was
437 // originally used, but inherit from the new version of the base
438 $.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, child._proto );
440 // remove the list of existing child constructors from the old constructor
441 // so the old child constructors can be garbage collected
442 delete existingConstructor._childConstructors;
444 base._childConstructors.push( constructor );
447 $.widget.bridge( name, constructor );
452 $.widget.extend = function( target ) {
453 var input = widget_slice.call( arguments, 1 ),
455 inputLength = input.length,
458 for ( ; inputIndex < inputLength; inputIndex++ ) {
459 for ( key in input[ inputIndex ] ) {
460 value = input[ inputIndex ][ key ];
461 if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) {
463 if ( $.isPlainObject( value ) ) {
464 target[ key ] = $.isPlainObject( target[ key ] ) ?
465 $.widget.extend( {}, target[ key ], value ) :
466 // Don't extend strings, arrays, etc. with objects
467 $.widget.extend( {}, value );
468 // Copy everything else by reference
470 target[ key ] = value;
478 $.widget.bridge = function( name, object ) {
479 var fullName = object.prototype.widgetFullName || name;
480 $.fn[ name ] = function( options ) {
481 var isMethodCall = typeof options === "string",
482 args = widget_slice.call( arguments, 1 ),
485 // allow multiple hashes to be passed on init
486 options = !isMethodCall && args.length ?
487 $.widget.extend.apply( null, [ options ].concat(args) ) :
490 if ( isMethodCall ) {
491 this.each(function() {
493 instance = $.data( this, fullName );
494 if ( options === "instance" ) {
495 returnValue = instance;
499 return $.error( "cannot call methods on " + name + " prior to initialization; " +
500 "attempted to call method '" + options + "'" );
502 if ( !$.isFunction( instance[options] ) || options.charAt( 0 ) === "_" ) {
503 return $.error( "no such method '" + options + "' for " + name + " widget instance" );
505 methodValue = instance[ options ].apply( instance, args );
506 if ( methodValue !== instance && methodValue !== undefined ) {
507 returnValue = methodValue && methodValue.jquery ?
508 returnValue.pushStack( methodValue.get() ) :
514 this.each(function() {
515 var instance = $.data( this, fullName );
517 instance.option( options || {} );
518 if ( instance._init ) {
522 $.data( this, fullName, new object( options, this ) );
531 $.Widget = function( /* options, element */ ) {};
532 $.Widget._childConstructors = [];
534 $.Widget.prototype = {
535 widgetName: "widget",
536 widgetEventPrefix: "",
537 defaultElement: "<div>",
544 _createWidget: function( options, element ) {
545 element = $( element || this.defaultElement || this )[ 0 ];
546 this.element = $( element );
547 this.uuid = widget_uuid++;
548 this.eventNamespace = "." + this.widgetName + this.uuid;
549 this.options = $.widget.extend( {},
551 this._getCreateOptions(),
555 this.hoverable = $();
556 this.focusable = $();
558 if ( element !== this ) {
559 $.data( element, this.widgetFullName, this );
560 this._on( true, this.element, {
561 remove: function( event ) {
562 if ( event.target === element ) {
567 this.document = $( element.style ?
568 // element within the document
569 element.ownerDocument :
570 // element is window or document
571 element.document || element );
572 this.window = $( this.document[0].defaultView || this.document[0].parentWindow );
576 this._trigger( "create", null, this._getCreateEventData() );
579 _getCreateOptions: $.noop,
580 _getCreateEventData: $.noop,
584 destroy: function() {
586 // we can probably remove the unbind calls in 2.0
587 // all event bindings should go through this._on()
589 .unbind( this.eventNamespace )
590 .removeData( this.widgetFullName )
591 // support: jquery <1.6.3
592 // http://bugs.jquery.com/ticket/9413
593 .removeData( $.camelCase( this.widgetFullName ) );
595 .unbind( this.eventNamespace )
596 .removeAttr( "aria-disabled" )
598 this.widgetFullName + "-disabled " +
599 "ui-state-disabled" );
601 // clean up events and states
602 this.bindings.unbind( this.eventNamespace );
603 this.hoverable.removeClass( "ui-state-hover" );
604 this.focusable.removeClass( "ui-state-focus" );
612 option: function( key, value ) {
618 if ( arguments.length === 0 ) {
619 // don't return a reference to the internal hash
620 return $.widget.extend( {}, this.options );
623 if ( typeof key === "string" ) {
624 // handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
626 parts = key.split( "." );
628 if ( parts.length ) {
629 curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );
630 for ( i = 0; i < parts.length - 1; i++ ) {
631 curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};
632 curOption = curOption[ parts[ i ] ];
635 if ( arguments.length === 1 ) {
636 return curOption[ key ] === undefined ? null : curOption[ key ];
638 curOption[ key ] = value;
640 if ( arguments.length === 1 ) {
641 return this.options[ key ] === undefined ? null : this.options[ key ];
643 options[ key ] = value;
647 this._setOptions( options );
651 _setOptions: function( options ) {
654 for ( key in options ) {
655 this._setOption( key, options[ key ] );
660 _setOption: function( key, value ) {
661 this.options[ key ] = value;
663 if ( key === "disabled" ) {
665 .toggleClass( this.widgetFullName + "-disabled", !!value );
667 // If the widget is becoming disabled, then nothing is interactive
669 this.hoverable.removeClass( "ui-state-hover" );
670 this.focusable.removeClass( "ui-state-focus" );
678 return this._setOptions({ disabled: false });
680 disable: function() {
681 return this._setOptions({ disabled: true });
684 _on: function( suppressDisabledCheck, element, handlers ) {
688 // no suppressDisabledCheck flag, shuffle arguments
689 if ( typeof suppressDisabledCheck !== "boolean" ) {
691 element = suppressDisabledCheck;
692 suppressDisabledCheck = false;
695 // no element argument, shuffle and use this.element
698 element = this.element;
699 delegateElement = this.widget();
701 element = delegateElement = $( element );
702 this.bindings = this.bindings.add( element );
705 $.each( handlers, function( event, handler ) {
706 function handlerProxy() {
707 // allow widgets to customize the disabled handling
708 // - disabled as an array instead of boolean
709 // - disabled class as method for disabling individual parts
710 if ( !suppressDisabledCheck &&
711 ( instance.options.disabled === true ||
712 $( this ).hasClass( "ui-state-disabled" ) ) ) {
715 return ( typeof handler === "string" ? instance[ handler ] : handler )
716 .apply( instance, arguments );
719 // copy the guid so direct unbinding works
720 if ( typeof handler !== "string" ) {
721 handlerProxy.guid = handler.guid =
722 handler.guid || handlerProxy.guid || $.guid++;
725 var match = event.match( /^([\w:-]*)\s*(.*)$/ ),
726 eventName = match[1] + instance.eventNamespace,
729 delegateElement.delegate( selector, eventName, handlerProxy );
731 element.bind( eventName, handlerProxy );
736 _off: function( element, eventName ) {
737 eventName = (eventName || "").split( " " ).join( this.eventNamespace + " " ) + this.eventNamespace;
738 element.unbind( eventName ).undelegate( eventName );
741 _delay: function( handler, delay ) {
742 function handlerProxy() {
743 return ( typeof handler === "string" ? instance[ handler ] : handler )
744 .apply( instance, arguments );
747 return setTimeout( handlerProxy, delay || 0 );
750 _hoverable: function( element ) {
751 this.hoverable = this.hoverable.add( element );
753 mouseenter: function( event ) {
754 $( event.currentTarget ).addClass( "ui-state-hover" );
756 mouseleave: function( event ) {
757 $( event.currentTarget ).removeClass( "ui-state-hover" );
762 _focusable: function( element ) {
763 this.focusable = this.focusable.add( element );
765 focusin: function( event ) {
766 $( event.currentTarget ).addClass( "ui-state-focus" );
768 focusout: function( event ) {
769 $( event.currentTarget ).removeClass( "ui-state-focus" );
774 _trigger: function( type, event, data ) {
776 callback = this.options[ type ];
779 event = $.Event( event );
780 event.type = ( type === this.widgetEventPrefix ?
782 this.widgetEventPrefix + type ).toLowerCase();
783 // the original event may come from any element
784 // so we need to reset the target on the new event
785 event.target = this.element[ 0 ];
787 // copy original event properties over to the new event
788 orig = event.originalEvent;
790 for ( prop in orig ) {
791 if ( !( prop in event ) ) {
792 event[ prop ] = orig[ prop ];
797 this.element.trigger( event, data );
798 return !( $.isFunction( callback ) &&
799 callback.apply( this.element[0], [ event ].concat( data ) ) === false ||
800 event.isDefaultPrevented() );
804 $.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {
805 $.Widget.prototype[ "_" + method ] = function( element, options, callback ) {
806 if ( typeof options === "string" ) {
807 options = { effect: options };
810 effectName = !options ?
812 options === true || typeof options === "number" ?
814 options.effect || defaultEffect;
815 options = options || {};
816 if ( typeof options === "number" ) {
817 options = { duration: options };
819 hasOptions = !$.isEmptyObject( options );
820 options.complete = callback;
821 if ( options.delay ) {
822 element.delay( options.delay );
824 if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) {
825 element[ method ]( options );
826 } else if ( effectName !== method && element[ effectName ] ) {
827 element[ effectName ]( options.duration, options.easing, callback );
829 element.queue(function( next ) {
830 $( this )[ method ]();
832 callback.call( element[ 0 ] );
840 var widget = $.widget;
844 * jQuery UI Mouse 1.11.0
845 * http://jqueryui.com
847 * Copyright 2014 jQuery Foundation and other contributors
848 * Released under the MIT license.
849 * http://jquery.org/license
851 * http://api.jqueryui.com/mouse/
855 var mouseHandled = false;
856 $( document ).mouseup( function() {
857 mouseHandled = false;
860 var mouse = $.widget("ui.mouse", {
863 cancel: "input,textarea,button,select,option",
867 _mouseInit: function() {
871 .bind("mousedown." + this.widgetName, function(event) {
872 return that._mouseDown(event);
874 .bind("click." + this.widgetName, function(event) {
875 if (true === $.data(event.target, that.widgetName + ".preventClickEvent")) {
876 $.removeData(event.target, that.widgetName + ".preventClickEvent");
877 event.stopImmediatePropagation();
882 this.started = false;
885 // TODO: make sure destroying one instance of mouse doesn't mess with
886 // other instances of mouse
887 _mouseDestroy: function() {
888 this.element.unbind("." + this.widgetName);
889 if ( this._mouseMoveDelegate ) {
891 .unbind("mousemove." + this.widgetName, this._mouseMoveDelegate)
892 .unbind("mouseup." + this.widgetName, this._mouseUpDelegate);
896 _mouseDown: function(event) {
897 // don't let more than one widget handle mouseStart
898 if ( mouseHandled ) {
902 // we may have missed mouseup (out of window)
903 (this._mouseStarted && this._mouseUp(event));
905 this._mouseDownEvent = event;
908 btnIsLeft = (event.which === 1),
909 // event.target.nodeName works around a bug in IE 8 with
910 // disabled inputs (#7620)
911 elIsCancel = (typeof this.options.cancel === "string" && event.target.nodeName ? $(event.target).closest(this.options.cancel).length : false);
912 if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
916 this.mouseDelayMet = !this.options.delay;
917 if (!this.mouseDelayMet) {
918 this._mouseDelayTimer = setTimeout(function() {
919 that.mouseDelayMet = true;
920 }, this.options.delay);
923 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
924 this._mouseStarted = (this._mouseStart(event) !== false);
925 if (!this._mouseStarted) {
926 event.preventDefault();
931 // Click event may never have fired (Gecko & Opera)
932 if (true === $.data(event.target, this.widgetName + ".preventClickEvent")) {
933 $.removeData(event.target, this.widgetName + ".preventClickEvent");
936 // these delegates are required to keep context
937 this._mouseMoveDelegate = function(event) {
938 return that._mouseMove(event);
940 this._mouseUpDelegate = function(event) {
941 return that._mouseUp(event);
945 .bind( "mousemove." + this.widgetName, this._mouseMoveDelegate )
946 .bind( "mouseup." + this.widgetName, this._mouseUpDelegate );
948 event.preventDefault();
954 _mouseMove: function(event) {
955 // IE mouseup check - mouseup happened when mouse was out of window
956 if ($.ui.ie && ( !document.documentMode || document.documentMode < 9 ) && !event.button) {
957 return this._mouseUp(event);
959 // Iframe mouseup check - mouseup occurred in another document
960 } else if ( !event.which ) {
961 return this._mouseUp( event );
964 if (this._mouseStarted) {
965 this._mouseDrag(event);
966 return event.preventDefault();
969 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
971 (this._mouseStart(this._mouseDownEvent, event) !== false);
972 (this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
975 return !this._mouseStarted;
978 _mouseUp: function(event) {
980 .unbind( "mousemove." + this.widgetName, this._mouseMoveDelegate )
981 .unbind( "mouseup." + this.widgetName, this._mouseUpDelegate );
983 if (this._mouseStarted) {
984 this._mouseStarted = false;
986 if (event.target === this._mouseDownEvent.target) {
987 $.data(event.target, this.widgetName + ".preventClickEvent", true);
990 this._mouseStop(event);
993 mouseHandled = false;
997 _mouseDistanceMet: function(event) {
999 Math.abs(this._mouseDownEvent.pageX - event.pageX),
1000 Math.abs(this._mouseDownEvent.pageY - event.pageY)
1001 ) >= this.options.distance
1005 _mouseDelayMet: function(/* event */) {
1006 return this.mouseDelayMet;
1009 // These are placeholder methods, to be overriden by extending plugin
1010 _mouseStart: function(/* event */) {},
1011 _mouseDrag: function(/* event */) {},
1012 _mouseStop: function(/* event */) {},
1013 _mouseCapture: function(/* event */) { return true; }
1018 * jQuery UI Position 1.11.0
1019 * http://jqueryui.com
1021 * Copyright 2014 jQuery Foundation and other contributors
1022 * Released under the MIT license.
1023 * http://jquery.org/license
1025 * http://api.jqueryui.com/position/
1032 var cachedScrollbarWidth, supportsOffsetFractions,
1036 rhorizontal = /left|center|right/,
1037 rvertical = /top|center|bottom/,
1038 roffset = /[\+\-]\d+(\.[\d]+)?%?/,
1041 _position = $.fn.position;
1043 function getOffsets( offsets, width, height ) {
1045 parseFloat( offsets[ 0 ] ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ),
1046 parseFloat( offsets[ 1 ] ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 )
1050 function parseCss( element, property ) {
1051 return parseInt( $.css( element, property ), 10 ) || 0;
1054 function getDimensions( elem ) {
1056 if ( raw.nodeType === 9 ) {
1058 width: elem.width(),
1059 height: elem.height(),
1060 offset: { top: 0, left: 0 }
1063 if ( $.isWindow( raw ) ) {
1065 width: elem.width(),
1066 height: elem.height(),
1067 offset: { top: elem.scrollTop(), left: elem.scrollLeft() }
1070 if ( raw.preventDefault ) {
1074 offset: { top: raw.pageY, left: raw.pageX }
1078 width: elem.outerWidth(),
1079 height: elem.outerHeight(),
1080 offset: elem.offset()
1085 scrollbarWidth: function() {
1086 if ( cachedScrollbarWidth !== undefined ) {
1087 return cachedScrollbarWidth;
1090 div = $( "<div style='display:block;position:absolute;width:50px;height:50px;overflow:hidden;'><div style='height:100px;width:auto;'></div></div>" ),
1091 innerDiv = div.children()[0];
1093 $( "body" ).append( div );
1094 w1 = innerDiv.offsetWidth;
1095 div.css( "overflow", "scroll" );
1097 w2 = innerDiv.offsetWidth;
1100 w2 = div[0].clientWidth;
1105 return (cachedScrollbarWidth = w1 - w2);
1107 getScrollInfo: function( within ) {
1108 var overflowX = within.isWindow || within.isDocument ? "" :
1109 within.element.css( "overflow-x" ),
1110 overflowY = within.isWindow || within.isDocument ? "" :
1111 within.element.css( "overflow-y" ),
1112 hasOverflowX = overflowX === "scroll" ||
1113 ( overflowX === "auto" && within.width < within.element[0].scrollWidth ),
1114 hasOverflowY = overflowY === "scroll" ||
1115 ( overflowY === "auto" && within.height < within.element[0].scrollHeight );
1117 width: hasOverflowY ? $.position.scrollbarWidth() : 0,
1118 height: hasOverflowX ? $.position.scrollbarWidth() : 0
1121 getWithinInfo: function( element ) {
1122 var withinElement = $( element || window ),
1123 isWindow = $.isWindow( withinElement[0] ),
1124 isDocument = !!withinElement[ 0 ] && withinElement[ 0 ].nodeType === 9;
1126 element: withinElement,
1128 isDocument: isDocument,
1129 offset: withinElement.offset() || { left: 0, top: 0 },
1130 scrollLeft: withinElement.scrollLeft(),
1131 scrollTop: withinElement.scrollTop(),
1132 width: isWindow ? withinElement.width() : withinElement.outerWidth(),
1133 height: isWindow ? withinElement.height() : withinElement.outerHeight()
1138 $.fn.position = function( options ) {
1139 if ( !options || !options.of ) {
1140 return _position.apply( this, arguments );
1143 // make a copy, we don't want to modify arguments
1144 options = $.extend( {}, options );
1146 var atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions,
1147 target = $( options.of ),
1148 within = $.position.getWithinInfo( options.within ),
1149 scrollInfo = $.position.getScrollInfo( within ),
1150 collision = ( options.collision || "flip" ).split( " " ),
1153 dimensions = getDimensions( target );
1154 if ( target[0].preventDefault ) {
1155 // force left top to allow flipping
1156 options.at = "left top";
1158 targetWidth = dimensions.width;
1159 targetHeight = dimensions.height;
1160 targetOffset = dimensions.offset;
1161 // clone to reuse original targetOffset later
1162 basePosition = $.extend( {}, targetOffset );
1164 // force my and at to have valid horizontal and vertical positions
1165 // if a value is missing or invalid, it will be converted to center
1166 $.each( [ "my", "at" ], function() {
1167 var pos = ( options[ this ] || "" ).split( " " ),
1171 if ( pos.length === 1) {
1172 pos = rhorizontal.test( pos[ 0 ] ) ?
1173 pos.concat( [ "center" ] ) :
1174 rvertical.test( pos[ 0 ] ) ?
1175 [ "center" ].concat( pos ) :
1176 [ "center", "center" ];
1178 pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center";
1179 pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center";
1181 // calculate offsets
1182 horizontalOffset = roffset.exec( pos[ 0 ] );
1183 verticalOffset = roffset.exec( pos[ 1 ] );
1185 horizontalOffset ? horizontalOffset[ 0 ] : 0,
1186 verticalOffset ? verticalOffset[ 0 ] : 0
1189 // reduce to just the positions without the offsets
1191 rposition.exec( pos[ 0 ] )[ 0 ],
1192 rposition.exec( pos[ 1 ] )[ 0 ]
1196 // normalize collision option
1197 if ( collision.length === 1 ) {
1198 collision[ 1 ] = collision[ 0 ];
1201 if ( options.at[ 0 ] === "right" ) {
1202 basePosition.left += targetWidth;
1203 } else if ( options.at[ 0 ] === "center" ) {
1204 basePosition.left += targetWidth / 2;
1207 if ( options.at[ 1 ] === "bottom" ) {
1208 basePosition.top += targetHeight;
1209 } else if ( options.at[ 1 ] === "center" ) {
1210 basePosition.top += targetHeight / 2;
1213 atOffset = getOffsets( offsets.at, targetWidth, targetHeight );
1214 basePosition.left += atOffset[ 0 ];
1215 basePosition.top += atOffset[ 1 ];
1217 return this.each(function() {
1218 var collisionPosition, using,
1220 elemWidth = elem.outerWidth(),
1221 elemHeight = elem.outerHeight(),
1222 marginLeft = parseCss( this, "marginLeft" ),
1223 marginTop = parseCss( this, "marginTop" ),
1224 collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) + scrollInfo.width,
1225 collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) + scrollInfo.height,
1226 position = $.extend( {}, basePosition ),
1227 myOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() );
1229 if ( options.my[ 0 ] === "right" ) {
1230 position.left -= elemWidth;
1231 } else if ( options.my[ 0 ] === "center" ) {
1232 position.left -= elemWidth / 2;
1235 if ( options.my[ 1 ] === "bottom" ) {
1236 position.top -= elemHeight;
1237 } else if ( options.my[ 1 ] === "center" ) {
1238 position.top -= elemHeight / 2;
1241 position.left += myOffset[ 0 ];
1242 position.top += myOffset[ 1 ];
1244 // if the browser doesn't support fractions, then round for consistent results
1245 if ( !supportsOffsetFractions ) {
1246 position.left = round( position.left );
1247 position.top = round( position.top );
1250 collisionPosition = {
1251 marginLeft: marginLeft,
1252 marginTop: marginTop
1255 $.each( [ "left", "top" ], function( i, dir ) {
1256 if ( $.ui.position[ collision[ i ] ] ) {
1257 $.ui.position[ collision[ i ] ][ dir ]( position, {
1258 targetWidth: targetWidth,
1259 targetHeight: targetHeight,
1260 elemWidth: elemWidth,
1261 elemHeight: elemHeight,
1262 collisionPosition: collisionPosition,
1263 collisionWidth: collisionWidth,
1264 collisionHeight: collisionHeight,
1265 offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ],
1274 if ( options.using ) {
1275 // adds feedback as second argument to using callback, if present
1276 using = function( props ) {
1277 var left = targetOffset.left - position.left,
1278 right = left + targetWidth - elemWidth,
1279 top = targetOffset.top - position.top,
1280 bottom = top + targetHeight - elemHeight,
1284 left: targetOffset.left,
1285 top: targetOffset.top,
1287 height: targetHeight
1291 left: position.left,
1296 horizontal: right < 0 ? "left" : left > 0 ? "right" : "center",
1297 vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle"
1299 if ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) {
1300 feedback.horizontal = "center";
1302 if ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) {
1303 feedback.vertical = "middle";
1305 if ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) {
1306 feedback.important = "horizontal";
1308 feedback.important = "vertical";
1310 options.using.call( this, props, feedback );
1314 elem.offset( $.extend( position, { using: using } ) );
1320 left: function( position, data ) {
1321 var within = data.within,
1322 withinOffset = within.isWindow ? within.scrollLeft : within.offset.left,
1323 outerWidth = within.width,
1324 collisionPosLeft = position.left - data.collisionPosition.marginLeft,
1325 overLeft = withinOffset - collisionPosLeft,
1326 overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset,
1329 // element is wider than within
1330 if ( data.collisionWidth > outerWidth ) {
1331 // element is initially over the left side of within
1332 if ( overLeft > 0 && overRight <= 0 ) {
1333 newOverRight = position.left + overLeft + data.collisionWidth - outerWidth - withinOffset;
1334 position.left += overLeft - newOverRight;
1335 // element is initially over right side of within
1336 } else if ( overRight > 0 && overLeft <= 0 ) {
1337 position.left = withinOffset;
1338 // element is initially over both left and right sides of within
1340 if ( overLeft > overRight ) {
1341 position.left = withinOffset + outerWidth - data.collisionWidth;
1343 position.left = withinOffset;
1346 // too far left -> align with left edge
1347 } else if ( overLeft > 0 ) {
1348 position.left += overLeft;
1349 // too far right -> align with right edge
1350 } else if ( overRight > 0 ) {
1351 position.left -= overRight;
1352 // adjust based on position and margin
1354 position.left = max( position.left - collisionPosLeft, position.left );
1357 top: function( position, data ) {
1358 var within = data.within,
1359 withinOffset = within.isWindow ? within.scrollTop : within.offset.top,
1360 outerHeight = data.within.height,
1361 collisionPosTop = position.top - data.collisionPosition.marginTop,
1362 overTop = withinOffset - collisionPosTop,
1363 overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset,
1366 // element is taller than within
1367 if ( data.collisionHeight > outerHeight ) {
1368 // element is initially over the top of within
1369 if ( overTop > 0 && overBottom <= 0 ) {
1370 newOverBottom = position.top + overTop + data.collisionHeight - outerHeight - withinOffset;
1371 position.top += overTop - newOverBottom;
1372 // element is initially over bottom of within
1373 } else if ( overBottom > 0 && overTop <= 0 ) {
1374 position.top = withinOffset;
1375 // element is initially over both top and bottom of within
1377 if ( overTop > overBottom ) {
1378 position.top = withinOffset + outerHeight - data.collisionHeight;
1380 position.top = withinOffset;
1383 // too far up -> align with top
1384 } else if ( overTop > 0 ) {
1385 position.top += overTop;
1386 // too far down -> align with bottom edge
1387 } else if ( overBottom > 0 ) {
1388 position.top -= overBottom;
1389 // adjust based on position and margin
1391 position.top = max( position.top - collisionPosTop, position.top );
1396 left: function( position, data ) {
1397 var within = data.within,
1398 withinOffset = within.offset.left + within.scrollLeft,
1399 outerWidth = within.width,
1400 offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left,
1401 collisionPosLeft = position.left - data.collisionPosition.marginLeft,
1402 overLeft = collisionPosLeft - offsetLeft,
1403 overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft,
1404 myOffset = data.my[ 0 ] === "left" ?
1406 data.my[ 0 ] === "right" ?
1409 atOffset = data.at[ 0 ] === "left" ?
1411 data.at[ 0 ] === "right" ?
1414 offset = -2 * data.offset[ 0 ],
1418 if ( overLeft < 0 ) {
1419 newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth - outerWidth - withinOffset;
1420 if ( newOverRight < 0 || newOverRight < abs( overLeft ) ) {
1421 position.left += myOffset + atOffset + offset;
1423 } else if ( overRight > 0 ) {
1424 newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset + atOffset + offset - offsetLeft;
1425 if ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) {
1426 position.left += myOffset + atOffset + offset;
1430 top: function( position, data ) {
1431 var within = data.within,
1432 withinOffset = within.offset.top + within.scrollTop,
1433 outerHeight = within.height,
1434 offsetTop = within.isWindow ? within.scrollTop : within.offset.top,
1435 collisionPosTop = position.top - data.collisionPosition.marginTop,
1436 overTop = collisionPosTop - offsetTop,
1437 overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop,
1438 top = data.my[ 1 ] === "top",
1441 data.my[ 1 ] === "bottom" ?
1444 atOffset = data.at[ 1 ] === "top" ?
1446 data.at[ 1 ] === "bottom" ?
1447 -data.targetHeight :
1449 offset = -2 * data.offset[ 1 ],
1452 if ( overTop < 0 ) {
1453 newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight - outerHeight - withinOffset;
1454 if ( ( position.top + myOffset + atOffset + offset) > overTop && ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) ) {
1455 position.top += myOffset + atOffset + offset;
1457 } else if ( overBottom > 0 ) {
1458 newOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset + offset - offsetTop;
1459 if ( ( position.top + myOffset + atOffset + offset) > overBottom && ( newOverTop > 0 || abs( newOverTop ) < overBottom ) ) {
1460 position.top += myOffset + atOffset + offset;
1467 $.ui.position.flip.left.apply( this, arguments );
1468 $.ui.position.fit.left.apply( this, arguments );
1471 $.ui.position.flip.top.apply( this, arguments );
1472 $.ui.position.fit.top.apply( this, arguments );
1477 // fraction support test
1479 var testElement, testElementParent, testElementStyle, offsetLeft, i,
1480 body = document.getElementsByTagName( "body" )[ 0 ],
1481 div = document.createElement( "div" );
1483 //Create a "fake body" for testing based on method used in jQuery.support
1484 testElement = document.createElement( body ? "div" : "body" );
1485 testElementStyle = {
1486 visibility: "hidden",
1494 $.extend( testElementStyle, {
1495 position: "absolute",
1500 for ( i in testElementStyle ) {
1501 testElement.style[ i ] = testElementStyle[ i ];
1503 testElement.appendChild( div );
1504 testElementParent = body || document.documentElement;
1505 testElementParent.insertBefore( testElement, testElementParent.firstChild );
1507 div.style.cssText = "position: absolute; left: 10.7432222px;";
1509 offsetLeft = $( div ).offset().left;
1510 supportsOffsetFractions = offsetLeft > 10 && offsetLeft < 11;
1512 testElement.innerHTML = "";
1513 testElementParent.removeChild( testElement );
1518 var position = $.ui.position;
1522 * jQuery UI Draggable 1.11.0
1523 * http://jqueryui.com
1525 * Copyright 2014 jQuery Foundation and other contributors
1526 * Released under the MIT license.
1527 * http://jquery.org/license
1529 * http://api.jqueryui.com/draggable/
1533 $.widget("ui.draggable", $.ui.mouse, {
1535 widgetEventPrefix: "drag",
1540 connectToSortable: false,
1549 refreshPositions: false,
1551 revertDuration: 500,
1554 scrollSensitivity: 20,
1567 _create: function() {
1569 if (this.options.helper === "original" && !(/^(?:r|a|f)/).test(this.element.css("position"))) {
1570 this.element[0].style.position = "relative";
1572 if (this.options.addClasses){
1573 this.element.addClass("ui-draggable");
1575 if (this.options.disabled){
1576 this.element.addClass("ui-draggable-disabled");
1578 this._setHandleClassName();
1583 _setOption: function( key, value ) {
1584 this._super( key, value );
1585 if ( key === "handle" ) {
1586 this._setHandleClassName();
1590 _destroy: function() {
1591 if ( ( this.helper || this.element ).is( ".ui-draggable-dragging" ) ) {
1592 this.destroyOnClear = true;
1595 this.element.removeClass( "ui-draggable ui-draggable-dragging ui-draggable-disabled" );
1596 this._removeHandleClassName();
1597 this._mouseDestroy();
1600 _mouseCapture: function(event) {
1602 var document = this.document[ 0 ],
1606 // IE9 throws an "Unspecified error" accessing document.activeElement from an <iframe>
1609 // If the <body> is blurred, IE will switch windows, see #9520
1610 if ( document.activeElement && document.activeElement.nodeName.toLowerCase() !== "body" ) {
1611 // Blur any element that currently has focus, see #4261
1612 $( document.activeElement ).blur();
1614 } catch ( error ) {}
1616 // among others, prevent a drag on a resizable-handle
1617 if (this.helper || o.disabled || $(event.target).closest(".ui-resizable-handle").length > 0) {
1621 //Quit if we're not on a valid handle
1622 this.handle = this._getHandle(event);
1627 $(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() {
1628 $("<div class='ui-draggable-iframeFix' style='background: #fff;'></div>")
1630 width: this.offsetWidth + "px", height: this.offsetHeight + "px",
1631 position: "absolute", opacity: "0.001", zIndex: 1000
1633 .css($(this).offset())
1641 _mouseStart: function(event) {
1643 var o = this.options;
1645 //Create and append the visible helper
1646 this.helper = this._createHelper(event);
1648 this.helper.addClass("ui-draggable-dragging");
1650 //Cache the helper size
1651 this._cacheHelperProportions();
1653 //If ddmanager is used for droppables, set the global draggable
1654 if ($.ui.ddmanager) {
1655 $.ui.ddmanager.current = this;
1659 * - Position generation -
1660 * This block generates everything position related - it's the core of draggables.
1663 //Cache the margins of the original element
1664 this._cacheMargins();
1666 //Store the helper's css position
1667 this.cssPosition = this.helper.css( "position" );
1668 this.scrollParent = this.helper.scrollParent();
1669 this.offsetParent = this.helper.offsetParent();
1670 this.offsetParentCssPosition = this.offsetParent.css( "position" );
1672 //The element's absolute position on the page minus margins
1673 this.offset = this.positionAbs = this.element.offset();
1675 top: this.offset.top - this.margins.top,
1676 left: this.offset.left - this.margins.left
1679 //Reset scroll cache
1680 this.offset.scroll = false;
1682 $.extend(this.offset, {
1683 click: { //Where the click happened, relative to the element
1684 left: event.pageX - this.offset.left,
1685 top: event.pageY - this.offset.top
1687 parent: this._getParentOffset(),
1688 relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
1691 //Generate the original position
1692 this.originalPosition = this.position = this._generatePosition( event, false );
1693 this.originalPageX = event.pageX;
1694 this.originalPageY = event.pageY;
1696 //Adjust the mouse offset relative to the helper if "cursorAt" is supplied
1697 (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
1699 //Set a containment if given in the options
1700 this._setContainment();
1702 //Trigger event + callbacks
1703 if (this._trigger("start", event) === false) {
1708 //Recache the helper size
1709 this._cacheHelperProportions();
1711 //Prepare the droppable offsets
1712 if ($.ui.ddmanager && !o.dropBehaviour) {
1713 $.ui.ddmanager.prepareOffsets(this, event);
1716 this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position
1718 //If the ddmanager is used for droppables, inform the manager that dragging has started (see #5003)
1719 if ( $.ui.ddmanager ) {
1720 $.ui.ddmanager.dragStart(this, event);
1726 _mouseDrag: function(event, noPropagation) {
1727 // reset any necessary cached properties (see #5009)
1728 if ( this.offsetParentCssPosition === "fixed" ) {
1729 this.offset.parent = this._getParentOffset();
1732 //Compute the helpers position
1733 this.position = this._generatePosition( event, true );
1734 this.positionAbs = this._convertPositionTo("absolute");
1736 //Call plugins and callbacks and use the resulting position if something is returned
1737 if (!noPropagation) {
1738 var ui = this._uiHash();
1739 if (this._trigger("drag", event, ui) === false) {
1743 this.position = ui.position;
1746 this.helper[ 0 ].style.left = this.position.left + "px";
1747 this.helper[ 0 ].style.top = this.position.top + "px";
1749 if ($.ui.ddmanager) {
1750 $.ui.ddmanager.drag(this, event);
1756 _mouseStop: function(event) {
1758 //If we are using droppables, inform the manager about the drop
1761 if ($.ui.ddmanager && !this.options.dropBehaviour) {
1762 dropped = $.ui.ddmanager.drop(this, event);
1765 //if a drop comes from outside (a sortable)
1767 dropped = this.dropped;
1768 this.dropped = false;
1771 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))) {
1772 $(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() {
1773 if (that._trigger("stop", event) !== false) {
1778 if (this._trigger("stop", event) !== false) {
1786 _mouseUp: function(event) {
1787 //Remove frame helpers
1788 $("div.ui-draggable-iframeFix").each(function() {
1789 this.parentNode.removeChild(this);
1792 //If the ddmanager is used for droppables, inform the manager that dragging has stopped (see #5003)
1793 if ( $.ui.ddmanager ) {
1794 $.ui.ddmanager.dragStop(this, event);
1797 // The interaction is over; whether or not the click resulted in a drag, focus the element
1798 this.element.focus();
1800 return $.ui.mouse.prototype._mouseUp.call(this, event);
1803 cancel: function() {
1805 if (this.helper.is(".ui-draggable-dragging")) {
1815 _getHandle: function(event) {
1816 return this.options.handle ?
1817 !!$( event.target ).closest( this.element.find( this.options.handle ) ).length :
1821 _setHandleClassName: function() {
1822 this._removeHandleClassName();
1823 $( this.options.handle || this.element ).addClass( "ui-draggable-handle" );
1826 _removeHandleClassName: function() {
1827 this.element.find( ".ui-draggable-handle" )
1829 .removeClass( "ui-draggable-handle" );
1832 _createHelper: function(event) {
1834 var o = this.options,
1835 helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[ 0 ], [ event ])) : (o.helper === "clone" ? this.element.clone().removeAttr("id") : this.element);
1837 if (!helper.parents("body").length) {
1838 helper.appendTo((o.appendTo === "parent" ? this.element[0].parentNode : o.appendTo));
1841 if (helper[0] !== this.element[0] && !(/(fixed|absolute)/).test(helper.css("position"))) {
1842 helper.css("position", "absolute");
1849 _adjustOffsetFromHelper: function(obj) {
1850 if (typeof obj === "string") {
1851 obj = obj.split(" ");
1853 if ($.isArray(obj)) {
1854 obj = { left: +obj[0], top: +obj[1] || 0 };
1856 if ("left" in obj) {
1857 this.offset.click.left = obj.left + this.margins.left;
1859 if ("right" in obj) {
1860 this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
1863 this.offset.click.top = obj.top + this.margins.top;
1865 if ("bottom" in obj) {
1866 this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
1870 _isRootNode: function( element ) {
1871 return ( /(html|body)/i ).test( element.tagName ) || element === this.document[ 0 ];
1874 _getParentOffset: function() {
1876 //Get the offsetParent and cache its position
1877 var po = this.offsetParent.offset(),
1878 document = this.document[ 0 ];
1880 // This is a special case where we need to modify a offset calculated on start, since the following happened:
1881 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
1882 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
1883 // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
1884 if (this.cssPosition === "absolute" && this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) {
1885 po.left += this.scrollParent.scrollLeft();
1886 po.top += this.scrollParent.scrollTop();
1889 if ( this._isRootNode( this.offsetParent[ 0 ] ) ) {
1890 po = { top: 0, left: 0 };
1894 top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
1895 left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
1900 _getRelativeOffset: function() {
1901 if ( this.cssPosition !== "relative" ) {
1902 return { top: 0, left: 0 };
1905 var p = this.element.position(),
1906 scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] );
1909 top: p.top - ( parseInt(this.helper.css( "top" ), 10) || 0 ) + ( !scrollIsRootNode ? this.scrollParent.scrollTop() : 0 ),
1910 left: p.left - ( parseInt(this.helper.css( "left" ), 10) || 0 ) + ( !scrollIsRootNode ? this.scrollParent.scrollLeft() : 0 )
1915 _cacheMargins: function() {
1917 left: (parseInt(this.element.css("marginLeft"),10) || 0),
1918 top: (parseInt(this.element.css("marginTop"),10) || 0),
1919 right: (parseInt(this.element.css("marginRight"),10) || 0),
1920 bottom: (parseInt(this.element.css("marginBottom"),10) || 0)
1924 _cacheHelperProportions: function() {
1925 this.helperProportions = {
1926 width: this.helper.outerWidth(),
1927 height: this.helper.outerHeight()
1931 _setContainment: function() {
1935 document = this.document[ 0 ];
1937 this.relative_container = null;
1939 if ( !o.containment ) {
1940 this.containment = null;
1944 if ( o.containment === "window" ) {
1945 this.containment = [
1946 $( window ).scrollLeft() - this.offset.relative.left - this.offset.parent.left,
1947 $( window ).scrollTop() - this.offset.relative.top - this.offset.parent.top,
1948 $( window ).scrollLeft() + $( window ).width() - this.helperProportions.width - this.margins.left,
1949 $( window ).scrollTop() + ( $( window ).height() || document.body.parentNode.scrollHeight ) - this.helperProportions.height - this.margins.top
1954 if ( o.containment === "document") {
1955 this.containment = [
1958 $( document ).width() - this.helperProportions.width - this.margins.left,
1959 ( $( document ).height() || document.body.parentNode.scrollHeight ) - this.helperProportions.height - this.margins.top
1964 if ( o.containment.constructor === Array ) {
1965 this.containment = o.containment;
1969 if ( o.containment === "parent" ) {
1970 o.containment = this.helper[ 0 ].parentNode;
1973 c = $( o.containment );
1980 over = c.css( "overflow" ) !== "hidden";
1982 this.containment = [
1983 ( parseInt( c.css( "borderLeftWidth" ), 10 ) || 0 ) + ( parseInt( c.css( "paddingLeft" ), 10 ) || 0 ),
1984 ( parseInt( c.css( "borderTopWidth" ), 10 ) || 0 ) + ( parseInt( c.css( "paddingTop" ), 10 ) || 0 ),
1985 ( over ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) - ( parseInt( c.css( "borderRightWidth" ), 10 ) || 0 ) - ( parseInt( c.css( "paddingRight" ), 10 ) || 0 ) - this.helperProportions.width - this.margins.left - this.margins.right,
1986 ( over ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) - ( parseInt( c.css( "borderBottomWidth" ), 10 ) || 0 ) - ( parseInt( c.css( "paddingBottom" ), 10 ) || 0 ) - this.helperProportions.height - this.margins.top - this.margins.bottom
1988 this.relative_container = c;
1991 _convertPositionTo: function(d, pos) {
1994 pos = this.position;
1997 var mod = d === "absolute" ? 1 : -1,
1998 scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] );
2002 pos.top + // The absolute mouse position
2003 this.offset.relative.top * mod + // Only for relative positioned nodes: Relative offset from element to offset parent
2004 this.offset.parent.top * mod - // The offsetParent's offset without borders (offset + border)
2005 ( ( this.cssPosition === "fixed" ? -this.offset.scroll.top : ( scrollIsRootNode ? 0 : this.offset.scroll.top ) ) * mod)
2008 pos.left + // The absolute mouse position
2009 this.offset.relative.left * mod + // Only for relative positioned nodes: Relative offset from element to offset parent
2010 this.offset.parent.left * mod - // The offsetParent's offset without borders (offset + border)
2011 ( ( this.cssPosition === "fixed" ? -this.offset.scroll.left : ( scrollIsRootNode ? 0 : this.offset.scroll.left ) ) * mod)
2017 _generatePosition: function( event, constrainPosition ) {
2019 var containment, co, top, left,
2021 scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] ),
2022 pageX = event.pageX,
2023 pageY = event.pageY;
2026 if ( !scrollIsRootNode || !this.offset.scroll ) {
2027 this.offset.scroll = {
2028 top: this.scrollParent.scrollTop(),
2029 left: this.scrollParent.scrollLeft()
2034 * - Position constraining -
2035 * Constrain the position to a mix of grid, containment.
2038 // If we are not dragging yet, we won't check for options
2039 if ( constrainPosition ) {
2040 if ( this.containment ) {
2041 if ( this.relative_container ){
2042 co = this.relative_container.offset();
2044 this.containment[ 0 ] + co.left,
2045 this.containment[ 1 ] + co.top,
2046 this.containment[ 2 ] + co.left,
2047 this.containment[ 3 ] + co.top
2050 containment = this.containment;
2053 if (event.pageX - this.offset.click.left < containment[0]) {
2054 pageX = containment[0] + this.offset.click.left;
2056 if (event.pageY - this.offset.click.top < containment[1]) {
2057 pageY = containment[1] + this.offset.click.top;
2059 if (event.pageX - this.offset.click.left > containment[2]) {
2060 pageX = containment[2] + this.offset.click.left;
2062 if (event.pageY - this.offset.click.top > containment[3]) {
2063 pageY = containment[3] + this.offset.click.top;
2068 //Check for grid elements set to 0 to prevent divide by 0 error causing invalid argument errors in IE (see ticket #6950)
2069 top = o.grid[1] ? this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1] : this.originalPageY;
2070 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;
2072 left = o.grid[0] ? this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0] : this.originalPageX;
2073 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;
2076 if ( o.axis === "y" ) {
2077 pageX = this.originalPageX;
2080 if ( o.axis === "x" ) {
2081 pageY = this.originalPageY;
2087 pageY - // The absolute mouse position
2088 this.offset.click.top - // Click offset (relative to the element)
2089 this.offset.relative.top - // Only for relative positioned nodes: Relative offset from element to offset parent
2090 this.offset.parent.top + // The offsetParent's offset without borders (offset + border)
2091 ( this.cssPosition === "fixed" ? -this.offset.scroll.top : ( scrollIsRootNode ? 0 : this.offset.scroll.top ) )
2094 pageX - // The absolute mouse position
2095 this.offset.click.left - // Click offset (relative to the element)
2096 this.offset.relative.left - // Only for relative positioned nodes: Relative offset from element to offset parent
2097 this.offset.parent.left + // The offsetParent's offset without borders (offset + border)
2098 ( this.cssPosition === "fixed" ? -this.offset.scroll.left : ( scrollIsRootNode ? 0 : this.offset.scroll.left ) )
2104 _clear: function() {
2105 this.helper.removeClass("ui-draggable-dragging");
2106 if (this.helper[0] !== this.element[0] && !this.cancelHelperRemoval) {
2107 this.helper.remove();
2110 this.cancelHelperRemoval = false;
2111 if ( this.destroyOnClear ) {
2116 // From now on bulk stuff - mainly helpers
2118 _trigger: function(type, event, ui) {
2119 ui = ui || this._uiHash();
2120 $.ui.plugin.call( this, type, [ event, ui, this ], true );
2121 //The absolute position has to be recalculated after plugins
2122 if (type === "drag") {
2123 this.positionAbs = this._convertPositionTo("absolute");
2125 return $.Widget.prototype._trigger.call(this, type, event, ui);
2130 _uiHash: function() {
2132 helper: this.helper,
2133 position: this.position,
2134 originalPosition: this.originalPosition,
2135 offset: this.positionAbs
2141 $.ui.plugin.add("draggable", "connectToSortable", {
2142 start: function( event, ui, inst ) {
2144 var o = inst.options,
2145 uiSortable = $.extend({}, ui, { item: inst.element });
2146 inst.sortables = [];
2147 $(o.connectToSortable).each(function() {
2148 var sortable = $( this ).sortable( "instance" );
2149 if (sortable && !sortable.options.disabled) {
2150 inst.sortables.push({
2152 shouldRevert: sortable.options.revert
2154 sortable.refreshPositions(); // Call the sortable's refreshPositions at drag start to refresh the containerCache since the sortable container cache is used in drag and needs to be up to date (this will ensure it's initialised as well as being kept in step with any changes that might have happened on the page).
2155 sortable._trigger("activate", event, uiSortable);
2160 stop: function( event, ui, inst ) {
2162 //If we are still over the sortable, we fake the stop event of the sortable, but also remove helper
2163 var uiSortable = $.extend( {}, ui, {
2167 $.each(inst.sortables, function() {
2168 if (this.instance.isOver) {
2170 this.instance.isOver = 0;
2172 inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance
2173 this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work)
2175 //The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: "valid/invalid"
2176 if (this.shouldRevert) {
2177 this.instance.options.revert = this.shouldRevert;
2180 //Trigger the stop of the sortable
2181 this.instance._mouseStop(event);
2183 this.instance.options.helper = this.instance.options._helper;
2185 //If the helper has been the original item, restore properties in the sortable
2186 if (inst.options.helper === "original") {
2187 this.instance.currentItem.css({ top: "auto", left: "auto" });
2191 this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance
2192 this.instance._trigger("deactivate", event, uiSortable);
2198 drag: function( event, ui, inst ) {
2202 $.each(inst.sortables, function() {
2204 var innermostIntersecting = false,
2205 thisSortable = this;
2207 //Copy over some variables to allow calling the sortable's native _intersectsWith
2208 this.instance.positionAbs = inst.positionAbs;
2209 this.instance.helperProportions = inst.helperProportions;
2210 this.instance.offset.click = inst.offset.click;
2212 if (this.instance._intersectsWith(this.instance.containerCache)) {
2213 innermostIntersecting = true;
2214 $.each(inst.sortables, function() {
2215 this.instance.positionAbs = inst.positionAbs;
2216 this.instance.helperProportions = inst.helperProportions;
2217 this.instance.offset.click = inst.offset.click;
2218 if (this !== thisSortable &&
2219 this.instance._intersectsWith(this.instance.containerCache) &&
2220 $.contains(thisSortable.instance.element[0], this.instance.element[0])
2222 innermostIntersecting = false;
2224 return innermostIntersecting;
2228 if (innermostIntersecting) {
2229 //If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once
2230 if (!this.instance.isOver) {
2232 this.instance.isOver = 1;
2233 //Now we fake the start of dragging for the sortable instance,
2234 //by cloning the list group item, appending it to the sortable and using it as inst.currentItem
2235 //We can then fire the start event of the sortable with our passed browser event, and our own helper (so it doesn't create a new one)
2236 this.instance.currentItem = $(that).clone().removeAttr("id").appendTo(this.instance.element).data("ui-sortable-item", true);
2237 this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it
2238 this.instance.options.helper = function() { return ui.helper[0]; };
2240 event.target = this.instance.currentItem[0];
2241 this.instance._mouseCapture(event, true);
2242 this.instance._mouseStart(event, true, true);
2244 //Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes
2245 this.instance.offset.click.top = inst.offset.click.top;
2246 this.instance.offset.click.left = inst.offset.click.left;
2247 this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left;
2248 this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top;
2250 inst._trigger("toSortable", event);
2251 inst.dropped = this.instance.element; //draggable revert needs that
2252 //hack so receive/update callbacks work (mostly)
2253 inst.currentItem = inst.element;
2254 this.instance.fromOutside = inst;
2258 //Provided we did all the previous steps, we can fire the drag event of the sortable on every draggable drag, when it intersects with the sortable
2259 if (this.instance.currentItem) {
2260 this.instance._mouseDrag(event);
2265 //If it doesn't intersect with the sortable, and it intersected before,
2266 //we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval
2267 if (this.instance.isOver) {
2269 this.instance.isOver = 0;
2270 this.instance.cancelHelperRemoval = true;
2272 //Prevent reverting on this forced stop
2273 this.instance.options.revert = false;
2275 // The out event needs to be triggered independently
2276 this.instance._trigger("out", event, this.instance._uiHash(this.instance));
2278 this.instance._mouseStop(event, true);
2279 this.instance.options.helper = this.instance.options._helper;
2281 //Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size
2282 this.instance.currentItem.remove();
2283 if (this.instance.placeholder) {
2284 this.instance.placeholder.remove();
2287 inst._trigger("fromSortable", event);
2288 inst.dropped = false; //draggable revert needs that
2298 $.ui.plugin.add("draggable", "cursor", {
2299 start: function( event, ui, instance ) {
2300 var t = $( "body" ),
2301 o = instance.options;
2303 if (t.css("cursor")) {
2304 o._cursor = t.css("cursor");
2306 t.css("cursor", o.cursor);
2308 stop: function( event, ui, instance ) {
2309 var o = instance.options;
2311 $("body").css("cursor", o._cursor);
2316 $.ui.plugin.add("draggable", "opacity", {
2317 start: function( event, ui, instance ) {
2318 var t = $( ui.helper ),
2319 o = instance.options;
2320 if (t.css("opacity")) {
2321 o._opacity = t.css("opacity");
2323 t.css("opacity", o.opacity);
2325 stop: function( event, ui, instance ) {
2326 var o = instance.options;
2328 $(ui.helper).css("opacity", o._opacity);
2333 $.ui.plugin.add("draggable", "scroll", {
2334 start: function( event, ui, i ) {
2335 if ( i.scrollParent[ 0 ] !== i.document[ 0 ] && i.scrollParent[ 0 ].tagName !== "HTML" ) {
2336 i.overflowOffset = i.scrollParent.offset();
2339 drag: function( event, ui, i ) {
2343 document = i.document[ 0 ];
2345 if ( i.scrollParent[ 0 ] !== document && i.scrollParent[ 0 ].tagName !== "HTML" ) {
2346 if (!o.axis || o.axis !== "x") {
2347 if ((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) {
2348 i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed;
2349 } else if (event.pageY - i.overflowOffset.top < o.scrollSensitivity) {
2350 i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed;
2354 if (!o.axis || o.axis !== "y") {
2355 if ((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) {
2356 i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed;
2357 } else if (event.pageX - i.overflowOffset.left < o.scrollSensitivity) {
2358 i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed;
2364 if (!o.axis || o.axis !== "x") {
2365 if (event.pageY - $(document).scrollTop() < o.scrollSensitivity) {
2366 scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
2367 } else if ($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) {
2368 scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
2372 if (!o.axis || o.axis !== "y") {
2373 if (event.pageX - $(document).scrollLeft() < o.scrollSensitivity) {
2374 scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
2375 } else if ($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) {
2376 scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
2382 if (scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) {
2383 $.ui.ddmanager.prepareOffsets(i, event);
2389 $.ui.plugin.add("draggable", "snap", {
2390 start: function( event, ui, i ) {
2394 i.snapElements = [];
2396 $(o.snap.constructor !== String ? ( o.snap.items || ":data(ui-draggable)" ) : o.snap).each(function() {
2399 if (this !== i.element[0]) {
2400 i.snapElements.push({
2402 width: $t.outerWidth(), height: $t.outerHeight(),
2403 top: $o.top, left: $o.left
2409 drag: function( event, ui, inst ) {
2411 var ts, bs, ls, rs, l, r, t, b, i, first,
2413 d = o.snapTolerance,
2414 x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
2415 y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
2417 for (i = inst.snapElements.length - 1; i >= 0; i--){
2419 l = inst.snapElements[i].left;
2420 r = l + inst.snapElements[i].width;
2421 t = inst.snapElements[i].top;
2422 b = t + inst.snapElements[i].height;
2424 if ( x2 < l - d || x1 > r + d || y2 < t - d || y1 > b + d || !$.contains( inst.snapElements[ i ].item.ownerDocument, inst.snapElements[ i ].item ) ) {
2425 if (inst.snapElements[i].snapping) {
2426 (inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
2428 inst.snapElements[i].snapping = false;
2432 if (o.snapMode !== "inner") {
2433 ts = Math.abs(t - y2) <= d;
2434 bs = Math.abs(b - y1) <= d;
2435 ls = Math.abs(l - x2) <= d;
2436 rs = Math.abs(r - x1) <= d;
2438 ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
2441 ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top;
2444 ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left;
2447 ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left;
2451 first = (ts || bs || ls || rs);
2453 if (o.snapMode !== "outer") {
2454 ts = Math.abs(t - y1) <= d;
2455 bs = Math.abs(b - y2) <= d;
2456 ls = Math.abs(l - x1) <= d;
2457 rs = Math.abs(r - x2) <= d;
2459 ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top;
2462 ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
2465 ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left;
2468 ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left;
2472 if (!inst.snapElements[i].snapping && (ts || bs || ls || rs || first)) {
2473 (inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
2475 inst.snapElements[i].snapping = (ts || bs || ls || rs || first);
2482 $.ui.plugin.add("draggable", "stack", {
2483 start: function( event, ui, instance ) {
2485 o = instance.options,
2486 group = $.makeArray($(o.stack)).sort(function(a,b) {
2487 return (parseInt($(a).css("zIndex"),10) || 0) - (parseInt($(b).css("zIndex"),10) || 0);
2490 if (!group.length) { return; }
2492 min = parseInt($(group[0]).css("zIndex"), 10) || 0;
2493 $(group).each(function(i) {
2494 $(this).css("zIndex", min + i);
2496 this.css("zIndex", (min + group.length));
2500 $.ui.plugin.add("draggable", "zIndex", {
2501 start: function( event, ui, instance ) {
2502 var t = $( ui.helper ),
2503 o = instance.options;
2505 if (t.css("zIndex")) {
2506 o._zIndex = t.css("zIndex");
2508 t.css("zIndex", o.zIndex);
2510 stop: function( event, ui, instance ) {
2511 var o = instance.options;
2514 $(ui.helper).css("zIndex", o._zIndex);
2519 var draggable = $.ui.draggable;
2523 * jQuery UI Droppable 1.11.0
2524 * http://jqueryui.com
2526 * Copyright 2014 jQuery Foundation and other contributors
2527 * Released under the MIT license.
2528 * http://jquery.org/license
2530 * http://api.jqueryui.com/droppable/
2534 $.widget( "ui.droppable", {
2536 widgetEventPrefix: "drop",
2544 tolerance: "intersect",
2553 _create: function() {
2559 this.isover = false;
2562 this.accept = $.isFunction( accept ) ? accept : function( d ) {
2563 return d.is( accept );
2566 this.proportions = function( /* valueToWrite */ ) {
2567 if ( arguments.length ) {
2568 // Store the droppable's proportions
2569 proportions = arguments[ 0 ];
2571 // Retrieve or derive the droppable's proportions
2572 return proportions ?
2575 width: this.element[ 0 ].offsetWidth,
2576 height: this.element[ 0 ].offsetHeight
2581 this._addToManager( o.scope );
2583 o.addClasses && this.element.addClass( "ui-droppable" );
2587 _addToManager: function( scope ) {
2588 // Add the reference and positions to the manager
2589 $.ui.ddmanager.droppables[ scope ] = $.ui.ddmanager.droppables[ scope ] || [];
2590 $.ui.ddmanager.droppables[ scope ].push( this );
2593 _splice: function( drop ) {
2595 for ( ; i < drop.length; i++ ) {
2596 if ( drop[ i ] === this ) {
2597 drop.splice( i, 1 );
2602 _destroy: function() {
2603 var drop = $.ui.ddmanager.droppables[ this.options.scope ];
2605 this._splice( drop );
2607 this.element.removeClass( "ui-droppable ui-droppable-disabled" );
2610 _setOption: function( key, value ) {
2612 if ( key === "accept" ) {
2613 this.accept = $.isFunction( value ) ? value : function( d ) {
2614 return d.is( value );
2616 } else if ( key === "scope" ) {
2617 var drop = $.ui.ddmanager.droppables[ this.options.scope ];
2619 this._splice( drop );
2620 this._addToManager( value );
2623 this._super( key, value );
2626 _activate: function( event ) {
2627 var draggable = $.ui.ddmanager.current;
2628 if ( this.options.activeClass ) {
2629 this.element.addClass( this.options.activeClass );
2632 this._trigger( "activate", event, this.ui( draggable ) );
2636 _deactivate: function( event ) {
2637 var draggable = $.ui.ddmanager.current;
2638 if ( this.options.activeClass ) {
2639 this.element.removeClass( this.options.activeClass );
2642 this._trigger( "deactivate", event, this.ui( draggable ) );
2646 _over: function( event ) {
2648 var draggable = $.ui.ddmanager.current;
2650 // Bail if draggable and droppable are same element
2651 if ( !draggable || ( draggable.currentItem || draggable.element )[ 0 ] === this.element[ 0 ] ) {
2655 if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem || draggable.element ) ) ) {
2656 if ( this.options.hoverClass ) {
2657 this.element.addClass( this.options.hoverClass );
2659 this._trigger( "over", event, this.ui( draggable ) );
2664 _out: function( event ) {
2666 var draggable = $.ui.ddmanager.current;
2668 // Bail if draggable and droppable are same element
2669 if ( !draggable || ( draggable.currentItem || draggable.element )[ 0 ] === this.element[ 0 ] ) {
2673 if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem || draggable.element ) ) ) {
2674 if ( this.options.hoverClass ) {
2675 this.element.removeClass( this.options.hoverClass );
2677 this._trigger( "out", event, this.ui( draggable ) );
2682 _drop: function( event, custom ) {
2684 var draggable = custom || $.ui.ddmanager.current,
2685 childrenIntersection = false;
2687 // Bail if draggable and droppable are same element
2688 if ( !draggable || ( draggable.currentItem || draggable.element )[ 0 ] === this.element[ 0 ] ) {
2692 this.element.find( ":data(ui-droppable)" ).not( ".ui-draggable-dragging" ).each(function() {
2693 var inst = $( this ).droppable( "instance" );
2695 inst.options.greedy &&
2696 !inst.options.disabled &&
2697 inst.options.scope === draggable.options.scope &&
2698 inst.accept.call( inst.element[ 0 ], ( draggable.currentItem || draggable.element ) ) &&
2699 $.ui.intersect( draggable, $.extend( inst, { offset: inst.element.offset() } ), inst.options.tolerance )
2700 ) { childrenIntersection = true; return false; }
2702 if ( childrenIntersection ) {
2706 if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem || draggable.element ) ) ) {
2707 if ( this.options.activeClass ) {
2708 this.element.removeClass( this.options.activeClass );
2710 if ( this.options.hoverClass ) {
2711 this.element.removeClass( this.options.hoverClass );
2713 this._trigger( "drop", event, this.ui( draggable ) );
2714 return this.element;
2723 draggable: ( c.currentItem || c.element ),
2725 position: c.position,
2726 offset: c.positionAbs
2732 $.ui.intersect = (function() {
2733 function isOverAxis( x, reference, size ) {
2734 return ( x >= reference ) && ( x < ( reference + size ) );
2737 return function( draggable, droppable, toleranceMode ) {
2739 if ( !droppable.offset ) {
2743 var draggableLeft, draggableTop,
2744 x1 = ( draggable.positionAbs || draggable.position.absolute ).left,
2745 y1 = ( draggable.positionAbs || draggable.position.absolute ).top,
2746 x2 = x1 + draggable.helperProportions.width,
2747 y2 = y1 + draggable.helperProportions.height,
2748 l = droppable.offset.left,
2749 t = droppable.offset.top,
2750 r = l + droppable.proportions().width,
2751 b = t + droppable.proportions().height;
2753 switch ( toleranceMode ) {
2755 return ( l <= x1 && x2 <= r && t <= y1 && y2 <= b );
2757 return ( l < x1 + ( draggable.helperProportions.width / 2 ) && // Right Half
2758 x2 - ( draggable.helperProportions.width / 2 ) < r && // Left Half
2759 t < y1 + ( draggable.helperProportions.height / 2 ) && // Bottom Half
2760 y2 - ( draggable.helperProportions.height / 2 ) < b ); // Top Half
2762 draggableLeft = ( ( draggable.positionAbs || draggable.position.absolute ).left + ( draggable.clickOffset || draggable.offset.click ).left );
2763 draggableTop = ( ( draggable.positionAbs || draggable.position.absolute ).top + ( draggable.clickOffset || draggable.offset.click ).top );
2764 return isOverAxis( draggableTop, t, droppable.proportions().height ) && isOverAxis( draggableLeft, l, droppable.proportions().width );
2767 ( y1 >= t && y1 <= b ) || // Top edge touching
2768 ( y2 >= t && y2 <= b ) || // Bottom edge touching
2769 ( y1 < t && y2 > b ) // Surrounded vertically
2771 ( x1 >= l && x1 <= r ) || // Left edge touching
2772 ( x2 >= l && x2 <= r ) || // Right edge touching
2773 ( x1 < l && x2 > r ) // Surrounded horizontally
2782 This manager tracks offsets of draggables and droppables
2786 droppables: { "default": [] },
2787 prepareOffsets: function( t, event ) {
2790 m = $.ui.ddmanager.droppables[ t.options.scope ] || [],
2791 type = event ? event.type : null, // workaround for #2317
2792 list = ( t.currentItem || t.element ).find( ":data(ui-droppable)" ).addBack();
2794 droppablesLoop: for ( i = 0; i < m.length; i++ ) {
2796 // No disabled and non-accepted
2797 if ( m[ i ].options.disabled || ( t && !m[ i ].accept.call( m[ i ].element[ 0 ], ( t.currentItem || t.element ) ) ) ) {
2801 // Filter out elements in the current dragged item
2802 for ( j = 0; j < list.length; j++ ) {
2803 if ( list[ j ] === m[ i ].element[ 0 ] ) {
2804 m[ i ].proportions().height = 0;
2805 continue droppablesLoop;
2809 m[ i ].visible = m[ i ].element.css( "display" ) !== "none";
2810 if ( !m[ i ].visible ) {
2814 // Activate the droppable if used directly from draggables
2815 if ( type === "mousedown" ) {
2816 m[ i ]._activate.call( m[ i ], event );
2819 m[ i ].offset = m[ i ].element.offset();
2820 m[ i ].proportions({ width: m[ i ].element[ 0 ].offsetWidth, height: m[ i ].element[ 0 ].offsetHeight });
2825 drop: function( draggable, event ) {
2827 var dropped = false;
2828 // Create a copy of the droppables in case the list changes during the drop (#9116)
2829 $.each( ( $.ui.ddmanager.droppables[ draggable.options.scope ] || [] ).slice(), function() {
2831 if ( !this.options ) {
2834 if ( !this.options.disabled && this.visible && $.ui.intersect( draggable, this, this.options.tolerance ) ) {
2835 dropped = this._drop.call( this, event ) || dropped;
2838 if ( !this.options.disabled && this.visible && this.accept.call( this.element[ 0 ], ( draggable.currentItem || draggable.element ) ) ) {
2840 this.isover = false;
2841 this._deactivate.call( this, event );
2848 dragStart: function( draggable, event ) {
2849 // Listen for scrolling so that if the dragging causes scrolling the position of the droppables can be recalculated (see #5003)
2850 draggable.element.parentsUntil( "body" ).bind( "scroll.droppable", function() {
2851 if ( !draggable.options.refreshPositions ) {
2852 $.ui.ddmanager.prepareOffsets( draggable, event );
2856 drag: function( draggable, event ) {
2858 // If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse.
2859 if ( draggable.options.refreshPositions ) {
2860 $.ui.ddmanager.prepareOffsets( draggable, event );
2863 // Run through all droppables and check their positions based on specific tolerance options
2864 $.each( $.ui.ddmanager.droppables[ draggable.options.scope ] || [], function() {
2866 if ( this.options.disabled || this.greedyChild || !this.visible ) {
2870 var parentInstance, scope, parent,
2871 intersects = $.ui.intersect( draggable, this, this.options.tolerance ),
2872 c = !intersects && this.isover ? "isout" : ( intersects && !this.isover ? "isover" : null );
2877 if ( this.options.greedy ) {
2878 // find droppable parents with same scope
2879 scope = this.options.scope;
2880 parent = this.element.parents( ":data(ui-droppable)" ).filter(function() {
2881 return $( this ).droppable( "instance" ).options.scope === scope;
2884 if ( parent.length ) {
2885 parentInstance = $( parent[ 0 ] ).droppable( "instance" );
2886 parentInstance.greedyChild = ( c === "isover" );
2890 // we just moved into a greedy child
2891 if ( parentInstance && c === "isover" ) {
2892 parentInstance.isover = false;
2893 parentInstance.isout = true;
2894 parentInstance._out.call( parentInstance, event );
2898 this[c === "isout" ? "isover" : "isout"] = false;
2899 this[c === "isover" ? "_over" : "_out"].call( this, event );
2901 // we just moved out of a greedy child
2902 if ( parentInstance && c === "isout" ) {
2903 parentInstance.isout = false;
2904 parentInstance.isover = true;
2905 parentInstance._over.call( parentInstance, event );
2910 dragStop: function( draggable, event ) {
2911 draggable.element.parentsUntil( "body" ).unbind( "scroll.droppable" );
2912 // Call prepareOffsets one final time since IE does not fire return scroll events when overflow was caused by drag (see #5003)
2913 if ( !draggable.options.refreshPositions ) {
2914 $.ui.ddmanager.prepareOffsets( draggable, event );
2919 var droppable = $.ui.droppable;
2923 * jQuery UI Resizable 1.11.0
2924 * http://jqueryui.com
2926 * Copyright 2014 jQuery Foundation and other contributors
2927 * Released under the MIT license.
2928 * http://jquery.org/license
2930 * http://api.jqueryui.com/resizable/
2934 $.widget("ui.resizable", $.ui.mouse, {
2936 widgetEventPrefix: "resize",
2940 animateDuration: "slow",
2941 animateEasing: "swing",
2962 _num: function( value ) {
2963 return parseInt( value, 10 ) || 0;
2966 _isNumber: function( value ) {
2967 return !isNaN( parseInt( value , 10 ) );
2970 _hasScroll: function( el, a ) {
2972 if ( $( el ).css( "overflow" ) === "hidden") {
2976 var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
2979 if ( el[ scroll ] > 0 ) {
2983 // TODO: determine which cases actually cause this to happen
2984 // if the element doesn't have the scroll set, see if it's possible to
2987 has = ( el[ scroll ] > 0 );
2992 _create: function() {
2994 var n, i, handle, axis, hname,
2997 this.element.addClass("ui-resizable");
3000 _aspectRatio: !!(o.aspectRatio),
3001 aspectRatio: o.aspectRatio,
3002 originalElement: this.element,
3003 _proportionallyResizeElements: [],
3004 _helper: o.helper || o.ghost || o.animate ? o.helper || "ui-resizable-helper" : null
3007 // Wrap the element if it cannot hold child nodes
3008 if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) {
3011 $("<div class='ui-wrapper' style='overflow: hidden;'></div>").css({
3012 position: this.element.css("position"),
3013 width: this.element.outerWidth(),
3014 height: this.element.outerHeight(),
3015 top: this.element.css("top"),
3016 left: this.element.css("left")
3020 this.element = this.element.parent().data(
3021 "ui-resizable", this.element.resizable( "instance" )
3024 this.elementIsWrapper = true;
3026 this.element.css({ marginLeft: this.originalElement.css("marginLeft"), marginTop: this.originalElement.css("marginTop"), marginRight: this.originalElement.css("marginRight"), marginBottom: this.originalElement.css("marginBottom") });
3027 this.originalElement.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0});
3029 // Prevent Safari textarea resize
3030 this.originalResizeStyle = this.originalElement.css("resize");
3031 this.originalElement.css("resize", "none");
3033 this._proportionallyResizeElements.push(this.originalElement.css({ position: "static", zoom: 1, display: "block" }));
3036 // avoid IE jump (hard set the margin)
3037 this.originalElement.css({ margin: this.originalElement.css("margin") });
3039 this._proportionallyResize();
3042 this.handles = o.handles || (!$(".ui-resizable-handle", this.element).length ? "e,s,se" : { n: ".ui-resizable-n", e: ".ui-resizable-e", s: ".ui-resizable-s", w: ".ui-resizable-w", se: ".ui-resizable-se", sw: ".ui-resizable-sw", ne: ".ui-resizable-ne", nw: ".ui-resizable-nw" });
3043 if(this.handles.constructor === String) {
3045 if ( this.handles === "all") {
3046 this.handles = "n,e,s,w,se,sw,ne,nw";
3049 n = this.handles.split(",");
3052 for(i = 0; i < n.length; i++) {
3054 handle = $.trim(n[i]);
3055 hname = "ui-resizable-"+handle;
3056 axis = $("<div class='ui-resizable-handle " + hname + "'></div>");
3058 axis.css({ zIndex: o.zIndex });
3060 // TODO : What's going on here?
3061 if ("se" === handle) {
3062 axis.addClass("ui-icon ui-icon-gripsmall-diagonal-se");
3065 this.handles[handle] = ".ui-resizable-"+handle;
3066 this.element.append(axis);
3071 this._renderAxis = function(target) {
3073 var i, axis, padPos, padWrapper;
3075 target = target || this.element;
3077 for(i in this.handles) {
3079 if(this.handles[i].constructor === String) {
3080 this.handles[i] = this.element.children( this.handles[ i ] ).first().show();
3083 if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) {
3085 axis = $(this.handles[i], this.element);
3087 padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth();
3089 padPos = [ "padding",
3090 /ne|nw|n/.test(i) ? "Top" :
3091 /se|sw|s/.test(i) ? "Bottom" :
3092 /^e$/.test(i) ? "Right" : "Left" ].join("");
3094 target.css(padPos, padWrapper);
3096 this._proportionallyResize();
3100 // TODO: What's that good for? There's not anything to be executed left
3101 if(!$(this.handles[i]).length) {
3107 // TODO: make renderAxis a prototype function
3108 this._renderAxis(this.element);
3110 this._handles = $(".ui-resizable-handle", this.element)
3111 .disableSelection();
3113 this._handles.mouseover(function() {
3114 if (!that.resizing) {
3115 if (this.className) {
3116 axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);
3118 that.axis = axis && axis[1] ? axis[1] : "se";
3123 this._handles.hide();
3125 .addClass("ui-resizable-autohide")
3126 .mouseenter(function() {
3130 $(this).removeClass("ui-resizable-autohide");
3131 that._handles.show();
3133 .mouseleave(function(){
3137 if (!that.resizing) {
3138 $(this).addClass("ui-resizable-autohide");
3139 that._handles.hide();
3148 _destroy: function() {
3150 this._mouseDestroy();
3153 _destroy = function(exp) {
3154 $(exp).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing")
3155 .removeData("resizable").removeData("ui-resizable").unbind(".resizable").find(".ui-resizable-handle").remove();
3158 // TODO: Unwrap at same DOM position
3159 if (this.elementIsWrapper) {
3160 _destroy(this.element);
3161 wrapper = this.element;
3162 this.originalElement.css({
3163 position: wrapper.css("position"),
3164 width: wrapper.outerWidth(),
3165 height: wrapper.outerHeight(),
3166 top: wrapper.css("top"),
3167 left: wrapper.css("left")
3168 }).insertAfter( wrapper );
3172 this.originalElement.css("resize", this.originalResizeStyle);
3173 _destroy(this.originalElement);
3178 _mouseCapture: function(event) {
3182 for (i in this.handles) {
3183 handle = $(this.handles[i])[0];
3184 if (handle === event.target || $.contains(handle, event.target)) {
3189 return !this.options.disabled && capture;
3192 _mouseStart: function(event) {
3194 var curleft, curtop, cursor,
3198 this.resizing = true;
3200 this._renderProxy();
3202 curleft = this._num(this.helper.css("left"));
3203 curtop = this._num(this.helper.css("top"));
3205 if (o.containment) {
3206 curleft += $(o.containment).scrollLeft() || 0;
3207 curtop += $(o.containment).scrollTop() || 0;
3210 this.offset = this.helper.offset();
3211 this.position = { left: curleft, top: curtop };
3212 this.size = this._helper ? { width: this.helper.width(), height: this.helper.height() } : { width: el.width(), height: el.height() };
3213 this.originalSize = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
3214 this.originalPosition = { left: curleft, top: curtop };
3215 this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() };
3216 this.originalMousePosition = { left: event.pageX, top: event.pageY };
3218 this.aspectRatio = (typeof o.aspectRatio === "number") ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1);
3220 cursor = $(".ui-resizable-" + this.axis).css("cursor");
3221 $("body").css("cursor", cursor === "auto" ? this.axis + "-resize" : cursor);
3223 el.addClass("ui-resizable-resizing");
3224 this._propagate("start", event);
3228 _mouseDrag: function(event) {
3231 el = this.helper, props = {},
3232 smp = this.originalMousePosition,
3234 dx = (event.pageX-smp.left)||0,
3235 dy = (event.pageY-smp.top)||0,
3236 trigger = this._change[a];
3238 this.prevPosition = {
3239 top: this.position.top,
3240 left: this.position.left
3243 width: this.size.width,
3244 height: this.size.height
3251 data = trigger.apply(this, [event, dx, dy]);
3253 this._updateVirtualBoundaries(event.shiftKey);
3254 if (this._aspectRatio || event.shiftKey) {
3255 data = this._updateRatio(data, event);
3258 data = this._respectSize(data, event);
3260 this._updateCache(data);
3262 this._propagate("resize", event);
3264 if ( this.position.top !== this.prevPosition.top ) {
3265 props.top = this.position.top + "px";
3267 if ( this.position.left !== this.prevPosition.left ) {
3268 props.left = this.position.left + "px";
3270 if ( this.size.width !== this.prevSize.width ) {
3271 props.width = this.size.width + "px";
3273 if ( this.size.height !== this.prevSize.height ) {
3274 props.height = this.size.height + "px";
3278 if ( !this._helper && this._proportionallyResizeElements.length ) {
3279 this._proportionallyResize();
3282 if ( !$.isEmptyObject( props ) ) {
3283 this._trigger( "resize", event, this.ui() );
3289 _mouseStop: function(event) {
3291 this.resizing = false;
3292 var pr, ista, soffseth, soffsetw, s, left, top,
3293 o = this.options, that = this;
3297 pr = this._proportionallyResizeElements;
3298 ista = pr.length && (/textarea/i).test(pr[0].nodeName);
3299 soffseth = ista && this._hasScroll(pr[0], "left") /* TODO - jump height */ ? 0 : that.sizeDiff.height;
3300 soffsetw = ista ? 0 : that.sizeDiff.width;
3302 s = { width: (that.helper.width() - soffsetw), height: (that.helper.height() - soffseth) };
3303 left = (parseInt(that.element.css("left"), 10) + (that.position.left - that.originalPosition.left)) || null;
3304 top = (parseInt(that.element.css("top"), 10) + (that.position.top - that.originalPosition.top)) || null;
3307 this.element.css($.extend(s, { top: top, left: left }));
3310 that.helper.height(that.size.height);
3311 that.helper.width(that.size.width);
3313 if (this._helper && !o.animate) {
3314 this._proportionallyResize();
3318 $("body").css("cursor", "auto");
3320 this.element.removeClass("ui-resizable-resizing");
3322 this._propagate("stop", event);
3325 this.helper.remove();
3332 _updateVirtualBoundaries: function(forceAspectRatio) {
3333 var pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b,
3337 minWidth: this._isNumber(o.minWidth) ? o.minWidth : 0,
3338 maxWidth: this._isNumber(o.maxWidth) ? o.maxWidth : Infinity,
3339 minHeight: this._isNumber(o.minHeight) ? o.minHeight : 0,
3340 maxHeight: this._isNumber(o.maxHeight) ? o.maxHeight : Infinity
3343 if(this._aspectRatio || forceAspectRatio) {
3344 pMinWidth = b.minHeight * this.aspectRatio;
3345 pMinHeight = b.minWidth / this.aspectRatio;
3346 pMaxWidth = b.maxHeight * this.aspectRatio;
3347 pMaxHeight = b.maxWidth / this.aspectRatio;
3349 if(pMinWidth > b.minWidth) {
3350 b.minWidth = pMinWidth;
3352 if(pMinHeight > b.minHeight) {
3353 b.minHeight = pMinHeight;
3355 if(pMaxWidth < b.maxWidth) {
3356 b.maxWidth = pMaxWidth;
3358 if(pMaxHeight < b.maxHeight) {
3359 b.maxHeight = pMaxHeight;
3362 this._vBoundaries = b;
3365 _updateCache: function(data) {
3366 this.offset = this.helper.offset();
3367 if (this._isNumber(data.left)) {
3368 this.position.left = data.left;
3370 if (this._isNumber(data.top)) {
3371 this.position.top = data.top;
3373 if (this._isNumber(data.height)) {
3374 this.size.height = data.height;
3376 if (this._isNumber(data.width)) {
3377 this.size.width = data.width;
3381 _updateRatio: function( data ) {
3383 var cpos = this.position,
3387 if (this._isNumber(data.height)) {
3388 data.width = (data.height * this.aspectRatio);
3389 } else if (this._isNumber(data.width)) {
3390 data.height = (data.width / this.aspectRatio);
3394 data.left = cpos.left + (csize.width - data.width);
3398 data.top = cpos.top + (csize.height - data.height);
3399 data.left = cpos.left + (csize.width - data.width);
3405 _respectSize: function( data ) {
3407 var o = this._vBoundaries,
3409 ismaxw = this._isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh = this._isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height),
3410 isminw = this._isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh = this._isNumber(data.height) && o.minHeight && (o.minHeight > data.height),
3411 dw = this.originalPosition.left + this.originalSize.width,
3412 dh = this.position.top + this.size.height,
3413 cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a);
3415 data.width = o.minWidth;
3418 data.height = o.minHeight;
3421 data.width = o.maxWidth;
3424 data.height = o.maxHeight;
3428 data.left = dw - o.minWidth;
3431 data.left = dw - o.maxWidth;
3434 data.top = dh - o.minHeight;
3437 data.top = dh - o.maxHeight;
3440 // Fixing jump error on top/left - bug #2330
3441 if (!data.width && !data.height && !data.left && data.top) {
3443 } else if (!data.width && !data.height && !data.top && data.left) {
3450 _proportionallyResize: function() {
3452 if (!this._proportionallyResizeElements.length) {
3456 var i, j, borders, paddings, prel,
3457 element = this.helper || this.element;
3459 for ( i=0; i < this._proportionallyResizeElements.length; i++) {
3461 prel = this._proportionallyResizeElements[i];
3463 if (!this.borderDif) {
3464 this.borderDif = [];
3465 borders = [prel.css("borderTopWidth"), prel.css("borderRightWidth"), prel.css("borderBottomWidth"), prel.css("borderLeftWidth")];
3466 paddings = [prel.css("paddingTop"), prel.css("paddingRight"), prel.css("paddingBottom"), prel.css("paddingLeft")];
3468 for ( j = 0; j < borders.length; j++ ) {
3469 this.borderDif[ j ] = ( parseInt( borders[ j ], 10 ) || 0 ) + ( parseInt( paddings[ j ], 10 ) || 0 );
3474 height: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0,
3475 width: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0
3482 _renderProxy: function() {
3484 var el = this.element, o = this.options;
3485 this.elementOffset = el.offset();
3489 this.helper = this.helper || $("<div style='overflow:hidden;'></div>");
3491 this.helper.addClass(this._helper).css({
3492 width: this.element.outerWidth() - 1,
3493 height: this.element.outerHeight() - 1,
3494 position: "absolute",
3495 left: this.elementOffset.left +"px",
3496 top: this.elementOffset.top +"px",
3497 zIndex: ++o.zIndex //TODO: Don't modify option
3502 .disableSelection();
3505 this.helper = this.element;
3511 e: function(event, dx) {
3512 return { width: this.originalSize.width + dx };
3514 w: function(event, dx) {
3515 var cs = this.originalSize, sp = this.originalPosition;
3516 return { left: sp.left + dx, width: cs.width - dx };
3518 n: function(event, dx, dy) {
3519 var cs = this.originalSize, sp = this.originalPosition;
3520 return { top: sp.top + dy, height: cs.height - dy };
3522 s: function(event, dx, dy) {
3523 return { height: this.originalSize.height + dy };
3525 se: function(event, dx, dy) {
3526 return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
3528 sw: function(event, dx, dy) {
3529 return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
3531 ne: function(event, dx, dy) {
3532 return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
3534 nw: function(event, dx, dy) {
3535 return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
3539 _propagate: function(n, event) {
3540 $.ui.plugin.call(this, n, [event, this.ui()]);
3541 (n !== "resize" && this._trigger(n, event, this.ui()));
3548 originalElement: this.originalElement,
3549 element: this.element,
3550 helper: this.helper,
3551 position: this.position,
3553 originalSize: this.originalSize,
3554 originalPosition: this.originalPosition,
3555 prevSize: this.prevSize,
3556 prevPosition: this.prevPosition
3563 * Resizable Extensions
3566 $.ui.plugin.add("resizable", "animate", {
3568 stop: function( event ) {
3569 var that = $(this).resizable( "instance" ),
3571 pr = that._proportionallyResizeElements,
3572 ista = pr.length && (/textarea/i).test(pr[0].nodeName),
3573 soffseth = ista && that._hasScroll(pr[0], "left") /* TODO - jump height */ ? 0 : that.sizeDiff.height,
3574 soffsetw = ista ? 0 : that.sizeDiff.width,
3575 style = { width: (that.size.width - soffsetw), height: (that.size.height - soffseth) },
3576 left = (parseInt(that.element.css("left"), 10) + (that.position.left - that.originalPosition.left)) || null,
3577 top = (parseInt(that.element.css("top"), 10) + (that.position.top - that.originalPosition.top)) || null;
3579 that.element.animate(
3580 $.extend(style, top && left ? { top: top, left: left } : {}), {
3581 duration: o.animateDuration,
3582 easing: o.animateEasing,
3586 width: parseInt(that.element.css("width"), 10),
3587 height: parseInt(that.element.css("height"), 10),
3588 top: parseInt(that.element.css("top"), 10),
3589 left: parseInt(that.element.css("left"), 10)
3592 if (pr && pr.length) {
3593 $(pr[0]).css({ width: data.width, height: data.height });
3596 // propagating resize, and updating values for each animation step
3597 that._updateCache(data);
3598 that._propagate("resize", event);
3607 $.ui.plugin.add( "resizable", "containment", {
3610 var element, p, co, ch, cw, width, height,
3611 that = $( this ).resizable( "instance" ),
3615 ce = ( oc instanceof $ ) ? oc.get( 0 ) : ( /parent/.test( oc ) ) ? el.parent().get( 0 ) : oc;
3621 that.containerElement = $( ce );
3623 if ( /document/.test( oc ) || oc === document ) {
3624 that.containerOffset = {
3628 that.containerPosition = {
3634 element: $( document ),
3637 width: $( document ).width(),
3638 height: $( document ).height() || document.body.parentNode.scrollHeight
3643 $([ "Top", "Right", "Left", "Bottom" ]).each(function( i, name ) {
3644 p[ i ] = that._num( element.css( "padding" + name ) );
3647 that.containerOffset = element.offset();
3648 that.containerPosition = element.position();
3649 that.containerSize = {
3650 height: ( element.innerHeight() - p[ 3 ] ),
3651 width: ( element.innerWidth() - p[ 1 ] )
3654 co = that.containerOffset;
3655 ch = that.containerSize.height;
3656 cw = that.containerSize.width;
3657 width = ( that._hasScroll ( ce, "left" ) ? ce.scrollWidth : cw );
3658 height = ( that._hasScroll ( ce ) ? ce.scrollHeight : ch ) ;
3670 resize: function( event, ui ) {
3671 var woset, hoset, isParent, isOffsetRelative,
3672 that = $( this ).resizable( "instance" ),
3674 co = that.containerOffset,
3676 pRatio = that._aspectRatio || event.shiftKey,
3681 ce = that.containerElement,
3682 continueResize = true;
3684 if ( ce[ 0 ] !== document && ( /static/ ).test( ce.css( "position" ) ) ) {
3688 if ( cp.left < ( that._helper ? co.left : 0 ) ) {
3689 that.size.width = that.size.width + ( that._helper ? ( that.position.left - co.left ) : ( that.position.left - cop.left ) );
3691 that.size.height = that.size.width / that.aspectRatio;
3692 continueResize = false;
3694 that.position.left = o.helper ? co.left : 0;
3697 if ( cp.top < ( that._helper ? co.top : 0 ) ) {
3698 that.size.height = that.size.height + ( that._helper ? ( that.position.top - co.top ) : that.position.top );
3700 that.size.width = that.size.height * that.aspectRatio;
3701 continueResize = false;
3703 that.position.top = that._helper ? co.top : 0;
3706 that.offset.left = that.parentData.left + that.position.left;
3707 that.offset.top = that.parentData.top + that.position.top;
3709 woset = Math.abs( ( that._helper ? that.offset.left - cop.left : ( that.offset.left - co.left ) ) + that.sizeDiff.width );
3710 hoset = Math.abs( ( that._helper ? that.offset.top - cop.top : ( that.offset.top - co.top ) ) + that.sizeDiff.height );
3712 isParent = that.containerElement.get( 0 ) === that.element.parent().get( 0 );
3713 isOffsetRelative = /relative|absolute/.test( that.containerElement.css( "position" ) );
3715 if ( isParent && isOffsetRelative ) {
3716 woset -= Math.abs( that.parentData.left );
3719 if ( woset + that.size.width >= that.parentData.width ) {
3720 that.size.width = that.parentData.width - woset;
3722 that.size.height = that.size.width / that.aspectRatio;
3723 continueResize = false;
3727 if ( hoset + that.size.height >= that.parentData.height ) {
3728 that.size.height = that.parentData.height - hoset;
3730 that.size.width = that.size.height * that.aspectRatio;
3731 continueResize = false;
3735 if ( !continueResize ){
3736 that.position.left = ui.prevPosition.left;
3737 that.position.top = ui.prevPosition.top;
3738 that.size.width = ui.prevSize.width;
3739 that.size.height = ui.prevSize.height;
3744 var that = $( this ).resizable( "instance" ),
3746 co = that.containerOffset,
3747 cop = that.containerPosition,
3748 ce = that.containerElement,
3749 helper = $( that.helper ),
3750 ho = helper.offset(),
3751 w = helper.outerWidth() - that.sizeDiff.width,
3752 h = helper.outerHeight() - that.sizeDiff.height;
3754 if ( that._helper && !o.animate && ( /relative/ ).test( ce.css( "position" ) ) ) {
3756 left: ho.left - cop.left - co.left,
3762 if ( that._helper && !o.animate && ( /static/ ).test( ce.css( "position" ) ) ) {
3764 left: ho.left - cop.left - co.left,
3772 $.ui.plugin.add("resizable", "alsoResize", {
3774 start: function () {
3775 var that = $(this).resizable( "instance" ),
3777 _store = function (exp) {
3778 $(exp).each(function() {
3780 el.data("ui-resizable-alsoresize", {
3781 width: parseInt(el.width(), 10), height: parseInt(el.height(), 10),
3782 left: parseInt(el.css("left"), 10), top: parseInt(el.css("top"), 10)
3787 if (typeof(o.alsoResize) === "object" && !o.alsoResize.parentNode) {
3788 if (o.alsoResize.length) { o.alsoResize = o.alsoResize[0]; _store(o.alsoResize); }
3789 else { $.each(o.alsoResize, function (exp) { _store(exp); }); }
3791 _store(o.alsoResize);
3795 resize: function (event, ui) {
3796 var that = $(this).resizable( "instance" ),
3798 os = that.originalSize,
3799 op = that.originalPosition,
3801 height: (that.size.height - os.height) || 0, width: (that.size.width - os.width) || 0,
3802 top: (that.position.top - op.top) || 0, left: (that.position.left - op.left) || 0
3805 _alsoResize = function (exp, c) {
3806 $(exp).each(function() {
3807 var el = $(this), start = $(this).data("ui-resizable-alsoresize"), style = {},
3808 css = c && c.length ? c : el.parents(ui.originalElement[0]).length ? ["width", "height"] : ["width", "height", "top", "left"];
3810 $.each(css, function (i, prop) {
3811 var sum = (start[prop]||0) + (delta[prop]||0);
3812 if (sum && sum >= 0) {
3813 style[prop] = sum || null;
3821 if (typeof(o.alsoResize) === "object" && !o.alsoResize.nodeType) {
3822 $.each(o.alsoResize, function (exp, c) { _alsoResize(exp, c); });
3824 _alsoResize(o.alsoResize);
3829 $(this).removeData("resizable-alsoresize");
3833 $.ui.plugin.add("resizable", "ghost", {
3837 var that = $(this).resizable( "instance" ), o = that.options, cs = that.size;
3839 that.ghost = that.originalElement.clone();
3841 .css({ opacity: 0.25, display: "block", position: "relative", height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 })
3842 .addClass("ui-resizable-ghost")
3843 .addClass(typeof o.ghost === "string" ? o.ghost : "");
3845 that.ghost.appendTo(that.helper);
3850 var that = $(this).resizable( "instance" );
3852 that.ghost.css({ position: "relative", height: that.size.height, width: that.size.width });
3857 var that = $(this).resizable( "instance" );
3858 if (that.ghost && that.helper) {
3859 that.helper.get(0).removeChild(that.ghost.get(0));
3865 $.ui.plugin.add("resizable", "grid", {
3867 resize: function() {
3868 var that = $(this).resizable( "instance" ),
3871 os = that.originalSize,
3872 op = that.originalPosition,
3874 grid = typeof o.grid === "number" ? [o.grid, o.grid] : o.grid,
3875 gridX = (grid[0]||1),
3876 gridY = (grid[1]||1),
3877 ox = Math.round((cs.width - os.width) / gridX) * gridX,
3878 oy = Math.round((cs.height - os.height) / gridY) * gridY,
3879 newWidth = os.width + ox,
3880 newHeight = os.height + oy,
3881 isMaxWidth = o.maxWidth && (o.maxWidth < newWidth),
3882 isMaxHeight = o.maxHeight && (o.maxHeight < newHeight),
3883 isMinWidth = o.minWidth && (o.minWidth > newWidth),
3884 isMinHeight = o.minHeight && (o.minHeight > newHeight);
3889 newWidth = newWidth + gridX;
3892 newHeight = newHeight + gridY;
3895 newWidth = newWidth - gridX;
3898 newHeight = newHeight - gridY;
3901 if (/^(se|s|e)$/.test(a)) {
3902 that.size.width = newWidth;
3903 that.size.height = newHeight;
3904 } else if (/^(ne)$/.test(a)) {
3905 that.size.width = newWidth;
3906 that.size.height = newHeight;
3907 that.position.top = op.top - oy;
3908 } else if (/^(sw)$/.test(a)) {
3909 that.size.width = newWidth;
3910 that.size.height = newHeight;
3911 that.position.left = op.left - ox;
3913 if ( newHeight - gridY > 0 ) {
3914 that.size.height = newHeight;
3915 that.position.top = op.top - oy;
3917 that.size.height = gridY;
3918 that.position.top = op.top + os.height - gridY;
3920 if ( newWidth - gridX > 0 ) {
3921 that.size.width = newWidth;
3922 that.position.left = op.left - ox;
3924 that.size.width = gridX;
3925 that.position.left = op.left + os.width - gridX;
3932 var resizable = $.ui.resizable;
3936 * jQuery UI Selectable 1.11.0
3937 * http://jqueryui.com
3939 * Copyright 2014 jQuery Foundation and other contributors
3940 * Released under the MIT license.
3941 * http://jquery.org/license
3943 * http://api.jqueryui.com/selectable/
3947 var selectable = $.widget("ui.selectable", $.ui.mouse, {
3964 _create: function() {
3968 this.element.addClass("ui-selectable");
3970 this.dragged = false;
3972 // cache selectee children based on filter
3973 this.refresh = function() {
3974 selectees = $(that.options.filter, that.element[0]);
3975 selectees.addClass("ui-selectee");
3976 selectees.each(function() {
3977 var $this = $(this),
3978 pos = $this.offset();
3979 $.data(this, "selectable-item", {
3984 right: pos.left + $this.outerWidth(),
3985 bottom: pos.top + $this.outerHeight(),
3986 startselected: false,
3987 selected: $this.hasClass("ui-selected"),
3988 selecting: $this.hasClass("ui-selecting"),
3989 unselecting: $this.hasClass("ui-unselecting")
3995 this.selectees = selectees.addClass("ui-selectee");
3999 this.helper = $("<div class='ui-selectable-helper'></div>");
4002 _destroy: function() {
4004 .removeClass("ui-selectee")
4005 .removeData("selectable-item");
4007 .removeClass("ui-selectable ui-selectable-disabled");
4008 this._mouseDestroy();
4011 _mouseStart: function(event) {
4013 options = this.options;
4015 this.opos = [ event.pageX, event.pageY ];
4017 if (this.options.disabled) {
4021 this.selectees = $(options.filter, this.element[0]);
4023 this._trigger("start", event);
4025 $(options.appendTo).append(this.helper);
4026 // position helper (lasso)
4028 "left": event.pageX,
4034 if (options.autoRefresh) {
4038 this.selectees.filter(".ui-selected").each(function() {
4039 var selectee = $.data(this, "selectable-item");
4040 selectee.startselected = true;
4041 if (!event.metaKey && !event.ctrlKey) {
4042 selectee.$element.removeClass("ui-selected");
4043 selectee.selected = false;
4044 selectee.$element.addClass("ui-unselecting");
4045 selectee.unselecting = true;
4046 // selectable UNSELECTING callback
4047 that._trigger("unselecting", event, {
4048 unselecting: selectee.element
4053 $(event.target).parents().addBack().each(function() {
4055 selectee = $.data(this, "selectable-item");
4057 doSelect = (!event.metaKey && !event.ctrlKey) || !selectee.$element.hasClass("ui-selected");
4059 .removeClass(doSelect ? "ui-unselecting" : "ui-selected")
4060 .addClass(doSelect ? "ui-selecting" : "ui-unselecting");
4061 selectee.unselecting = !doSelect;
4062 selectee.selecting = doSelect;
4063 selectee.selected = doSelect;
4064 // selectable (UN)SELECTING callback
4066 that._trigger("selecting", event, {
4067 selecting: selectee.element
4070 that._trigger("unselecting", event, {
4071 unselecting: selectee.element
4080 _mouseDrag: function(event) {
4082 this.dragged = true;
4084 if (this.options.disabled) {
4090 options = this.options,
4096 if (x1 > x2) { tmp = x2; x2 = x1; x1 = tmp; }
4097 if (y1 > y2) { tmp = y2; y2 = y1; y1 = tmp; }
4098 this.helper.css({ left: x1, top: y1, width: x2 - x1, height: y2 - y1 });
4100 this.selectees.each(function() {
4101 var selectee = $.data(this, "selectable-item"),
4104 //prevent helper from being selected if appendTo: selectable
4105 if (!selectee || selectee.element === that.element[0]) {
4109 if (options.tolerance === "touch") {
4110 hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) );
4111 } else if (options.tolerance === "fit") {
4112 hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2);
4117 if (selectee.selected) {
4118 selectee.$element.removeClass("ui-selected");
4119 selectee.selected = false;
4121 if (selectee.unselecting) {
4122 selectee.$element.removeClass("ui-unselecting");
4123 selectee.unselecting = false;
4125 if (!selectee.selecting) {
4126 selectee.$element.addClass("ui-selecting");
4127 selectee.selecting = true;
4128 // selectable SELECTING callback
4129 that._trigger("selecting", event, {
4130 selecting: selectee.element
4135 if (selectee.selecting) {
4136 if ((event.metaKey || event.ctrlKey) && selectee.startselected) {
4137 selectee.$element.removeClass("ui-selecting");
4138 selectee.selecting = false;
4139 selectee.$element.addClass("ui-selected");
4140 selectee.selected = true;
4142 selectee.$element.removeClass("ui-selecting");
4143 selectee.selecting = false;
4144 if (selectee.startselected) {
4145 selectee.$element.addClass("ui-unselecting");
4146 selectee.unselecting = true;
4148 // selectable UNSELECTING callback
4149 that._trigger("unselecting", event, {
4150 unselecting: selectee.element
4154 if (selectee.selected) {
4155 if (!event.metaKey && !event.ctrlKey && !selectee.startselected) {
4156 selectee.$element.removeClass("ui-selected");
4157 selectee.selected = false;
4159 selectee.$element.addClass("ui-unselecting");
4160 selectee.unselecting = true;
4161 // selectable UNSELECTING callback
4162 that._trigger("unselecting", event, {
4163 unselecting: selectee.element
4173 _mouseStop: function(event) {
4176 this.dragged = false;
4178 $(".ui-unselecting", this.element[0]).each(function() {
4179 var selectee = $.data(this, "selectable-item");
4180 selectee.$element.removeClass("ui-unselecting");
4181 selectee.unselecting = false;
4182 selectee.startselected = false;
4183 that._trigger("unselected", event, {
4184 unselected: selectee.element
4187 $(".ui-selecting", this.element[0]).each(function() {
4188 var selectee = $.data(this, "selectable-item");
4189 selectee.$element.removeClass("ui-selecting").addClass("ui-selected");
4190 selectee.selecting = false;
4191 selectee.selected = true;
4192 selectee.startselected = true;
4193 that._trigger("selected", event, {
4194 selected: selectee.element
4197 this._trigger("stop", event);
4199 this.helper.remove();
4208 * jQuery UI Sortable 1.11.0
4209 * http://jqueryui.com
4211 * Copyright 2014 jQuery Foundation and other contributors
4212 * Released under the MIT license.
4213 * http://jquery.org/license
4215 * http://api.jqueryui.com/sortable/
4219 var sortable = $.widget("ui.sortable", $.ui.mouse, {
4221 widgetEventPrefix: "sort",
4231 forcePlaceholderSize: false,
4232 forceHelperSize: false,
4241 scrollSensitivity: 20,
4244 tolerance: "intersect",
4262 _isOverAxis: function( x, reference, size ) {
4263 return ( x >= reference ) && ( x < ( reference + size ) );
4266 _isFloating: function( item ) {
4267 return (/left|right/).test(item.css("float")) || (/inline|table-cell/).test(item.css("display"));
4270 _create: function() {
4272 var o = this.options;
4273 this.containerCache = {};
4274 this.element.addClass("ui-sortable");
4279 //Let's determine if the items are being displayed horizontally
4280 this.floating = this.items.length ? o.axis === "x" || this._isFloating(this.items[0].item) : false;
4282 //Let's determine the parent's offset
4283 this.offset = this.element.offset();
4285 //Initialize mouse events for interaction
4288 this._setHandleClassName();
4295 _setOption: function( key, value ) {
4296 this._super( key, value );
4298 if ( key === "handle" ) {
4299 this._setHandleClassName();
4303 _setHandleClassName: function() {
4304 this.element.find( ".ui-sortable-handle" ).removeClass( "ui-sortable-handle" );
4305 $.each( this.items, function() {
4306 ( this.instance.options.handle ?
4307 this.item.find( this.instance.options.handle ) : this.item )
4308 .addClass( "ui-sortable-handle" );
4312 _destroy: function() {
4314 .removeClass( "ui-sortable ui-sortable-disabled" )
4315 .find( ".ui-sortable-handle" )
4316 .removeClass( "ui-sortable-handle" );
4317 this._mouseDestroy();
4319 for ( var i = this.items.length - 1; i >= 0; i-- ) {
4320 this.items[i].item.removeData(this.widgetName + "-item");
4326 _mouseCapture: function(event, overrideHandle) {
4327 var currentItem = null,
4328 validHandle = false,
4331 if (this.reverting) {
4335 if(this.options.disabled || this.options.type === "static") {
4339 //We have to refresh the items data once first
4340 this._refreshItems(event);
4342 //Find out if the clicked node (or one of its parents) is a actual item in this.items
4343 $(event.target).parents().each(function() {
4344 if($.data(this, that.widgetName + "-item") === that) {
4345 currentItem = $(this);
4349 if($.data(event.target, that.widgetName + "-item") === that) {
4350 currentItem = $(event.target);
4356 if(this.options.handle && !overrideHandle) {
4357 $(this.options.handle, currentItem).find("*").addBack().each(function() {
4358 if(this === event.target) {
4367 this.currentItem = currentItem;
4368 this._removeCurrentsFromItems();
4373 _mouseStart: function(event, overrideHandle, noActivation) {
4378 this.currentContainer = this;
4380 //We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture
4381 this.refreshPositions();
4383 //Create and append the visible helper
4384 this.helper = this._createHelper(event);
4386 //Cache the helper size
4387 this._cacheHelperProportions();
4390 * - Position generation -
4391 * This block generates everything position related - it's the core of draggables.
4394 //Cache the margins of the original element
4395 this._cacheMargins();
4397 //Get the next scrolling parent
4398 this.scrollParent = this.helper.scrollParent();
4400 //The element's absolute position on the page minus margins
4401 this.offset = this.currentItem.offset();
4403 top: this.offset.top - this.margins.top,
4404 left: this.offset.left - this.margins.left
4407 $.extend(this.offset, {
4408 click: { //Where the click happened, relative to the element
4409 left: event.pageX - this.offset.left,
4410 top: event.pageY - this.offset.top
4412 parent: this._getParentOffset(),
4413 relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
4416 // Only after we got the offset, we can change the helper's position to absolute
4417 // TODO: Still need to figure out a way to make relative sorting possible
4418 this.helper.css("position", "absolute");
4419 this.cssPosition = this.helper.css("position");
4421 //Generate the original position
4422 this.originalPosition = this._generatePosition(event);
4423 this.originalPageX = event.pageX;
4424 this.originalPageY = event.pageY;
4426 //Adjust the mouse offset relative to the helper if "cursorAt" is supplied
4427 (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
4429 //Cache the former DOM position
4430 this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] };
4432 //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
4433 if(this.helper[0] !== this.currentItem[0]) {
4434 this.currentItem.hide();
4437 //Create the placeholder
4438 this._createPlaceholder();
4440 //Set a containment if given in the options
4442 this._setContainment();
4445 if( o.cursor && o.cursor !== "auto" ) { // cursor option
4446 body = this.document.find( "body" );
4449 this.storedCursor = body.css( "cursor" );
4450 body.css( "cursor", o.cursor );
4452 this.storedStylesheet = $( "<style>*{ cursor: "+o.cursor+" !important; }</style>" ).appendTo( body );
4455 if(o.opacity) { // opacity option
4456 if (this.helper.css("opacity")) {
4457 this._storedOpacity = this.helper.css("opacity");
4459 this.helper.css("opacity", o.opacity);
4462 if(o.zIndex) { // zIndex option
4463 if (this.helper.css("zIndex")) {
4464 this._storedZIndex = this.helper.css("zIndex");
4466 this.helper.css("zIndex", o.zIndex);
4470 if(this.scrollParent[0] !== document && this.scrollParent[0].tagName !== "HTML") {
4471 this.overflowOffset = this.scrollParent.offset();
4475 this._trigger("start", event, this._uiHash());
4477 //Recache the helper size
4478 if(!this._preserveHelperProportions) {
4479 this._cacheHelperProportions();
4483 //Post "activate" events to possible containers
4484 if( !noActivation ) {
4485 for ( i = this.containers.length - 1; i >= 0; i-- ) {
4486 this.containers[ i ]._trigger( "activate", event, this._uiHash( this ) );
4490 //Prepare possible droppables
4491 if($.ui.ddmanager) {
4492 $.ui.ddmanager.current = this;
4495 if ($.ui.ddmanager && !o.dropBehaviour) {
4496 $.ui.ddmanager.prepareOffsets(this, event);
4499 this.dragging = true;
4501 this.helper.addClass("ui-sortable-helper");
4502 this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position
4507 _mouseDrag: function(event) {
4508 var i, item, itemElement, intersection,
4512 //Compute the helpers position
4513 this.position = this._generatePosition(event);
4514 this.positionAbs = this._convertPositionTo("absolute");
4516 if (!this.lastPositionAbs) {
4517 this.lastPositionAbs = this.positionAbs;
4521 if(this.options.scroll) {
4522 if(this.scrollParent[0] !== document && this.scrollParent[0].tagName !== "HTML") {
4524 if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) {
4525 this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed;
4526 } else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity) {
4527 this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed;
4530 if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) {
4531 this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed;
4532 } else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity) {
4533 this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed;
4538 if(event.pageY - $(document).scrollTop() < o.scrollSensitivity) {
4539 scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
4540 } else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) {
4541 scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
4544 if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity) {
4545 scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
4546 } else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) {
4547 scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
4552 if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) {
4553 $.ui.ddmanager.prepareOffsets(this, event);
4557 //Regenerate the absolute position used for position checks
4558 this.positionAbs = this._convertPositionTo("absolute");
4560 //Set the helper position
4561 if(!this.options.axis || this.options.axis !== "y") {
4562 this.helper[0].style.left = this.position.left+"px";
4564 if(!this.options.axis || this.options.axis !== "x") {
4565 this.helper[0].style.top = this.position.top+"px";
4569 for (i = this.items.length - 1; i >= 0; i--) {
4571 //Cache variables and intersection, continue if no intersection
4572 item = this.items[i];
4573 itemElement = item.item[0];
4574 intersection = this._intersectsWithPointer(item);
4575 if (!intersection) {
4579 // Only put the placeholder inside the current Container, skip all
4580 // items from other containers. This works because when moving
4581 // an item from one container to another the
4582 // currentContainer is switched before the placeholder is moved.
4584 // Without this, moving items in "sub-sortables" can cause
4585 // the placeholder to jitter between the outer and inner container.
4586 if (item.instance !== this.currentContainer) {
4590 // cannot intersect with itself
4591 // no useless actions that have been done before
4592 // no action if the item moved is the parent of the item checked
4593 if (itemElement !== this.currentItem[0] &&
4594 this.placeholder[intersection === 1 ? "next" : "prev"]()[0] !== itemElement &&
4595 !$.contains(this.placeholder[0], itemElement) &&
4596 (this.options.type === "semi-dynamic" ? !$.contains(this.element[0], itemElement) : true)
4599 this.direction = intersection === 1 ? "down" : "up";
4601 if (this.options.tolerance === "pointer" || this._intersectsWithSides(item)) {
4602 this._rearrange(event, item);
4607 this._trigger("change", event, this._uiHash());
4612 //Post events to containers
4613 this._contactContainers(event);
4615 //Interconnect with droppables
4616 if($.ui.ddmanager) {
4617 $.ui.ddmanager.drag(this, event);
4621 this._trigger("sort", event, this._uiHash());
4623 this.lastPositionAbs = this.positionAbs;
4628 _mouseStop: function(event, noPropagation) {
4634 //If we are using droppables, inform the manager about the drop
4635 if ($.ui.ddmanager && !this.options.dropBehaviour) {
4636 $.ui.ddmanager.drop(this, event);
4639 if(this.options.revert) {
4641 cur = this.placeholder.offset(),
4642 axis = this.options.axis,
4645 if ( !axis || axis === "x" ) {
4646 animation.left = cur.left - this.offset.parent.left - this.margins.left + (this.offsetParent[0] === document.body ? 0 : this.offsetParent[0].scrollLeft);
4648 if ( !axis || axis === "y" ) {
4649 animation.top = cur.top - this.offset.parent.top - this.margins.top + (this.offsetParent[0] === document.body ? 0 : this.offsetParent[0].scrollTop);
4651 this.reverting = true;
4652 $(this.helper).animate( animation, parseInt(this.options.revert, 10) || 500, function() {
4656 this._clear(event, noPropagation);
4663 cancel: function() {
4667 this._mouseUp({ target: null });
4669 if(this.options.helper === "original") {
4670 this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
4672 this.currentItem.show();
4675 //Post deactivating events to containers
4676 for (var i = this.containers.length - 1; i >= 0; i--){
4677 this.containers[i]._trigger("deactivate", null, this._uiHash(this));
4678 if(this.containers[i].containerCache.over) {
4679 this.containers[i]._trigger("out", null, this._uiHash(this));
4680 this.containers[i].containerCache.over = 0;
4686 if (this.placeholder) {
4687 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
4688 if(this.placeholder[0].parentNode) {
4689 this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
4691 if(this.options.helper !== "original" && this.helper && this.helper[0].parentNode) {
4692 this.helper.remove();
4702 if(this.domPosition.prev) {
4703 $(this.domPosition.prev).after(this.currentItem);
4705 $(this.domPosition.parent).prepend(this.currentItem);
4713 serialize: function(o) {
4715 var items = this._getItemsAsjQuery(o && o.connected),
4719 $(items).each(function() {
4720 var res = ($(o.item || this).attr(o.attribute || "id") || "").match(o.expression || (/(.+)[\-=_](.+)/));
4722 str.push((o.key || res[1]+"[]")+"="+(o.key && o.expression ? res[1] : res[2]));
4726 if(!str.length && o.key) {
4727 str.push(o.key + "=");
4730 return str.join("&");
4734 toArray: function(o) {
4736 var items = this._getItemsAsjQuery(o && o.connected),
4741 items.each(function() { ret.push($(o.item || this).attr(o.attribute || "id") || ""); });
4746 /* Be careful with the following core functions */
4747 _intersectsWith: function(item) {
4749 var x1 = this.positionAbs.left,
4750 x2 = x1 + this.helperProportions.width,
4751 y1 = this.positionAbs.top,
4752 y2 = y1 + this.helperProportions.height,
4756 b = t + item.height,
4757 dyClick = this.offset.click.top,
4758 dxClick = this.offset.click.left,
4759 isOverElementHeight = ( this.options.axis === "x" ) || ( ( y1 + dyClick ) > t && ( y1 + dyClick ) < b ),
4760 isOverElementWidth = ( this.options.axis === "y" ) || ( ( x1 + dxClick ) > l && ( x1 + dxClick ) < r ),
4761 isOverElement = isOverElementHeight && isOverElementWidth;
4763 if ( this.options.tolerance === "pointer" ||
4764 this.options.forcePointerForContainers ||
4765 (this.options.tolerance !== "pointer" && this.helperProportions[this.floating ? "width" : "height"] > item[this.floating ? "width" : "height"])
4767 return isOverElement;
4770 return (l < x1 + (this.helperProportions.width / 2) && // Right Half
4771 x2 - (this.helperProportions.width / 2) < r && // Left Half
4772 t < y1 + (this.helperProportions.height / 2) && // Bottom Half
4773 y2 - (this.helperProportions.height / 2) < b ); // Top Half
4778 _intersectsWithPointer: function(item) {
4780 var isOverElementHeight = (this.options.axis === "x") || this._isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height),
4781 isOverElementWidth = (this.options.axis === "y") || this._isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width),
4782 isOverElement = isOverElementHeight && isOverElementWidth,
4783 verticalDirection = this._getDragVerticalDirection(),
4784 horizontalDirection = this._getDragHorizontalDirection();
4786 if (!isOverElement) {
4790 return this.floating ?
4791 ( ((horizontalDirection && horizontalDirection === "right") || verticalDirection === "down") ? 2 : 1 )
4792 : ( verticalDirection && (verticalDirection === "down" ? 2 : 1) );
4796 _intersectsWithSides: function(item) {
4798 var isOverBottomHalf = this._isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height),
4799 isOverRightHalf = this._isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width),
4800 verticalDirection = this._getDragVerticalDirection(),
4801 horizontalDirection = this._getDragHorizontalDirection();
4803 if (this.floating && horizontalDirection) {
4804 return ((horizontalDirection === "right" && isOverRightHalf) || (horizontalDirection === "left" && !isOverRightHalf));
4806 return verticalDirection && ((verticalDirection === "down" && isOverBottomHalf) || (verticalDirection === "up" && !isOverBottomHalf));
4811 _getDragVerticalDirection: function() {
4812 var delta = this.positionAbs.top - this.lastPositionAbs.top;
4813 return delta !== 0 && (delta > 0 ? "down" : "up");
4816 _getDragHorizontalDirection: function() {
4817 var delta = this.positionAbs.left - this.lastPositionAbs.left;
4818 return delta !== 0 && (delta > 0 ? "right" : "left");
4821 refresh: function(event) {
4822 this._refreshItems(event);
4823 this._setHandleClassName();
4824 this.refreshPositions();
4828 _connectWith: function() {
4829 var options = this.options;
4830 return options.connectWith.constructor === String ? [options.connectWith] : options.connectWith;
4833 _getItemsAsjQuery: function(connected) {
4835 var i, j, cur, inst,
4838 connectWith = this._connectWith();
4840 if(connectWith && connected) {
4841 for (i = connectWith.length - 1; i >= 0; i--){
4842 cur = $(connectWith[i]);
4843 for ( j = cur.length - 1; j >= 0; j--){
4844 inst = $.data(cur[j], this.widgetFullName);
4845 if(inst && inst !== this && !inst.options.disabled) {
4846 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]);
4852 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]);
4854 function addItems() {
4857 for (i = queries.length - 1; i >= 0; i--){
4858 queries[i][0].each( addItems );
4865 _removeCurrentsFromItems: function() {
4867 var list = this.currentItem.find(":data(" + this.widgetName + "-item)");
4869 this.items = $.grep(this.items, function (item) {
4870 for (var j=0; j < list.length; j++) {
4871 if(list[j] === item.item[0]) {
4880 _refreshItems: function(event) {
4883 this.containers = [this];
4885 var i, j, cur, inst, targetData, _queries, item, queriesLength,
4887 queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]],
4888 connectWith = this._connectWith();
4890 if(connectWith && this.ready) { //Shouldn't be run the first time through due to massive slow-down
4891 for (i = connectWith.length - 1; i >= 0; i--){
4892 cur = $(connectWith[i]);
4893 for (j = cur.length - 1; j >= 0; j--){
4894 inst = $.data(cur[j], this.widgetFullName);
4895 if(inst && inst !== this && !inst.options.disabled) {
4896 queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]);
4897 this.containers.push(inst);
4903 for (i = queries.length - 1; i >= 0; i--) {
4904 targetData = queries[i][1];
4905 _queries = queries[i][0];
4907 for (j=0, queriesLength = _queries.length; j < queriesLength; j++) {
4908 item = $(_queries[j]);
4910 item.data(this.widgetName + "-item", targetData); // Data for target checking (mouse manager)
4914 instance: targetData,
4915 width: 0, height: 0,
4923 refreshPositions: function(fast) {
4925 //This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change
4926 if(this.offsetParent && this.helper) {
4927 this.offset.parent = this._getParentOffset();
4932 for (i = this.items.length - 1; i >= 0; i--){
4933 item = this.items[i];
4935 //We ignore calculating positions of all connected containers when we're not over them
4936 if(item.instance !== this.currentContainer && this.currentContainer && item.item[0] !== this.currentItem[0]) {
4940 t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item;
4943 item.width = t.outerWidth();
4944 item.height = t.outerHeight();
4952 if(this.options.custom && this.options.custom.refreshContainers) {
4953 this.options.custom.refreshContainers.call(this);
4955 for (i = this.containers.length - 1; i >= 0; i--){
4956 p = this.containers[i].element.offset();
4957 this.containers[i].containerCache.left = p.left;
4958 this.containers[i].containerCache.top = p.top;
4959 this.containers[i].containerCache.width = this.containers[i].element.outerWidth();
4960 this.containers[i].containerCache.height = this.containers[i].element.outerHeight();
4967 _createPlaceholder: function(that) {
4968 that = that || this;
4972 if(!o.placeholder || o.placeholder.constructor === String) {
4973 className = o.placeholder;
4975 element: function() {
4977 var nodeName = that.currentItem[0].nodeName.toLowerCase(),
4978 element = $( "<" + nodeName + ">", that.document[0] )
4979 .addClass(className || that.currentItem[0].className+" ui-sortable-placeholder")
4980 .removeClass("ui-sortable-helper");
4982 if ( nodeName === "tr" ) {
4983 that.currentItem.children().each(function() {
4984 $( "<td> </td>", that.document[0] )
4985 .attr( "colspan", $( this ).attr( "colspan" ) || 1 )
4986 .appendTo( element );
4988 } else if ( nodeName === "img" ) {
4989 element.attr( "src", that.currentItem.attr( "src" ) );
4993 element.css( "visibility", "hidden" );
4998 update: function(container, p) {
5000 // 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that
5001 // 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified
5002 if(className && !o.forcePlaceholderSize) {
5006 //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
5007 if(!p.height()) { p.height(that.currentItem.innerHeight() - parseInt(that.currentItem.css("paddingTop")||0, 10) - parseInt(that.currentItem.css("paddingBottom")||0, 10)); }
5008 if(!p.width()) { p.width(that.currentItem.innerWidth() - parseInt(that.currentItem.css("paddingLeft")||0, 10) - parseInt(that.currentItem.css("paddingRight")||0, 10)); }
5013 //Create the placeholder
5014 that.placeholder = $(o.placeholder.element.call(that.element, that.currentItem));
5016 //Append it after the actual current item
5017 that.currentItem.after(that.placeholder);
5019 //Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
5020 o.placeholder.update(that, that.placeholder);
5024 _contactContainers: function(event) {
5025 var i, j, dist, itemWithLeastDistance, posProperty, sizeProperty, cur, nearBottom, floating, axis,
5026 innermostContainer = null,
5027 innermostIndex = null;
5029 // get innermost container that intersects with item
5030 for (i = this.containers.length - 1; i >= 0; i--) {
5032 // never consider a container that's located within the item itself
5033 if($.contains(this.currentItem[0], this.containers[i].element[0])) {
5037 if(this._intersectsWith(this.containers[i].containerCache)) {
5039 // if we've already found a container and it's more "inner" than this, then continue
5040 if(innermostContainer && $.contains(this.containers[i].element[0], innermostContainer.element[0])) {
5044 innermostContainer = this.containers[i];
5048 // container doesn't intersect. trigger "out" event if necessary
5049 if(this.containers[i].containerCache.over) {
5050 this.containers[i]._trigger("out", event, this._uiHash(this));
5051 this.containers[i].containerCache.over = 0;
5057 // if no intersecting containers found, return
5058 if(!innermostContainer) {
5062 // move the item into the container if it's not there already
5063 if(this.containers.length === 1) {
5064 if (!this.containers[innermostIndex].containerCache.over) {
5065 this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
5066 this.containers[innermostIndex].containerCache.over = 1;
5070 //When entering a new container, we will find the item with the least distance and append our item near it
5072 itemWithLeastDistance = null;
5073 floating = innermostContainer.floating || this._isFloating(this.currentItem);
5074 posProperty = floating ? "left" : "top";
5075 sizeProperty = floating ? "width" : "height";
5076 axis = floating ? "clientX" : "clientY";
5078 for (j = this.items.length - 1; j >= 0; j--) {
5079 if(!$.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) {
5082 if(this.items[j].item[0] === this.currentItem[0]) {
5086 cur = this.items[j].item.offset()[posProperty];
5088 if ( event[ axis ] - cur > this.items[ j ][ sizeProperty ] / 2 ) {
5092 if ( Math.abs( event[ axis ] - cur ) < dist ) {
5093 dist = Math.abs( event[ axis ] - cur );
5094 itemWithLeastDistance = this.items[ j ];
5095 this.direction = nearBottom ? "up": "down";
5099 //Check if dropOnEmpty is enabled
5100 if(!itemWithLeastDistance && !this.options.dropOnEmpty) {
5104 if(this.currentContainer === this.containers[innermostIndex]) {
5108 itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true);
5109 this._trigger("change", event, this._uiHash());
5110 this.containers[innermostIndex]._trigger("change", event, this._uiHash(this));
5111 this.currentContainer = this.containers[innermostIndex];
5113 //Update the placeholder
5114 this.options.placeholder.update(this.currentContainer, this.placeholder);
5116 this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
5117 this.containers[innermostIndex].containerCache.over = 1;
5123 _createHelper: function(event) {
5125 var o = this.options,
5126 helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper === "clone" ? this.currentItem.clone() : this.currentItem);
5128 //Add the helper to the DOM if that didn't happen already
5129 if(!helper.parents("body").length) {
5130 $(o.appendTo !== "parent" ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]);
5133 if(helper[0] === this.currentItem[0]) {
5134 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") };
5137 if(!helper[0].style.width || o.forceHelperSize) {
5138 helper.width(this.currentItem.width());
5140 if(!helper[0].style.height || o.forceHelperSize) {
5141 helper.height(this.currentItem.height());
5148 _adjustOffsetFromHelper: function(obj) {
5149 if (typeof obj === "string") {
5150 obj = obj.split(" ");
5152 if ($.isArray(obj)) {
5153 obj = {left: +obj[0], top: +obj[1] || 0};
5155 if ("left" in obj) {
5156 this.offset.click.left = obj.left + this.margins.left;
5158 if ("right" in obj) {
5159 this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
5162 this.offset.click.top = obj.top + this.margins.top;
5164 if ("bottom" in obj) {
5165 this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
5169 _getParentOffset: function() {
5172 //Get the offsetParent and cache its position
5173 this.offsetParent = this.helper.offsetParent();
5174 var po = this.offsetParent.offset();
5176 // This is a special case where we need to modify a offset calculated on start, since the following happened:
5177 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
5178 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
5179 // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
5180 if(this.cssPosition === "absolute" && this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) {
5181 po.left += this.scrollParent.scrollLeft();
5182 po.top += this.scrollParent.scrollTop();
5185 // This needs to be actually done for all browsers, since pageX/pageY includes this information
5186 // with an ugly IE fix
5187 if( this.offsetParent[0] === document.body || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() === "html" && $.ui.ie)) {
5188 po = { top: 0, left: 0 };
5192 top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
5193 left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
5198 _getRelativeOffset: function() {
5200 if(this.cssPosition === "relative") {
5201 var p = this.currentItem.position();
5203 top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
5204 left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
5207 return { top: 0, left: 0 };
5212 _cacheMargins: function() {
5214 left: (parseInt(this.currentItem.css("marginLeft"),10) || 0),
5215 top: (parseInt(this.currentItem.css("marginTop"),10) || 0)
5219 _cacheHelperProportions: function() {
5220 this.helperProportions = {
5221 width: this.helper.outerWidth(),
5222 height: this.helper.outerHeight()
5226 _setContainment: function() {
5230 if(o.containment === "parent") {
5231 o.containment = this.helper[0].parentNode;
5233 if(o.containment === "document" || o.containment === "window") {
5234 this.containment = [
5235 0 - this.offset.relative.left - this.offset.parent.left,
5236 0 - this.offset.relative.top - this.offset.parent.top,
5237 $(o.containment === "document" ? document : window).width() - this.helperProportions.width - this.margins.left,
5238 ($(o.containment === "document" ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
5242 if(!(/^(document|window|parent)$/).test(o.containment)) {
5243 ce = $(o.containment)[0];
5244 co = $(o.containment).offset();
5245 over = ($(ce).css("overflow") !== "hidden");
5247 this.containment = [
5248 co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
5249 co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
5250 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,
5251 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
5257 _convertPositionTo: function(d, pos) {
5260 pos = this.position;
5262 var mod = d === "absolute" ? 1 : -1,
5263 scroll = this.cssPosition === "absolute" && !(this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent,
5264 scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
5268 pos.top + // The absolute mouse position
5269 this.offset.relative.top * mod + // Only for relative positioned nodes: Relative offset from element to offset parent
5270 this.offset.parent.top * mod - // The offsetParent's offset without borders (offset + border)
5271 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
5274 pos.left + // The absolute mouse position
5275 this.offset.relative.left * mod + // Only for relative positioned nodes: Relative offset from element to offset parent
5276 this.offset.parent.left * mod - // The offsetParent's offset without borders (offset + border)
5277 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
5283 _generatePosition: function(event) {
5287 pageX = event.pageX,
5288 pageY = event.pageY,
5289 scroll = this.cssPosition === "absolute" && !(this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
5291 // This is another very weird special case that only happens for relative elements:
5292 // 1. If the css position is relative
5293 // 2. and the scroll parent is the document or similar to the offset parent
5294 // we have to refresh the relative offset during the scroll so there are no jumps
5295 if(this.cssPosition === "relative" && !(this.scrollParent[0] !== document && this.scrollParent[0] !== this.offsetParent[0])) {
5296 this.offset.relative = this._getRelativeOffset();
5300 * - Position constraining -
5301 * Constrain the position to a mix of grid, containment.
5304 if(this.originalPosition) { //If we are not dragging yet, we won't check for options
5306 if(this.containment) {
5307 if(event.pageX - this.offset.click.left < this.containment[0]) {
5308 pageX = this.containment[0] + this.offset.click.left;
5310 if(event.pageY - this.offset.click.top < this.containment[1]) {
5311 pageY = this.containment[1] + this.offset.click.top;
5313 if(event.pageX - this.offset.click.left > this.containment[2]) {
5314 pageX = this.containment[2] + this.offset.click.left;
5316 if(event.pageY - this.offset.click.top > this.containment[3]) {
5317 pageY = this.containment[3] + this.offset.click.top;
5322 top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
5323 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;
5325 left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
5326 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;
5333 pageY - // The absolute mouse position
5334 this.offset.click.top - // Click offset (relative to the element)
5335 this.offset.relative.top - // Only for relative positioned nodes: Relative offset from element to offset parent
5336 this.offset.parent.top + // The offsetParent's offset without borders (offset + border)
5337 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
5340 pageX - // The absolute mouse position
5341 this.offset.click.left - // Click offset (relative to the element)
5342 this.offset.relative.left - // Only for relative positioned nodes: Relative offset from element to offset parent
5343 this.offset.parent.left + // The offsetParent's offset without borders (offset + border)
5344 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
5350 _rearrange: function(event, i, a, hardRefresh) {
5352 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));
5354 //Various things done here to improve the performance:
5355 // 1. we create a setTimeout, that calls refreshPositions
5356 // 2. on the instance, we have a counter variable, that get's higher after every append
5357 // 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same
5358 // 4. this lets only the last addition to the timeout stack through
5359 this.counter = this.counter ? ++this.counter : 1;
5360 var counter = this.counter;
5362 this._delay(function() {
5363 if(counter === this.counter) {
5364 this.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove
5370 _clear: function(event, noPropagation) {
5372 this.reverting = false;
5373 // We delay all events that have to be triggered to after the point where the placeholder has been removed and
5374 // everything else normalized again
5376 delayedTriggers = [];
5378 // We first have to update the dom position of the actual currentItem
5379 // Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088)
5380 if(!this._noFinalSort && this.currentItem.parent().length) {
5381 this.placeholder.before(this.currentItem);
5383 this._noFinalSort = null;
5385 if(this.helper[0] === this.currentItem[0]) {
5386 for(i in this._storedCSS) {
5387 if(this._storedCSS[i] === "auto" || this._storedCSS[i] === "static") {
5388 this._storedCSS[i] = "";
5391 this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
5393 this.currentItem.show();
5396 if(this.fromOutside && !noPropagation) {
5397 delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); });
5399 if((this.fromOutside || this.domPosition.prev !== this.currentItem.prev().not(".ui-sortable-helper")[0] || this.domPosition.parent !== this.currentItem.parent()[0]) && !noPropagation) {
5400 delayedTriggers.push(function(event) { this._trigger("update", event, this._uiHash()); }); //Trigger update callback if the DOM position has changed
5403 // Check if the items Container has Changed and trigger appropriate
5405 if (this !== this.currentContainer) {
5406 if(!noPropagation) {
5407 delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); });
5408 delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); }; }).call(this, this.currentContainer));
5409 delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this)); }; }).call(this, this.currentContainer));
5414 //Post events to containers
5415 function delayEvent( type, instance, container ) {
5416 return function( event ) {
5417 container._trigger( type, event, instance._uiHash( instance ) );
5420 for (i = this.containers.length - 1; i >= 0; i--){
5421 if (!noPropagation) {
5422 delayedTriggers.push( delayEvent( "deactivate", this, this.containers[ i ] ) );
5424 if(this.containers[i].containerCache.over) {
5425 delayedTriggers.push( delayEvent( "out", this, this.containers[ i ] ) );
5426 this.containers[i].containerCache.over = 0;
5430 //Do what was originally in plugins
5431 if ( this.storedCursor ) {
5432 this.document.find( "body" ).css( "cursor", this.storedCursor );
5433 this.storedStylesheet.remove();
5435 if(this._storedOpacity) {
5436 this.helper.css("opacity", this._storedOpacity);
5438 if(this._storedZIndex) {
5439 this.helper.css("zIndex", this._storedZIndex === "auto" ? "" : this._storedZIndex);
5442 this.dragging = false;
5443 if(this.cancelHelperRemoval) {
5444 if(!noPropagation) {
5445 this._trigger("beforeStop", event, this._uiHash());
5446 for (i=0; i < delayedTriggers.length; i++) {
5447 delayedTriggers[i].call(this, event);
5448 } //Trigger all delayed events
5449 this._trigger("stop", event, this._uiHash());
5452 this.fromOutside = false;
5456 if(!noPropagation) {
5457 this._trigger("beforeStop", event, this._uiHash());
5460 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
5461 this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
5463 if(this.helper[0] !== this.currentItem[0]) {
5464 this.helper.remove();
5468 if(!noPropagation) {
5469 for (i=0; i < delayedTriggers.length; i++) {
5470 delayedTriggers[i].call(this, event);
5471 } //Trigger all delayed events
5472 this._trigger("stop", event, this._uiHash());
5475 this.fromOutside = false;
5480 _trigger: function() {
5481 if ($.Widget.prototype._trigger.apply(this, arguments) === false) {
5486 _uiHash: function(_inst) {
5487 var inst = _inst || this;
5489 helper: inst.helper,
5490 placeholder: inst.placeholder || $([]),
5491 position: inst.position,
5492 originalPosition: inst.originalPosition,
5493 offset: inst.positionAbs,
5494 item: inst.currentItem,
5495 sender: _inst ? _inst.element : null
5503 * jQuery UI Accordion 1.11.0
5504 * http://jqueryui.com
5506 * Copyright 2014 jQuery Foundation and other contributors
5507 * Released under the MIT license.
5508 * http://jquery.org/license
5510 * http://api.jqueryui.com/accordion/
5514 var accordion = $.widget( "ui.accordion", {
5521 header: "> li > :first-child,> :not(li):even",
5522 heightStyle: "auto",
5524 activeHeader: "ui-icon-triangle-1-s",
5525 header: "ui-icon-triangle-1-e"
5530 beforeActivate: null
5534 borderTopWidth: "hide",
5535 borderBottomWidth: "hide",
5537 paddingBottom: "hide",
5542 borderTopWidth: "show",
5543 borderBottomWidth: "show",
5545 paddingBottom: "show",
5549 _create: function() {
5550 var options = this.options;
5551 this.prevShow = this.prevHide = $();
5552 this.element.addClass( "ui-accordion ui-widget ui-helper-reset" )
5554 .attr( "role", "tablist" );
5556 // don't allow collapsible: false and active: false / null
5557 if ( !options.collapsible && (options.active === false || options.active == null) ) {
5561 this._processPanels();
5562 // handle negative values
5563 if ( options.active < 0 ) {
5564 options.active += this.headers.length;
5569 _getCreateEventData: function() {
5571 header: this.active,
5572 panel: !this.active.length ? $() : this.active.next()
5576 _createIcons: function() {
5577 var icons = this.options.icons;
5580 .addClass( "ui-accordion-header-icon ui-icon " + icons.header )
5581 .prependTo( this.headers );
5582 this.active.children( ".ui-accordion-header-icon" )
5583 .removeClass( icons.header )
5584 .addClass( icons.activeHeader );
5585 this.headers.addClass( "ui-accordion-icons" );
5589 _destroyIcons: function() {
5591 .removeClass( "ui-accordion-icons" )
5592 .children( ".ui-accordion-header-icon" )
5596 _destroy: function() {
5599 // clean up main element
5601 .removeClass( "ui-accordion ui-widget ui-helper-reset" )
5602 .removeAttr( "role" );
5606 .removeClass( "ui-accordion-header ui-accordion-header-active ui-state-default " +
5607 "ui-corner-all ui-state-active ui-state-disabled ui-corner-top" )
5608 .removeAttr( "role" )
5609 .removeAttr( "aria-expanded" )
5610 .removeAttr( "aria-selected" )
5611 .removeAttr( "aria-controls" )
5612 .removeAttr( "tabIndex" )
5615 this._destroyIcons();
5617 // clean up content panels
5618 contents = this.headers.next()
5619 .removeClass( "ui-helper-reset ui-widget-content ui-corner-bottom " +
5620 "ui-accordion-content ui-accordion-content-active ui-state-disabled" )
5621 .css( "display", "" )
5622 .removeAttr( "role" )
5623 .removeAttr( "aria-hidden" )
5624 .removeAttr( "aria-labelledby" )
5627 if ( this.options.heightStyle !== "content" ) {
5628 contents.css( "height", "" );
5632 _setOption: function( key, value ) {
5633 if ( key === "active" ) {
5634 // _activate() will handle invalid values and update this.options
5635 this._activate( value );
5639 if ( key === "event" ) {
5640 if ( this.options.event ) {
5641 this._off( this.headers, this.options.event );
5643 this._setupEvents( value );
5646 this._super( key, value );
5648 // setting collapsible: false while collapsed; open first panel
5649 if ( key === "collapsible" && !value && this.options.active === false ) {
5650 this._activate( 0 );
5653 if ( key === "icons" ) {
5654 this._destroyIcons();
5656 this._createIcons();
5660 // #5332 - opacity doesn't cascade to positioned elements in IE
5661 // so we need to add the disabled class to the headers and panels
5662 if ( key === "disabled" ) {
5664 .toggleClass( "ui-state-disabled", !!value )
5665 .attr( "aria-disabled", value );
5666 this.headers.add( this.headers.next() )
5667 .toggleClass( "ui-state-disabled", !!value );
5671 _keydown: function( event ) {
5672 if ( event.altKey || event.ctrlKey ) {
5676 var keyCode = $.ui.keyCode,
5677 length = this.headers.length,
5678 currentIndex = this.headers.index( event.target ),
5681 switch ( event.keyCode ) {
5684 toFocus = this.headers[ ( currentIndex + 1 ) % length ];
5688 toFocus = this.headers[ ( currentIndex - 1 + length ) % length ];
5692 this._eventHandler( event );
5695 toFocus = this.headers[ 0 ];
5698 toFocus = this.headers[ length - 1 ];
5703 $( event.target ).attr( "tabIndex", -1 );
5704 $( toFocus ).attr( "tabIndex", 0 );
5706 event.preventDefault();
5710 _panelKeyDown: function( event ) {
5711 if ( event.keyCode === $.ui.keyCode.UP && event.ctrlKey ) {
5712 $( event.currentTarget ).prev().focus();
5716 refresh: function() {
5717 var options = this.options;
5718 this._processPanels();
5720 // was collapsed or no panel
5721 if ( ( options.active === false && options.collapsible === true ) || !this.headers.length ) {
5722 options.active = false;
5724 // active false only when collapsible is true
5725 } else if ( options.active === false ) {
5726 this._activate( 0 );
5727 // was active, but active panel is gone
5728 } else if ( this.active.length && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
5729 // all remaining panel are disabled
5730 if ( this.headers.length === this.headers.find(".ui-state-disabled").length ) {
5731 options.active = false;
5733 // activate previous panel
5735 this._activate( Math.max( 0, options.active - 1 ) );
5737 // was active, active panel still exists
5739 // make sure active index is correct
5740 options.active = this.headers.index( this.active );
5743 this._destroyIcons();
5748 _processPanels: function() {
5749 this.headers = this.element.find( this.options.header )
5750 .addClass( "ui-accordion-header ui-state-default ui-corner-all" );
5753 .addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" )
5754 .filter( ":not(.ui-accordion-content-active)" )
5758 _refresh: function() {
5760 options = this.options,
5761 heightStyle = options.heightStyle,
5762 parent = this.element.parent();
5764 this.active = this._findActive( options.active )
5765 .addClass( "ui-accordion-header-active ui-state-active ui-corner-top" )
5766 .removeClass( "ui-corner-all" );
5768 .addClass( "ui-accordion-content-active" )
5772 .attr( "role", "tab" )
5774 var header = $( this ),
5775 headerId = header.uniqueId().attr( "id" ),
5776 panel = header.next(),
5777 panelId = panel.uniqueId().attr( "id" );
5778 header.attr( "aria-controls", panelId );
5779 panel.attr( "aria-labelledby", headerId );
5782 .attr( "role", "tabpanel" );
5787 "aria-selected": "false",
5788 "aria-expanded": "false",
5793 "aria-hidden": "true"
5797 // make sure at least one header is in the tab order
5798 if ( !this.active.length ) {
5799 this.headers.eq( 0 ).attr( "tabIndex", 0 );
5802 "aria-selected": "true",
5803 "aria-expanded": "true",
5808 "aria-hidden": "false"
5812 this._createIcons();
5814 this._setupEvents( options.event );
5816 if ( heightStyle === "fill" ) {
5817 maxHeight = parent.height();
5818 this.element.siblings( ":visible" ).each(function() {
5819 var elem = $( this ),
5820 position = elem.css( "position" );
5822 if ( position === "absolute" || position === "fixed" ) {
5825 maxHeight -= elem.outerHeight( true );
5828 this.headers.each(function() {
5829 maxHeight -= $( this ).outerHeight( true );
5834 $( this ).height( Math.max( 0, maxHeight -
5835 $( this ).innerHeight() + $( this ).height() ) );
5837 .css( "overflow", "auto" );
5838 } else if ( heightStyle === "auto" ) {
5842 maxHeight = Math.max( maxHeight, $( this ).css( "height", "" ).height() );
5844 .height( maxHeight );
5848 _activate: function( index ) {
5849 var active = this._findActive( index )[ 0 ];
5851 // trying to activate the already active panel
5852 if ( active === this.active[ 0 ] ) {
5856 // trying to collapse, simulate a click on the currently active header
5857 active = active || this.active[ 0 ];
5859 this._eventHandler({
5861 currentTarget: active,
5862 preventDefault: $.noop
5866 _findActive: function( selector ) {
5867 return typeof selector === "number" ? this.headers.eq( selector ) : $();
5870 _setupEvents: function( event ) {
5875 $.each( event.split( " " ), function( index, eventName ) {
5876 events[ eventName ] = "_eventHandler";
5880 this._off( this.headers.add( this.headers.next() ) );
5881 this._on( this.headers, events );
5882 this._on( this.headers.next(), { keydown: "_panelKeyDown" });
5883 this._hoverable( this.headers );
5884 this._focusable( this.headers );
5887 _eventHandler: function( event ) {
5888 var options = this.options,
5889 active = this.active,
5890 clicked = $( event.currentTarget ),
5891 clickedIsActive = clicked[ 0 ] === active[ 0 ],
5892 collapsing = clickedIsActive && options.collapsible,
5893 toShow = collapsing ? $() : clicked.next(),
5894 toHide = active.next(),
5898 newHeader: collapsing ? $() : clicked,
5902 event.preventDefault();
5905 // click on active header, but not collapsible
5906 ( clickedIsActive && !options.collapsible ) ||
5907 // allow canceling activation
5908 ( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
5912 options.active = collapsing ? false : this.headers.index( clicked );
5914 // when the call to ._toggle() comes after the class changes
5915 // it causes a very odd bug in IE 8 (see #6720)
5916 this.active = clickedIsActive ? $() : clicked;
5917 this._toggle( eventData );
5920 // corner classes on the previously active header stay after the animation
5921 active.removeClass( "ui-accordion-header-active ui-state-active" );
5922 if ( options.icons ) {
5923 active.children( ".ui-accordion-header-icon" )
5924 .removeClass( options.icons.activeHeader )
5925 .addClass( options.icons.header );
5928 if ( !clickedIsActive ) {
5930 .removeClass( "ui-corner-all" )
5931 .addClass( "ui-accordion-header-active ui-state-active ui-corner-top" );
5932 if ( options.icons ) {
5933 clicked.children( ".ui-accordion-header-icon" )
5934 .removeClass( options.icons.header )
5935 .addClass( options.icons.activeHeader );
5940 .addClass( "ui-accordion-content-active" );
5944 _toggle: function( data ) {
5945 var toShow = data.newPanel,
5946 toHide = this.prevShow.length ? this.prevShow : data.oldPanel;
5948 // handle activating a panel during the animation for another activation
5949 this.prevShow.add( this.prevHide ).stop( true, true );
5950 this.prevShow = toShow;
5951 this.prevHide = toHide;
5953 if ( this.options.animate ) {
5954 this._animate( toShow, toHide, data );
5958 this._toggleComplete( data );
5962 "aria-hidden": "true"
5964 toHide.prev().attr( "aria-selected", "false" );
5965 // if we're switching panels, remove the old header from the tab order
5966 // if we're opening from collapsed state, remove the previous header from the tab order
5967 // if we're collapsing, then keep the collapsing header in the tab order
5968 if ( toShow.length && toHide.length ) {
5969 toHide.prev().attr({
5971 "aria-expanded": "false"
5973 } else if ( toShow.length ) {
5974 this.headers.filter(function() {
5975 return $( this ).attr( "tabIndex" ) === 0;
5977 .attr( "tabIndex", -1 );
5981 .attr( "aria-hidden", "false" )
5984 "aria-selected": "true",
5986 "aria-expanded": "true"
5990 _animate: function( toShow, toHide, data ) {
5991 var total, easing, duration,
5994 down = toShow.length &&
5995 ( !toHide.length || ( toShow.index() < toHide.index() ) ),
5996 animate = this.options.animate || {},
5997 options = down && animate.down || animate,
5998 complete = function() {
5999 that._toggleComplete( data );
6002 if ( typeof options === "number" ) {
6005 if ( typeof options === "string" ) {
6008 // fall back from options to animation in case of partial down settings
6009 easing = easing || options.easing || animate.easing;
6010 duration = duration || options.duration || animate.duration;
6012 if ( !toHide.length ) {
6013 return toShow.animate( this.showProps, duration, easing, complete );
6015 if ( !toShow.length ) {
6016 return toHide.animate( this.hideProps, duration, easing, complete );
6019 total = toShow.show().outerHeight();
6020 toHide.animate( this.hideProps, {
6023 step: function( now, fx ) {
6024 fx.now = Math.round( now );
6029 .animate( this.showProps, {
6033 step: function( now, fx ) {
6034 fx.now = Math.round( now );
6035 if ( fx.prop !== "height" ) {
6037 } else if ( that.options.heightStyle !== "content" ) {
6038 fx.now = Math.round( total - toHide.outerHeight() - adjust );
6045 _toggleComplete: function( data ) {
6046 var toHide = data.oldPanel;
6049 .removeClass( "ui-accordion-content-active" )
6051 .removeClass( "ui-corner-top" )
6052 .addClass( "ui-corner-all" );
6054 // Work around for rendering bug in IE (#5421)
6055 if ( toHide.length ) {
6056 toHide.parent()[ 0 ].className = toHide.parent()[ 0 ].className;
6058 this._trigger( "activate", null, data );
6064 * jQuery UI Menu 1.11.0
6065 * http://jqueryui.com
6067 * Copyright 2014 jQuery Foundation and other contributors
6068 * Released under the MIT license.
6069 * http://jquery.org/license
6071 * http://api.jqueryui.com/menu/
6075 var menu = $.widget( "ui.menu", {
6077 defaultElement: "<ul>",
6081 submenu: "ui-icon-carat-1-e"
6097 _create: function() {
6098 this.activeMenu = this.element;
6100 // Flag used to prevent firing of the click handler
6101 // as the event bubbles up through nested menus
6102 this.mouseHandled = false;
6105 .addClass( "ui-menu ui-widget ui-widget-content" )
6106 .toggleClass( "ui-menu-icons", !!this.element.find( ".ui-icon" ).length )
6108 role: this.options.role,
6112 if ( this.options.disabled ) {
6114 .addClass( "ui-state-disabled" )
6115 .attr( "aria-disabled", "true" );
6119 // Prevent focus from sticking to links inside menu after clicking
6120 // them (focus should always stay on UL during navigation).
6121 "mousedown .ui-menu-item": function( event ) {
6122 event.preventDefault();
6124 "click .ui-menu-item": function( event ) {
6125 var target = $( event.target );
6126 if ( !this.mouseHandled && target.not( ".ui-state-disabled" ).length ) {
6127 this.select( event );
6129 // Only set the mouseHandled flag if the event will bubble, see #9469.
6130 if ( !event.isPropagationStopped() ) {
6131 this.mouseHandled = true;
6134 // Open submenu on click
6135 if ( target.has( ".ui-menu" ).length ) {
6136 this.expand( event );
6137 } else if ( !this.element.is( ":focus" ) && $( this.document[ 0 ].activeElement ).closest( ".ui-menu" ).length ) {
6139 // Redirect focus to the menu
6140 this.element.trigger( "focus", [ true ] );
6142 // If the active item is on the top level, let it stay active.
6143 // Otherwise, blur the active item since it is no longer visible.
6144 if ( this.active && this.active.parents( ".ui-menu" ).length === 1 ) {
6145 clearTimeout( this.timer );
6150 "mouseenter .ui-menu-item": function( event ) {
6151 var target = $( event.currentTarget );
6152 // Remove ui-state-active class from siblings of the newly focused menu item
6153 // to avoid a jump caused by adjacent elements both having a class with a border
6154 target.siblings( ".ui-state-active" ).removeClass( "ui-state-active" );
6155 this.focus( event, target );
6157 mouseleave: "collapseAll",
6158 "mouseleave .ui-menu": "collapseAll",
6159 focus: function( event, keepActiveItem ) {
6160 // If there's already an active item, keep it active
6161 // If not, activate the first item
6162 var item = this.active || this.element.find( this.options.items ).eq( 0 );
6164 if ( !keepActiveItem ) {
6165 this.focus( event, item );
6168 blur: function( event ) {
6169 this._delay(function() {
6170 if ( !$.contains( this.element[0], this.document[0].activeElement ) ) {
6171 this.collapseAll( event );
6180 // Clicks outside of a menu collapse any open menus
6181 this._on( this.document, {
6182 click: function( event ) {
6183 if ( this._closeOnDocumentClick( event ) ) {
6184 this.collapseAll( event );
6187 // Reset the mouseHandled flag
6188 this.mouseHandled = false;
6193 _destroy: function() {
6194 // Destroy (sub)menus
6196 .removeAttr( "aria-activedescendant" )
6197 .find( ".ui-menu" ).addBack()
6198 .removeClass( "ui-menu ui-widget ui-widget-content ui-menu-icons ui-front" )
6199 .removeAttr( "role" )
6200 .removeAttr( "tabIndex" )
6201 .removeAttr( "aria-labelledby" )
6202 .removeAttr( "aria-expanded" )
6203 .removeAttr( "aria-hidden" )
6204 .removeAttr( "aria-disabled" )
6208 // Destroy menu items
6209 this.element.find( ".ui-menu-item" )
6210 .removeClass( "ui-menu-item" )
6211 .removeAttr( "role" )
6212 .removeAttr( "aria-disabled" )
6214 .removeClass( "ui-state-hover" )
6215 .removeAttr( "tabIndex" )
6216 .removeAttr( "role" )
6217 .removeAttr( "aria-haspopup" )
6218 .children().each( function() {
6219 var elem = $( this );
6220 if ( elem.data( "ui-menu-submenu-carat" ) ) {
6225 // Destroy menu dividers
6226 this.element.find( ".ui-menu-divider" ).removeClass( "ui-menu-divider ui-widget-content" );
6229 _keydown: function( event ) {
6230 var match, prev, character, skip, regex,
6231 preventDefault = true;
6233 function escape( value ) {
6234 return value.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" );
6237 switch ( event.keyCode ) {
6238 case $.ui.keyCode.PAGE_UP:
6239 this.previousPage( event );
6241 case $.ui.keyCode.PAGE_DOWN:
6242 this.nextPage( event );
6244 case $.ui.keyCode.HOME:
6245 this._move( "first", "first", event );
6247 case $.ui.keyCode.END:
6248 this._move( "last", "last", event );
6250 case $.ui.keyCode.UP:
6251 this.previous( event );
6253 case $.ui.keyCode.DOWN:
6256 case $.ui.keyCode.LEFT:
6257 this.collapse( event );
6259 case $.ui.keyCode.RIGHT:
6260 if ( this.active && !this.active.is( ".ui-state-disabled" ) ) {
6261 this.expand( event );
6264 case $.ui.keyCode.ENTER:
6265 case $.ui.keyCode.SPACE:
6266 this._activate( event );
6268 case $.ui.keyCode.ESCAPE:
6269 this.collapse( event );
6272 preventDefault = false;
6273 prev = this.previousFilter || "";
6274 character = String.fromCharCode( event.keyCode );
6277 clearTimeout( this.filterTimer );
6279 if ( character === prev ) {
6282 character = prev + character;
6285 regex = new RegExp( "^" + escape( character ), "i" );
6286 match = this.activeMenu.find( this.options.items ).filter(function() {
6287 return regex.test( $( this ).text() );
6289 match = skip && match.index( this.active.next() ) !== -1 ?
6290 this.active.nextAll( ".ui-menu-item" ) :
6293 // If no matches on the current filter, reset to the last character pressed
6294 // to move down the menu to the first item that starts with that character
6295 if ( !match.length ) {
6296 character = String.fromCharCode( event.keyCode );
6297 regex = new RegExp( "^" + escape( character ), "i" );
6298 match = this.activeMenu.find( this.options.items ).filter(function() {
6299 return regex.test( $( this ).text() );
6303 if ( match.length ) {
6304 this.focus( event, match );
6305 if ( match.length > 1 ) {
6306 this.previousFilter = character;
6307 this.filterTimer = this._delay(function() {
6308 delete this.previousFilter;
6311 delete this.previousFilter;
6314 delete this.previousFilter;
6318 if ( preventDefault ) {
6319 event.preventDefault();
6323 _activate: function( event ) {
6324 if ( !this.active.is( ".ui-state-disabled" ) ) {
6325 if ( this.active.is( "[aria-haspopup='true']" ) ) {
6326 this.expand( event );
6328 this.select( event );
6333 refresh: function() {
6336 icon = this.options.icons.submenu,
6337 submenus = this.element.find( this.options.menus );
6339 this.element.toggleClass( "ui-menu-icons", !!this.element.find( ".ui-icon" ).length );
6341 // Initialize nested menus
6342 submenus.filter( ":not(.ui-menu)" )
6343 .addClass( "ui-menu ui-widget ui-widget-content ui-front" )
6346 role: this.options.role,
6347 "aria-hidden": "true",
6348 "aria-expanded": "false"
6351 var menu = $( this ),
6352 item = menu.parent(),
6353 submenuCarat = $( "<span>" )
6354 .addClass( "ui-menu-icon ui-icon " + icon )
6355 .data( "ui-menu-submenu-carat", true );
6358 .attr( "aria-haspopup", "true" )
6359 .prepend( submenuCarat );
6360 menu.attr( "aria-labelledby", item.attr( "id" ) );
6363 menus = submenus.add( this.element );
6364 items = menus.find( this.options.items );
6366 // Initialize menu-items containing spaces and/or dashes only as dividers
6367 items.not( ".ui-menu-item" ).each(function() {
6368 var item = $( this );
6369 if ( that._isDivider( item ) ) {
6370 item.addClass( "ui-widget-content ui-menu-divider" );
6374 // Don't refresh list items that are already adapted
6375 items.not( ".ui-menu-item, .ui-menu-divider" )
6376 .addClass( "ui-menu-item" )
6380 role: this._itemRole()
6383 // Add aria-disabled attribute to any disabled menu item
6384 items.filter( ".ui-state-disabled" ).attr( "aria-disabled", "true" );
6386 // If the active item has been removed, blur the menu
6387 if ( this.active && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
6392 _itemRole: function() {
6396 }[ this.options.role ];
6399 _setOption: function( key, value ) {
6400 if ( key === "icons" ) {
6401 this.element.find( ".ui-menu-icon" )
6402 .removeClass( this.options.icons.submenu )
6403 .addClass( value.submenu );
6405 if ( key === "disabled" ) {
6407 .toggleClass( "ui-state-disabled", !!value )
6408 .attr( "aria-disabled", value );
6410 this._super( key, value );
6413 focus: function( event, item ) {
6414 var nested, focused;
6415 this.blur( event, event && event.type === "focus" );
6417 this._scrollIntoView( item );
6419 this.active = item.first();
6420 focused = this.active.addClass( "ui-state-focus" ).removeClass( "ui-state-active" );
6421 // Only update aria-activedescendant if there's a role
6422 // otherwise we assume focus is managed elsewhere
6423 if ( this.options.role ) {
6424 this.element.attr( "aria-activedescendant", focused.attr( "id" ) );
6427 // Highlight active parent menu item, if any
6430 .closest( ".ui-menu-item" )
6431 .addClass( "ui-state-active" );
6433 if ( event && event.type === "keydown" ) {
6436 this.timer = this._delay(function() {
6441 nested = item.children( ".ui-menu" );
6442 if ( nested.length && event && ( /^mouse/.test( event.type ) ) ) {
6443 this._startOpening(nested);
6445 this.activeMenu = item.parent();
6447 this._trigger( "focus", event, { item: item } );
6450 _scrollIntoView: function( item ) {
6451 var borderTop, paddingTop, offset, scroll, elementHeight, itemHeight;
6452 if ( this._hasScroll() ) {
6453 borderTop = parseFloat( $.css( this.activeMenu[0], "borderTopWidth" ) ) || 0;
6454 paddingTop = parseFloat( $.css( this.activeMenu[0], "paddingTop" ) ) || 0;
6455 offset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop;
6456 scroll = this.activeMenu.scrollTop();
6457 elementHeight = this.activeMenu.height();
6458 itemHeight = item.outerHeight();
6461 this.activeMenu.scrollTop( scroll + offset );
6462 } else if ( offset + itemHeight > elementHeight ) {
6463 this.activeMenu.scrollTop( scroll + offset - elementHeight + itemHeight );
6468 blur: function( event, fromFocus ) {
6470 clearTimeout( this.timer );
6473 if ( !this.active ) {
6477 this.active.removeClass( "ui-state-focus" );
6480 this._trigger( "blur", event, { item: this.active } );
6483 _startOpening: function( submenu ) {
6484 clearTimeout( this.timer );
6486 // Don't open if already open fixes a Firefox bug that caused a .5 pixel
6487 // shift in the submenu position when mousing over the carat icon
6488 if ( submenu.attr( "aria-hidden" ) !== "true" ) {
6492 this.timer = this._delay(function() {
6494 this._open( submenu );
6498 _open: function( submenu ) {
6499 var position = $.extend({
6501 }, this.options.position );
6503 clearTimeout( this.timer );
6504 this.element.find( ".ui-menu" ).not( submenu.parents( ".ui-menu" ) )
6506 .attr( "aria-hidden", "true" );
6510 .removeAttr( "aria-hidden" )
6511 .attr( "aria-expanded", "true" )
6512 .position( position );
6515 collapseAll: function( event, all ) {
6516 clearTimeout( this.timer );
6517 this.timer = this._delay(function() {
6518 // If we were passed an event, look for the submenu that contains the event
6519 var currentMenu = all ? this.element :
6520 $( event && event.target ).closest( this.element.find( ".ui-menu" ) );
6522 // If we found no valid submenu ancestor, use the main menu to close all sub menus anyway
6523 if ( !currentMenu.length ) {
6524 currentMenu = this.element;
6527 this._close( currentMenu );
6530 this.activeMenu = currentMenu;
6534 // With no arguments, closes the currently active menu - if nothing is active
6535 // it closes all menus. If passed an argument, it will search for menus BELOW
6536 _close: function( startMenu ) {
6538 startMenu = this.active ? this.active.parent() : this.element;
6544 .attr( "aria-hidden", "true" )
6545 .attr( "aria-expanded", "false" )
6547 .find( ".ui-state-active" ).not( ".ui-state-focus" )
6548 .removeClass( "ui-state-active" );
6551 _closeOnDocumentClick: function( event ) {
6552 return !$( event.target ).closest( ".ui-menu" ).length;
6555 _isDivider: function( item ) {
6557 // Match hyphen, em dash, en dash
6558 return !/[^\-\u2014\u2013\s]/.test( item.text() );
6561 collapse: function( event ) {
6562 var newItem = this.active &&
6563 this.active.parent().closest( ".ui-menu-item", this.element );
6564 if ( newItem && newItem.length ) {
6566 this.focus( event, newItem );
6570 expand: function( event ) {
6571 var newItem = this.active &&
6573 .children( ".ui-menu " )
6574 .find( this.options.items )
6577 if ( newItem && newItem.length ) {
6578 this._open( newItem.parent() );
6580 // Delay so Firefox will not hide activedescendant change in expanding submenu from AT
6581 this._delay(function() {
6582 this.focus( event, newItem );
6587 next: function( event ) {
6588 this._move( "next", "first", event );
6591 previous: function( event ) {
6592 this._move( "prev", "last", event );
6595 isFirstItem: function() {
6596 return this.active && !this.active.prevAll( ".ui-menu-item" ).length;
6599 isLastItem: function() {
6600 return this.active && !this.active.nextAll( ".ui-menu-item" ).length;
6603 _move: function( direction, filter, event ) {
6605 if ( this.active ) {
6606 if ( direction === "first" || direction === "last" ) {
6608 [ direction === "first" ? "prevAll" : "nextAll" ]( ".ui-menu-item" )
6612 [ direction + "All" ]( ".ui-menu-item" )
6616 if ( !next || !next.length || !this.active ) {
6617 next = this.activeMenu.find( this.options.items )[ filter ]();
6620 this.focus( event, next );
6623 nextPage: function( event ) {
6624 var item, base, height;
6626 if ( !this.active ) {
6630 if ( this.isLastItem() ) {
6633 if ( this._hasScroll() ) {
6634 base = this.active.offset().top;
6635 height = this.element.height();
6636 this.active.nextAll( ".ui-menu-item" ).each(function() {
6638 return item.offset().top - base - height < 0;
6641 this.focus( event, item );
6643 this.focus( event, this.activeMenu.find( this.options.items )
6644 [ !this.active ? "first" : "last" ]() );
6648 previousPage: function( event ) {
6649 var item, base, height;
6650 if ( !this.active ) {
6654 if ( this.isFirstItem() ) {
6657 if ( this._hasScroll() ) {
6658 base = this.active.offset().top;
6659 height = this.element.height();
6660 this.active.prevAll( ".ui-menu-item" ).each(function() {
6662 return item.offset().top - base + height > 0;
6665 this.focus( event, item );
6667 this.focus( event, this.activeMenu.find( this.options.items ).first() );
6671 _hasScroll: function() {
6672 return this.element.outerHeight() < this.element.prop( "scrollHeight" );
6675 select: function( event ) {
6676 // TODO: It should never be possible to not have an active item at this
6677 // point, but the tests don't trigger mouseenter before click.
6678 this.active = this.active || $( event.target ).closest( ".ui-menu-item" );
6679 var ui = { item: this.active };
6680 if ( !this.active.has( ".ui-menu" ).length ) {
6681 this.collapseAll( event, true );
6683 this._trigger( "select", event, ui );
6689 * jQuery UI Autocomplete 1.11.0
6690 * http://jqueryui.com
6692 * Copyright 2014 jQuery Foundation and other contributors
6693 * Released under the MIT license.
6694 * http://jquery.org/license
6696 * http://api.jqueryui.com/autocomplete/
6700 $.widget( "ui.autocomplete", {
6702 defaultElement: "<input>",
6728 _create: function() {
6729 // Some browsers only repeat keydown events, not keypress events,
6730 // so we use the suppressKeyPress flag to determine if we've already
6731 // handled the keydown event. #7269
6732 // Unfortunately the code for & in keypress is the same as the up arrow,
6733 // so we use the suppressKeyPressRepeat flag to avoid handling keypress
6734 // events when we know the keydown event was used to modify the
6735 // search term. #7799
6736 var suppressKeyPress, suppressKeyPressRepeat, suppressInput,
6737 nodeName = this.element[ 0 ].nodeName.toLowerCase(),
6738 isTextarea = nodeName === "textarea",
6739 isInput = nodeName === "input";
6742 // Textareas are always multi-line
6744 // Inputs are always single-line, even if inside a contentEditable element
6745 // IE also treats inputs as contentEditable
6747 // All other element types are determined by whether or not they're contentEditable
6748 this.element.prop( "isContentEditable" );
6750 this.valueMethod = this.element[ isTextarea || isInput ? "val" : "text" ];
6751 this.isNewMenu = true;
6754 .addClass( "ui-autocomplete-input" )
6755 .attr( "autocomplete", "off" );
6757 this._on( this.element, {
6758 keydown: function( event ) {
6759 if ( this.element.prop( "readOnly" ) ) {
6760 suppressKeyPress = true;
6761 suppressInput = true;
6762 suppressKeyPressRepeat = true;
6766 suppressKeyPress = false;
6767 suppressInput = false;
6768 suppressKeyPressRepeat = false;
6769 var keyCode = $.ui.keyCode;
6770 switch ( event.keyCode ) {
6771 case keyCode.PAGE_UP:
6772 suppressKeyPress = true;
6773 this._move( "previousPage", event );
6775 case keyCode.PAGE_DOWN:
6776 suppressKeyPress = true;
6777 this._move( "nextPage", event );
6780 suppressKeyPress = true;
6781 this._keyEvent( "previous", event );
6784 suppressKeyPress = true;
6785 this._keyEvent( "next", event );
6788 // when menu is open and has focus
6789 if ( this.menu.active ) {
6790 // #6055 - Opera still allows the keypress to occur
6791 // which causes forms to submit
6792 suppressKeyPress = true;
6793 event.preventDefault();
6794 this.menu.select( event );
6798 if ( this.menu.active ) {
6799 this.menu.select( event );
6802 case keyCode.ESCAPE:
6803 if ( this.menu.element.is( ":visible" ) ) {
6804 this._value( this.term );
6805 this.close( event );
6806 // Different browsers have different default behavior for escape
6807 // Single press can mean undo or clear
6808 // Double press in IE means clear the whole form
6809 event.preventDefault();
6813 suppressKeyPressRepeat = true;
6814 // search timeout should be triggered before the input value is changed
6815 this._searchTimeout( event );
6819 keypress: function( event ) {
6820 if ( suppressKeyPress ) {
6821 suppressKeyPress = false;
6822 if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
6823 event.preventDefault();
6827 if ( suppressKeyPressRepeat ) {
6831 // replicate some key handlers to allow them to repeat in Firefox and Opera
6832 var keyCode = $.ui.keyCode;
6833 switch ( event.keyCode ) {
6834 case keyCode.PAGE_UP:
6835 this._move( "previousPage", event );
6837 case keyCode.PAGE_DOWN:
6838 this._move( "nextPage", event );
6841 this._keyEvent( "previous", event );
6844 this._keyEvent( "next", event );
6848 input: function( event ) {
6849 if ( suppressInput ) {
6850 suppressInput = false;
6851 event.preventDefault();
6854 this._searchTimeout( event );
6857 this.selectedItem = null;
6858 this.previous = this._value();
6860 blur: function( event ) {
6861 if ( this.cancelBlur ) {
6862 delete this.cancelBlur;
6866 clearTimeout( this.searching );
6867 this.close( event );
6868 this._change( event );
6873 this.menu = $( "<ul>" )
6874 .addClass( "ui-autocomplete ui-front" )
6875 .appendTo( this._appendTo() )
6877 // disable ARIA support, the live region takes care of that
6881 .menu( "instance" );
6883 this._on( this.menu.element, {
6884 mousedown: function( event ) {
6885 // prevent moving focus out of the text field
6886 event.preventDefault();
6888 // IE doesn't prevent moving focus even with event.preventDefault()
6889 // so we set a flag to know when we should ignore the blur event
6890 this.cancelBlur = true;
6891 this._delay(function() {
6892 delete this.cancelBlur;
6895 // clicking on the scrollbar causes focus to shift to the body
6896 // but we can't detect a mouseup or a click immediately afterward
6897 // so we have to track the next mousedown and close the menu if
6898 // the user clicks somewhere outside of the autocomplete
6899 var menuElement = this.menu.element[ 0 ];
6900 if ( !$( event.target ).closest( ".ui-menu-item" ).length ) {
6901 this._delay(function() {
6903 this.document.one( "mousedown", function( event ) {
6904 if ( event.target !== that.element[ 0 ] &&
6905 event.target !== menuElement &&
6906 !$.contains( menuElement, event.target ) ) {
6913 menufocus: function( event, ui ) {
6916 // Prevent accidental activation of menu items in Firefox (#7024 #9118)
6917 if ( this.isNewMenu ) {
6918 this.isNewMenu = false;
6919 if ( event.originalEvent && /^mouse/.test( event.originalEvent.type ) ) {
6922 this.document.one( "mousemove", function() {
6923 $( event.target ).trigger( event.originalEvent );
6930 item = ui.item.data( "ui-autocomplete-item" );
6931 if ( false !== this._trigger( "focus", event, { item: item } ) ) {
6932 // use value to match what will end up in the input, if it was a key event
6933 if ( event.originalEvent && /^key/.test( event.originalEvent.type ) ) {
6934 this._value( item.value );
6938 // Announce the value in the liveRegion
6939 label = ui.item.attr( "aria-label" ) || item.value;
6940 if ( label && jQuery.trim( label ).length ) {
6941 this.liveRegion.children().hide();
6942 $( "<div>" ).text( label ).appendTo( this.liveRegion );
6945 menuselect: function( event, ui ) {
6946 var item = ui.item.data( "ui-autocomplete-item" ),
6947 previous = this.previous;
6949 // only trigger when focus was lost (click on menu)
6950 if ( this.element[ 0 ] !== this.document[ 0 ].activeElement ) {
6951 this.element.focus();
6952 this.previous = previous;
6953 // #6109 - IE triggers two focus events and the second
6954 // is asynchronous, so we need to reset the previous
6955 // term synchronously and asynchronously :-(
6956 this._delay(function() {
6957 this.previous = previous;
6958 this.selectedItem = item;
6962 if ( false !== this._trigger( "select", event, { item: item } ) ) {
6963 this._value( item.value );
6965 // reset the term after the select event
6966 // this allows custom select handling to work properly
6967 this.term = this._value();
6969 this.close( event );
6970 this.selectedItem = item;
6974 this.liveRegion = $( "<span>", {
6976 "aria-live": "assertive",
6977 "aria-relevant": "additions"
6979 .addClass( "ui-helper-hidden-accessible" )
6980 .appendTo( this.document[ 0 ].body );
6982 // turning off autocomplete prevents the browser from remembering the
6983 // value when navigating through history, so we re-enable autocomplete
6984 // if the page is unloaded before the widget is destroyed. #7790
6985 this._on( this.window, {
6986 beforeunload: function() {
6987 this.element.removeAttr( "autocomplete" );
6992 _destroy: function() {
6993 clearTimeout( this.searching );
6995 .removeClass( "ui-autocomplete-input" )
6996 .removeAttr( "autocomplete" );
6997 this.menu.element.remove();
6998 this.liveRegion.remove();
7001 _setOption: function( key, value ) {
7002 this._super( key, value );
7003 if ( key === "source" ) {
7006 if ( key === "appendTo" ) {
7007 this.menu.element.appendTo( this._appendTo() );
7009 if ( key === "disabled" && value && this.xhr ) {
7014 _appendTo: function() {
7015 var element = this.options.appendTo;
7018 element = element.jquery || element.nodeType ?
7020 this.document.find( element ).eq( 0 );
7023 if ( !element || !element[ 0 ] ) {
7024 element = this.element.closest( ".ui-front" );
7027 if ( !element.length ) {
7028 element = this.document[ 0 ].body;
7034 _initSource: function() {
7037 if ( $.isArray( this.options.source ) ) {
7038 array = this.options.source;
7039 this.source = function( request, response ) {
7040 response( $.ui.autocomplete.filter( array, request.term ) );
7042 } else if ( typeof this.options.source === "string" ) {
7043 url = this.options.source;
7044 this.source = function( request, response ) {
7052 success: function( data ) {
7061 this.source = this.options.source;
7065 _searchTimeout: function( event ) {
7066 clearTimeout( this.searching );
7067 this.searching = this._delay(function() {
7069 // Search if the value has changed, or if the user retypes the same value (see #7434)
7070 var equalValues = this.term === this._value(),
7071 menuVisible = this.menu.element.is( ":visible" ),
7072 modifierKey = event.altKey || event.ctrlKey || event.metaKey || event.shiftKey;
7074 if ( !equalValues || ( equalValues && !menuVisible && !modifierKey ) ) {
7075 this.selectedItem = null;
7076 this.search( null, event );
7078 }, this.options.delay );
7081 search: function( value, event ) {
7082 value = value != null ? value : this._value();
7084 // always save the actual value, not the one passed as an argument
7085 this.term = this._value();
7087 if ( value.length < this.options.minLength ) {
7088 return this.close( event );
7091 if ( this._trigger( "search", event ) === false ) {
7095 return this._search( value );
7098 _search: function( value ) {
7100 this.element.addClass( "ui-autocomplete-loading" );
7101 this.cancelSearch = false;
7103 this.source( { term: value }, this._response() );
7106 _response: function() {
7107 var index = ++this.requestIndex;
7109 return $.proxy(function( content ) {
7110 if ( index === this.requestIndex ) {
7111 this.__response( content );
7115 if ( !this.pending ) {
7116 this.element.removeClass( "ui-autocomplete-loading" );
7121 __response: function( content ) {
7123 content = this._normalize( content );
7125 this._trigger( "response", null, { content: content } );
7126 if ( !this.options.disabled && content && content.length && !this.cancelSearch ) {
7127 this._suggest( content );
7128 this._trigger( "open" );
7130 // use ._close() instead of .close() so we don't cancel future searches
7135 close: function( event ) {
7136 this.cancelSearch = true;
7137 this._close( event );
7140 _close: function( event ) {
7141 if ( this.menu.element.is( ":visible" ) ) {
7142 this.menu.element.hide();
7144 this.isNewMenu = true;
7145 this._trigger( "close", event );
7149 _change: function( event ) {
7150 if ( this.previous !== this._value() ) {
7151 this._trigger( "change", event, { item: this.selectedItem } );
7155 _normalize: function( items ) {
7156 // assume all items have the right format when the first item is complete
7157 if ( items.length && items[ 0 ].label && items[ 0 ].value ) {
7160 return $.map( items, function( item ) {
7161 if ( typeof item === "string" ) {
7167 return $.extend( {}, item, {
7168 label: item.label || item.value,
7169 value: item.value || item.label
7174 _suggest: function( items ) {
7175 var ul = this.menu.element.empty();
7176 this._renderMenu( ul, items );
7177 this.isNewMenu = true;
7178 this.menu.refresh();
7180 // size and position menu
7183 ul.position( $.extend({
7185 }, this.options.position ) );
7187 if ( this.options.autoFocus ) {
7192 _resizeMenu: function() {
7193 var ul = this.menu.element;
7194 ul.outerWidth( Math.max(
7195 // Firefox wraps long text (possibly a rounding bug)
7196 // so we add 1px to avoid the wrapping (#7513)
7197 ul.width( "" ).outerWidth() + 1,
7198 this.element.outerWidth()
7202 _renderMenu: function( ul, items ) {
7204 $.each( items, function( index, item ) {
7205 that._renderItemData( ul, item );
7209 _renderItemData: function( ul, item ) {
7210 return this._renderItem( ul, item ).data( "ui-autocomplete-item", item );
7213 _renderItem: function( ul, item ) {
7214 return $( "<li>" ).text( item.label ).appendTo( ul );
7217 _move: function( direction, event ) {
7218 if ( !this.menu.element.is( ":visible" ) ) {
7219 this.search( null, event );
7222 if ( this.menu.isFirstItem() && /^previous/.test( direction ) ||
7223 this.menu.isLastItem() && /^next/.test( direction ) ) {
7225 if ( !this.isMultiLine ) {
7226 this._value( this.term );
7232 this.menu[ direction ]( event );
7235 widget: function() {
7236 return this.menu.element;
7239 _value: function() {
7240 return this.valueMethod.apply( this.element, arguments );
7243 _keyEvent: function( keyEvent, event ) {
7244 if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
7245 this._move( keyEvent, event );
7247 // prevents moving cursor to beginning/end of the text field in some browsers
7248 event.preventDefault();
7253 $.extend( $.ui.autocomplete, {
7254 escapeRegex: function( value ) {
7255 return value.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" );
7257 filter: function( array, term ) {
7258 var matcher = new RegExp( $.ui.autocomplete.escapeRegex( term ), "i" );
7259 return $.grep( array, function( value ) {
7260 return matcher.test( value.label || value.value || value );
7265 // live region extension, adding a `messages` option
7266 // NOTE: This is an experimental API. We are still investigating
7267 // a full solution for string manipulation and internationalization.
7268 $.widget( "ui.autocomplete", $.ui.autocomplete, {
7271 noResults: "No search results.",
7272 results: function( amount ) {
7273 return amount + ( amount > 1 ? " results are" : " result is" ) +
7274 " available, use up and down arrow keys to navigate.";
7279 __response: function( content ) {
7281 this._superApply( arguments );
7282 if ( this.options.disabled || this.cancelSearch ) {
7285 if ( content && content.length ) {
7286 message = this.options.messages.results( content.length );
7288 message = this.options.messages.noResults;
7290 this.liveRegion.children().hide();
7291 $( "<div>" ).text( message ).appendTo( this.liveRegion );
7295 var autocomplete = $.ui.autocomplete;
7299 * jQuery UI Button 1.11.0
7300 * http://jqueryui.com
7302 * Copyright 2014 jQuery Foundation and other contributors
7303 * Released under the MIT license.
7304 * http://jquery.org/license
7306 * http://api.jqueryui.com/button/
7311 baseClasses = "ui-button ui-widget ui-state-default ui-corner-all",
7312 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",
7313 formResetHandler = function() {
7314 var form = $( this );
7315 setTimeout(function() {
7316 form.find( ":ui-button" ).button( "refresh" );
7319 radioGroup = function( radio ) {
7320 var name = radio.name,
7324 name = name.replace( /'/g, "\\'" );
7326 radios = $( form ).find( "[name='" + name + "'][type=radio]" );
7328 radios = $( "[name='" + name + "'][type=radio]", radio.ownerDocument )
7329 .filter(function() {
7337 $.widget( "ui.button", {
7339 defaultElement: "<button>",
7349 _create: function() {
7350 this.element.closest( "form" )
7351 .unbind( "reset" + this.eventNamespace )
7352 .bind( "reset" + this.eventNamespace, formResetHandler );
7354 if ( typeof this.options.disabled !== "boolean" ) {
7355 this.options.disabled = !!this.element.prop( "disabled" );
7357 this.element.prop( "disabled", this.options.disabled );
7360 this._determineButtonType();
7361 this.hasTitle = !!this.buttonElement.attr( "title" );
7364 options = this.options,
7365 toggleButton = this.type === "checkbox" || this.type === "radio",
7366 activeClass = !toggleButton ? "ui-state-active" : "";
7368 if ( options.label === null ) {
7369 options.label = (this.type === "input" ? this.buttonElement.val() : this.buttonElement.html());
7372 this._hoverable( this.buttonElement );
7375 .addClass( baseClasses )
7376 .attr( "role", "button" )
7377 .bind( "mouseenter" + this.eventNamespace, function() {
7378 if ( options.disabled ) {
7381 if ( this === lastActive ) {
7382 $( this ).addClass( "ui-state-active" );
7385 .bind( "mouseleave" + this.eventNamespace, function() {
7386 if ( options.disabled ) {
7389 $( this ).removeClass( activeClass );
7391 .bind( "click" + this.eventNamespace, function( event ) {
7392 if ( options.disabled ) {
7393 event.preventDefault();
7394 event.stopImmediatePropagation();
7398 // Can't use _focusable() because the element that receives focus
7399 // and the element that gets the ui-state-focus class are different
7402 this.buttonElement.addClass( "ui-state-focus" );
7405 this.buttonElement.removeClass( "ui-state-focus" );
7409 if ( toggleButton ) {
7410 this.element.bind( "change" + this.eventNamespace, function() {
7415 if ( this.type === "checkbox" ) {
7416 this.buttonElement.bind( "click" + this.eventNamespace, function() {
7417 if ( options.disabled ) {
7421 } else if ( this.type === "radio" ) {
7422 this.buttonElement.bind( "click" + this.eventNamespace, function() {
7423 if ( options.disabled ) {
7426 $( this ).addClass( "ui-state-active" );
7427 that.buttonElement.attr( "aria-pressed", "true" );
7429 var radio = that.element[ 0 ];
7433 return $( this ).button( "widget" )[ 0 ];
7435 .removeClass( "ui-state-active" )
7436 .attr( "aria-pressed", "false" );
7440 .bind( "mousedown" + this.eventNamespace, function() {
7441 if ( options.disabled ) {
7444 $( this ).addClass( "ui-state-active" );
7446 that.document.one( "mouseup", function() {
7450 .bind( "mouseup" + this.eventNamespace, function() {
7451 if ( options.disabled ) {
7454 $( this ).removeClass( "ui-state-active" );
7456 .bind( "keydown" + this.eventNamespace, function(event) {
7457 if ( options.disabled ) {
7460 if ( event.keyCode === $.ui.keyCode.SPACE || event.keyCode === $.ui.keyCode.ENTER ) {
7461 $( this ).addClass( "ui-state-active" );
7464 // see #8559, we bind to blur here in case the button element loses
7465 // focus between keydown and keyup, it would be left in an "active" state
7466 .bind( "keyup" + this.eventNamespace + " blur" + this.eventNamespace, function() {
7467 $( this ).removeClass( "ui-state-active" );
7470 if ( this.buttonElement.is("a") ) {
7471 this.buttonElement.keyup(function(event) {
7472 if ( event.keyCode === $.ui.keyCode.SPACE ) {
7473 // TODO pass through original event correctly (just as 2nd argument doesn't work)
7480 this._setOption( "disabled", options.disabled );
7481 this._resetButton();
7484 _determineButtonType: function() {
7485 var ancestor, labelSelector, checked;
7487 if ( this.element.is("[type=checkbox]") ) {
7488 this.type = "checkbox";
7489 } else if ( this.element.is("[type=radio]") ) {
7490 this.type = "radio";
7491 } else if ( this.element.is("input") ) {
7492 this.type = "input";
7494 this.type = "button";
7497 if ( this.type === "checkbox" || this.type === "radio" ) {
7498 // we don't search against the document in case the element
7499 // is disconnected from the DOM
7500 ancestor = this.element.parents().last();
7501 labelSelector = "label[for='" + this.element.attr("id") + "']";
7502 this.buttonElement = ancestor.find( labelSelector );
7503 if ( !this.buttonElement.length ) {
7504 ancestor = ancestor.length ? ancestor.siblings() : this.element.siblings();
7505 this.buttonElement = ancestor.filter( labelSelector );
7506 if ( !this.buttonElement.length ) {
7507 this.buttonElement = ancestor.find( labelSelector );
7510 this.element.addClass( "ui-helper-hidden-accessible" );
7512 checked = this.element.is( ":checked" );
7514 this.buttonElement.addClass( "ui-state-active" );
7516 this.buttonElement.prop( "aria-pressed", checked );
7518 this.buttonElement = this.element;
7522 widget: function() {
7523 return this.buttonElement;
7526 _destroy: function() {
7528 .removeClass( "ui-helper-hidden-accessible" );
7530 .removeClass( baseClasses + " ui-state-active " + typeClasses )
7531 .removeAttr( "role" )
7532 .removeAttr( "aria-pressed" )
7533 .html( this.buttonElement.find(".ui-button-text").html() );
7535 if ( !this.hasTitle ) {
7536 this.buttonElement.removeAttr( "title" );
7540 _setOption: function( key, value ) {
7541 this._super( key, value );
7542 if ( key === "disabled" ) {
7543 this.widget().toggleClass( "ui-state-disabled", !!value );
7544 this.element.prop( "disabled", !!value );
7546 if ( this.type === "checkbox" || this.type === "radio" ) {
7547 this.buttonElement.removeClass( "ui-state-focus" );
7549 this.buttonElement.removeClass( "ui-state-focus ui-state-active" );
7554 this._resetButton();
7557 refresh: function() {
7559 var isDisabled = this.element.is( "input, button" ) ? this.element.is( ":disabled" ) : this.element.hasClass( "ui-button-disabled" );
7561 if ( isDisabled !== this.options.disabled ) {
7562 this._setOption( "disabled", isDisabled );
7564 if ( this.type === "radio" ) {
7565 radioGroup( this.element[0] ).each(function() {
7566 if ( $( this ).is( ":checked" ) ) {
7567 $( this ).button( "widget" )
7568 .addClass( "ui-state-active" )
7569 .attr( "aria-pressed", "true" );
7571 $( this ).button( "widget" )
7572 .removeClass( "ui-state-active" )
7573 .attr( "aria-pressed", "false" );
7576 } else if ( this.type === "checkbox" ) {
7577 if ( this.element.is( ":checked" ) ) {
7579 .addClass( "ui-state-active" )
7580 .attr( "aria-pressed", "true" );
7583 .removeClass( "ui-state-active" )
7584 .attr( "aria-pressed", "false" );
7589 _resetButton: function() {
7590 if ( this.type === "input" ) {
7591 if ( this.options.label ) {
7592 this.element.val( this.options.label );
7596 var buttonElement = this.buttonElement.removeClass( typeClasses ),
7597 buttonText = $( "<span></span>", this.document[0] )
7598 .addClass( "ui-button-text" )
7599 .html( this.options.label )
7600 .appendTo( buttonElement.empty() )
7602 icons = this.options.icons,
7603 multipleIcons = icons.primary && icons.secondary,
7606 if ( icons.primary || icons.secondary ) {
7607 if ( this.options.text ) {
7608 buttonClasses.push( "ui-button-text-icon" + ( multipleIcons ? "s" : ( icons.primary ? "-primary" : "-secondary" ) ) );
7611 if ( icons.primary ) {
7612 buttonElement.prepend( "<span class='ui-button-icon-primary ui-icon " + icons.primary + "'></span>" );
7615 if ( icons.secondary ) {
7616 buttonElement.append( "<span class='ui-button-icon-secondary ui-icon " + icons.secondary + "'></span>" );
7619 if ( !this.options.text ) {
7620 buttonClasses.push( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" );
7622 if ( !this.hasTitle ) {
7623 buttonElement.attr( "title", $.trim( buttonText ) );
7627 buttonClasses.push( "ui-button-text-only" );
7629 buttonElement.addClass( buttonClasses.join( " " ) );
7633 $.widget( "ui.buttonset", {
7636 items: "button, input[type=button], input[type=submit], input[type=reset], input[type=checkbox], input[type=radio], a, :data(ui-button)"
7639 _create: function() {
7640 this.element.addClass( "ui-buttonset" );
7647 _setOption: function( key, value ) {
7648 if ( key === "disabled" ) {
7649 this.buttons.button( "option", key, value );
7652 this._super( key, value );
7655 refresh: function() {
7656 var rtl = this.element.css( "direction" ) === "rtl",
7657 allButtons = this.element.find( this.options.items ),
7658 existingButtons = allButtons.filter( ":ui-button" );
7660 // Initialize new buttons
7661 allButtons.not( ":ui-button" ).button();
7663 // Refresh existing buttons
7664 existingButtons.button( "refresh" );
7666 this.buttons = allButtons
7668 return $( this ).button( "widget" )[ 0 ];
7670 .removeClass( "ui-corner-all ui-corner-left ui-corner-right" )
7672 .addClass( rtl ? "ui-corner-right" : "ui-corner-left" )
7675 .addClass( rtl ? "ui-corner-left" : "ui-corner-right" )
7680 _destroy: function() {
7681 this.element.removeClass( "ui-buttonset" );
7684 return $( this ).button( "widget" )[ 0 ];
7686 .removeClass( "ui-corner-left ui-corner-right" )
7688 .button( "destroy" );
7692 var button = $.ui.button;
7696 * jQuery UI Datepicker 1.11.0
7697 * http://jqueryui.com
7699 * Copyright 2014 jQuery Foundation and other contributors
7700 * Released under the MIT license.
7701 * http://jquery.org/license
7703 * http://api.jqueryui.com/datepicker/
7707 $.extend($.ui, { datepicker: { version: "1.11.0" } });
7709 var datepicker_instActive;
7711 function datepicker_getZindex( elem ) {
7712 var position, value;
7713 while ( elem.length && elem[ 0 ] !== document ) {
7714 // Ignore z-index if position is set to a value where z-index is ignored by the browser
7715 // This makes behavior of this function consistent across browsers
7716 // WebKit always returns auto if the element is positioned
7717 position = elem.css( "position" );
7718 if ( position === "absolute" || position === "relative" || position === "fixed" ) {
7719 // IE returns 0 when zIndex is not specified
7720 // other browsers return a string
7721 // we ignore the case of nested elements with an explicit value of 0
7722 // <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
7723 value = parseInt( elem.css( "zIndex" ), 10 );
7724 if ( !isNaN( value ) && value !== 0 ) {
7728 elem = elem.parent();
7733 /* Date picker manager.
7734 Use the singleton instance of this class, $.datepicker, to interact with the date picker.
7735 Settings for (groups of) date pickers are maintained in an instance object,
7736 allowing multiple different settings on the same page. */
7738 function Datepicker() {
7739 this._curInst = null; // The current instance in use
7740 this._keyEvent = false; // If the last event was a key event
7741 this._disabledInputs = []; // List of date picker inputs that have been disabled
7742 this._datepickerShowing = false; // True if the popup picker is showing , false if not
7743 this._inDialog = false; // True if showing within a "dialog", false if not
7744 this._mainDivId = "ui-datepicker-div"; // The ID of the main datepicker division
7745 this._inlineClass = "ui-datepicker-inline"; // The name of the inline marker class
7746 this._appendClass = "ui-datepicker-append"; // The name of the append marker class
7747 this._triggerClass = "ui-datepicker-trigger"; // The name of the trigger marker class
7748 this._dialogClass = "ui-datepicker-dialog"; // The name of the dialog marker class
7749 this._disableClass = "ui-datepicker-disabled"; // The name of the disabled covering marker class
7750 this._unselectableClass = "ui-datepicker-unselectable"; // The name of the unselectable cell marker class
7751 this._currentClass = "ui-datepicker-current-day"; // The name of the current day marker class
7752 this._dayOverClass = "ui-datepicker-days-cell-over"; // The name of the day hover marker class
7753 this.regional = []; // Available regional settings, indexed by language code
7754 this.regional[""] = { // Default regional settings
7755 closeText: "Done", // Display text for close link
7756 prevText: "Prev", // Display text for previous month link
7757 nextText: "Next", // Display text for next month link
7758 currentText: "Today", // Display text for current month link
7759 monthNames: ["January","February","March","April","May","June",
7760 "July","August","September","October","November","December"], // Names of months for drop-down and formatting
7761 monthNamesShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], // For formatting
7762 dayNames: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], // For formatting
7763 dayNamesShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], // For formatting
7764 dayNamesMin: ["Su","Mo","Tu","We","Th","Fr","Sa"], // Column headings for days starting at Sunday
7765 weekHeader: "Wk", // Column header for week of the year
7766 dateFormat: "mm/dd/yy", // See format options on parseDate
7767 firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
7768 isRTL: false, // True if right-to-left language, false if left-to-right
7769 showMonthAfterYear: false, // True if the year select precedes month, false for month then year
7770 yearSuffix: "" // Additional text to append to the year in the month headers
7772 this._defaults = { // Global defaults for all the date picker instances
7773 showOn: "focus", // "focus" for popup on focus,
7774 // "button" for trigger button, or "both" for either
7775 showAnim: "fadeIn", // Name of jQuery animation for popup
7776 showOptions: {}, // Options for enhanced animations
7777 defaultDate: null, // Used when field is blank: actual date,
7778 // +/-number for offset from today, null for today
7779 appendText: "", // Display text following the input box, e.g. showing the format
7780 buttonText: "...", // Text for trigger button
7781 buttonImage: "", // URL for trigger button image
7782 buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
7783 hideIfNoPrevNext: false, // True to hide next/previous month links
7784 // if not applicable, false to just disable them
7785 navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
7786 gotoCurrent: false, // True if today link goes back to current selection instead
7787 changeMonth: false, // True if month can be selected directly, false if only prev/next
7788 changeYear: false, // True if year can be selected directly, false if only prev/next
7789 yearRange: "c-10:c+10", // Range of years to display in drop-down,
7790 // either relative to today's year (-nn:+nn), relative to currently displayed year
7791 // (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
7792 showOtherMonths: false, // True to show dates in other months, false to leave blank
7793 selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
7794 showWeek: false, // True to show week of the year, false to not show it
7795 calculateWeek: this.iso8601Week, // How to calculate the week of the year,
7796 // takes a Date and returns the number of the week for it
7797 shortYearCutoff: "+10", // Short year values < this are in the current century,
7798 // > this are in the previous century,
7799 // string value starting with "+" for current year + value
7800 minDate: null, // The earliest selectable date, or null for no limit
7801 maxDate: null, // The latest selectable date, or null for no limit
7802 duration: "fast", // Duration of display/closure
7803 beforeShowDay: null, // Function that takes a date and returns an array with
7804 // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or "",
7805 // [2] = cell title (optional), e.g. $.datepicker.noWeekends
7806 beforeShow: null, // Function that takes an input field and
7807 // returns a set of custom settings for the date picker
7808 onSelect: null, // Define a callback function when a date is selected
7809 onChangeMonthYear: null, // Define a callback function when the month or year is changed
7810 onClose: null, // Define a callback function when the datepicker is closed
7811 numberOfMonths: 1, // Number of months to show at a time
7812 showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
7813 stepMonths: 1, // Number of months to step back/forward
7814 stepBigMonths: 12, // Number of months to step back/forward for the big links
7815 altField: "", // Selector for an alternate field to store selected dates into
7816 altFormat: "", // The date format to use for the alternate field
7817 constrainInput: true, // The input is constrained by the current date format
7818 showButtonPanel: false, // True to show button panel, false to not show it
7819 autoSize: false, // True to size the input for the date format, false to leave as is
7820 disabled: false // The initial disabled state
7822 $.extend(this._defaults, this.regional[""]);
7823 this.regional.en = $.extend( true, {}, this.regional[ "" ]);
7824 this.regional[ "en-US" ] = $.extend( true, {}, this.regional.en );
7825 this.dpDiv = datepicker_bindHover($("<div id='" + this._mainDivId + "' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>"));
7828 $.extend(Datepicker.prototype, {
7829 /* Class name added to elements to indicate already configured with a date picker. */
7830 markerClassName: "hasDatepicker",
7832 //Keep track of the maximum number of rows displayed (see #7043)
7835 // TODO rename to "widget" when switching to widget factory
7836 _widgetDatepicker: function() {
7840 /* Override the default settings for all instances of the date picker.
7841 * @param settings object - the new settings to use as defaults (anonymous object)
7842 * @return the manager object
7844 setDefaults: function(settings) {
7845 datepicker_extendRemove(this._defaults, settings || {});
7849 /* Attach the date picker to a jQuery selection.
7850 * @param target element - the target input field or division or span
7851 * @param settings object - the new settings to use for this date picker instance (anonymous)
7853 _attachDatepicker: function(target, settings) {
7854 var nodeName, inline, inst;
7855 nodeName = target.nodeName.toLowerCase();
7856 inline = (nodeName === "div" || nodeName === "span");
7859 target.id = "dp" + this.uuid;
7861 inst = this._newInst($(target), inline);
7862 inst.settings = $.extend({}, settings || {});
7863 if (nodeName === "input") {
7864 this._connectDatepicker(target, inst);
7865 } else if (inline) {
7866 this._inlineDatepicker(target, inst);
7870 /* Create a new instance object. */
7871 _newInst: function(target, inline) {
7872 var id = target[0].id.replace(/([^A-Za-z0-9_\-])/g, "\\\\$1"); // escape jQuery meta chars
7873 return {id: id, input: target, // associated target
7874 selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
7875 drawMonth: 0, drawYear: 0, // month being drawn
7876 inline: inline, // is datepicker inline or not
7877 dpDiv: (!inline ? this.dpDiv : // presentation div
7878 datepicker_bindHover($("<div class='" + this._inlineClass + " ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>")))};
7881 /* Attach the date picker to an input field. */
7882 _connectDatepicker: function(target, inst) {
7883 var input = $(target);
7884 inst.append = $([]);
7885 inst.trigger = $([]);
7886 if (input.hasClass(this.markerClassName)) {
7889 this._attachments(input, inst);
7890 input.addClass(this.markerClassName).keydown(this._doKeyDown).
7891 keypress(this._doKeyPress).keyup(this._doKeyUp);
7892 this._autoSize(inst);
7893 $.data(target, "datepicker", inst);
7894 //If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665)
7895 if( inst.settings.disabled ) {
7896 this._disableDatepicker( target );
7900 /* Make attachments based on settings. */
7901 _attachments: function(input, inst) {
7902 var showOn, buttonText, buttonImage,
7903 appendText = this._get(inst, "appendText"),
7904 isRTL = this._get(inst, "isRTL");
7907 inst.append.remove();
7910 inst.append = $("<span class='" + this._appendClass + "'>" + appendText + "</span>");
7911 input[isRTL ? "before" : "after"](inst.append);
7914 input.unbind("focus", this._showDatepicker);
7917 inst.trigger.remove();
7920 showOn = this._get(inst, "showOn");
7921 if (showOn === "focus" || showOn === "both") { // pop-up date picker when in the marked field
7922 input.focus(this._showDatepicker);
7924 if (showOn === "button" || showOn === "both") { // pop-up date picker when button clicked
7925 buttonText = this._get(inst, "buttonText");
7926 buttonImage = this._get(inst, "buttonImage");
7927 inst.trigger = $(this._get(inst, "buttonImageOnly") ?
7928 $("<img/>").addClass(this._triggerClass).
7929 attr({ src: buttonImage, alt: buttonText, title: buttonText }) :
7930 $("<button type='button'></button>").addClass(this._triggerClass).
7931 html(!buttonImage ? buttonText : $("<img/>").attr(
7932 { src:buttonImage, alt:buttonText, title:buttonText })));
7933 input[isRTL ? "before" : "after"](inst.trigger);
7934 inst.trigger.click(function() {
7935 if ($.datepicker._datepickerShowing && $.datepicker._lastInput === input[0]) {
7936 $.datepicker._hideDatepicker();
7937 } else if ($.datepicker._datepickerShowing && $.datepicker._lastInput !== input[0]) {
7938 $.datepicker._hideDatepicker();
7939 $.datepicker._showDatepicker(input[0]);
7941 $.datepicker._showDatepicker(input[0]);
7948 /* Apply the maximum length for the date format. */
7949 _autoSize: function(inst) {
7950 if (this._get(inst, "autoSize") && !inst.inline) {
7951 var findMax, max, maxI, i,
7952 date = new Date(2009, 12 - 1, 20), // Ensure double digits
7953 dateFormat = this._get(inst, "dateFormat");
7955 if (dateFormat.match(/[DM]/)) {
7956 findMax = function(names) {
7959 for (i = 0; i < names.length; i++) {
7960 if (names[i].length > max) {
7961 max = names[i].length;
7967 date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ?
7968 "monthNames" : "monthNamesShort"))));
7969 date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ?
7970 "dayNames" : "dayNamesShort"))) + 20 - date.getDay());
7972 inst.input.attr("size", this._formatDate(inst, date).length);
7976 /* Attach an inline date picker to a div. */
7977 _inlineDatepicker: function(target, inst) {
7978 var divSpan = $(target);
7979 if (divSpan.hasClass(this.markerClassName)) {
7982 divSpan.addClass(this.markerClassName).append(inst.dpDiv);
7983 $.data(target, "datepicker", inst);
7984 this._setDate(inst, this._getDefaultDate(inst), true);
7985 this._updateDatepicker(inst);
7986 this._updateAlternate(inst);
7987 //If disabled option is true, disable the datepicker before showing it (see ticket #5665)
7988 if( inst.settings.disabled ) {
7989 this._disableDatepicker( target );
7991 // Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements
7992 // http://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height
7993 inst.dpDiv.css( "display", "block" );
7996 /* Pop-up the date picker in a "dialog" box.
7997 * @param input element - ignored
7998 * @param date string or Date - the initial date to display
7999 * @param onSelect function - the function to call when a date is selected
8000 * @param settings object - update the dialog date picker instance's settings (anonymous object)
8001 * @param pos int[2] - coordinates for the dialog's position within the screen or
8002 * event - with x/y coordinates or
8003 * leave empty for default (screen centre)
8004 * @return the manager object
8006 _dialogDatepicker: function(input, date, onSelect, settings, pos) {
8007 var id, browserWidth, browserHeight, scrollX, scrollY,
8008 inst = this._dialogInst; // internal instance
8012 id = "dp" + this.uuid;
8013 this._dialogInput = $("<input type='text' id='" + id +
8014 "' style='position: absolute; top: -100px; width: 0px;'/>");
8015 this._dialogInput.keydown(this._doKeyDown);
8016 $("body").append(this._dialogInput);
8017 inst = this._dialogInst = this._newInst(this._dialogInput, false);
8019 $.data(this._dialogInput[0], "datepicker", inst);
8021 datepicker_extendRemove(inst.settings, settings || {});
8022 date = (date && date.constructor === Date ? this._formatDate(inst, date) : date);
8023 this._dialogInput.val(date);
8025 this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);
8027 browserWidth = document.documentElement.clientWidth;
8028 browserHeight = document.documentElement.clientHeight;
8029 scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
8030 scrollY = document.documentElement.scrollTop || document.body.scrollTop;
8031 this._pos = // should use actual width/height below
8032 [(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY];
8035 // move input on screen for focus, but hidden behind dialog
8036 this._dialogInput.css("left", (this._pos[0] + 20) + "px").css("top", this._pos[1] + "px");
8037 inst.settings.onSelect = onSelect;
8038 this._inDialog = true;
8039 this.dpDiv.addClass(this._dialogClass);
8040 this._showDatepicker(this._dialogInput[0]);
8042 $.blockUI(this.dpDiv);
8044 $.data(this._dialogInput[0], "datepicker", inst);
8048 /* Detach a datepicker from its control.
8049 * @param target element - the target input field or division or span
8051 _destroyDatepicker: function(target) {
8053 $target = $(target),
8054 inst = $.data(target, "datepicker");
8056 if (!$target.hasClass(this.markerClassName)) {
8060 nodeName = target.nodeName.toLowerCase();
8061 $.removeData(target, "datepicker");
8062 if (nodeName === "input") {
8063 inst.append.remove();
8064 inst.trigger.remove();
8065 $target.removeClass(this.markerClassName).
8066 unbind("focus", this._showDatepicker).
8067 unbind("keydown", this._doKeyDown).
8068 unbind("keypress", this._doKeyPress).
8069 unbind("keyup", this._doKeyUp);
8070 } else if (nodeName === "div" || nodeName === "span") {
8071 $target.removeClass(this.markerClassName).empty();
8075 /* Enable the date picker to a jQuery selection.
8076 * @param target element - the target input field or division or span
8078 _enableDatepicker: function(target) {
8079 var nodeName, inline,
8080 $target = $(target),
8081 inst = $.data(target, "datepicker");
8083 if (!$target.hasClass(this.markerClassName)) {
8087 nodeName = target.nodeName.toLowerCase();
8088 if (nodeName === "input") {
8089 target.disabled = false;
8090 inst.trigger.filter("button").
8091 each(function() { this.disabled = false; }).end().
8092 filter("img").css({opacity: "1.0", cursor: ""});
8093 } else if (nodeName === "div" || nodeName === "span") {
8094 inline = $target.children("." + this._inlineClass);
8095 inline.children().removeClass("ui-state-disabled");
8096 inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
8097 prop("disabled", false);
8099 this._disabledInputs = $.map(this._disabledInputs,
8100 function(value) { return (value === target ? null : value); }); // delete entry
8103 /* Disable the date picker to a jQuery selection.
8104 * @param target element - the target input field or division or span
8106 _disableDatepicker: function(target) {
8107 var nodeName, inline,
8108 $target = $(target),
8109 inst = $.data(target, "datepicker");
8111 if (!$target.hasClass(this.markerClassName)) {
8115 nodeName = target.nodeName.toLowerCase();
8116 if (nodeName === "input") {
8117 target.disabled = true;
8118 inst.trigger.filter("button").
8119 each(function() { this.disabled = true; }).end().
8120 filter("img").css({opacity: "0.5", cursor: "default"});
8121 } else if (nodeName === "div" || nodeName === "span") {
8122 inline = $target.children("." + this._inlineClass);
8123 inline.children().addClass("ui-state-disabled");
8124 inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
8125 prop("disabled", true);
8127 this._disabledInputs = $.map(this._disabledInputs,
8128 function(value) { return (value === target ? null : value); }); // delete entry
8129 this._disabledInputs[this._disabledInputs.length] = target;
8132 /* Is the first field in a jQuery collection disabled as a datepicker?
8133 * @param target element - the target input field or division or span
8134 * @return boolean - true if disabled, false if enabled
8136 _isDisabledDatepicker: function(target) {
8140 for (var i = 0; i < this._disabledInputs.length; i++) {
8141 if (this._disabledInputs[i] === target) {
8148 /* Retrieve the instance data for the target control.
8149 * @param target element - the target input field or division or span
8150 * @return object - the associated instance data
8151 * @throws error if a jQuery problem getting data
8153 _getInst: function(target) {
8155 return $.data(target, "datepicker");
8158 throw "Missing instance data for this datepicker";
8162 /* Update or retrieve the settings for a date picker attached to an input field or division.
8163 * @param target element - the target input field or division or span
8164 * @param name object - the new settings to update or
8165 * string - the name of the setting to change or retrieve,
8166 * when retrieving also "all" for all instance settings or
8167 * "defaults" for all global defaults
8168 * @param value any - the new value for the setting
8169 * (omit if above is an object or to retrieve a value)
8171 _optionDatepicker: function(target, name, value) {
8172 var settings, date, minDate, maxDate,
8173 inst = this._getInst(target);
8175 if (arguments.length === 2 && typeof name === "string") {
8176 return (name === "defaults" ? $.extend({}, $.datepicker._defaults) :
8177 (inst ? (name === "all" ? $.extend({}, inst.settings) :
8178 this._get(inst, name)) : null));
8181 settings = name || {};
8182 if (typeof name === "string") {
8184 settings[name] = value;
8188 if (this._curInst === inst) {
8189 this._hideDatepicker();
8192 date = this._getDateDatepicker(target, true);
8193 minDate = this._getMinMaxDate(inst, "min");
8194 maxDate = this._getMinMaxDate(inst, "max");
8195 datepicker_extendRemove(inst.settings, settings);
8196 // reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided
8197 if (minDate !== null && settings.dateFormat !== undefined && settings.minDate === undefined) {
8198 inst.settings.minDate = this._formatDate(inst, minDate);
8200 if (maxDate !== null && settings.dateFormat !== undefined && settings.maxDate === undefined) {
8201 inst.settings.maxDate = this._formatDate(inst, maxDate);
8203 if ( "disabled" in settings ) {
8204 if ( settings.disabled ) {
8205 this._disableDatepicker(target);
8207 this._enableDatepicker(target);
8210 this._attachments($(target), inst);
8211 this._autoSize(inst);
8212 this._setDate(inst, date);
8213 this._updateAlternate(inst);
8214 this._updateDatepicker(inst);
8218 // change method deprecated
8219 _changeDatepicker: function(target, name, value) {
8220 this._optionDatepicker(target, name, value);
8223 /* Redraw the date picker attached to an input field or division.
8224 * @param target element - the target input field or division or span
8226 _refreshDatepicker: function(target) {
8227 var inst = this._getInst(target);
8229 this._updateDatepicker(inst);
8233 /* Set the dates for a jQuery selection.
8234 * @param target element - the target input field or division or span
8235 * @param date Date - the new date
8237 _setDateDatepicker: function(target, date) {
8238 var inst = this._getInst(target);
8240 this._setDate(inst, date);
8241 this._updateDatepicker(inst);
8242 this._updateAlternate(inst);
8246 /* Get the date(s) for the first entry in a jQuery selection.
8247 * @param target element - the target input field or division or span
8248 * @param noDefault boolean - true if no default date is to be used
8249 * @return Date - the current date
8251 _getDateDatepicker: function(target, noDefault) {
8252 var inst = this._getInst(target);
8253 if (inst && !inst.inline) {
8254 this._setDateFromField(inst, noDefault);
8256 return (inst ? this._getDate(inst) : null);
8259 /* Handle keystrokes. */
8260 _doKeyDown: function(event) {
8261 var onSelect, dateStr, sel,
8262 inst = $.datepicker._getInst(event.target),
8264 isRTL = inst.dpDiv.is(".ui-datepicker-rtl");
8266 inst._keyEvent = true;
8267 if ($.datepicker._datepickerShowing) {
8268 switch (event.keyCode) {
8269 case 9: $.datepicker._hideDatepicker();
8271 break; // hide on tab out
8272 case 13: sel = $("td." + $.datepicker._dayOverClass + ":not(." +
8273 $.datepicker._currentClass + ")", inst.dpDiv);
8275 $.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);
8278 onSelect = $.datepicker._get(inst, "onSelect");
8280 dateStr = $.datepicker._formatDate(inst);
8282 // trigger custom callback
8283 onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);
8285 $.datepicker._hideDatepicker();
8288 return false; // don't submit the form
8289 case 27: $.datepicker._hideDatepicker();
8290 break; // hide on escape
8291 case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
8292 -$.datepicker._get(inst, "stepBigMonths") :
8293 -$.datepicker._get(inst, "stepMonths")), "M");
8294 break; // previous month/year on page up/+ ctrl
8295 case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
8296 +$.datepicker._get(inst, "stepBigMonths") :
8297 +$.datepicker._get(inst, "stepMonths")), "M");
8298 break; // next month/year on page down/+ ctrl
8299 case 35: if (event.ctrlKey || event.metaKey) {
8300 $.datepicker._clearDate(event.target);
8302 handled = event.ctrlKey || event.metaKey;
8303 break; // clear on ctrl or command +end
8304 case 36: if (event.ctrlKey || event.metaKey) {
8305 $.datepicker._gotoToday(event.target);
8307 handled = event.ctrlKey || event.metaKey;
8308 break; // current on ctrl or command +home
8309 case 37: if (event.ctrlKey || event.metaKey) {
8310 $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), "D");
8312 handled = event.ctrlKey || event.metaKey;
8313 // -1 day on ctrl or command +left
8314 if (event.originalEvent.altKey) {
8315 $.datepicker._adjustDate(event.target, (event.ctrlKey ?
8316 -$.datepicker._get(inst, "stepBigMonths") :
8317 -$.datepicker._get(inst, "stepMonths")), "M");
8319 // next month/year on alt +left on Mac
8321 case 38: if (event.ctrlKey || event.metaKey) {
8322 $.datepicker._adjustDate(event.target, -7, "D");
8324 handled = event.ctrlKey || event.metaKey;
8325 break; // -1 week on ctrl or command +up
8326 case 39: if (event.ctrlKey || event.metaKey) {
8327 $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), "D");
8329 handled = event.ctrlKey || event.metaKey;
8330 // +1 day on ctrl or command +right
8331 if (event.originalEvent.altKey) {
8332 $.datepicker._adjustDate(event.target, (event.ctrlKey ?
8333 +$.datepicker._get(inst, "stepBigMonths") :
8334 +$.datepicker._get(inst, "stepMonths")), "M");
8336 // next month/year on alt +right
8338 case 40: if (event.ctrlKey || event.metaKey) {
8339 $.datepicker._adjustDate(event.target, +7, "D");
8341 handled = event.ctrlKey || event.metaKey;
8342 break; // +1 week on ctrl or command +down
8343 default: handled = false;
8345 } else if (event.keyCode === 36 && event.ctrlKey) { // display the date picker on ctrl+home
8346 $.datepicker._showDatepicker(this);
8352 event.preventDefault();
8353 event.stopPropagation();
8357 /* Filter entered characters - based on date format. */
8358 _doKeyPress: function(event) {
8360 inst = $.datepicker._getInst(event.target);
8362 if ($.datepicker._get(inst, "constrainInput")) {
8363 chars = $.datepicker._possibleChars($.datepicker._get(inst, "dateFormat"));
8364 chr = String.fromCharCode(event.charCode == null ? event.keyCode : event.charCode);
8365 return event.ctrlKey || event.metaKey || (chr < " " || !chars || chars.indexOf(chr) > -1);
8369 /* Synchronise manual entry and field/alternate field. */
8370 _doKeyUp: function(event) {
8372 inst = $.datepicker._getInst(event.target);
8374 if (inst.input.val() !== inst.lastVal) {
8376 date = $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"),
8377 (inst.input ? inst.input.val() : null),
8378 $.datepicker._getFormatConfig(inst));
8380 if (date) { // only if valid
8381 $.datepicker._setDateFromField(inst);
8382 $.datepicker._updateAlternate(inst);
8383 $.datepicker._updateDatepicker(inst);
8392 /* Pop-up the date picker for a given input field.
8393 * If false returned from beforeShow event handler do not show.
8394 * @param input element - the input field attached to the date picker or
8395 * event - if triggered by focus
8397 _showDatepicker: function(input) {
8398 input = input.target || input;
8399 if (input.nodeName.toLowerCase() !== "input") { // find from button/image trigger
8400 input = $("input", input.parentNode)[0];
8403 if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput === input) { // already here
8407 var inst, beforeShow, beforeShowSettings, isFixed,
8408 offset, showAnim, duration;
8410 inst = $.datepicker._getInst(input);
8411 if ($.datepicker._curInst && $.datepicker._curInst !== inst) {
8412 $.datepicker._curInst.dpDiv.stop(true, true);
8413 if ( inst && $.datepicker._datepickerShowing ) {
8414 $.datepicker._hideDatepicker( $.datepicker._curInst.input[0] );
8418 beforeShow = $.datepicker._get(inst, "beforeShow");
8419 beforeShowSettings = beforeShow ? beforeShow.apply(input, [input, inst]) : {};
8420 if(beforeShowSettings === false){
8423 datepicker_extendRemove(inst.settings, beforeShowSettings);
8425 inst.lastVal = null;
8426 $.datepicker._lastInput = input;
8427 $.datepicker._setDateFromField(inst);
8429 if ($.datepicker._inDialog) { // hide cursor
8432 if (!$.datepicker._pos) { // position below input
8433 $.datepicker._pos = $.datepicker._findPos(input);
8434 $.datepicker._pos[1] += input.offsetHeight; // add the height
8438 $(input).parents().each(function() {
8439 isFixed |= $(this).css("position") === "fixed";
8443 offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]};
8444 $.datepicker._pos = null;
8445 //to avoid flashes on Firefox
8447 // determine sizing offscreen
8448 inst.dpDiv.css({position: "absolute", display: "block", top: "-1000px"});
8449 $.datepicker._updateDatepicker(inst);
8450 // fix width for dynamic number of date pickers
8451 // and adjust position before showing
8452 offset = $.datepicker._checkOffset(inst, offset, isFixed);
8453 inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ?
8454 "static" : (isFixed ? "fixed" : "absolute")), display: "none",
8455 left: offset.left + "px", top: offset.top + "px"});
8458 showAnim = $.datepicker._get(inst, "showAnim");
8459 duration = $.datepicker._get(inst, "duration");
8460 inst.dpDiv.css( "z-index", datepicker_getZindex( $( input ) ) + 1 );
8461 $.datepicker._datepickerShowing = true;
8463 if ( $.effects && $.effects.effect[ showAnim ] ) {
8464 inst.dpDiv.show(showAnim, $.datepicker._get(inst, "showOptions"), duration);
8466 inst.dpDiv[showAnim || "show"](showAnim ? duration : null);
8469 if ( $.datepicker._shouldFocusInput( inst ) ) {
8473 $.datepicker._curInst = inst;
8477 /* Generate the date picker content. */
8478 _updateDatepicker: function(inst) {
8479 this.maxRows = 4; //Reset the max number of rows being displayed (see #7043)
8480 datepicker_instActive = inst; // for delegate hover events
8481 inst.dpDiv.empty().append(this._generateHTML(inst));
8482 this._attachHandlers(inst);
8483 inst.dpDiv.find("." + this._dayOverClass + " a");
8486 numMonths = this._getNumberOfMonths(inst),
8487 cols = numMonths[1],
8490 inst.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width("");
8492 inst.dpDiv.addClass("ui-datepicker-multi-" + cols).css("width", (width * cols) + "em");
8494 inst.dpDiv[(numMonths[0] !== 1 || numMonths[1] !== 1 ? "add" : "remove") +
8495 "Class"]("ui-datepicker-multi");
8496 inst.dpDiv[(this._get(inst, "isRTL") ? "add" : "remove") +
8497 "Class"]("ui-datepicker-rtl");
8499 if (inst === $.datepicker._curInst && $.datepicker._datepickerShowing && $.datepicker._shouldFocusInput( inst ) ) {
8503 // deffered render of the years select (to avoid flashes on Firefox)
8504 if( inst.yearshtml ){
8505 origyearshtml = inst.yearshtml;
8506 setTimeout(function(){
8507 //assure that inst.yearshtml didn't change.
8508 if( origyearshtml === inst.yearshtml && inst.yearshtml ){
8509 inst.dpDiv.find("select.ui-datepicker-year:first").replaceWith(inst.yearshtml);
8511 origyearshtml = inst.yearshtml = null;
8516 // #6694 - don't focus the input if it's already focused
8517 // this breaks the change event in IE
8518 // Support: IE and jQuery <1.9
8519 _shouldFocusInput: function( inst ) {
8520 return inst.input && inst.input.is( ":visible" ) && !inst.input.is( ":disabled" ) && !inst.input.is( ":focus" );
8523 /* Check positioning to remain on screen. */
8524 _checkOffset: function(inst, offset, isFixed) {
8525 var dpWidth = inst.dpDiv.outerWidth(),
8526 dpHeight = inst.dpDiv.outerHeight(),
8527 inputWidth = inst.input ? inst.input.outerWidth() : 0,
8528 inputHeight = inst.input ? inst.input.outerHeight() : 0,
8529 viewWidth = document.documentElement.clientWidth + (isFixed ? 0 : $(document).scrollLeft()),
8530 viewHeight = document.documentElement.clientHeight + (isFixed ? 0 : $(document).scrollTop());
8532 offset.left -= (this._get(inst, "isRTL") ? (dpWidth - inputWidth) : 0);
8533 offset.left -= (isFixed && offset.left === inst.input.offset().left) ? $(document).scrollLeft() : 0;
8534 offset.top -= (isFixed && offset.top === (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;
8536 // now check if datepicker is showing outside window viewport - move to a better place if so.
8537 offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?
8538 Math.abs(offset.left + dpWidth - viewWidth) : 0);
8539 offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?
8540 Math.abs(dpHeight + inputHeight) : 0);
8545 /* Find an object's position on the screen. */
8546 _findPos: function(obj) {
8548 inst = this._getInst(obj),
8549 isRTL = this._get(inst, "isRTL");
8551 while (obj && (obj.type === "hidden" || obj.nodeType !== 1 || $.expr.filters.hidden(obj))) {
8552 obj = obj[isRTL ? "previousSibling" : "nextSibling"];
8555 position = $(obj).offset();
8556 return [position.left, position.top];
8559 /* Hide the date picker from view.
8560 * @param input element - the input field attached to the date picker
8562 _hideDatepicker: function(input) {
8563 var showAnim, duration, postProcess, onClose,
8564 inst = this._curInst;
8566 if (!inst || (input && inst !== $.data(input, "datepicker"))) {
8570 if (this._datepickerShowing) {
8571 showAnim = this._get(inst, "showAnim");
8572 duration = this._get(inst, "duration");
8573 postProcess = function() {
8574 $.datepicker._tidyDialog(inst);
8577 // DEPRECATED: after BC for 1.8.x $.effects[ showAnim ] is not needed
8578 if ( $.effects && ( $.effects.effect[ showAnim ] || $.effects[ showAnim ] ) ) {
8579 inst.dpDiv.hide(showAnim, $.datepicker._get(inst, "showOptions"), duration, postProcess);
8581 inst.dpDiv[(showAnim === "slideDown" ? "slideUp" :
8582 (showAnim === "fadeIn" ? "fadeOut" : "hide"))]((showAnim ? duration : null), postProcess);
8588 this._datepickerShowing = false;
8590 onClose = this._get(inst, "onClose");
8592 onClose.apply((inst.input ? inst.input[0] : null), [(inst.input ? inst.input.val() : ""), inst]);
8595 this._lastInput = null;
8596 if (this._inDialog) {
8597 this._dialogInput.css({ position: "absolute", left: "0", top: "-100px" });
8600 $("body").append(this.dpDiv);
8603 this._inDialog = false;
8607 /* Tidy up after a dialog display. */
8608 _tidyDialog: function(inst) {
8609 inst.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar");
8612 /* Close date picker if clicked elsewhere. */
8613 _checkExternalClick: function(event) {
8614 if (!$.datepicker._curInst) {
8618 var $target = $(event.target),
8619 inst = $.datepicker._getInst($target[0]);
8621 if ( ( ( $target[0].id !== $.datepicker._mainDivId &&
8622 $target.parents("#" + $.datepicker._mainDivId).length === 0 &&
8623 !$target.hasClass($.datepicker.markerClassName) &&
8624 !$target.closest("." + $.datepicker._triggerClass).length &&
8625 $.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI) ) ) ||
8626 ( $target.hasClass($.datepicker.markerClassName) && $.datepicker._curInst !== inst ) ) {
8627 $.datepicker._hideDatepicker();
8631 /* Adjust one of the date sub-fields. */
8632 _adjustDate: function(id, offset, period) {
8634 inst = this._getInst(target[0]);
8636 if (this._isDisabledDatepicker(target[0])) {
8639 this._adjustInstDate(inst, offset +
8640 (period === "M" ? this._get(inst, "showCurrentAtPos") : 0), // undo positioning
8642 this._updateDatepicker(inst);
8645 /* Action for current link. */
8646 _gotoToday: function(id) {
8649 inst = this._getInst(target[0]);
8651 if (this._get(inst, "gotoCurrent") && inst.currentDay) {
8652 inst.selectedDay = inst.currentDay;
8653 inst.drawMonth = inst.selectedMonth = inst.currentMonth;
8654 inst.drawYear = inst.selectedYear = inst.currentYear;
8657 inst.selectedDay = date.getDate();
8658 inst.drawMonth = inst.selectedMonth = date.getMonth();
8659 inst.drawYear = inst.selectedYear = date.getFullYear();
8661 this._notifyChange(inst);
8662 this._adjustDate(target);
8665 /* Action for selecting a new month/year. */
8666 _selectMonthYear: function(id, select, period) {
8668 inst = this._getInst(target[0]);
8670 inst["selected" + (period === "M" ? "Month" : "Year")] =
8671 inst["draw" + (period === "M" ? "Month" : "Year")] =
8672 parseInt(select.options[select.selectedIndex].value,10);
8674 this._notifyChange(inst);
8675 this._adjustDate(target);
8678 /* Action for selecting a day. */
8679 _selectDay: function(id, month, year, td) {
8683 if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) {
8687 inst = this._getInst(target[0]);
8688 inst.selectedDay = inst.currentDay = $("a", td).html();
8689 inst.selectedMonth = inst.currentMonth = month;
8690 inst.selectedYear = inst.currentYear = year;
8691 this._selectDate(id, this._formatDate(inst,
8692 inst.currentDay, inst.currentMonth, inst.currentYear));
8695 /* Erase the input field and hide the date picker. */
8696 _clearDate: function(id) {
8698 this._selectDate(target, "");
8701 /* Update the input field with the selected date. */
8702 _selectDate: function(id, dateStr) {
8705 inst = this._getInst(target[0]);
8707 dateStr = (dateStr != null ? dateStr : this._formatDate(inst));
8709 inst.input.val(dateStr);
8711 this._updateAlternate(inst);
8713 onSelect = this._get(inst, "onSelect");
8715 onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); // trigger custom callback
8716 } else if (inst.input) {
8717 inst.input.trigger("change"); // fire the change event
8721 this._updateDatepicker(inst);
8723 this._hideDatepicker();
8724 this._lastInput = inst.input[0];
8725 if (typeof(inst.input[0]) !== "object") {
8726 inst.input.focus(); // restore focus
8728 this._lastInput = null;
8732 /* Update any alternate field to synchronise with the main field. */
8733 _updateAlternate: function(inst) {
8734 var altFormat, date, dateStr,
8735 altField = this._get(inst, "altField");
8737 if (altField) { // update alternate field too
8738 altFormat = this._get(inst, "altFormat") || this._get(inst, "dateFormat");
8739 date = this._getDate(inst);
8740 dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst));
8741 $(altField).each(function() { $(this).val(dateStr); });
8745 /* Set as beforeShowDay function to prevent selection of weekends.
8746 * @param date Date - the date to customise
8747 * @return [boolean, string] - is this date selectable?, what is its CSS class?
8749 noWeekends: function(date) {
8750 var day = date.getDay();
8751 return [(day > 0 && day < 6), ""];
8754 /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
8755 * @param date Date - the date to get the week for
8756 * @return number - the number of the week within the year that contains this date
8758 iso8601Week: function(date) {
8760 checkDate = new Date(date.getTime());
8762 // Find Thursday of this week starting on Monday
8763 checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7));
8765 time = checkDate.getTime();
8766 checkDate.setMonth(0); // Compare with Jan 1
8767 checkDate.setDate(1);
8768 return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
8771 /* Parse a string value into a date object.
8772 * See formatDate below for the possible formats.
8774 * @param format string - the expected format of the date
8775 * @param value string - the date in the above format
8776 * @param settings Object - attributes include:
8777 * shortYearCutoff number - the cutoff year for determining the century (optional)
8778 * dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
8779 * dayNames string[7] - names of the days from Sunday (optional)
8780 * monthNamesShort string[12] - abbreviated names of the months (optional)
8781 * monthNames string[12] - names of the months (optional)
8782 * @return Date - the extracted date value or null if value is blank
8784 parseDate: function (format, value, settings) {
8785 if (format == null || value == null) {
8786 throw "Invalid arguments";
8789 value = (typeof value === "object" ? value.toString() : value + "");
8794 var iFormat, dim, extra,
8796 shortYearCutoffTemp = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff,
8797 shortYearCutoff = (typeof shortYearCutoffTemp !== "string" ? shortYearCutoffTemp :
8798 new Date().getFullYear() % 100 + parseInt(shortYearCutoffTemp, 10)),
8799 dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort,
8800 dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames,
8801 monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort,
8802 monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames,
8809 // Check whether a format character is doubled
8810 lookAhead = function(match) {
8811 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match);
8817 // Extract a number from the string value
8818 getNumber = function(match) {
8819 var isDoubled = lookAhead(match),
8820 size = (match === "@" ? 14 : (match === "!" ? 20 :
8821 (match === "y" && isDoubled ? 4 : (match === "o" ? 3 : 2)))),
8822 digits = new RegExp("^\\d{1," + size + "}"),
8823 num = value.substring(iValue).match(digits);
8825 throw "Missing number at position " + iValue;
8827 iValue += num[0].length;
8828 return parseInt(num[0], 10);
8830 // Extract a name from the string value and convert to an index
8831 getName = function(match, shortNames, longNames) {
8833 names = $.map(lookAhead(match) ? longNames : shortNames, function (v, k) {
8835 }).sort(function (a, b) {
8836 return -(a[1].length - b[1].length);
8839 $.each(names, function (i, pair) {
8841 if (value.substr(iValue, name.length).toLowerCase() === name.toLowerCase()) {
8843 iValue += name.length;
8850 throw "Unknown name at position " + iValue;
8853 // Confirm that a literal character matches the string value
8854 checkLiteral = function() {
8855 if (value.charAt(iValue) !== format.charAt(iFormat)) {
8856 throw "Unexpected literal at position " + iValue;
8861 for (iFormat = 0; iFormat < format.length; iFormat++) {
8863 if (format.charAt(iFormat) === "'" && !lookAhead("'")) {
8869 switch (format.charAt(iFormat)) {
8871 day = getNumber("d");
8874 getName("D", dayNamesShort, dayNames);
8877 doy = getNumber("o");
8880 month = getNumber("m");
8883 month = getName("M", monthNamesShort, monthNames);
8886 year = getNumber("y");
8889 date = new Date(getNumber("@"));
8890 year = date.getFullYear();
8891 month = date.getMonth() + 1;
8892 day = date.getDate();
8895 date = new Date((getNumber("!") - this._ticksTo1970) / 10000);
8896 year = date.getFullYear();
8897 month = date.getMonth() + 1;
8898 day = date.getDate();
8901 if (lookAhead("'")){
8913 if (iValue < value.length){
8914 extra = value.substr(iValue);
8915 if (!/^\s+/.test(extra)) {
8916 throw "Extra/unparsed characters found in date: " + extra;
8921 year = new Date().getFullYear();
8922 } else if (year < 100) {
8923 year += new Date().getFullYear() - new Date().getFullYear() % 100 +
8924 (year <= shortYearCutoff ? 0 : -100);
8931 dim = this._getDaysInMonth(year, month - 1);
8940 date = this._daylightSavingAdjust(new Date(year, month - 1, day));
8941 if (date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day) {
8942 throw "Invalid date"; // E.g. 31/02/00
8947 /* Standard date formats. */
8948 ATOM: "yy-mm-dd", // RFC 3339 (ISO 8601)
8949 COOKIE: "D, dd M yy",
8950 ISO_8601: "yy-mm-dd",
8951 RFC_822: "D, d M y",
8952 RFC_850: "DD, dd-M-y",
8953 RFC_1036: "D, d M y",
8954 RFC_1123: "D, d M yy",
8955 RFC_2822: "D, d M yy",
8956 RSS: "D, d M y", // RFC 822
8959 W3C: "yy-mm-dd", // ISO 8601
8961 _ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) +
8962 Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000),
8964 /* Format a date object into a string value.
8965 * The format can be combinations of the following:
8966 * d - day of month (no leading zero)
8967 * dd - day of month (two digit)
8968 * o - day of year (no leading zeros)
8969 * oo - day of year (three digit)
8970 * D - day name short
8971 * DD - day name long
8972 * m - month of year (no leading zero)
8973 * mm - month of year (two digit)
8974 * M - month name short
8975 * MM - month name long
8976 * y - year (two digit)
8977 * yy - year (four digit)
8978 * @ - Unix timestamp (ms since 01/01/1970)
8979 * ! - Windows ticks (100ns since 01/01/0001)
8980 * "..." - literal text
8983 * @param format string - the desired format of the date
8984 * @param date Date - the date value to format
8985 * @param settings Object - attributes include:
8986 * dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
8987 * dayNames string[7] - names of the days from Sunday (optional)
8988 * monthNamesShort string[12] - abbreviated names of the months (optional)
8989 * monthNames string[12] - names of the months (optional)
8990 * @return string - the date in the above format
8992 formatDate: function (format, date, settings) {
8998 dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort,
8999 dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames,
9000 monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort,
9001 monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames,
9002 // Check whether a format character is doubled
9003 lookAhead = function(match) {
9004 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match);
9010 // Format a number, with leading zero if necessary
9011 formatNumber = function(match, value, len) {
9012 var num = "" + value;
9013 if (lookAhead(match)) {
9014 while (num.length < len) {
9020 // Format a name, short or long as requested
9021 formatName = function(match, value, shortNames, longNames) {
9022 return (lookAhead(match) ? longNames[value] : shortNames[value]);
9028 for (iFormat = 0; iFormat < format.length; iFormat++) {
9030 if (format.charAt(iFormat) === "'" && !lookAhead("'")) {
9033 output += format.charAt(iFormat);
9036 switch (format.charAt(iFormat)) {
9038 output += formatNumber("d", date.getDate(), 2);
9041 output += formatName("D", date.getDay(), dayNamesShort, dayNames);
9044 output += formatNumber("o",
9045 Math.round((new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000), 3);
9048 output += formatNumber("m", date.getMonth() + 1, 2);
9051 output += formatName("M", date.getMonth(), monthNamesShort, monthNames);
9054 output += (lookAhead("y") ? date.getFullYear() :
9055 (date.getYear() % 100 < 10 ? "0" : "") + date.getYear() % 100);
9058 output += date.getTime();
9061 output += date.getTime() * 10000 + this._ticksTo1970;
9064 if (lookAhead("'")) {
9071 output += format.charAt(iFormat);
9079 /* Extract all possible characters from the date format. */
9080 _possibleChars: function (format) {
9084 // Check whether a format character is doubled
9085 lookAhead = function(match) {
9086 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match);
9093 for (iFormat = 0; iFormat < format.length; iFormat++) {
9095 if (format.charAt(iFormat) === "'" && !lookAhead("'")) {
9098 chars += format.charAt(iFormat);
9101 switch (format.charAt(iFormat)) {
9102 case "d": case "m": case "y": case "@":
9103 chars += "0123456789";
9106 return null; // Accept anything
9108 if (lookAhead("'")) {
9115 chars += format.charAt(iFormat);
9122 /* Get a setting value, defaulting if necessary. */
9123 _get: function(inst, name) {
9124 return inst.settings[name] !== undefined ?
9125 inst.settings[name] : this._defaults[name];
9128 /* Parse existing date and initialise date picker. */
9129 _setDateFromField: function(inst, noDefault) {
9130 if (inst.input.val() === inst.lastVal) {
9134 var dateFormat = this._get(inst, "dateFormat"),
9135 dates = inst.lastVal = inst.input ? inst.input.val() : null,
9136 defaultDate = this._getDefaultDate(inst),
9138 settings = this._getFormatConfig(inst);
9141 date = this.parseDate(dateFormat, dates, settings) || defaultDate;
9143 dates = (noDefault ? "" : dates);
9145 inst.selectedDay = date.getDate();
9146 inst.drawMonth = inst.selectedMonth = date.getMonth();
9147 inst.drawYear = inst.selectedYear = date.getFullYear();
9148 inst.currentDay = (dates ? date.getDate() : 0);
9149 inst.currentMonth = (dates ? date.getMonth() : 0);
9150 inst.currentYear = (dates ? date.getFullYear() : 0);
9151 this._adjustInstDate(inst);
9154 /* Retrieve the default date shown on opening. */
9155 _getDefaultDate: function(inst) {
9156 return this._restrictMinMax(inst,
9157 this._determineDate(inst, this._get(inst, "defaultDate"), new Date()));
9160 /* A date may be specified as an exact value or a relative one. */
9161 _determineDate: function(inst, date, defaultDate) {
9162 var offsetNumeric = function(offset) {
9163 var date = new Date();
9164 date.setDate(date.getDate() + offset);
9167 offsetString = function(offset) {
9169 return $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"),
9170 offset, $.datepicker._getFormatConfig(inst));
9176 var date = (offset.toLowerCase().match(/^c/) ?
9177 $.datepicker._getDate(inst) : null) || new Date(),
9178 year = date.getFullYear(),
9179 month = date.getMonth(),
9180 day = date.getDate(),
9181 pattern = /([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,
9182 matches = pattern.exec(offset);
9185 switch (matches[2] || "d") {
9186 case "d" : case "D" :
9187 day += parseInt(matches[1],10); break;
9188 case "w" : case "W" :
9189 day += parseInt(matches[1],10) * 7; break;
9190 case "m" : case "M" :
9191 month += parseInt(matches[1],10);
9192 day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
9194 case "y": case "Y" :
9195 year += parseInt(matches[1],10);
9196 day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
9199 matches = pattern.exec(offset);
9201 return new Date(year, month, day);
9203 newDate = (date == null || date === "" ? defaultDate : (typeof date === "string" ? offsetString(date) :
9204 (typeof date === "number" ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : new Date(date.getTime()))));
9206 newDate = (newDate && newDate.toString() === "Invalid Date" ? defaultDate : newDate);
9208 newDate.setHours(0);
9209 newDate.setMinutes(0);
9210 newDate.setSeconds(0);
9211 newDate.setMilliseconds(0);
9213 return this._daylightSavingAdjust(newDate);
9216 /* Handle switch to/from daylight saving.
9217 * Hours may be non-zero on daylight saving cut-over:
9218 * > 12 when midnight changeover, but then cannot generate
9219 * midnight datetime, so jump to 1AM, otherwise reset.
9220 * @param date (Date) the date to check
9221 * @return (Date) the corrected date
9223 _daylightSavingAdjust: function(date) {
9227 date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
9231 /* Set the date(s) directly. */
9232 _setDate: function(inst, date, noChange) {
9234 origMonth = inst.selectedMonth,
9235 origYear = inst.selectedYear,
9236 newDate = this._restrictMinMax(inst, this._determineDate(inst, date, new Date()));
9238 inst.selectedDay = inst.currentDay = newDate.getDate();
9239 inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth();
9240 inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear();
9241 if ((origMonth !== inst.selectedMonth || origYear !== inst.selectedYear) && !noChange) {
9242 this._notifyChange(inst);
9244 this._adjustInstDate(inst);
9246 inst.input.val(clear ? "" : this._formatDate(inst));
9250 /* Retrieve the date(s) directly. */
9251 _getDate: function(inst) {
9252 var startDate = (!inst.currentYear || (inst.input && inst.input.val() === "") ? null :
9253 this._daylightSavingAdjust(new Date(
9254 inst.currentYear, inst.currentMonth, inst.currentDay)));
9258 /* Attach the onxxx handlers. These are declared statically so
9259 * they work with static code transformers like Caja.
9261 _attachHandlers: function(inst) {
9262 var stepMonths = this._get(inst, "stepMonths"),
9263 id = "#" + inst.id.replace( /\\\\/g, "\\" );
9264 inst.dpDiv.find("[data-handler]").map(function () {
9267 $.datepicker._adjustDate(id, -stepMonths, "M");
9270 $.datepicker._adjustDate(id, +stepMonths, "M");
9273 $.datepicker._hideDatepicker();
9275 today: function () {
9276 $.datepicker._gotoToday(id);
9278 selectDay: function () {
9279 $.datepicker._selectDay(id, +this.getAttribute("data-month"), +this.getAttribute("data-year"), this);
9282 selectMonth: function () {
9283 $.datepicker._selectMonthYear(id, this, "M");
9286 selectYear: function () {
9287 $.datepicker._selectMonthYear(id, this, "Y");
9291 $(this).bind(this.getAttribute("data-event"), handler[this.getAttribute("data-handler")]);
9295 /* Generate the HTML for the current state of the date picker. */
9296 _generateHTML: function(inst) {
9297 var maxDraw, prevText, prev, nextText, next, currentText, gotoDate,
9298 controls, buttonPanel, firstDay, showWeek, dayNames, dayNamesMin,
9299 monthNames, monthNamesShort, beforeShowDay, showOtherMonths,
9300 selectOtherMonths, defaultDate, html, dow, row, group, col, selectedDate,
9301 cornerClass, calender, thead, day, daysInMonth, leadDays, curRows, numRows,
9302 printDate, dRow, tbody, daySettings, otherMonth, unselectable,
9303 tempDate = new Date(),
9304 today = this._daylightSavingAdjust(
9305 new Date(tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate())), // clear time
9306 isRTL = this._get(inst, "isRTL"),
9307 showButtonPanel = this._get(inst, "showButtonPanel"),
9308 hideIfNoPrevNext = this._get(inst, "hideIfNoPrevNext"),
9309 navigationAsDateFormat = this._get(inst, "navigationAsDateFormat"),
9310 numMonths = this._getNumberOfMonths(inst),
9311 showCurrentAtPos = this._get(inst, "showCurrentAtPos"),
9312 stepMonths = this._get(inst, "stepMonths"),
9313 isMultiMonth = (numMonths[0] !== 1 || numMonths[1] !== 1),
9314 currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) :
9315 new Date(inst.currentYear, inst.currentMonth, inst.currentDay))),
9316 minDate = this._getMinMaxDate(inst, "min"),
9317 maxDate = this._getMinMaxDate(inst, "max"),
9318 drawMonth = inst.drawMonth - showCurrentAtPos,
9319 drawYear = inst.drawYear;
9321 if (drawMonth < 0) {
9326 maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),
9327 maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate()));
9328 maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);
9329 while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {
9331 if (drawMonth < 0) {
9337 inst.drawMonth = drawMonth;
9338 inst.drawYear = drawYear;
9340 prevText = this._get(inst, "prevText");
9341 prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText,
9342 this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),
9343 this._getFormatConfig(inst)));
9345 prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?
9346 "<a class='ui-datepicker-prev ui-corner-all' data-handler='prev' data-event='click'" +
9347 " title='" + prevText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "e" : "w") + "'>" + prevText + "</span></a>" :
9348 (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>"));
9350 nextText = this._get(inst, "nextText");
9351 nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText,
9352 this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),
9353 this._getFormatConfig(inst)));
9355 next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?
9356 "<a class='ui-datepicker-next ui-corner-all' data-handler='next' data-event='click'" +
9357 " title='" + nextText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "w" : "e") + "'>" + nextText + "</span></a>" :
9358 (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>"));
9360 currentText = this._get(inst, "currentText");
9361 gotoDate = (this._get(inst, "gotoCurrent") && inst.currentDay ? currentDate : today);
9362 currentText = (!navigationAsDateFormat ? currentText :
9363 this.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));
9365 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'>" +
9366 this._get(inst, "closeText") + "</button>" : "");
9368 buttonPanel = (showButtonPanel) ? "<div class='ui-datepicker-buttonpane ui-widget-content'>" + (isRTL ? controls : "") +
9369 (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'" +
9370 ">" + currentText + "</button>" : "") + (isRTL ? "" : controls) + "</div>" : "";
9372 firstDay = parseInt(this._get(inst, "firstDay"),10);
9373 firstDay = (isNaN(firstDay) ? 0 : firstDay);
9375 showWeek = this._get(inst, "showWeek");
9376 dayNames = this._get(inst, "dayNames");
9377 dayNamesMin = this._get(inst, "dayNamesMin");
9378 monthNames = this._get(inst, "monthNames");
9379 monthNamesShort = this._get(inst, "monthNamesShort");
9380 beforeShowDay = this._get(inst, "beforeShowDay");
9381 showOtherMonths = this._get(inst, "showOtherMonths");
9382 selectOtherMonths = this._get(inst, "selectOtherMonths");
9383 defaultDate = this._getDefaultDate(inst);
9386 for (row = 0; row < numMonths[0]; row++) {
9389 for (col = 0; col < numMonths[1]; col++) {
9390 selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay));
9391 cornerClass = " ui-corner-all";
9394 calender += "<div class='ui-datepicker-group";
9395 if (numMonths[1] > 1) {
9397 case 0: calender += " ui-datepicker-group-first";
9398 cornerClass = " ui-corner-" + (isRTL ? "right" : "left"); break;
9399 case numMonths[1]-1: calender += " ui-datepicker-group-last";
9400 cornerClass = " ui-corner-" + (isRTL ? "left" : "right"); break;
9401 default: calender += " ui-datepicker-group-middle"; cornerClass = ""; break;
9406 calender += "<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix" + cornerClass + "'>" +
9407 (/all|left/.test(cornerClass) && row === 0 ? (isRTL ? next : prev) : "") +
9408 (/all|right/.test(cornerClass) && row === 0 ? (isRTL ? prev : next) : "") +
9409 this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,
9410 row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers
9411 "</div><table class='ui-datepicker-calendar'><thead>" +
9413 thead = (showWeek ? "<th class='ui-datepicker-week-col'>" + this._get(inst, "weekHeader") + "</th>" : "");
9414 for (dow = 0; dow < 7; dow++) { // days of the week
9415 day = (dow + firstDay) % 7;
9416 thead += "<th scope='col'" + ((dow + firstDay + 6) % 7 >= 5 ? " class='ui-datepicker-week-end'" : "") + ">" +
9417 "<span title='" + dayNames[day] + "'>" + dayNamesMin[day] + "</span></th>";
9419 calender += thead + "</tr></thead><tbody>";
9420 daysInMonth = this._getDaysInMonth(drawYear, drawMonth);
9421 if (drawYear === inst.selectedYear && drawMonth === inst.selectedMonth) {
9422 inst.selectedDay = Math.min(inst.selectedDay, daysInMonth);
9424 leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;
9425 curRows = Math.ceil((leadDays + daysInMonth) / 7); // calculate the number of rows to generate
9426 numRows = (isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows); //If multiple months, use the higher number of rows (see #7043)
9427 this.maxRows = numRows;
9428 printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
9429 for (dRow = 0; dRow < numRows; dRow++) { // create date picker rows
9431 tbody = (!showWeek ? "" : "<td class='ui-datepicker-week-col'>" +
9432 this._get(inst, "calculateWeek")(printDate) + "</td>");
9433 for (dow = 0; dow < 7; dow++) { // create date picker days
9434 daySettings = (beforeShowDay ?
9435 beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, ""]);
9436 otherMonth = (printDate.getMonth() !== drawMonth);
9437 unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] ||
9438 (minDate && printDate < minDate) || (maxDate && printDate > maxDate);
9439 tbody += "<td class='" +
9440 ((dow + firstDay + 6) % 7 >= 5 ? " ui-datepicker-week-end" : "") + // highlight weekends
9441 (otherMonth ? " ui-datepicker-other-month" : "") + // highlight days from other months
9442 ((printDate.getTime() === selectedDate.getTime() && drawMonth === inst.selectedMonth && inst._keyEvent) || // user pressed key
9443 (defaultDate.getTime() === printDate.getTime() && defaultDate.getTime() === selectedDate.getTime()) ?
9444 // or defaultDate is current printedDate and defaultDate is selectedDate
9445 " " + this._dayOverClass : "") + // highlight selected day
9446 (unselectable ? " " + this._unselectableClass + " ui-state-disabled": "") + // highlight unselectable days
9447 (otherMonth && !showOtherMonths ? "" : " " + daySettings[1] + // highlight custom dates
9448 (printDate.getTime() === currentDate.getTime() ? " " + this._currentClass : "") + // highlight selected day
9449 (printDate.getTime() === today.getTime() ? " ui-datepicker-today" : "")) + "'" + // highlight today (if different)
9450 ((!otherMonth || showOtherMonths) && daySettings[2] ? " title='" + daySettings[2].replace(/'/g, "'") + "'" : "") + // cell title
9451 (unselectable ? "" : " data-handler='selectDay' data-event='click' data-month='" + printDate.getMonth() + "' data-year='" + printDate.getFullYear() + "'") + ">" + // actions
9452 (otherMonth && !showOtherMonths ? " " : // display for other months
9453 (unselectable ? "<span class='ui-state-default'>" + printDate.getDate() + "</span>" : "<a class='ui-state-default" +
9454 (printDate.getTime() === today.getTime() ? " ui-state-highlight" : "") +
9455 (printDate.getTime() === currentDate.getTime() ? " ui-state-active" : "") + // highlight selected day
9456 (otherMonth ? " ui-priority-secondary" : "") + // distinguish dates from other months
9457 "' href='#'>" + printDate.getDate() + "</a>")) + "</td>"; // display selectable date
9458 printDate.setDate(printDate.getDate() + 1);
9459 printDate = this._daylightSavingAdjust(printDate);
9461 calender += tbody + "</tr>";
9464 if (drawMonth > 11) {
9468 calender += "</tbody></table>" + (isMultiMonth ? "</div>" +
9469 ((numMonths[0] > 0 && col === numMonths[1]-1) ? "<div class='ui-datepicker-row-break'></div>" : "") : "");
9474 html += buttonPanel;
9475 inst._keyEvent = false;
9479 /* Generate the month and year header. */
9480 _generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate,
9481 secondary, monthNames, monthNamesShort) {
9483 var inMinYear, inMaxYear, month, years, thisYear, determineYear, year, endYear,
9484 changeMonth = this._get(inst, "changeMonth"),
9485 changeYear = this._get(inst, "changeYear"),
9486 showMonthAfterYear = this._get(inst, "showMonthAfterYear"),
9487 html = "<div class='ui-datepicker-title'>",
9491 if (secondary || !changeMonth) {
9492 monthHtml += "<span class='ui-datepicker-month'>" + monthNames[drawMonth] + "</span>";
9494 inMinYear = (minDate && minDate.getFullYear() === drawYear);
9495 inMaxYear = (maxDate && maxDate.getFullYear() === drawYear);
9496 monthHtml += "<select class='ui-datepicker-month' data-handler='selectMonth' data-event='change'>";
9497 for ( month = 0; month < 12; month++) {
9498 if ((!inMinYear || month >= minDate.getMonth()) && (!inMaxYear || month <= maxDate.getMonth())) {
9499 monthHtml += "<option value='" + month + "'" +
9500 (month === drawMonth ? " selected='selected'" : "") +
9501 ">" + monthNamesShort[month] + "</option>";
9504 monthHtml += "</select>";
9507 if (!showMonthAfterYear) {
9508 html += monthHtml + (secondary || !(changeMonth && changeYear) ? " " : "");
9512 if ( !inst.yearshtml ) {
9513 inst.yearshtml = "";
9514 if (secondary || !changeYear) {
9515 html += "<span class='ui-datepicker-year'>" + drawYear + "</span>";
9517 // determine range of years to display
9518 years = this._get(inst, "yearRange").split(":");
9519 thisYear = new Date().getFullYear();
9520 determineYear = function(value) {
9521 var year = (value.match(/c[+\-].*/) ? drawYear + parseInt(value.substring(1), 10) :
9522 (value.match(/[+\-].*/) ? thisYear + parseInt(value, 10) :
9523 parseInt(value, 10)));
9524 return (isNaN(year) ? thisYear : year);
9526 year = determineYear(years[0]);
9527 endYear = Math.max(year, determineYear(years[1] || ""));
9528 year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
9529 endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
9530 inst.yearshtml += "<select class='ui-datepicker-year' data-handler='selectYear' data-event='change'>";
9531 for (; year <= endYear; year++) {
9532 inst.yearshtml += "<option value='" + year + "'" +
9533 (year === drawYear ? " selected='selected'" : "") +
9534 ">" + year + "</option>";
9536 inst.yearshtml += "</select>";
9538 html += inst.yearshtml;
9539 inst.yearshtml = null;
9543 html += this._get(inst, "yearSuffix");
9544 if (showMonthAfterYear) {
9545 html += (secondary || !(changeMonth && changeYear) ? " " : "") + monthHtml;
9547 html += "</div>"; // Close datepicker_header
9551 /* Adjust one of the date sub-fields. */
9552 _adjustInstDate: function(inst, offset, period) {
9553 var year = inst.drawYear + (period === "Y" ? offset : 0),
9554 month = inst.drawMonth + (period === "M" ? offset : 0),
9555 day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) + (period === "D" ? offset : 0),
9556 date = this._restrictMinMax(inst, this._daylightSavingAdjust(new Date(year, month, day)));
9558 inst.selectedDay = date.getDate();
9559 inst.drawMonth = inst.selectedMonth = date.getMonth();
9560 inst.drawYear = inst.selectedYear = date.getFullYear();
9561 if (period === "M" || period === "Y") {
9562 this._notifyChange(inst);
9566 /* Ensure a date is within any min/max bounds. */
9567 _restrictMinMax: function(inst, date) {
9568 var minDate = this._getMinMaxDate(inst, "min"),
9569 maxDate = this._getMinMaxDate(inst, "max"),
9570 newDate = (minDate && date < minDate ? minDate : date);
9571 return (maxDate && newDate > maxDate ? maxDate : newDate);
9574 /* Notify change of month/year. */
9575 _notifyChange: function(inst) {
9576 var onChange = this._get(inst, "onChangeMonthYear");
9578 onChange.apply((inst.input ? inst.input[0] : null),
9579 [inst.selectedYear, inst.selectedMonth + 1, inst]);
9583 /* Determine the number of months to show. */
9584 _getNumberOfMonths: function(inst) {
9585 var numMonths = this._get(inst, "numberOfMonths");
9586 return (numMonths == null ? [1, 1] : (typeof numMonths === "number" ? [1, numMonths] : numMonths));
9589 /* Determine the current maximum date - ensure no time components are set. */
9590 _getMinMaxDate: function(inst, minMax) {
9591 return this._determineDate(inst, this._get(inst, minMax + "Date"), null);
9594 /* Find the number of days in a given month. */
9595 _getDaysInMonth: function(year, month) {
9596 return 32 - this._daylightSavingAdjust(new Date(year, month, 32)).getDate();
9599 /* Find the day of the week of the first of a month. */
9600 _getFirstDayOfMonth: function(year, month) {
9601 return new Date(year, month, 1).getDay();
9604 /* Determines if we should allow a "next/prev" month display change. */
9605 _canAdjustMonth: function(inst, offset, curYear, curMonth) {
9606 var numMonths = this._getNumberOfMonths(inst),
9607 date = this._daylightSavingAdjust(new Date(curYear,
9608 curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1));
9611 date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
9613 return this._isInRange(inst, date);
9616 /* Is the given date in the accepted range? */
9617 _isInRange: function(inst, date) {
9618 var yearSplit, currentYear,
9619 minDate = this._getMinMaxDate(inst, "min"),
9620 maxDate = this._getMinMaxDate(inst, "max"),
9623 years = this._get(inst, "yearRange");
9625 yearSplit = years.split(":");
9626 currentYear = new Date().getFullYear();
9627 minYear = parseInt(yearSplit[0], 10);
9628 maxYear = parseInt(yearSplit[1], 10);
9629 if ( yearSplit[0].match(/[+\-].*/) ) {
9630 minYear += currentYear;
9632 if ( yearSplit[1].match(/[+\-].*/) ) {
9633 maxYear += currentYear;
9637 return ((!minDate || date.getTime() >= minDate.getTime()) &&
9638 (!maxDate || date.getTime() <= maxDate.getTime()) &&
9639 (!minYear || date.getFullYear() >= minYear) &&
9640 (!maxYear || date.getFullYear() <= maxYear));
9643 /* Provide the configuration settings for formatting/parsing. */
9644 _getFormatConfig: function(inst) {
9645 var shortYearCutoff = this._get(inst, "shortYearCutoff");
9646 shortYearCutoff = (typeof shortYearCutoff !== "string" ? shortYearCutoff :
9647 new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
9648 return {shortYearCutoff: shortYearCutoff,
9649 dayNamesShort: this._get(inst, "dayNamesShort"), dayNames: this._get(inst, "dayNames"),
9650 monthNamesShort: this._get(inst, "monthNamesShort"), monthNames: this._get(inst, "monthNames")};
9653 /* Format the given date for display. */
9654 _formatDate: function(inst, day, month, year) {
9656 inst.currentDay = inst.selectedDay;
9657 inst.currentMonth = inst.selectedMonth;
9658 inst.currentYear = inst.selectedYear;
9660 var date = (day ? (typeof day === "object" ? day :
9661 this._daylightSavingAdjust(new Date(year, month, day))) :
9662 this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
9663 return this.formatDate(this._get(inst, "dateFormat"), date, this._getFormatConfig(inst));
9668 * Bind hover events for datepicker elements.
9669 * Done via delegate so the binding only occurs once in the lifetime of the parent div.
9670 * Global datepicker_instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker.
9672 function datepicker_bindHover(dpDiv) {
9673 var selector = "button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";
9674 return dpDiv.delegate(selector, "mouseout", function() {
9675 $(this).removeClass("ui-state-hover");
9676 if (this.className.indexOf("ui-datepicker-prev") !== -1) {
9677 $(this).removeClass("ui-datepicker-prev-hover");
9679 if (this.className.indexOf("ui-datepicker-next") !== -1) {
9680 $(this).removeClass("ui-datepicker-next-hover");
9683 .delegate(selector, "mouseover", function(){
9684 if (!$.datepicker._isDisabledDatepicker( datepicker_instActive.inline ? dpDiv.parent()[0] : datepicker_instActive.input[0])) {
9685 $(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover");
9686 $(this).addClass("ui-state-hover");
9687 if (this.className.indexOf("ui-datepicker-prev") !== -1) {
9688 $(this).addClass("ui-datepicker-prev-hover");
9690 if (this.className.indexOf("ui-datepicker-next") !== -1) {
9691 $(this).addClass("ui-datepicker-next-hover");
9697 /* jQuery extend now ignores nulls! */
9698 function datepicker_extendRemove(target, props) {
9699 $.extend(target, props);
9700 for (var name in props) {
9701 if (props[name] == null) {
9702 target[name] = props[name];
9708 /* Invoke the datepicker functionality.
9709 @param options string - a command, optionally followed by additional parameters or
9710 Object - settings for attaching new datepicker functionality
9711 @return jQuery object */
9712 $.fn.datepicker = function(options){
9714 /* Verify an empty collection wasn't passed - Fixes #6976 */
9715 if ( !this.length ) {
9719 /* Initialise the date picker. */
9720 if (!$.datepicker.initialized) {
9721 $(document).mousedown($.datepicker._checkExternalClick);
9722 $.datepicker.initialized = true;
9725 /* Append datepicker main container to body if not exist. */
9726 if ($("#"+$.datepicker._mainDivId).length === 0) {
9727 $("body").append($.datepicker.dpDiv);
9730 var otherArgs = Array.prototype.slice.call(arguments, 1);
9731 if (typeof options === "string" && (options === "isDisabled" || options === "getDate" || options === "widget")) {
9732 return $.datepicker["_" + options + "Datepicker"].
9733 apply($.datepicker, [this[0]].concat(otherArgs));
9735 if (options === "option" && arguments.length === 2 && typeof arguments[1] === "string") {
9736 return $.datepicker["_" + options + "Datepicker"].
9737 apply($.datepicker, [this[0]].concat(otherArgs));
9739 return this.each(function() {
9740 typeof options === "string" ?
9741 $.datepicker["_" + options + "Datepicker"].
9742 apply($.datepicker, [this].concat(otherArgs)) :
9743 $.datepicker._attachDatepicker(this, options);
9747 $.datepicker = new Datepicker(); // singleton instance
9748 $.datepicker.initialized = false;
9749 $.datepicker.uuid = new Date().getTime();
9750 $.datepicker.version = "1.11.0";
9752 var datepicker = $.datepicker;
9756 * jQuery UI Dialog 1.11.0
9757 * http://jqueryui.com
9759 * Copyright 2014 jQuery Foundation and other contributors
9760 * Released under the MIT license.
9761 * http://jquery.org/license
9763 * http://api.jqueryui.com/dialog/
9767 var dialog = $.widget( "ui.dialog", {
9773 closeOnEscape: true,
9789 // Ensure the titlebar is always visible
9790 using: function( pos ) {
9791 var topOffset = $( this ).css( pos ).offset().top;
9792 if ( topOffset < 0 ) {
9793 $( this ).css( "top", pos.top - topOffset );
9815 sizeRelatedOptions: {
9825 resizableRelatedOptions: {
9832 _create: function() {
9833 this.originalCss = {
9834 display: this.element[ 0 ].style.display,
9835 width: this.element[ 0 ].style.width,
9836 minHeight: this.element[ 0 ].style.minHeight,
9837 maxHeight: this.element[ 0 ].style.maxHeight,
9838 height: this.element[ 0 ].style.height
9840 this.originalPosition = {
9841 parent: this.element.parent(),
9842 index: this.element.parent().children().index( this.element )
9844 this.originalTitle = this.element.attr( "title" );
9845 this.options.title = this.options.title || this.originalTitle;
9847 this._createWrapper();
9851 .removeAttr( "title" )
9852 .addClass( "ui-dialog-content ui-widget-content" )
9853 .appendTo( this.uiDialog );
9855 this._createTitlebar();
9856 this._createButtonPane();
9858 if ( this.options.draggable && $.fn.draggable ) {
9859 this._makeDraggable();
9861 if ( this.options.resizable && $.fn.resizable ) {
9862 this._makeResizable();
9865 this._isOpen = false;
9871 if ( this.options.autoOpen ) {
9876 _appendTo: function() {
9877 var element = this.options.appendTo;
9878 if ( element && (element.jquery || element.nodeType) ) {
9879 return $( element );
9881 return this.document.find( element || "body" ).eq( 0 );
9884 _destroy: function() {
9886 originalPosition = this.originalPosition;
9888 this._destroyOverlay();
9892 .removeClass( "ui-dialog-content ui-widget-content" )
9893 .css( this.originalCss )
9894 // Without detaching first, the following becomes really slow
9897 this.uiDialog.stop( true, true ).remove();
9899 if ( this.originalTitle ) {
9900 this.element.attr( "title", this.originalTitle );
9903 next = originalPosition.parent.children().eq( originalPosition.index );
9904 // Don't try to place the dialog next to itself (#8613)
9905 if ( next.length && next[ 0 ] !== this.element[ 0 ] ) {
9906 next.before( this.element );
9908 originalPosition.parent.append( this.element );
9912 widget: function() {
9913 return this.uiDialog;
9919 close: function( event ) {
9923 if ( !this._isOpen || this._trigger( "beforeClose", event ) === false ) {
9927 this._isOpen = false;
9928 this._focusedElement = null;
9929 this._destroyOverlay();
9930 this._untrackInstance();
9932 if ( !this.opener.filter( ":focusable" ).focus().length ) {
9935 // IE9 throws an "Unspecified error" accessing document.activeElement from an <iframe>
9937 activeElement = this.document[ 0 ].activeElement;
9939 // Support: IE9, IE10
9940 // If the <body> is blurred, IE will switch windows, see #4520
9941 if ( activeElement && activeElement.nodeName.toLowerCase() !== "body" ) {
9943 // Hiding a focused element doesn't trigger blur in WebKit
9944 // so in case we have nothing to focus on, explicitly blur the active element
9945 // https://bugs.webkit.org/show_bug.cgi?id=47182
9946 $( activeElement ).blur();
9948 } catch ( error ) {}
9951 this._hide( this.uiDialog, this.options.hide, function() {
9952 that._trigger( "close", event );
9956 isOpen: function() {
9957 return this._isOpen;
9960 moveToTop: function() {
9964 _moveToTop: function( event, silent ) {
9966 zIndicies = this.uiDialog.siblings( ".ui-front:visible" ).map(function() {
9967 return +$( this ).css( "z-index" );
9969 zIndexMax = Math.max.apply( null, zIndicies );
9971 if ( zIndexMax >= +this.uiDialog.css( "z-index" ) ) {
9972 this.uiDialog.css( "z-index", zIndexMax + 1 );
9976 if ( moved && !silent ) {
9977 this._trigger( "focus", event );
9984 if ( this._isOpen ) {
9985 if ( this._moveToTop() ) {
9986 this._focusTabbable();
9991 this._isOpen = true;
9992 this.opener = $( this.document[ 0 ].activeElement );
9996 this._createOverlay();
9997 this._moveToTop( null, true );
9998 this._show( this.uiDialog, this.options.show, function() {
9999 that._focusTabbable();
10000 that._trigger( "focus" );
10003 this._trigger( "open" );
10006 _focusTabbable: function() {
10007 // Set focus to the first match:
10008 // 1. An element that was focused previously
10009 // 2. First element inside the dialog matching [autofocus]
10010 // 3. Tabbable element inside the content element
10011 // 4. Tabbable element inside the buttonpane
10012 // 5. The close button
10013 // 6. The dialog itself
10014 var hasFocus = this._focusedElement;
10016 hasFocus = this.element.find( "[autofocus]" );
10018 if ( !hasFocus.length ) {
10019 hasFocus = this.element.find( ":tabbable" );
10021 if ( !hasFocus.length ) {
10022 hasFocus = this.uiDialogButtonPane.find( ":tabbable" );
10024 if ( !hasFocus.length ) {
10025 hasFocus = this.uiDialogTitlebarClose.filter( ":tabbable" );
10027 if ( !hasFocus.length ) {
10028 hasFocus = this.uiDialog;
10030 hasFocus.eq( 0 ).focus();
10033 _keepFocus: function( event ) {
10034 function checkFocus() {
10035 var activeElement = this.document[0].activeElement,
10036 isActive = this.uiDialog[0] === activeElement ||
10037 $.contains( this.uiDialog[0], activeElement );
10039 this._focusTabbable();
10042 event.preventDefault();
10043 checkFocus.call( this );
10045 // IE <= 8 doesn't prevent moving focus even with event.preventDefault()
10046 // so we check again later
10047 this._delay( checkFocus );
10050 _createWrapper: function() {
10051 this.uiDialog = $("<div>")
10052 .addClass( "ui-dialog ui-widget ui-widget-content ui-corner-all ui-front " +
10053 this.options.dialogClass )
10056 // Setting tabIndex makes the div focusable
10060 .appendTo( this._appendTo() );
10062 this._on( this.uiDialog, {
10063 keydown: function( event ) {
10064 if ( this.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode &&
10065 event.keyCode === $.ui.keyCode.ESCAPE ) {
10066 event.preventDefault();
10067 this.close( event );
10071 // prevent tabbing out of dialogs
10072 if ( event.keyCode !== $.ui.keyCode.TAB || event.isDefaultPrevented() ) {
10075 var tabbables = this.uiDialog.find( ":tabbable" ),
10076 first = tabbables.filter( ":first" ),
10077 last = tabbables.filter( ":last" );
10079 if ( ( event.target === last[0] || event.target === this.uiDialog[0] ) && !event.shiftKey ) {
10080 this._delay(function() {
10083 event.preventDefault();
10084 } else if ( ( event.target === first[0] || event.target === this.uiDialog[0] ) && event.shiftKey ) {
10085 this._delay(function() {
10088 event.preventDefault();
10091 mousedown: function( event ) {
10092 if ( this._moveToTop( event ) ) {
10093 this._focusTabbable();
10098 // We assume that any existing aria-describedby attribute means
10099 // that the dialog content is marked up properly
10100 // otherwise we brute force the content as the description
10101 if ( !this.element.find( "[aria-describedby]" ).length ) {
10102 this.uiDialog.attr({
10103 "aria-describedby": this.element.uniqueId().attr( "id" )
10108 _createTitlebar: function() {
10111 this.uiDialogTitlebar = $( "<div>" )
10112 .addClass( "ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix" )
10113 .prependTo( this.uiDialog );
10114 this._on( this.uiDialogTitlebar, {
10115 mousedown: function( event ) {
10116 // Don't prevent click on close button (#8838)
10117 // Focusing a dialog that is partially scrolled out of view
10118 // causes the browser to scroll it into view, preventing the click event
10119 if ( !$( event.target ).closest( ".ui-dialog-titlebar-close" ) ) {
10120 // Dialog isn't getting focus when dragging (#8063)
10121 this.uiDialog.focus();
10127 // Use type="button" to prevent enter keypresses in textboxes from closing the
10128 // dialog in IE (#9312)
10129 this.uiDialogTitlebarClose = $( "<button type='button'></button>" )
10131 label: this.options.closeText,
10133 primary: "ui-icon-closethick"
10137 .addClass( "ui-dialog-titlebar-close" )
10138 .appendTo( this.uiDialogTitlebar );
10139 this._on( this.uiDialogTitlebarClose, {
10140 click: function( event ) {
10141 event.preventDefault();
10142 this.close( event );
10146 uiDialogTitle = $( "<span>" )
10148 .addClass( "ui-dialog-title" )
10149 .prependTo( this.uiDialogTitlebar );
10150 this._title( uiDialogTitle );
10152 this.uiDialog.attr({
10153 "aria-labelledby": uiDialogTitle.attr( "id" )
10157 _title: function( title ) {
10158 if ( !this.options.title ) {
10159 title.html( " " );
10161 title.text( this.options.title );
10164 _createButtonPane: function() {
10165 this.uiDialogButtonPane = $( "<div>" )
10166 .addClass( "ui-dialog-buttonpane ui-widget-content ui-helper-clearfix" );
10168 this.uiButtonSet = $( "<div>" )
10169 .addClass( "ui-dialog-buttonset" )
10170 .appendTo( this.uiDialogButtonPane );
10172 this._createButtons();
10175 _createButtons: function() {
10177 buttons = this.options.buttons;
10179 // if we already have a button pane, remove it
10180 this.uiDialogButtonPane.remove();
10181 this.uiButtonSet.empty();
10183 if ( $.isEmptyObject( buttons ) || ($.isArray( buttons ) && !buttons.length) ) {
10184 this.uiDialog.removeClass( "ui-dialog-buttons" );
10188 $.each( buttons, function( name, props ) {
10189 var click, buttonOptions;
10190 props = $.isFunction( props ) ?
10191 { click: props, text: name } :
10193 // Default to a non-submitting button
10194 props = $.extend( { type: "button" }, props );
10195 // Change the context for the click callback to be the main element
10196 click = props.click;
10197 props.click = function() {
10198 click.apply( that.element[ 0 ], arguments );
10201 icons: props.icons,
10202 text: props.showText
10204 delete props.icons;
10205 delete props.showText;
10206 $( "<button></button>", props )
10207 .button( buttonOptions )
10208 .appendTo( that.uiButtonSet );
10210 this.uiDialog.addClass( "ui-dialog-buttons" );
10211 this.uiDialogButtonPane.appendTo( this.uiDialog );
10214 _makeDraggable: function() {
10216 options = this.options;
10218 function filteredUi( ui ) {
10220 position: ui.position,
10225 this.uiDialog.draggable({
10226 cancel: ".ui-dialog-content, .ui-dialog-titlebar-close",
10227 handle: ".ui-dialog-titlebar",
10228 containment: "document",
10229 start: function( event, ui ) {
10230 $( this ).addClass( "ui-dialog-dragging" );
10231 that._blockFrames();
10232 that._trigger( "dragStart", event, filteredUi( ui ) );
10234 drag: function( event, ui ) {
10235 that._trigger( "drag", event, filteredUi( ui ) );
10237 stop: function( event, ui ) {
10238 var left = ui.offset.left - that.document.scrollLeft(),
10239 top = ui.offset.top - that.document.scrollTop();
10241 options.position = {
10243 at: "left" + (left >= 0 ? "+" : "") + left + " " +
10244 "top" + (top >= 0 ? "+" : "") + top,
10247 $( this ).removeClass( "ui-dialog-dragging" );
10248 that._unblockFrames();
10249 that._trigger( "dragStop", event, filteredUi( ui ) );
10254 _makeResizable: function() {
10256 options = this.options,
10257 handles = options.resizable,
10258 // .ui-resizable has position: relative defined in the stylesheet
10259 // but dialogs have to use absolute or fixed positioning
10260 position = this.uiDialog.css("position"),
10261 resizeHandles = typeof handles === "string" ?
10263 "n,e,s,w,se,sw,ne,nw";
10265 function filteredUi( ui ) {
10267 originalPosition: ui.originalPosition,
10268 originalSize: ui.originalSize,
10269 position: ui.position,
10274 this.uiDialog.resizable({
10275 cancel: ".ui-dialog-content",
10276 containment: "document",
10277 alsoResize: this.element,
10278 maxWidth: options.maxWidth,
10279 maxHeight: options.maxHeight,
10280 minWidth: options.minWidth,
10281 minHeight: this._minHeight(),
10282 handles: resizeHandles,
10283 start: function( event, ui ) {
10284 $( this ).addClass( "ui-dialog-resizing" );
10285 that._blockFrames();
10286 that._trigger( "resizeStart", event, filteredUi( ui ) );
10288 resize: function( event, ui ) {
10289 that._trigger( "resize", event, filteredUi( ui ) );
10291 stop: function( event, ui ) {
10292 var offset = that.uiDialog.offset(),
10293 left = offset.left - that.document.scrollLeft(),
10294 top = offset.top - that.document.scrollTop();
10296 options.height = that.uiDialog.height();
10297 options.width = that.uiDialog.width();
10298 options.position = {
10300 at: "left" + (left >= 0 ? "+" : "") + left + " " +
10301 "top" + (top >= 0 ? "+" : "") + top,
10304 $( this ).removeClass( "ui-dialog-resizing" );
10305 that._unblockFrames();
10306 that._trigger( "resizeStop", event, filteredUi( ui ) );
10309 .css( "position", position );
10312 _trackFocus: function() {
10313 this._on( this.widget(), {
10314 "focusin": function( event ) {
10315 this._untrackInstance();
10316 this._trackingInstances().unshift( this );
10317 this._focusedElement = $( event.target );
10322 _untrackInstance: function() {
10323 var instances = this._trackingInstances(),
10324 exists = $.inArray( this, instances );
10325 if ( exists !== -1 ) {
10326 instances.splice( exists, 1 );
10330 _trackingInstances: function() {
10331 var instances = this.document.data( "ui-dialog-instances" );
10332 if ( !instances ) {
10334 this.document.data( "ui-dialog-instances", instances );
10339 _minHeight: function() {
10340 var options = this.options;
10342 return options.height === "auto" ?
10343 options.minHeight :
10344 Math.min( options.minHeight, options.height );
10347 _position: function() {
10348 // Need to show the dialog to get the actual offset in the position plugin
10349 var isVisible = this.uiDialog.is( ":visible" );
10350 if ( !isVisible ) {
10351 this.uiDialog.show();
10353 this.uiDialog.position( this.options.position );
10354 if ( !isVisible ) {
10355 this.uiDialog.hide();
10359 _setOptions: function( options ) {
10362 resizableOptions = {};
10364 $.each( options, function( key, value ) {
10365 that._setOption( key, value );
10367 if ( key in that.sizeRelatedOptions ) {
10370 if ( key in that.resizableRelatedOptions ) {
10371 resizableOptions[ key ] = value;
10379 if ( this.uiDialog.is( ":data(ui-resizable)" ) ) {
10380 this.uiDialog.resizable( "option", resizableOptions );
10384 _setOption: function( key, value ) {
10385 var isDraggable, isResizable,
10386 uiDialog = this.uiDialog;
10388 if ( key === "dialogClass" ) {
10390 .removeClass( this.options.dialogClass )
10391 .addClass( value );
10394 if ( key === "disabled" ) {
10398 this._super( key, value );
10400 if ( key === "appendTo" ) {
10401 this.uiDialog.appendTo( this._appendTo() );
10404 if ( key === "buttons" ) {
10405 this._createButtons();
10408 if ( key === "closeText" ) {
10409 this.uiDialogTitlebarClose.button({
10410 // Ensure that we always pass a string
10415 if ( key === "draggable" ) {
10416 isDraggable = uiDialog.is( ":data(ui-draggable)" );
10417 if ( isDraggable && !value ) {
10418 uiDialog.draggable( "destroy" );
10421 if ( !isDraggable && value ) {
10422 this._makeDraggable();
10426 if ( key === "position" ) {
10430 if ( key === "resizable" ) {
10431 // currently resizable, becoming non-resizable
10432 isResizable = uiDialog.is( ":data(ui-resizable)" );
10433 if ( isResizable && !value ) {
10434 uiDialog.resizable( "destroy" );
10437 // currently resizable, changing handles
10438 if ( isResizable && typeof value === "string" ) {
10439 uiDialog.resizable( "option", "handles", value );
10442 // currently non-resizable, becoming resizable
10443 if ( !isResizable && value !== false ) {
10444 this._makeResizable();
10448 if ( key === "title" ) {
10449 this._title( this.uiDialogTitlebar.find( ".ui-dialog-title" ) );
10453 _size: function() {
10454 // If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
10455 // divs will both have width and height set, so we need to reset them
10456 var nonContentHeight, minContentHeight, maxContentHeight,
10457 options = this.options;
10459 // Reset content sizing
10460 this.element.show().css({
10467 if ( options.minWidth > options.width ) {
10468 options.width = options.minWidth;
10471 // reset wrapper sizing
10472 // determine the height of all the non-content elements
10473 nonContentHeight = this.uiDialog.css({
10475 width: options.width
10478 minContentHeight = Math.max( 0, options.minHeight - nonContentHeight );
10479 maxContentHeight = typeof options.maxHeight === "number" ?
10480 Math.max( 0, options.maxHeight - nonContentHeight ) :
10483 if ( options.height === "auto" ) {
10485 minHeight: minContentHeight,
10486 maxHeight: maxContentHeight,
10490 this.element.height( Math.max( 0, options.height - nonContentHeight ) );
10493 if ( this.uiDialog.is( ":data(ui-resizable)" ) ) {
10494 this.uiDialog.resizable( "option", "minHeight", this._minHeight() );
10498 _blockFrames: function() {
10499 this.iframeBlocks = this.document.find( "iframe" ).map(function() {
10500 var iframe = $( this );
10502 return $( "<div>" )
10504 position: "absolute",
10505 width: iframe.outerWidth(),
10506 height: iframe.outerHeight()
10508 .appendTo( iframe.parent() )
10509 .offset( iframe.offset() )[0];
10513 _unblockFrames: function() {
10514 if ( this.iframeBlocks ) {
10515 this.iframeBlocks.remove();
10516 delete this.iframeBlocks;
10520 _allowInteraction: function( event ) {
10521 if ( $( event.target ).closest( ".ui-dialog" ).length ) {
10525 // TODO: Remove hack when datepicker implements
10526 // the .ui-front logic (#8989)
10527 return !!$( event.target ).closest( ".ui-datepicker" ).length;
10530 _createOverlay: function() {
10531 if ( !this.options.modal ) {
10535 // We use a delay in case the overlay is created from an
10536 // event that we're going to be cancelling (#2804)
10537 var isOpening = true;
10538 this._delay(function() {
10542 if ( !this.document.data( "ui-dialog-overlays" ) ) {
10544 // Prevent use of anchors and inputs
10545 // Using _on() for an event handler shared across many instances is
10546 // safe because the dialogs stack and must be closed in reverse order
10547 this._on( this.document, {
10548 focusin: function( event ) {
10553 if ( !this._allowInteraction( event ) ) {
10554 event.preventDefault();
10555 this._trackingInstances()[ 0 ]._focusTabbable();
10561 this.overlay = $( "<div>" )
10562 .addClass( "ui-widget-overlay ui-front" )
10563 .appendTo( this._appendTo() );
10564 this._on( this.overlay, {
10565 mousedown: "_keepFocus"
10567 this.document.data( "ui-dialog-overlays",
10568 (this.document.data( "ui-dialog-overlays" ) || 0) + 1 );
10571 _destroyOverlay: function() {
10572 if ( !this.options.modal ) {
10576 if ( this.overlay ) {
10577 var overlays = this.document.data( "ui-dialog-overlays" ) - 1;
10581 .unbind( "focusin" )
10582 .removeData( "ui-dialog-overlays" );
10584 this.document.data( "ui-dialog-overlays", overlays );
10587 this.overlay.remove();
10588 this.overlay = null;
10595 * jQuery UI Progressbar 1.11.0
10596 * http://jqueryui.com
10598 * Copyright 2014 jQuery Foundation and other contributors
10599 * Released under the MIT license.
10600 * http://jquery.org/license
10602 * http://api.jqueryui.com/progressbar/
10606 var progressbar = $.widget( "ui.progressbar", {
10618 _create: function() {
10619 // Constrain initial value
10620 this.oldValue = this.options.value = this._constrainedValue();
10623 .addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
10625 // Only set static values, aria-valuenow and aria-valuemax are
10626 // set inside _refreshValue()
10627 role: "progressbar",
10628 "aria-valuemin": this.min
10631 this.valueDiv = $( "<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>" )
10632 .appendTo( this.element );
10634 this._refreshValue();
10637 _destroy: function() {
10639 .removeClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
10640 .removeAttr( "role" )
10641 .removeAttr( "aria-valuemin" )
10642 .removeAttr( "aria-valuemax" )
10643 .removeAttr( "aria-valuenow" );
10645 this.valueDiv.remove();
10648 value: function( newValue ) {
10649 if ( newValue === undefined ) {
10650 return this.options.value;
10653 this.options.value = this._constrainedValue( newValue );
10654 this._refreshValue();
10657 _constrainedValue: function( newValue ) {
10658 if ( newValue === undefined ) {
10659 newValue = this.options.value;
10662 this.indeterminate = newValue === false;
10665 if ( typeof newValue !== "number" ) {
10669 return this.indeterminate ? false :
10670 Math.min( this.options.max, Math.max( this.min, newValue ) );
10673 _setOptions: function( options ) {
10674 // Ensure "value" option is set after other values (like max)
10675 var value = options.value;
10676 delete options.value;
10678 this._super( options );
10680 this.options.value = this._constrainedValue( value );
10681 this._refreshValue();
10684 _setOption: function( key, value ) {
10685 if ( key === "max" ) {
10686 // Don't allow a max less than min
10687 value = Math.max( this.min, value );
10689 if ( key === "disabled" ) {
10691 .toggleClass( "ui-state-disabled", !!value )
10692 .attr( "aria-disabled", value );
10694 this._super( key, value );
10697 _percentage: function() {
10698 return this.indeterminate ? 100 : 100 * ( this.options.value - this.min ) / ( this.options.max - this.min );
10701 _refreshValue: function() {
10702 var value = this.options.value,
10703 percentage = this._percentage();
10706 .toggle( this.indeterminate || value > this.min )
10707 .toggleClass( "ui-corner-right", value === this.options.max )
10708 .width( percentage.toFixed(0) + "%" );
10710 this.element.toggleClass( "ui-progressbar-indeterminate", this.indeterminate );
10712 if ( this.indeterminate ) {
10713 this.element.removeAttr( "aria-valuenow" );
10714 if ( !this.overlayDiv ) {
10715 this.overlayDiv = $( "<div class='ui-progressbar-overlay'></div>" ).appendTo( this.valueDiv );
10718 this.element.attr({
10719 "aria-valuemax": this.options.max,
10720 "aria-valuenow": value
10722 if ( this.overlayDiv ) {
10723 this.overlayDiv.remove();
10724 this.overlayDiv = null;
10728 if ( this.oldValue !== value ) {
10729 this.oldValue = value;
10730 this._trigger( "change" );
10732 if ( value === this.options.max ) {
10733 this._trigger( "complete" );
10740 * jQuery UI Selectmenu 1.11.0
10741 * http://jqueryui.com
10743 * Copyright 2014 jQuery Foundation and other contributors
10744 * Released under the MIT license.
10745 * http://jquery.org/license
10747 * http://api.jqueryui.com/selectmenu
10751 var selectmenu = $.widget( "ui.selectmenu", {
10753 defaultElement: "<select>",
10758 button: "ui-icon-triangle-1-s"
10775 _create: function() {
10776 var selectmenuId = this.element.uniqueId().attr( "id" );
10778 element: selectmenuId,
10779 button: selectmenuId + "-button",
10780 menu: selectmenuId + "-menu"
10783 this._drawButton();
10786 if ( this.options.disabled ) {
10791 _drawButton: function() {
10793 tabindex = this.element.attr( "tabindex" );
10795 // Associate existing label with the new button
10796 this.label = $( "label[for='" + this.ids.element + "']" ).attr( "for", this.ids.button );
10797 this._on( this.label, {
10798 click: function( event ) {
10799 this.button.focus();
10800 event.preventDefault();
10804 // Hide original select element
10805 this.element.hide();
10808 this.button = $( "<span>", {
10809 "class": "ui-selectmenu-button ui-widget ui-state-default ui-corner-all",
10810 tabindex: tabindex || this.options.disabled ? -1 : 0,
10811 id: this.ids.button,
10813 "aria-expanded": "false",
10814 "aria-autocomplete": "list",
10815 "aria-owns": this.ids.menu,
10816 "aria-haspopup": "true"
10818 .insertAfter( this.element );
10821 "class": "ui-icon " + this.options.icons.button
10823 .prependTo( this.button );
10825 this.buttonText = $( "<span>", {
10826 "class": "ui-selectmenu-text"
10828 .appendTo( this.button );
10830 this._setText( this.buttonText, this.element.find( "option:selected" ).text() );
10831 this._setOption( "width", this.options.width );
10833 this._on( this.button, this._buttonEvents );
10834 this.button.one( "focusin", function() {
10836 // Delay rendering the menu items until the button receives focus.
10837 // The menu may have already been rendered via a programmatic open.
10838 if ( !that.menuItems ) {
10839 that._refreshMenu();
10842 this._hoverable( this.button );
10843 this._focusable( this.button );
10846 _drawMenu: function() {
10850 this.menu = $( "<ul>", {
10851 "aria-hidden": "true",
10852 "aria-labelledby": this.ids.button,
10857 this.menuWrap = $( "<div>", {
10858 "class": "ui-selectmenu-menu ui-front"
10860 .append( this.menu )
10861 .appendTo( this._appendTo() );
10863 // Initialize menu widget
10864 this.menuInstance = this.menu
10867 select: function( event, ui ) {
10868 event.preventDefault();
10869 that._select( ui.item.data( "ui-selectmenu-item" ), event );
10871 focus: function( event, ui ) {
10872 var item = ui.item.data( "ui-selectmenu-item" );
10874 // Prevent inital focus from firing and check if its a newly focused item
10875 if ( that.focusIndex != null && item.index !== that.focusIndex ) {
10876 that._trigger( "focus", event, { item: item } );
10877 if ( !that.isOpen ) {
10878 that._select( item, event );
10881 that.focusIndex = item.index;
10883 that.button.attr( "aria-activedescendant",
10884 that.menuItems.eq( item.index ).attr( "id" ) );
10887 .menu( "instance" );
10889 // Adjust menu styles to dropdown
10891 .addClass( "ui-corner-bottom" )
10892 .removeClass( "ui-corner-all" );
10894 // Don't close the menu on mouseleave
10895 this.menuInstance._off( this.menu, "mouseleave" );
10897 // Cancel the menu's collapseAll on document click
10898 this.menuInstance._closeOnDocumentClick = function() {
10902 // Selects often contain empty items, but never contain dividers
10903 this.menuInstance._isDivider = function() {
10908 refresh: function() {
10909 this._refreshMenu();
10910 this._setText( this.buttonText, this._getSelectedItem().text() );
10911 this._setOption( "width", this.options.width );
10914 _refreshMenu: function() {
10918 options = this.element.find( "option" );
10920 if ( !options.length ) {
10924 this._parseOptions( options );
10925 this._renderMenu( this.menu, this.items );
10927 this.menuInstance.refresh();
10928 this.menuItems = this.menu.find( "li" ).not( ".ui-selectmenu-optgroup" );
10930 item = this._getSelectedItem();
10932 // Update the menu to have the correct item focused
10933 this.menuInstance.focus( null, item );
10934 this._setAria( item.data( "ui-selectmenu-item" ) );
10936 // Set disabled state
10937 this._setOption( "disabled", this.element.prop( "disabled" ) );
10940 open: function( event ) {
10941 if ( this.options.disabled ) {
10945 // If this is the first time the menu is being opened, render the items
10946 if ( !this.menuItems ) {
10947 this._refreshMenu();
10950 // Menu clears focus on close, reset focus to selected item
10951 this.menu.find( ".ui-state-focus" ).removeClass( "ui-state-focus" );
10952 this.menuInstance.focus( null, this._getSelectedItem() );
10955 this.isOpen = true;
10956 this._toggleAttr();
10957 this._resizeMenu();
10960 this._on( this.document, this._documentClick );
10962 this._trigger( "open", event );
10965 _position: function() {
10966 this.menuWrap.position( $.extend( { of: this.button }, this.options.position ) );
10969 close: function( event ) {
10970 if ( !this.isOpen ) {
10974 this.isOpen = false;
10975 this._toggleAttr();
10977 this._off( this.document );
10979 this._trigger( "close", event );
10982 widget: function() {
10983 return this.button;
10986 menuWidget: function() {
10990 _renderMenu: function( ul, items ) {
10992 currentOptgroup = "";
10994 $.each( items, function( index, item ) {
10995 if ( item.optgroup !== currentOptgroup ) {
10997 "class": "ui-selectmenu-optgroup ui-menu-divider" +
10998 ( item.element.parent( "optgroup" ).prop( "disabled" ) ?
10999 " ui-state-disabled" :
11001 text: item.optgroup
11005 currentOptgroup = item.optgroup;
11008 that._renderItemData( ul, item );
11012 _renderItemData: function( ul, item ) {
11013 return this._renderItem( ul, item ).data( "ui-selectmenu-item", item );
11016 _renderItem: function( ul, item ) {
11017 var li = $( "<li>" );
11019 if ( item.disabled ) {
11020 li.addClass( "ui-state-disabled" );
11022 this._setText( li, item.label );
11024 return li.appendTo( ul );
11027 _setText: function( element, value ) {
11029 element.text( value );
11031 element.html( " " );
11035 _move: function( direction, event ) {
11037 filter = ".ui-menu-item";
11039 if ( this.isOpen ) {
11040 item = this.menuItems.eq( this.focusIndex );
11042 item = this.menuItems.eq( this.element[ 0 ].selectedIndex );
11043 filter += ":not(.ui-state-disabled)";
11046 if ( direction === "first" || direction === "last" ) {
11047 next = item[ direction === "first" ? "prevAll" : "nextAll" ]( filter ).eq( -1 );
11049 next = item[ direction + "All" ]( filter ).eq( 0 );
11052 if ( next.length ) {
11053 this.menuInstance.focus( event, next );
11057 _getSelectedItem: function() {
11058 return this.menuItems.eq( this.element[ 0 ].selectedIndex );
11061 _toggle: function( event ) {
11062 this[ this.isOpen ? "close" : "open" ]( event );
11066 mousedown: function( event ) {
11067 if ( !this.isOpen ) {
11071 if ( !$( event.target ).closest( ".ui-selectmenu-menu, #" + this.ids.button ).length ) {
11072 this.close( event );
11079 keydown: function( event ) {
11080 var preventDefault = true;
11081 switch ( event.keyCode ) {
11082 case $.ui.keyCode.TAB:
11083 case $.ui.keyCode.ESCAPE:
11084 this.close( event );
11085 preventDefault = false;
11087 case $.ui.keyCode.ENTER:
11088 if ( this.isOpen ) {
11089 this._selectFocusedItem( event );
11092 case $.ui.keyCode.UP:
11093 if ( event.altKey ) {
11094 this._toggle( event );
11096 this._move( "prev", event );
11099 case $.ui.keyCode.DOWN:
11100 if ( event.altKey ) {
11101 this._toggle( event );
11103 this._move( "next", event );
11106 case $.ui.keyCode.SPACE:
11107 if ( this.isOpen ) {
11108 this._selectFocusedItem( event );
11110 this._toggle( event );
11113 case $.ui.keyCode.LEFT:
11114 this._move( "prev", event );
11116 case $.ui.keyCode.RIGHT:
11117 this._move( "next", event );
11119 case $.ui.keyCode.HOME:
11120 case $.ui.keyCode.PAGE_UP:
11121 this._move( "first", event );
11123 case $.ui.keyCode.END:
11124 case $.ui.keyCode.PAGE_DOWN:
11125 this._move( "last", event );
11128 this.menu.trigger( event );
11129 preventDefault = false;
11132 if ( preventDefault ) {
11133 event.preventDefault();
11138 _selectFocusedItem: function( event ) {
11139 var item = this.menuItems.eq( this.focusIndex );
11140 if ( !item.hasClass( "ui-state-disabled" ) ) {
11141 this._select( item.data( "ui-selectmenu-item" ), event );
11145 _select: function( item, event ) {
11146 var oldIndex = this.element[ 0 ].selectedIndex;
11148 // Change native select element
11149 this.element[ 0 ].selectedIndex = item.index;
11150 this._setText( this.buttonText, item.label );
11151 this._setAria( item );
11152 this._trigger( "select", event, { item: item } );
11154 if ( item.index !== oldIndex ) {
11155 this._trigger( "change", event, { item: item } );
11158 this.close( event );
11161 _setAria: function( item ) {
11162 var id = this.menuItems.eq( item.index ).attr( "id" );
11165 "aria-labelledby": id,
11166 "aria-activedescendant": id
11168 this.menu.attr( "aria-activedescendant", id );
11171 _setOption: function( key, value ) {
11172 if ( key === "icons" ) {
11173 this.button.find( "span.ui-icon" )
11174 .removeClass( this.options.icons.button )
11175 .addClass( value.button );
11178 this._super( key, value );
11180 if ( key === "appendTo" ) {
11181 this.menuWrap.appendTo( this._appendTo() );
11184 if ( key === "disabled" ) {
11185 this.menuInstance.option( "disabled", value );
11187 .toggleClass( "ui-state-disabled", value )
11188 .attr( "aria-disabled", value );
11190 this.element.prop( "disabled", value );
11192 this.button.attr( "tabindex", -1 );
11195 this.button.attr( "tabindex", 0 );
11199 if ( key === "width" ) {
11201 value = this.element.outerWidth();
11203 this.button.outerWidth( value );
11207 _appendTo: function() {
11208 var element = this.options.appendTo;
11211 element = element.jquery || element.nodeType ?
11213 this.document.find( element ).eq( 0 );
11216 if ( !element || !element[ 0 ] ) {
11217 element = this.element.closest( ".ui-front" );
11220 if ( !element.length ) {
11221 element = this.document[ 0 ].body;
11227 _toggleAttr: function() {
11229 .toggleClass( "ui-corner-top", this.isOpen )
11230 .toggleClass( "ui-corner-all", !this.isOpen )
11231 .attr( "aria-expanded", this.isOpen );
11232 this.menuWrap.toggleClass( "ui-selectmenu-open", this.isOpen );
11233 this.menu.attr( "aria-hidden", !this.isOpen );
11236 _resizeMenu: function() {
11237 this.menu.outerWidth( Math.max(
11238 this.button.outerWidth(),
11241 // IE10 wraps long text (possibly a rounding bug)
11242 // so we add 1px to avoid the wrapping
11243 this.menu.width( "" ).outerWidth() + 1
11247 _getCreateOptions: function() {
11248 return { disabled: this.element.prop( "disabled" ) };
11251 _parseOptions: function( options ) {
11253 options.each(function( index, item ) {
11254 var option = $( item ),
11255 optgroup = option.parent( "optgroup" );
11259 value: option.attr( "value" ),
11260 label: option.text(),
11261 optgroup: optgroup.attr( "label" ) || "",
11262 disabled: optgroup.prop( "disabled" ) || option.prop( "disabled" )
11268 _destroy: function() {
11269 this.menuWrap.remove();
11270 this.button.remove();
11271 this.element.show();
11272 this.element.removeUniqueId();
11273 this.label.attr( "for", this.ids.element );
11279 * jQuery UI Slider 1.11.0
11280 * http://jqueryui.com
11282 * Copyright 2014 jQuery Foundation and other contributors
11283 * Released under the MIT license.
11284 * http://jquery.org/license
11286 * http://api.jqueryui.com/slider/
11290 var slider = $.widget( "ui.slider", $.ui.mouse, {
11292 widgetEventPrefix: "slide",
11299 orientation: "horizontal",
11312 // number of pages in a slider
11313 // (how many times can you page up/down to go through the whole range)
11316 _create: function() {
11317 this._keySliding = false;
11318 this._mouseSliding = false;
11319 this._animateOff = true;
11320 this._handleIndex = null;
11321 this._detectOrientation();
11325 .addClass( "ui-slider" +
11326 " ui-slider-" + this.orientation +
11328 " ui-widget-content" +
11332 this._setOption( "disabled", this.options.disabled );
11334 this._animateOff = false;
11337 _refresh: function() {
11338 this._createRange();
11339 this._createHandles();
11340 this._setupEvents();
11341 this._refreshValue();
11344 _createHandles: function() {
11345 var i, handleCount,
11346 options = this.options,
11347 existingHandles = this.element.find( ".ui-slider-handle" ).addClass( "ui-state-default ui-corner-all" ),
11348 handle = "<span class='ui-slider-handle ui-state-default ui-corner-all' tabindex='0'></span>",
11351 handleCount = ( options.values && options.values.length ) || 1;
11353 if ( existingHandles.length > handleCount ) {
11354 existingHandles.slice( handleCount ).remove();
11355 existingHandles = existingHandles.slice( 0, handleCount );
11358 for ( i = existingHandles.length; i < handleCount; i++ ) {
11359 handles.push( handle );
11362 this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( this.element ) );
11364 this.handle = this.handles.eq( 0 );
11366 this.handles.each(function( i ) {
11367 $( this ).data( "ui-slider-handle-index", i );
11371 _createRange: function() {
11372 var options = this.options,
11375 if ( options.range ) {
11376 if ( options.range === true ) {
11377 if ( !options.values ) {
11378 options.values = [ this._valueMin(), this._valueMin() ];
11379 } else if ( options.values.length && options.values.length !== 2 ) {
11380 options.values = [ options.values[0], options.values[0] ];
11381 } else if ( $.isArray( options.values ) ) {
11382 options.values = options.values.slice(0);
11386 if ( !this.range || !this.range.length ) {
11387 this.range = $( "<div></div>" )
11388 .appendTo( this.element );
11390 classes = "ui-slider-range" +
11391 // note: this isn't the most fittingly semantic framework class for this element,
11392 // but worked best visually with a variety of themes
11393 " ui-widget-header ui-corner-all";
11395 this.range.removeClass( "ui-slider-range-min ui-slider-range-max" )
11396 // Handle range switching from true to min/max
11403 this.range.addClass( classes +
11404 ( ( options.range === "min" || options.range === "max" ) ? " ui-slider-range-" + options.range : "" ) );
11406 if ( this.range ) {
11407 this.range.remove();
11413 _setupEvents: function() {
11414 this._off( this.handles );
11415 this._on( this.handles, this._handleEvents );
11416 this._hoverable( this.handles );
11417 this._focusable( this.handles );
11420 _destroy: function() {
11421 this.handles.remove();
11422 if ( this.range ) {
11423 this.range.remove();
11427 .removeClass( "ui-slider" +
11428 " ui-slider-horizontal" +
11429 " ui-slider-vertical" +
11431 " ui-widget-content" +
11432 " ui-corner-all" );
11434 this._mouseDestroy();
11437 _mouseCapture: function( event ) {
11438 var position, normValue, distance, closestHandle, index, allowed, offset, mouseOverHandle,
11442 if ( o.disabled ) {
11446 this.elementSize = {
11447 width: this.element.outerWidth(),
11448 height: this.element.outerHeight()
11450 this.elementOffset = this.element.offset();
11452 position = { x: event.pageX, y: event.pageY };
11453 normValue = this._normValueFromMouse( position );
11454 distance = this._valueMax() - this._valueMin() + 1;
11455 this.handles.each(function( i ) {
11456 var thisDistance = Math.abs( normValue - that.values(i) );
11457 if (( distance > thisDistance ) ||
11458 ( distance === thisDistance &&
11459 (i === that._lastChangedValue || that.values(i) === o.min ))) {
11460 distance = thisDistance;
11461 closestHandle = $( this );
11466 allowed = this._start( event, index );
11467 if ( allowed === false ) {
11470 this._mouseSliding = true;
11472 this._handleIndex = index;
11475 .addClass( "ui-state-active" )
11478 offset = closestHandle.offset();
11479 mouseOverHandle = !$( event.target ).parents().addBack().is( ".ui-slider-handle" );
11480 this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
11481 left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
11482 top: event.pageY - offset.top -
11483 ( closestHandle.height() / 2 ) -
11484 ( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) -
11485 ( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) +
11486 ( parseInt( closestHandle.css("marginTop"), 10 ) || 0)
11489 if ( !this.handles.hasClass( "ui-state-hover" ) ) {
11490 this._slide( event, index, normValue );
11492 this._animateOff = true;
11496 _mouseStart: function() {
11500 _mouseDrag: function( event ) {
11501 var position = { x: event.pageX, y: event.pageY },
11502 normValue = this._normValueFromMouse( position );
11504 this._slide( event, this._handleIndex, normValue );
11509 _mouseStop: function( event ) {
11510 this.handles.removeClass( "ui-state-active" );
11511 this._mouseSliding = false;
11513 this._stop( event, this._handleIndex );
11514 this._change( event, this._handleIndex );
11516 this._handleIndex = null;
11517 this._clickOffset = null;
11518 this._animateOff = false;
11523 _detectOrientation: function() {
11524 this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
11527 _normValueFromMouse: function( position ) {
11534 if ( this.orientation === "horizontal" ) {
11535 pixelTotal = this.elementSize.width;
11536 pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 );
11538 pixelTotal = this.elementSize.height;
11539 pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 );
11542 percentMouse = ( pixelMouse / pixelTotal );
11543 if ( percentMouse > 1 ) {
11546 if ( percentMouse < 0 ) {
11549 if ( this.orientation === "vertical" ) {
11550 percentMouse = 1 - percentMouse;
11553 valueTotal = this._valueMax() - this._valueMin();
11554 valueMouse = this._valueMin() + percentMouse * valueTotal;
11556 return this._trimAlignValue( valueMouse );
11559 _start: function( event, index ) {
11561 handle: this.handles[ index ],
11562 value: this.value()
11564 if ( this.options.values && this.options.values.length ) {
11565 uiHash.value = this.values( index );
11566 uiHash.values = this.values();
11568 return this._trigger( "start", event, uiHash );
11571 _slide: function( event, index, newVal ) {
11576 if ( this.options.values && this.options.values.length ) {
11577 otherVal = this.values( index ? 0 : 1 );
11579 if ( ( this.options.values.length === 2 && this.options.range === true ) &&
11580 ( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) )
11585 if ( newVal !== this.values( index ) ) {
11586 newValues = this.values();
11587 newValues[ index ] = newVal;
11588 // A slide can be canceled by returning false from the slide callback
11589 allowed = this._trigger( "slide", event, {
11590 handle: this.handles[ index ],
11594 otherVal = this.values( index ? 0 : 1 );
11595 if ( allowed !== false ) {
11596 this.values( index, newVal );
11600 if ( newVal !== this.value() ) {
11601 // A slide can be canceled by returning false from the slide callback
11602 allowed = this._trigger( "slide", event, {
11603 handle: this.handles[ index ],
11606 if ( allowed !== false ) {
11607 this.value( newVal );
11613 _stop: function( event, index ) {
11615 handle: this.handles[ index ],
11616 value: this.value()
11618 if ( this.options.values && this.options.values.length ) {
11619 uiHash.value = this.values( index );
11620 uiHash.values = this.values();
11623 this._trigger( "stop", event, uiHash );
11626 _change: function( event, index ) {
11627 if ( !this._keySliding && !this._mouseSliding ) {
11629 handle: this.handles[ index ],
11630 value: this.value()
11632 if ( this.options.values && this.options.values.length ) {
11633 uiHash.value = this.values( index );
11634 uiHash.values = this.values();
11637 //store the last changed value index for reference when handles overlap
11638 this._lastChangedValue = index;
11640 this._trigger( "change", event, uiHash );
11644 value: function( newValue ) {
11645 if ( arguments.length ) {
11646 this.options.value = this._trimAlignValue( newValue );
11647 this._refreshValue();
11648 this._change( null, 0 );
11652 return this._value();
11655 values: function( index, newValue ) {
11660 if ( arguments.length > 1 ) {
11661 this.options.values[ index ] = this._trimAlignValue( newValue );
11662 this._refreshValue();
11663 this._change( null, index );
11667 if ( arguments.length ) {
11668 if ( $.isArray( arguments[ 0 ] ) ) {
11669 vals = this.options.values;
11670 newValues = arguments[ 0 ];
11671 for ( i = 0; i < vals.length; i += 1 ) {
11672 vals[ i ] = this._trimAlignValue( newValues[ i ] );
11673 this._change( null, i );
11675 this._refreshValue();
11677 if ( this.options.values && this.options.values.length ) {
11678 return this._values( index );
11680 return this.value();
11684 return this._values();
11688 _setOption: function( key, value ) {
11692 if ( key === "range" && this.options.range === true ) {
11693 if ( value === "min" ) {
11694 this.options.value = this._values( 0 );
11695 this.options.values = null;
11696 } else if ( value === "max" ) {
11697 this.options.value = this._values( this.options.values.length - 1 );
11698 this.options.values = null;
11702 if ( $.isArray( this.options.values ) ) {
11703 valsLength = this.options.values.length;
11706 if ( key === "disabled" ) {
11707 this.element.toggleClass( "ui-state-disabled", !!value );
11710 this._super( key, value );
11713 case "orientation":
11714 this._detectOrientation();
11716 .removeClass( "ui-slider-horizontal ui-slider-vertical" )
11717 .addClass( "ui-slider-" + this.orientation );
11718 this._refreshValue();
11721 this._animateOff = true;
11722 this._refreshValue();
11723 this._change( null, 0 );
11724 this._animateOff = false;
11727 this._animateOff = true;
11728 this._refreshValue();
11729 for ( i = 0; i < valsLength; i += 1 ) {
11730 this._change( null, i );
11732 this._animateOff = false;
11736 this._animateOff = true;
11737 this._refreshValue();
11738 this._animateOff = false;
11741 this._animateOff = true;
11743 this._animateOff = false;
11748 //internal value getter
11749 // _value() returns value trimmed by min and max, aligned by step
11750 _value: function() {
11751 var val = this.options.value;
11752 val = this._trimAlignValue( val );
11757 //internal values getter
11758 // _values() returns array of values trimmed by min and max, aligned by step
11759 // _values( index ) returns single value trimmed by min and max, aligned by step
11760 _values: function( index ) {
11765 if ( arguments.length ) {
11766 val = this.options.values[ index ];
11767 val = this._trimAlignValue( val );
11770 } else if ( this.options.values && this.options.values.length ) {
11771 // .slice() creates a copy of the array
11772 // this copy gets trimmed by min and max and then returned
11773 vals = this.options.values.slice();
11774 for ( i = 0; i < vals.length; i+= 1) {
11775 vals[ i ] = this._trimAlignValue( vals[ i ] );
11784 // returns the step-aligned value that val is closest to, between (inclusive) min and max
11785 _trimAlignValue: function( val ) {
11786 if ( val <= this._valueMin() ) {
11787 return this._valueMin();
11789 if ( val >= this._valueMax() ) {
11790 return this._valueMax();
11792 var step = ( this.options.step > 0 ) ? this.options.step : 1,
11793 valModStep = (val - this._valueMin()) % step,
11794 alignValue = val - valModStep;
11796 if ( Math.abs(valModStep) * 2 >= step ) {
11797 alignValue += ( valModStep > 0 ) ? step : ( -step );
11800 // Since JavaScript has problems with large floats, round
11801 // the final value to 5 digits after the decimal point (see #4124)
11802 return parseFloat( alignValue.toFixed(5) );
11805 _valueMin: function() {
11806 return this.options.min;
11809 _valueMax: function() {
11810 return this.options.max;
11813 _refreshValue: function() {
11814 var lastValPercent, valPercent, value, valueMin, valueMax,
11815 oRange = this.options.range,
11818 animate = ( !this._animateOff ) ? o.animate : false,
11821 if ( this.options.values && this.options.values.length ) {
11822 this.handles.each(function( i ) {
11823 valPercent = ( that.values(i) - that._valueMin() ) / ( that._valueMax() - that._valueMin() ) * 100;
11824 _set[ that.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
11825 $( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
11826 if ( that.options.range === true ) {
11827 if ( that.orientation === "horizontal" ) {
11829 that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate );
11832 that.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
11836 that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate );
11839 that.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
11843 lastValPercent = valPercent;
11846 value = this.value();
11847 valueMin = this._valueMin();
11848 valueMax = this._valueMax();
11849 valPercent = ( valueMax !== valueMin ) ?
11850 ( value - valueMin ) / ( valueMax - valueMin ) * 100 :
11852 _set[ this.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
11853 this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
11855 if ( oRange === "min" && this.orientation === "horizontal" ) {
11856 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate );
11858 if ( oRange === "max" && this.orientation === "horizontal" ) {
11859 this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
11861 if ( oRange === "min" && this.orientation === "vertical" ) {
11862 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate );
11864 if ( oRange === "max" && this.orientation === "vertical" ) {
11865 this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
11871 keydown: function( event ) {
11872 var allowed, curVal, newVal, step,
11873 index = $( event.target ).data( "ui-slider-handle-index" );
11875 switch ( event.keyCode ) {
11876 case $.ui.keyCode.HOME:
11877 case $.ui.keyCode.END:
11878 case $.ui.keyCode.PAGE_UP:
11879 case $.ui.keyCode.PAGE_DOWN:
11880 case $.ui.keyCode.UP:
11881 case $.ui.keyCode.RIGHT:
11882 case $.ui.keyCode.DOWN:
11883 case $.ui.keyCode.LEFT:
11884 event.preventDefault();
11885 if ( !this._keySliding ) {
11886 this._keySliding = true;
11887 $( event.target ).addClass( "ui-state-active" );
11888 allowed = this._start( event, index );
11889 if ( allowed === false ) {
11896 step = this.options.step;
11897 if ( this.options.values && this.options.values.length ) {
11898 curVal = newVal = this.values( index );
11900 curVal = newVal = this.value();
11903 switch ( event.keyCode ) {
11904 case $.ui.keyCode.HOME:
11905 newVal = this._valueMin();
11907 case $.ui.keyCode.END:
11908 newVal = this._valueMax();
11910 case $.ui.keyCode.PAGE_UP:
11911 newVal = this._trimAlignValue(
11912 curVal + ( ( this._valueMax() - this._valueMin() ) / this.numPages )
11915 case $.ui.keyCode.PAGE_DOWN:
11916 newVal = this._trimAlignValue(
11917 curVal - ( (this._valueMax() - this._valueMin()) / this.numPages ) );
11919 case $.ui.keyCode.UP:
11920 case $.ui.keyCode.RIGHT:
11921 if ( curVal === this._valueMax() ) {
11924 newVal = this._trimAlignValue( curVal + step );
11926 case $.ui.keyCode.DOWN:
11927 case $.ui.keyCode.LEFT:
11928 if ( curVal === this._valueMin() ) {
11931 newVal = this._trimAlignValue( curVal - step );
11935 this._slide( event, index, newVal );
11937 keyup: function( event ) {
11938 var index = $( event.target ).data( "ui-slider-handle-index" );
11940 if ( this._keySliding ) {
11941 this._keySliding = false;
11942 this._stop( event, index );
11943 this._change( event, index );
11944 $( event.target ).removeClass( "ui-state-active" );
11952 * jQuery UI Spinner 1.11.0
11953 * http://jqueryui.com
11955 * Copyright 2014 jQuery Foundation and other contributors
11956 * Released under the MIT license.
11957 * http://jquery.org/license
11959 * http://api.jqueryui.com/spinner/
11963 function spinner_modifier( fn ) {
11964 return function() {
11965 var previous = this.element.val();
11966 fn.apply( this, arguments );
11968 if ( previous !== this.element.val() ) {
11969 this._trigger( "change" );
11974 var spinner = $.widget( "ui.spinner", {
11976 defaultElement: "<input>",
11977 widgetEventPrefix: "spin",
11981 down: "ui-icon-triangle-1-s",
11982 up: "ui-icon-triangle-1-n"
11987 numberFormat: null,
11997 _create: function() {
11998 // handle string values that need to be parsed
11999 this._setOption( "max", this.options.max );
12000 this._setOption( "min", this.options.min );
12001 this._setOption( "step", this.options.step );
12003 // Only format if there is a value, prevents the field from being marked
12004 // as invalid in Firefox, see #9573.
12005 if ( this.value() !== "" ) {
12006 // Format the value, but don't constrain.
12007 this._value( this.element.val(), true );
12011 this._on( this._events );
12014 // turning off autocomplete prevents the browser from remembering the
12015 // value when navigating through history, so we re-enable autocomplete
12016 // if the page is unloaded before the widget is destroyed. #7790
12017 this._on( this.window, {
12018 beforeunload: function() {
12019 this.element.removeAttr( "autocomplete" );
12024 _getCreateOptions: function() {
12026 element = this.element;
12028 $.each( [ "min", "max", "step" ], function( i, option ) {
12029 var value = element.attr( option );
12030 if ( value !== undefined && value.length ) {
12031 options[ option ] = value;
12039 keydown: function( event ) {
12040 if ( this._start( event ) && this._keydown( event ) ) {
12041 event.preventDefault();
12045 focus: function() {
12046 this.previous = this.element.val();
12048 blur: function( event ) {
12049 if ( this.cancelBlur ) {
12050 delete this.cancelBlur;
12056 if ( this.previous !== this.element.val() ) {
12057 this._trigger( "change", event );
12060 mousewheel: function( event, delta ) {
12064 if ( !this.spinning && !this._start( event ) ) {
12068 this._spin( (delta > 0 ? 1 : -1) * this.options.step, event );
12069 clearTimeout( this.mousewheelTimer );
12070 this.mousewheelTimer = this._delay(function() {
12071 if ( this.spinning ) {
12072 this._stop( event );
12075 event.preventDefault();
12077 "mousedown .ui-spinner-button": function( event ) {
12080 // We never want the buttons to have focus; whenever the user is
12081 // interacting with the spinner, the focus should be on the input.
12082 // If the input is focused then this.previous is properly set from
12083 // when the input first received focus. If the input is not focused
12084 // then we need to set this.previous based on the value before spinning.
12085 previous = this.element[0] === this.document[0].activeElement ?
12086 this.previous : this.element.val();
12087 function checkFocus() {
12088 var isActive = this.element[0] === this.document[0].activeElement;
12090 this.element.focus();
12091 this.previous = previous;
12093 // IE sets focus asynchronously, so we need to check if focus
12094 // moved off of the input because the user clicked on the button.
12095 this._delay(function() {
12096 this.previous = previous;
12101 // ensure focus is on (or stays on) the text field
12102 event.preventDefault();
12103 checkFocus.call( this );
12106 // IE doesn't prevent moving focus even with event.preventDefault()
12107 // so we set a flag to know when we should ignore the blur event
12108 // and check (again) if focus moved off of the input.
12109 this.cancelBlur = true;
12110 this._delay(function() {
12111 delete this.cancelBlur;
12112 checkFocus.call( this );
12115 if ( this._start( event ) === false ) {
12119 this._repeat( null, $( event.currentTarget ).hasClass( "ui-spinner-up" ) ? 1 : -1, event );
12121 "mouseup .ui-spinner-button": "_stop",
12122 "mouseenter .ui-spinner-button": function( event ) {
12123 // button will add ui-state-active if mouse was down while mouseleave and kept down
12124 if ( !$( event.currentTarget ).hasClass( "ui-state-active" ) ) {
12128 if ( this._start( event ) === false ) {
12131 this._repeat( null, $( event.currentTarget ).hasClass( "ui-spinner-up" ) ? 1 : -1, event );
12133 // TODO: do we really want to consider this a stop?
12134 // shouldn't we just stop the repeater and wait until mouseup before
12135 // we trigger the stop event?
12136 "mouseleave .ui-spinner-button": "_stop"
12139 _draw: function() {
12140 var uiSpinner = this.uiSpinner = this.element
12141 .addClass( "ui-spinner-input" )
12142 .attr( "autocomplete", "off" )
12143 .wrap( this._uiSpinnerHtml() )
12146 .append( this._buttonHtml() );
12148 this.element.attr( "role", "spinbutton" );
12151 this.buttons = uiSpinner.find( ".ui-spinner-button" )
12152 .attr( "tabIndex", -1 )
12154 .removeClass( "ui-corner-all" );
12156 // IE 6 doesn't understand height: 50% for the buttons
12157 // unless the wrapper has an explicit height
12158 if ( this.buttons.height() > Math.ceil( uiSpinner.height() * 0.5 ) &&
12159 uiSpinner.height() > 0 ) {
12160 uiSpinner.height( uiSpinner.height() );
12163 // disable spinner if element was already disabled
12164 if ( this.options.disabled ) {
12169 _keydown: function( event ) {
12170 var options = this.options,
12171 keyCode = $.ui.keyCode;
12173 switch ( event.keyCode ) {
12175 this._repeat( null, 1, event );
12178 this._repeat( null, -1, event );
12180 case keyCode.PAGE_UP:
12181 this._repeat( null, options.page, event );
12183 case keyCode.PAGE_DOWN:
12184 this._repeat( null, -options.page, event );
12191 _uiSpinnerHtml: function() {
12192 return "<span class='ui-spinner ui-widget ui-widget-content ui-corner-all'></span>";
12195 _buttonHtml: function() {
12197 "<a class='ui-spinner-button ui-spinner-up ui-corner-tr'>" +
12198 "<span class='ui-icon " + this.options.icons.up + "'>▲</span>" +
12200 "<a class='ui-spinner-button ui-spinner-down ui-corner-br'>" +
12201 "<span class='ui-icon " + this.options.icons.down + "'>▼</span>" +
12205 _start: function( event ) {
12206 if ( !this.spinning && this._trigger( "start", event ) === false ) {
12210 if ( !this.counter ) {
12213 this.spinning = true;
12217 _repeat: function( i, steps, event ) {
12220 clearTimeout( this.timer );
12221 this.timer = this._delay(function() {
12222 this._repeat( 40, steps, event );
12225 this._spin( steps * this.options.step, event );
12228 _spin: function( step, event ) {
12229 var value = this.value() || 0;
12231 if ( !this.counter ) {
12235 value = this._adjustValue( value + step * this._increment( this.counter ) );
12237 if ( !this.spinning || this._trigger( "spin", event, { value: value } ) !== false) {
12238 this._value( value );
12243 _increment: function( i ) {
12244 var incremental = this.options.incremental;
12246 if ( incremental ) {
12247 return $.isFunction( incremental ) ?
12249 Math.floor( i * i * i / 50000 - i * i / 500 + 17 * i / 200 + 1 );
12255 _precision: function() {
12256 var precision = this._precisionOf( this.options.step );
12257 if ( this.options.min !== null ) {
12258 precision = Math.max( precision, this._precisionOf( this.options.min ) );
12263 _precisionOf: function( num ) {
12264 var str = num.toString(),
12265 decimal = str.indexOf( "." );
12266 return decimal === -1 ? 0 : str.length - decimal - 1;
12269 _adjustValue: function( value ) {
12270 var base, aboveMin,
12271 options = this.options;
12273 // make sure we're at a valid step
12274 // - find out where we are relative to the base (min or 0)
12275 base = options.min !== null ? options.min : 0;
12276 aboveMin = value - base;
12277 // - round to the nearest step
12278 aboveMin = Math.round(aboveMin / options.step) * options.step;
12279 // - rounding is based on 0, so adjust back to our base
12280 value = base + aboveMin;
12282 // fix precision from bad JS floating point math
12283 value = parseFloat( value.toFixed( this._precision() ) );
12286 if ( options.max !== null && value > options.max) {
12287 return options.max;
12289 if ( options.min !== null && value < options.min ) {
12290 return options.min;
12296 _stop: function( event ) {
12297 if ( !this.spinning ) {
12301 clearTimeout( this.timer );
12302 clearTimeout( this.mousewheelTimer );
12304 this.spinning = false;
12305 this._trigger( "stop", event );
12308 _setOption: function( key, value ) {
12309 if ( key === "culture" || key === "numberFormat" ) {
12310 var prevValue = this._parse( this.element.val() );
12311 this.options[ key ] = value;
12312 this.element.val( this._format( prevValue ) );
12316 if ( key === "max" || key === "min" || key === "step" ) {
12317 if ( typeof value === "string" ) {
12318 value = this._parse( value );
12321 if ( key === "icons" ) {
12322 this.buttons.first().find( ".ui-icon" )
12323 .removeClass( this.options.icons.up )
12324 .addClass( value.up );
12325 this.buttons.last().find( ".ui-icon" )
12326 .removeClass( this.options.icons.down )
12327 .addClass( value.down );
12330 this._super( key, value );
12332 if ( key === "disabled" ) {
12333 this.widget().toggleClass( "ui-state-disabled", !!value );
12334 this.element.prop( "disabled", !!value );
12335 this.buttons.button( value ? "disable" : "enable" );
12339 _setOptions: spinner_modifier(function( options ) {
12340 this._super( options );
12343 _parse: function( val ) {
12344 if ( typeof val === "string" && val !== "" ) {
12345 val = window.Globalize && this.options.numberFormat ?
12346 Globalize.parseFloat( val, 10, this.options.culture ) : +val;
12348 return val === "" || isNaN( val ) ? null : val;
12351 _format: function( value ) {
12352 if ( value === "" ) {
12355 return window.Globalize && this.options.numberFormat ?
12356 Globalize.format( value, this.options.numberFormat, this.options.culture ) :
12360 _refresh: function() {
12361 this.element.attr({
12362 "aria-valuemin": this.options.min,
12363 "aria-valuemax": this.options.max,
12364 // TODO: what should we do with values that can't be parsed?
12365 "aria-valuenow": this._parse( this.element.val() )
12369 isValid: function() {
12370 var value = this.value();
12373 if ( value === null ) {
12377 // if value gets adjusted, it's invalid
12378 return value === this._adjustValue( value );
12381 // update the value without triggering change
12382 _value: function( value, allowAny ) {
12384 if ( value !== "" ) {
12385 parsed = this._parse( value );
12386 if ( parsed !== null ) {
12388 parsed = this._adjustValue( parsed );
12390 value = this._format( parsed );
12393 this.element.val( value );
12397 _destroy: function() {
12399 .removeClass( "ui-spinner-input" )
12400 .prop( "disabled", false )
12401 .removeAttr( "autocomplete" )
12402 .removeAttr( "role" )
12403 .removeAttr( "aria-valuemin" )
12404 .removeAttr( "aria-valuemax" )
12405 .removeAttr( "aria-valuenow" );
12406 this.uiSpinner.replaceWith( this.element );
12409 stepUp: spinner_modifier(function( steps ) {
12410 this._stepUp( steps );
12412 _stepUp: function( steps ) {
12413 if ( this._start() ) {
12414 this._spin( (steps || 1) * this.options.step );
12419 stepDown: spinner_modifier(function( steps ) {
12420 this._stepDown( steps );
12422 _stepDown: function( steps ) {
12423 if ( this._start() ) {
12424 this._spin( (steps || 1) * -this.options.step );
12429 pageUp: spinner_modifier(function( pages ) {
12430 this._stepUp( (pages || 1) * this.options.page );
12433 pageDown: spinner_modifier(function( pages ) {
12434 this._stepDown( (pages || 1) * this.options.page );
12437 value: function( newVal ) {
12438 if ( !arguments.length ) {
12439 return this._parse( this.element.val() );
12441 spinner_modifier( this._value ).call( this, newVal );
12444 widget: function() {
12445 return this.uiSpinner;
12451 * jQuery UI Tabs 1.11.0
12452 * http://jqueryui.com
12454 * Copyright 2014 jQuery Foundation and other contributors
12455 * Released under the MIT license.
12456 * http://jquery.org/license
12458 * http://api.jqueryui.com/tabs/
12462 var tabs = $.widget( "ui.tabs", {
12467 collapsible: false,
12469 heightStyle: "content",
12475 beforeActivate: null,
12480 _isLocal: (function() {
12481 var rhash = /#.*$/;
12483 return function( anchor ) {
12484 var anchorUrl, locationUrl;
12487 // IE7 doesn't normalize the href property when set via script (#9317)
12488 anchor = anchor.cloneNode( false );
12490 anchorUrl = anchor.href.replace( rhash, "" );
12491 locationUrl = location.href.replace( rhash, "" );
12493 // decoding may throw an error if the URL isn't UTF-8 (#9518)
12495 anchorUrl = decodeURIComponent( anchorUrl );
12496 } catch ( error ) {}
12498 locationUrl = decodeURIComponent( locationUrl );
12499 } catch ( error ) {}
12501 return anchor.hash.length > 1 && anchorUrl === locationUrl;
12505 _create: function() {
12507 options = this.options;
12509 this.running = false;
12512 .addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" )
12513 .toggleClass( "ui-tabs-collapsible", options.collapsible )
12514 // Prevent users from focusing disabled tabs via click
12515 .delegate( ".ui-tabs-nav > li", "mousedown" + this.eventNamespace, function( event ) {
12516 if ( $( this ).is( ".ui-state-disabled" ) ) {
12517 event.preventDefault();
12521 // Preventing the default action in mousedown doesn't prevent IE
12522 // from focusing the element, so if the anchor gets focused, blur.
12523 // We don't have to worry about focusing the previously focused
12524 // element since clicking on a non-focusable element should focus
12525 // the body anyway.
12526 .delegate( ".ui-tabs-anchor", "focus" + this.eventNamespace, function() {
12527 if ( $( this ).closest( "li" ).is( ".ui-state-disabled" ) ) {
12532 this._processTabs();
12533 options.active = this._initialActive();
12535 // Take disabling tabs via class attribute from HTML
12536 // into account and update option properly.
12537 if ( $.isArray( options.disabled ) ) {
12538 options.disabled = $.unique( options.disabled.concat(
12539 $.map( this.tabs.filter( ".ui-state-disabled" ), function( li ) {
12540 return that.tabs.index( li );
12545 // check for length avoids error when initializing empty list
12546 if ( this.options.active !== false && this.anchors.length ) {
12547 this.active = this._findActive( options.active );
12554 if ( this.active.length ) {
12555 this.load( options.active );
12559 _initialActive: function() {
12560 var active = this.options.active,
12561 collapsible = this.options.collapsible,
12562 locationHash = location.hash.substring( 1 );
12564 if ( active === null ) {
12565 // check the fragment identifier in the URL
12566 if ( locationHash ) {
12567 this.tabs.each(function( i, tab ) {
12568 if ( $( tab ).attr( "aria-controls" ) === locationHash ) {
12575 // check for a tab marked active via a class
12576 if ( active === null ) {
12577 active = this.tabs.index( this.tabs.filter( ".ui-tabs-active" ) );
12580 // no active tab, set to false
12581 if ( active === null || active === -1 ) {
12582 active = this.tabs.length ? 0 : false;
12586 // handle numbers: negative, out of range
12587 if ( active !== false ) {
12588 active = this.tabs.index( this.tabs.eq( active ) );
12589 if ( active === -1 ) {
12590 active = collapsible ? false : 0;
12594 // don't allow collapsible: false and active: false
12595 if ( !collapsible && active === false && this.anchors.length ) {
12602 _getCreateEventData: function() {
12605 panel: !this.active.length ? $() : this._getPanelForTab( this.active )
12609 _tabKeydown: function( event ) {
12610 var focusedTab = $( this.document[0].activeElement ).closest( "li" ),
12611 selectedIndex = this.tabs.index( focusedTab ),
12612 goingForward = true;
12614 if ( this._handlePageNav( event ) ) {
12618 switch ( event.keyCode ) {
12619 case $.ui.keyCode.RIGHT:
12620 case $.ui.keyCode.DOWN:
12623 case $.ui.keyCode.UP:
12624 case $.ui.keyCode.LEFT:
12625 goingForward = false;
12628 case $.ui.keyCode.END:
12629 selectedIndex = this.anchors.length - 1;
12631 case $.ui.keyCode.HOME:
12634 case $.ui.keyCode.SPACE:
12635 // Activate only, no collapsing
12636 event.preventDefault();
12637 clearTimeout( this.activating );
12638 this._activate( selectedIndex );
12640 case $.ui.keyCode.ENTER:
12641 // Toggle (cancel delayed activation, allow collapsing)
12642 event.preventDefault();
12643 clearTimeout( this.activating );
12644 // Determine if we should collapse or activate
12645 this._activate( selectedIndex === this.options.active ? false : selectedIndex );
12651 // Focus the appropriate tab, based on which key was pressed
12652 event.preventDefault();
12653 clearTimeout( this.activating );
12654 selectedIndex = this._focusNextTab( selectedIndex, goingForward );
12656 // Navigating with control key will prevent automatic activation
12657 if ( !event.ctrlKey ) {
12658 // Update aria-selected immediately so that AT think the tab is already selected.
12659 // Otherwise AT may confuse the user by stating that they need to activate the tab,
12660 // but the tab will already be activated by the time the announcement finishes.
12661 focusedTab.attr( "aria-selected", "false" );
12662 this.tabs.eq( selectedIndex ).attr( "aria-selected", "true" );
12664 this.activating = this._delay(function() {
12665 this.option( "active", selectedIndex );
12670 _panelKeydown: function( event ) {
12671 if ( this._handlePageNav( event ) ) {
12675 // Ctrl+up moves focus to the current tab
12676 if ( event.ctrlKey && event.keyCode === $.ui.keyCode.UP ) {
12677 event.preventDefault();
12678 this.active.focus();
12682 // Alt+page up/down moves focus to the previous/next tab (and activates)
12683 _handlePageNav: function( event ) {
12684 if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_UP ) {
12685 this._activate( this._focusNextTab( this.options.active - 1, false ) );
12688 if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_DOWN ) {
12689 this._activate( this._focusNextTab( this.options.active + 1, true ) );
12694 _findNextTab: function( index, goingForward ) {
12695 var lastTabIndex = this.tabs.length - 1;
12697 function constrain() {
12698 if ( index > lastTabIndex ) {
12702 index = lastTabIndex;
12707 while ( $.inArray( constrain(), this.options.disabled ) !== -1 ) {
12708 index = goingForward ? index + 1 : index - 1;
12714 _focusNextTab: function( index, goingForward ) {
12715 index = this._findNextTab( index, goingForward );
12716 this.tabs.eq( index ).focus();
12720 _setOption: function( key, value ) {
12721 if ( key === "active" ) {
12722 // _activate() will handle invalid values and update this.options
12723 this._activate( value );
12727 if ( key === "disabled" ) {
12728 // don't use the widget factory's disabled handling
12729 this._setupDisabled( value );
12733 this._super( key, value);
12735 if ( key === "collapsible" ) {
12736 this.element.toggleClass( "ui-tabs-collapsible", value );
12737 // Setting collapsible: false while collapsed; open first panel
12738 if ( !value && this.options.active === false ) {
12739 this._activate( 0 );
12743 if ( key === "event" ) {
12744 this._setupEvents( value );
12747 if ( key === "heightStyle" ) {
12748 this._setupHeightStyle( value );
12752 _sanitizeSelector: function( hash ) {
12753 return hash ? hash.replace( /[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g, "\\$&" ) : "";
12756 refresh: function() {
12757 var options = this.options,
12758 lis = this.tablist.children( ":has(a[href])" );
12760 // get disabled tabs from class attribute from HTML
12761 // this will get converted to a boolean if needed in _refresh()
12762 options.disabled = $.map( lis.filter( ".ui-state-disabled" ), function( tab ) {
12763 return lis.index( tab );
12766 this._processTabs();
12768 // was collapsed or no tabs
12769 if ( options.active === false || !this.anchors.length ) {
12770 options.active = false;
12772 // was active, but active tab is gone
12773 } else if ( this.active.length && !$.contains( this.tablist[ 0 ], this.active[ 0 ] ) ) {
12774 // all remaining tabs are disabled
12775 if ( this.tabs.length === options.disabled.length ) {
12776 options.active = false;
12778 // activate previous tab
12780 this._activate( this._findNextTab( Math.max( 0, options.active - 1 ), false ) );
12782 // was active, active tab still exists
12784 // make sure active index is correct
12785 options.active = this.tabs.index( this.active );
12791 _refresh: function() {
12792 this._setupDisabled( this.options.disabled );
12793 this._setupEvents( this.options.event );
12794 this._setupHeightStyle( this.options.heightStyle );
12796 this.tabs.not( this.active ).attr({
12797 "aria-selected": "false",
12798 "aria-expanded": "false",
12801 this.panels.not( this._getPanelForTab( this.active ) )
12804 "aria-hidden": "true"
12807 // Make sure one tab is in the tab order
12808 if ( !this.active.length ) {
12809 this.tabs.eq( 0 ).attr( "tabIndex", 0 );
12812 .addClass( "ui-tabs-active ui-state-active" )
12814 "aria-selected": "true",
12815 "aria-expanded": "true",
12818 this._getPanelForTab( this.active )
12821 "aria-hidden": "false"
12826 _processTabs: function() {
12829 this.tablist = this._getList()
12830 .addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" )
12831 .attr( "role", "tablist" );
12833 this.tabs = this.tablist.find( "> li:has(a[href])" )
12834 .addClass( "ui-state-default ui-corner-top" )
12840 this.anchors = this.tabs.map(function() {
12841 return $( "a", this )[ 0 ];
12843 .addClass( "ui-tabs-anchor" )
12845 role: "presentation",
12851 this.anchors.each(function( i, anchor ) {
12852 var selector, panel, panelId,
12853 anchorId = $( anchor ).uniqueId().attr( "id" ),
12854 tab = $( anchor ).closest( "li" ),
12855 originalAriaControls = tab.attr( "aria-controls" );
12858 if ( that._isLocal( anchor ) ) {
12859 selector = anchor.hash;
12860 panelId = selector.substring( 1 );
12861 panel = that.element.find( that._sanitizeSelector( selector ) );
12864 // If the tab doesn't already have aria-controls,
12865 // generate an id by using a throw-away element
12866 panelId = tab.attr( "aria-controls" ) || $( {} ).uniqueId()[ 0 ].id;
12867 selector = "#" + panelId;
12868 panel = that.element.find( selector );
12869 if ( !panel.length ) {
12870 panel = that._createPanel( panelId );
12871 panel.insertAfter( that.panels[ i - 1 ] || that.tablist );
12873 panel.attr( "aria-live", "polite" );
12876 if ( panel.length) {
12877 that.panels = that.panels.add( panel );
12879 if ( originalAriaControls ) {
12880 tab.data( "ui-tabs-aria-controls", originalAriaControls );
12883 "aria-controls": panelId,
12884 "aria-labelledby": anchorId
12886 panel.attr( "aria-labelledby", anchorId );
12890 .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
12891 .attr( "role", "tabpanel" );
12894 // allow overriding how to find the list for rare usage scenarios (#7715)
12895 _getList: function() {
12896 return this.tablist || this.element.find( "ol,ul" ).eq( 0 );
12899 _createPanel: function( id ) {
12900 return $( "<div>" )
12902 .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
12903 .data( "ui-tabs-destroy", true );
12906 _setupDisabled: function( disabled ) {
12907 if ( $.isArray( disabled ) ) {
12908 if ( !disabled.length ) {
12910 } else if ( disabled.length === this.anchors.length ) {
12916 for ( var i = 0, li; ( li = this.tabs[ i ] ); i++ ) {
12917 if ( disabled === true || $.inArray( i, disabled ) !== -1 ) {
12919 .addClass( "ui-state-disabled" )
12920 .attr( "aria-disabled", "true" );
12923 .removeClass( "ui-state-disabled" )
12924 .removeAttr( "aria-disabled" );
12928 this.options.disabled = disabled;
12931 _setupEvents: function( event ) {
12934 $.each( event.split(" "), function( index, eventName ) {
12935 events[ eventName ] = "_eventHandler";
12939 this._off( this.anchors.add( this.tabs ).add( this.panels ) );
12940 // Always prevent the default action, even when disabled
12941 this._on( true, this.anchors, {
12942 click: function( event ) {
12943 event.preventDefault();
12946 this._on( this.anchors, events );
12947 this._on( this.tabs, { keydown: "_tabKeydown" } );
12948 this._on( this.panels, { keydown: "_panelKeydown" } );
12950 this._focusable( this.tabs );
12951 this._hoverable( this.tabs );
12954 _setupHeightStyle: function( heightStyle ) {
12956 parent = this.element.parent();
12958 if ( heightStyle === "fill" ) {
12959 maxHeight = parent.height();
12960 maxHeight -= this.element.outerHeight() - this.element.height();
12962 this.element.siblings( ":visible" ).each(function() {
12963 var elem = $( this ),
12964 position = elem.css( "position" );
12966 if ( position === "absolute" || position === "fixed" ) {
12969 maxHeight -= elem.outerHeight( true );
12972 this.element.children().not( this.panels ).each(function() {
12973 maxHeight -= $( this ).outerHeight( true );
12976 this.panels.each(function() {
12977 $( this ).height( Math.max( 0, maxHeight -
12978 $( this ).innerHeight() + $( this ).height() ) );
12980 .css( "overflow", "auto" );
12981 } else if ( heightStyle === "auto" ) {
12983 this.panels.each(function() {
12984 maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() );
12985 }).height( maxHeight );
12989 _eventHandler: function( event ) {
12990 var options = this.options,
12991 active = this.active,
12992 anchor = $( event.currentTarget ),
12993 tab = anchor.closest( "li" ),
12994 clickedIsActive = tab[ 0 ] === active[ 0 ],
12995 collapsing = clickedIsActive && options.collapsible,
12996 toShow = collapsing ? $() : this._getPanelForTab( tab ),
12997 toHide = !active.length ? $() : this._getPanelForTab( active ),
13001 newTab: collapsing ? $() : tab,
13005 event.preventDefault();
13007 if ( tab.hasClass( "ui-state-disabled" ) ||
13008 // tab is already loading
13009 tab.hasClass( "ui-tabs-loading" ) ||
13010 // can't switch durning an animation
13012 // click on active header, but not collapsible
13013 ( clickedIsActive && !options.collapsible ) ||
13014 // allow canceling activation
13015 ( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
13019 options.active = collapsing ? false : this.tabs.index( tab );
13021 this.active = clickedIsActive ? $() : tab;
13026 if ( !toHide.length && !toShow.length ) {
13027 $.error( "jQuery UI Tabs: Mismatching fragment identifier." );
13030 if ( toShow.length ) {
13031 this.load( this.tabs.index( tab ), event );
13033 this._toggle( event, eventData );
13036 // handles show/hide for selecting tabs
13037 _toggle: function( event, eventData ) {
13039 toShow = eventData.newPanel,
13040 toHide = eventData.oldPanel;
13042 this.running = true;
13044 function complete() {
13045 that.running = false;
13046 that._trigger( "activate", event, eventData );
13050 eventData.newTab.closest( "li" ).addClass( "ui-tabs-active ui-state-active" );
13052 if ( toShow.length && that.options.show ) {
13053 that._show( toShow, that.options.show, complete );
13060 // start out by hiding, then showing, then completing
13061 if ( toHide.length && this.options.hide ) {
13062 this._hide( toHide, this.options.hide, function() {
13063 eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" );
13067 eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" );
13072 toHide.attr( "aria-hidden", "true" );
13073 eventData.oldTab.attr({
13074 "aria-selected": "false",
13075 "aria-expanded": "false"
13077 // If we're switching tabs, remove the old tab from the tab order.
13078 // If we're opening from collapsed state, remove the previous tab from the tab order.
13079 // If we're collapsing, then keep the collapsing tab in the tab order.
13080 if ( toShow.length && toHide.length ) {
13081 eventData.oldTab.attr( "tabIndex", -1 );
13082 } else if ( toShow.length ) {
13083 this.tabs.filter(function() {
13084 return $( this ).attr( "tabIndex" ) === 0;
13086 .attr( "tabIndex", -1 );
13089 toShow.attr( "aria-hidden", "false" );
13090 eventData.newTab.attr({
13091 "aria-selected": "true",
13092 "aria-expanded": "true",
13097 _activate: function( index ) {
13099 active = this._findActive( index );
13101 // trying to activate the already active panel
13102 if ( active[ 0 ] === this.active[ 0 ] ) {
13106 // trying to collapse, simulate a click on the current active header
13107 if ( !active.length ) {
13108 active = this.active;
13111 anchor = active.find( ".ui-tabs-anchor" )[ 0 ];
13112 this._eventHandler({
13114 currentTarget: anchor,
13115 preventDefault: $.noop
13119 _findActive: function( index ) {
13120 return index === false ? $() : this.tabs.eq( index );
13123 _getIndex: function( index ) {
13124 // meta-function to give users option to provide a href string instead of a numerical index.
13125 if ( typeof index === "string" ) {
13126 index = this.anchors.index( this.anchors.filter( "[href$='" + index + "']" ) );
13132 _destroy: function() {
13137 this.element.removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" );
13140 .removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" )
13141 .removeAttr( "role" );
13144 .removeClass( "ui-tabs-anchor" )
13145 .removeAttr( "role" )
13146 .removeAttr( "tabIndex" )
13149 this.tabs.add( this.panels ).each(function() {
13150 if ( $.data( this, "ui-tabs-destroy" ) ) {
13151 $( this ).remove();
13154 .removeClass( "ui-state-default ui-state-active ui-state-disabled " +
13155 "ui-corner-top ui-corner-bottom ui-widget-content ui-tabs-active ui-tabs-panel" )
13156 .removeAttr( "tabIndex" )
13157 .removeAttr( "aria-live" )
13158 .removeAttr( "aria-busy" )
13159 .removeAttr( "aria-selected" )
13160 .removeAttr( "aria-labelledby" )
13161 .removeAttr( "aria-hidden" )
13162 .removeAttr( "aria-expanded" )
13163 .removeAttr( "role" );
13167 this.tabs.each(function() {
13168 var li = $( this ),
13169 prev = li.data( "ui-tabs-aria-controls" );
13172 .attr( "aria-controls", prev )
13173 .removeData( "ui-tabs-aria-controls" );
13175 li.removeAttr( "aria-controls" );
13179 this.panels.show();
13181 if ( this.options.heightStyle !== "content" ) {
13182 this.panels.css( "height", "" );
13186 enable: function( index ) {
13187 var disabled = this.options.disabled;
13188 if ( disabled === false ) {
13192 if ( index === undefined ) {
13195 index = this._getIndex( index );
13196 if ( $.isArray( disabled ) ) {
13197 disabled = $.map( disabled, function( num ) {
13198 return num !== index ? num : null;
13201 disabled = $.map( this.tabs, function( li, num ) {
13202 return num !== index ? num : null;
13206 this._setupDisabled( disabled );
13209 disable: function( index ) {
13210 var disabled = this.options.disabled;
13211 if ( disabled === true ) {
13215 if ( index === undefined ) {
13218 index = this._getIndex( index );
13219 if ( $.inArray( index, disabled ) !== -1 ) {
13222 if ( $.isArray( disabled ) ) {
13223 disabled = $.merge( [ index ], disabled ).sort();
13225 disabled = [ index ];
13228 this._setupDisabled( disabled );
13231 load: function( index, event ) {
13232 index = this._getIndex( index );
13234 tab = this.tabs.eq( index ),
13235 anchor = tab.find( ".ui-tabs-anchor" ),
13236 panel = this._getPanelForTab( tab ),
13243 if ( this._isLocal( anchor[ 0 ] ) ) {
13247 this.xhr = $.ajax( this._ajaxSettings( anchor, event, eventData ) );
13249 // support: jQuery <1.8
13250 // jQuery <1.8 returns false if the request is canceled in beforeSend,
13251 // but as of 1.8, $.ajax() always returns a jqXHR object.
13252 if ( this.xhr && this.xhr.statusText !== "canceled" ) {
13253 tab.addClass( "ui-tabs-loading" );
13254 panel.attr( "aria-busy", "true" );
13257 .success(function( response ) {
13258 // support: jQuery <1.8
13259 // http://bugs.jquery.com/ticket/11778
13260 setTimeout(function() {
13261 panel.html( response );
13262 that._trigger( "load", event, eventData );
13265 .complete(function( jqXHR, status ) {
13266 // support: jQuery <1.8
13267 // http://bugs.jquery.com/ticket/11778
13268 setTimeout(function() {
13269 if ( status === "abort" ) {
13270 that.panels.stop( false, true );
13273 tab.removeClass( "ui-tabs-loading" );
13274 panel.removeAttr( "aria-busy" );
13276 if ( jqXHR === that.xhr ) {
13284 _ajaxSettings: function( anchor, event, eventData ) {
13287 url: anchor.attr( "href" ),
13288 beforeSend: function( jqXHR, settings ) {
13289 return that._trigger( "beforeLoad", event,
13290 $.extend( { jqXHR: jqXHR, ajaxSettings: settings }, eventData ) );
13295 _getPanelForTab: function( tab ) {
13296 var id = $( tab ).attr( "aria-controls" );
13297 return this.element.find( this._sanitizeSelector( "#" + id ) );
13303 * jQuery UI Tooltip 1.11.0
13304 * http://jqueryui.com
13306 * Copyright 2014 jQuery Foundation and other contributors
13307 * Released under the MIT license.
13308 * http://jquery.org/license
13310 * http://api.jqueryui.com/tooltip/
13314 var tooltip = $.widget( "ui.tooltip", {
13317 content: function() {
13318 // support: IE<9, Opera in jQuery <1.7
13319 // .text() can't accept undefined, so coerce to a string
13320 var title = $( this ).attr( "title" ) || "";
13321 // Escape title, since we're going from an attribute to raw HTML
13322 return $( "<a>" ).text( title ).html();
13325 // Disabled elements have inconsistent behavior across browsers (#8661)
13326 items: "[title]:not([disabled])",
13330 collision: "flipfit flip"
13333 tooltipClass: null,
13341 _addDescribedBy: function( elem, id ) {
13342 var describedby = (elem.attr( "aria-describedby" ) || "").split( /\s+/ );
13343 describedby.push( id );
13345 .data( "ui-tooltip-id", id )
13346 .attr( "aria-describedby", $.trim( describedby.join( " " ) ) );
13349 _removeDescribedBy: function( elem ) {
13350 var id = elem.data( "ui-tooltip-id" ),
13351 describedby = (elem.attr( "aria-describedby" ) || "").split( /\s+/ ),
13352 index = $.inArray( id, describedby );
13354 if ( index !== -1 ) {
13355 describedby.splice( index, 1 );
13358 elem.removeData( "ui-tooltip-id" );
13359 describedby = $.trim( describedby.join( " " ) );
13360 if ( describedby ) {
13361 elem.attr( "aria-describedby", describedby );
13363 elem.removeAttr( "aria-describedby" );
13367 _create: function() {
13373 // IDs of generated tooltips, needed for destroy
13374 this.tooltips = {};
13375 // IDs of parent tooltips where we removed the title attribute
13378 if ( this.options.disabled ) {
13382 // Append the aria-live region so tooltips announce correctly
13383 this.liveRegion = $( "<div>" )
13386 "aria-live": "assertive",
13387 "aria-relevant": "additions"
13389 .addClass( "ui-helper-hidden-accessible" )
13390 .appendTo( this.document[ 0 ].body );
13393 _setOption: function( key, value ) {
13396 if ( key === "disabled" ) {
13397 this[ value ? "_disable" : "_enable" ]();
13398 this.options[ key ] = value;
13399 // disable element style changes
13403 this._super( key, value );
13405 if ( key === "content" ) {
13406 $.each( this.tooltips, function( id, element ) {
13407 that._updateContent( element );
13412 _disable: function() {
13415 // close open tooltips
13416 $.each( this.tooltips, function( id, element ) {
13417 var event = $.Event( "blur" );
13418 event.target = event.currentTarget = element[0];
13419 that.close( event, true );
13422 // remove title attributes to prevent native tooltips
13423 this.element.find( this.options.items ).addBack().each(function() {
13424 var element = $( this );
13425 if ( element.is( "[title]" ) ) {
13427 .data( "ui-tooltip-title", element.attr( "title" ) )
13428 .removeAttr( "title" );
13433 _enable: function() {
13434 // restore title attributes
13435 this.element.find( this.options.items ).addBack().each(function() {
13436 var element = $( this );
13437 if ( element.data( "ui-tooltip-title" ) ) {
13438 element.attr( "title", element.data( "ui-tooltip-title" ) );
13443 open: function( event ) {
13445 target = $( event ? event.target : this.element )
13446 // we need closest here due to mouseover bubbling,
13447 // but always pointing at the same event target
13448 .closest( this.options.items );
13450 // No element to show a tooltip for or the tooltip is already open
13451 if ( !target.length || target.data( "ui-tooltip-id" ) ) {
13455 if ( target.attr( "title" ) ) {
13456 target.data( "ui-tooltip-title", target.attr( "title" ) );
13459 target.data( "ui-tooltip-open", true );
13461 // kill parent tooltips, custom or native, for hover
13462 if ( event && event.type === "mouseover" ) {
13463 target.parents().each(function() {
13464 var parent = $( this ),
13466 if ( parent.data( "ui-tooltip-open" ) ) {
13467 blurEvent = $.Event( "blur" );
13468 blurEvent.target = blurEvent.currentTarget = this;
13469 that.close( blurEvent, true );
13471 if ( parent.attr( "title" ) ) {
13473 that.parents[ this.id ] = {
13475 title: parent.attr( "title" )
13477 parent.attr( "title", "" );
13482 this._updateContent( target, event );
13485 _updateContent: function( target, event ) {
13487 contentOption = this.options.content,
13489 eventType = event ? event.type : null;
13491 if ( typeof contentOption === "string" ) {
13492 return this._open( event, target, contentOption );
13495 content = contentOption.call( target[0], function( response ) {
13496 // ignore async response if tooltip was closed already
13497 if ( !target.data( "ui-tooltip-open" ) ) {
13500 // IE may instantly serve a cached response for ajax requests
13501 // delay this call to _open so the other call to _open runs first
13502 that._delay(function() {
13503 // jQuery creates a special event for focusin when it doesn't
13504 // exist natively. To improve performance, the native event
13505 // object is reused and the type is changed. Therefore, we can't
13506 // rely on the type being correct after the event finished
13507 // bubbling, so we set it back to the previous value. (#8740)
13509 event.type = eventType;
13511 this._open( event, target, response );
13515 this._open( event, target, content );
13519 _open: function( event, target, content ) {
13520 var tooltip, events, delayedShow, a11yContent,
13521 positionOption = $.extend( {}, this.options.position );
13527 // Content can be updated multiple times. If the tooltip already
13528 // exists, then just update the content and bail.
13529 tooltip = this._find( target );
13530 if ( tooltip.length ) {
13531 tooltip.find( ".ui-tooltip-content" ).html( content );
13535 // if we have a title, clear it to prevent the native tooltip
13536 // we have to check first to avoid defining a title if none exists
13537 // (we don't want to cause an element to start matching [title])
13539 // We use removeAttr only for key events, to allow IE to export the correct
13540 // accessible attributes. For mouse events, set to empty string to avoid
13541 // native tooltip showing up (happens only when removing inside mouseover).
13542 if ( target.is( "[title]" ) ) {
13543 if ( event && event.type === "mouseover" ) {
13544 target.attr( "title", "" );
13546 target.removeAttr( "title" );
13550 tooltip = this._tooltip( target );
13551 this._addDescribedBy( target, tooltip.attr( "id" ) );
13552 tooltip.find( ".ui-tooltip-content" ).html( content );
13554 // Support: Voiceover on OS X, JAWS on IE <= 9
13555 // JAWS announces deletions even when aria-relevant="additions"
13556 // Voiceover will sometimes re-read the entire log region's contents from the beginning
13557 this.liveRegion.children().hide();
13558 if ( content.clone ) {
13559 a11yContent = content.clone();
13560 a11yContent.removeAttr( "id" ).find( "[id]" ).removeAttr( "id" );
13562 a11yContent = content;
13564 $( "<div>" ).html( a11yContent ).appendTo( this.liveRegion );
13566 function position( event ) {
13567 positionOption.of = event;
13568 if ( tooltip.is( ":hidden" ) ) {
13571 tooltip.position( positionOption );
13573 if ( this.options.track && event && /^mouse/.test( event.type ) ) {
13574 this._on( this.document, {
13575 mousemove: position
13577 // trigger once to override element-relative positioning
13580 tooltip.position( $.extend({
13582 }, this.options.position ) );
13587 this._show( tooltip, this.options.show );
13588 // Handle tracking tooltips that are shown with a delay (#8644). As soon
13589 // as the tooltip is visible, position the tooltip using the most recent
13591 if ( this.options.show && this.options.show.delay ) {
13592 delayedShow = this.delayedShow = setInterval(function() {
13593 if ( tooltip.is( ":visible" ) ) {
13594 position( positionOption.of );
13595 clearInterval( delayedShow );
13597 }, $.fx.interval );
13600 this._trigger( "open", event, { tooltip: tooltip } );
13603 keyup: function( event ) {
13604 if ( event.keyCode === $.ui.keyCode.ESCAPE ) {
13605 var fakeEvent = $.Event(event);
13606 fakeEvent.currentTarget = target[0];
13607 this.close( fakeEvent, true );
13612 // Only bind remove handler for delegated targets. Non-delegated
13613 // tooltips will handle this in destroy.
13614 if ( target[ 0 ] !== this.element[ 0 ] ) {
13615 events.remove = function() {
13616 this._removeTooltip( tooltip );
13620 if ( !event || event.type === "mouseover" ) {
13621 events.mouseleave = "close";
13623 if ( !event || event.type === "focusin" ) {
13624 events.focusout = "close";
13626 this._on( true, target, events );
13629 close: function( event ) {
13631 target = $( event ? event.currentTarget : this.element ),
13632 tooltip = this._find( target );
13634 // disabling closes the tooltip, so we need to track when we're closing
13635 // to avoid an infinite loop in case the tooltip becomes disabled on close
13636 if ( this.closing ) {
13640 // Clear the interval for delayed tracking tooltips
13641 clearInterval( this.delayedShow );
13643 // only set title if we had one before (see comment in _open())
13644 // If the title attribute has changed since open(), don't restore
13645 if ( target.data( "ui-tooltip-title" ) && !target.attr( "title" ) ) {
13646 target.attr( "title", target.data( "ui-tooltip-title" ) );
13649 this._removeDescribedBy( target );
13651 tooltip.stop( true );
13652 this._hide( tooltip, this.options.hide, function() {
13653 that._removeTooltip( $( this ) );
13656 target.removeData( "ui-tooltip-open" );
13657 this._off( target, "mouseleave focusout keyup" );
13659 // Remove 'remove' binding only on delegated targets
13660 if ( target[ 0 ] !== this.element[ 0 ] ) {
13661 this._off( target, "remove" );
13663 this._off( this.document, "mousemove" );
13665 if ( event && event.type === "mouseleave" ) {
13666 $.each( this.parents, function( id, parent ) {
13667 $( parent.element ).attr( "title", parent.title );
13668 delete that.parents[ id ];
13672 this.closing = true;
13673 this._trigger( "close", event, { tooltip: tooltip } );
13674 this.closing = false;
13677 _tooltip: function( element ) {
13678 var tooltip = $( "<div>" )
13679 .attr( "role", "tooltip" )
13680 .addClass( "ui-tooltip ui-widget ui-corner-all ui-widget-content " +
13681 ( this.options.tooltipClass || "" ) ),
13682 id = tooltip.uniqueId().attr( "id" );
13685 .addClass( "ui-tooltip-content" )
13686 .appendTo( tooltip );
13688 tooltip.appendTo( this.document[0].body );
13689 this.tooltips[ id ] = element;
13693 _find: function( target ) {
13694 var id = target.data( "ui-tooltip-id" );
13695 return id ? $( "#" + id ) : $();
13698 _removeTooltip: function( tooltip ) {
13700 delete this.tooltips[ tooltip.attr( "id" ) ];
13703 _destroy: function() {
13706 // close open tooltips
13707 $.each( this.tooltips, function( id, element ) {
13708 // Delegate to close method to handle common cleanup
13709 var event = $.Event( "blur" );
13710 event.target = event.currentTarget = element[0];
13711 that.close( event, true );
13713 // Remove immediately; destroying an open tooltip doesn't use the
13715 $( "#" + id ).remove();
13717 // Restore the title
13718 if ( element.data( "ui-tooltip-title" ) ) {
13719 // If the title attribute has changed since open(), don't restore
13720 if ( !element.attr( "title" ) ) {
13721 element.attr( "title", element.data( "ui-tooltip-title" ) );
13723 element.removeData( "ui-tooltip-title" );
13726 this.liveRegion.remove();
13732 * jQuery UI Effects 1.11.0
13733 * http://jqueryui.com
13735 * Copyright 2014 jQuery Foundation and other contributors
13736 * Released under the MIT license.
13737 * http://jquery.org/license
13739 * http://api.jqueryui.com/category/effects-core/
13743 var dataSpace = "ui-effects-";
13750 * jQuery Color Animations v2.1.2
13751 * https://github.com/jquery/jquery-color
13753 * Copyright 2014 jQuery Foundation and other contributors
13754 * Released under the MIT license.
13755 * http://jquery.org/license
13757 * Date: Wed Jan 16 08:47:09 2013 -0600
13759 (function( jQuery, undefined ) {
13761 var stepHooks = "backgroundColor borderBottomColor borderLeftColor borderRightColor borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor",
13763 // plusequals test for += 100 -= 100
13764 rplusequals = /^([\-+])=\s*(\d+\.?\d*)/,
13765 // a set of RE's that can match strings and generate color tuples.
13766 stringParsers = [ {
13767 re: /rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
13768 parse: function( execResult ) {
13777 re: /rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
13778 parse: function( execResult ) {
13780 execResult[ 1 ] * 2.55,
13781 execResult[ 2 ] * 2.55,
13782 execResult[ 3 ] * 2.55,
13787 // this regex ignores A-F because it's compared against an already lowercased string
13788 re: /#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/,
13789 parse: function( execResult ) {
13791 parseInt( execResult[ 1 ], 16 ),
13792 parseInt( execResult[ 2 ], 16 ),
13793 parseInt( execResult[ 3 ], 16 )
13797 // this regex ignores A-F because it's compared against an already lowercased string
13798 re: /#([a-f0-9])([a-f0-9])([a-f0-9])/,
13799 parse: function( execResult ) {
13801 parseInt( execResult[ 1 ] + execResult[ 1 ], 16 ),
13802 parseInt( execResult[ 2 ] + execResult[ 2 ], 16 ),
13803 parseInt( execResult[ 3 ] + execResult[ 3 ], 16 )
13807 re: /hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
13809 parse: function( execResult ) {
13812 execResult[ 2 ] / 100,
13813 execResult[ 3 ] / 100,
13820 color = jQuery.Color = function( color, green, blue, alpha ) {
13821 return new jQuery.Color.fn.parse( color, green, blue, alpha );
13871 support = color.support = {},
13873 // element for support tests
13874 supportElem = jQuery( "<p>" )[ 0 ],
13876 // colors = jQuery.Color.names
13879 // local aliases of functions called often
13880 each = jQuery.each;
13882 // determine rgba support immediately
13883 supportElem.style.cssText = "background-color:rgba(1,1,1,.5)";
13884 support.rgba = supportElem.style.backgroundColor.indexOf( "rgba" ) > -1;
13886 // define cache name and alpha properties
13887 // for rgba and hsla spaces
13888 each( spaces, function( spaceName, space ) {
13889 space.cache = "_" + spaceName;
13890 space.props.alpha = {
13897 function clamp( value, prop, allowEmpty ) {
13898 var type = propTypes[ prop.type ] || {};
13900 if ( value == null ) {
13901 return (allowEmpty || !prop.def) ? null : prop.def;
13904 // ~~ is an short way of doing floor for positive numbers
13905 value = type.floor ? ~~value : parseFloat( value );
13907 // IE will pass in empty strings as value for alpha,
13908 // which will hit this case
13909 if ( isNaN( value ) ) {
13914 // we add mod before modding to make sure that negatives values
13915 // get converted properly: -10 -> 350
13916 return (value + type.mod) % type.mod;
13919 // for now all property types without mod have min and max
13920 return 0 > value ? 0 : type.max < value ? type.max : value;
13923 function stringParse( string ) {
13924 var inst = color(),
13925 rgba = inst._rgba = [];
13927 string = string.toLowerCase();
13929 each( stringParsers, function( i, parser ) {
13931 match = parser.re.exec( string ),
13932 values = match && parser.parse( match ),
13933 spaceName = parser.space || "rgba";
13936 parsed = inst[ spaceName ]( values );
13938 // if this was an rgba parse the assignment might happen twice
13940 inst[ spaces[ spaceName ].cache ] = parsed[ spaces[ spaceName ].cache ];
13941 rgba = inst._rgba = parsed._rgba;
13943 // exit each( stringParsers ) here because we matched
13948 // Found a stringParser that handled it
13949 if ( rgba.length ) {
13951 // if this came from a parsed string, force "transparent" when alpha is 0
13952 // chrome, (and maybe others) return "transparent" as rgba(0,0,0,0)
13953 if ( rgba.join() === "0,0,0,0" ) {
13954 jQuery.extend( rgba, colors.transparent );
13960 return colors[ string ];
13963 color.fn = jQuery.extend( color.prototype, {
13964 parse: function( red, green, blue, alpha ) {
13965 if ( red === undefined ) {
13966 this._rgba = [ null, null, null, null ];
13969 if ( red.jquery || red.nodeType ) {
13970 red = jQuery( red ).css( green );
13975 type = jQuery.type( red ),
13976 rgba = this._rgba = [];
13978 // more than 1 argument specified - assume ( red, green, blue, alpha )
13979 if ( green !== undefined ) {
13980 red = [ red, green, blue, alpha ];
13984 if ( type === "string" ) {
13985 return this.parse( stringParse( red ) || colors._default );
13988 if ( type === "array" ) {
13989 each( spaces.rgba.props, function( key, prop ) {
13990 rgba[ prop.idx ] = clamp( red[ prop.idx ], prop );
13995 if ( type === "object" ) {
13996 if ( red instanceof color ) {
13997 each( spaces, function( spaceName, space ) {
13998 if ( red[ space.cache ] ) {
13999 inst[ space.cache ] = red[ space.cache ].slice();
14003 each( spaces, function( spaceName, space ) {
14004 var cache = space.cache;
14005 each( space.props, function( key, prop ) {
14007 // if the cache doesn't exist, and we know how to convert
14008 if ( !inst[ cache ] && space.to ) {
14010 // if the value was null, we don't need to copy it
14011 // if the key was alpha, we don't need to copy it either
14012 if ( key === "alpha" || red[ key ] == null ) {
14015 inst[ cache ] = space.to( inst._rgba );
14018 // this is the only case where we allow nulls for ALL properties.
14019 // call clamp with alwaysAllowEmpty
14020 inst[ cache ][ prop.idx ] = clamp( red[ key ], prop, true );
14023 // everything defined but alpha?
14024 if ( inst[ cache ] && jQuery.inArray( null, inst[ cache ].slice( 0, 3 ) ) < 0 ) {
14025 // use the default of 1
14026 inst[ cache ][ 3 ] = 1;
14027 if ( space.from ) {
14028 inst._rgba = space.from( inst[ cache ] );
14036 is: function( compare ) {
14037 var is = color( compare ),
14041 each( spaces, function( _, space ) {
14043 isCache = is[ space.cache ];
14045 localCache = inst[ space.cache ] || space.to && space.to( inst._rgba ) || [];
14046 each( space.props, function( _, prop ) {
14047 if ( isCache[ prop.idx ] != null ) {
14048 same = ( isCache[ prop.idx ] === localCache[ prop.idx ] );
14057 _space: function() {
14060 each( spaces, function( spaceName, space ) {
14061 if ( inst[ space.cache ] ) {
14062 used.push( spaceName );
14067 transition: function( other, distance ) {
14068 var end = color( other ),
14069 spaceName = end._space(),
14070 space = spaces[ spaceName ],
14071 startColor = this.alpha() === 0 ? color( "transparent" ) : this,
14072 start = startColor[ space.cache ] || space.to( startColor._rgba ),
14073 result = start.slice();
14075 end = end[ space.cache ];
14076 each( space.props, function( key, prop ) {
14077 var index = prop.idx,
14078 startValue = start[ index ],
14079 endValue = end[ index ],
14080 type = propTypes[ prop.type ] || {};
14082 // if null, don't override start value
14083 if ( endValue === null ) {
14086 // if null - use end
14087 if ( startValue === null ) {
14088 result[ index ] = endValue;
14091 if ( endValue - startValue > type.mod / 2 ) {
14092 startValue += type.mod;
14093 } else if ( startValue - endValue > type.mod / 2 ) {
14094 startValue -= type.mod;
14097 result[ index ] = clamp( ( endValue - startValue ) * distance + startValue, prop );
14100 return this[ spaceName ]( result );
14102 blend: function( opaque ) {
14103 // if we are already opaque - return ourself
14104 if ( this._rgba[ 3 ] === 1 ) {
14108 var rgb = this._rgba.slice(),
14110 blend = color( opaque )._rgba;
14112 return color( jQuery.map( rgb, function( v, i ) {
14113 return ( 1 - a ) * blend[ i ] + a * v;
14116 toRgbaString: function() {
14117 var prefix = "rgba(",
14118 rgba = jQuery.map( this._rgba, function( v, i ) {
14119 return v == null ? ( i > 2 ? 1 : 0 ) : v;
14122 if ( rgba[ 3 ] === 1 ) {
14127 return prefix + rgba.join() + ")";
14129 toHslaString: function() {
14130 var prefix = "hsla(",
14131 hsla = jQuery.map( this.hsla(), function( v, i ) {
14137 if ( i && i < 3 ) {
14138 v = Math.round( v * 100 ) + "%";
14143 if ( hsla[ 3 ] === 1 ) {
14147 return prefix + hsla.join() + ")";
14149 toHexString: function( includeAlpha ) {
14150 var rgba = this._rgba.slice(),
14151 alpha = rgba.pop();
14153 if ( includeAlpha ) {
14154 rgba.push( ~~( alpha * 255 ) );
14157 return "#" + jQuery.map( rgba, function( v ) {
14159 // default to 0 when nulls exist
14160 v = ( v || 0 ).toString( 16 );
14161 return v.length === 1 ? "0" + v : v;
14164 toString: function() {
14165 return this._rgba[ 3 ] === 0 ? "transparent" : this.toRgbaString();
14168 color.fn.parse.prototype = color.fn;
14170 // hsla conversions adapted from:
14171 // https://code.google.com/p/maashaack/source/browse/packages/graphics/trunk/src/graphics/colors/HUE2RGB.as?r=5021
14173 function hue2rgb( p, q, h ) {
14176 return p + ( q - p ) * h * 6;
14182 return p + ( q - p ) * ( ( 2 / 3 ) - h ) * 6;
14187 spaces.hsla.to = function( rgba ) {
14188 if ( rgba[ 0 ] == null || rgba[ 1 ] == null || rgba[ 2 ] == null ) {
14189 return [ null, null, null, rgba[ 3 ] ];
14191 var r = rgba[ 0 ] / 255,
14192 g = rgba[ 1 ] / 255,
14193 b = rgba[ 2 ] / 255,
14195 max = Math.max( r, g, b ),
14196 min = Math.min( r, g, b ),
14202 if ( min === max ) {
14204 } else if ( r === max ) {
14205 h = ( 60 * ( g - b ) / diff ) + 360;
14206 } else if ( g === max ) {
14207 h = ( 60 * ( b - r ) / diff ) + 120;
14209 h = ( 60 * ( r - g ) / diff ) + 240;
14212 // chroma (diff) == 0 means greyscale which, by definition, saturation = 0%
14213 // otherwise, saturation is based on the ratio of chroma (diff) to lightness (add)
14214 if ( diff === 0 ) {
14216 } else if ( l <= 0.5 ) {
14219 s = diff / ( 2 - add );
14221 return [ Math.round(h) % 360, s, l, a == null ? 1 : a ];
14224 spaces.hsla.from = function( hsla ) {
14225 if ( hsla[ 0 ] == null || hsla[ 1 ] == null || hsla[ 2 ] == null ) {
14226 return [ null, null, null, hsla[ 3 ] ];
14228 var h = hsla[ 0 ] / 360,
14232 q = l <= 0.5 ? l * ( 1 + s ) : l + s - l * s,
14236 Math.round( hue2rgb( p, q, h + ( 1 / 3 ) ) * 255 ),
14237 Math.round( hue2rgb( p, q, h ) * 255 ),
14238 Math.round( hue2rgb( p, q, h - ( 1 / 3 ) ) * 255 ),
14243 each( spaces, function( spaceName, space ) {
14244 var props = space.props,
14245 cache = space.cache,
14249 // makes rgba() and hsla()
14250 color.fn[ spaceName ] = function( value ) {
14252 // generate a cache for this space if it doesn't exist
14253 if ( to && !this[ cache ] ) {
14254 this[ cache ] = to( this._rgba );
14256 if ( value === undefined ) {
14257 return this[ cache ].slice();
14261 type = jQuery.type( value ),
14262 arr = ( type === "array" || type === "object" ) ? value : arguments,
14263 local = this[ cache ].slice();
14265 each( props, function( key, prop ) {
14266 var val = arr[ type === "object" ? key : prop.idx ];
14267 if ( val == null ) {
14268 val = local[ prop.idx ];
14270 local[ prop.idx ] = clamp( val, prop );
14274 ret = color( from( local ) );
14275 ret[ cache ] = local;
14278 return color( local );
14282 // makes red() green() blue() alpha() hue() saturation() lightness()
14283 each( props, function( key, prop ) {
14284 // alpha is included in more than one space
14285 if ( color.fn[ key ] ) {
14288 color.fn[ key ] = function( value ) {
14289 var vtype = jQuery.type( value ),
14290 fn = ( key === "alpha" ? ( this._hsla ? "hsla" : "rgba" ) : spaceName ),
14291 local = this[ fn ](),
14292 cur = local[ prop.idx ],
14295 if ( vtype === "undefined" ) {
14299 if ( vtype === "function" ) {
14300 value = value.call( this, cur );
14301 vtype = jQuery.type( value );
14303 if ( value == null && prop.empty ) {
14306 if ( vtype === "string" ) {
14307 match = rplusequals.exec( value );
14309 value = cur + parseFloat( match[ 2 ] ) * ( match[ 1 ] === "+" ? 1 : -1 );
14312 local[ prop.idx ] = value;
14313 return this[ fn ]( local );
14318 // add cssHook and .fx.step function for each named hook.
14319 // accept a space separated string of properties
14320 color.hook = function( hook ) {
14321 var hooks = hook.split( " " );
14322 each( hooks, function( i, hook ) {
14323 jQuery.cssHooks[ hook ] = {
14324 set: function( elem, value ) {
14325 var parsed, curElem,
14326 backgroundColor = "";
14328 if ( value !== "transparent" && ( jQuery.type( value ) !== "string" || ( parsed = stringParse( value ) ) ) ) {
14329 value = color( parsed || value );
14330 if ( !support.rgba && value._rgba[ 3 ] !== 1 ) {
14331 curElem = hook === "backgroundColor" ? elem.parentNode : elem;
14333 (backgroundColor === "" || backgroundColor === "transparent") &&
14334 curElem && curElem.style
14337 backgroundColor = jQuery.css( curElem, "backgroundColor" );
14338 curElem = curElem.parentNode;
14343 value = value.blend( backgroundColor && backgroundColor !== "transparent" ?
14348 value = value.toRgbaString();
14351 elem.style[ hook ] = value;
14353 // wrapped to prevent IE from throwing errors on "invalid" values like 'auto' or 'inherit'
14357 jQuery.fx.step[ hook ] = function( fx ) {
14358 if ( !fx.colorInit ) {
14359 fx.start = color( fx.elem, hook );
14360 fx.end = color( fx.end );
14361 fx.colorInit = true;
14363 jQuery.cssHooks[ hook ].set( fx.elem, fx.start.transition( fx.end, fx.pos ) );
14369 color.hook( stepHooks );
14371 jQuery.cssHooks.borderColor = {
14372 expand: function( value ) {
14375 each( [ "Top", "Right", "Bottom", "Left" ], function( i, part ) {
14376 expanded[ "border" + part + "Color" ] = value;
14382 // Basic color names only.
14383 // Usage of any of the other color names requires adding yourself or including
14384 // jquery.color.svg-names.js.
14385 colors = jQuery.Color.names = {
14386 // 4.1. Basic color keywords
14390 fuchsia: "#ff00ff",
14404 // 4.2.3. "transparent" color keyword
14405 transparent: [ null, null, null, 0 ],
14407 _default: "#ffffff"
14412 /******************************************************************************/
14413 /****************************** CLASS ANIMATIONS ******************************/
14414 /******************************************************************************/
14417 var classAnimationActions = [ "add", "remove", "toggle" ],
14418 shorthandStyles = {
14430 $.each([ "borderLeftStyle", "borderRightStyle", "borderBottomStyle", "borderTopStyle" ], function( _, prop ) {
14431 $.fx.step[ prop ] = function( fx ) {
14432 if ( fx.end !== "none" && !fx.setAttr || fx.pos === 1 && !fx.setAttr ) {
14433 jQuery.style( fx.elem, prop, fx.end );
14439 function getElementStyles( elem ) {
14441 style = elem.ownerDocument.defaultView ?
14442 elem.ownerDocument.defaultView.getComputedStyle( elem, null ) :
14446 if ( style && style.length && style[ 0 ] && style[ style[ 0 ] ] ) {
14447 len = style.length;
14449 key = style[ len ];
14450 if ( typeof style[ key ] === "string" ) {
14451 styles[ $.camelCase( key ) ] = style[ key ];
14454 // support: Opera, IE <9
14456 for ( key in style ) {
14457 if ( typeof style[ key ] === "string" ) {
14458 styles[ key ] = style[ key ];
14466 function styleDifference( oldStyle, newStyle ) {
14470 for ( name in newStyle ) {
14471 value = newStyle[ name ];
14472 if ( oldStyle[ name ] !== value ) {
14473 if ( !shorthandStyles[ name ] ) {
14474 if ( $.fx.step[ name ] || !isNaN( parseFloat( value ) ) ) {
14475 diff[ name ] = value;
14484 // support: jQuery <1.8
14485 if ( !$.fn.addBack ) {
14486 $.fn.addBack = function( selector ) {
14487 return this.add( selector == null ?
14488 this.prevObject : this.prevObject.filter( selector )
14493 $.effects.animateClass = function( value, duration, easing, callback ) {
14494 var o = $.speed( duration, easing, callback );
14496 return this.queue( function() {
14497 var animated = $( this ),
14498 baseClass = animated.attr( "class" ) || "",
14500 allAnimations = o.children ? animated.find( "*" ).addBack() : animated;
14502 // map the animated objects to store the original styles.
14503 allAnimations = allAnimations.map(function() {
14504 var el = $( this );
14507 start: getElementStyles( this )
14511 // apply class change
14512 applyClassChange = function() {
14513 $.each( classAnimationActions, function(i, action) {
14514 if ( value[ action ] ) {
14515 animated[ action + "Class" ]( value[ action ] );
14519 applyClassChange();
14521 // map all animated objects again - calculate new styles and diff
14522 allAnimations = allAnimations.map(function() {
14523 this.end = getElementStyles( this.el[ 0 ] );
14524 this.diff = styleDifference( this.start, this.end );
14528 // apply original class
14529 animated.attr( "class", baseClass );
14531 // map all animated objects again - this time collecting a promise
14532 allAnimations = allAnimations.map(function() {
14533 var styleInfo = this,
14534 dfd = $.Deferred(),
14535 opts = $.extend({}, o, {
14537 complete: function() {
14538 dfd.resolve( styleInfo );
14542 this.el.animate( this.diff, opts );
14543 return dfd.promise();
14546 // once all animations have completed:
14547 $.when.apply( $, allAnimations.get() ).done(function() {
14549 // set the final class
14550 applyClassChange();
14552 // for each animated element,
14553 // clear all css properties that were animated
14554 $.each( arguments, function() {
14556 $.each( this.diff, function(key) {
14561 // this is guarnteed to be there if you use jQuery.speed()
14562 // it also handles dequeuing the next anim...
14563 o.complete.call( animated[ 0 ] );
14569 addClass: (function( orig ) {
14570 return function( classNames, speed, easing, callback ) {
14572 $.effects.animateClass.call( this,
14573 { add: classNames }, speed, easing, callback ) :
14574 orig.apply( this, arguments );
14576 })( $.fn.addClass ),
14578 removeClass: (function( orig ) {
14579 return function( classNames, speed, easing, callback ) {
14580 return arguments.length > 1 ?
14581 $.effects.animateClass.call( this,
14582 { remove: classNames }, speed, easing, callback ) :
14583 orig.apply( this, arguments );
14585 })( $.fn.removeClass ),
14587 toggleClass: (function( orig ) {
14588 return function( classNames, force, speed, easing, callback ) {
14589 if ( typeof force === "boolean" || force === undefined ) {
14591 // without speed parameter
14592 return orig.apply( this, arguments );
14594 return $.effects.animateClass.call( this,
14595 (force ? { add: classNames } : { remove: classNames }),
14596 speed, easing, callback );
14599 // without force parameter
14600 return $.effects.animateClass.call( this,
14601 { toggle: classNames }, force, speed, easing );
14604 })( $.fn.toggleClass ),
14606 switchClass: function( remove, add, speed, easing, callback) {
14607 return $.effects.animateClass.call( this, {
14610 }, speed, easing, callback );
14616 /******************************************************************************/
14617 /*********************************** EFFECTS **********************************/
14618 /******************************************************************************/
14622 $.extend( $.effects, {
14625 // Saves a set of properties in a data storage
14626 save: function( element, set ) {
14627 for ( var i = 0; i < set.length; i++ ) {
14628 if ( set[ i ] !== null ) {
14629 element.data( dataSpace + set[ i ], element[ 0 ].style[ set[ i ] ] );
14634 // Restores a set of previously saved properties from a data storage
14635 restore: function( element, set ) {
14637 for ( i = 0; i < set.length; i++ ) {
14638 if ( set[ i ] !== null ) {
14639 val = element.data( dataSpace + set[ i ] );
14640 // support: jQuery 1.6.2
14641 // http://bugs.jquery.com/ticket/9917
14642 // jQuery 1.6.2 incorrectly returns undefined for any falsy value.
14643 // We can't differentiate between "" and 0 here, so we just assume
14644 // empty string since it's likely to be a more common value...
14645 if ( val === undefined ) {
14648 element.css( set[ i ], val );
14653 setMode: function( el, mode ) {
14654 if (mode === "toggle") {
14655 mode = el.is( ":hidden" ) ? "show" : "hide";
14660 // Translates a [top,left] array into a baseline value
14661 // this should be a little more flexible in the future to handle a string & hash
14662 getBaseline: function( origin, original ) {
14664 switch ( origin[ 0 ] ) {
14665 case "top": y = 0; break;
14666 case "middle": y = 0.5; break;
14667 case "bottom": y = 1; break;
14668 default: y = origin[ 0 ] / original.height;
14670 switch ( origin[ 1 ] ) {
14671 case "left": x = 0; break;
14672 case "center": x = 0.5; break;
14673 case "right": x = 1; break;
14674 default: x = origin[ 1 ] / original.width;
14682 // Wraps the element around a wrapper that copies position properties
14683 createWrapper: function( element ) {
14685 // if the element is already wrapped, return it
14686 if ( element.parent().is( ".ui-effects-wrapper" )) {
14687 return element.parent();
14690 // wrap the element
14692 width: element.outerWidth(true),
14693 height: element.outerHeight(true),
14694 "float": element.css( "float" )
14696 wrapper = $( "<div></div>" )
14697 .addClass( "ui-effects-wrapper" )
14700 background: "transparent",
14705 // Store the size in case width/height are defined in % - Fixes #5245
14707 width: element.width(),
14708 height: element.height()
14710 active = document.activeElement;
14712 // support: Firefox
14713 // Firefox incorrectly exposes anonymous content
14714 // https://bugzilla.mozilla.org/show_bug.cgi?id=561664
14718 active = document.body;
14721 element.wrap( wrapper );
14723 // Fixes #7595 - Elements lose focus when wrapped.
14724 if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
14725 $( active ).focus();
14728 wrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually lose the reference to the wrapped element
14730 // transfer positioning properties to the wrapper
14731 if ( element.css( "position" ) === "static" ) {
14732 wrapper.css({ position: "relative" });
14733 element.css({ position: "relative" });
14736 position: element.css( "position" ),
14737 zIndex: element.css( "z-index" )
14739 $.each([ "top", "left", "bottom", "right" ], function(i, pos) {
14740 props[ pos ] = element.css( pos );
14741 if ( isNaN( parseInt( props[ pos ], 10 ) ) ) {
14742 props[ pos ] = "auto";
14746 position: "relative",
14755 return wrapper.css( props ).show();
14758 removeWrapper: function( element ) {
14759 var active = document.activeElement;
14761 if ( element.parent().is( ".ui-effects-wrapper" ) ) {
14762 element.parent().replaceWith( element );
14764 // Fixes #7595 - Elements lose focus when wrapped.
14765 if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
14766 $( active ).focus();
14773 setTransition: function( element, list, factor, value ) {
14774 value = value || {};
14775 $.each( list, function( i, x ) {
14776 var unit = element.cssUnit( x );
14777 if ( unit[ 0 ] > 0 ) {
14778 value[ x ] = unit[ 0 ] * factor + unit[ 1 ];
14785 // return an effect options object for the given parameters:
14786 function _normalizeArguments( effect, options, speed, callback ) {
14788 // allow passing all options as the first parameter
14789 if ( $.isPlainObject( effect ) ) {
14791 effect = effect.effect;
14794 // convert to an object
14795 effect = { effect: effect };
14797 // catch (effect, null, ...)
14798 if ( options == null ) {
14802 // catch (effect, callback)
14803 if ( $.isFunction( options ) ) {
14804 callback = options;
14809 // catch (effect, speed, ?)
14810 if ( typeof options === "number" || $.fx.speeds[ options ] ) {
14816 // catch (effect, options, callback)
14817 if ( $.isFunction( speed ) ) {
14822 // add options to effect
14824 $.extend( effect, options );
14827 speed = speed || options.duration;
14828 effect.duration = $.fx.off ? 0 :
14829 typeof speed === "number" ? speed :
14830 speed in $.fx.speeds ? $.fx.speeds[ speed ] :
14831 $.fx.speeds._default;
14833 effect.complete = callback || options.complete;
14838 function standardAnimationOption( option ) {
14839 // Valid standard speeds (nothing, number, named speed)
14840 if ( !option || typeof option === "number" || $.fx.speeds[ option ] ) {
14844 // Invalid strings - treat as "normal" speed
14845 if ( typeof option === "string" && !$.effects.effect[ option ] ) {
14849 // Complete callback
14850 if ( $.isFunction( option ) ) {
14854 // Options hash (but not naming an effect)
14855 if ( typeof option === "object" && !option.effect ) {
14859 // Didn't match any standard API
14864 effect: function( /* effect, options, speed, callback */ ) {
14865 var args = _normalizeArguments.apply( this, arguments ),
14867 queue = args.queue,
14868 effectMethod = $.effects.effect[ args.effect ];
14870 if ( $.fx.off || !effectMethod ) {
14871 // delegate to the original method (e.g., .show()) if possible
14873 return this[ mode ]( args.duration, args.complete );
14875 return this.each( function() {
14876 if ( args.complete ) {
14877 args.complete.call( this );
14883 function run( next ) {
14884 var elem = $( this ),
14885 complete = args.complete,
14889 if ( $.isFunction( complete ) ) {
14890 complete.call( elem[0] );
14892 if ( $.isFunction( next ) ) {
14897 // If the element already has the correct final state, delegate to
14898 // the core methods so the internal tracking of "olddisplay" works.
14899 if ( elem.is( ":hidden" ) ? mode === "hide" : mode === "show" ) {
14903 effectMethod.call( elem[0], args, done );
14907 return queue === false ? this.each( run ) : this.queue( queue || "fx", run );
14910 show: (function( orig ) {
14911 return function( option ) {
14912 if ( standardAnimationOption( option ) ) {
14913 return orig.apply( this, arguments );
14915 var args = _normalizeArguments.apply( this, arguments );
14916 args.mode = "show";
14917 return this.effect.call( this, args );
14922 hide: (function( orig ) {
14923 return function( option ) {
14924 if ( standardAnimationOption( option ) ) {
14925 return orig.apply( this, arguments );
14927 var args = _normalizeArguments.apply( this, arguments );
14928 args.mode = "hide";
14929 return this.effect.call( this, args );
14934 toggle: (function( orig ) {
14935 return function( option ) {
14936 if ( standardAnimationOption( option ) || typeof option === "boolean" ) {
14937 return orig.apply( this, arguments );
14939 var args = _normalizeArguments.apply( this, arguments );
14940 args.mode = "toggle";
14941 return this.effect.call( this, args );
14946 // helper functions
14947 cssUnit: function(key) {
14948 var style = this.css( key ),
14951 $.each( [ "em", "px", "%", "pt" ], function( i, unit ) {
14952 if ( style.indexOf( unit ) > 0 ) {
14953 val = [ parseFloat( style ), unit ];
14962 /******************************************************************************/
14963 /*********************************** EASING ***********************************/
14964 /******************************************************************************/
14968 // based on easing equations from Robert Penner (http://www.robertpenner.com/easing)
14970 var baseEasings = {};
14972 $.each( [ "Quad", "Cubic", "Quart", "Quint", "Expo" ], function( i, name ) {
14973 baseEasings[ name ] = function( p ) {
14974 return Math.pow( p, i + 2 );
14978 $.extend( baseEasings, {
14979 Sine: function( p ) {
14980 return 1 - Math.cos( p * Math.PI / 2 );
14982 Circ: function( p ) {
14983 return 1 - Math.sqrt( 1 - p * p );
14985 Elastic: function( p ) {
14986 return p === 0 || p === 1 ? p :
14987 -Math.pow( 2, 8 * (p - 1) ) * Math.sin( ( (p - 1) * 80 - 7.5 ) * Math.PI / 15 );
14989 Back: function( p ) {
14990 return p * p * ( 3 * p - 2 );
14992 Bounce: function( p ) {
14996 while ( p < ( ( pow2 = Math.pow( 2, --bounce ) ) - 1 ) / 11 ) {}
14997 return 1 / Math.pow( 4, 3 - bounce ) - 7.5625 * Math.pow( ( pow2 * 3 - 2 ) / 22 - p, 2 );
15001 $.each( baseEasings, function( name, easeIn ) {
15002 $.easing[ "easeIn" + name ] = easeIn;
15003 $.easing[ "easeOut" + name ] = function( p ) {
15004 return 1 - easeIn( 1 - p );
15006 $.easing[ "easeInOut" + name ] = function( p ) {
15008 easeIn( p * 2 ) / 2 :
15009 1 - easeIn( p * -2 + 2 ) / 2;
15015 var effect = $.effects;
15019 * jQuery UI Effects Blind 1.11.0
15020 * http://jqueryui.com
15022 * Copyright 2014 jQuery Foundation and other contributors
15023 * Released under the MIT license.
15024 * http://jquery.org/license
15026 * http://api.jqueryui.com/blind-effect/
15030 var effectBlind = $.effects.effect.blind = function( o, done ) {
15032 var el = $( this ),
15033 rvertical = /up|down|vertical/,
15034 rpositivemotion = /up|left|vertical|horizontal/,
15035 props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
15036 mode = $.effects.setMode( el, o.mode || "hide" ),
15037 direction = o.direction || "up",
15038 vertical = rvertical.test( direction ),
15039 ref = vertical ? "height" : "width",
15040 ref2 = vertical ? "top" : "left",
15041 motion = rpositivemotion.test( direction ),
15043 show = mode === "show",
15044 wrapper, distance, margin;
15046 // if already wrapped, the wrapper's properties are my property. #6245
15047 if ( el.parent().is( ".ui-effects-wrapper" ) ) {
15048 $.effects.save( el.parent(), props );
15050 $.effects.save( el, props );
15053 wrapper = $.effects.createWrapper( el ).css({
15057 distance = wrapper[ ref ]();
15058 margin = parseFloat( wrapper.css( ref2 ) ) || 0;
15060 animation[ ref ] = show ? distance : 0;
15063 .css( vertical ? "bottom" : "right", 0 )
15064 .css( vertical ? "top" : "left", "auto" )
15065 .css({ position: "absolute" });
15067 animation[ ref2 ] = show ? margin : distance + margin;
15070 // start at 0 if we are showing
15072 wrapper.css( ref, 0 );
15074 wrapper.css( ref2, margin + distance );
15079 wrapper.animate( animation, {
15080 duration: o.duration,
15083 complete: function() {
15084 if ( mode === "hide" ) {
15087 $.effects.restore( el, props );
15088 $.effects.removeWrapper( el );
15096 * jQuery UI Effects Bounce 1.11.0
15097 * http://jqueryui.com
15099 * Copyright 2014 jQuery Foundation and other contributors
15100 * Released under the MIT license.
15101 * http://jquery.org/license
15103 * http://api.jqueryui.com/bounce-effect/
15107 var effectBounce = $.effects.effect.bounce = function( o, done ) {
15108 var el = $( this ),
15109 props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
15112 mode = $.effects.setMode( el, o.mode || "effect" ),
15113 hide = mode === "hide",
15114 show = mode === "show",
15115 direction = o.direction || "up",
15116 distance = o.distance,
15117 times = o.times || 5,
15119 // number of internal animations
15120 anims = times * 2 + ( show || hide ? 1 : 0 ),
15121 speed = o.duration / anims,
15125 ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
15126 motion = ( direction === "up" || direction === "left" ),
15131 // we will need to re-assemble the queue to stack our animations in place
15132 queue = el.queue(),
15133 queuelen = queue.length;
15135 // Avoid touching opacity to prevent clearType and PNG issues in IE
15136 if ( show || hide ) {
15137 props.push( "opacity" );
15140 $.effects.save( el, props );
15142 $.effects.createWrapper( el ); // Create Wrapper
15144 // default distance for the BIGGEST bounce is the outer Distance / 3
15146 distance = el[ ref === "top" ? "outerHeight" : "outerWidth" ]() / 3;
15150 downAnim = { opacity: 1 };
15151 downAnim[ ref ] = 0;
15153 // if we are showing, force opacity 0 and set the initial position
15154 // then do the "first" animation
15155 el.css( "opacity", 0 )
15156 .css( ref, motion ? -distance * 2 : distance * 2 )
15157 .animate( downAnim, speed, easing );
15160 // start at the smallest distance if we are hiding
15162 distance = distance / Math.pow( 2, times - 1 );
15166 downAnim[ ref ] = 0;
15167 // Bounces up/down/left/right then back to 0 -- times * 2 animations happen here
15168 for ( i = 0; i < times; i++ ) {
15170 upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance;
15172 el.animate( upAnim, speed, easing )
15173 .animate( downAnim, speed, easing );
15175 distance = hide ? distance * 2 : distance / 2;
15178 // Last Bounce when Hiding
15180 upAnim = { opacity: 0 };
15181 upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance;
15183 el.animate( upAnim, speed, easing );
15186 el.queue(function() {
15190 $.effects.restore( el, props );
15191 $.effects.removeWrapper( el );
15195 // inject all the animations we just queued to be first in line (after "inprogress")
15196 if ( queuelen > 1) {
15197 queue.splice.apply( queue,
15198 [ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) );
15206 * jQuery UI Effects Clip 1.11.0
15207 * http://jqueryui.com
15209 * Copyright 2014 jQuery Foundation and other contributors
15210 * Released under the MIT license.
15211 * http://jquery.org/license
15213 * http://api.jqueryui.com/clip-effect/
15217 var effectClip = $.effects.effect.clip = function( o, done ) {
15219 var el = $( this ),
15220 props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
15221 mode = $.effects.setMode( el, o.mode || "hide" ),
15222 show = mode === "show",
15223 direction = o.direction || "vertical",
15224 vert = direction === "vertical",
15225 size = vert ? "height" : "width",
15226 position = vert ? "top" : "left",
15228 wrapper, animate, distance;
15231 $.effects.save( el, props );
15235 wrapper = $.effects.createWrapper( el ).css({
15238 animate = ( el[0].tagName === "IMG" ) ? wrapper : el;
15239 distance = animate[ size ]();
15243 animate.css( size, 0 );
15244 animate.css( position, distance / 2 );
15247 // Create Animation Object:
15248 animation[ size ] = show ? distance : 0;
15249 animation[ position ] = show ? 0 : distance / 2;
15252 animate.animate( animation, {
15254 duration: o.duration,
15256 complete: function() {
15260 $.effects.restore( el, props );
15261 $.effects.removeWrapper( el );
15270 * jQuery UI Effects Drop 1.11.0
15271 * http://jqueryui.com
15273 * Copyright 2014 jQuery Foundation and other contributors
15274 * Released under the MIT license.
15275 * http://jquery.org/license
15277 * http://api.jqueryui.com/drop-effect/
15281 var effectDrop = $.effects.effect.drop = function( o, done ) {
15283 var el = $( this ),
15284 props = [ "position", "top", "bottom", "left", "right", "opacity", "height", "width" ],
15285 mode = $.effects.setMode( el, o.mode || "hide" ),
15286 show = mode === "show",
15287 direction = o.direction || "left",
15288 ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
15289 motion = ( direction === "up" || direction === "left" ) ? "pos" : "neg",
15291 opacity: show ? 1 : 0
15296 $.effects.save( el, props );
15298 $.effects.createWrapper( el );
15300 distance = o.distance || el[ ref === "top" ? "outerHeight": "outerWidth" ]( true ) / 2;
15304 .css( "opacity", 0 )
15305 .css( ref, motion === "pos" ? -distance : distance );
15309 animation[ ref ] = ( show ?
15310 ( motion === "pos" ? "+=" : "-=" ) :
15311 ( motion === "pos" ? "-=" : "+=" ) ) +
15315 el.animate( animation, {
15317 duration: o.duration,
15319 complete: function() {
15320 if ( mode === "hide" ) {
15323 $.effects.restore( el, props );
15324 $.effects.removeWrapper( el );
15332 * jQuery UI Effects Explode 1.11.0
15333 * http://jqueryui.com
15335 * Copyright 2014 jQuery Foundation and other contributors
15336 * Released under the MIT license.
15337 * http://jquery.org/license
15339 * http://api.jqueryui.com/explode-effect/
15343 var effectExplode = $.effects.effect.explode = function( o, done ) {
15345 var rows = o.pieces ? Math.round( Math.sqrt( o.pieces ) ) : 3,
15348 mode = $.effects.setMode( el, o.mode || "hide" ),
15349 show = mode === "show",
15351 // show and then visibility:hidden the element before calculating offset
15352 offset = el.show().css( "visibility", "hidden" ).offset(),
15354 // width and height of a piece
15355 width = Math.ceil( el.outerWidth() / cells ),
15356 height = Math.ceil( el.outerHeight() / rows ),
15360 i, j, left, top, mx, my;
15362 // children animate complete:
15363 function childComplete() {
15364 pieces.push( this );
15365 if ( pieces.length === rows * cells ) {
15370 // clone the element for each row and cell.
15371 for ( i = 0; i < rows ; i++ ) { // ===>
15372 top = offset.top + i * height;
15373 my = i - ( rows - 1 ) / 2 ;
15375 for ( j = 0; j < cells ; j++ ) { // |||
15376 left = offset.left + j * width;
15377 mx = j - ( cells - 1 ) / 2 ;
15379 // Create a clone of the now hidden main element that will be absolute positioned
15380 // within a wrapper div off the -left and -top equal to size of our pieces
15383 .appendTo( "body" )
15384 .wrap( "<div></div>" )
15386 position: "absolute",
15387 visibility: "visible",
15392 // select the wrapper - make it overflow: hidden and absolute positioned based on
15393 // where the original was located +left and +top equal to the size of pieces
15395 .addClass( "ui-effects-explode" )
15397 position: "absolute",
15398 overflow: "hidden",
15401 left: left + ( show ? mx * width : 0 ),
15402 top: top + ( show ? my * height : 0 ),
15403 opacity: show ? 0 : 1
15405 left: left + ( show ? 0 : mx * width ),
15406 top: top + ( show ? 0 : my * height ),
15407 opacity: show ? 1 : 0
15408 }, o.duration || 500, o.easing, childComplete );
15412 function animComplete() {
15414 visibility: "visible"
15416 $( pieces ).remove();
15426 * jQuery UI Effects Fade 1.11.0
15427 * http://jqueryui.com
15429 * Copyright 2014 jQuery Foundation and other contributors
15430 * Released under the MIT license.
15431 * http://jquery.org/license
15433 * http://api.jqueryui.com/fade-effect/
15437 var effectFade = $.effects.effect.fade = function( o, done ) {
15438 var el = $( this ),
15439 mode = $.effects.setMode( el, o.mode || "toggle" );
15445 duration: o.duration,
15453 * jQuery UI Effects Fold 1.11.0
15454 * http://jqueryui.com
15456 * Copyright 2014 jQuery Foundation and other contributors
15457 * Released under the MIT license.
15458 * http://jquery.org/license
15460 * http://api.jqueryui.com/fold-effect/
15464 var effectFold = $.effects.effect.fold = function( o, done ) {
15467 var el = $( this ),
15468 props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
15469 mode = $.effects.setMode( el, o.mode || "hide" ),
15470 show = mode === "show",
15471 hide = mode === "hide",
15472 size = o.size || 15,
15473 percent = /([0-9]+)%/.exec( size ),
15474 horizFirst = !!o.horizFirst,
15475 widthFirst = show !== horizFirst,
15476 ref = widthFirst ? [ "width", "height" ] : [ "height", "width" ],
15477 duration = o.duration / 2,
15482 $.effects.save( el, props );
15486 wrapper = $.effects.createWrapper( el ).css({
15489 distance = widthFirst ?
15490 [ wrapper.width(), wrapper.height() ] :
15491 [ wrapper.height(), wrapper.width() ];
15494 size = parseInt( percent[ 1 ], 10 ) / 100 * distance[ hide ? 0 : 1 ];
15497 wrapper.css( horizFirst ? {
15507 animation1[ ref[ 0 ] ] = show ? distance[ 0 ] : size;
15508 animation2[ ref[ 1 ] ] = show ? distance[ 1 ] : 0;
15512 .animate( animation1, duration, o.easing )
15513 .animate( animation2, duration, o.easing, function() {
15517 $.effects.restore( el, props );
15518 $.effects.removeWrapper( el );
15526 * jQuery UI Effects Highlight 1.11.0
15527 * http://jqueryui.com
15529 * Copyright 2014 jQuery Foundation and other contributors
15530 * Released under the MIT license.
15531 * http://jquery.org/license
15533 * http://api.jqueryui.com/highlight-effect/
15537 var effectHighlight = $.effects.effect.highlight = function( o, done ) {
15538 var elem = $( this ),
15539 props = [ "backgroundImage", "backgroundColor", "opacity" ],
15540 mode = $.effects.setMode( elem, o.mode || "show" ),
15542 backgroundColor: elem.css( "backgroundColor" )
15545 if (mode === "hide") {
15546 animation.opacity = 0;
15549 $.effects.save( elem, props );
15554 backgroundImage: "none",
15555 backgroundColor: o.color || "#ffff99"
15557 .animate( animation, {
15559 duration: o.duration,
15561 complete: function() {
15562 if ( mode === "hide" ) {
15565 $.effects.restore( elem, props );
15573 * jQuery UI Effects Size 1.11.0
15574 * http://jqueryui.com
15576 * Copyright 2014 jQuery Foundation and other contributors
15577 * Released under the MIT license.
15578 * http://jquery.org/license
15580 * http://api.jqueryui.com/size-effect/
15584 var effectSize = $.effects.effect.size = function( o, done ) {
15587 var original, baseline, factor,
15589 props0 = [ "position", "top", "bottom", "left", "right", "width", "height", "overflow", "opacity" ],
15592 props1 = [ "position", "top", "bottom", "left", "right", "overflow", "opacity" ],
15594 // Copy for children
15595 props2 = [ "width", "height", "overflow" ],
15596 cProps = [ "fontSize" ],
15597 vProps = [ "borderTopWidth", "borderBottomWidth", "paddingTop", "paddingBottom" ],
15598 hProps = [ "borderLeftWidth", "borderRightWidth", "paddingLeft", "paddingRight" ],
15601 mode = $.effects.setMode( el, o.mode || "effect" ),
15602 restore = o.restore || mode !== "effect",
15603 scale = o.scale || "both",
15604 origin = o.origin || [ "middle", "center" ],
15605 position = el.css( "position" ),
15606 props = restore ? props0 : props1,
15614 if ( mode === "show" ) {
15618 height: el.height(),
15620 outerHeight: el.outerHeight(),
15621 outerWidth: el.outerWidth()
15624 if ( o.mode === "toggle" && mode === "show" ) {
15625 el.from = o.to || zero;
15626 el.to = o.from || original;
15628 el.from = o.from || ( mode === "show" ? zero : original );
15629 el.to = o.to || ( mode === "hide" ? zero : original );
15632 // Set scaling factor
15635 y: el.from.height / original.height,
15636 x: el.from.width / original.width
15639 y: el.to.height / original.height,
15640 x: el.to.width / original.width
15644 // Scale the css box
15645 if ( scale === "box" || scale === "both" ) {
15647 // Vertical props scaling
15648 if ( factor.from.y !== factor.to.y ) {
15649 props = props.concat( vProps );
15650 el.from = $.effects.setTransition( el, vProps, factor.from.y, el.from );
15651 el.to = $.effects.setTransition( el, vProps, factor.to.y, el.to );
15654 // Horizontal props scaling
15655 if ( factor.from.x !== factor.to.x ) {
15656 props = props.concat( hProps );
15657 el.from = $.effects.setTransition( el, hProps, factor.from.x, el.from );
15658 el.to = $.effects.setTransition( el, hProps, factor.to.x, el.to );
15662 // Scale the content
15663 if ( scale === "content" || scale === "both" ) {
15665 // Vertical props scaling
15666 if ( factor.from.y !== factor.to.y ) {
15667 props = props.concat( cProps ).concat( props2 );
15668 el.from = $.effects.setTransition( el, cProps, factor.from.y, el.from );
15669 el.to = $.effects.setTransition( el, cProps, factor.to.y, el.to );
15673 $.effects.save( el, props );
15675 $.effects.createWrapper( el );
15676 el.css( "overflow", "hidden" ).css( el.from );
15679 if (origin) { // Calculate baseline shifts
15680 baseline = $.effects.getBaseline( origin, original );
15681 el.from.top = ( original.outerHeight - el.outerHeight() ) * baseline.y;
15682 el.from.left = ( original.outerWidth - el.outerWidth() ) * baseline.x;
15683 el.to.top = ( original.outerHeight - el.to.outerHeight ) * baseline.y;
15684 el.to.left = ( original.outerWidth - el.to.outerWidth ) * baseline.x;
15686 el.css( el.from ); // set top & left
15689 if ( scale === "content" || scale === "both" ) { // Scale the children
15691 // Add margins/font-size
15692 vProps = vProps.concat([ "marginTop", "marginBottom" ]).concat(cProps);
15693 hProps = hProps.concat([ "marginLeft", "marginRight" ]);
15694 props2 = props0.concat(vProps).concat(hProps);
15696 el.find( "*[width]" ).each( function() {
15697 var child = $( this ),
15699 height: child.height(),
15700 width: child.width(),
15701 outerHeight: child.outerHeight(),
15702 outerWidth: child.outerWidth()
15705 $.effects.save(child, props2);
15709 height: c_original.height * factor.from.y,
15710 width: c_original.width * factor.from.x,
15711 outerHeight: c_original.outerHeight * factor.from.y,
15712 outerWidth: c_original.outerWidth * factor.from.x
15715 height: c_original.height * factor.to.y,
15716 width: c_original.width * factor.to.x,
15717 outerHeight: c_original.height * factor.to.y,
15718 outerWidth: c_original.width * factor.to.x
15721 // Vertical props scaling
15722 if ( factor.from.y !== factor.to.y ) {
15723 child.from = $.effects.setTransition( child, vProps, factor.from.y, child.from );
15724 child.to = $.effects.setTransition( child, vProps, factor.to.y, child.to );
15727 // Horizontal props scaling
15728 if ( factor.from.x !== factor.to.x ) {
15729 child.from = $.effects.setTransition( child, hProps, factor.from.x, child.from );
15730 child.to = $.effects.setTransition( child, hProps, factor.to.x, child.to );
15733 // Animate children
15734 child.css( child.from );
15735 child.animate( child.to, o.duration, o.easing, function() {
15737 // Restore children
15739 $.effects.restore( child, props2 );
15746 el.animate( el.to, {
15748 duration: o.duration,
15750 complete: function() {
15751 if ( el.to.opacity === 0 ) {
15752 el.css( "opacity", el.from.opacity );
15754 if ( mode === "hide" ) {
15757 $.effects.restore( el, props );
15760 // we need to calculate our new positioning based on the scaling
15761 if ( position === "static" ) {
15763 position: "relative",
15768 $.each([ "top", "left" ], function( idx, pos ) {
15769 el.css( pos, function( _, str ) {
15770 var val = parseInt( str, 10 ),
15771 toRef = idx ? el.to.left : el.to.top;
15773 // if original was "auto", recalculate the new value from wrapper
15774 if ( str === "auto" ) {
15775 return toRef + "px";
15778 return val + toRef + "px";
15784 $.effects.removeWrapper( el );
15793 * jQuery UI Effects Scale 1.11.0
15794 * http://jqueryui.com
15796 * Copyright 2014 jQuery Foundation and other contributors
15797 * Released under the MIT license.
15798 * http://jquery.org/license
15800 * http://api.jqueryui.com/scale-effect/
15804 var effectScale = $.effects.effect.scale = function( o, done ) {
15807 var el = $( this ),
15808 options = $.extend( true, {}, o ),
15809 mode = $.effects.setMode( el, o.mode || "effect" ),
15810 percent = parseInt( o.percent, 10 ) ||
15811 ( parseInt( o.percent, 10 ) === 0 ? 0 : ( mode === "hide" ? 0 : 100 ) ),
15812 direction = o.direction || "both",
15815 height: el.height(),
15817 outerHeight: el.outerHeight(),
15818 outerWidth: el.outerWidth()
15821 y: direction !== "horizontal" ? (percent / 100) : 1,
15822 x: direction !== "vertical" ? (percent / 100) : 1
15825 // We are going to pass this effect to the size effect:
15826 options.effect = "size";
15827 options.queue = false;
15828 options.complete = done;
15830 // Set default origin and restore for show/hide
15831 if ( mode !== "effect" ) {
15832 options.origin = origin || [ "middle", "center" ];
15833 options.restore = true;
15836 options.from = o.from || ( mode === "show" ? {
15843 height: original.height * factor.y,
15844 width: original.width * factor.x,
15845 outerHeight: original.outerHeight * factor.y,
15846 outerWidth: original.outerWidth * factor.x
15849 // Fade option to support puff
15850 if ( options.fade ) {
15851 if ( mode === "show" ) {
15852 options.from.opacity = 0;
15853 options.to.opacity = 1;
15855 if ( mode === "hide" ) {
15856 options.from.opacity = 1;
15857 options.to.opacity = 0;
15862 el.effect( options );
15868 * jQuery UI Effects Puff 1.11.0
15869 * http://jqueryui.com
15871 * Copyright 2014 jQuery Foundation and other contributors
15872 * Released under the MIT license.
15873 * http://jquery.org/license
15875 * http://api.jqueryui.com/puff-effect/
15879 var effectPuff = $.effects.effect.puff = function( o, done ) {
15880 var elem = $( this ),
15881 mode = $.effects.setMode( elem, o.mode || "hide" ),
15882 hide = mode === "hide",
15883 percent = parseInt( o.percent, 10 ) || 150,
15884 factor = percent / 100,
15886 height: elem.height(),
15887 width: elem.width(),
15888 outerHeight: elem.outerHeight(),
15889 outerWidth: elem.outerWidth()
15898 percent: hide ? percent : 100,
15902 height: original.height * factor,
15903 width: original.width * factor,
15904 outerHeight: original.outerHeight * factor,
15905 outerWidth: original.outerWidth * factor
15914 * jQuery UI Effects Pulsate 1.11.0
15915 * http://jqueryui.com
15917 * Copyright 2014 jQuery Foundation and other contributors
15918 * Released under the MIT license.
15919 * http://jquery.org/license
15921 * http://api.jqueryui.com/pulsate-effect/
15925 var effectPulsate = $.effects.effect.pulsate = function( o, done ) {
15926 var elem = $( this ),
15927 mode = $.effects.setMode( elem, o.mode || "show" ),
15928 show = mode === "show",
15929 hide = mode === "hide",
15930 showhide = ( show || mode === "hide" ),
15932 // showing or hiding leaves of the "last" animation
15933 anims = ( ( o.times || 5 ) * 2 ) + ( showhide ? 1 : 0 ),
15934 duration = o.duration / anims,
15936 queue = elem.queue(),
15937 queuelen = queue.length,
15940 if ( show || !elem.is(":visible")) {
15941 elem.css( "opacity", 0 ).show();
15945 // anims - 1 opacity "toggles"
15946 for ( i = 1; i < anims; i++ ) {
15949 }, duration, o.easing );
15950 animateTo = 1 - animateTo;
15955 }, duration, o.easing);
15957 elem.queue(function() {
15964 // We just queued up "anims" animations, we need to put them next in the queue
15965 if ( queuelen > 1 ) {
15966 queue.splice.apply( queue,
15967 [ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) );
15974 * jQuery UI Effects Shake 1.11.0
15975 * http://jqueryui.com
15977 * Copyright 2014 jQuery Foundation and other contributors
15978 * Released under the MIT license.
15979 * http://jquery.org/license
15981 * http://api.jqueryui.com/shake-effect/
15985 var effectShake = $.effects.effect.shake = function( o, done ) {
15987 var el = $( this ),
15988 props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
15989 mode = $.effects.setMode( el, o.mode || "effect" ),
15990 direction = o.direction || "left",
15991 distance = o.distance || 20,
15992 times = o.times || 3,
15993 anims = times * 2 + 1,
15994 speed = Math.round( o.duration / anims ),
15995 ref = (direction === "up" || direction === "down") ? "top" : "left",
15996 positiveMotion = (direction === "up" || direction === "left"),
16002 // we will need to re-assemble the queue to stack our animations in place
16003 queue = el.queue(),
16004 queuelen = queue.length;
16006 $.effects.save( el, props );
16008 $.effects.createWrapper( el );
16011 animation[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance;
16012 animation1[ ref ] = ( positiveMotion ? "+=" : "-=" ) + distance * 2;
16013 animation2[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance * 2;
16016 el.animate( animation, speed, o.easing );
16019 for ( i = 1; i < times; i++ ) {
16020 el.animate( animation1, speed, o.easing ).animate( animation2, speed, o.easing );
16023 .animate( animation1, speed, o.easing )
16024 .animate( animation, speed / 2, o.easing )
16025 .queue(function() {
16026 if ( mode === "hide" ) {
16029 $.effects.restore( el, props );
16030 $.effects.removeWrapper( el );
16034 // inject all the animations we just queued to be first in line (after "inprogress")
16035 if ( queuelen > 1) {
16036 queue.splice.apply( queue,
16037 [ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) );
16045 * jQuery UI Effects Slide 1.11.0
16046 * http://jqueryui.com
16048 * Copyright 2014 jQuery Foundation and other contributors
16049 * Released under the MIT license.
16050 * http://jquery.org/license
16052 * http://api.jqueryui.com/slide-effect/
16056 var effectSlide = $.effects.effect.slide = function( o, done ) {
16059 var el = $( this ),
16060 props = [ "position", "top", "bottom", "left", "right", "width", "height" ],
16061 mode = $.effects.setMode( el, o.mode || "show" ),
16062 show = mode === "show",
16063 direction = o.direction || "left",
16064 ref = (direction === "up" || direction === "down") ? "top" : "left",
16065 positiveMotion = (direction === "up" || direction === "left"),
16070 $.effects.save( el, props );
16072 distance = o.distance || el[ ref === "top" ? "outerHeight" : "outerWidth" ]( true );
16074 $.effects.createWrapper( el ).css({
16079 el.css( ref, positiveMotion ? (isNaN(distance) ? "-" + distance : -distance) : distance );
16083 animation[ ref ] = ( show ?
16084 ( positiveMotion ? "+=" : "-=") :
16085 ( positiveMotion ? "-=" : "+=")) +
16089 el.animate( animation, {
16091 duration: o.duration,
16093 complete: function() {
16094 if ( mode === "hide" ) {
16097 $.effects.restore( el, props );
16098 $.effects.removeWrapper( el );
16106 * jQuery UI Effects Transfer 1.11.0
16107 * http://jqueryui.com
16109 * Copyright 2014 jQuery Foundation and other contributors
16110 * Released under the MIT license.
16111 * http://jquery.org/license
16113 * http://api.jqueryui.com/transfer-effect/
16117 var effectTransfer = $.effects.effect.transfer = function( o, done ) {
16118 var elem = $( this ),
16119 target = $( o.to ),
16120 targetFixed = target.css( "position" ) === "fixed",
16122 fixTop = targetFixed ? body.scrollTop() : 0,
16123 fixLeft = targetFixed ? body.scrollLeft() : 0,
16124 endPosition = target.offset(),
16126 top: endPosition.top - fixTop,
16127 left: endPosition.left - fixLeft,
16128 height: target.innerHeight(),
16129 width: target.innerWidth()
16131 startPosition = elem.offset(),
16132 transfer = $( "<div class='ui-effects-transfer'></div>" )
16133 .appendTo( document.body )
16134 .addClass( o.className )
16136 top: startPosition.top - fixTop,
16137 left: startPosition.left - fixLeft,
16138 height: elem.innerHeight(),
16139 width: elem.innerWidth(),
16140 position: targetFixed ? "fixed" : "absolute"
16142 .animate( animation, o.duration, o.easing, function() {