1
/*! jQuery UI - v1.11.4 - 2015-03-11
3
* Includes: core.js, widget.js, mouse.js, position.js, accordion.js, autocomplete.js, button.js, datepicker.js, dialog.js, draggable.js, droppable.js, effect.js, effect-blind.js, effect-bounce.js, effect-clip.js, effect-drop.js, effect-explode.js, effect-fade.js, effect-fold.js, effect-highlight.js, effect-puff.js, effect-pulsate.js, effect-scale.js, effect-shake.js, effect-size.js, effect-slide.js, effect-transfer.js, menu.js, progressbar.js, resizable.js, selectable.js, selectmenu.js, slider.js, sortable.js, spinner.js, tabs.js, tooltip.js
4
* Copyright 2015 jQuery Foundation and other contributors; Licensed MIT */
7
if ( typeof define === "function" && define.amd ) {
9
// AMD. Register as an anonymous module.
10
define([ "jquery" ], factory );
18
* jQuery UI Core 1.11.4
21
* Copyright 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( includeHidden ) {
58
var position = this.css( "position" ),
59
excludeStaticParent = position === "absolute",
60
overflowRegex = includeHidden ? /(auto|scroll|hidden)/ : /(auto|scroll)/,
61
scrollParent = this.parents().filter( function() {
62
var parent = $( this );
63
if ( excludeStaticParent && parent.css( "position" ) === "static" ) {
66
return overflowRegex.test( parent.css( "overflow" ) + parent.css( "overflow-y" ) + parent.css( "overflow-x" ) );
69
return position === "fixed" || !scrollParent.length ? $( this[ 0 ].ownerDocument || document ) : scrollParent;
72
uniqueId: (function() {
76
return this.each(function() {
78
this.id = "ui-id-" + ( ++uuid );
84
removeUniqueId: function() {
85
return this.each(function() {
86
if ( /^ui-id-\d+$/.test( this.id ) ) {
87
$( this ).removeAttr( "id" );
94
function focusable( element, isTabIndexNotNaN ) {
95
var map, mapName, img,
96
nodeName = element.nodeName.toLowerCase();
97
if ( "area" === nodeName ) {
98
map = element.parentNode;
100
if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
103
img = $( "img[usemap='#" + mapName + "']" )[ 0 ];
104
return !!img && visible( img );
106
return ( /^(input|select|textarea|button|object)$/.test( nodeName ) ?
109
element.href || isTabIndexNotNaN :
111
// the element and all of its ancestors must be visible
115
function visible( element ) {
116
return $.expr.filters.visible( element ) &&
117
!$( element ).parents().addBack().filter(function() {
118
return $.css( this, "visibility" ) === "hidden";
122
$.extend( $.expr[ ":" ], {
123
data: $.expr.createPseudo ?
124
$.expr.createPseudo(function( dataName ) {
125
return function( elem ) {
126
return !!$.data( elem, dataName );
129
// support: jQuery <1.8
130
function( elem, i, match ) {
131
return !!$.data( elem, match[ 3 ] );
134
focusable: function( element ) {
135
return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) );
138
tabbable: function( element ) {
139
var tabIndex = $.attr( element, "tabindex" ),
140
isTabIndexNaN = isNaN( tabIndex );
141
return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN );
145
// support: jQuery <1.8
146
if ( !$( "<a>" ).outerWidth( 1 ).jquery ) {
147
$.each( [ "Width", "Height" ], function( i, name ) {
148
var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
149
type = name.toLowerCase(),
151
innerWidth: $.fn.innerWidth,
152
innerHeight: $.fn.innerHeight,
153
outerWidth: $.fn.outerWidth,
154
outerHeight: $.fn.outerHeight
157
function reduce( elem, size, border, margin ) {
158
$.each( side, function() {
159
size -= parseFloat( $.css( elem, "padding" + this ) ) || 0;
161
size -= parseFloat( $.css( elem, "border" + this + "Width" ) ) || 0;
164
size -= parseFloat( $.css( elem, "margin" + this ) ) || 0;
170
$.fn[ "inner" + name ] = function( size ) {
171
if ( size === undefined ) {
172
return orig[ "inner" + name ].call( this );
175
return this.each(function() {
176
$( this ).css( type, reduce( this, size ) + "px" );
180
$.fn[ "outer" + name] = function( size, margin ) {
181
if ( typeof size !== "number" ) {
182
return orig[ "outer" + name ].call( this, size );
185
return this.each(function() {
186
$( this).css( type, reduce( this, size, true, margin ) + "px" );
192
// support: jQuery <1.8
193
if ( !$.fn.addBack ) {
194
$.fn.addBack = function( selector ) {
195
return this.add( selector == null ?
196
this.prevObject : this.prevObject.filter( selector )
201
// support: jQuery 1.6.1, 1.6.2 (http://bugs.jquery.com/ticket/9413)
202
if ( $( "<a>" ).data( "a-b", "a" ).removeData( "a-b" ).data( "a-b" ) ) {
203
$.fn.removeData = (function( removeData ) {
204
return function( key ) {
205
if ( arguments.length ) {
206
return removeData.call( this, $.camelCase( key ) );
208
return removeData.call( this );
211
})( $.fn.removeData );
215
$.ui.ie = !!/msie [\w.]+/.exec( navigator.userAgent.toLowerCase() );
218
focus: (function( orig ) {
219
return function( delay, fn ) {
220
return typeof delay === "number" ?
221
this.each(function() {
223
setTimeout(function() {
230
orig.apply( this, arguments );
234
disableSelection: (function() {
235
var eventType = "onselectstart" in document.createElement( "div" ) ?
240
return this.bind( eventType + ".ui-disableSelection", function( event ) {
241
event.preventDefault();
246
enableSelection: function() {
247
return this.unbind( ".ui-disableSelection" );
250
zIndex: function( zIndex ) {
251
if ( zIndex !== undefined ) {
252
return this.css( "zIndex", zIndex );
256
var elem = $( this[ 0 ] ), position, value;
257
while ( elem.length && elem[ 0 ] !== document ) {
258
// Ignore z-index if position is set to a value where z-index is ignored by the browser
259
// This makes behavior of this function consistent across browsers
260
// WebKit always returns auto if the element is positioned
261
position = elem.css( "position" );
262
if ( position === "absolute" || position === "relative" || position === "fixed" ) {
263
// IE returns 0 when zIndex is not specified
264
// other browsers return a string
265
// we ignore the case of nested elements with an explicit value of 0
266
// <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
267
value = parseInt( elem.css( "zIndex" ), 10 );
268
if ( !isNaN( value ) && value !== 0 ) {
272
elem = elem.parent();
280
// $.ui.plugin is deprecated. Use $.widget() extensions instead.
282
add: function( module, option, set ) {
284
proto = $.ui[ module ].prototype;
286
proto.plugins[ i ] = proto.plugins[ i ] || [];
287
proto.plugins[ i ].push( [ option, set[ i ] ] );
290
call: function( instance, name, args, allowDisconnected ) {
292
set = instance.plugins[ name ];
298
if ( !allowDisconnected && ( !instance.element[ 0 ].parentNode || instance.element[ 0 ].parentNode.nodeType === 11 ) ) {
302
for ( i = 0; i < set.length; i++ ) {
303
if ( instance.options[ set[ i ][ 0 ] ] ) {
304
set[ i ][ 1 ].apply( instance.element, args );
312
* jQuery UI Widget 1.11.4
313
* http://jqueryui.com
315
* Copyright jQuery Foundation and other contributors
316
* Released under the MIT license.
317
* http://jquery.org/license
319
* http://api.jqueryui.com/jQuery.widget/
324
widget_slice = Array.prototype.slice;
326
$.cleanData = (function( orig ) {
327
return function( elems ) {
329
for ( i = 0; (elem = elems[i]) != null; i++ ) {
332
// Only trigger remove when necessary to save time
333
events = $._data( elem, "events" );
334
if ( events && events.remove ) {
335
$( elem ).triggerHandler( "remove" );
338
// http://bugs.jquery.com/ticket/8235
345
$.widget = function( name, base, prototype ) {
346
var fullName, existingConstructor, constructor, basePrototype,
347
// proxiedPrototype allows the provided prototype to remain unmodified
348
// so that it can be used as a mixin for multiple widgets (#8876)
349
proxiedPrototype = {},
350
namespace = name.split( "." )[ 0 ];
352
name = name.split( "." )[ 1 ];
353
fullName = namespace + "-" + name;
360
// create selector for plugin
361
$.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) {
362
return !!$.data( elem, fullName );
365
$[ namespace ] = $[ namespace ] || {};
366
existingConstructor = $[ namespace ][ name ];
367
constructor = $[ namespace ][ name ] = function( options, element ) {
368
// allow instantiation without "new" keyword
369
if ( !this._createWidget ) {
370
return new constructor( options, element );
373
// allow instantiation without initializing for simple inheritance
374
// must use "new" keyword (the code above always passes args)
375
if ( arguments.length ) {
376
this._createWidget( options, element );
379
// extend with the existing constructor to carry over any static properties
380
$.extend( constructor, existingConstructor, {
381
version: prototype.version,
382
// copy the object used to create the prototype in case we need to
383
// redefine the widget later
384
_proto: $.extend( {}, prototype ),
385
// track widgets that inherit from this widget in case this widget is
386
// redefined after a widget inherits from it
387
_childConstructors: []
390
basePrototype = new base();
391
// we need to make the options hash a property directly on the new instance
392
// otherwise we'll modify the options hash on the prototype that we're
394
basePrototype.options = $.widget.extend( {}, basePrototype.options );
395
$.each( prototype, function( prop, value ) {
396
if ( !$.isFunction( value ) ) {
397
proxiedPrototype[ prop ] = value;
400
proxiedPrototype[ prop ] = (function() {
401
var _super = function() {
402
return base.prototype[ prop ].apply( this, arguments );
404
_superApply = function( args ) {
405
return base.prototype[ prop ].apply( this, args );
408
var __super = this._super,
409
__superApply = this._superApply,
412
this._super = _super;
413
this._superApply = _superApply;
415
returnValue = value.apply( this, arguments );
417
this._super = __super;
418
this._superApply = __superApply;
424
constructor.prototype = $.widget.extend( basePrototype, {
425
// TODO: remove support for widgetEventPrefix
426
// always use the name + a colon as the prefix, e.g., draggable:start
427
// don't prefix for widgets that aren't DOM-based
428
widgetEventPrefix: existingConstructor ? (basePrototype.widgetEventPrefix || name) : name
429
}, proxiedPrototype, {
430
constructor: constructor,
431
namespace: namespace,
433
widgetFullName: fullName
436
// If this widget is being redefined then we need to find all widgets that
437
// are inheriting from it and redefine all of them so that they inherit from
438
// the new version of this widget. We're essentially trying to replace one
439
// level in the prototype chain.
440
if ( existingConstructor ) {
441
$.each( existingConstructor._childConstructors, function( i, child ) {
442
var childPrototype = child.prototype;
444
// redefine the child widget using the same prototype that was
445
// originally used, but inherit from the new version of the base
446
$.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, child._proto );
448
// remove the list of existing child constructors from the old constructor
449
// so the old child constructors can be garbage collected
450
delete existingConstructor._childConstructors;
452
base._childConstructors.push( constructor );
455
$.widget.bridge( name, constructor );
460
$.widget.extend = function( target ) {
461
var input = widget_slice.call( arguments, 1 ),
463
inputLength = input.length,
466
for ( ; inputIndex < inputLength; inputIndex++ ) {
467
for ( key in input[ inputIndex ] ) {
468
value = input[ inputIndex ][ key ];
469
if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) {
471
if ( $.isPlainObject( value ) ) {
472
target[ key ] = $.isPlainObject( target[ key ] ) ?
473
$.widget.extend( {}, target[ key ], value ) :
474
// Don't extend strings, arrays, etc. with objects
475
$.widget.extend( {}, value );
476
// Copy everything else by reference
478
target[ key ] = value;
486
$.widget.bridge = function( name, object ) {
487
var fullName = object.prototype.widgetFullName || name;
488
$.fn[ name ] = function( options ) {
489
var isMethodCall = typeof options === "string",
490
args = widget_slice.call( arguments, 1 ),
493
if ( isMethodCall ) {
494
this.each(function() {
496
instance = $.data( this, fullName );
497
if ( options === "instance" ) {
498
returnValue = instance;
502
return $.error( "cannot call methods on " + name + " prior to initialization; " +
503
"attempted to call method '" + options + "'" );
505
if ( !$.isFunction( instance[options] ) || options.charAt( 0 ) === "_" ) {
506
return $.error( "no such method '" + options + "' for " + name + " widget instance" );
508
methodValue = instance[ options ].apply( instance, args );
509
if ( methodValue !== instance && methodValue !== undefined ) {
510
returnValue = methodValue && methodValue.jquery ?
511
returnValue.pushStack( methodValue.get() ) :
518
// Allow multiple hashes to be passed on init
520
options = $.widget.extend.apply( null, [ options ].concat(args) );
523
this.each(function() {
524
var instance = $.data( this, fullName );
526
instance.option( options || {} );
527
if ( instance._init ) {
531
$.data( this, fullName, new object( options, this ) );
540
$.Widget = function( /* options, element */ ) {};
541
$.Widget._childConstructors = [];
543
$.Widget.prototype = {
544
widgetName: "widget",
545
widgetEventPrefix: "",
546
defaultElement: "<div>",
553
_createWidget: function( options, element ) {
554
element = $( element || this.defaultElement || this )[ 0 ];
555
this.element = $( element );
556
this.uuid = widget_uuid++;
557
this.eventNamespace = "." + this.widgetName + this.uuid;
560
this.hoverable = $();
561
this.focusable = $();
563
if ( element !== this ) {
564
$.data( element, this.widgetFullName, this );
565
this._on( true, this.element, {
566
remove: function( event ) {
567
if ( event.target === element ) {
572
this.document = $( element.style ?
573
// element within the document
574
element.ownerDocument :
575
// element is window or document
576
element.document || element );
577
this.window = $( this.document[0].defaultView || this.document[0].parentWindow );
580
this.options = $.widget.extend( {},
582
this._getCreateOptions(),
586
this._trigger( "create", null, this._getCreateEventData() );
589
_getCreateOptions: $.noop,
590
_getCreateEventData: $.noop,
594
destroy: function() {
596
// we can probably remove the unbind calls in 2.0
597
// all event bindings should go through this._on()
599
.unbind( this.eventNamespace )
600
.removeData( this.widgetFullName )
601
// support: jquery <1.6.3
602
// http://bugs.jquery.com/ticket/9413
603
.removeData( $.camelCase( this.widgetFullName ) );
605
.unbind( this.eventNamespace )
606
.removeAttr( "aria-disabled" )
608
this.widgetFullName + "-disabled " +
609
"ui-state-disabled" );
611
// clean up events and states
612
this.bindings.unbind( this.eventNamespace );
613
this.hoverable.removeClass( "ui-state-hover" );
614
this.focusable.removeClass( "ui-state-focus" );
622
option: function( key, value ) {
628
if ( arguments.length === 0 ) {
629
// don't return a reference to the internal hash
630
return $.widget.extend( {}, this.options );
633
if ( typeof key === "string" ) {
634
// handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
636
parts = key.split( "." );
638
if ( parts.length ) {
639
curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );
640
for ( i = 0; i < parts.length - 1; i++ ) {
641
curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};
642
curOption = curOption[ parts[ i ] ];
645
if ( arguments.length === 1 ) {
646
return curOption[ key ] === undefined ? null : curOption[ key ];
648
curOption[ key ] = value;
650
if ( arguments.length === 1 ) {
651
return this.options[ key ] === undefined ? null : this.options[ key ];
653
options[ key ] = value;
657
this._setOptions( options );
661
_setOptions: function( options ) {
664
for ( key in options ) {
665
this._setOption( key, options[ key ] );
670
_setOption: function( key, value ) {
671
this.options[ key ] = value;
673
if ( key === "disabled" ) {
675
.toggleClass( this.widgetFullName + "-disabled", !!value );
677
// If the widget is becoming disabled, then nothing is interactive
679
this.hoverable.removeClass( "ui-state-hover" );
680
this.focusable.removeClass( "ui-state-focus" );
688
return this._setOptions({ disabled: false });
690
disable: function() {
691
return this._setOptions({ disabled: true });
694
_on: function( suppressDisabledCheck, element, handlers ) {
698
// no suppressDisabledCheck flag, shuffle arguments
699
if ( typeof suppressDisabledCheck !== "boolean" ) {
701
element = suppressDisabledCheck;
702
suppressDisabledCheck = false;
705
// no element argument, shuffle and use this.element
708
element = this.element;
709
delegateElement = this.widget();
711
element = delegateElement = $( element );
712
this.bindings = this.bindings.add( element );
715
$.each( handlers, function( event, handler ) {
716
function handlerProxy() {
717
// allow widgets to customize the disabled handling
718
// - disabled as an array instead of boolean
719
// - disabled class as method for disabling individual parts
720
if ( !suppressDisabledCheck &&
721
( instance.options.disabled === true ||
722
$( this ).hasClass( "ui-state-disabled" ) ) ) {
725
return ( typeof handler === "string" ? instance[ handler ] : handler )
726
.apply( instance, arguments );
729
// copy the guid so direct unbinding works
730
if ( typeof handler !== "string" ) {
731
handlerProxy.guid = handler.guid =
732
handler.guid || handlerProxy.guid || $.guid++;
735
var match = event.match( /^([\w:-]*)\s*(.*)$/ ),
736
eventName = match[1] + instance.eventNamespace,
739
delegateElement.delegate( selector, eventName, handlerProxy );
741
element.bind( eventName, handlerProxy );
746
_off: function( element, eventName ) {
747
eventName = (eventName || "").split( " " ).join( this.eventNamespace + " " ) +
749
element.unbind( eventName ).undelegate( eventName );
751
// Clear the stack to avoid memory leaks (#10056)
752
this.bindings = $( this.bindings.not( element ).get() );
753
this.focusable = $( this.focusable.not( element ).get() );
754
this.hoverable = $( this.hoverable.not( element ).get() );
757
_delay: function( handler, delay ) {
758
function handlerProxy() {
759
return ( typeof handler === "string" ? instance[ handler ] : handler )
760
.apply( instance, arguments );
763
return setTimeout( handlerProxy, delay || 0 );
766
_hoverable: function( element ) {
767
this.hoverable = this.hoverable.add( element );
769
mouseenter: function( event ) {
770
$( event.currentTarget ).addClass( "ui-state-hover" );
772
mouseleave: function( event ) {
773
$( event.currentTarget ).removeClass( "ui-state-hover" );
778
_focusable: function( element ) {
779
this.focusable = this.focusable.add( element );
781
focusin: function( event ) {
782
$( event.currentTarget ).addClass( "ui-state-focus" );
784
focusout: function( event ) {
785
$( event.currentTarget ).removeClass( "ui-state-focus" );
790
_trigger: function( type, event, data ) {
792
callback = this.options[ type ];
795
event = $.Event( event );
796
event.type = ( type === this.widgetEventPrefix ?
798
this.widgetEventPrefix + type ).toLowerCase();
799
// the original event may come from any element
800
// so we need to reset the target on the new event
801
event.target = this.element[ 0 ];
803
// copy original event properties over to the new event
804
orig = event.originalEvent;
806
for ( prop in orig ) {
807
if ( !( prop in event ) ) {
808
event[ prop ] = orig[ prop ];
813
this.element.trigger( event, data );
814
return !( $.isFunction( callback ) &&
815
callback.apply( this.element[0], [ event ].concat( data ) ) === false ||
816
event.isDefaultPrevented() );
820
$.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {
821
$.Widget.prototype[ "_" + method ] = function( element, options, callback ) {
822
if ( typeof options === "string" ) {
823
options = { effect: options };
826
effectName = !options ?
828
options === true || typeof options === "number" ?
830
options.effect || defaultEffect;
831
options = options || {};
832
if ( typeof options === "number" ) {
833
options = { duration: options };
835
hasOptions = !$.isEmptyObject( options );
836
options.complete = callback;
837
if ( options.delay ) {
838
element.delay( options.delay );
840
if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) {
841
element[ method ]( options );
842
} else if ( effectName !== method && element[ effectName ] ) {
843
element[ effectName ]( options.duration, options.easing, callback );
845
element.queue(function( next ) {
846
$( this )[ method ]();
848
callback.call( element[ 0 ] );
856
var widget = $.widget;
860
* jQuery UI Mouse 1.11.4
861
* http://jqueryui.com
863
* Copyright jQuery Foundation and other contributors
864
* Released under the MIT license.
865
* http://jquery.org/license
867
* http://api.jqueryui.com/mouse/
871
var mouseHandled = false;
872
$( document ).mouseup( function() {
873
mouseHandled = false;
876
var mouse = $.widget("ui.mouse", {
879
cancel: "input,textarea,button,select,option",
883
_mouseInit: function() {
887
.bind("mousedown." + this.widgetName, function(event) {
888
return that._mouseDown(event);
890
.bind("click." + this.widgetName, function(event) {
891
if (true === $.data(event.target, that.widgetName + ".preventClickEvent")) {
892
$.removeData(event.target, that.widgetName + ".preventClickEvent");
893
event.stopImmediatePropagation();
898
this.started = false;
901
// TODO: make sure destroying one instance of mouse doesn't mess with
902
// other instances of mouse
903
_mouseDestroy: function() {
904
this.element.unbind("." + this.widgetName);
905
if ( this._mouseMoveDelegate ) {
907
.unbind("mousemove." + this.widgetName, this._mouseMoveDelegate)
908
.unbind("mouseup." + this.widgetName, this._mouseUpDelegate);
912
_mouseDown: function(event) {
913
// don't let more than one widget handle mouseStart
914
if ( mouseHandled ) {
918
this._mouseMoved = false;
920
// we may have missed mouseup (out of window)
921
(this._mouseStarted && this._mouseUp(event));
923
this._mouseDownEvent = event;
926
btnIsLeft = (event.which === 1),
927
// event.target.nodeName works around a bug in IE 8 with
928
// disabled inputs (#7620)
929
elIsCancel = (typeof this.options.cancel === "string" && event.target.nodeName ? $(event.target).closest(this.options.cancel).length : false);
930
if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
934
this.mouseDelayMet = !this.options.delay;
935
if (!this.mouseDelayMet) {
936
this._mouseDelayTimer = setTimeout(function() {
937
that.mouseDelayMet = true;
938
}, this.options.delay);
941
if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
942
this._mouseStarted = (this._mouseStart(event) !== false);
943
if (!this._mouseStarted) {
944
event.preventDefault();
949
// Click event may never have fired (Gecko & Opera)
950
if (true === $.data(event.target, this.widgetName + ".preventClickEvent")) {
951
$.removeData(event.target, this.widgetName + ".preventClickEvent");
954
// these delegates are required to keep context
955
this._mouseMoveDelegate = function(event) {
956
return that._mouseMove(event);
958
this._mouseUpDelegate = function(event) {
959
return that._mouseUp(event);
963
.bind( "mousemove." + this.widgetName, this._mouseMoveDelegate )
964
.bind( "mouseup." + this.widgetName, this._mouseUpDelegate );
966
event.preventDefault();
972
_mouseMove: function(event) {
973
// Only check for mouseups outside the document if you've moved inside the document
974
// at least once. This prevents the firing of mouseup in the case of IE<9, which will
975
// fire a mousemove event if content is placed under the cursor. See #7778
977
if ( this._mouseMoved ) {
978
// IE mouseup check - mouseup happened when mouse was out of window
979
if ($.ui.ie && ( !document.documentMode || document.documentMode < 9 ) && !event.button) {
980
return this._mouseUp(event);
982
// Iframe mouseup check - mouseup occurred in another document
983
} else if ( !event.which ) {
984
return this._mouseUp( event );
988
if ( event.which || event.button ) {
989
this._mouseMoved = true;
992
if (this._mouseStarted) {
993
this._mouseDrag(event);
994
return event.preventDefault();
997
if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
999
(this._mouseStart(this._mouseDownEvent, event) !== false);
1000
(this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
1003
return !this._mouseStarted;
1006
_mouseUp: function(event) {
1008
.unbind( "mousemove." + this.widgetName, this._mouseMoveDelegate )
1009
.unbind( "mouseup." + this.widgetName, this._mouseUpDelegate );
1011
if (this._mouseStarted) {
1012
this._mouseStarted = false;
1014
if (event.target === this._mouseDownEvent.target) {
1015
$.data(event.target, this.widgetName + ".preventClickEvent", true);
1018
this._mouseStop(event);
1021
mouseHandled = false;
1025
_mouseDistanceMet: function(event) {
1027
Math.abs(this._mouseDownEvent.pageX - event.pageX),
1028
Math.abs(this._mouseDownEvent.pageY - event.pageY)
1029
) >= this.options.distance
1033
_mouseDelayMet: function(/* event */) {
1034
return this.mouseDelayMet;
1037
// These are placeholder methods, to be overriden by extending plugin
1038
_mouseStart: function(/* event */) {},
1039
_mouseDrag: function(/* event */) {},
1040
_mouseStop: function(/* event */) {},
1041
_mouseCapture: function(/* event */) { return true; }
1046
* jQuery UI Position 1.11.4
1047
* http://jqueryui.com
1049
* Copyright jQuery Foundation and other contributors
1050
* Released under the MIT license.
1051
* http://jquery.org/license
1053
* http://api.jqueryui.com/position/
1060
var cachedScrollbarWidth, supportsOffsetFractions,
1064
rhorizontal = /left|center|right/,
1065
rvertical = /top|center|bottom/,
1066
roffset = /[\+\-]\d+(\.[\d]+)?%?/,
1069
_position = $.fn.position;
1071
function getOffsets( offsets, width, height ) {
1073
parseFloat( offsets[ 0 ] ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ),
1074
parseFloat( offsets[ 1 ] ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 )
1078
function parseCss( element, property ) {
1079
return parseInt( $.css( element, property ), 10 ) || 0;
1082
function getDimensions( elem ) {
1084
if ( raw.nodeType === 9 ) {
1086
width: elem.width(),
1087
height: elem.height(),
1088
offset: { top: 0, left: 0 }
1091
if ( $.isWindow( raw ) ) {
1093
width: elem.width(),
1094
height: elem.height(),
1095
offset: { top: elem.scrollTop(), left: elem.scrollLeft() }
1098
if ( raw.preventDefault ) {
1102
offset: { top: raw.pageY, left: raw.pageX }
1106
width: elem.outerWidth(),
1107
height: elem.outerHeight(),
1108
offset: elem.offset()
1113
scrollbarWidth: function() {
1114
if ( cachedScrollbarWidth !== undefined ) {
1115
return cachedScrollbarWidth;
1118
div = $( "<div style='display:block;position:absolute;width:50px;height:50px;overflow:hidden;'><div style='height:100px;width:auto;'></div></div>" ),
1119
innerDiv = div.children()[0];
1121
$( "body" ).append( div );
1122
w1 = innerDiv.offsetWidth;
1123
div.css( "overflow", "scroll" );
1125
w2 = innerDiv.offsetWidth;
1128
w2 = div[0].clientWidth;
1133
return (cachedScrollbarWidth = w1 - w2);
1135
getScrollInfo: function( within ) {
1136
var overflowX = within.isWindow || within.isDocument ? "" :
1137
within.element.css( "overflow-x" ),
1138
overflowY = within.isWindow || within.isDocument ? "" :
1139
within.element.css( "overflow-y" ),
1140
hasOverflowX = overflowX === "scroll" ||
1141
( overflowX === "auto" && within.width < within.element[0].scrollWidth ),
1142
hasOverflowY = overflowY === "scroll" ||
1143
( overflowY === "auto" && within.height < within.element[0].scrollHeight );
1145
width: hasOverflowY ? $.position.scrollbarWidth() : 0,
1146
height: hasOverflowX ? $.position.scrollbarWidth() : 0
1149
getWithinInfo: function( element ) {
1150
var withinElement = $( element || window ),
1151
isWindow = $.isWindow( withinElement[0] ),
1152
isDocument = !!withinElement[ 0 ] && withinElement[ 0 ].nodeType === 9;
1154
element: withinElement,
1156
isDocument: isDocument,
1157
offset: withinElement.offset() || { left: 0, top: 0 },
1158
scrollLeft: withinElement.scrollLeft(),
1159
scrollTop: withinElement.scrollTop(),
1161
// support: jQuery 1.6.x
1162
// jQuery 1.6 doesn't support .outerWidth/Height() on documents or windows
1163
width: isWindow || isDocument ? withinElement.width() : withinElement.outerWidth(),
1164
height: isWindow || isDocument ? withinElement.height() : withinElement.outerHeight()
1169
$.fn.position = function( options ) {
1170
if ( !options || !options.of ) {
1171
return _position.apply( this, arguments );
1174
// make a copy, we don't want to modify arguments
1175
options = $.extend( {}, options );
1177
var atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions,
1178
target = $( options.of ),
1179
within = $.position.getWithinInfo( options.within ),
1180
scrollInfo = $.position.getScrollInfo( within ),
1181
collision = ( options.collision || "flip" ).split( " " ),
1184
dimensions = getDimensions( target );
1185
if ( target[0].preventDefault ) {
1186
// force left top to allow flipping
1187
options.at = "left top";
1189
targetWidth = dimensions.width;
1190
targetHeight = dimensions.height;
1191
targetOffset = dimensions.offset;
1192
// clone to reuse original targetOffset later
1193
basePosition = $.extend( {}, targetOffset );
1195
// force my and at to have valid horizontal and vertical positions
1196
// if a value is missing or invalid, it will be converted to center
1197
$.each( [ "my", "at" ], function() {
1198
var pos = ( options[ this ] || "" ).split( " " ),
1202
if ( pos.length === 1) {
1203
pos = rhorizontal.test( pos[ 0 ] ) ?
1204
pos.concat( [ "center" ] ) :
1205
rvertical.test( pos[ 0 ] ) ?
1206
[ "center" ].concat( pos ) :
1207
[ "center", "center" ];
1209
pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center";
1210
pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center";
1212
// calculate offsets
1213
horizontalOffset = roffset.exec( pos[ 0 ] );
1214
verticalOffset = roffset.exec( pos[ 1 ] );
1216
horizontalOffset ? horizontalOffset[ 0 ] : 0,
1217
verticalOffset ? verticalOffset[ 0 ] : 0
1220
// reduce to just the positions without the offsets
1222
rposition.exec( pos[ 0 ] )[ 0 ],
1223
rposition.exec( pos[ 1 ] )[ 0 ]
1227
// normalize collision option
1228
if ( collision.length === 1 ) {
1229
collision[ 1 ] = collision[ 0 ];
1232
if ( options.at[ 0 ] === "right" ) {
1233
basePosition.left += targetWidth;
1234
} else if ( options.at[ 0 ] === "center" ) {
1235
basePosition.left += targetWidth / 2;
1238
if ( options.at[ 1 ] === "bottom" ) {
1239
basePosition.top += targetHeight;
1240
} else if ( options.at[ 1 ] === "center" ) {
1241
basePosition.top += targetHeight / 2;
1244
atOffset = getOffsets( offsets.at, targetWidth, targetHeight );
1245
basePosition.left += atOffset[ 0 ];
1246
basePosition.top += atOffset[ 1 ];
1248
return this.each(function() {
1249
var collisionPosition, using,
1251
elemWidth = elem.outerWidth(),
1252
elemHeight = elem.outerHeight(),
1253
marginLeft = parseCss( this, "marginLeft" ),
1254
marginTop = parseCss( this, "marginTop" ),
1255
collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) + scrollInfo.width,
1256
collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) + scrollInfo.height,
1257
position = $.extend( {}, basePosition ),
1258
myOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() );
1260
if ( options.my[ 0 ] === "right" ) {
1261
position.left -= elemWidth;
1262
} else if ( options.my[ 0 ] === "center" ) {
1263
position.left -= elemWidth / 2;
1266
if ( options.my[ 1 ] === "bottom" ) {
1267
position.top -= elemHeight;
1268
} else if ( options.my[ 1 ] === "center" ) {
1269
position.top -= elemHeight / 2;
1272
position.left += myOffset[ 0 ];
1273
position.top += myOffset[ 1 ];
1275
// if the browser doesn't support fractions, then round for consistent results
1276
if ( !supportsOffsetFractions ) {
1277
position.left = round( position.left );
1278
position.top = round( position.top );
1281
collisionPosition = {
1282
marginLeft: marginLeft,
1283
marginTop: marginTop
1286
$.each( [ "left", "top" ], function( i, dir ) {
1287
if ( $.ui.position[ collision[ i ] ] ) {
1288
$.ui.position[ collision[ i ] ][ dir ]( position, {
1289
targetWidth: targetWidth,
1290
targetHeight: targetHeight,
1291
elemWidth: elemWidth,
1292
elemHeight: elemHeight,
1293
collisionPosition: collisionPosition,
1294
collisionWidth: collisionWidth,
1295
collisionHeight: collisionHeight,
1296
offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ],
1305
if ( options.using ) {
1306
// adds feedback as second argument to using callback, if present
1307
using = function( props ) {
1308
var left = targetOffset.left - position.left,
1309
right = left + targetWidth - elemWidth,
1310
top = targetOffset.top - position.top,
1311
bottom = top + targetHeight - elemHeight,
1315
left: targetOffset.left,
1316
top: targetOffset.top,
1318
height: targetHeight
1322
left: position.left,
1327
horizontal: right < 0 ? "left" : left > 0 ? "right" : "center",
1328
vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle"
1330
if ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) {
1331
feedback.horizontal = "center";
1333
if ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) {
1334
feedback.vertical = "middle";
1336
if ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) {
1337
feedback.important = "horizontal";
1339
feedback.important = "vertical";
1341
options.using.call( this, props, feedback );
1345
elem.offset( $.extend( position, { using: using } ) );
1351
left: function( position, data ) {
1352
var within = data.within,
1353
withinOffset = within.isWindow ? within.scrollLeft : within.offset.left,
1354
outerWidth = within.width,
1355
collisionPosLeft = position.left - data.collisionPosition.marginLeft,
1356
overLeft = withinOffset - collisionPosLeft,
1357
overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset,
1360
// element is wider than within
1361
if ( data.collisionWidth > outerWidth ) {
1362
// element is initially over the left side of within
1363
if ( overLeft > 0 && overRight <= 0 ) {
1364
newOverRight = position.left + overLeft + data.collisionWidth - outerWidth - withinOffset;
1365
position.left += overLeft - newOverRight;
1366
// element is initially over right side of within
1367
} else if ( overRight > 0 && overLeft <= 0 ) {
1368
position.left = withinOffset;
1369
// element is initially over both left and right sides of within
1371
if ( overLeft > overRight ) {
1372
position.left = withinOffset + outerWidth - data.collisionWidth;
1374
position.left = withinOffset;
1377
// too far left -> align with left edge
1378
} else if ( overLeft > 0 ) {
1379
position.left += overLeft;
1380
// too far right -> align with right edge
1381
} else if ( overRight > 0 ) {
1382
position.left -= overRight;
1383
// adjust based on position and margin
1385
position.left = max( position.left - collisionPosLeft, position.left );
1388
top: function( position, data ) {
1389
var within = data.within,
1390
withinOffset = within.isWindow ? within.scrollTop : within.offset.top,
1391
outerHeight = data.within.height,
1392
collisionPosTop = position.top - data.collisionPosition.marginTop,
1393
overTop = withinOffset - collisionPosTop,
1394
overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset,
1397
// element is taller than within
1398
if ( data.collisionHeight > outerHeight ) {
1399
// element is initially over the top of within
1400
if ( overTop > 0 && overBottom <= 0 ) {
1401
newOverBottom = position.top + overTop + data.collisionHeight - outerHeight - withinOffset;
1402
position.top += overTop - newOverBottom;
1403
// element is initially over bottom of within
1404
} else if ( overBottom > 0 && overTop <= 0 ) {
1405
position.top = withinOffset;
1406
// element is initially over both top and bottom of within
1408
if ( overTop > overBottom ) {
1409
position.top = withinOffset + outerHeight - data.collisionHeight;
1411
position.top = withinOffset;
1414
// too far up -> align with top
1415
} else if ( overTop > 0 ) {
1416
position.top += overTop;
1417
// too far down -> align with bottom edge
1418
} else if ( overBottom > 0 ) {
1419
position.top -= overBottom;
1420
// adjust based on position and margin
1422
position.top = max( position.top - collisionPosTop, position.top );
1427
left: function( position, data ) {
1428
var within = data.within,
1429
withinOffset = within.offset.left + within.scrollLeft,
1430
outerWidth = within.width,
1431
offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left,
1432
collisionPosLeft = position.left - data.collisionPosition.marginLeft,
1433
overLeft = collisionPosLeft - offsetLeft,
1434
overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft,
1435
myOffset = data.my[ 0 ] === "left" ?
1437
data.my[ 0 ] === "right" ?
1440
atOffset = data.at[ 0 ] === "left" ?
1442
data.at[ 0 ] === "right" ?
1445
offset = -2 * data.offset[ 0 ],
1449
if ( overLeft < 0 ) {
1450
newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth - outerWidth - withinOffset;
1451
if ( newOverRight < 0 || newOverRight < abs( overLeft ) ) {
1452
position.left += myOffset + atOffset + offset;
1454
} else if ( overRight > 0 ) {
1455
newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset + atOffset + offset - offsetLeft;
1456
if ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) {
1457
position.left += myOffset + atOffset + offset;
1461
top: function( position, data ) {
1462
var within = data.within,
1463
withinOffset = within.offset.top + within.scrollTop,
1464
outerHeight = within.height,
1465
offsetTop = within.isWindow ? within.scrollTop : within.offset.top,
1466
collisionPosTop = position.top - data.collisionPosition.marginTop,
1467
overTop = collisionPosTop - offsetTop,
1468
overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop,
1469
top = data.my[ 1 ] === "top",
1472
data.my[ 1 ] === "bottom" ?
1475
atOffset = data.at[ 1 ] === "top" ?
1477
data.at[ 1 ] === "bottom" ?
1478
-data.targetHeight :
1480
offset = -2 * data.offset[ 1 ],
1483
if ( overTop < 0 ) {
1484
newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight - outerHeight - withinOffset;
1485
if ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) {
1486
position.top += myOffset + atOffset + offset;
1488
} else if ( overBottom > 0 ) {
1489
newOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset + offset - offsetTop;
1490
if ( newOverTop > 0 || abs( newOverTop ) < overBottom ) {
1491
position.top += myOffset + atOffset + offset;
1498
$.ui.position.flip.left.apply( this, arguments );
1499
$.ui.position.fit.left.apply( this, arguments );
1502
$.ui.position.flip.top.apply( this, arguments );
1503
$.ui.position.fit.top.apply( this, arguments );
1508
// fraction support test
1510
var testElement, testElementParent, testElementStyle, offsetLeft, i,
1511
body = document.getElementsByTagName( "body" )[ 0 ],
1512
div = document.createElement( "div" );
1514
//Create a "fake body" for testing based on method used in jQuery.support
1515
testElement = document.createElement( body ? "div" : "body" );
1516
testElementStyle = {
1517
visibility: "hidden",
1525
$.extend( testElementStyle, {
1526
position: "absolute",
1531
for ( i in testElementStyle ) {
1532
testElement.style[ i ] = testElementStyle[ i ];
1534
testElement.appendChild( div );
1535
testElementParent = body || document.documentElement;
1536
testElementParent.insertBefore( testElement, testElementParent.firstChild );
1538
div.style.cssText = "position: absolute; left: 10.7432222px;";
1540
offsetLeft = $( div ).offset().left;
1541
supportsOffsetFractions = offsetLeft > 10 && offsetLeft < 11;
1543
testElement.innerHTML = "";
1544
testElementParent.removeChild( testElement );
1549
var position = $.ui.position;
1553
* jQuery UI Accordion 1.11.4
1554
* http://jqueryui.com
1556
* Copyright jQuery Foundation and other contributors
1557
* Released under the MIT license.
1558
* http://jquery.org/license
1560
* http://api.jqueryui.com/accordion/
1564
var accordion = $.widget( "ui.accordion", {
1571
header: "> li > :first-child,> :not(li):even",
1572
heightStyle: "auto",
1574
activeHeader: "ui-icon-triangle-1-s",
1575
header: "ui-icon-triangle-1-e"
1580
beforeActivate: null
1584
borderTopWidth: "hide",
1585
borderBottomWidth: "hide",
1587
paddingBottom: "hide",
1592
borderTopWidth: "show",
1593
borderBottomWidth: "show",
1595
paddingBottom: "show",
1599
_create: function() {
1600
var options = this.options;
1601
this.prevShow = this.prevHide = $();
1602
this.element.addClass( "ui-accordion ui-widget ui-helper-reset" )
1604
.attr( "role", "tablist" );
1606
// don't allow collapsible: false and active: false / null
1607
if ( !options.collapsible && (options.active === false || options.active == null) ) {
1611
this._processPanels();
1612
// handle negative values
1613
if ( options.active < 0 ) {
1614
options.active += this.headers.length;
1619
_getCreateEventData: function() {
1621
header: this.active,
1622
panel: !this.active.length ? $() : this.active.next()
1626
_createIcons: function() {
1627
var icons = this.options.icons;
1630
.addClass( "ui-accordion-header-icon ui-icon " + icons.header )
1631
.prependTo( this.headers );
1632
this.active.children( ".ui-accordion-header-icon" )
1633
.removeClass( icons.header )
1634
.addClass( icons.activeHeader );
1635
this.headers.addClass( "ui-accordion-icons" );
1639
_destroyIcons: function() {
1641
.removeClass( "ui-accordion-icons" )
1642
.children( ".ui-accordion-header-icon" )
1646
_destroy: function() {
1649
// clean up main element
1651
.removeClass( "ui-accordion ui-widget ui-helper-reset" )
1652
.removeAttr( "role" );
1656
.removeClass( "ui-accordion-header ui-accordion-header-active ui-state-default " +
1657
"ui-corner-all ui-state-active ui-state-disabled ui-corner-top" )
1658
.removeAttr( "role" )
1659
.removeAttr( "aria-expanded" )
1660
.removeAttr( "aria-selected" )
1661
.removeAttr( "aria-controls" )
1662
.removeAttr( "tabIndex" )
1665
this._destroyIcons();
1667
// clean up content panels
1668
contents = this.headers.next()
1669
.removeClass( "ui-helper-reset ui-widget-content ui-corner-bottom " +
1670
"ui-accordion-content ui-accordion-content-active ui-state-disabled" )
1671
.css( "display", "" )
1672
.removeAttr( "role" )
1673
.removeAttr( "aria-hidden" )
1674
.removeAttr( "aria-labelledby" )
1677
if ( this.options.heightStyle !== "content" ) {
1678
contents.css( "height", "" );
1682
_setOption: function( key, value ) {
1683
if ( key === "active" ) {
1684
// _activate() will handle invalid values and update this.options
1685
this._activate( value );
1689
if ( key === "event" ) {
1690
if ( this.options.event ) {
1691
this._off( this.headers, this.options.event );
1693
this._setupEvents( value );
1696
this._super( key, value );
1698
// setting collapsible: false while collapsed; open first panel
1699
if ( key === "collapsible" && !value && this.options.active === false ) {
1700
this._activate( 0 );
1703
if ( key === "icons" ) {
1704
this._destroyIcons();
1706
this._createIcons();
1710
// #5332 - opacity doesn't cascade to positioned elements in IE
1711
// so we need to add the disabled class to the headers and panels
1712
if ( key === "disabled" ) {
1714
.toggleClass( "ui-state-disabled", !!value )
1715
.attr( "aria-disabled", value );
1716
this.headers.add( this.headers.next() )
1717
.toggleClass( "ui-state-disabled", !!value );
1721
_keydown: function( event ) {
1722
if ( event.altKey || event.ctrlKey ) {
1726
var keyCode = $.ui.keyCode,
1727
length = this.headers.length,
1728
currentIndex = this.headers.index( event.target ),
1731
switch ( event.keyCode ) {
1734
toFocus = this.headers[ ( currentIndex + 1 ) % length ];
1738
toFocus = this.headers[ ( currentIndex - 1 + length ) % length ];
1742
this._eventHandler( event );
1745
toFocus = this.headers[ 0 ];
1748
toFocus = this.headers[ length - 1 ];
1753
$( event.target ).attr( "tabIndex", -1 );
1754
$( toFocus ).attr( "tabIndex", 0 );
1756
event.preventDefault();
1760
_panelKeyDown: function( event ) {
1761
if ( event.keyCode === $.ui.keyCode.UP && event.ctrlKey ) {
1762
$( event.currentTarget ).prev().focus();
1766
refresh: function() {
1767
var options = this.options;
1768
this._processPanels();
1770
// was collapsed or no panel
1771
if ( ( options.active === false && options.collapsible === true ) || !this.headers.length ) {
1772
options.active = false;
1774
// active false only when collapsible is true
1775
} else if ( options.active === false ) {
1776
this._activate( 0 );
1777
// was active, but active panel is gone
1778
} else if ( this.active.length && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
1779
// all remaining panel are disabled
1780
if ( this.headers.length === this.headers.find(".ui-state-disabled").length ) {
1781
options.active = false;
1783
// activate previous panel
1785
this._activate( Math.max( 0, options.active - 1 ) );
1787
// was active, active panel still exists
1789
// make sure active index is correct
1790
options.active = this.headers.index( this.active );
1793
this._destroyIcons();
1798
_processPanels: function() {
1799
var prevHeaders = this.headers,
1800
prevPanels = this.panels;
1802
this.headers = this.element.find( this.options.header )
1803
.addClass( "ui-accordion-header ui-state-default ui-corner-all" );
1805
this.panels = this.headers.next()
1806
.addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" )
1807
.filter( ":not(.ui-accordion-content-active)" )
1810
// Avoid memory leaks (#10056)
1812
this._off( prevHeaders.not( this.headers ) );
1813
this._off( prevPanels.not( this.panels ) );
1817
_refresh: function() {
1819
options = this.options,
1820
heightStyle = options.heightStyle,
1821
parent = this.element.parent();
1823
this.active = this._findActive( options.active )
1824
.addClass( "ui-accordion-header-active ui-state-active ui-corner-top" )
1825
.removeClass( "ui-corner-all" );
1827
.addClass( "ui-accordion-content-active" )
1831
.attr( "role", "tab" )
1833
var header = $( this ),
1834
headerId = header.uniqueId().attr( "id" ),
1835
panel = header.next(),
1836
panelId = panel.uniqueId().attr( "id" );
1837
header.attr( "aria-controls", panelId );
1838
panel.attr( "aria-labelledby", headerId );
1841
.attr( "role", "tabpanel" );
1846
"aria-selected": "false",
1847
"aria-expanded": "false",
1852
"aria-hidden": "true"
1856
// make sure at least one header is in the tab order
1857
if ( !this.active.length ) {
1858
this.headers.eq( 0 ).attr( "tabIndex", 0 );
1861
"aria-selected": "true",
1862
"aria-expanded": "true",
1867
"aria-hidden": "false"
1871
this._createIcons();
1873
this._setupEvents( options.event );
1875
if ( heightStyle === "fill" ) {
1876
maxHeight = parent.height();
1877
this.element.siblings( ":visible" ).each(function() {
1878
var elem = $( this ),
1879
position = elem.css( "position" );
1881
if ( position === "absolute" || position === "fixed" ) {
1884
maxHeight -= elem.outerHeight( true );
1887
this.headers.each(function() {
1888
maxHeight -= $( this ).outerHeight( true );
1893
$( this ).height( Math.max( 0, maxHeight -
1894
$( this ).innerHeight() + $( this ).height() ) );
1896
.css( "overflow", "auto" );
1897
} else if ( heightStyle === "auto" ) {
1901
maxHeight = Math.max( maxHeight, $( this ).css( "height", "" ).height() );
1903
.height( maxHeight );
1907
_activate: function( index ) {
1908
var active = this._findActive( index )[ 0 ];
1910
// trying to activate the already active panel
1911
if ( active === this.active[ 0 ] ) {
1915
// trying to collapse, simulate a click on the currently active header
1916
active = active || this.active[ 0 ];
1918
this._eventHandler({
1920
currentTarget: active,
1921
preventDefault: $.noop
1925
_findActive: function( selector ) {
1926
return typeof selector === "number" ? this.headers.eq( selector ) : $();
1929
_setupEvents: function( event ) {
1934
$.each( event.split( " " ), function( index, eventName ) {
1935
events[ eventName ] = "_eventHandler";
1939
this._off( this.headers.add( this.headers.next() ) );
1940
this._on( this.headers, events );
1941
this._on( this.headers.next(), { keydown: "_panelKeyDown" });
1942
this._hoverable( this.headers );
1943
this._focusable( this.headers );
1946
_eventHandler: function( event ) {
1947
var options = this.options,
1948
active = this.active,
1949
clicked = $( event.currentTarget ),
1950
clickedIsActive = clicked[ 0 ] === active[ 0 ],
1951
collapsing = clickedIsActive && options.collapsible,
1952
toShow = collapsing ? $() : clicked.next(),
1953
toHide = active.next(),
1957
newHeader: collapsing ? $() : clicked,
1961
event.preventDefault();
1964
// click on active header, but not collapsible
1965
( clickedIsActive && !options.collapsible ) ||
1966
// allow canceling activation
1967
( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
1971
options.active = collapsing ? false : this.headers.index( clicked );
1973
// when the call to ._toggle() comes after the class changes
1974
// it causes a very odd bug in IE 8 (see #6720)
1975
this.active = clickedIsActive ? $() : clicked;
1976
this._toggle( eventData );
1979
// corner classes on the previously active header stay after the animation
1980
active.removeClass( "ui-accordion-header-active ui-state-active" );
1981
if ( options.icons ) {
1982
active.children( ".ui-accordion-header-icon" )
1983
.removeClass( options.icons.activeHeader )
1984
.addClass( options.icons.header );
1987
if ( !clickedIsActive ) {
1989
.removeClass( "ui-corner-all" )
1990
.addClass( "ui-accordion-header-active ui-state-active ui-corner-top" );
1991
if ( options.icons ) {
1992
clicked.children( ".ui-accordion-header-icon" )
1993
.removeClass( options.icons.header )
1994
.addClass( options.icons.activeHeader );
1999
.addClass( "ui-accordion-content-active" );
2003
_toggle: function( data ) {
2004
var toShow = data.newPanel,
2005
toHide = this.prevShow.length ? this.prevShow : data.oldPanel;
2007
// handle activating a panel during the animation for another activation
2008
this.prevShow.add( this.prevHide ).stop( true, true );
2009
this.prevShow = toShow;
2010
this.prevHide = toHide;
2012
if ( this.options.animate ) {
2013
this._animate( toShow, toHide, data );
2017
this._toggleComplete( data );
2021
"aria-hidden": "true"
2023
toHide.prev().attr({
2024
"aria-selected": "false",
2025
"aria-expanded": "false"
2027
// if we're switching panels, remove the old header from the tab order
2028
// if we're opening from collapsed state, remove the previous header from the tab order
2029
// if we're collapsing, then keep the collapsing header in the tab order
2030
if ( toShow.length && toHide.length ) {
2031
toHide.prev().attr({
2033
"aria-expanded": "false"
2035
} else if ( toShow.length ) {
2036
this.headers.filter(function() {
2037
return parseInt( $( this ).attr( "tabIndex" ), 10 ) === 0;
2039
.attr( "tabIndex", -1 );
2043
.attr( "aria-hidden", "false" )
2046
"aria-selected": "true",
2047
"aria-expanded": "true",
2052
_animate: function( toShow, toHide, data ) {
2053
var total, easing, duration,
2056
boxSizing = toShow.css( "box-sizing" ),
2057
down = toShow.length &&
2058
( !toHide.length || ( toShow.index() < toHide.index() ) ),
2059
animate = this.options.animate || {},
2060
options = down && animate.down || animate,
2061
complete = function() {
2062
that._toggleComplete( data );
2065
if ( typeof options === "number" ) {
2068
if ( typeof options === "string" ) {
2071
// fall back from options to animation in case of partial down settings
2072
easing = easing || options.easing || animate.easing;
2073
duration = duration || options.duration || animate.duration;
2075
if ( !toHide.length ) {
2076
return toShow.animate( this.showProps, duration, easing, complete );
2078
if ( !toShow.length ) {
2079
return toHide.animate( this.hideProps, duration, easing, complete );
2082
total = toShow.show().outerHeight();
2083
toHide.animate( this.hideProps, {
2086
step: function( now, fx ) {
2087
fx.now = Math.round( now );
2092
.animate( this.showProps, {
2096
step: function( now, fx ) {
2097
fx.now = Math.round( now );
2098
if ( fx.prop !== "height" ) {
2099
if ( boxSizing === "content-box" ) {
2102
} else if ( that.options.heightStyle !== "content" ) {
2103
fx.now = Math.round( total - toHide.outerHeight() - adjust );
2110
_toggleComplete: function( data ) {
2111
var toHide = data.oldPanel;
2114
.removeClass( "ui-accordion-content-active" )
2116
.removeClass( "ui-corner-top" )
2117
.addClass( "ui-corner-all" );
2119
// Work around for rendering bug in IE (#5421)
2120
if ( toHide.length ) {
2121
toHide.parent()[ 0 ].className = toHide.parent()[ 0 ].className;
2123
this._trigger( "activate", null, data );
2129
* jQuery UI Menu 1.11.4
2130
* http://jqueryui.com
2132
* Copyright jQuery Foundation and other contributors
2133
* Released under the MIT license.
2134
* http://jquery.org/license
2136
* http://api.jqueryui.com/menu/
2140
var menu = $.widget( "ui.menu", {
2142
defaultElement: "<ul>",
2146
submenu: "ui-icon-carat-1-e"
2162
_create: function() {
2163
this.activeMenu = this.element;
2165
// Flag used to prevent firing of the click handler
2166
// as the event bubbles up through nested menus
2167
this.mouseHandled = false;
2170
.addClass( "ui-menu ui-widget ui-widget-content" )
2171
.toggleClass( "ui-menu-icons", !!this.element.find( ".ui-icon" ).length )
2173
role: this.options.role,
2177
if ( this.options.disabled ) {
2179
.addClass( "ui-state-disabled" )
2180
.attr( "aria-disabled", "true" );
2184
// Prevent focus from sticking to links inside menu after clicking
2185
// them (focus should always stay on UL during navigation).
2186
"mousedown .ui-menu-item": function( event ) {
2187
event.preventDefault();
2189
"click .ui-menu-item": function( event ) {
2190
var target = $( event.target );
2191
if ( !this.mouseHandled && target.not( ".ui-state-disabled" ).length ) {
2192
this.select( event );
2194
// Only set the mouseHandled flag if the event will bubble, see #9469.
2195
if ( !event.isPropagationStopped() ) {
2196
this.mouseHandled = true;
2199
// Open submenu on click
2200
if ( target.has( ".ui-menu" ).length ) {
2201
this.expand( event );
2202
} else if ( !this.element.is( ":focus" ) && $( this.document[ 0 ].activeElement ).closest( ".ui-menu" ).length ) {
2204
// Redirect focus to the menu
2205
this.element.trigger( "focus", [ true ] );
2207
// If the active item is on the top level, let it stay active.
2208
// Otherwise, blur the active item since it is no longer visible.
2209
if ( this.active && this.active.parents( ".ui-menu" ).length === 1 ) {
2210
clearTimeout( this.timer );
2215
"mouseenter .ui-menu-item": function( event ) {
2216
// Ignore mouse events while typeahead is active, see #10458.
2217
// Prevents focusing the wrong item when typeahead causes a scroll while the mouse
2218
// is over an item in the menu
2219
if ( this.previousFilter ) {
2222
var target = $( event.currentTarget );
2223
// Remove ui-state-active class from siblings of the newly focused menu item
2224
// to avoid a jump caused by adjacent elements both having a class with a border
2225
target.siblings( ".ui-state-active" ).removeClass( "ui-state-active" );
2226
this.focus( event, target );
2228
mouseleave: "collapseAll",
2229
"mouseleave .ui-menu": "collapseAll",
2230
focus: function( event, keepActiveItem ) {
2231
// If there's already an active item, keep it active
2232
// If not, activate the first item
2233
var item = this.active || this.element.find( this.options.items ).eq( 0 );
2235
if ( !keepActiveItem ) {
2236
this.focus( event, item );
2239
blur: function( event ) {
2240
this._delay(function() {
2241
if ( !$.contains( this.element[0], this.document[0].activeElement ) ) {
2242
this.collapseAll( event );
2251
// Clicks outside of a menu collapse any open menus
2252
this._on( this.document, {
2253
click: function( event ) {
2254
if ( this._closeOnDocumentClick( event ) ) {
2255
this.collapseAll( event );
2258
// Reset the mouseHandled flag
2259
this.mouseHandled = false;
2264
_destroy: function() {
2265
// Destroy (sub)menus
2267
.removeAttr( "aria-activedescendant" )
2268
.find( ".ui-menu" ).addBack()
2269
.removeClass( "ui-menu ui-widget ui-widget-content ui-menu-icons ui-front" )
2270
.removeAttr( "role" )
2271
.removeAttr( "tabIndex" )
2272
.removeAttr( "aria-labelledby" )
2273
.removeAttr( "aria-expanded" )
2274
.removeAttr( "aria-hidden" )
2275
.removeAttr( "aria-disabled" )
2279
// Destroy menu items
2280
this.element.find( ".ui-menu-item" )
2281
.removeClass( "ui-menu-item" )
2282
.removeAttr( "role" )
2283
.removeAttr( "aria-disabled" )
2285
.removeClass( "ui-state-hover" )
2286
.removeAttr( "tabIndex" )
2287
.removeAttr( "role" )
2288
.removeAttr( "aria-haspopup" )
2289
.children().each( function() {
2290
var elem = $( this );
2291
if ( elem.data( "ui-menu-submenu-carat" ) ) {
2296
// Destroy menu dividers
2297
this.element.find( ".ui-menu-divider" ).removeClass( "ui-menu-divider ui-widget-content" );
2300
_keydown: function( event ) {
2301
var match, prev, character, skip,
2302
preventDefault = true;
2304
switch ( event.keyCode ) {
2305
case $.ui.keyCode.PAGE_UP:
2306
this.previousPage( event );
2308
case $.ui.keyCode.PAGE_DOWN:
2309
this.nextPage( event );
2311
case $.ui.keyCode.HOME:
2312
this._move( "first", "first", event );
2314
case $.ui.keyCode.END:
2315
this._move( "last", "last", event );
2317
case $.ui.keyCode.UP:
2318
this.previous( event );
2320
case $.ui.keyCode.DOWN:
2323
case $.ui.keyCode.LEFT:
2324
this.collapse( event );
2326
case $.ui.keyCode.RIGHT:
2327
if ( this.active && !this.active.is( ".ui-state-disabled" ) ) {
2328
this.expand( event );
2331
case $.ui.keyCode.ENTER:
2332
case $.ui.keyCode.SPACE:
2333
this._activate( event );
2335
case $.ui.keyCode.ESCAPE:
2336
this.collapse( event );
2339
preventDefault = false;
2340
prev = this.previousFilter || "";
2341
character = String.fromCharCode( event.keyCode );
2344
clearTimeout( this.filterTimer );
2346
if ( character === prev ) {
2349
character = prev + character;
2352
match = this._filterMenuItems( character );
2353
match = skip && match.index( this.active.next() ) !== -1 ?
2354
this.active.nextAll( ".ui-menu-item" ) :
2357
// If no matches on the current filter, reset to the last character pressed
2358
// to move down the menu to the first item that starts with that character
2359
if ( !match.length ) {
2360
character = String.fromCharCode( event.keyCode );
2361
match = this._filterMenuItems( character );
2364
if ( match.length ) {
2365
this.focus( event, match );
2366
this.previousFilter = character;
2367
this.filterTimer = this._delay(function() {
2368
delete this.previousFilter;
2371
delete this.previousFilter;
2375
if ( preventDefault ) {
2376
event.preventDefault();
2380
_activate: function( event ) {
2381
if ( !this.active.is( ".ui-state-disabled" ) ) {
2382
if ( this.active.is( "[aria-haspopup='true']" ) ) {
2383
this.expand( event );
2385
this.select( event );
2390
refresh: function() {
2393
icon = this.options.icons.submenu,
2394
submenus = this.element.find( this.options.menus );
2396
this.element.toggleClass( "ui-menu-icons", !!this.element.find( ".ui-icon" ).length );
2398
// Initialize nested menus
2399
submenus.filter( ":not(.ui-menu)" )
2400
.addClass( "ui-menu ui-widget ui-widget-content ui-front" )
2403
role: this.options.role,
2404
"aria-hidden": "true",
2405
"aria-expanded": "false"
2408
var menu = $( this ),
2409
item = menu.parent(),
2410
submenuCarat = $( "<span>" )
2411
.addClass( "ui-menu-icon ui-icon " + icon )
2412
.data( "ui-menu-submenu-carat", true );
2415
.attr( "aria-haspopup", "true" )
2416
.prepend( submenuCarat );
2417
menu.attr( "aria-labelledby", item.attr( "id" ) );
2420
menus = submenus.add( this.element );
2421
items = menus.find( this.options.items );
2423
// Initialize menu-items containing spaces and/or dashes only as dividers
2424
items.not( ".ui-menu-item" ).each(function() {
2425
var item = $( this );
2426
if ( that._isDivider( item ) ) {
2427
item.addClass( "ui-widget-content ui-menu-divider" );
2431
// Don't refresh list items that are already adapted
2432
items.not( ".ui-menu-item, .ui-menu-divider" )
2433
.addClass( "ui-menu-item" )
2437
role: this._itemRole()
2440
// Add aria-disabled attribute to any disabled menu item
2441
items.filter( ".ui-state-disabled" ).attr( "aria-disabled", "true" );
2443
// If the active item has been removed, blur the menu
2444
if ( this.active && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
2449
_itemRole: function() {
2453
}[ this.options.role ];
2456
_setOption: function( key, value ) {
2457
if ( key === "icons" ) {
2458
this.element.find( ".ui-menu-icon" )
2459
.removeClass( this.options.icons.submenu )
2460
.addClass( value.submenu );
2462
if ( key === "disabled" ) {
2464
.toggleClass( "ui-state-disabled", !!value )
2465
.attr( "aria-disabled", value );
2467
this._super( key, value );
2470
focus: function( event, item ) {
2471
var nested, focused;
2472
this.blur( event, event && event.type === "focus" );
2474
this._scrollIntoView( item );
2476
this.active = item.first();
2477
focused = this.active.addClass( "ui-state-focus" ).removeClass( "ui-state-active" );
2478
// Only update aria-activedescendant if there's a role
2479
// otherwise we assume focus is managed elsewhere
2480
if ( this.options.role ) {
2481
this.element.attr( "aria-activedescendant", focused.attr( "id" ) );
2484
// Highlight active parent menu item, if any
2487
.closest( ".ui-menu-item" )
2488
.addClass( "ui-state-active" );
2490
if ( event && event.type === "keydown" ) {
2493
this.timer = this._delay(function() {
2498
nested = item.children( ".ui-menu" );
2499
if ( nested.length && event && ( /^mouse/.test( event.type ) ) ) {
2500
this._startOpening(nested);
2502
this.activeMenu = item.parent();
2504
this._trigger( "focus", event, { item: item } );
2507
_scrollIntoView: function( item ) {
2508
var borderTop, paddingTop, offset, scroll, elementHeight, itemHeight;
2509
if ( this._hasScroll() ) {
2510
borderTop = parseFloat( $.css( this.activeMenu[0], "borderTopWidth" ) ) || 0;
2511
paddingTop = parseFloat( $.css( this.activeMenu[0], "paddingTop" ) ) || 0;
2512
offset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop;
2513
scroll = this.activeMenu.scrollTop();
2514
elementHeight = this.activeMenu.height();
2515
itemHeight = item.outerHeight();
2518
this.activeMenu.scrollTop( scroll + offset );
2519
} else if ( offset + itemHeight > elementHeight ) {
2520
this.activeMenu.scrollTop( scroll + offset - elementHeight + itemHeight );
2525
blur: function( event, fromFocus ) {
2527
clearTimeout( this.timer );
2530
if ( !this.active ) {
2534
this.active.removeClass( "ui-state-focus" );
2537
this._trigger( "blur", event, { item: this.active } );
2540
_startOpening: function( submenu ) {
2541
clearTimeout( this.timer );
2543
// Don't open if already open fixes a Firefox bug that caused a .5 pixel
2544
// shift in the submenu position when mousing over the carat icon
2545
if ( submenu.attr( "aria-hidden" ) !== "true" ) {
2549
this.timer = this._delay(function() {
2551
this._open( submenu );
2555
_open: function( submenu ) {
2556
var position = $.extend({
2558
}, this.options.position );
2560
clearTimeout( this.timer );
2561
this.element.find( ".ui-menu" ).not( submenu.parents( ".ui-menu" ) )
2563
.attr( "aria-hidden", "true" );
2567
.removeAttr( "aria-hidden" )
2568
.attr( "aria-expanded", "true" )
2569
.position( position );
2572
collapseAll: function( event, all ) {
2573
clearTimeout( this.timer );
2574
this.timer = this._delay(function() {
2575
// If we were passed an event, look for the submenu that contains the event
2576
var currentMenu = all ? this.element :
2577
$( event && event.target ).closest( this.element.find( ".ui-menu" ) );
2579
// If we found no valid submenu ancestor, use the main menu to close all sub menus anyway
2580
if ( !currentMenu.length ) {
2581
currentMenu = this.element;
2584
this._close( currentMenu );
2587
this.activeMenu = currentMenu;
2591
// With no arguments, closes the currently active menu - if nothing is active
2592
// it closes all menus. If passed an argument, it will search for menus BELOW
2593
_close: function( startMenu ) {
2595
startMenu = this.active ? this.active.parent() : this.element;
2601
.attr( "aria-hidden", "true" )
2602
.attr( "aria-expanded", "false" )
2604
.find( ".ui-state-active" ).not( ".ui-state-focus" )
2605
.removeClass( "ui-state-active" );
2608
_closeOnDocumentClick: function( event ) {
2609
return !$( event.target ).closest( ".ui-menu" ).length;
2612
_isDivider: function( item ) {
2614
// Match hyphen, em dash, en dash
2615
return !/[^\-\u2014\u2013\s]/.test( item.text() );
2618
collapse: function( event ) {
2619
var newItem = this.active &&
2620
this.active.parent().closest( ".ui-menu-item", this.element );
2621
if ( newItem && newItem.length ) {
2623
this.focus( event, newItem );
2627
expand: function( event ) {
2628
var newItem = this.active &&
2630
.children( ".ui-menu " )
2631
.find( this.options.items )
2634
if ( newItem && newItem.length ) {
2635
this._open( newItem.parent() );
2637
// Delay so Firefox will not hide activedescendant change in expanding submenu from AT
2638
this._delay(function() {
2639
this.focus( event, newItem );
2644
next: function( event ) {
2645
this._move( "next", "first", event );
2648
previous: function( event ) {
2649
this._move( "prev", "last", event );
2652
isFirstItem: function() {
2653
return this.active && !this.active.prevAll( ".ui-menu-item" ).length;
2656
isLastItem: function() {
2657
return this.active && !this.active.nextAll( ".ui-menu-item" ).length;
2660
_move: function( direction, filter, event ) {
2662
if ( this.active ) {
2663
if ( direction === "first" || direction === "last" ) {
2665
[ direction === "first" ? "prevAll" : "nextAll" ]( ".ui-menu-item" )
2669
[ direction + "All" ]( ".ui-menu-item" )
2673
if ( !next || !next.length || !this.active ) {
2674
next = this.activeMenu.find( this.options.items )[ filter ]();
2677
this.focus( event, next );
2680
nextPage: function( event ) {
2681
var item, base, height;
2683
if ( !this.active ) {
2687
if ( this.isLastItem() ) {
2690
if ( this._hasScroll() ) {
2691
base = this.active.offset().top;
2692
height = this.element.height();
2693
this.active.nextAll( ".ui-menu-item" ).each(function() {
2695
return item.offset().top - base - height < 0;
2698
this.focus( event, item );
2700
this.focus( event, this.activeMenu.find( this.options.items )
2701
[ !this.active ? "first" : "last" ]() );
2705
previousPage: function( event ) {
2706
var item, base, height;
2707
if ( !this.active ) {
2711
if ( this.isFirstItem() ) {
2714
if ( this._hasScroll() ) {
2715
base = this.active.offset().top;
2716
height = this.element.height();
2717
this.active.prevAll( ".ui-menu-item" ).each(function() {
2719
return item.offset().top - base + height > 0;
2722
this.focus( event, item );
2724
this.focus( event, this.activeMenu.find( this.options.items ).first() );
2728
_hasScroll: function() {
2729
return this.element.outerHeight() < this.element.prop( "scrollHeight" );
2732
select: function( event ) {
2733
// TODO: It should never be possible to not have an active item at this
2734
// point, but the tests don't trigger mouseenter before click.
2735
this.active = this.active || $( event.target ).closest( ".ui-menu-item" );
2736
var ui = { item: this.active };
2737
if ( !this.active.has( ".ui-menu" ).length ) {
2738
this.collapseAll( event, true );
2740
this._trigger( "select", event, ui );
2743
_filterMenuItems: function(character) {
2744
var escapedCharacter = character.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" ),
2745
regex = new RegExp( "^" + escapedCharacter, "i" );
2747
return this.activeMenu
2748
.find( this.options.items )
2750
// Only match on items, not dividers or other content (#10571)
2751
.filter( ".ui-menu-item" )
2752
.filter(function() {
2753
return regex.test( $.trim( $( this ).text() ) );
2760
* jQuery UI Autocomplete 1.11.4
2761
* http://jqueryui.com
2763
* Copyright jQuery Foundation and other contributors
2764
* Released under the MIT license.
2765
* http://jquery.org/license
2767
* http://api.jqueryui.com/autocomplete/
2771
$.widget( "ui.autocomplete", {
2773
defaultElement: "<input>",
2799
_create: function() {
2800
// Some browsers only repeat keydown events, not keypress events,
2801
// so we use the suppressKeyPress flag to determine if we've already
2802
// handled the keydown event. #7269
2803
// Unfortunately the code for & in keypress is the same as the up arrow,
2804
// so we use the suppressKeyPressRepeat flag to avoid handling keypress
2805
// events when we know the keydown event was used to modify the
2806
// search term. #7799
2807
var suppressKeyPress, suppressKeyPressRepeat, suppressInput,
2808
nodeName = this.element[ 0 ].nodeName.toLowerCase(),
2809
isTextarea = nodeName === "textarea",
2810
isInput = nodeName === "input";
2813
// Textareas are always multi-line
2815
// Inputs are always single-line, even if inside a contentEditable element
2816
// IE also treats inputs as contentEditable
2818
// All other element types are determined by whether or not they're contentEditable
2819
this.element.prop( "isContentEditable" );
2821
this.valueMethod = this.element[ isTextarea || isInput ? "val" : "text" ];
2822
this.isNewMenu = true;
2825
.addClass( "ui-autocomplete-input" )
2826
.attr( "autocomplete", "off" );
2828
this._on( this.element, {
2829
keydown: function( event ) {
2830
if ( this.element.prop( "readOnly" ) ) {
2831
suppressKeyPress = true;
2832
suppressInput = true;
2833
suppressKeyPressRepeat = true;
2837
suppressKeyPress = false;
2838
suppressInput = false;
2839
suppressKeyPressRepeat = false;
2840
var keyCode = $.ui.keyCode;
2841
switch ( event.keyCode ) {
2842
case keyCode.PAGE_UP:
2843
suppressKeyPress = true;
2844
this._move( "previousPage", event );
2846
case keyCode.PAGE_DOWN:
2847
suppressKeyPress = true;
2848
this._move( "nextPage", event );
2851
suppressKeyPress = true;
2852
this._keyEvent( "previous", event );
2855
suppressKeyPress = true;
2856
this._keyEvent( "next", event );
2859
// when menu is open and has focus
2860
if ( this.menu.active ) {
2861
// #6055 - Opera still allows the keypress to occur
2862
// which causes forms to submit
2863
suppressKeyPress = true;
2864
event.preventDefault();
2865
this.menu.select( event );
2869
if ( this.menu.active ) {
2870
this.menu.select( event );
2873
case keyCode.ESCAPE:
2874
if ( this.menu.element.is( ":visible" ) ) {
2875
if ( !this.isMultiLine ) {
2876
this._value( this.term );
2878
this.close( event );
2879
// Different browsers have different default behavior for escape
2880
// Single press can mean undo or clear
2881
// Double press in IE means clear the whole form
2882
event.preventDefault();
2886
suppressKeyPressRepeat = true;
2887
// search timeout should be triggered before the input value is changed
2888
this._searchTimeout( event );
2892
keypress: function( event ) {
2893
if ( suppressKeyPress ) {
2894
suppressKeyPress = false;
2895
if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
2896
event.preventDefault();
2900
if ( suppressKeyPressRepeat ) {
2904
// replicate some key handlers to allow them to repeat in Firefox and Opera
2905
var keyCode = $.ui.keyCode;
2906
switch ( event.keyCode ) {
2907
case keyCode.PAGE_UP:
2908
this._move( "previousPage", event );
2910
case keyCode.PAGE_DOWN:
2911
this._move( "nextPage", event );
2914
this._keyEvent( "previous", event );
2917
this._keyEvent( "next", event );
2921
input: function( event ) {
2922
if ( suppressInput ) {
2923
suppressInput = false;
2924
event.preventDefault();
2927
this._searchTimeout( event );
2930
this.selectedItem = null;
2931
this.previous = this._value();
2933
blur: function( event ) {
2934
if ( this.cancelBlur ) {
2935
delete this.cancelBlur;
2939
clearTimeout( this.searching );
2940
this.close( event );
2941
this._change( event );
2946
this.menu = $( "<ul>" )
2947
.addClass( "ui-autocomplete ui-front" )
2948
.appendTo( this._appendTo() )
2950
// disable ARIA support, the live region takes care of that
2954
.menu( "instance" );
2956
this._on( this.menu.element, {
2957
mousedown: function( event ) {
2958
// prevent moving focus out of the text field
2959
event.preventDefault();
2961
// IE doesn't prevent moving focus even with event.preventDefault()
2962
// so we set a flag to know when we should ignore the blur event
2963
this.cancelBlur = true;
2964
this._delay(function() {
2965
delete this.cancelBlur;
2968
// clicking on the scrollbar causes focus to shift to the body
2969
// but we can't detect a mouseup or a click immediately afterward
2970
// so we have to track the next mousedown and close the menu if
2971
// the user clicks somewhere outside of the autocomplete
2972
var menuElement = this.menu.element[ 0 ];
2973
if ( !$( event.target ).closest( ".ui-menu-item" ).length ) {
2974
this._delay(function() {
2976
this.document.one( "mousedown", function( event ) {
2977
if ( event.target !== that.element[ 0 ] &&
2978
event.target !== menuElement &&
2979
!$.contains( menuElement, event.target ) ) {
2986
menufocus: function( event, ui ) {
2989
// Prevent accidental activation of menu items in Firefox (#7024 #9118)
2990
if ( this.isNewMenu ) {
2991
this.isNewMenu = false;
2992
if ( event.originalEvent && /^mouse/.test( event.originalEvent.type ) ) {
2995
this.document.one( "mousemove", function() {
2996
$( event.target ).trigger( event.originalEvent );
3003
item = ui.item.data( "ui-autocomplete-item" );
3004
if ( false !== this._trigger( "focus", event, { item: item } ) ) {
3005
// use value to match what will end up in the input, if it was a key event
3006
if ( event.originalEvent && /^key/.test( event.originalEvent.type ) ) {
3007
this._value( item.value );
3011
// Announce the value in the liveRegion
3012
label = ui.item.attr( "aria-label" ) || item.value;
3013
if ( label && $.trim( label ).length ) {
3014
this.liveRegion.children().hide();
3015
$( "<div>" ).text( label ).appendTo( this.liveRegion );
3018
menuselect: function( event, ui ) {
3019
var item = ui.item.data( "ui-autocomplete-item" ),
3020
previous = this.previous;
3022
// only trigger when focus was lost (click on menu)
3023
if ( this.element[ 0 ] !== this.document[ 0 ].activeElement ) {
3024
this.element.focus();
3025
this.previous = previous;
3026
// #6109 - IE triggers two focus events and the second
3027
// is asynchronous, so we need to reset the previous
3028
// term synchronously and asynchronously :-(
3029
this._delay(function() {
3030
this.previous = previous;
3031
this.selectedItem = item;
3035
if ( false !== this._trigger( "select", event, { item: item } ) ) {
3036
this._value( item.value );
3038
// reset the term after the select event
3039
// this allows custom select handling to work properly
3040
this.term = this._value();
3042
this.close( event );
3043
this.selectedItem = item;
3047
this.liveRegion = $( "<span>", {
3049
"aria-live": "assertive",
3050
"aria-relevant": "additions"
3052
.addClass( "ui-helper-hidden-accessible" )
3053
.appendTo( this.document[ 0 ].body );
3055
// turning off autocomplete prevents the browser from remembering the
3056
// value when navigating through history, so we re-enable autocomplete
3057
// if the page is unloaded before the widget is destroyed. #7790
3058
this._on( this.window, {
3059
beforeunload: function() {
3060
this.element.removeAttr( "autocomplete" );
3065
_destroy: function() {
3066
clearTimeout( this.searching );
3068
.removeClass( "ui-autocomplete-input" )
3069
.removeAttr( "autocomplete" );
3070
this.menu.element.remove();
3071
this.liveRegion.remove();
3074
_setOption: function( key, value ) {
3075
this._super( key, value );
3076
if ( key === "source" ) {
3079
if ( key === "appendTo" ) {
3080
this.menu.element.appendTo( this._appendTo() );
3082
if ( key === "disabled" && value && this.xhr ) {
3087
_appendTo: function() {
3088
var element = this.options.appendTo;
3091
element = element.jquery || element.nodeType ?
3093
this.document.find( element ).eq( 0 );
3096
if ( !element || !element[ 0 ] ) {
3097
element = this.element.closest( ".ui-front" );
3100
if ( !element.length ) {
3101
element = this.document[ 0 ].body;
3107
_initSource: function() {
3110
if ( $.isArray( this.options.source ) ) {
3111
array = this.options.source;
3112
this.source = function( request, response ) {
3113
response( $.ui.autocomplete.filter( array, request.term ) );
3115
} else if ( typeof this.options.source === "string" ) {
3116
url = this.options.source;
3117
this.source = function( request, response ) {
3125
success: function( data ) {
3134
this.source = this.options.source;
3138
_searchTimeout: function( event ) {
3139
clearTimeout( this.searching );
3140
this.searching = this._delay(function() {
3142
// Search if the value has changed, or if the user retypes the same value (see #7434)
3143
var equalValues = this.term === this._value(),
3144
menuVisible = this.menu.element.is( ":visible" ),
3145
modifierKey = event.altKey || event.ctrlKey || event.metaKey || event.shiftKey;
3147
if ( !equalValues || ( equalValues && !menuVisible && !modifierKey ) ) {
3148
this.selectedItem = null;
3149
this.search( null, event );
3151
}, this.options.delay );
3154
search: function( value, event ) {
3155
value = value != null ? value : this._value();
3157
// always save the actual value, not the one passed as an argument
3158
this.term = this._value();
3160
if ( value.length < this.options.minLength ) {
3161
return this.close( event );
3164
if ( this._trigger( "search", event ) === false ) {
3168
return this._search( value );
3171
_search: function( value ) {
3173
this.element.addClass( "ui-autocomplete-loading" );
3174
this.cancelSearch = false;
3176
this.source( { term: value }, this._response() );
3179
_response: function() {
3180
var index = ++this.requestIndex;
3182
return $.proxy(function( content ) {
3183
if ( index === this.requestIndex ) {
3184
this.__response( content );
3188
if ( !this.pending ) {
3189
this.element.removeClass( "ui-autocomplete-loading" );
3194
__response: function( content ) {
3196
content = this._normalize( content );
3198
this._trigger( "response", null, { content: content } );
3199
if ( !this.options.disabled && content && content.length && !this.cancelSearch ) {
3200
this._suggest( content );
3201
this._trigger( "open" );
3203
// use ._close() instead of .close() so we don't cancel future searches
3208
close: function( event ) {
3209
this.cancelSearch = true;
3210
this._close( event );
3213
_close: function( event ) {
3214
if ( this.menu.element.is( ":visible" ) ) {
3215
this.menu.element.hide();
3217
this.isNewMenu = true;
3218
this._trigger( "close", event );
3222
_change: function( event ) {
3223
if ( this.previous !== this._value() ) {
3224
this._trigger( "change", event, { item: this.selectedItem } );
3228
_normalize: function( items ) {
3229
// assume all items have the right format when the first item is complete
3230
if ( items.length && items[ 0 ].label && items[ 0 ].value ) {
3233
return $.map( items, function( item ) {
3234
if ( typeof item === "string" ) {
3240
return $.extend( {}, item, {
3241
label: item.label || item.value,
3242
value: item.value || item.label
3247
_suggest: function( items ) {
3248
var ul = this.menu.element.empty();
3249
this._renderMenu( ul, items );
3250
this.isNewMenu = true;
3251
this.menu.refresh();
3253
// size and position menu
3256
ul.position( $.extend({
3258
}, this.options.position ) );
3260
if ( this.options.autoFocus ) {
3265
_resizeMenu: function() {
3266
var ul = this.menu.element;
3267
ul.outerWidth( Math.max(
3268
// Firefox wraps long text (possibly a rounding bug)
3269
// so we add 1px to avoid the wrapping (#7513)
3270
ul.width( "" ).outerWidth() + 1,
3271
this.element.outerWidth()
3275
_renderMenu: function( ul, items ) {
3277
$.each( items, function( index, item ) {
3278
that._renderItemData( ul, item );
3282
_renderItemData: function( ul, item ) {
3283
return this._renderItem( ul, item ).data( "ui-autocomplete-item", item );
3286
_renderItem: function( ul, item ) {
3287
return $( "<li>" ).text( item.label ).appendTo( ul );
3290
_move: function( direction, event ) {
3291
if ( !this.menu.element.is( ":visible" ) ) {
3292
this.search( null, event );
3295
if ( this.menu.isFirstItem() && /^previous/.test( direction ) ||
3296
this.menu.isLastItem() && /^next/.test( direction ) ) {
3298
if ( !this.isMultiLine ) {
3299
this._value( this.term );
3305
this.menu[ direction ]( event );
3308
widget: function() {
3309
return this.menu.element;
3312
_value: function() {
3313
return this.valueMethod.apply( this.element, arguments );
3316
_keyEvent: function( keyEvent, event ) {
3317
if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
3318
this._move( keyEvent, event );
3320
// prevents moving cursor to beginning/end of the text field in some browsers
3321
event.preventDefault();
3326
$.extend( $.ui.autocomplete, {
3327
escapeRegex: function( value ) {
3328
return value.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" );
3330
filter: function( array, term ) {
3331
var matcher = new RegExp( $.ui.autocomplete.escapeRegex( term ), "i" );
3332
return $.grep( array, function( value ) {
3333
return matcher.test( value.label || value.value || value );
3338
// live region extension, adding a `messages` option
3339
// NOTE: This is an experimental API. We are still investigating
3340
// a full solution for string manipulation and internationalization.
3341
$.widget( "ui.autocomplete", $.ui.autocomplete, {
3344
noResults: "No search results.",
3345
results: function( amount ) {
3346
return amount + ( amount > 1 ? " results are" : " result is" ) +
3347
" available, use up and down arrow keys to navigate.";
3352
__response: function( content ) {
3354
this._superApply( arguments );
3355
if ( this.options.disabled || this.cancelSearch ) {
3358
if ( content && content.length ) {
3359
message = this.options.messages.results( content.length );
3361
message = this.options.messages.noResults;
3363
this.liveRegion.children().hide();
3364
$( "<div>" ).text( message ).appendTo( this.liveRegion );
3368
var autocomplete = $.ui.autocomplete;
3372
* jQuery UI Button 1.11.4
3373
* http://jqueryui.com
3375
* Copyright jQuery Foundation and other contributors
3376
* Released under the MIT license.
3377
* http://jquery.org/license
3379
* http://api.jqueryui.com/button/
3384
baseClasses = "ui-button ui-widget ui-state-default ui-corner-all",
3385
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",
3386
formResetHandler = function() {
3387
var form = $( this );
3388
setTimeout(function() {
3389
form.find( ":ui-button" ).button( "refresh" );
3392
radioGroup = function( radio ) {
3393
var name = radio.name,
3397
name = name.replace( /'/g, "\\'" );
3399
radios = $( form ).find( "[name='" + name + "'][type=radio]" );
3401
radios = $( "[name='" + name + "'][type=radio]", radio.ownerDocument )
3402
.filter(function() {
3410
$.widget( "ui.button", {
3412
defaultElement: "<button>",
3422
_create: function() {
3423
this.element.closest( "form" )
3424
.unbind( "reset" + this.eventNamespace )
3425
.bind( "reset" + this.eventNamespace, formResetHandler );
3427
if ( typeof this.options.disabled !== "boolean" ) {
3428
this.options.disabled = !!this.element.prop( "disabled" );
3430
this.element.prop( "disabled", this.options.disabled );
3433
this._determineButtonType();
3434
this.hasTitle = !!this.buttonElement.attr( "title" );
3437
options = this.options,
3438
toggleButton = this.type === "checkbox" || this.type === "radio",
3439
activeClass = !toggleButton ? "ui-state-active" : "";
3441
if ( options.label === null ) {
3442
options.label = (this.type === "input" ? this.buttonElement.val() : this.buttonElement.html());
3445
this._hoverable( this.buttonElement );
3448
.addClass( baseClasses )
3449
.attr( "role", "button" )
3450
.bind( "mouseenter" + this.eventNamespace, function() {
3451
if ( options.disabled ) {
3454
if ( this === lastActive ) {
3455
$( this ).addClass( "ui-state-active" );
3458
.bind( "mouseleave" + this.eventNamespace, function() {
3459
if ( options.disabled ) {
3462
$( this ).removeClass( activeClass );
3464
.bind( "click" + this.eventNamespace, function( event ) {
3465
if ( options.disabled ) {
3466
event.preventDefault();
3467
event.stopImmediatePropagation();
3471
// Can't use _focusable() because the element that receives focus
3472
// and the element that gets the ui-state-focus class are different
3475
this.buttonElement.addClass( "ui-state-focus" );
3478
this.buttonElement.removeClass( "ui-state-focus" );
3482
if ( toggleButton ) {
3483
this.element.bind( "change" + this.eventNamespace, function() {
3488
if ( this.type === "checkbox" ) {
3489
this.buttonElement.bind( "click" + this.eventNamespace, function() {
3490
if ( options.disabled ) {
3494
} else if ( this.type === "radio" ) {
3495
this.buttonElement.bind( "click" + this.eventNamespace, function() {
3496
if ( options.disabled ) {
3499
$( this ).addClass( "ui-state-active" );
3500
that.buttonElement.attr( "aria-pressed", "true" );
3502
var radio = that.element[ 0 ];
3506
return $( this ).button( "widget" )[ 0 ];
3508
.removeClass( "ui-state-active" )
3509
.attr( "aria-pressed", "false" );
3513
.bind( "mousedown" + this.eventNamespace, function() {
3514
if ( options.disabled ) {
3517
$( this ).addClass( "ui-state-active" );
3519
that.document.one( "mouseup", function() {
3523
.bind( "mouseup" + this.eventNamespace, function() {
3524
if ( options.disabled ) {
3527
$( this ).removeClass( "ui-state-active" );
3529
.bind( "keydown" + this.eventNamespace, function(event) {
3530
if ( options.disabled ) {
3533
if ( event.keyCode === $.ui.keyCode.SPACE || event.keyCode === $.ui.keyCode.ENTER ) {
3534
$( this ).addClass( "ui-state-active" );
3537
// see #8559, we bind to blur here in case the button element loses
3538
// focus between keydown and keyup, it would be left in an "active" state
3539
.bind( "keyup" + this.eventNamespace + " blur" + this.eventNamespace, function() {
3540
$( this ).removeClass( "ui-state-active" );
3543
if ( this.buttonElement.is("a") ) {
3544
this.buttonElement.keyup(function(event) {
3545
if ( event.keyCode === $.ui.keyCode.SPACE ) {
3546
// TODO pass through original event correctly (just as 2nd argument doesn't work)
3553
this._setOption( "disabled", options.disabled );
3554
this._resetButton();
3557
_determineButtonType: function() {
3558
var ancestor, labelSelector, checked;
3560
if ( this.element.is("[type=checkbox]") ) {
3561
this.type = "checkbox";
3562
} else if ( this.element.is("[type=radio]") ) {
3563
this.type = "radio";
3564
} else if ( this.element.is("input") ) {
3565
this.type = "input";
3567
this.type = "button";
3570
if ( this.type === "checkbox" || this.type === "radio" ) {
3571
// we don't search against the document in case the element
3572
// is disconnected from the DOM
3573
ancestor = this.element.parents().last();
3574
labelSelector = "label[for='" + this.element.attr("id") + "']";
3575
this.buttonElement = ancestor.find( labelSelector );
3576
if ( !this.buttonElement.length ) {
3577
ancestor = ancestor.length ? ancestor.siblings() : this.element.siblings();
3578
this.buttonElement = ancestor.filter( labelSelector );
3579
if ( !this.buttonElement.length ) {
3580
this.buttonElement = ancestor.find( labelSelector );
3583
this.element.addClass( "ui-helper-hidden-accessible" );
3585
checked = this.element.is( ":checked" );
3587
this.buttonElement.addClass( "ui-state-active" );
3589
this.buttonElement.prop( "aria-pressed", checked );
3591
this.buttonElement = this.element;
3595
widget: function() {
3596
return this.buttonElement;
3599
_destroy: function() {
3601
.removeClass( "ui-helper-hidden-accessible" );
3603
.removeClass( baseClasses + " ui-state-active " + typeClasses )
3604
.removeAttr( "role" )
3605
.removeAttr( "aria-pressed" )
3606
.html( this.buttonElement.find(".ui-button-text").html() );
3608
if ( !this.hasTitle ) {
3609
this.buttonElement.removeAttr( "title" );
3613
_setOption: function( key, value ) {
3614
this._super( key, value );
3615
if ( key === "disabled" ) {
3616
this.widget().toggleClass( "ui-state-disabled", !!value );
3617
this.element.prop( "disabled", !!value );
3619
if ( this.type === "checkbox" || this.type === "radio" ) {
3620
this.buttonElement.removeClass( "ui-state-focus" );
3622
this.buttonElement.removeClass( "ui-state-focus ui-state-active" );
3627
this._resetButton();
3630
refresh: function() {
3632
var isDisabled = this.element.is( "input, button" ) ? this.element.is( ":disabled" ) : this.element.hasClass( "ui-button-disabled" );
3634
if ( isDisabled !== this.options.disabled ) {
3635
this._setOption( "disabled", isDisabled );
3637
if ( this.type === "radio" ) {
3638
radioGroup( this.element[0] ).each(function() {
3639
if ( $( this ).is( ":checked" ) ) {
3640
$( this ).button( "widget" )
3641
.addClass( "ui-state-active" )
3642
.attr( "aria-pressed", "true" );
3644
$( this ).button( "widget" )
3645
.removeClass( "ui-state-active" )
3646
.attr( "aria-pressed", "false" );
3649
} else if ( this.type === "checkbox" ) {
3650
if ( this.element.is( ":checked" ) ) {
3652
.addClass( "ui-state-active" )
3653
.attr( "aria-pressed", "true" );
3656
.removeClass( "ui-state-active" )
3657
.attr( "aria-pressed", "false" );
3662
_resetButton: function() {
3663
if ( this.type === "input" ) {
3664
if ( this.options.label ) {
3665
this.element.val( this.options.label );
3669
var buttonElement = this.buttonElement.removeClass( typeClasses ),
3670
buttonText = $( "<span></span>", this.document[0] )
3671
.addClass( "ui-button-text" )
3672
.html( this.options.label )
3673
.appendTo( buttonElement.empty() )
3675
icons = this.options.icons,
3676
multipleIcons = icons.primary && icons.secondary,
3679
if ( icons.primary || icons.secondary ) {
3680
if ( this.options.text ) {
3681
buttonClasses.push( "ui-button-text-icon" + ( multipleIcons ? "s" : ( icons.primary ? "-primary" : "-secondary" ) ) );
3684
if ( icons.primary ) {
3685
buttonElement.prepend( "<span class='ui-button-icon-primary ui-icon " + icons.primary + "'></span>" );
3688
if ( icons.secondary ) {
3689
buttonElement.append( "<span class='ui-button-icon-secondary ui-icon " + icons.secondary + "'></span>" );
3692
if ( !this.options.text ) {
3693
buttonClasses.push( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" );
3695
if ( !this.hasTitle ) {
3696
buttonElement.attr( "title", $.trim( buttonText ) );
3700
buttonClasses.push( "ui-button-text-only" );
3702
buttonElement.addClass( buttonClasses.join( " " ) );
3706
$.widget( "ui.buttonset", {
3709
items: "button, input[type=button], input[type=submit], input[type=reset], input[type=checkbox], input[type=radio], a, :data(ui-button)"
3712
_create: function() {
3713
this.element.addClass( "ui-buttonset" );
3720
_setOption: function( key, value ) {
3721
if ( key === "disabled" ) {
3722
this.buttons.button( "option", key, value );
3725
this._super( key, value );
3728
refresh: function() {
3729
var rtl = this.element.css( "direction" ) === "rtl",
3730
allButtons = this.element.find( this.options.items ),
3731
existingButtons = allButtons.filter( ":ui-button" );
3733
// Initialize new buttons
3734
allButtons.not( ":ui-button" ).button();
3736
// Refresh existing buttons
3737
existingButtons.button( "refresh" );
3739
this.buttons = allButtons
3741
return $( this ).button( "widget" )[ 0 ];
3743
.removeClass( "ui-corner-all ui-corner-left ui-corner-right" )
3745
.addClass( rtl ? "ui-corner-right" : "ui-corner-left" )
3748
.addClass( rtl ? "ui-corner-left" : "ui-corner-right" )
3753
_destroy: function() {
3754
this.element.removeClass( "ui-buttonset" );
3757
return $( this ).button( "widget" )[ 0 ];
3759
.removeClass( "ui-corner-left ui-corner-right" )
3761
.button( "destroy" );
3765
var button = $.ui.button;
3769
* jQuery UI Datepicker 1.11.4
3770
* http://jqueryui.com
3772
* Copyright jQuery Foundation and other contributors
3773
* Released under the MIT license.
3774
* http://jquery.org/license
3776
* http://api.jqueryui.com/datepicker/
3780
$.extend($.ui, { datepicker: { version: "1.11.4" } });
3782
var datepicker_instActive;
3784
function datepicker_getZindex( elem ) {
3785
var position, value;
3786
while ( elem.length && elem[ 0 ] !== document ) {
3787
// Ignore z-index if position is set to a value where z-index is ignored by the browser
3788
// This makes behavior of this function consistent across browsers
3789
// WebKit always returns auto if the element is positioned
3790
position = elem.css( "position" );
3791
if ( position === "absolute" || position === "relative" || position === "fixed" ) {
3792
// IE returns 0 when zIndex is not specified
3793
// other browsers return a string
3794
// we ignore the case of nested elements with an explicit value of 0
3795
// <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
3796
value = parseInt( elem.css( "zIndex" ), 10 );
3797
if ( !isNaN( value ) && value !== 0 ) {
3801
elem = elem.parent();
3806
/* Date picker manager.
3807
Use the singleton instance of this class, $.datepicker, to interact with the date picker.
3808
Settings for (groups of) date pickers are maintained in an instance object,
3809
allowing multiple different settings on the same page. */
3811
function Datepicker() {
3812
this._curInst = null; // The current instance in use
3813
this._keyEvent = false; // If the last event was a key event
3814
this._disabledInputs = []; // List of date picker inputs that have been disabled
3815
this._datepickerShowing = false; // True if the popup picker is showing , false if not
3816
this._inDialog = false; // True if showing within a "dialog", false if not
3817
this._mainDivId = "ui-datepicker-div"; // The ID of the main datepicker division
3818
this._inlineClass = "ui-datepicker-inline"; // The name of the inline marker class
3819
this._appendClass = "ui-datepicker-append"; // The name of the append marker class
3820
this._triggerClass = "ui-datepicker-trigger"; // The name of the trigger marker class
3821
this._dialogClass = "ui-datepicker-dialog"; // The name of the dialog marker class
3822
this._disableClass = "ui-datepicker-disabled"; // The name of the disabled covering marker class
3823
this._unselectableClass = "ui-datepicker-unselectable"; // The name of the unselectable cell marker class
3824
this._currentClass = "ui-datepicker-current-day"; // The name of the current day marker class
3825
this._dayOverClass = "ui-datepicker-days-cell-over"; // The name of the day hover marker class
3826
this.regional = []; // Available regional settings, indexed by language code
3827
this.regional[""] = { // Default regional settings
3828
closeText: "Done", // Display text for close link
3829
prevText: "Prev", // Display text for previous month link
3830
nextText: "Next", // Display text for next month link
3831
currentText: "Today", // Display text for current month link
3832
monthNames: ["January","February","March","April","May","June",
3833
"July","August","September","October","November","December"], // Names of months for drop-down and formatting
3834
monthNamesShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], // For formatting
3835
dayNames: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], // For formatting
3836
dayNamesShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], // For formatting
3837
dayNamesMin: ["Su","Mo","Tu","We","Th","Fr","Sa"], // Column headings for days starting at Sunday
3838
weekHeader: "Wk", // Column header for week of the year
3839
dateFormat: "mm/dd/yy", // See format options on parseDate
3840
firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
3841
isRTL: false, // True if right-to-left language, false if left-to-right
3842
showMonthAfterYear: false, // True if the year select precedes month, false for month then year
3843
yearSuffix: "" // Additional text to append to the year in the month headers
3845
this._defaults = { // Global defaults for all the date picker instances
3846
showOn: "focus", // "focus" for popup on focus,
3847
// "button" for trigger button, or "both" for either
3848
showAnim: "fadeIn", // Name of jQuery animation for popup
3849
showOptions: {}, // Options for enhanced animations
3850
defaultDate: null, // Used when field is blank: actual date,
3851
// +/-number for offset from today, null for today
3852
appendText: "", // Display text following the input box, e.g. showing the format
3853
buttonText: "...", // Text for trigger button
3854
buttonImage: "", // URL for trigger button image
3855
buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
3856
hideIfNoPrevNext: false, // True to hide next/previous month links
3857
// if not applicable, false to just disable them
3858
navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
3859
gotoCurrent: false, // True if today link goes back to current selection instead
3860
changeMonth: false, // True if month can be selected directly, false if only prev/next
3861
changeYear: false, // True if year can be selected directly, false if only prev/next
3862
yearRange: "c-10:c+10", // Range of years to display in drop-down,
3863
// either relative to today's year (-nn:+nn), relative to currently displayed year
3864
// (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
3865
showOtherMonths: false, // True to show dates in other months, false to leave blank
3866
selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
3867
showWeek: false, // True to show week of the year, false to not show it
3868
calculateWeek: this.iso8601Week, // How to calculate the week of the year,
3869
// takes a Date and returns the number of the week for it
3870
shortYearCutoff: "+10", // Short year values < this are in the current century,
3871
// > this are in the previous century,
3872
// string value starting with "+" for current year + value
3873
minDate: null, // The earliest selectable date, or null for no limit
3874
maxDate: null, // The latest selectable date, or null for no limit
3875
duration: "fast", // Duration of display/closure
3876
beforeShowDay: null, // Function that takes a date and returns an array with
3877
// [0] = true if selectable, false if not, [1] = custom CSS class name(s) or "",
3878
// [2] = cell title (optional), e.g. $.datepicker.noWeekends
3879
beforeShow: null, // Function that takes an input field and
3880
// returns a set of custom settings for the date picker
3881
onSelect: null, // Define a callback function when a date is selected
3882
onChangeMonthYear: null, // Define a callback function when the month or year is changed
3883
onClose: null, // Define a callback function when the datepicker is closed
3884
numberOfMonths: 1, // Number of months to show at a time
3885
showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
3886
stepMonths: 1, // Number of months to step back/forward
3887
stepBigMonths: 12, // Number of months to step back/forward for the big links
3888
altField: "", // Selector for an alternate field to store selected dates into
3889
altFormat: "", // The date format to use for the alternate field
3890
constrainInput: true, // The input is constrained by the current date format
3891
showButtonPanel: false, // True to show button panel, false to not show it
3892
autoSize: false, // True to size the input for the date format, false to leave as is
3893
disabled: false // The initial disabled state
3895
$.extend(this._defaults, this.regional[""]);
3896
this.regional.en = $.extend( true, {}, this.regional[ "" ]);
3897
this.regional[ "en-US" ] = $.extend( true, {}, this.regional.en );
3898
this.dpDiv = datepicker_bindHover($("<div id='" + this._mainDivId + "' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>"));
3901
$.extend(Datepicker.prototype, {
3902
/* Class name added to elements to indicate already configured with a date picker. */
3903
markerClassName: "hasDatepicker",
3905
//Keep track of the maximum number of rows displayed (see #7043)
3908
// TODO rename to "widget" when switching to widget factory
3909
_widgetDatepicker: function() {
3913
/* Override the default settings for all instances of the date picker.
3914
* @param settings object - the new settings to use as defaults (anonymous object)
3915
* @return the manager object
3917
setDefaults: function(settings) {
3918
datepicker_extendRemove(this._defaults, settings || {});
3922
/* Attach the date picker to a jQuery selection.
3923
* @param target element - the target input field or division or span
3924
* @param settings object - the new settings to use for this date picker instance (anonymous)
3926
_attachDatepicker: function(target, settings) {
3927
var nodeName, inline, inst;
3928
nodeName = target.nodeName.toLowerCase();
3929
inline = (nodeName === "div" || nodeName === "span");
3932
target.id = "dp" + this.uuid;
3934
inst = this._newInst($(target), inline);
3935
inst.settings = $.extend({}, settings || {});
3936
if (nodeName === "input") {
3937
this._connectDatepicker(target, inst);
3938
} else if (inline) {
3939
this._inlineDatepicker(target, inst);
3943
/* Create a new instance object. */
3944
_newInst: function(target, inline) {
3945
var id = target[0].id.replace(/([^A-Za-z0-9_\-])/g, "\\\\$1"); // escape jQuery meta chars
3946
return {id: id, input: target, // associated target
3947
selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
3948
drawMonth: 0, drawYear: 0, // month being drawn
3949
inline: inline, // is datepicker inline or not
3950
dpDiv: (!inline ? this.dpDiv : // presentation div
3951
datepicker_bindHover($("<div class='" + this._inlineClass + " ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>")))};
3954
/* Attach the date picker to an input field. */
3955
_connectDatepicker: function(target, inst) {
3956
var input = $(target);
3957
inst.append = $([]);
3958
inst.trigger = $([]);
3959
if (input.hasClass(this.markerClassName)) {
3962
this._attachments(input, inst);
3963
input.addClass(this.markerClassName).keydown(this._doKeyDown).
3964
keypress(this._doKeyPress).keyup(this._doKeyUp);
3965
this._autoSize(inst);
3966
$.data(target, "datepicker", inst);
3967
//If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665)
3968
if( inst.settings.disabled ) {
3969
this._disableDatepicker( target );
3973
/* Make attachments based on settings. */
3974
_attachments: function(input, inst) {
3975
var showOn, buttonText, buttonImage,
3976
appendText = this._get(inst, "appendText"),
3977
isRTL = this._get(inst, "isRTL");
3980
inst.append.remove();
3983
inst.append = $("<span class='" + this._appendClass + "'>" + appendText + "</span>");
3984
input[isRTL ? "before" : "after"](inst.append);
3987
input.unbind("focus", this._showDatepicker);
3990
inst.trigger.remove();
3993
showOn = this._get(inst, "showOn");
3994
if (showOn === "focus" || showOn === "both") { // pop-up date picker when in the marked field
3995
input.focus(this._showDatepicker);
3997
if (showOn === "button" || showOn === "both") { // pop-up date picker when button clicked
3998
buttonText = this._get(inst, "buttonText");
3999
buttonImage = this._get(inst, "buttonImage");
4000
inst.trigger = $(this._get(inst, "buttonImageOnly") ?
4001
$("<img/>").addClass(this._triggerClass).
4002
attr({ src: buttonImage, alt: buttonText, title: buttonText }) :
4003
$("<button type='button'></button>").addClass(this._triggerClass).
4004
html(!buttonImage ? buttonText : $("<img/>").attr(
4005
{ src:buttonImage, alt:buttonText, title:buttonText })));
4006
input[isRTL ? "before" : "after"](inst.trigger);
4007
inst.trigger.click(function() {
4008
if ($.datepicker._datepickerShowing && $.datepicker._lastInput === input[0]) {
4009
$.datepicker._hideDatepicker();
4010
} else if ($.datepicker._datepickerShowing && $.datepicker._lastInput !== input[0]) {
4011
$.datepicker._hideDatepicker();
4012
$.datepicker._showDatepicker(input[0]);
4014
$.datepicker._showDatepicker(input[0]);
4021
/* Apply the maximum length for the date format. */
4022
_autoSize: function(inst) {
4023
if (this._get(inst, "autoSize") && !inst.inline) {
4024
var findMax, max, maxI, i,
4025
date = new Date(2009, 12 - 1, 20), // Ensure double digits
4026
dateFormat = this._get(inst, "dateFormat");
4028
if (dateFormat.match(/[DM]/)) {
4029
findMax = function(names) {
4032
for (i = 0; i < names.length; i++) {
4033
if (names[i].length > max) {
4034
max = names[i].length;
4040
date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ?
4041
"monthNames" : "monthNamesShort"))));
4042
date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ?
4043
"dayNames" : "dayNamesShort"))) + 20 - date.getDay());
4045
inst.input.attr("size", this._formatDate(inst, date).length);
4049
/* Attach an inline date picker to a div. */
4050
_inlineDatepicker: function(target, inst) {
4051
var divSpan = $(target);
4052
if (divSpan.hasClass(this.markerClassName)) {
4055
divSpan.addClass(this.markerClassName).append(inst.dpDiv);
4056
$.data(target, "datepicker", inst);
4057
this._setDate(inst, this._getDefaultDate(inst), true);
4058
this._updateDatepicker(inst);
4059
this._updateAlternate(inst);
4060
//If disabled option is true, disable the datepicker before showing it (see ticket #5665)
4061
if( inst.settings.disabled ) {
4062
this._disableDatepicker( target );
4064
// Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements
4065
// http://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height
4066
inst.dpDiv.css( "display", "block" );
4069
/* Pop-up the date picker in a "dialog" box.
4070
* @param input element - ignored
4071
* @param date string or Date - the initial date to display
4072
* @param onSelect function - the function to call when a date is selected
4073
* @param settings object - update the dialog date picker instance's settings (anonymous object)
4074
* @param pos int[2] - coordinates for the dialog's position within the screen or
4075
* event - with x/y coordinates or
4076
* leave empty for default (screen centre)
4077
* @return the manager object
4079
_dialogDatepicker: function(input, date, onSelect, settings, pos) {
4080
var id, browserWidth, browserHeight, scrollX, scrollY,
4081
inst = this._dialogInst; // internal instance
4085
id = "dp" + this.uuid;
4086
this._dialogInput = $("<input type='text' id='" + id +
4087
"' style='position: absolute; top: -100px; width: 0px;'/>");
4088
this._dialogInput.keydown(this._doKeyDown);
4089
$("body").append(this._dialogInput);
4090
inst = this._dialogInst = this._newInst(this._dialogInput, false);
4092
$.data(this._dialogInput[0], "datepicker", inst);
4094
datepicker_extendRemove(inst.settings, settings || {});
4095
date = (date && date.constructor === Date ? this._formatDate(inst, date) : date);
4096
this._dialogInput.val(date);
4098
this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);
4100
browserWidth = document.documentElement.clientWidth;
4101
browserHeight = document.documentElement.clientHeight;
4102
scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
4103
scrollY = document.documentElement.scrollTop || document.body.scrollTop;
4104
this._pos = // should use actual width/height below
4105
[(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY];
4108
// move input on screen for focus, but hidden behind dialog
4109
this._dialogInput.css("left", (this._pos[0] + 20) + "px").css("top", this._pos[1] + "px");
4110
inst.settings.onSelect = onSelect;
4111
this._inDialog = true;
4112
this.dpDiv.addClass(this._dialogClass);
4113
this._showDatepicker(this._dialogInput[0]);
4115
$.blockUI(this.dpDiv);
4117
$.data(this._dialogInput[0], "datepicker", inst);
4121
/* Detach a datepicker from its control.
4122
* @param target element - the target input field or division or span
4124
_destroyDatepicker: function(target) {
4126
$target = $(target),
4127
inst = $.data(target, "datepicker");
4129
if (!$target.hasClass(this.markerClassName)) {
4133
nodeName = target.nodeName.toLowerCase();
4134
$.removeData(target, "datepicker");
4135
if (nodeName === "input") {
4136
inst.append.remove();
4137
inst.trigger.remove();
4138
$target.removeClass(this.markerClassName).
4139
unbind("focus", this._showDatepicker).
4140
unbind("keydown", this._doKeyDown).
4141
unbind("keypress", this._doKeyPress).
4142
unbind("keyup", this._doKeyUp);
4143
} else if (nodeName === "div" || nodeName === "span") {
4144
$target.removeClass(this.markerClassName).empty();
4147
if ( datepicker_instActive === inst ) {
4148
datepicker_instActive = null;
4152
/* Enable the date picker to a jQuery selection.
4153
* @param target element - the target input field or division or span
4155
_enableDatepicker: function(target) {
4156
var nodeName, inline,
4157
$target = $(target),
4158
inst = $.data(target, "datepicker");
4160
if (!$target.hasClass(this.markerClassName)) {
4164
nodeName = target.nodeName.toLowerCase();
4165
if (nodeName === "input") {
4166
target.disabled = false;
4167
inst.trigger.filter("button").
4168
each(function() { this.disabled = false; }).end().
4169
filter("img").css({opacity: "1.0", cursor: ""});
4170
} else if (nodeName === "div" || nodeName === "span") {
4171
inline = $target.children("." + this._inlineClass);
4172
inline.children().removeClass("ui-state-disabled");
4173
inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
4174
prop("disabled", false);
4176
this._disabledInputs = $.map(this._disabledInputs,
4177
function(value) { return (value === target ? null : value); }); // delete entry
4180
/* Disable the date picker to a jQuery selection.
4181
* @param target element - the target input field or division or span
4183
_disableDatepicker: function(target) {
4184
var nodeName, inline,
4185
$target = $(target),
4186
inst = $.data(target, "datepicker");
4188
if (!$target.hasClass(this.markerClassName)) {
4192
nodeName = target.nodeName.toLowerCase();
4193
if (nodeName === "input") {
4194
target.disabled = true;
4195
inst.trigger.filter("button").
4196
each(function() { this.disabled = true; }).end().
4197
filter("img").css({opacity: "0.5", cursor: "default"});
4198
} else if (nodeName === "div" || nodeName === "span") {
4199
inline = $target.children("." + this._inlineClass);
4200
inline.children().addClass("ui-state-disabled");
4201
inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
4202
prop("disabled", true);
4204
this._disabledInputs = $.map(this._disabledInputs,
4205
function(value) { return (value === target ? null : value); }); // delete entry
4206
this._disabledInputs[this._disabledInputs.length] = target;
4209
/* Is the first field in a jQuery collection disabled as a datepicker?
4210
* @param target element - the target input field or division or span
4211
* @return boolean - true if disabled, false if enabled
4213
_isDisabledDatepicker: function(target) {
4217
for (var i = 0; i < this._disabledInputs.length; i++) {
4218
if (this._disabledInputs[i] === target) {
4225
/* Retrieve the instance data for the target control.
4226
* @param target element - the target input field or division or span
4227
* @return object - the associated instance data
4228
* @throws error if a jQuery problem getting data
4230
_getInst: function(target) {
4232
return $.data(target, "datepicker");
4235
throw "Missing instance data for this datepicker";
4239
/* Update or retrieve the settings for a date picker attached to an input field or division.
4240
* @param target element - the target input field or division or span
4241
* @param name object - the new settings to update or
4242
* string - the name of the setting to change or retrieve,
4243
* when retrieving also "all" for all instance settings or
4244
* "defaults" for all global defaults
4245
* @param value any - the new value for the setting
4246
* (omit if above is an object or to retrieve a value)
4248
_optionDatepicker: function(target, name, value) {
4249
var settings, date, minDate, maxDate,
4250
inst = this._getInst(target);
4252
if (arguments.length === 2 && typeof name === "string") {
4253
return (name === "defaults" ? $.extend({}, $.datepicker._defaults) :
4254
(inst ? (name === "all" ? $.extend({}, inst.settings) :
4255
this._get(inst, name)) : null));
4258
settings = name || {};
4259
if (typeof name === "string") {
4261
settings[name] = value;
4265
if (this._curInst === inst) {
4266
this._hideDatepicker();
4269
date = this._getDateDatepicker(target, true);
4270
minDate = this._getMinMaxDate(inst, "min");
4271
maxDate = this._getMinMaxDate(inst, "max");
4272
datepicker_extendRemove(inst.settings, settings);
4273
// reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided
4274
if (minDate !== null && settings.dateFormat !== undefined && settings.minDate === undefined) {
4275
inst.settings.minDate = this._formatDate(inst, minDate);
4277
if (maxDate !== null && settings.dateFormat !== undefined && settings.maxDate === undefined) {
4278
inst.settings.maxDate = this._formatDate(inst, maxDate);
4280
if ( "disabled" in settings ) {
4281
if ( settings.disabled ) {
4282
this._disableDatepicker(target);
4284
this._enableDatepicker(target);
4287
this._attachments($(target), inst);
4288
this._autoSize(inst);
4289
this._setDate(inst, date);
4290
this._updateAlternate(inst);
4291
this._updateDatepicker(inst);
4295
// change method deprecated
4296
_changeDatepicker: function(target, name, value) {
4297
this._optionDatepicker(target, name, value);
4300
/* Redraw the date picker attached to an input field or division.
4301
* @param target element - the target input field or division or span
4303
_refreshDatepicker: function(target) {
4304
var inst = this._getInst(target);
4306
this._updateDatepicker(inst);
4310
/* Set the dates for a jQuery selection.
4311
* @param target element - the target input field or division or span
4312
* @param date Date - the new date
4314
_setDateDatepicker: function(target, date) {
4315
var inst = this._getInst(target);
4317
this._setDate(inst, date);
4318
this._updateDatepicker(inst);
4319
this._updateAlternate(inst);
4323
/* Get the date(s) for the first entry in a jQuery selection.
4324
* @param target element - the target input field or division or span
4325
* @param noDefault boolean - true if no default date is to be used
4326
* @return Date - the current date
4328
_getDateDatepicker: function(target, noDefault) {
4329
var inst = this._getInst(target);
4330
if (inst && !inst.inline) {
4331
this._setDateFromField(inst, noDefault);
4333
return (inst ? this._getDate(inst) : null);
4336
/* Handle keystrokes. */
4337
_doKeyDown: function(event) {
4338
var onSelect, dateStr, sel,
4339
inst = $.datepicker._getInst(event.target),
4341
isRTL = inst.dpDiv.is(".ui-datepicker-rtl");
4343
inst._keyEvent = true;
4344
if ($.datepicker._datepickerShowing) {
4345
switch (event.keyCode) {
4346
case 9: $.datepicker._hideDatepicker();
4348
break; // hide on tab out
4349
case 13: sel = $("td." + $.datepicker._dayOverClass + ":not(." +
4350
$.datepicker._currentClass + ")", inst.dpDiv);
4352
$.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);
4355
onSelect = $.datepicker._get(inst, "onSelect");
4357
dateStr = $.datepicker._formatDate(inst);
4359
// trigger custom callback
4360
onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);
4362
$.datepicker._hideDatepicker();
4365
return false; // don't submit the form
4366
case 27: $.datepicker._hideDatepicker();
4367
break; // hide on escape
4368
case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
4369
-$.datepicker._get(inst, "stepBigMonths") :
4370
-$.datepicker._get(inst, "stepMonths")), "M");
4371
break; // previous month/year on page up/+ ctrl
4372
case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
4373
+$.datepicker._get(inst, "stepBigMonths") :
4374
+$.datepicker._get(inst, "stepMonths")), "M");
4375
break; // next month/year on page down/+ ctrl
4376
case 35: if (event.ctrlKey || event.metaKey) {
4377
$.datepicker._clearDate(event.target);
4379
handled = event.ctrlKey || event.metaKey;
4380
break; // clear on ctrl or command +end
4381
case 36: if (event.ctrlKey || event.metaKey) {
4382
$.datepicker._gotoToday(event.target);
4384
handled = event.ctrlKey || event.metaKey;
4385
break; // current on ctrl or command +home
4386
case 37: if (event.ctrlKey || event.metaKey) {
4387
$.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), "D");
4389
handled = event.ctrlKey || event.metaKey;
4390
// -1 day on ctrl or command +left
4391
if (event.originalEvent.altKey) {
4392
$.datepicker._adjustDate(event.target, (event.ctrlKey ?
4393
-$.datepicker._get(inst, "stepBigMonths") :
4394
-$.datepicker._get(inst, "stepMonths")), "M");
4396
// next month/year on alt +left on Mac
4398
case 38: if (event.ctrlKey || event.metaKey) {
4399
$.datepicker._adjustDate(event.target, -7, "D");
4401
handled = event.ctrlKey || event.metaKey;
4402
break; // -1 week on ctrl or command +up
4403
case 39: if (event.ctrlKey || event.metaKey) {
4404
$.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), "D");
4406
handled = event.ctrlKey || event.metaKey;
4407
// +1 day on ctrl or command +right
4408
if (event.originalEvent.altKey) {
4409
$.datepicker._adjustDate(event.target, (event.ctrlKey ?
4410
+$.datepicker._get(inst, "stepBigMonths") :
4411
+$.datepicker._get(inst, "stepMonths")), "M");
4413
// next month/year on alt +right
4415
case 40: if (event.ctrlKey || event.metaKey) {
4416
$.datepicker._adjustDate(event.target, +7, "D");
4418
handled = event.ctrlKey || event.metaKey;
4419
break; // +1 week on ctrl or command +down
4420
default: handled = false;
4422
} else if (event.keyCode === 36 && event.ctrlKey) { // display the date picker on ctrl+home
4423
$.datepicker._showDatepicker(this);
4429
event.preventDefault();
4430
event.stopPropagation();
4434
/* Filter entered characters - based on date format. */
4435
_doKeyPress: function(event) {
4437
inst = $.datepicker._getInst(event.target);
4439
if ($.datepicker._get(inst, "constrainInput")) {
4440
chars = $.datepicker._possibleChars($.datepicker._get(inst, "dateFormat"));
4441
chr = String.fromCharCode(event.charCode == null ? event.keyCode : event.charCode);
4442
return event.ctrlKey || event.metaKey || (chr < " " || !chars || chars.indexOf(chr) > -1);
4446
/* Synchronise manual entry and field/alternate field. */
4447
_doKeyUp: function(event) {
4449
inst = $.datepicker._getInst(event.target);
4451
if (inst.input.val() !== inst.lastVal) {
4453
date = $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"),
4454
(inst.input ? inst.input.val() : null),
4455
$.datepicker._getFormatConfig(inst));
4457
if (date) { // only if valid
4458
$.datepicker._setDateFromField(inst);
4459
$.datepicker._updateAlternate(inst);
4460
$.datepicker._updateDatepicker(inst);
4469
/* Pop-up the date picker for a given input field.
4470
* If false returned from beforeShow event handler do not show.
4471
* @param input element - the input field attached to the date picker or
4472
* event - if triggered by focus
4474
_showDatepicker: function(input) {
4475
input = input.target || input;
4476
if (input.nodeName.toLowerCase() !== "input") { // find from button/image trigger
4477
input = $("input", input.parentNode)[0];
4480
if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput === input) { // already here
4484
var inst, beforeShow, beforeShowSettings, isFixed,
4485
offset, showAnim, duration;
4487
inst = $.datepicker._getInst(input);
4488
if ($.datepicker._curInst && $.datepicker._curInst !== inst) {
4489
$.datepicker._curInst.dpDiv.stop(true, true);
4490
if ( inst && $.datepicker._datepickerShowing ) {
4491
$.datepicker._hideDatepicker( $.datepicker._curInst.input[0] );
4495
beforeShow = $.datepicker._get(inst, "beforeShow");
4496
beforeShowSettings = beforeShow ? beforeShow.apply(input, [input, inst]) : {};
4497
if(beforeShowSettings === false){
4500
datepicker_extendRemove(inst.settings, beforeShowSettings);
4502
inst.lastVal = null;
4503
$.datepicker._lastInput = input;
4504
$.datepicker._setDateFromField(inst);
4506
if ($.datepicker._inDialog) { // hide cursor
4509
if (!$.datepicker._pos) { // position below input
4510
$.datepicker._pos = $.datepicker._findPos(input);
4511
$.datepicker._pos[1] += input.offsetHeight; // add the height
4515
$(input).parents().each(function() {
4516
isFixed |= $(this).css("position") === "fixed";
4520
offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]};
4521
$.datepicker._pos = null;
4522
//to avoid flashes on Firefox
4524
// determine sizing offscreen
4525
inst.dpDiv.css({position: "absolute", display: "block", top: "-1000px"});
4526
$.datepicker._updateDatepicker(inst);
4527
// fix width for dynamic number of date pickers
4528
// and adjust position before showing
4529
offset = $.datepicker._checkOffset(inst, offset, isFixed);
4530
inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ?
4531
"static" : (isFixed ? "fixed" : "absolute")), display: "none",
4532
left: offset.left + "px", top: offset.top + "px"});
4535
showAnim = $.datepicker._get(inst, "showAnim");
4536
duration = $.datepicker._get(inst, "duration");
4537
inst.dpDiv.css( "z-index", datepicker_getZindex( $( input ) ) + 1 );
4538
$.datepicker._datepickerShowing = true;
4540
if ( $.effects && $.effects.effect[ showAnim ] ) {
4541
inst.dpDiv.show(showAnim, $.datepicker._get(inst, "showOptions"), duration);
4543
inst.dpDiv[showAnim || "show"](showAnim ? duration : null);
4546
if ( $.datepicker._shouldFocusInput( inst ) ) {
4550
$.datepicker._curInst = inst;
4554
/* Generate the date picker content. */
4555
_updateDatepicker: function(inst) {
4556
this.maxRows = 4; //Reset the max number of rows being displayed (see #7043)
4557
datepicker_instActive = inst; // for delegate hover events
4558
inst.dpDiv.empty().append(this._generateHTML(inst));
4559
this._attachHandlers(inst);
4562
numMonths = this._getNumberOfMonths(inst),
4563
cols = numMonths[1],
4565
activeCell = inst.dpDiv.find( "." + this._dayOverClass + " a" );
4567
if ( activeCell.length > 0 ) {
4568
datepicker_handleMouseover.apply( activeCell.get( 0 ) );
4571
inst.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width("");
4573
inst.dpDiv.addClass("ui-datepicker-multi-" + cols).css("width", (width * cols) + "em");
4575
inst.dpDiv[(numMonths[0] !== 1 || numMonths[1] !== 1 ? "add" : "remove") +
4576
"Class"]("ui-datepicker-multi");
4577
inst.dpDiv[(this._get(inst, "isRTL") ? "add" : "remove") +
4578
"Class"]("ui-datepicker-rtl");
4580
if (inst === $.datepicker._curInst && $.datepicker._datepickerShowing && $.datepicker._shouldFocusInput( inst ) ) {
4584
// deffered render of the years select (to avoid flashes on Firefox)
4585
if( inst.yearshtml ){
4586
origyearshtml = inst.yearshtml;
4587
setTimeout(function(){
4588
//assure that inst.yearshtml didn't change.
4589
if( origyearshtml === inst.yearshtml && inst.yearshtml ){
4590
inst.dpDiv.find("select.ui-datepicker-year:first").replaceWith(inst.yearshtml);
4592
origyearshtml = inst.yearshtml = null;
4597
// #6694 - don't focus the input if it's already focused
4598
// this breaks the change event in IE
4599
// Support: IE and jQuery <1.9
4600
_shouldFocusInput: function( inst ) {
4601
return inst.input && inst.input.is( ":visible" ) && !inst.input.is( ":disabled" ) && !inst.input.is( ":focus" );
4604
/* Check positioning to remain on screen. */
4605
_checkOffset: function(inst, offset, isFixed) {
4606
var dpWidth = inst.dpDiv.outerWidth(),
4607
dpHeight = inst.dpDiv.outerHeight(),
4608
inputWidth = inst.input ? inst.input.outerWidth() : 0,
4609
inputHeight = inst.input ? inst.input.outerHeight() : 0,
4610
viewWidth = document.documentElement.clientWidth + (isFixed ? 0 : $(document).scrollLeft()),
4611
viewHeight = document.documentElement.clientHeight + (isFixed ? 0 : $(document).scrollTop());
4613
offset.left -= (this._get(inst, "isRTL") ? (dpWidth - inputWidth) : 0);
4614
offset.left -= (isFixed && offset.left === inst.input.offset().left) ? $(document).scrollLeft() : 0;
4615
offset.top -= (isFixed && offset.top === (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;
4617
// now check if datepicker is showing outside window viewport - move to a better place if so.
4618
offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?
4619
Math.abs(offset.left + dpWidth - viewWidth) : 0);
4620
offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?
4621
Math.abs(dpHeight + inputHeight) : 0);
4626
/* Find an object's position on the screen. */
4627
_findPos: function(obj) {
4629
inst = this._getInst(obj),
4630
isRTL = this._get(inst, "isRTL");
4632
while (obj && (obj.type === "hidden" || obj.nodeType !== 1 || $.expr.filters.hidden(obj))) {
4633
obj = obj[isRTL ? "previousSibling" : "nextSibling"];
4636
position = $(obj).offset();
4637
return [position.left, position.top];
4640
/* Hide the date picker from view.
4641
* @param input element - the input field attached to the date picker
4643
_hideDatepicker: function(input) {
4644
var showAnim, duration, postProcess, onClose,
4645
inst = this._curInst;
4647
if (!inst || (input && inst !== $.data(input, "datepicker"))) {
4651
if (this._datepickerShowing) {
4652
showAnim = this._get(inst, "showAnim");
4653
duration = this._get(inst, "duration");
4654
postProcess = function() {
4655
$.datepicker._tidyDialog(inst);
4658
// DEPRECATED: after BC for 1.8.x $.effects[ showAnim ] is not needed
4659
if ( $.effects && ( $.effects.effect[ showAnim ] || $.effects[ showAnim ] ) ) {
4660
inst.dpDiv.hide(showAnim, $.datepicker._get(inst, "showOptions"), duration, postProcess);
4662
inst.dpDiv[(showAnim === "slideDown" ? "slideUp" :
4663
(showAnim === "fadeIn" ? "fadeOut" : "hide"))]((showAnim ? duration : null), postProcess);
4669
this._datepickerShowing = false;
4671
onClose = this._get(inst, "onClose");
4673
onClose.apply((inst.input ? inst.input[0] : null), [(inst.input ? inst.input.val() : ""), inst]);
4676
this._lastInput = null;
4677
if (this._inDialog) {
4678
this._dialogInput.css({ position: "absolute", left: "0", top: "-100px" });
4681
$("body").append(this.dpDiv);
4684
this._inDialog = false;
4688
/* Tidy up after a dialog display. */
4689
_tidyDialog: function(inst) {
4690
inst.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar");
4693
/* Close date picker if clicked elsewhere. */
4694
_checkExternalClick: function(event) {
4695
if (!$.datepicker._curInst) {
4699
var $target = $(event.target),
4700
inst = $.datepicker._getInst($target[0]);
4702
if ( ( ( $target[0].id !== $.datepicker._mainDivId &&
4703
$target.parents("#" + $.datepicker._mainDivId).length === 0 &&
4704
!$target.hasClass($.datepicker.markerClassName) &&
4705
!$target.closest("." + $.datepicker._triggerClass).length &&
4706
$.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI) ) ) ||
4707
( $target.hasClass($.datepicker.markerClassName) && $.datepicker._curInst !== inst ) ) {
4708
$.datepicker._hideDatepicker();
4712
/* Adjust one of the date sub-fields. */
4713
_adjustDate: function(id, offset, period) {
4715
inst = this._getInst(target[0]);
4717
if (this._isDisabledDatepicker(target[0])) {
4720
this._adjustInstDate(inst, offset +
4721
(period === "M" ? this._get(inst, "showCurrentAtPos") : 0), // undo positioning
4723
this._updateDatepicker(inst);
4726
/* Action for current link. */
4727
_gotoToday: function(id) {
4730
inst = this._getInst(target[0]);
4732
if (this._get(inst, "gotoCurrent") && inst.currentDay) {
4733
inst.selectedDay = inst.currentDay;
4734
inst.drawMonth = inst.selectedMonth = inst.currentMonth;
4735
inst.drawYear = inst.selectedYear = inst.currentYear;
4738
inst.selectedDay = date.getDate();
4739
inst.drawMonth = inst.selectedMonth = date.getMonth();
4740
inst.drawYear = inst.selectedYear = date.getFullYear();
4742
this._notifyChange(inst);
4743
this._adjustDate(target);
4746
/* Action for selecting a new month/year. */
4747
_selectMonthYear: function(id, select, period) {
4749
inst = this._getInst(target[0]);
4751
inst["selected" + (period === "M" ? "Month" : "Year")] =
4752
inst["draw" + (period === "M" ? "Month" : "Year")] =
4753
parseInt(select.options[select.selectedIndex].value,10);
4755
this._notifyChange(inst);
4756
this._adjustDate(target);
4759
/* Action for selecting a day. */
4760
_selectDay: function(id, month, year, td) {
4764
if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) {
4768
inst = this._getInst(target[0]);
4769
inst.selectedDay = inst.currentDay = $("a", td).html();
4770
inst.selectedMonth = inst.currentMonth = month;
4771
inst.selectedYear = inst.currentYear = year;
4772
this._selectDate(id, this._formatDate(inst,
4773
inst.currentDay, inst.currentMonth, inst.currentYear));
4776
/* Erase the input field and hide the date picker. */
4777
_clearDate: function(id) {
4779
this._selectDate(target, "");
4782
/* Update the input field with the selected date. */
4783
_selectDate: function(id, dateStr) {
4786
inst = this._getInst(target[0]);
4788
dateStr = (dateStr != null ? dateStr : this._formatDate(inst));
4790
inst.input.val(dateStr);
4792
this._updateAlternate(inst);
4794
onSelect = this._get(inst, "onSelect");
4796
onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); // trigger custom callback
4797
} else if (inst.input) {
4798
inst.input.trigger("change"); // fire the change event
4802
this._updateDatepicker(inst);
4804
this._hideDatepicker();
4805
this._lastInput = inst.input[0];
4806
if (typeof(inst.input[0]) !== "object") {
4807
inst.input.focus(); // restore focus
4809
this._lastInput = null;
4813
/* Update any alternate field to synchronise with the main field. */
4814
_updateAlternate: function(inst) {
4815
var altFormat, date, dateStr,
4816
altField = this._get(inst, "altField");
4818
if (altField) { // update alternate field too
4819
altFormat = this._get(inst, "altFormat") || this._get(inst, "dateFormat");
4820
date = this._getDate(inst);
4821
dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst));
4822
$(altField).each(function() { $(this).val(dateStr); });
4826
/* Set as beforeShowDay function to prevent selection of weekends.
4827
* @param date Date - the date to customise
4828
* @return [boolean, string] - is this date selectable?, what is its CSS class?
4830
noWeekends: function(date) {
4831
var day = date.getDay();
4832
return [(day > 0 && day < 6), ""];
4835
/* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
4836
* @param date Date - the date to get the week for
4837
* @return number - the number of the week within the year that contains this date
4839
iso8601Week: function(date) {
4841
checkDate = new Date(date.getTime());
4843
// Find Thursday of this week starting on Monday
4844
checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7));
4846
time = checkDate.getTime();
4847
checkDate.setMonth(0); // Compare with Jan 1
4848
checkDate.setDate(1);
4849
return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
4852
/* Parse a string value into a date object.
4853
* See formatDate below for the possible formats.
4855
* @param format string - the expected format of the date
4856
* @param value string - the date in the above format
4857
* @param settings Object - attributes include:
4858
* shortYearCutoff number - the cutoff year for determining the century (optional)
4859
* dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
4860
* dayNames string[7] - names of the days from Sunday (optional)
4861
* monthNamesShort string[12] - abbreviated names of the months (optional)
4862
* monthNames string[12] - names of the months (optional)
4863
* @return Date - the extracted date value or null if value is blank
4865
parseDate: function (format, value, settings) {
4866
if (format == null || value == null) {
4867
throw "Invalid arguments";
4870
value = (typeof value === "object" ? value.toString() : value + "");
4875
var iFormat, dim, extra,
4877
shortYearCutoffTemp = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff,
4878
shortYearCutoff = (typeof shortYearCutoffTemp !== "string" ? shortYearCutoffTemp :
4879
new Date().getFullYear() % 100 + parseInt(shortYearCutoffTemp, 10)),
4880
dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort,
4881
dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames,
4882
monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort,
4883
monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames,
4890
// Check whether a format character is doubled
4891
lookAhead = function(match) {
4892
var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match);
4898
// Extract a number from the string value
4899
getNumber = function(match) {
4900
var isDoubled = lookAhead(match),
4901
size = (match === "@" ? 14 : (match === "!" ? 20 :
4902
(match === "y" && isDoubled ? 4 : (match === "o" ? 3 : 2)))),
4903
minSize = (match === "y" ? size : 1),
4904
digits = new RegExp("^\\d{" + minSize + "," + size + "}"),
4905
num = value.substring(iValue).match(digits);
4907
throw "Missing number at position " + iValue;
4909
iValue += num[0].length;
4910
return parseInt(num[0], 10);
4912
// Extract a name from the string value and convert to an index
4913
getName = function(match, shortNames, longNames) {
4915
names = $.map(lookAhead(match) ? longNames : shortNames, function (v, k) {
4917
}).sort(function (a, b) {
4918
return -(a[1].length - b[1].length);
4921
$.each(names, function (i, pair) {
4923
if (value.substr(iValue, name.length).toLowerCase() === name.toLowerCase()) {
4925
iValue += name.length;
4932
throw "Unknown name at position " + iValue;
4935
// Confirm that a literal character matches the string value
4936
checkLiteral = function() {
4937
if (value.charAt(iValue) !== format.charAt(iFormat)) {
4938
throw "Unexpected literal at position " + iValue;
4943
for (iFormat = 0; iFormat < format.length; iFormat++) {
4945
if (format.charAt(iFormat) === "'" && !lookAhead("'")) {
4951
switch (format.charAt(iFormat)) {
4953
day = getNumber("d");
4956
getName("D", dayNamesShort, dayNames);
4959
doy = getNumber("o");
4962
month = getNumber("m");
4965
month = getName("M", monthNamesShort, monthNames);
4968
year = getNumber("y");
4971
date = new Date(getNumber("@"));
4972
year = date.getFullYear();
4973
month = date.getMonth() + 1;
4974
day = date.getDate();
4977
date = new Date((getNumber("!") - this._ticksTo1970) / 10000);
4978
year = date.getFullYear();
4979
month = date.getMonth() + 1;
4980
day = date.getDate();
4983
if (lookAhead("'")){
4995
if (iValue < value.length){
4996
extra = value.substr(iValue);
4997
if (!/^\s+/.test(extra)) {
4998
throw "Extra/unparsed characters found in date: " + extra;
5003
year = new Date().getFullYear();
5004
} else if (year < 100) {
5005
year += new Date().getFullYear() - new Date().getFullYear() % 100 +
5006
(year <= shortYearCutoff ? 0 : -100);
5013
dim = this._getDaysInMonth(year, month - 1);
5022
date = this._daylightSavingAdjust(new Date(year, month - 1, day));
5023
if (date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day) {
5024
throw "Invalid date"; // E.g. 31/02/00
5029
/* Standard date formats. */
5030
ATOM: "yy-mm-dd", // RFC 3339 (ISO 8601)
5031
COOKIE: "D, dd M yy",
5032
ISO_8601: "yy-mm-dd",
5033
RFC_822: "D, d M y",
5034
RFC_850: "DD, dd-M-y",
5035
RFC_1036: "D, d M y",
5036
RFC_1123: "D, d M yy",
5037
RFC_2822: "D, d M yy",
5038
RSS: "D, d M y", // RFC 822
5041
W3C: "yy-mm-dd", // ISO 8601
5043
_ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) +
5044
Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000),
5046
/* Format a date object into a string value.
5047
* The format can be combinations of the following:
5048
* d - day of month (no leading zero)
5049
* dd - day of month (two digit)
5050
* o - day of year (no leading zeros)
5051
* oo - day of year (three digit)
5052
* D - day name short
5053
* DD - day name long
5054
* m - month of year (no leading zero)
5055
* mm - month of year (two digit)
5056
* M - month name short
5057
* MM - month name long
5058
* y - year (two digit)
5059
* yy - year (four digit)
5060
* @ - Unix timestamp (ms since 01/01/1970)
5061
* ! - Windows ticks (100ns since 01/01/0001)
5062
* "..." - literal text
5065
* @param format string - the desired format of the date
5066
* @param date Date - the date value to format
5067
* @param settings Object - attributes include:
5068
* dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
5069
* dayNames string[7] - names of the days from Sunday (optional)
5070
* monthNamesShort string[12] - abbreviated names of the months (optional)
5071
* monthNames string[12] - names of the months (optional)
5072
* @return string - the date in the above format
5074
formatDate: function (format, date, settings) {
5080
dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort,
5081
dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames,
5082
monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort,
5083
monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames,
5084
// Check whether a format character is doubled
5085
lookAhead = function(match) {
5086
var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match);
5092
// Format a number, with leading zero if necessary
5093
formatNumber = function(match, value, len) {
5094
var num = "" + value;
5095
if (lookAhead(match)) {
5096
while (num.length < len) {
5102
// Format a name, short or long as requested
5103
formatName = function(match, value, shortNames, longNames) {
5104
return (lookAhead(match) ? longNames[value] : shortNames[value]);
5110
for (iFormat = 0; iFormat < format.length; iFormat++) {
5112
if (format.charAt(iFormat) === "'" && !lookAhead("'")) {
5115
output += format.charAt(iFormat);
5118
switch (format.charAt(iFormat)) {
5120
output += formatNumber("d", date.getDate(), 2);
5123
output += formatName("D", date.getDay(), dayNamesShort, dayNames);
5126
output += formatNumber("o",
5127
Math.round((new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000), 3);
5130
output += formatNumber("m", date.getMonth() + 1, 2);
5133
output += formatName("M", date.getMonth(), monthNamesShort, monthNames);
5136
output += (lookAhead("y") ? date.getFullYear() :
5137
(date.getYear() % 100 < 10 ? "0" : "") + date.getYear() % 100);
5140
output += date.getTime();
5143
output += date.getTime() * 10000 + this._ticksTo1970;
5146
if (lookAhead("'")) {
5153
output += format.charAt(iFormat);
5161
/* Extract all possible characters from the date format. */
5162
_possibleChars: function (format) {
5166
// Check whether a format character is doubled
5167
lookAhead = function(match) {
5168
var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match);
5175
for (iFormat = 0; iFormat < format.length; iFormat++) {
5177
if (format.charAt(iFormat) === "'" && !lookAhead("'")) {
5180
chars += format.charAt(iFormat);
5183
switch (format.charAt(iFormat)) {
5184
case "d": case "m": case "y": case "@":
5185
chars += "0123456789";
5188
return null; // Accept anything
5190
if (lookAhead("'")) {
5197
chars += format.charAt(iFormat);
5204
/* Get a setting value, defaulting if necessary. */
5205
_get: function(inst, name) {
5206
return inst.settings[name] !== undefined ?
5207
inst.settings[name] : this._defaults[name];
5210
/* Parse existing date and initialise date picker. */
5211
_setDateFromField: function(inst, noDefault) {
5212
if (inst.input.val() === inst.lastVal) {
5216
var dateFormat = this._get(inst, "dateFormat"),
5217
dates = inst.lastVal = inst.input ? inst.input.val() : null,
5218
defaultDate = this._getDefaultDate(inst),
5220
settings = this._getFormatConfig(inst);
5223
date = this.parseDate(dateFormat, dates, settings) || defaultDate;
5225
dates = (noDefault ? "" : dates);
5227
inst.selectedDay = date.getDate();
5228
inst.drawMonth = inst.selectedMonth = date.getMonth();
5229
inst.drawYear = inst.selectedYear = date.getFullYear();
5230
inst.currentDay = (dates ? date.getDate() : 0);
5231
inst.currentMonth = (dates ? date.getMonth() : 0);
5232
inst.currentYear = (dates ? date.getFullYear() : 0);
5233
this._adjustInstDate(inst);
5236
/* Retrieve the default date shown on opening. */
5237
_getDefaultDate: function(inst) {
5238
return this._restrictMinMax(inst,
5239
this._determineDate(inst, this._get(inst, "defaultDate"), new Date()));
5242
/* A date may be specified as an exact value or a relative one. */
5243
_determineDate: function(inst, date, defaultDate) {
5244
var offsetNumeric = function(offset) {
5245
var date = new Date();
5246
date.setDate(date.getDate() + offset);
5249
offsetString = function(offset) {
5251
return $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"),
5252
offset, $.datepicker._getFormatConfig(inst));
5258
var date = (offset.toLowerCase().match(/^c/) ?
5259
$.datepicker._getDate(inst) : null) || new Date(),
5260
year = date.getFullYear(),
5261
month = date.getMonth(),
5262
day = date.getDate(),
5263
pattern = /([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,
5264
matches = pattern.exec(offset);
5267
switch (matches[2] || "d") {
5268
case "d" : case "D" :
5269
day += parseInt(matches[1],10); break;
5270
case "w" : case "W" :
5271
day += parseInt(matches[1],10) * 7; break;
5272
case "m" : case "M" :
5273
month += parseInt(matches[1],10);
5274
day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
5276
case "y": case "Y" :
5277
year += parseInt(matches[1],10);
5278
day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
5281
matches = pattern.exec(offset);
5283
return new Date(year, month, day);
5285
newDate = (date == null || date === "" ? defaultDate : (typeof date === "string" ? offsetString(date) :
5286
(typeof date === "number" ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : new Date(date.getTime()))));
5288
newDate = (newDate && newDate.toString() === "Invalid Date" ? defaultDate : newDate);
5290
newDate.setHours(0);
5291
newDate.setMinutes(0);
5292
newDate.setSeconds(0);
5293
newDate.setMilliseconds(0);
5295
return this._daylightSavingAdjust(newDate);
5298
/* Handle switch to/from daylight saving.
5299
* Hours may be non-zero on daylight saving cut-over:
5300
* > 12 when midnight changeover, but then cannot generate
5301
* midnight datetime, so jump to 1AM, otherwise reset.
5302
* @param date (Date) the date to check
5303
* @return (Date) the corrected date
5305
_daylightSavingAdjust: function(date) {
5309
date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
5313
/* Set the date(s) directly. */
5314
_setDate: function(inst, date, noChange) {
5316
origMonth = inst.selectedMonth,
5317
origYear = inst.selectedYear,
5318
newDate = this._restrictMinMax(inst, this._determineDate(inst, date, new Date()));
5320
inst.selectedDay = inst.currentDay = newDate.getDate();
5321
inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth();
5322
inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear();
5323
if ((origMonth !== inst.selectedMonth || origYear !== inst.selectedYear) && !noChange) {
5324
this._notifyChange(inst);
5326
this._adjustInstDate(inst);
5328
inst.input.val(clear ? "" : this._formatDate(inst));
5332
/* Retrieve the date(s) directly. */
5333
_getDate: function(inst) {
5334
var startDate = (!inst.currentYear || (inst.input && inst.input.val() === "") ? null :
5335
this._daylightSavingAdjust(new Date(
5336
inst.currentYear, inst.currentMonth, inst.currentDay)));
5340
/* Attach the onxxx handlers. These are declared statically so
5341
* they work with static code transformers like Caja.
5343
_attachHandlers: function(inst) {
5344
var stepMonths = this._get(inst, "stepMonths"),
5345
id = "#" + inst.id.replace( /\\\\/g, "\\" );
5346
inst.dpDiv.find("[data-handler]").map(function () {
5349
$.datepicker._adjustDate(id, -stepMonths, "M");
5352
$.datepicker._adjustDate(id, +stepMonths, "M");
5355
$.datepicker._hideDatepicker();
5357
today: function () {
5358
$.datepicker._gotoToday(id);
5360
selectDay: function () {
5361
$.datepicker._selectDay(id, +this.getAttribute("data-month"), +this.getAttribute("data-year"), this);
5364
selectMonth: function () {
5365
$.datepicker._selectMonthYear(id, this, "M");
5368
selectYear: function () {
5369
$.datepicker._selectMonthYear(id, this, "Y");
5373
$(this).bind(this.getAttribute("data-event"), handler[this.getAttribute("data-handler")]);
5377
/* Generate the HTML for the current state of the date picker. */
5378
_generateHTML: function(inst) {
5379
var maxDraw, prevText, prev, nextText, next, currentText, gotoDate,
5380
controls, buttonPanel, firstDay, showWeek, dayNames, dayNamesMin,
5381
monthNames, monthNamesShort, beforeShowDay, showOtherMonths,
5382
selectOtherMonths, defaultDate, html, dow, row, group, col, selectedDate,
5383
cornerClass, calender, thead, day, daysInMonth, leadDays, curRows, numRows,
5384
printDate, dRow, tbody, daySettings, otherMonth, unselectable,
5385
tempDate = new Date(),
5386
today = this._daylightSavingAdjust(
5387
new Date(tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate())), // clear time
5388
isRTL = this._get(inst, "isRTL"),
5389
showButtonPanel = this._get(inst, "showButtonPanel"),
5390
hideIfNoPrevNext = this._get(inst, "hideIfNoPrevNext"),
5391
navigationAsDateFormat = this._get(inst, "navigationAsDateFormat"),
5392
numMonths = this._getNumberOfMonths(inst),
5393
showCurrentAtPos = this._get(inst, "showCurrentAtPos"),
5394
stepMonths = this._get(inst, "stepMonths"),
5395
isMultiMonth = (numMonths[0] !== 1 || numMonths[1] !== 1),
5396
currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) :
5397
new Date(inst.currentYear, inst.currentMonth, inst.currentDay))),
5398
minDate = this._getMinMaxDate(inst, "min"),
5399
maxDate = this._getMinMaxDate(inst, "max"),
5400
drawMonth = inst.drawMonth - showCurrentAtPos,
5401
drawYear = inst.drawYear;
5403
if (drawMonth < 0) {
5408
maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),
5409
maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate()));
5410
maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);
5411
while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {
5413
if (drawMonth < 0) {
5419
inst.drawMonth = drawMonth;
5420
inst.drawYear = drawYear;
5422
prevText = this._get(inst, "prevText");
5423
prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText,
5424
this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),
5425
this._getFormatConfig(inst)));
5427
prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?
5428
"<a class='ui-datepicker-prev ui-corner-all' data-handler='prev' data-event='click'" +
5429
" title='" + prevText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "e" : "w") + "'>" + prevText + "</span></a>" :
5430
(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>"));
5432
nextText = this._get(inst, "nextText");
5433
nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText,
5434
this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),
5435
this._getFormatConfig(inst)));
5437
next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?
5438
"<a class='ui-datepicker-next ui-corner-all' data-handler='next' data-event='click'" +
5439
" title='" + nextText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "w" : "e") + "'>" + nextText + "</span></a>" :
5440
(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>"));
5442
currentText = this._get(inst, "currentText");
5443
gotoDate = (this._get(inst, "gotoCurrent") && inst.currentDay ? currentDate : today);
5444
currentText = (!navigationAsDateFormat ? currentText :
5445
this.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));
5447
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'>" +
5448
this._get(inst, "closeText") + "</button>" : "");
5450
buttonPanel = (showButtonPanel) ? "<div class='ui-datepicker-buttonpane ui-widget-content'>" + (isRTL ? controls : "") +
5451
(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'" +
5452
">" + currentText + "</button>" : "") + (isRTL ? "" : controls) + "</div>" : "";
5454
firstDay = parseInt(this._get(inst, "firstDay"),10);
5455
firstDay = (isNaN(firstDay) ? 0 : firstDay);
5457
showWeek = this._get(inst, "showWeek");
5458
dayNames = this._get(inst, "dayNames");
5459
dayNamesMin = this._get(inst, "dayNamesMin");
5460
monthNames = this._get(inst, "monthNames");
5461
monthNamesShort = this._get(inst, "monthNamesShort");
5462
beforeShowDay = this._get(inst, "beforeShowDay");
5463
showOtherMonths = this._get(inst, "showOtherMonths");
5464
selectOtherMonths = this._get(inst, "selectOtherMonths");
5465
defaultDate = this._getDefaultDate(inst);
5468
for (row = 0; row < numMonths[0]; row++) {
5471
for (col = 0; col < numMonths[1]; col++) {
5472
selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay));
5473
cornerClass = " ui-corner-all";
5476
calender += "<div class='ui-datepicker-group";
5477
if (numMonths[1] > 1) {
5479
case 0: calender += " ui-datepicker-group-first";
5480
cornerClass = " ui-corner-" + (isRTL ? "right" : "left"); break;
5481
case numMonths[1]-1: calender += " ui-datepicker-group-last";
5482
cornerClass = " ui-corner-" + (isRTL ? "left" : "right"); break;
5483
default: calender += " ui-datepicker-group-middle"; cornerClass = ""; break;
5488
calender += "<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix" + cornerClass + "'>" +
5489
(/all|left/.test(cornerClass) && row === 0 ? (isRTL ? next : prev) : "") +
5490
(/all|right/.test(cornerClass) && row === 0 ? (isRTL ? prev : next) : "") +
5491
this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,
5492
row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers
5493
"</div><table class='ui-datepicker-calendar'><thead>" +
5495
thead = (showWeek ? "<th class='ui-datepicker-week-col'>" + this._get(inst, "weekHeader") + "</th>" : "");
5496
for (dow = 0; dow < 7; dow++) { // days of the week
5497
day = (dow + firstDay) % 7;
5498
thead += "<th scope='col'" + ((dow + firstDay + 6) % 7 >= 5 ? " class='ui-datepicker-week-end'" : "") + ">" +
5499
"<span title='" + dayNames[day] + "'>" + dayNamesMin[day] + "</span></th>";
5501
calender += thead + "</tr></thead><tbody>";
5502
daysInMonth = this._getDaysInMonth(drawYear, drawMonth);
5503
if (drawYear === inst.selectedYear && drawMonth === inst.selectedMonth) {
5504
inst.selectedDay = Math.min(inst.selectedDay, daysInMonth);
5506
leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;
5507
curRows = Math.ceil((leadDays + daysInMonth) / 7); // calculate the number of rows to generate
5508
numRows = (isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows); //If multiple months, use the higher number of rows (see #7043)
5509
this.maxRows = numRows;
5510
printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
5511
for (dRow = 0; dRow < numRows; dRow++) { // create date picker rows
5513
tbody = (!showWeek ? "" : "<td class='ui-datepicker-week-col'>" +
5514
this._get(inst, "calculateWeek")(printDate) + "</td>");
5515
for (dow = 0; dow < 7; dow++) { // create date picker days
5516
daySettings = (beforeShowDay ?
5517
beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, ""]);
5518
otherMonth = (printDate.getMonth() !== drawMonth);
5519
unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] ||
5520
(minDate && printDate < minDate) || (maxDate && printDate > maxDate);
5521
tbody += "<td class='" +
5522
((dow + firstDay + 6) % 7 >= 5 ? " ui-datepicker-week-end" : "") + // highlight weekends
5523
(otherMonth ? " ui-datepicker-other-month" : "") + // highlight days from other months
5524
((printDate.getTime() === selectedDate.getTime() && drawMonth === inst.selectedMonth && inst._keyEvent) || // user pressed key
5525
(defaultDate.getTime() === printDate.getTime() && defaultDate.getTime() === selectedDate.getTime()) ?
5526
// or defaultDate is current printedDate and defaultDate is selectedDate
5527
" " + this._dayOverClass : "") + // highlight selected day
5528
(unselectable ? " " + this._unselectableClass + " ui-state-disabled": "") + // highlight unselectable days
5529
(otherMonth && !showOtherMonths ? "" : " " + daySettings[1] + // highlight custom dates
5530
(printDate.getTime() === currentDate.getTime() ? " " + this._currentClass : "") + // highlight selected day
5531
(printDate.getTime() === today.getTime() ? " ui-datepicker-today" : "")) + "'" + // highlight today (if different)
5532
((!otherMonth || showOtherMonths) && daySettings[2] ? " title='" + daySettings[2].replace(/'/g, "'") + "'" : "") + // cell title
5533
(unselectable ? "" : " data-handler='selectDay' data-event='click' data-month='" + printDate.getMonth() + "' data-year='" + printDate.getFullYear() + "'") + ">" + // actions
5534
(otherMonth && !showOtherMonths ? " " : // display for other months
5535
(unselectable ? "<span class='ui-state-default'>" + printDate.getDate() + "</span>" : "<a class='ui-state-default" +
5536
(printDate.getTime() === today.getTime() ? " ui-state-highlight" : "") +
5537
(printDate.getTime() === currentDate.getTime() ? " ui-state-active" : "") + // highlight selected day
5538
(otherMonth ? " ui-priority-secondary" : "") + // distinguish dates from other months
5539
"' href='#'>" + printDate.getDate() + "</a>")) + "</td>"; // display selectable date
5540
printDate.setDate(printDate.getDate() + 1);
5541
printDate = this._daylightSavingAdjust(printDate);
5543
calender += tbody + "</tr>";
5546
if (drawMonth > 11) {
5550
calender += "</tbody></table>" + (isMultiMonth ? "</div>" +
5551
((numMonths[0] > 0 && col === numMonths[1]-1) ? "<div class='ui-datepicker-row-break'></div>" : "") : "");
5556
html += buttonPanel;
5557
inst._keyEvent = false;
5561
/* Generate the month and year header. */
5562
_generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate,
5563
secondary, monthNames, monthNamesShort) {
5565
var inMinYear, inMaxYear, month, years, thisYear, determineYear, year, endYear,
5566
changeMonth = this._get(inst, "changeMonth"),
5567
changeYear = this._get(inst, "changeYear"),
5568
showMonthAfterYear = this._get(inst, "showMonthAfterYear"),
5569
html = "<div class='ui-datepicker-title'>",
5573
if (secondary || !changeMonth) {
5574
monthHtml += "<span class='ui-datepicker-month'>" + monthNames[drawMonth] + "</span>";
5576
inMinYear = (minDate && minDate.getFullYear() === drawYear);
5577
inMaxYear = (maxDate && maxDate.getFullYear() === drawYear);
5578
monthHtml += "<select class='ui-datepicker-month' data-handler='selectMonth' data-event='change'>";
5579
for ( month = 0; month < 12; month++) {
5580
if ((!inMinYear || month >= minDate.getMonth()) && (!inMaxYear || month <= maxDate.getMonth())) {
5581
monthHtml += "<option value='" + month + "'" +
5582
(month === drawMonth ? " selected='selected'" : "") +
5583
">" + monthNamesShort[month] + "</option>";
5586
monthHtml += "</select>";
5589
if (!showMonthAfterYear) {
5590
html += monthHtml + (secondary || !(changeMonth && changeYear) ? " " : "");
5594
if ( !inst.yearshtml ) {
5595
inst.yearshtml = "";
5596
if (secondary || !changeYear) {
5597
html += "<span class='ui-datepicker-year'>" + drawYear + "</span>";
5599
// determine range of years to display
5600
years = this._get(inst, "yearRange").split(":");
5601
thisYear = new Date().getFullYear();
5602
determineYear = function(value) {
5603
var year = (value.match(/c[+\-].*/) ? drawYear + parseInt(value.substring(1), 10) :
5604
(value.match(/[+\-].*/) ? thisYear + parseInt(value, 10) :
5605
parseInt(value, 10)));
5606
return (isNaN(year) ? thisYear : year);
5608
year = determineYear(years[0]);
5609
endYear = Math.max(year, determineYear(years[1] || ""));
5610
year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
5611
endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
5612
inst.yearshtml += "<select class='ui-datepicker-year' data-handler='selectYear' data-event='change'>";
5613
for (; year <= endYear; year++) {
5614
inst.yearshtml += "<option value='" + year + "'" +
5615
(year === drawYear ? " selected='selected'" : "") +
5616
">" + year + "</option>";
5618
inst.yearshtml += "</select>";
5620
html += inst.yearshtml;
5621
inst.yearshtml = null;
5625
html += this._get(inst, "yearSuffix");
5626
if (showMonthAfterYear) {
5627
html += (secondary || !(changeMonth && changeYear) ? " " : "") + monthHtml;
5629
html += "</div>"; // Close datepicker_header
5633
/* Adjust one of the date sub-fields. */
5634
_adjustInstDate: function(inst, offset, period) {
5635
var year = inst.drawYear + (period === "Y" ? offset : 0),
5636
month = inst.drawMonth + (period === "M" ? offset : 0),
5637
day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) + (period === "D" ? offset : 0),
5638
date = this._restrictMinMax(inst, this._daylightSavingAdjust(new Date(year, month, day)));
5640
inst.selectedDay = date.getDate();
5641
inst.drawMonth = inst.selectedMonth = date.getMonth();
5642
inst.drawYear = inst.selectedYear = date.getFullYear();
5643
if (period === "M" || period === "Y") {
5644
this._notifyChange(inst);
5648
/* Ensure a date is within any min/max bounds. */
5649
_restrictMinMax: function(inst, date) {
5650
var minDate = this._getMinMaxDate(inst, "min"),
5651
maxDate = this._getMinMaxDate(inst, "max"),
5652
newDate = (minDate && date < minDate ? minDate : date);
5653
return (maxDate && newDate > maxDate ? maxDate : newDate);
5656
/* Notify change of month/year. */
5657
_notifyChange: function(inst) {
5658
var onChange = this._get(inst, "onChangeMonthYear");
5660
onChange.apply((inst.input ? inst.input[0] : null),
5661
[inst.selectedYear, inst.selectedMonth + 1, inst]);
5665
/* Determine the number of months to show. */
5666
_getNumberOfMonths: function(inst) {
5667
var numMonths = this._get(inst, "numberOfMonths");
5668
return (numMonths == null ? [1, 1] : (typeof numMonths === "number" ? [1, numMonths] : numMonths));
5671
/* Determine the current maximum date - ensure no time components are set. */
5672
_getMinMaxDate: function(inst, minMax) {
5673
return this._determineDate(inst, this._get(inst, minMax + "Date"), null);
5676
/* Find the number of days in a given month. */
5677
_getDaysInMonth: function(year, month) {
5678
return 32 - this._daylightSavingAdjust(new Date(year, month, 32)).getDate();
5681
/* Find the day of the week of the first of a month. */
5682
_getFirstDayOfMonth: function(year, month) {
5683
return new Date(year, month, 1).getDay();
5686
/* Determines if we should allow a "next/prev" month display change. */
5687
_canAdjustMonth: function(inst, offset, curYear, curMonth) {
5688
var numMonths = this._getNumberOfMonths(inst),
5689
date = this._daylightSavingAdjust(new Date(curYear,
5690
curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1));
5693
date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
5695
return this._isInRange(inst, date);
5698
/* Is the given date in the accepted range? */
5699
_isInRange: function(inst, date) {
5700
var yearSplit, currentYear,
5701
minDate = this._getMinMaxDate(inst, "min"),
5702
maxDate = this._getMinMaxDate(inst, "max"),
5705
years = this._get(inst, "yearRange");
5707
yearSplit = years.split(":");
5708
currentYear = new Date().getFullYear();
5709
minYear = parseInt(yearSplit[0], 10);
5710
maxYear = parseInt(yearSplit[1], 10);
5711
if ( yearSplit[0].match(/[+\-].*/) ) {
5712
minYear += currentYear;
5714
if ( yearSplit[1].match(/[+\-].*/) ) {
5715
maxYear += currentYear;
5719
return ((!minDate || date.getTime() >= minDate.getTime()) &&
5720
(!maxDate || date.getTime() <= maxDate.getTime()) &&
5721
(!minYear || date.getFullYear() >= minYear) &&
5722
(!maxYear || date.getFullYear() <= maxYear));
5725
/* Provide the configuration settings for formatting/parsing. */
5726
_getFormatConfig: function(inst) {
5727
var shortYearCutoff = this._get(inst, "shortYearCutoff");
5728
shortYearCutoff = (typeof shortYearCutoff !== "string" ? shortYearCutoff :
5729
new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
5730
return {shortYearCutoff: shortYearCutoff,
5731
dayNamesShort: this._get(inst, "dayNamesShort"), dayNames: this._get(inst, "dayNames"),
5732
monthNamesShort: this._get(inst, "monthNamesShort"), monthNames: this._get(inst, "monthNames")};
5735
/* Format the given date for display. */
5736
_formatDate: function(inst, day, month, year) {
5738
inst.currentDay = inst.selectedDay;
5739
inst.currentMonth = inst.selectedMonth;
5740
inst.currentYear = inst.selectedYear;
5742
var date = (day ? (typeof day === "object" ? day :
5743
this._daylightSavingAdjust(new Date(year, month, day))) :
5744
this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
5745
return this.formatDate(this._get(inst, "dateFormat"), date, this._getFormatConfig(inst));
5750
* Bind hover events for datepicker elements.
5751
* Done via delegate so the binding only occurs once in the lifetime of the parent div.
5752
* Global datepicker_instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker.
5754
function datepicker_bindHover(dpDiv) {
5755
var selector = "button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";
5756
return dpDiv.delegate(selector, "mouseout", function() {
5757
$(this).removeClass("ui-state-hover");
5758
if (this.className.indexOf("ui-datepicker-prev") !== -1) {
5759
$(this).removeClass("ui-datepicker-prev-hover");
5761
if (this.className.indexOf("ui-datepicker-next") !== -1) {
5762
$(this).removeClass("ui-datepicker-next-hover");
5765
.delegate( selector, "mouseover", datepicker_handleMouseover );
5768
function datepicker_handleMouseover() {
5769
if (!$.datepicker._isDisabledDatepicker( datepicker_instActive.inline? datepicker_instActive.dpDiv.parent()[0] : datepicker_instActive.input[0])) {
5770
$(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover");
5771
$(this).addClass("ui-state-hover");
5772
if (this.className.indexOf("ui-datepicker-prev") !== -1) {
5773
$(this).addClass("ui-datepicker-prev-hover");
5775
if (this.className.indexOf("ui-datepicker-next") !== -1) {
5776
$(this).addClass("ui-datepicker-next-hover");
5781
/* jQuery extend now ignores nulls! */
5782
function datepicker_extendRemove(target, props) {
5783
$.extend(target, props);
5784
for (var name in props) {
5785
if (props[name] == null) {
5786
target[name] = props[name];
5792
/* Invoke the datepicker functionality.
5793
@param options string - a command, optionally followed by additional parameters or
5794
Object - settings for attaching new datepicker functionality
5795
@return jQuery object */
5796
$.fn.datepicker = function(options){
5798
/* Verify an empty collection wasn't passed - Fixes #6976 */
5799
if ( !this.length ) {
5803
/* Initialise the date picker. */
5804
if (!$.datepicker.initialized) {
5805
$(document).mousedown($.datepicker._checkExternalClick);
5806
$.datepicker.initialized = true;
5809
/* Append datepicker main container to body if not exist. */
5810
if ($("#"+$.datepicker._mainDivId).length === 0) {
5811
$("body").append($.datepicker.dpDiv);
5814
var otherArgs = Array.prototype.slice.call(arguments, 1);
5815
if (typeof options === "string" && (options === "isDisabled" || options === "getDate" || options === "widget")) {
5816
return $.datepicker["_" + options + "Datepicker"].
5817
apply($.datepicker, [this[0]].concat(otherArgs));
5819
if (options === "option" && arguments.length === 2 && typeof arguments[1] === "string") {
5820
return $.datepicker["_" + options + "Datepicker"].
5821
apply($.datepicker, [this[0]].concat(otherArgs));
5823
return this.each(function() {
5824
typeof options === "string" ?
5825
$.datepicker["_" + options + "Datepicker"].
5826
apply($.datepicker, [this].concat(otherArgs)) :
5827
$.datepicker._attachDatepicker(this, options);
5831
$.datepicker = new Datepicker(); // singleton instance
5832
$.datepicker.initialized = false;
5833
$.datepicker.uuid = new Date().getTime();
5834
$.datepicker.version = "1.11.4";
5836
var datepicker = $.datepicker;
5840
* jQuery UI Draggable 1.11.4
5841
* http://jqueryui.com
5843
* Copyright jQuery Foundation and other contributors
5844
* Released under the MIT license.
5845
* http://jquery.org/license
5847
* http://api.jqueryui.com/draggable/
5851
$.widget("ui.draggable", $.ui.mouse, {
5853
widgetEventPrefix: "drag",
5858
connectToSortable: false,
5867
refreshPositions: false,
5869
revertDuration: 500,
5872
scrollSensitivity: 20,
5885
_create: function() {
5887
if ( this.options.helper === "original" ) {
5888
this._setPositionRelative();
5890
if (this.options.addClasses){
5891
this.element.addClass("ui-draggable");
5893
if (this.options.disabled){
5894
this.element.addClass("ui-draggable-disabled");
5896
this._setHandleClassName();
5901
_setOption: function( key, value ) {
5902
this._super( key, value );
5903
if ( key === "handle" ) {
5904
this._removeHandleClassName();
5905
this._setHandleClassName();
5909
_destroy: function() {
5910
if ( ( this.helper || this.element ).is( ".ui-draggable-dragging" ) ) {
5911
this.destroyOnClear = true;
5914
this.element.removeClass( "ui-draggable ui-draggable-dragging ui-draggable-disabled" );
5915
this._removeHandleClassName();
5916
this._mouseDestroy();
5919
_mouseCapture: function(event) {
5920
var o = this.options;
5922
this._blurActiveElement( event );
5924
// among others, prevent a drag on a resizable-handle
5925
if (this.helper || o.disabled || $(event.target).closest(".ui-resizable-handle").length > 0) {
5929
//Quit if we're not on a valid handle
5930
this.handle = this._getHandle(event);
5935
this._blockFrames( o.iframeFix === true ? "iframe" : o.iframeFix );
5941
_blockFrames: function( selector ) {
5942
this.iframeBlocks = this.document.find( selector ).map(function() {
5943
var iframe = $( this );
5946
.css( "position", "absolute" )
5947
.appendTo( iframe.parent() )
5948
.outerWidth( iframe.outerWidth() )
5949
.outerHeight( iframe.outerHeight() )
5950
.offset( iframe.offset() )[ 0 ];
5954
_unblockFrames: function() {
5955
if ( this.iframeBlocks ) {
5956
this.iframeBlocks.remove();
5957
delete this.iframeBlocks;
5961
_blurActiveElement: function( event ) {
5962
var document = this.document[ 0 ];
5964
// Only need to blur if the event occurred on the draggable itself, see #10527
5965
if ( !this.handleElement.is( event.target ) ) {
5970
// IE9 throws an "Unspecified error" accessing document.activeElement from an <iframe>
5973
// Support: IE9, IE10
5974
// If the <body> is blurred, IE will switch windows, see #9520
5975
if ( document.activeElement && document.activeElement.nodeName.toLowerCase() !== "body" ) {
5977
// Blur any element that currently has focus, see #4261
5978
$( document.activeElement ).blur();
5980
} catch ( error ) {}
5983
_mouseStart: function(event) {
5985
var o = this.options;
5987
//Create and append the visible helper
5988
this.helper = this._createHelper(event);
5990
this.helper.addClass("ui-draggable-dragging");
5992
//Cache the helper size
5993
this._cacheHelperProportions();
5995
//If ddmanager is used for droppables, set the global draggable
5996
if ($.ui.ddmanager) {
5997
$.ui.ddmanager.current = this;
6001
* - Position generation -
6002
* This block generates everything position related - it's the core of draggables.
6005
//Cache the margins of the original element
6006
this._cacheMargins();
6008
//Store the helper's css position
6009
this.cssPosition = this.helper.css( "position" );
6010
this.scrollParent = this.helper.scrollParent( true );
6011
this.offsetParent = this.helper.offsetParent();
6012
this.hasFixedAncestor = this.helper.parents().filter(function() {
6013
return $( this ).css( "position" ) === "fixed";
6016
//The element's absolute position on the page minus margins
6017
this.positionAbs = this.element.offset();
6018
this._refreshOffsets( event );
6020
//Generate the original position
6021
this.originalPosition = this.position = this._generatePosition( event, false );
6022
this.originalPageX = event.pageX;
6023
this.originalPageY = event.pageY;
6025
//Adjust the mouse offset relative to the helper if "cursorAt" is supplied
6026
(o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
6028
//Set a containment if given in the options
6029
this._setContainment();
6031
//Trigger event + callbacks
6032
if (this._trigger("start", event) === false) {
6037
//Recache the helper size
6038
this._cacheHelperProportions();
6040
//Prepare the droppable offsets
6041
if ($.ui.ddmanager && !o.dropBehaviour) {
6042
$.ui.ddmanager.prepareOffsets(this, event);
6045
// Reset helper's right/bottom css if they're set and set explicit width/height instead
6046
// as this prevents resizing of elements with right/bottom set (see #7772)
6047
this._normalizeRightBottom();
6049
this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position
6051
//If the ddmanager is used for droppables, inform the manager that dragging has started (see #5003)
6052
if ( $.ui.ddmanager ) {
6053
$.ui.ddmanager.dragStart(this, event);
6059
_refreshOffsets: function( event ) {
6061
top: this.positionAbs.top - this.margins.top,
6062
left: this.positionAbs.left - this.margins.left,
6064
parent: this._getParentOffset(),
6065
relative: this._getRelativeOffset()
6068
this.offset.click = {
6069
left: event.pageX - this.offset.left,
6070
top: event.pageY - this.offset.top
6074
_mouseDrag: function(event, noPropagation) {
6075
// reset any necessary cached properties (see #5009)
6076
if ( this.hasFixedAncestor ) {
6077
this.offset.parent = this._getParentOffset();
6080
//Compute the helpers position
6081
this.position = this._generatePosition( event, true );
6082
this.positionAbs = this._convertPositionTo("absolute");
6084
//Call plugins and callbacks and use the resulting position if something is returned
6085
if (!noPropagation) {
6086
var ui = this._uiHash();
6087
if (this._trigger("drag", event, ui) === false) {
6091
this.position = ui.position;
6094
this.helper[ 0 ].style.left = this.position.left + "px";
6095
this.helper[ 0 ].style.top = this.position.top + "px";
6097
if ($.ui.ddmanager) {
6098
$.ui.ddmanager.drag(this, event);
6104
_mouseStop: function(event) {
6106
//If we are using droppables, inform the manager about the drop
6109
if ($.ui.ddmanager && !this.options.dropBehaviour) {
6110
dropped = $.ui.ddmanager.drop(this, event);
6113
//if a drop comes from outside (a sortable)
6115
dropped = this.dropped;
6116
this.dropped = false;
6119
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))) {
6120
$(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() {
6121
if (that._trigger("stop", event) !== false) {
6126
if (this._trigger("stop", event) !== false) {
6134
_mouseUp: function( event ) {
6135
this._unblockFrames();
6137
//If the ddmanager is used for droppables, inform the manager that dragging has stopped (see #5003)
6138
if ( $.ui.ddmanager ) {
6139
$.ui.ddmanager.dragStop(this, event);
6142
// Only need to focus if the event occurred on the draggable itself, see #10527
6143
if ( this.handleElement.is( event.target ) ) {
6144
// The interaction is over; whether or not the click resulted in a drag, focus the element
6145
this.element.focus();
6148
return $.ui.mouse.prototype._mouseUp.call(this, event);
6151
cancel: function() {
6153
if (this.helper.is(".ui-draggable-dragging")) {
6163
_getHandle: function(event) {
6164
return this.options.handle ?
6165
!!$( event.target ).closest( this.element.find( this.options.handle ) ).length :
6169
_setHandleClassName: function() {
6170
this.handleElement = this.options.handle ?
6171
this.element.find( this.options.handle ) : this.element;
6172
this.handleElement.addClass( "ui-draggable-handle" );
6175
_removeHandleClassName: function() {
6176
this.handleElement.removeClass( "ui-draggable-handle" );
6179
_createHelper: function(event) {
6181
var o = this.options,
6182
helperIsFunction = $.isFunction( o.helper ),
6183
helper = helperIsFunction ?
6184
$( o.helper.apply( this.element[ 0 ], [ event ] ) ) :
6185
( o.helper === "clone" ?
6186
this.element.clone().removeAttr( "id" ) :
6189
if (!helper.parents("body").length) {
6190
helper.appendTo((o.appendTo === "parent" ? this.element[0].parentNode : o.appendTo));
6193
// http://bugs.jqueryui.com/ticket/9446
6194
// a helper function can return the original element
6195
// which wouldn't have been set to relative in _create
6196
if ( helperIsFunction && helper[ 0 ] === this.element[ 0 ] ) {
6197
this._setPositionRelative();
6200
if (helper[0] !== this.element[0] && !(/(fixed|absolute)/).test(helper.css("position"))) {
6201
helper.css("position", "absolute");
6208
_setPositionRelative: function() {
6209
if ( !( /^(?:r|a|f)/ ).test( this.element.css( "position" ) ) ) {
6210
this.element[ 0 ].style.position = "relative";
6214
_adjustOffsetFromHelper: function(obj) {
6215
if (typeof obj === "string") {
6216
obj = obj.split(" ");
6218
if ($.isArray(obj)) {
6219
obj = { left: +obj[0], top: +obj[1] || 0 };
6221
if ("left" in obj) {
6222
this.offset.click.left = obj.left + this.margins.left;
6224
if ("right" in obj) {
6225
this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
6228
this.offset.click.top = obj.top + this.margins.top;
6230
if ("bottom" in obj) {
6231
this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
6235
_isRootNode: function( element ) {
6236
return ( /(html|body)/i ).test( element.tagName ) || element === this.document[ 0 ];
6239
_getParentOffset: function() {
6241
//Get the offsetParent and cache its position
6242
var po = this.offsetParent.offset(),
6243
document = this.document[ 0 ];
6245
// This is a special case where we need to modify a offset calculated on start, since the following happened:
6246
// 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
6247
// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
6248
// the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
6249
if (this.cssPosition === "absolute" && this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) {
6250
po.left += this.scrollParent.scrollLeft();
6251
po.top += this.scrollParent.scrollTop();
6254
if ( this._isRootNode( this.offsetParent[ 0 ] ) ) {
6255
po = { top: 0, left: 0 };
6259
top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"), 10) || 0),
6260
left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"), 10) || 0)
6265
_getRelativeOffset: function() {
6266
if ( this.cssPosition !== "relative" ) {
6267
return { top: 0, left: 0 };
6270
var p = this.element.position(),
6271
scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] );
6274
top: p.top - ( parseInt(this.helper.css( "top" ), 10) || 0 ) + ( !scrollIsRootNode ? this.scrollParent.scrollTop() : 0 ),
6275
left: p.left - ( parseInt(this.helper.css( "left" ), 10) || 0 ) + ( !scrollIsRootNode ? this.scrollParent.scrollLeft() : 0 )
6280
_cacheMargins: function() {
6282
left: (parseInt(this.element.css("marginLeft"), 10) || 0),
6283
top: (parseInt(this.element.css("marginTop"), 10) || 0),
6284
right: (parseInt(this.element.css("marginRight"), 10) || 0),
6285
bottom: (parseInt(this.element.css("marginBottom"), 10) || 0)
6289
_cacheHelperProportions: function() {
6290
this.helperProportions = {
6291
width: this.helper.outerWidth(),
6292
height: this.helper.outerHeight()
6296
_setContainment: function() {
6298
var isUserScrollable, c, ce,
6300
document = this.document[ 0 ];
6302
this.relativeContainer = null;
6304
if ( !o.containment ) {
6305
this.containment = null;
6309
if ( o.containment === "window" ) {
6310
this.containment = [
6311
$( window ).scrollLeft() - this.offset.relative.left - this.offset.parent.left,
6312
$( window ).scrollTop() - this.offset.relative.top - this.offset.parent.top,
6313
$( window ).scrollLeft() + $( window ).width() - this.helperProportions.width - this.margins.left,
6314
$( window ).scrollTop() + ( $( window ).height() || document.body.parentNode.scrollHeight ) - this.helperProportions.height - this.margins.top
6319
if ( o.containment === "document") {
6320
this.containment = [
6323
$( document ).width() - this.helperProportions.width - this.margins.left,
6324
( $( document ).height() || document.body.parentNode.scrollHeight ) - this.helperProportions.height - this.margins.top
6329
if ( o.containment.constructor === Array ) {
6330
this.containment = o.containment;
6334
if ( o.containment === "parent" ) {
6335
o.containment = this.helper[ 0 ].parentNode;
6338
c = $( o.containment );
6345
isUserScrollable = /(scroll|auto)/.test( c.css( "overflow" ) );
6347
this.containment = [
6348
( parseInt( c.css( "borderLeftWidth" ), 10 ) || 0 ) + ( parseInt( c.css( "paddingLeft" ), 10 ) || 0 ),
6349
( parseInt( c.css( "borderTopWidth" ), 10 ) || 0 ) + ( parseInt( c.css( "paddingTop" ), 10 ) || 0 ),
6350
( isUserScrollable ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) -
6351
( parseInt( c.css( "borderRightWidth" ), 10 ) || 0 ) -
6352
( parseInt( c.css( "paddingRight" ), 10 ) || 0 ) -
6353
this.helperProportions.width -
6356
( isUserScrollable ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) -
6357
( parseInt( c.css( "borderBottomWidth" ), 10 ) || 0 ) -
6358
( parseInt( c.css( "paddingBottom" ), 10 ) || 0 ) -
6359
this.helperProportions.height -
6363
this.relativeContainer = c;
6366
_convertPositionTo: function(d, pos) {
6369
pos = this.position;
6372
var mod = d === "absolute" ? 1 : -1,
6373
scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] );
6377
pos.top + // The absolute mouse position
6378
this.offset.relative.top * mod + // Only for relative positioned nodes: Relative offset from element to offset parent
6379
this.offset.parent.top * mod - // The offsetParent's offset without borders (offset + border)
6380
( ( this.cssPosition === "fixed" ? -this.offset.scroll.top : ( scrollIsRootNode ? 0 : this.offset.scroll.top ) ) * mod)
6383
pos.left + // The absolute mouse position
6384
this.offset.relative.left * mod + // Only for relative positioned nodes: Relative offset from element to offset parent
6385
this.offset.parent.left * mod - // The offsetParent's offset without borders (offset + border)
6386
( ( this.cssPosition === "fixed" ? -this.offset.scroll.left : ( scrollIsRootNode ? 0 : this.offset.scroll.left ) ) * mod)
6392
_generatePosition: function( event, constrainPosition ) {
6394
var containment, co, top, left,
6396
scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] ),
6397
pageX = event.pageX,
6398
pageY = event.pageY;
6401
if ( !scrollIsRootNode || !this.offset.scroll ) {
6402
this.offset.scroll = {
6403
top: this.scrollParent.scrollTop(),
6404
left: this.scrollParent.scrollLeft()
6409
* - Position constraining -
6410
* Constrain the position to a mix of grid, containment.
6413
// If we are not dragging yet, we won't check for options
6414
if ( constrainPosition ) {
6415
if ( this.containment ) {
6416
if ( this.relativeContainer ){
6417
co = this.relativeContainer.offset();
6419
this.containment[ 0 ] + co.left,
6420
this.containment[ 1 ] + co.top,
6421
this.containment[ 2 ] + co.left,
6422
this.containment[ 3 ] + co.top
6425
containment = this.containment;
6428
if (event.pageX - this.offset.click.left < containment[0]) {
6429
pageX = containment[0] + this.offset.click.left;
6431
if (event.pageY - this.offset.click.top < containment[1]) {
6432
pageY = containment[1] + this.offset.click.top;
6434
if (event.pageX - this.offset.click.left > containment[2]) {
6435
pageX = containment[2] + this.offset.click.left;
6437
if (event.pageY - this.offset.click.top > containment[3]) {
6438
pageY = containment[3] + this.offset.click.top;
6443
//Check for grid elements set to 0 to prevent divide by 0 error causing invalid argument errors in IE (see ticket #6950)
6444
top = o.grid[1] ? this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1] : this.originalPageY;
6445
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;
6447
left = o.grid[0] ? this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0] : this.originalPageX;
6448
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;
6451
if ( o.axis === "y" ) {
6452
pageX = this.originalPageX;
6455
if ( o.axis === "x" ) {
6456
pageY = this.originalPageY;
6462
pageY - // The absolute mouse position
6463
this.offset.click.top - // Click offset (relative to the element)
6464
this.offset.relative.top - // Only for relative positioned nodes: Relative offset from element to offset parent
6465
this.offset.parent.top + // The offsetParent's offset without borders (offset + border)
6466
( this.cssPosition === "fixed" ? -this.offset.scroll.top : ( scrollIsRootNode ? 0 : this.offset.scroll.top ) )
6469
pageX - // The absolute mouse position
6470
this.offset.click.left - // Click offset (relative to the element)
6471
this.offset.relative.left - // Only for relative positioned nodes: Relative offset from element to offset parent
6472
this.offset.parent.left + // The offsetParent's offset without borders (offset + border)
6473
( this.cssPosition === "fixed" ? -this.offset.scroll.left : ( scrollIsRootNode ? 0 : this.offset.scroll.left ) )
6479
_clear: function() {
6480
this.helper.removeClass("ui-draggable-dragging");
6481
if (this.helper[0] !== this.element[0] && !this.cancelHelperRemoval) {
6482
this.helper.remove();
6485
this.cancelHelperRemoval = false;
6486
if ( this.destroyOnClear ) {
6491
_normalizeRightBottom: function() {
6492
if ( this.options.axis !== "y" && this.helper.css( "right" ) !== "auto" ) {
6493
this.helper.width( this.helper.width() );
6494
this.helper.css( "right", "auto" );
6496
if ( this.options.axis !== "x" && this.helper.css( "bottom" ) !== "auto" ) {
6497
this.helper.height( this.helper.height() );
6498
this.helper.css( "bottom", "auto" );
6502
// From now on bulk stuff - mainly helpers
6504
_trigger: function( type, event, ui ) {
6505
ui = ui || this._uiHash();
6506
$.ui.plugin.call( this, type, [ event, ui, this ], true );
6508
// Absolute position and offset (see #6884 ) have to be recalculated after plugins
6509
if ( /^(drag|start|stop)/.test( type ) ) {
6510
this.positionAbs = this._convertPositionTo( "absolute" );
6511
ui.offset = this.positionAbs;
6513
return $.Widget.prototype._trigger.call( this, type, event, ui );
6518
_uiHash: function() {
6520
helper: this.helper,
6521
position: this.position,
6522
originalPosition: this.originalPosition,
6523
offset: this.positionAbs
6529
$.ui.plugin.add( "draggable", "connectToSortable", {
6530
start: function( event, ui, draggable ) {
6531
var uiSortable = $.extend( {}, ui, {
6532
item: draggable.element
6535
draggable.sortables = [];
6536
$( draggable.options.connectToSortable ).each(function() {
6537
var sortable = $( this ).sortable( "instance" );
6539
if ( sortable && !sortable.options.disabled ) {
6540
draggable.sortables.push( sortable );
6542
// refreshPositions is called at drag start to refresh the containerCache
6543
// which is used in drag. This ensures it's initialized and synchronized
6544
// with any changes that might have happened on the page since initialization.
6545
sortable.refreshPositions();
6546
sortable._trigger("activate", event, uiSortable);
6550
stop: function( event, ui, draggable ) {
6551
var uiSortable = $.extend( {}, ui, {
6552
item: draggable.element
6555
draggable.cancelHelperRemoval = false;
6557
$.each( draggable.sortables, function() {
6558
var sortable = this;
6560
if ( sortable.isOver ) {
6561
sortable.isOver = 0;
6563
// Allow this sortable to handle removing the helper
6564
draggable.cancelHelperRemoval = true;
6565
sortable.cancelHelperRemoval = false;
6567
// Use _storedCSS To restore properties in the sortable,
6568
// as this also handles revert (#9675) since the draggable
6569
// may have modified them in unexpected ways (#8809)
6570
sortable._storedCSS = {
6571
position: sortable.placeholder.css( "position" ),
6572
top: sortable.placeholder.css( "top" ),
6573
left: sortable.placeholder.css( "left" )
6576
sortable._mouseStop(event);
6578
// Once drag has ended, the sortable should return to using
6579
// its original helper, not the shared helper from draggable
6580
sortable.options.helper = sortable.options._helper;
6582
// Prevent this Sortable from removing the helper.
6583
// However, don't set the draggable to remove the helper
6584
// either as another connected Sortable may yet handle the removal.
6585
sortable.cancelHelperRemoval = true;
6587
sortable._trigger( "deactivate", event, uiSortable );
6591
drag: function( event, ui, draggable ) {
6592
$.each( draggable.sortables, function() {
6593
var innermostIntersecting = false,
6596
// Copy over variables that sortable's _intersectsWith uses
6597
sortable.positionAbs = draggable.positionAbs;
6598
sortable.helperProportions = draggable.helperProportions;
6599
sortable.offset.click = draggable.offset.click;
6601
if ( sortable._intersectsWith( sortable.containerCache ) ) {
6602
innermostIntersecting = true;
6604
$.each( draggable.sortables, function() {
6605
// Copy over variables that sortable's _intersectsWith uses
6606
this.positionAbs = draggable.positionAbs;
6607
this.helperProportions = draggable.helperProportions;
6608
this.offset.click = draggable.offset.click;
6610
if ( this !== sortable &&
6611
this._intersectsWith( this.containerCache ) &&
6612
$.contains( sortable.element[ 0 ], this.element[ 0 ] ) ) {
6613
innermostIntersecting = false;
6616
return innermostIntersecting;
6620
if ( innermostIntersecting ) {
6621
// If it intersects, we use a little isOver variable and set it once,
6622
// so that the move-in stuff gets fired only once.
6623
if ( !sortable.isOver ) {
6624
sortable.isOver = 1;
6626
// Store draggable's parent in case we need to reappend to it later.
6627
draggable._parent = ui.helper.parent();
6629
sortable.currentItem = ui.helper
6630
.appendTo( sortable.element )
6631
.data( "ui-sortable-item", true );
6633
// Store helper option to later restore it
6634
sortable.options._helper = sortable.options.helper;
6636
sortable.options.helper = function() {
6637
return ui.helper[ 0 ];
6640
// Fire the start events of the sortable with our passed browser event,
6641
// and our own helper (so it doesn't create a new one)
6642
event.target = sortable.currentItem[ 0 ];
6643
sortable._mouseCapture( event, true );
6644
sortable._mouseStart( event, true, true );
6646
// Because the browser event is way off the new appended portlet,
6647
// modify necessary variables to reflect the changes
6648
sortable.offset.click.top = draggable.offset.click.top;
6649
sortable.offset.click.left = draggable.offset.click.left;
6650
sortable.offset.parent.left -= draggable.offset.parent.left -
6651
sortable.offset.parent.left;
6652
sortable.offset.parent.top -= draggable.offset.parent.top -
6653
sortable.offset.parent.top;
6655
draggable._trigger( "toSortable", event );
6657
// Inform draggable that the helper is in a valid drop zone,
6658
// used solely in the revert option to handle "valid/invalid".
6659
draggable.dropped = sortable.element;
6661
// Need to refreshPositions of all sortables in the case that
6662
// adding to one sortable changes the location of the other sortables (#9675)
6663
$.each( draggable.sortables, function() {
6664
this.refreshPositions();
6667
// hack so receive/update callbacks work (mostly)
6668
draggable.currentItem = draggable.element;
6669
sortable.fromOutside = draggable;
6672
if ( sortable.currentItem ) {
6673
sortable._mouseDrag( event );
6674
// Copy the sortable's position because the draggable's can potentially reflect
6675
// a relative position, while sortable is always absolute, which the dragged
6676
// element has now become. (#8809)
6677
ui.position = sortable.position;
6680
// If it doesn't intersect with the sortable, and it intersected before,
6681
// we fake the drag stop of the sortable, but make sure it doesn't remove
6682
// the helper by using cancelHelperRemoval.
6683
if ( sortable.isOver ) {
6685
sortable.isOver = 0;
6686
sortable.cancelHelperRemoval = true;
6688
// Calling sortable's mouseStop would trigger a revert,
6689
// so revert must be temporarily false until after mouseStop is called.
6690
sortable.options._revert = sortable.options.revert;
6691
sortable.options.revert = false;
6693
sortable._trigger( "out", event, sortable._uiHash( sortable ) );
6694
sortable._mouseStop( event, true );
6696
// restore sortable behaviors that were modfied
6697
// when the draggable entered the sortable area (#9481)
6698
sortable.options.revert = sortable.options._revert;
6699
sortable.options.helper = sortable.options._helper;
6701
if ( sortable.placeholder ) {
6702
sortable.placeholder.remove();
6705
// Restore and recalculate the draggable's offset considering the sortable
6706
// may have modified them in unexpected ways. (#8809, #10669)
6707
ui.helper.appendTo( draggable._parent );
6708
draggable._refreshOffsets( event );
6709
ui.position = draggable._generatePosition( event, true );
6711
draggable._trigger( "fromSortable", event );
6713
// Inform draggable that the helper is no longer in a valid drop zone
6714
draggable.dropped = false;
6716
// Need to refreshPositions of all sortables just in case removing
6717
// from one sortable changes the location of other sortables (#9675)
6718
$.each( draggable.sortables, function() {
6719
this.refreshPositions();
6727
$.ui.plugin.add("draggable", "cursor", {
6728
start: function( event, ui, instance ) {
6729
var t = $( "body" ),
6730
o = instance.options;
6732
if (t.css("cursor")) {
6733
o._cursor = t.css("cursor");
6735
t.css("cursor", o.cursor);
6737
stop: function( event, ui, instance ) {
6738
var o = instance.options;
6740
$("body").css("cursor", o._cursor);
6745
$.ui.plugin.add("draggable", "opacity", {
6746
start: function( event, ui, instance ) {
6747
var t = $( ui.helper ),
6748
o = instance.options;
6749
if (t.css("opacity")) {
6750
o._opacity = t.css("opacity");
6752
t.css("opacity", o.opacity);
6754
stop: function( event, ui, instance ) {
6755
var o = instance.options;
6757
$(ui.helper).css("opacity", o._opacity);
6762
$.ui.plugin.add("draggable", "scroll", {
6763
start: function( event, ui, i ) {
6764
if ( !i.scrollParentNotHidden ) {
6765
i.scrollParentNotHidden = i.helper.scrollParent( false );
6768
if ( i.scrollParentNotHidden[ 0 ] !== i.document[ 0 ] && i.scrollParentNotHidden[ 0 ].tagName !== "HTML" ) {
6769
i.overflowOffset = i.scrollParentNotHidden.offset();
6772
drag: function( event, ui, i ) {
6776
scrollParent = i.scrollParentNotHidden[ 0 ],
6777
document = i.document[ 0 ];
6779
if ( scrollParent !== document && scrollParent.tagName !== "HTML" ) {
6780
if ( !o.axis || o.axis !== "x" ) {
6781
if ( ( i.overflowOffset.top + scrollParent.offsetHeight ) - event.pageY < o.scrollSensitivity ) {
6782
scrollParent.scrollTop = scrolled = scrollParent.scrollTop + o.scrollSpeed;
6783
} else if ( event.pageY - i.overflowOffset.top < o.scrollSensitivity ) {
6784
scrollParent.scrollTop = scrolled = scrollParent.scrollTop - o.scrollSpeed;
6788
if ( !o.axis || o.axis !== "y" ) {
6789
if ( ( i.overflowOffset.left + scrollParent.offsetWidth ) - event.pageX < o.scrollSensitivity ) {
6790
scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft + o.scrollSpeed;
6791
} else if ( event.pageX - i.overflowOffset.left < o.scrollSensitivity ) {
6792
scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft - o.scrollSpeed;
6798
if (!o.axis || o.axis !== "x") {
6799
if (event.pageY - $(document).scrollTop() < o.scrollSensitivity) {
6800
scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
6801
} else if ($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) {
6802
scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
6806
if (!o.axis || o.axis !== "y") {
6807
if (event.pageX - $(document).scrollLeft() < o.scrollSensitivity) {
6808
scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
6809
} else if ($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) {
6810
scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
6816
if (scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) {
6817
$.ui.ddmanager.prepareOffsets(i, event);
6823
$.ui.plugin.add("draggable", "snap", {
6824
start: function( event, ui, i ) {
6828
i.snapElements = [];
6830
$(o.snap.constructor !== String ? ( o.snap.items || ":data(ui-draggable)" ) : o.snap).each(function() {
6833
if (this !== i.element[0]) {
6834
i.snapElements.push({
6836
width: $t.outerWidth(), height: $t.outerHeight(),
6837
top: $o.top, left: $o.left
6843
drag: function( event, ui, inst ) {
6845
var ts, bs, ls, rs, l, r, t, b, i, first,
6847
d = o.snapTolerance,
6848
x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
6849
y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
6851
for (i = inst.snapElements.length - 1; i >= 0; i--){
6853
l = inst.snapElements[i].left - inst.margins.left;
6854
r = l + inst.snapElements[i].width;
6855
t = inst.snapElements[i].top - inst.margins.top;
6856
b = t + inst.snapElements[i].height;
6858
if ( x2 < l - d || x1 > r + d || y2 < t - d || y1 > b + d || !$.contains( inst.snapElements[ i ].item.ownerDocument, inst.snapElements[ i ].item ) ) {
6859
if (inst.snapElements[i].snapping) {
6860
(inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
6862
inst.snapElements[i].snapping = false;
6866
if (o.snapMode !== "inner") {
6867
ts = Math.abs(t - y2) <= d;
6868
bs = Math.abs(b - y1) <= d;
6869
ls = Math.abs(l - x2) <= d;
6870
rs = Math.abs(r - x1) <= d;
6872
ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top;
6875
ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top;
6878
ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left;
6881
ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left;
6885
first = (ts || bs || ls || rs);
6887
if (o.snapMode !== "outer") {
6888
ts = Math.abs(t - y1) <= d;
6889
bs = Math.abs(b - y2) <= d;
6890
ls = Math.abs(l - x1) <= d;
6891
rs = Math.abs(r - x2) <= d;
6893
ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top;
6896
ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top;
6899
ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left;
6902
ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left;
6906
if (!inst.snapElements[i].snapping && (ts || bs || ls || rs || first)) {
6907
(inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
6909
inst.snapElements[i].snapping = (ts || bs || ls || rs || first);
6916
$.ui.plugin.add("draggable", "stack", {
6917
start: function( event, ui, instance ) {
6919
o = instance.options,
6920
group = $.makeArray($(o.stack)).sort(function(a, b) {
6921
return (parseInt($(a).css("zIndex"), 10) || 0) - (parseInt($(b).css("zIndex"), 10) || 0);
6924
if (!group.length) { return; }
6926
min = parseInt($(group[0]).css("zIndex"), 10) || 0;
6927
$(group).each(function(i) {
6928
$(this).css("zIndex", min + i);
6930
this.css("zIndex", (min + group.length));
6934
$.ui.plugin.add("draggable", "zIndex", {
6935
start: function( event, ui, instance ) {
6936
var t = $( ui.helper ),
6937
o = instance.options;
6939
if (t.css("zIndex")) {
6940
o._zIndex = t.css("zIndex");
6942
t.css("zIndex", o.zIndex);
6944
stop: function( event, ui, instance ) {
6945
var o = instance.options;
6948
$(ui.helper).css("zIndex", o._zIndex);
6953
var draggable = $.ui.draggable;
6957
* jQuery UI Resizable 1.11.4
6958
* http://jqueryui.com
6960
* Copyright jQuery Foundation and other contributors
6961
* Released under the MIT license.
6962
* http://jquery.org/license
6964
* http://api.jqueryui.com/resizable/
6968
$.widget("ui.resizable", $.ui.mouse, {
6970
widgetEventPrefix: "resize",
6974
animateDuration: "slow",
6975
animateEasing: "swing",
6996
_num: function( value ) {
6997
return parseInt( value, 10 ) || 0;
7000
_isNumber: function( value ) {
7001
return !isNaN( parseInt( value, 10 ) );
7004
_hasScroll: function( el, a ) {
7006
if ( $( el ).css( "overflow" ) === "hidden") {
7010
var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
7013
if ( el[ scroll ] > 0 ) {
7017
// TODO: determine which cases actually cause this to happen
7018
// if the element doesn't have the scroll set, see if it's possible to
7021
has = ( el[ scroll ] > 0 );
7026
_create: function() {
7028
var n, i, handle, axis, hname,
7031
this.element.addClass("ui-resizable");
7034
_aspectRatio: !!(o.aspectRatio),
7035
aspectRatio: o.aspectRatio,
7036
originalElement: this.element,
7037
_proportionallyResizeElements: [],
7038
_helper: o.helper || o.ghost || o.animate ? o.helper || "ui-resizable-helper" : null
7041
// Wrap the element if it cannot hold child nodes
7042
if (this.element[0].nodeName.match(/^(canvas|textarea|input|select|button|img)$/i)) {
7045
$("<div class='ui-wrapper' style='overflow: hidden;'></div>").css({
7046
position: this.element.css("position"),
7047
width: this.element.outerWidth(),
7048
height: this.element.outerHeight(),
7049
top: this.element.css("top"),
7050
left: this.element.css("left")
7054
this.element = this.element.parent().data(
7055
"ui-resizable", this.element.resizable( "instance" )
7058
this.elementIsWrapper = true;
7061
marginLeft: this.originalElement.css("marginLeft"),
7062
marginTop: this.originalElement.css("marginTop"),
7063
marginRight: this.originalElement.css("marginRight"),
7064
marginBottom: this.originalElement.css("marginBottom")
7066
this.originalElement.css({
7073
// Prevent Safari textarea resize
7074
this.originalResizeStyle = this.originalElement.css("resize");
7075
this.originalElement.css("resize", "none");
7077
this._proportionallyResizeElements.push( this.originalElement.css({
7084
// avoid IE jump (hard set the margin)
7085
this.originalElement.css({ margin: this.originalElement.css("margin") });
7087
this._proportionallyResize();
7090
this.handles = o.handles ||
7091
( !$(".ui-resizable-handle", this.element).length ?
7093
n: ".ui-resizable-n",
7094
e: ".ui-resizable-e",
7095
s: ".ui-resizable-s",
7096
w: ".ui-resizable-w",
7097
se: ".ui-resizable-se",
7098
sw: ".ui-resizable-sw",
7099
ne: ".ui-resizable-ne",
7100
nw: ".ui-resizable-nw"
7103
this._handles = $();
7104
if ( this.handles.constructor === String ) {
7106
if ( this.handles === "all") {
7107
this.handles = "n,e,s,w,se,sw,ne,nw";
7110
n = this.handles.split(",");
7113
for (i = 0; i < n.length; i++) {
7115
handle = $.trim(n[i]);
7116
hname = "ui-resizable-" + handle;
7117
axis = $("<div class='ui-resizable-handle " + hname + "'></div>");
7119
axis.css({ zIndex: o.zIndex });
7121
// TODO : What's going on here?
7122
if ("se" === handle) {
7123
axis.addClass("ui-icon ui-icon-gripsmall-diagonal-se");
7126
this.handles[handle] = ".ui-resizable-" + handle;
7127
this.element.append(axis);
7132
this._renderAxis = function(target) {
7134
var i, axis, padPos, padWrapper;
7136
target = target || this.element;
7138
for (i in this.handles) {
7140
if (this.handles[i].constructor === String) {
7141
this.handles[i] = this.element.children( this.handles[ i ] ).first().show();
7142
} else if ( this.handles[ i ].jquery || this.handles[ i ].nodeType ) {
7143
this.handles[ i ] = $( this.handles[ i ] );
7144
this._on( this.handles[ i ], { "mousedown": that._mouseDown });
7147
if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/^(textarea|input|select|button)$/i)) {
7149
axis = $(this.handles[i], this.element);
7151
padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth();
7153
padPos = [ "padding",
7154
/ne|nw|n/.test(i) ? "Top" :
7155
/se|sw|s/.test(i) ? "Bottom" :
7156
/^e$/.test(i) ? "Right" : "Left" ].join("");
7158
target.css(padPos, padWrapper);
7160
this._proportionallyResize();
7163
this._handles = this._handles.add( this.handles[ i ] );
7167
// TODO: make renderAxis a prototype function
7168
this._renderAxis(this.element);
7170
this._handles = this._handles.add( this.element.find( ".ui-resizable-handle" ) );
7171
this._handles.disableSelection();
7173
this._handles.mouseover(function() {
7174
if (!that.resizing) {
7175
if (this.className) {
7176
axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);
7178
that.axis = axis && axis[1] ? axis[1] : "se";
7183
this._handles.hide();
7185
.addClass("ui-resizable-autohide")
7186
.mouseenter(function() {
7190
$(this).removeClass("ui-resizable-autohide");
7191
that._handles.show();
7193
.mouseleave(function() {
7197
if (!that.resizing) {
7198
$(this).addClass("ui-resizable-autohide");
7199
that._handles.hide();
7207
_destroy: function() {
7209
this._mouseDestroy();
7212
_destroy = function(exp) {
7214
.removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing")
7215
.removeData("resizable")
7216
.removeData("ui-resizable")
7217
.unbind(".resizable")
7218
.find(".ui-resizable-handle")
7222
// TODO: Unwrap at same DOM position
7223
if (this.elementIsWrapper) {
7224
_destroy(this.element);
7225
wrapper = this.element;
7226
this.originalElement.css({
7227
position: wrapper.css("position"),
7228
width: wrapper.outerWidth(),
7229
height: wrapper.outerHeight(),
7230
top: wrapper.css("top"),
7231
left: wrapper.css("left")
7232
}).insertAfter( wrapper );
7236
this.originalElement.css("resize", this.originalResizeStyle);
7237
_destroy(this.originalElement);
7242
_mouseCapture: function(event) {
7246
for (i in this.handles) {
7247
handle = $(this.handles[i])[0];
7248
if (handle === event.target || $.contains(handle, event.target)) {
7253
return !this.options.disabled && capture;
7256
_mouseStart: function(event) {
7258
var curleft, curtop, cursor,
7262
this.resizing = true;
7264
this._renderProxy();
7266
curleft = this._num(this.helper.css("left"));
7267
curtop = this._num(this.helper.css("top"));
7269
if (o.containment) {
7270
curleft += $(o.containment).scrollLeft() || 0;
7271
curtop += $(o.containment).scrollTop() || 0;
7274
this.offset = this.helper.offset();
7275
this.position = { left: curleft, top: curtop };
7277
this.size = this._helper ? {
7278
width: this.helper.width(),
7279
height: this.helper.height()
7285
this.originalSize = this._helper ? {
7286
width: el.outerWidth(),
7287
height: el.outerHeight()
7294
width: el.outerWidth() - el.width(),
7295
height: el.outerHeight() - el.height()
7298
this.originalPosition = { left: curleft, top: curtop };
7299
this.originalMousePosition = { left: event.pageX, top: event.pageY };
7301
this.aspectRatio = (typeof o.aspectRatio === "number") ?
7303
((this.originalSize.width / this.originalSize.height) || 1);
7305
cursor = $(".ui-resizable-" + this.axis).css("cursor");
7306
$("body").css("cursor", cursor === "auto" ? this.axis + "-resize" : cursor);
7308
el.addClass("ui-resizable-resizing");
7309
this._propagate("start", event);
7313
_mouseDrag: function(event) {
7316
smp = this.originalMousePosition,
7318
dx = (event.pageX - smp.left) || 0,
7319
dy = (event.pageY - smp.top) || 0,
7320
trigger = this._change[a];
7322
this._updatePrevProperties();
7328
data = trigger.apply(this, [ event, dx, dy ]);
7330
this._updateVirtualBoundaries(event.shiftKey);
7331
if (this._aspectRatio || event.shiftKey) {
7332
data = this._updateRatio(data, event);
7335
data = this._respectSize(data, event);
7337
this._updateCache(data);
7339
this._propagate("resize", event);
7341
props = this._applyChanges();
7343
if ( !this._helper && this._proportionallyResizeElements.length ) {
7344
this._proportionallyResize();
7347
if ( !$.isEmptyObject( props ) ) {
7348
this._updatePrevProperties();
7349
this._trigger( "resize", event, this.ui() );
7350
this._applyChanges();
7356
_mouseStop: function(event) {
7358
this.resizing = false;
7359
var pr, ista, soffseth, soffsetw, s, left, top,
7360
o = this.options, that = this;
7364
pr = this._proportionallyResizeElements;
7365
ista = pr.length && (/textarea/i).test(pr[0].nodeName);
7366
soffseth = ista && this._hasScroll(pr[0], "left") ? 0 : that.sizeDiff.height;
7367
soffsetw = ista ? 0 : that.sizeDiff.width;
7370
width: (that.helper.width() - soffsetw),
7371
height: (that.helper.height() - soffseth)
7373
left = (parseInt(that.element.css("left"), 10) +
7374
(that.position.left - that.originalPosition.left)) || null;
7375
top = (parseInt(that.element.css("top"), 10) +
7376
(that.position.top - that.originalPosition.top)) || null;
7379
this.element.css($.extend(s, { top: top, left: left }));
7382
that.helper.height(that.size.height);
7383
that.helper.width(that.size.width);
7385
if (this._helper && !o.animate) {
7386
this._proportionallyResize();
7390
$("body").css("cursor", "auto");
7392
this.element.removeClass("ui-resizable-resizing");
7394
this._propagate("stop", event);
7397
this.helper.remove();
7404
_updatePrevProperties: function() {
7405
this.prevPosition = {
7406
top: this.position.top,
7407
left: this.position.left
7410
width: this.size.width,
7411
height: this.size.height
7415
_applyChanges: function() {
7418
if ( this.position.top !== this.prevPosition.top ) {
7419
props.top = this.position.top + "px";
7421
if ( this.position.left !== this.prevPosition.left ) {
7422
props.left = this.position.left + "px";
7424
if ( this.size.width !== this.prevSize.width ) {
7425
props.width = this.size.width + "px";
7427
if ( this.size.height !== this.prevSize.height ) {
7428
props.height = this.size.height + "px";
7431
this.helper.css( props );
7436
_updateVirtualBoundaries: function(forceAspectRatio) {
7437
var pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b,
7441
minWidth: this._isNumber(o.minWidth) ? o.minWidth : 0,
7442
maxWidth: this._isNumber(o.maxWidth) ? o.maxWidth : Infinity,
7443
minHeight: this._isNumber(o.minHeight) ? o.minHeight : 0,
7444
maxHeight: this._isNumber(o.maxHeight) ? o.maxHeight : Infinity
7447
if (this._aspectRatio || forceAspectRatio) {
7448
pMinWidth = b.minHeight * this.aspectRatio;
7449
pMinHeight = b.minWidth / this.aspectRatio;
7450
pMaxWidth = b.maxHeight * this.aspectRatio;
7451
pMaxHeight = b.maxWidth / this.aspectRatio;
7453
if (pMinWidth > b.minWidth) {
7454
b.minWidth = pMinWidth;
7456
if (pMinHeight > b.minHeight) {
7457
b.minHeight = pMinHeight;
7459
if (pMaxWidth < b.maxWidth) {
7460
b.maxWidth = pMaxWidth;
7462
if (pMaxHeight < b.maxHeight) {
7463
b.maxHeight = pMaxHeight;
7466
this._vBoundaries = b;
7469
_updateCache: function(data) {
7470
this.offset = this.helper.offset();
7471
if (this._isNumber(data.left)) {
7472
this.position.left = data.left;
7474
if (this._isNumber(data.top)) {
7475
this.position.top = data.top;
7477
if (this._isNumber(data.height)) {
7478
this.size.height = data.height;
7480
if (this._isNumber(data.width)) {
7481
this.size.width = data.width;
7485
_updateRatio: function( data ) {
7487
var cpos = this.position,
7491
if (this._isNumber(data.height)) {
7492
data.width = (data.height * this.aspectRatio);
7493
} else if (this._isNumber(data.width)) {
7494
data.height = (data.width / this.aspectRatio);
7498
data.left = cpos.left + (csize.width - data.width);
7502
data.top = cpos.top + (csize.height - data.height);
7503
data.left = cpos.left + (csize.width - data.width);
7509
_respectSize: function( data ) {
7511
var o = this._vBoundaries,
7513
ismaxw = this._isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width),
7514
ismaxh = this._isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height),
7515
isminw = this._isNumber(data.width) && o.minWidth && (o.minWidth > data.width),
7516
isminh = this._isNumber(data.height) && o.minHeight && (o.minHeight > data.height),
7517
dw = this.originalPosition.left + this.originalSize.width,
7518
dh = this.position.top + this.size.height,
7519
cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a);
7521
data.width = o.minWidth;
7524
data.height = o.minHeight;
7527
data.width = o.maxWidth;
7530
data.height = o.maxHeight;
7534
data.left = dw - o.minWidth;
7537
data.left = dw - o.maxWidth;
7540
data.top = dh - o.minHeight;
7543
data.top = dh - o.maxHeight;
7546
// Fixing jump error on top/left - bug #2330
7547
if (!data.width && !data.height && !data.left && data.top) {
7549
} else if (!data.width && !data.height && !data.top && data.left) {
7556
_getPaddingPlusBorderDimensions: function( element ) {
7560
element.css( "borderTopWidth" ),
7561
element.css( "borderRightWidth" ),
7562
element.css( "borderBottomWidth" ),
7563
element.css( "borderLeftWidth" )
7566
element.css( "paddingTop" ),
7567
element.css( "paddingRight" ),
7568
element.css( "paddingBottom" ),
7569
element.css( "paddingLeft" )
7572
for ( ; i < 4; i++ ) {
7573
widths[ i ] = ( parseInt( borders[ i ], 10 ) || 0 );
7574
widths[ i ] += ( parseInt( paddings[ i ], 10 ) || 0 );
7578
height: widths[ 0 ] + widths[ 2 ],
7579
width: widths[ 1 ] + widths[ 3 ]
7583
_proportionallyResize: function() {
7585
if (!this._proportionallyResizeElements.length) {
7591
element = this.helper || this.element;
7593
for ( ; i < this._proportionallyResizeElements.length; i++) {
7595
prel = this._proportionallyResizeElements[i];
7597
// TODO: Seems like a bug to cache this.outerDimensions
7598
// considering that we are in a loop.
7599
if (!this.outerDimensions) {
7600
this.outerDimensions = this._getPaddingPlusBorderDimensions( prel );
7604
height: (element.height() - this.outerDimensions.height) || 0,
7605
width: (element.width() - this.outerDimensions.width) || 0
7612
_renderProxy: function() {
7614
var el = this.element, o = this.options;
7615
this.elementOffset = el.offset();
7619
this.helper = this.helper || $("<div style='overflow:hidden;'></div>");
7621
this.helper.addClass(this._helper).css({
7622
width: this.element.outerWidth() - 1,
7623
height: this.element.outerHeight() - 1,
7624
position: "absolute",
7625
left: this.elementOffset.left + "px",
7626
top: this.elementOffset.top + "px",
7627
zIndex: ++o.zIndex //TODO: Don't modify option
7632
.disableSelection();
7635
this.helper = this.element;
7641
e: function(event, dx) {
7642
return { width: this.originalSize.width + dx };
7644
w: function(event, dx) {
7645
var cs = this.originalSize, sp = this.originalPosition;
7646
return { left: sp.left + dx, width: cs.width - dx };
7648
n: function(event, dx, dy) {
7649
var cs = this.originalSize, sp = this.originalPosition;
7650
return { top: sp.top + dy, height: cs.height - dy };
7652
s: function(event, dx, dy) {
7653
return { height: this.originalSize.height + dy };
7655
se: function(event, dx, dy) {
7656
return $.extend(this._change.s.apply(this, arguments),
7657
this._change.e.apply(this, [ event, dx, dy ]));
7659
sw: function(event, dx, dy) {
7660
return $.extend(this._change.s.apply(this, arguments),
7661
this._change.w.apply(this, [ event, dx, dy ]));
7663
ne: function(event, dx, dy) {
7664
return $.extend(this._change.n.apply(this, arguments),
7665
this._change.e.apply(this, [ event, dx, dy ]));
7667
nw: function(event, dx, dy) {
7668
return $.extend(this._change.n.apply(this, arguments),
7669
this._change.w.apply(this, [ event, dx, dy ]));
7673
_propagate: function(n, event) {
7674
$.ui.plugin.call(this, n, [ event, this.ui() ]);
7675
(n !== "resize" && this._trigger(n, event, this.ui()));
7682
originalElement: this.originalElement,
7683
element: this.element,
7684
helper: this.helper,
7685
position: this.position,
7687
originalSize: this.originalSize,
7688
originalPosition: this.originalPosition
7695
* Resizable Extensions
7698
$.ui.plugin.add("resizable", "animate", {
7700
stop: function( event ) {
7701
var that = $(this).resizable( "instance" ),
7703
pr = that._proportionallyResizeElements,
7704
ista = pr.length && (/textarea/i).test(pr[0].nodeName),
7705
soffseth = ista && that._hasScroll(pr[0], "left") ? 0 : that.sizeDiff.height,
7706
soffsetw = ista ? 0 : that.sizeDiff.width,
7707
style = { width: (that.size.width - soffsetw), height: (that.size.height - soffseth) },
7708
left = (parseInt(that.element.css("left"), 10) +
7709
(that.position.left - that.originalPosition.left)) || null,
7710
top = (parseInt(that.element.css("top"), 10) +
7711
(that.position.top - that.originalPosition.top)) || null;
7713
that.element.animate(
7714
$.extend(style, top && left ? { top: top, left: left } : {}), {
7715
duration: o.animateDuration,
7716
easing: o.animateEasing,
7720
width: parseInt(that.element.css("width"), 10),
7721
height: parseInt(that.element.css("height"), 10),
7722
top: parseInt(that.element.css("top"), 10),
7723
left: parseInt(that.element.css("left"), 10)
7726
if (pr && pr.length) {
7727
$(pr[0]).css({ width: data.width, height: data.height });
7730
// propagating resize, and updating values for each animation step
7731
that._updateCache(data);
7732
that._propagate("resize", event);
7741
$.ui.plugin.add( "resizable", "containment", {
7744
var element, p, co, ch, cw, width, height,
7745
that = $( this ).resizable( "instance" ),
7749
ce = ( oc instanceof $ ) ? oc.get( 0 ) : ( /parent/.test( oc ) ) ? el.parent().get( 0 ) : oc;
7755
that.containerElement = $( ce );
7757
if ( /document/.test( oc ) || oc === document ) {
7758
that.containerOffset = {
7762
that.containerPosition = {
7768
element: $( document ),
7771
width: $( document ).width(),
7772
height: $( document ).height() || document.body.parentNode.scrollHeight
7777
$([ "Top", "Right", "Left", "Bottom" ]).each(function( i, name ) {
7778
p[ i ] = that._num( element.css( "padding" + name ) );
7781
that.containerOffset = element.offset();
7782
that.containerPosition = element.position();
7783
that.containerSize = {
7784
height: ( element.innerHeight() - p[ 3 ] ),
7785
width: ( element.innerWidth() - p[ 1 ] )
7788
co = that.containerOffset;
7789
ch = that.containerSize.height;
7790
cw = that.containerSize.width;
7791
width = ( that._hasScroll ( ce, "left" ) ? ce.scrollWidth : cw );
7792
height = ( that._hasScroll ( ce ) ? ce.scrollHeight : ch ) ;
7804
resize: function( event ) {
7805
var woset, hoset, isParent, isOffsetRelative,
7806
that = $( this ).resizable( "instance" ),
7808
co = that.containerOffset,
7810
pRatio = that._aspectRatio || event.shiftKey,
7815
ce = that.containerElement,
7816
continueResize = true;
7818
if ( ce[ 0 ] !== document && ( /static/ ).test( ce.css( "position" ) ) ) {
7822
if ( cp.left < ( that._helper ? co.left : 0 ) ) {
7823
that.size.width = that.size.width +
7825
( that.position.left - co.left ) :
7826
( that.position.left - cop.left ) );
7829
that.size.height = that.size.width / that.aspectRatio;
7830
continueResize = false;
7832
that.position.left = o.helper ? co.left : 0;
7835
if ( cp.top < ( that._helper ? co.top : 0 ) ) {
7836
that.size.height = that.size.height +
7838
( that.position.top - co.top ) :
7839
that.position.top );
7842
that.size.width = that.size.height * that.aspectRatio;
7843
continueResize = false;
7845
that.position.top = that._helper ? co.top : 0;
7848
isParent = that.containerElement.get( 0 ) === that.element.parent().get( 0 );
7849
isOffsetRelative = /relative|absolute/.test( that.containerElement.css( "position" ) );
7851
if ( isParent && isOffsetRelative ) {
7852
that.offset.left = that.parentData.left + that.position.left;
7853
that.offset.top = that.parentData.top + that.position.top;
7855
that.offset.left = that.element.offset().left;
7856
that.offset.top = that.element.offset().top;
7859
woset = Math.abs( that.sizeDiff.width +
7861
that.offset.left - cop.left :
7862
(that.offset.left - co.left)) );
7864
hoset = Math.abs( that.sizeDiff.height +
7866
that.offset.top - cop.top :
7867
(that.offset.top - co.top)) );
7869
if ( woset + that.size.width >= that.parentData.width ) {
7870
that.size.width = that.parentData.width - woset;
7872
that.size.height = that.size.width / that.aspectRatio;
7873
continueResize = false;
7877
if ( hoset + that.size.height >= that.parentData.height ) {
7878
that.size.height = that.parentData.height - hoset;
7880
that.size.width = that.size.height * that.aspectRatio;
7881
continueResize = false;
7885
if ( !continueResize ) {
7886
that.position.left = that.prevPosition.left;
7887
that.position.top = that.prevPosition.top;
7888
that.size.width = that.prevSize.width;
7889
that.size.height = that.prevSize.height;
7894
var that = $( this ).resizable( "instance" ),
7896
co = that.containerOffset,
7897
cop = that.containerPosition,
7898
ce = that.containerElement,
7899
helper = $( that.helper ),
7900
ho = helper.offset(),
7901
w = helper.outerWidth() - that.sizeDiff.width,
7902
h = helper.outerHeight() - that.sizeDiff.height;
7904
if ( that._helper && !o.animate && ( /relative/ ).test( ce.css( "position" ) ) ) {
7906
left: ho.left - cop.left - co.left,
7912
if ( that._helper && !o.animate && ( /static/ ).test( ce.css( "position" ) ) ) {
7914
left: ho.left - cop.left - co.left,
7922
$.ui.plugin.add("resizable", "alsoResize", {
7925
var that = $(this).resizable( "instance" ),
7928
$(o.alsoResize).each(function() {
7930
el.data("ui-resizable-alsoresize", {
7931
width: parseInt(el.width(), 10), height: parseInt(el.height(), 10),
7932
left: parseInt(el.css("left"), 10), top: parseInt(el.css("top"), 10)
7937
resize: function(event, ui) {
7938
var that = $(this).resizable( "instance" ),
7940
os = that.originalSize,
7941
op = that.originalPosition,
7943
height: (that.size.height - os.height) || 0,
7944
width: (that.size.width - os.width) || 0,
7945
top: (that.position.top - op.top) || 0,
7946
left: (that.position.left - op.left) || 0
7949
$(o.alsoResize).each(function() {
7950
var el = $(this), start = $(this).data("ui-resizable-alsoresize"), style = {},
7951
css = el.parents(ui.originalElement[0]).length ?
7952
[ "width", "height" ] :
7953
[ "width", "height", "top", "left" ];
7955
$.each(css, function(i, prop) {
7956
var sum = (start[prop] || 0) + (delta[prop] || 0);
7957
if (sum && sum >= 0) {
7958
style[prop] = sum || null;
7967
$(this).removeData("resizable-alsoresize");
7971
$.ui.plugin.add("resizable", "ghost", {
7975
var that = $(this).resizable( "instance" ), o = that.options, cs = that.size;
7977
that.ghost = that.originalElement.clone();
7982
position: "relative",
7989
.addClass("ui-resizable-ghost")
7990
.addClass(typeof o.ghost === "string" ? o.ghost : "");
7992
that.ghost.appendTo(that.helper);
7996
resize: function() {
7997
var that = $(this).resizable( "instance" );
8000
position: "relative",
8001
height: that.size.height,
8002
width: that.size.width
8008
var that = $(this).resizable( "instance" );
8009
if (that.ghost && that.helper) {
8010
that.helper.get(0).removeChild(that.ghost.get(0));
8016
$.ui.plugin.add("resizable", "grid", {
8018
resize: function() {
8019
var outerDimensions,
8020
that = $(this).resizable( "instance" ),
8023
os = that.originalSize,
8024
op = that.originalPosition,
8026
grid = typeof o.grid === "number" ? [ o.grid, o.grid ] : o.grid,
8027
gridX = (grid[0] || 1),
8028
gridY = (grid[1] || 1),
8029
ox = Math.round((cs.width - os.width) / gridX) * gridX,
8030
oy = Math.round((cs.height - os.height) / gridY) * gridY,
8031
newWidth = os.width + ox,
8032
newHeight = os.height + oy,
8033
isMaxWidth = o.maxWidth && (o.maxWidth < newWidth),
8034
isMaxHeight = o.maxHeight && (o.maxHeight < newHeight),
8035
isMinWidth = o.minWidth && (o.minWidth > newWidth),
8036
isMinHeight = o.minHeight && (o.minHeight > newHeight);
8053
if (/^(se|s|e)$/.test(a)) {
8054
that.size.width = newWidth;
8055
that.size.height = newHeight;
8056
} else if (/^(ne)$/.test(a)) {
8057
that.size.width = newWidth;
8058
that.size.height = newHeight;
8059
that.position.top = op.top - oy;
8060
} else if (/^(sw)$/.test(a)) {
8061
that.size.width = newWidth;
8062
that.size.height = newHeight;
8063
that.position.left = op.left - ox;
8065
if ( newHeight - gridY <= 0 || newWidth - gridX <= 0) {
8066
outerDimensions = that._getPaddingPlusBorderDimensions( this );
8069
if ( newHeight - gridY > 0 ) {
8070
that.size.height = newHeight;
8071
that.position.top = op.top - oy;
8073
newHeight = gridY - outerDimensions.height;
8074
that.size.height = newHeight;
8075
that.position.top = op.top + os.height - newHeight;
8077
if ( newWidth - gridX > 0 ) {
8078
that.size.width = newWidth;
8079
that.position.left = op.left - ox;
8081
newWidth = gridX - outerDimensions.width;
8082
that.size.width = newWidth;
8083
that.position.left = op.left + os.width - newWidth;
8090
var resizable = $.ui.resizable;
8094
* jQuery UI Dialog 1.11.4
8095
* http://jqueryui.com
8097
* Copyright jQuery Foundation and other contributors
8098
* Released under the MIT license.
8099
* http://jquery.org/license
8101
* http://api.jqueryui.com/dialog/
8105
var dialog = $.widget( "ui.dialog", {
8111
closeOnEscape: true,
8127
// Ensure the titlebar is always visible
8128
using: function( pos ) {
8129
var topOffset = $( this ).css( pos ).offset().top;
8130
if ( topOffset < 0 ) {
8131
$( this ).css( "top", pos.top - topOffset );
8153
sizeRelatedOptions: {
8163
resizableRelatedOptions: {
8170
_create: function() {
8171
this.originalCss = {
8172
display: this.element[ 0 ].style.display,
8173
width: this.element[ 0 ].style.width,
8174
minHeight: this.element[ 0 ].style.minHeight,
8175
maxHeight: this.element[ 0 ].style.maxHeight,
8176
height: this.element[ 0 ].style.height
8178
this.originalPosition = {
8179
parent: this.element.parent(),
8180
index: this.element.parent().children().index( this.element )
8182
this.originalTitle = this.element.attr( "title" );
8183
this.options.title = this.options.title || this.originalTitle;
8185
this._createWrapper();
8189
.removeAttr( "title" )
8190
.addClass( "ui-dialog-content ui-widget-content" )
8191
.appendTo( this.uiDialog );
8193
this._createTitlebar();
8194
this._createButtonPane();
8196
if ( this.options.draggable && $.fn.draggable ) {
8197
this._makeDraggable();
8199
if ( this.options.resizable && $.fn.resizable ) {
8200
this._makeResizable();
8203
this._isOpen = false;
8209
if ( this.options.autoOpen ) {
8214
_appendTo: function() {
8215
var element = this.options.appendTo;
8216
if ( element && (element.jquery || element.nodeType) ) {
8217
return $( element );
8219
return this.document.find( element || "body" ).eq( 0 );
8222
_destroy: function() {
8224
originalPosition = this.originalPosition;
8226
this._untrackInstance();
8227
this._destroyOverlay();
8231
.removeClass( "ui-dialog-content ui-widget-content" )
8232
.css( this.originalCss )
8233
// Without detaching first, the following becomes really slow
8236
this.uiDialog.stop( true, true ).remove();
8238
if ( this.originalTitle ) {
8239
this.element.attr( "title", this.originalTitle );
8242
next = originalPosition.parent.children().eq( originalPosition.index );
8243
// Don't try to place the dialog next to itself (#8613)
8244
if ( next.length && next[ 0 ] !== this.element[ 0 ] ) {
8245
next.before( this.element );
8247
originalPosition.parent.append( this.element );
8251
widget: function() {
8252
return this.uiDialog;
8258
close: function( event ) {
8262
if ( !this._isOpen || this._trigger( "beforeClose", event ) === false ) {
8266
this._isOpen = false;
8267
this._focusedElement = null;
8268
this._destroyOverlay();
8269
this._untrackInstance();
8271
if ( !this.opener.filter( ":focusable" ).focus().length ) {
8274
// IE9 throws an "Unspecified error" accessing document.activeElement from an <iframe>
8276
activeElement = this.document[ 0 ].activeElement;
8278
// Support: IE9, IE10
8279
// If the <body> is blurred, IE will switch windows, see #4520
8280
if ( activeElement && activeElement.nodeName.toLowerCase() !== "body" ) {
8282
// Hiding a focused element doesn't trigger blur in WebKit
8283
// so in case we have nothing to focus on, explicitly blur the active element
8284
// https://bugs.webkit.org/show_bug.cgi?id=47182
8285
$( activeElement ).blur();
8287
} catch ( error ) {}
8290
this._hide( this.uiDialog, this.options.hide, function() {
8291
that._trigger( "close", event );
8295
isOpen: function() {
8296
return this._isOpen;
8299
moveToTop: function() {
8303
_moveToTop: function( event, silent ) {
8305
zIndices = this.uiDialog.siblings( ".ui-front:visible" ).map(function() {
8306
return +$( this ).css( "z-index" );
8308
zIndexMax = Math.max.apply( null, zIndices );
8310
if ( zIndexMax >= +this.uiDialog.css( "z-index" ) ) {
8311
this.uiDialog.css( "z-index", zIndexMax + 1 );
8315
if ( moved && !silent ) {
8316
this._trigger( "focus", event );
8323
if ( this._isOpen ) {
8324
if ( this._moveToTop() ) {
8325
this._focusTabbable();
8330
this._isOpen = true;
8331
this.opener = $( this.document[ 0 ].activeElement );
8335
this._createOverlay();
8336
this._moveToTop( null, true );
8338
// Ensure the overlay is moved to the top with the dialog, but only when
8339
// opening. The overlay shouldn't move after the dialog is open so that
8340
// modeless dialogs opened after the modal dialog stack properly.
8341
if ( this.overlay ) {
8342
this.overlay.css( "z-index", this.uiDialog.css( "z-index" ) - 1 );
8345
this._show( this.uiDialog, this.options.show, function() {
8346
that._focusTabbable();
8347
that._trigger( "focus" );
8350
// Track the dialog immediately upon openening in case a focus event
8351
// somehow occurs outside of the dialog before an element inside the
8352
// dialog is focused (#10152)
8353
this._makeFocusTarget();
8355
this._trigger( "open" );
8358
_focusTabbable: function() {
8359
// Set focus to the first match:
8360
// 1. An element that was focused previously
8361
// 2. First element inside the dialog matching [autofocus]
8362
// 3. Tabbable element inside the content element
8363
// 4. Tabbable element inside the buttonpane
8364
// 5. The close button
8365
// 6. The dialog itself
8366
var hasFocus = this._focusedElement;
8368
hasFocus = this.element.find( "[autofocus]" );
8370
if ( !hasFocus.length ) {
8371
hasFocus = this.element.find( ":tabbable" );
8373
if ( !hasFocus.length ) {
8374
hasFocus = this.uiDialogButtonPane.find( ":tabbable" );
8376
if ( !hasFocus.length ) {
8377
hasFocus = this.uiDialogTitlebarClose.filter( ":tabbable" );
8379
if ( !hasFocus.length ) {
8380
hasFocus = this.uiDialog;
8382
hasFocus.eq( 0 ).focus();
8385
_keepFocus: function( event ) {
8386
function checkFocus() {
8387
var activeElement = this.document[0].activeElement,
8388
isActive = this.uiDialog[0] === activeElement ||
8389
$.contains( this.uiDialog[0], activeElement );
8391
this._focusTabbable();
8394
event.preventDefault();
8395
checkFocus.call( this );
8397
// IE <= 8 doesn't prevent moving focus even with event.preventDefault()
8398
// so we check again later
8399
this._delay( checkFocus );
8402
_createWrapper: function() {
8403
this.uiDialog = $("<div>")
8404
.addClass( "ui-dialog ui-widget ui-widget-content ui-corner-all ui-front " +
8405
this.options.dialogClass )
8408
// Setting tabIndex makes the div focusable
8412
.appendTo( this._appendTo() );
8414
this._on( this.uiDialog, {
8415
keydown: function( event ) {
8416
if ( this.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode &&
8417
event.keyCode === $.ui.keyCode.ESCAPE ) {
8418
event.preventDefault();
8419
this.close( event );
8423
// prevent tabbing out of dialogs
8424
if ( event.keyCode !== $.ui.keyCode.TAB || event.isDefaultPrevented() ) {
8427
var tabbables = this.uiDialog.find( ":tabbable" ),
8428
first = tabbables.filter( ":first" ),
8429
last = tabbables.filter( ":last" );
8431
if ( ( event.target === last[0] || event.target === this.uiDialog[0] ) && !event.shiftKey ) {
8432
this._delay(function() {
8435
event.preventDefault();
8436
} else if ( ( event.target === first[0] || event.target === this.uiDialog[0] ) && event.shiftKey ) {
8437
this._delay(function() {
8440
event.preventDefault();
8443
mousedown: function( event ) {
8444
if ( this._moveToTop( event ) ) {
8445
this._focusTabbable();
8450
// We assume that any existing aria-describedby attribute means
8451
// that the dialog content is marked up properly
8452
// otherwise we brute force the content as the description
8453
if ( !this.element.find( "[aria-describedby]" ).length ) {
8454
this.uiDialog.attr({
8455
"aria-describedby": this.element.uniqueId().attr( "id" )
8460
_createTitlebar: function() {
8463
this.uiDialogTitlebar = $( "<div>" )
8464
.addClass( "ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix" )
8465
.prependTo( this.uiDialog );
8466
this._on( this.uiDialogTitlebar, {
8467
mousedown: function( event ) {
8468
// Don't prevent click on close button (#8838)
8469
// Focusing a dialog that is partially scrolled out of view
8470
// causes the browser to scroll it into view, preventing the click event
8471
if ( !$( event.target ).closest( ".ui-dialog-titlebar-close" ) ) {
8472
// Dialog isn't getting focus when dragging (#8063)
8473
this.uiDialog.focus();
8479
// Use type="button" to prevent enter keypresses in textboxes from closing the
8480
// dialog in IE (#9312)
8481
this.uiDialogTitlebarClose = $( "<button type='button'></button>" )
8483
label: this.options.closeText,
8485
primary: "ui-icon-closethick"
8489
.addClass( "ui-dialog-titlebar-close" )
8490
.appendTo( this.uiDialogTitlebar );
8491
this._on( this.uiDialogTitlebarClose, {
8492
click: function( event ) {
8493
event.preventDefault();
8494
this.close( event );
8498
uiDialogTitle = $( "<span>" )
8500
.addClass( "ui-dialog-title" )
8501
.prependTo( this.uiDialogTitlebar );
8502
this._title( uiDialogTitle );
8504
this.uiDialog.attr({
8505
"aria-labelledby": uiDialogTitle.attr( "id" )
8509
_title: function( title ) {
8510
if ( !this.options.title ) {
8511
title.html( " " );
8513
title.text( this.options.title );
8516
_createButtonPane: function() {
8517
this.uiDialogButtonPane = $( "<div>" )
8518
.addClass( "ui-dialog-buttonpane ui-widget-content ui-helper-clearfix" );
8520
this.uiButtonSet = $( "<div>" )
8521
.addClass( "ui-dialog-buttonset" )
8522
.appendTo( this.uiDialogButtonPane );
8524
this._createButtons();
8527
_createButtons: function() {
8529
buttons = this.options.buttons;
8531
// if we already have a button pane, remove it
8532
this.uiDialogButtonPane.remove();
8533
this.uiButtonSet.empty();
8535
if ( $.isEmptyObject( buttons ) || ($.isArray( buttons ) && !buttons.length) ) {
8536
this.uiDialog.removeClass( "ui-dialog-buttons" );
8540
$.each( buttons, function( name, props ) {
8541
var click, buttonOptions;
8542
props = $.isFunction( props ) ?
8543
{ click: props, text: name } :
8545
// Default to a non-submitting button
8546
props = $.extend( { type: "button" }, props );
8547
// Change the context for the click callback to be the main element
8548
click = props.click;
8549
props.click = function() {
8550
click.apply( that.element[ 0 ], arguments );
8554
text: props.showText
8557
delete props.showText;
8558
$( "<button></button>", props )
8559
.button( buttonOptions )
8560
.appendTo( that.uiButtonSet );
8562
this.uiDialog.addClass( "ui-dialog-buttons" );
8563
this.uiDialogButtonPane.appendTo( this.uiDialog );
8566
_makeDraggable: function() {
8568
options = this.options;
8570
function filteredUi( ui ) {
8572
position: ui.position,
8577
this.uiDialog.draggable({
8578
cancel: ".ui-dialog-content, .ui-dialog-titlebar-close",
8579
handle: ".ui-dialog-titlebar",
8580
containment: "document",
8581
start: function( event, ui ) {
8582
$( this ).addClass( "ui-dialog-dragging" );
8583
that._blockFrames();
8584
that._trigger( "dragStart", event, filteredUi( ui ) );
8586
drag: function( event, ui ) {
8587
that._trigger( "drag", event, filteredUi( ui ) );
8589
stop: function( event, ui ) {
8590
var left = ui.offset.left - that.document.scrollLeft(),
8591
top = ui.offset.top - that.document.scrollTop();
8593
options.position = {
8595
at: "left" + (left >= 0 ? "+" : "") + left + " " +
8596
"top" + (top >= 0 ? "+" : "") + top,
8599
$( this ).removeClass( "ui-dialog-dragging" );
8600
that._unblockFrames();
8601
that._trigger( "dragStop", event, filteredUi( ui ) );
8606
_makeResizable: function() {
8608
options = this.options,
8609
handles = options.resizable,
8610
// .ui-resizable has position: relative defined in the stylesheet
8611
// but dialogs have to use absolute or fixed positioning
8612
position = this.uiDialog.css("position"),
8613
resizeHandles = typeof handles === "string" ?
8615
"n,e,s,w,se,sw,ne,nw";
8617
function filteredUi( ui ) {
8619
originalPosition: ui.originalPosition,
8620
originalSize: ui.originalSize,
8621
position: ui.position,
8626
this.uiDialog.resizable({
8627
cancel: ".ui-dialog-content",
8628
containment: "document",
8629
alsoResize: this.element,
8630
maxWidth: options.maxWidth,
8631
maxHeight: options.maxHeight,
8632
minWidth: options.minWidth,
8633
minHeight: this._minHeight(),
8634
handles: resizeHandles,
8635
start: function( event, ui ) {
8636
$( this ).addClass( "ui-dialog-resizing" );
8637
that._blockFrames();
8638
that._trigger( "resizeStart", event, filteredUi( ui ) );
8640
resize: function( event, ui ) {
8641
that._trigger( "resize", event, filteredUi( ui ) );
8643
stop: function( event, ui ) {
8644
var offset = that.uiDialog.offset(),
8645
left = offset.left - that.document.scrollLeft(),
8646
top = offset.top - that.document.scrollTop();
8648
options.height = that.uiDialog.height();
8649
options.width = that.uiDialog.width();
8650
options.position = {
8652
at: "left" + (left >= 0 ? "+" : "") + left + " " +
8653
"top" + (top >= 0 ? "+" : "") + top,
8656
$( this ).removeClass( "ui-dialog-resizing" );
8657
that._unblockFrames();
8658
that._trigger( "resizeStop", event, filteredUi( ui ) );
8661
.css( "position", position );
8664
_trackFocus: function() {
8665
this._on( this.widget(), {
8666
focusin: function( event ) {
8667
this._makeFocusTarget();
8668
this._focusedElement = $( event.target );
8673
_makeFocusTarget: function() {
8674
this._untrackInstance();
8675
this._trackingInstances().unshift( this );
8678
_untrackInstance: function() {
8679
var instances = this._trackingInstances(),
8680
exists = $.inArray( this, instances );
8681
if ( exists !== -1 ) {
8682
instances.splice( exists, 1 );
8686
_trackingInstances: function() {
8687
var instances = this.document.data( "ui-dialog-instances" );
8690
this.document.data( "ui-dialog-instances", instances );
8695
_minHeight: function() {
8696
var options = this.options;
8698
return options.height === "auto" ?
8700
Math.min( options.minHeight, options.height );
8703
_position: function() {
8704
// Need to show the dialog to get the actual offset in the position plugin
8705
var isVisible = this.uiDialog.is( ":visible" );
8707
this.uiDialog.show();
8709
this.uiDialog.position( this.options.position );
8711
this.uiDialog.hide();
8715
_setOptions: function( options ) {
8718
resizableOptions = {};
8720
$.each( options, function( key, value ) {
8721
that._setOption( key, value );
8723
if ( key in that.sizeRelatedOptions ) {
8726
if ( key in that.resizableRelatedOptions ) {
8727
resizableOptions[ key ] = value;
8735
if ( this.uiDialog.is( ":data(ui-resizable)" ) ) {
8736
this.uiDialog.resizable( "option", resizableOptions );
8740
_setOption: function( key, value ) {
8741
var isDraggable, isResizable,
8742
uiDialog = this.uiDialog;
8744
if ( key === "dialogClass" ) {
8746
.removeClass( this.options.dialogClass )
8750
if ( key === "disabled" ) {
8754
this._super( key, value );
8756
if ( key === "appendTo" ) {
8757
this.uiDialog.appendTo( this._appendTo() );
8760
if ( key === "buttons" ) {
8761
this._createButtons();
8764
if ( key === "closeText" ) {
8765
this.uiDialogTitlebarClose.button({
8766
// Ensure that we always pass a string
8771
if ( key === "draggable" ) {
8772
isDraggable = uiDialog.is( ":data(ui-draggable)" );
8773
if ( isDraggable && !value ) {
8774
uiDialog.draggable( "destroy" );
8777
if ( !isDraggable && value ) {
8778
this._makeDraggable();
8782
if ( key === "position" ) {
8786
if ( key === "resizable" ) {
8787
// currently resizable, becoming non-resizable
8788
isResizable = uiDialog.is( ":data(ui-resizable)" );
8789
if ( isResizable && !value ) {
8790
uiDialog.resizable( "destroy" );
8793
// currently resizable, changing handles
8794
if ( isResizable && typeof value === "string" ) {
8795
uiDialog.resizable( "option", "handles", value );
8798
// currently non-resizable, becoming resizable
8799
if ( !isResizable && value !== false ) {
8800
this._makeResizable();
8804
if ( key === "title" ) {
8805
this._title( this.uiDialogTitlebar.find( ".ui-dialog-title" ) );
8810
// If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
8811
// divs will both have width and height set, so we need to reset them
8812
var nonContentHeight, minContentHeight, maxContentHeight,
8813
options = this.options;
8815
// Reset content sizing
8816
this.element.show().css({
8823
if ( options.minWidth > options.width ) {
8824
options.width = options.minWidth;
8827
// reset wrapper sizing
8828
// determine the height of all the non-content elements
8829
nonContentHeight = this.uiDialog.css({
8831
width: options.width
8834
minContentHeight = Math.max( 0, options.minHeight - nonContentHeight );
8835
maxContentHeight = typeof options.maxHeight === "number" ?
8836
Math.max( 0, options.maxHeight - nonContentHeight ) :
8839
if ( options.height === "auto" ) {
8841
minHeight: minContentHeight,
8842
maxHeight: maxContentHeight,
8846
this.element.height( Math.max( 0, options.height - nonContentHeight ) );
8849
if ( this.uiDialog.is( ":data(ui-resizable)" ) ) {
8850
this.uiDialog.resizable( "option", "minHeight", this._minHeight() );
8854
_blockFrames: function() {
8855
this.iframeBlocks = this.document.find( "iframe" ).map(function() {
8856
var iframe = $( this );
8860
position: "absolute",
8861
width: iframe.outerWidth(),
8862
height: iframe.outerHeight()
8864
.appendTo( iframe.parent() )
8865
.offset( iframe.offset() )[0];
8869
_unblockFrames: function() {
8870
if ( this.iframeBlocks ) {
8871
this.iframeBlocks.remove();
8872
delete this.iframeBlocks;
8876
_allowInteraction: function( event ) {
8877
if ( $( event.target ).closest( ".ui-dialog" ).length ) {
8881
// TODO: Remove hack when datepicker implements
8882
// the .ui-front logic (#8989)
8883
return !!$( event.target ).closest( ".ui-datepicker" ).length;
8886
_createOverlay: function() {
8887
if ( !this.options.modal ) {
8891
// We use a delay in case the overlay is created from an
8892
// event that we're going to be cancelling (#2804)
8893
var isOpening = true;
8894
this._delay(function() {
8898
if ( !this.document.data( "ui-dialog-overlays" ) ) {
8900
// Prevent use of anchors and inputs
8901
// Using _on() for an event handler shared across many instances is
8902
// safe because the dialogs stack and must be closed in reverse order
8903
this._on( this.document, {
8904
focusin: function( event ) {
8909
if ( !this._allowInteraction( event ) ) {
8910
event.preventDefault();
8911
this._trackingInstances()[ 0 ]._focusTabbable();
8917
this.overlay = $( "<div>" )
8918
.addClass( "ui-widget-overlay ui-front" )
8919
.appendTo( this._appendTo() );
8920
this._on( this.overlay, {
8921
mousedown: "_keepFocus"
8923
this.document.data( "ui-dialog-overlays",
8924
(this.document.data( "ui-dialog-overlays" ) || 0) + 1 );
8927
_destroyOverlay: function() {
8928
if ( !this.options.modal ) {
8932
if ( this.overlay ) {
8933
var overlays = this.document.data( "ui-dialog-overlays" ) - 1;
8937
.unbind( "focusin" )
8938
.removeData( "ui-dialog-overlays" );
8940
this.document.data( "ui-dialog-overlays", overlays );
8943
this.overlay.remove();
8944
this.overlay = null;
8951
* jQuery UI Droppable 1.11.4
8952
* http://jqueryui.com
8954
* Copyright jQuery Foundation and other contributors
8955
* Released under the MIT license.
8956
* http://jquery.org/license
8958
* http://api.jqueryui.com/droppable/
8962
$.widget( "ui.droppable", {
8964
widgetEventPrefix: "drop",
8972
tolerance: "intersect",
8981
_create: function() {
8987
this.isover = false;
8990
this.accept = $.isFunction( accept ) ? accept : function( d ) {
8991
return d.is( accept );
8994
this.proportions = function( /* valueToWrite */ ) {
8995
if ( arguments.length ) {
8996
// Store the droppable's proportions
8997
proportions = arguments[ 0 ];
8999
// Retrieve or derive the droppable's proportions
9000
return proportions ?
9003
width: this.element[ 0 ].offsetWidth,
9004
height: this.element[ 0 ].offsetHeight
9009
this._addToManager( o.scope );
9011
o.addClasses && this.element.addClass( "ui-droppable" );
9015
_addToManager: function( scope ) {
9016
// Add the reference and positions to the manager
9017
$.ui.ddmanager.droppables[ scope ] = $.ui.ddmanager.droppables[ scope ] || [];
9018
$.ui.ddmanager.droppables[ scope ].push( this );
9021
_splice: function( drop ) {
9023
for ( ; i < drop.length; i++ ) {
9024
if ( drop[ i ] === this ) {
9025
drop.splice( i, 1 );
9030
_destroy: function() {
9031
var drop = $.ui.ddmanager.droppables[ this.options.scope ];
9033
this._splice( drop );
9035
this.element.removeClass( "ui-droppable ui-droppable-disabled" );
9038
_setOption: function( key, value ) {
9040
if ( key === "accept" ) {
9041
this.accept = $.isFunction( value ) ? value : function( d ) {
9042
return d.is( value );
9044
} else if ( key === "scope" ) {
9045
var drop = $.ui.ddmanager.droppables[ this.options.scope ];
9047
this._splice( drop );
9048
this._addToManager( value );
9051
this._super( key, value );
9054
_activate: function( event ) {
9055
var draggable = $.ui.ddmanager.current;
9056
if ( this.options.activeClass ) {
9057
this.element.addClass( this.options.activeClass );
9060
this._trigger( "activate", event, this.ui( draggable ) );
9064
_deactivate: function( event ) {
9065
var draggable = $.ui.ddmanager.current;
9066
if ( this.options.activeClass ) {
9067
this.element.removeClass( this.options.activeClass );
9070
this._trigger( "deactivate", event, this.ui( draggable ) );
9074
_over: function( event ) {
9076
var draggable = $.ui.ddmanager.current;
9078
// Bail if draggable and droppable are same element
9079
if ( !draggable || ( draggable.currentItem || draggable.element )[ 0 ] === this.element[ 0 ] ) {
9083
if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem || draggable.element ) ) ) {
9084
if ( this.options.hoverClass ) {
9085
this.element.addClass( this.options.hoverClass );
9087
this._trigger( "over", event, this.ui( draggable ) );
9092
_out: function( event ) {
9094
var draggable = $.ui.ddmanager.current;
9096
// Bail if draggable and droppable are same element
9097
if ( !draggable || ( draggable.currentItem || draggable.element )[ 0 ] === this.element[ 0 ] ) {
9101
if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem || draggable.element ) ) ) {
9102
if ( this.options.hoverClass ) {
9103
this.element.removeClass( this.options.hoverClass );
9105
this._trigger( "out", event, this.ui( draggable ) );
9110
_drop: function( event, custom ) {
9112
var draggable = custom || $.ui.ddmanager.current,
9113
childrenIntersection = false;
9115
// Bail if draggable and droppable are same element
9116
if ( !draggable || ( draggable.currentItem || draggable.element )[ 0 ] === this.element[ 0 ] ) {
9120
this.element.find( ":data(ui-droppable)" ).not( ".ui-draggable-dragging" ).each(function() {
9121
var inst = $( this ).droppable( "instance" );
9123
inst.options.greedy &&
9124
!inst.options.disabled &&
9125
inst.options.scope === draggable.options.scope &&
9126
inst.accept.call( inst.element[ 0 ], ( draggable.currentItem || draggable.element ) ) &&
9127
$.ui.intersect( draggable, $.extend( inst, { offset: inst.element.offset() } ), inst.options.tolerance, event )
9128
) { childrenIntersection = true; return false; }
9130
if ( childrenIntersection ) {
9134
if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem || draggable.element ) ) ) {
9135
if ( this.options.activeClass ) {
9136
this.element.removeClass( this.options.activeClass );
9138
if ( this.options.hoverClass ) {
9139
this.element.removeClass( this.options.hoverClass );
9141
this._trigger( "drop", event, this.ui( draggable ) );
9142
return this.element;
9151
draggable: ( c.currentItem || c.element ),
9153
position: c.position,
9154
offset: c.positionAbs
9160
$.ui.intersect = (function() {
9161
function isOverAxis( x, reference, size ) {
9162
return ( x >= reference ) && ( x < ( reference + size ) );
9165
return function( draggable, droppable, toleranceMode, event ) {
9167
if ( !droppable.offset ) {
9171
var x1 = ( draggable.positionAbs || draggable.position.absolute ).left + draggable.margins.left,
9172
y1 = ( draggable.positionAbs || draggable.position.absolute ).top + draggable.margins.top,
9173
x2 = x1 + draggable.helperProportions.width,
9174
y2 = y1 + draggable.helperProportions.height,
9175
l = droppable.offset.left,
9176
t = droppable.offset.top,
9177
r = l + droppable.proportions().width,
9178
b = t + droppable.proportions().height;
9180
switch ( toleranceMode ) {
9182
return ( l <= x1 && x2 <= r && t <= y1 && y2 <= b );
9184
return ( l < x1 + ( draggable.helperProportions.width / 2 ) && // Right Half
9185
x2 - ( draggable.helperProportions.width / 2 ) < r && // Left Half
9186
t < y1 + ( draggable.helperProportions.height / 2 ) && // Bottom Half
9187
y2 - ( draggable.helperProportions.height / 2 ) < b ); // Top Half
9189
return isOverAxis( event.pageY, t, droppable.proportions().height ) && isOverAxis( event.pageX, l, droppable.proportions().width );
9192
( y1 >= t && y1 <= b ) || // Top edge touching
9193
( y2 >= t && y2 <= b ) || // Bottom edge touching
9194
( y1 < t && y2 > b ) // Surrounded vertically
9196
( x1 >= l && x1 <= r ) || // Left edge touching
9197
( x2 >= l && x2 <= r ) || // Right edge touching
9198
( x1 < l && x2 > r ) // Surrounded horizontally
9207
This manager tracks offsets of draggables and droppables
9211
droppables: { "default": [] },
9212
prepareOffsets: function( t, event ) {
9215
m = $.ui.ddmanager.droppables[ t.options.scope ] || [],
9216
type = event ? event.type : null, // workaround for #2317
9217
list = ( t.currentItem || t.element ).find( ":data(ui-droppable)" ).addBack();
9219
droppablesLoop: for ( i = 0; i < m.length; i++ ) {
9221
// No disabled and non-accepted
9222
if ( m[ i ].options.disabled || ( t && !m[ i ].accept.call( m[ i ].element[ 0 ], ( t.currentItem || t.element ) ) ) ) {
9226
// Filter out elements in the current dragged item
9227
for ( j = 0; j < list.length; j++ ) {
9228
if ( list[ j ] === m[ i ].element[ 0 ] ) {
9229
m[ i ].proportions().height = 0;
9230
continue droppablesLoop;
9234
m[ i ].visible = m[ i ].element.css( "display" ) !== "none";
9235
if ( !m[ i ].visible ) {
9239
// Activate the droppable if used directly from draggables
9240
if ( type === "mousedown" ) {
9241
m[ i ]._activate.call( m[ i ], event );
9244
m[ i ].offset = m[ i ].element.offset();
9245
m[ i ].proportions({ width: m[ i ].element[ 0 ].offsetWidth, height: m[ i ].element[ 0 ].offsetHeight });
9250
drop: function( draggable, event ) {
9252
var dropped = false;
9253
// Create a copy of the droppables in case the list changes during the drop (#9116)
9254
$.each( ( $.ui.ddmanager.droppables[ draggable.options.scope ] || [] ).slice(), function() {
9256
if ( !this.options ) {
9259
if ( !this.options.disabled && this.visible && $.ui.intersect( draggable, this, this.options.tolerance, event ) ) {
9260
dropped = this._drop.call( this, event ) || dropped;
9263
if ( !this.options.disabled && this.visible && this.accept.call( this.element[ 0 ], ( draggable.currentItem || draggable.element ) ) ) {
9265
this.isover = false;
9266
this._deactivate.call( this, event );
9273
dragStart: function( draggable, event ) {
9274
// Listen for scrolling so that if the dragging causes scrolling the position of the droppables can be recalculated (see #5003)
9275
draggable.element.parentsUntil( "body" ).bind( "scroll.droppable", function() {
9276
if ( !draggable.options.refreshPositions ) {
9277
$.ui.ddmanager.prepareOffsets( draggable, event );
9281
drag: function( draggable, event ) {
9283
// If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse.
9284
if ( draggable.options.refreshPositions ) {
9285
$.ui.ddmanager.prepareOffsets( draggable, event );
9288
// Run through all droppables and check their positions based on specific tolerance options
9289
$.each( $.ui.ddmanager.droppables[ draggable.options.scope ] || [], function() {
9291
if ( this.options.disabled || this.greedyChild || !this.visible ) {
9295
var parentInstance, scope, parent,
9296
intersects = $.ui.intersect( draggable, this, this.options.tolerance, event ),
9297
c = !intersects && this.isover ? "isout" : ( intersects && !this.isover ? "isover" : null );
9302
if ( this.options.greedy ) {
9303
// find droppable parents with same scope
9304
scope = this.options.scope;
9305
parent = this.element.parents( ":data(ui-droppable)" ).filter(function() {
9306
return $( this ).droppable( "instance" ).options.scope === scope;
9309
if ( parent.length ) {
9310
parentInstance = $( parent[ 0 ] ).droppable( "instance" );
9311
parentInstance.greedyChild = ( c === "isover" );
9315
// we just moved into a greedy child
9316
if ( parentInstance && c === "isover" ) {
9317
parentInstance.isover = false;
9318
parentInstance.isout = true;
9319
parentInstance._out.call( parentInstance, event );
9323
this[c === "isout" ? "isover" : "isout"] = false;
9324
this[c === "isover" ? "_over" : "_out"].call( this, event );
9326
// we just moved out of a greedy child
9327
if ( parentInstance && c === "isout" ) {
9328
parentInstance.isout = false;
9329
parentInstance.isover = true;
9330
parentInstance._over.call( parentInstance, event );
9335
dragStop: function( draggable, event ) {
9336
draggable.element.parentsUntil( "body" ).unbind( "scroll.droppable" );
9337
// Call prepareOffsets one final time since IE does not fire return scroll events when overflow was caused by drag (see #5003)
9338
if ( !draggable.options.refreshPositions ) {
9339
$.ui.ddmanager.prepareOffsets( draggable, event );
9344
var droppable = $.ui.droppable;
9348
* jQuery UI Effects 1.11.4
9349
* http://jqueryui.com
9351
* Copyright jQuery Foundation and other contributors
9352
* Released under the MIT license.
9353
* http://jquery.org/license
9355
* http://api.jqueryui.com/category/effects-core/
9359
var dataSpace = "ui-effects-",
9361
// Create a local jQuery because jQuery Color relies on it and the
9362
// global may not exist with AMD and a custom build (#10199)
9370
* jQuery Color Animations v2.1.2
9371
* https://github.com/jquery/jquery-color
9373
* Copyright 2014 jQuery Foundation and other contributors
9374
* Released under the MIT license.
9375
* http://jquery.org/license
9377
* Date: Wed Jan 16 08:47:09 2013 -0600
9379
(function( jQuery, undefined ) {
9381
var stepHooks = "backgroundColor borderBottomColor borderLeftColor borderRightColor borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor",
9383
// plusequals test for += 100 -= 100
9384
rplusequals = /^([\-+])=\s*(\d+\.?\d*)/,
9385
// a set of RE's that can match strings and generate color tuples.
9387
re: /rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
9388
parse: function( execResult ) {
9397
re: /rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
9398
parse: function( execResult ) {
9400
execResult[ 1 ] * 2.55,
9401
execResult[ 2 ] * 2.55,
9402
execResult[ 3 ] * 2.55,
9407
// this regex ignores A-F because it's compared against an already lowercased string
9408
re: /#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/,
9409
parse: function( execResult ) {
9411
parseInt( execResult[ 1 ], 16 ),
9412
parseInt( execResult[ 2 ], 16 ),
9413
parseInt( execResult[ 3 ], 16 )
9417
// this regex ignores A-F because it's compared against an already lowercased string
9418
re: /#([a-f0-9])([a-f0-9])([a-f0-9])/,
9419
parse: function( execResult ) {
9421
parseInt( execResult[ 1 ] + execResult[ 1 ], 16 ),
9422
parseInt( execResult[ 2 ] + execResult[ 2 ], 16 ),
9423
parseInt( execResult[ 3 ] + execResult[ 3 ], 16 )
9427
re: /hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
9429
parse: function( execResult ) {
9432
execResult[ 2 ] / 100,
9433
execResult[ 3 ] / 100,
9440
color = jQuery.Color = function( color, green, blue, alpha ) {
9441
return new jQuery.Color.fn.parse( color, green, blue, alpha );
9491
support = color.support = {},
9493
// element for support tests
9494
supportElem = jQuery( "<p>" )[ 0 ],
9496
// colors = jQuery.Color.names
9499
// local aliases of functions called often
9502
// determine rgba support immediately
9503
supportElem.style.cssText = "background-color:rgba(1,1,1,.5)";
9504
support.rgba = supportElem.style.backgroundColor.indexOf( "rgba" ) > -1;
9506
// define cache name and alpha properties
9507
// for rgba and hsla spaces
9508
each( spaces, function( spaceName, space ) {
9509
space.cache = "_" + spaceName;
9510
space.props.alpha = {
9517
function clamp( value, prop, allowEmpty ) {
9518
var type = propTypes[ prop.type ] || {};
9520
if ( value == null ) {
9521
return (allowEmpty || !prop.def) ? null : prop.def;
9524
// ~~ is an short way of doing floor for positive numbers
9525
value = type.floor ? ~~value : parseFloat( value );
9527
// IE will pass in empty strings as value for alpha,
9528
// which will hit this case
9529
if ( isNaN( value ) ) {
9534
// we add mod before modding to make sure that negatives values
9535
// get converted properly: -10 -> 350
9536
return (value + type.mod) % type.mod;
9539
// for now all property types without mod have min and max
9540
return 0 > value ? 0 : type.max < value ? type.max : value;
9543
function stringParse( string ) {
9545
rgba = inst._rgba = [];
9547
string = string.toLowerCase();
9549
each( stringParsers, function( i, parser ) {
9551
match = parser.re.exec( string ),
9552
values = match && parser.parse( match ),
9553
spaceName = parser.space || "rgba";
9556
parsed = inst[ spaceName ]( values );
9558
// if this was an rgba parse the assignment might happen twice
9560
inst[ spaces[ spaceName ].cache ] = parsed[ spaces[ spaceName ].cache ];
9561
rgba = inst._rgba = parsed._rgba;
9563
// exit each( stringParsers ) here because we matched
9568
// Found a stringParser that handled it
9569
if ( rgba.length ) {
9571
// if this came from a parsed string, force "transparent" when alpha is 0
9572
// chrome, (and maybe others) return "transparent" as rgba(0,0,0,0)
9573
if ( rgba.join() === "0,0,0,0" ) {
9574
jQuery.extend( rgba, colors.transparent );
9580
return colors[ string ];
9583
color.fn = jQuery.extend( color.prototype, {
9584
parse: function( red, green, blue, alpha ) {
9585
if ( red === undefined ) {
9586
this._rgba = [ null, null, null, null ];
9589
if ( red.jquery || red.nodeType ) {
9590
red = jQuery( red ).css( green );
9595
type = jQuery.type( red ),
9596
rgba = this._rgba = [];
9598
// more than 1 argument specified - assume ( red, green, blue, alpha )
9599
if ( green !== undefined ) {
9600
red = [ red, green, blue, alpha ];
9604
if ( type === "string" ) {
9605
return this.parse( stringParse( red ) || colors._default );
9608
if ( type === "array" ) {
9609
each( spaces.rgba.props, function( key, prop ) {
9610
rgba[ prop.idx ] = clamp( red[ prop.idx ], prop );
9615
if ( type === "object" ) {
9616
if ( red instanceof color ) {
9617
each( spaces, function( spaceName, space ) {
9618
if ( red[ space.cache ] ) {
9619
inst[ space.cache ] = red[ space.cache ].slice();
9623
each( spaces, function( spaceName, space ) {
9624
var cache = space.cache;
9625
each( space.props, function( key, prop ) {
9627
// if the cache doesn't exist, and we know how to convert
9628
if ( !inst[ cache ] && space.to ) {
9630
// if the value was null, we don't need to copy it
9631
// if the key was alpha, we don't need to copy it either
9632
if ( key === "alpha" || red[ key ] == null ) {
9635
inst[ cache ] = space.to( inst._rgba );
9638
// this is the only case where we allow nulls for ALL properties.
9639
// call clamp with alwaysAllowEmpty
9640
inst[ cache ][ prop.idx ] = clamp( red[ key ], prop, true );
9643
// everything defined but alpha?
9644
if ( inst[ cache ] && jQuery.inArray( null, inst[ cache ].slice( 0, 3 ) ) < 0 ) {
9645
// use the default of 1
9646
inst[ cache ][ 3 ] = 1;
9648
inst._rgba = space.from( inst[ cache ] );
9656
is: function( compare ) {
9657
var is = color( compare ),
9661
each( spaces, function( _, space ) {
9663
isCache = is[ space.cache ];
9665
localCache = inst[ space.cache ] || space.to && space.to( inst._rgba ) || [];
9666
each( space.props, function( _, prop ) {
9667
if ( isCache[ prop.idx ] != null ) {
9668
same = ( isCache[ prop.idx ] === localCache[ prop.idx ] );
9677
_space: function() {
9680
each( spaces, function( spaceName, space ) {
9681
if ( inst[ space.cache ] ) {
9682
used.push( spaceName );
9687
transition: function( other, distance ) {
9688
var end = color( other ),
9689
spaceName = end._space(),
9690
space = spaces[ spaceName ],
9691
startColor = this.alpha() === 0 ? color( "transparent" ) : this,
9692
start = startColor[ space.cache ] || space.to( startColor._rgba ),
9693
result = start.slice();
9695
end = end[ space.cache ];
9696
each( space.props, function( key, prop ) {
9697
var index = prop.idx,
9698
startValue = start[ index ],
9699
endValue = end[ index ],
9700
type = propTypes[ prop.type ] || {};
9702
// if null, don't override start value
9703
if ( endValue === null ) {
9706
// if null - use end
9707
if ( startValue === null ) {
9708
result[ index ] = endValue;
9711
if ( endValue - startValue > type.mod / 2 ) {
9712
startValue += type.mod;
9713
} else if ( startValue - endValue > type.mod / 2 ) {
9714
startValue -= type.mod;
9717
result[ index ] = clamp( ( endValue - startValue ) * distance + startValue, prop );
9720
return this[ spaceName ]( result );
9722
blend: function( opaque ) {
9723
// if we are already opaque - return ourself
9724
if ( this._rgba[ 3 ] === 1 ) {
9728
var rgb = this._rgba.slice(),
9730
blend = color( opaque )._rgba;
9732
return color( jQuery.map( rgb, function( v, i ) {
9733
return ( 1 - a ) * blend[ i ] + a * v;
9736
toRgbaString: function() {
9737
var prefix = "rgba(",
9738
rgba = jQuery.map( this._rgba, function( v, i ) {
9739
return v == null ? ( i > 2 ? 1 : 0 ) : v;
9742
if ( rgba[ 3 ] === 1 ) {
9747
return prefix + rgba.join() + ")";
9749
toHslaString: function() {
9750
var prefix = "hsla(",
9751
hsla = jQuery.map( this.hsla(), function( v, i ) {
9758
v = Math.round( v * 100 ) + "%";
9763
if ( hsla[ 3 ] === 1 ) {
9767
return prefix + hsla.join() + ")";
9769
toHexString: function( includeAlpha ) {
9770
var rgba = this._rgba.slice(),
9773
if ( includeAlpha ) {
9774
rgba.push( ~~( alpha * 255 ) );
9777
return "#" + jQuery.map( rgba, function( v ) {
9779
// default to 0 when nulls exist
9780
v = ( v || 0 ).toString( 16 );
9781
return v.length === 1 ? "0" + v : v;
9784
toString: function() {
9785
return this._rgba[ 3 ] === 0 ? "transparent" : this.toRgbaString();
9788
color.fn.parse.prototype = color.fn;
9790
// hsla conversions adapted from:
9791
// https://code.google.com/p/maashaack/source/browse/packages/graphics/trunk/src/graphics/colors/HUE2RGB.as?r=5021
9793
function hue2rgb( p, q, h ) {
9796
return p + ( q - p ) * h * 6;
9802
return p + ( q - p ) * ( ( 2 / 3 ) - h ) * 6;
9807
spaces.hsla.to = function( rgba ) {
9808
if ( rgba[ 0 ] == null || rgba[ 1 ] == null || rgba[ 2 ] == null ) {
9809
return [ null, null, null, rgba[ 3 ] ];
9811
var r = rgba[ 0 ] / 255,
9812
g = rgba[ 1 ] / 255,
9813
b = rgba[ 2 ] / 255,
9815
max = Math.max( r, g, b ),
9816
min = Math.min( r, g, b ),
9822
if ( min === max ) {
9824
} else if ( r === max ) {
9825
h = ( 60 * ( g - b ) / diff ) + 360;
9826
} else if ( g === max ) {
9827
h = ( 60 * ( b - r ) / diff ) + 120;
9829
h = ( 60 * ( r - g ) / diff ) + 240;
9832
// chroma (diff) == 0 means greyscale which, by definition, saturation = 0%
9833
// otherwise, saturation is based on the ratio of chroma (diff) to lightness (add)
9836
} else if ( l <= 0.5 ) {
9839
s = diff / ( 2 - add );
9841
return [ Math.round(h) % 360, s, l, a == null ? 1 : a ];
9844
spaces.hsla.from = function( hsla ) {
9845
if ( hsla[ 0 ] == null || hsla[ 1 ] == null || hsla[ 2 ] == null ) {
9846
return [ null, null, null, hsla[ 3 ] ];
9848
var h = hsla[ 0 ] / 360,
9852
q = l <= 0.5 ? l * ( 1 + s ) : l + s - l * s,
9856
Math.round( hue2rgb( p, q, h + ( 1 / 3 ) ) * 255 ),
9857
Math.round( hue2rgb( p, q, h ) * 255 ),
9858
Math.round( hue2rgb( p, q, h - ( 1 / 3 ) ) * 255 ),
9863
each( spaces, function( spaceName, space ) {
9864
var props = space.props,
9865
cache = space.cache,
9869
// makes rgba() and hsla()
9870
color.fn[ spaceName ] = function( value ) {
9872
// generate a cache for this space if it doesn't exist
9873
if ( to && !this[ cache ] ) {
9874
this[ cache ] = to( this._rgba );
9876
if ( value === undefined ) {
9877
return this[ cache ].slice();
9881
type = jQuery.type( value ),
9882
arr = ( type === "array" || type === "object" ) ? value : arguments,
9883
local = this[ cache ].slice();
9885
each( props, function( key, prop ) {
9886
var val = arr[ type === "object" ? key : prop.idx ];
9887
if ( val == null ) {
9888
val = local[ prop.idx ];
9890
local[ prop.idx ] = clamp( val, prop );
9894
ret = color( from( local ) );
9895
ret[ cache ] = local;
9898
return color( local );
9902
// makes red() green() blue() alpha() hue() saturation() lightness()
9903
each( props, function( key, prop ) {
9904
// alpha is included in more than one space
9905
if ( color.fn[ key ] ) {
9908
color.fn[ key ] = function( value ) {
9909
var vtype = jQuery.type( value ),
9910
fn = ( key === "alpha" ? ( this._hsla ? "hsla" : "rgba" ) : spaceName ),
9911
local = this[ fn ](),
9912
cur = local[ prop.idx ],
9915
if ( vtype === "undefined" ) {
9919
if ( vtype === "function" ) {
9920
value = value.call( this, cur );
9921
vtype = jQuery.type( value );
9923
if ( value == null && prop.empty ) {
9926
if ( vtype === "string" ) {
9927
match = rplusequals.exec( value );
9929
value = cur + parseFloat( match[ 2 ] ) * ( match[ 1 ] === "+" ? 1 : -1 );
9932
local[ prop.idx ] = value;
9933
return this[ fn ]( local );
9938
// add cssHook and .fx.step function for each named hook.
9939
// accept a space separated string of properties
9940
color.hook = function( hook ) {
9941
var hooks = hook.split( " " );
9942
each( hooks, function( i, hook ) {
9943
jQuery.cssHooks[ hook ] = {
9944
set: function( elem, value ) {
9945
var parsed, curElem,
9946
backgroundColor = "";
9948
if ( value !== "transparent" && ( jQuery.type( value ) !== "string" || ( parsed = stringParse( value ) ) ) ) {
9949
value = color( parsed || value );
9950
if ( !support.rgba && value._rgba[ 3 ] !== 1 ) {
9951
curElem = hook === "backgroundColor" ? elem.parentNode : elem;
9953
(backgroundColor === "" || backgroundColor === "transparent") &&
9954
curElem && curElem.style
9957
backgroundColor = jQuery.css( curElem, "backgroundColor" );
9958
curElem = curElem.parentNode;
9963
value = value.blend( backgroundColor && backgroundColor !== "transparent" ?
9968
value = value.toRgbaString();
9971
elem.style[ hook ] = value;
9973
// wrapped to prevent IE from throwing errors on "invalid" values like 'auto' or 'inherit'
9977
jQuery.fx.step[ hook ] = function( fx ) {
9978
if ( !fx.colorInit ) {
9979
fx.start = color( fx.elem, hook );
9980
fx.end = color( fx.end );
9981
fx.colorInit = true;
9983
jQuery.cssHooks[ hook ].set( fx.elem, fx.start.transition( fx.end, fx.pos ) );
9989
color.hook( stepHooks );
9991
jQuery.cssHooks.borderColor = {
9992
expand: function( value ) {
9995
each( [ "Top", "Right", "Bottom", "Left" ], function( i, part ) {
9996
expanded[ "border" + part + "Color" ] = value;
10002
// Basic color names only.
10003
// Usage of any of the other color names requires adding yourself or including
10004
// jquery.color.svg-names.js.
10005
colors = jQuery.Color.names = {
10006
// 4.1. Basic color keywords
10010
fuchsia: "#ff00ff",
10024
// 4.2.3. "transparent" color keyword
10025
transparent: [ null, null, null, 0 ],
10027
_default: "#ffffff"
10032
/******************************************************************************/
10033
/****************************** CLASS ANIMATIONS ******************************/
10034
/******************************************************************************/
10037
var classAnimationActions = [ "add", "remove", "toggle" ],
10038
shorthandStyles = {
10050
$.each([ "borderLeftStyle", "borderRightStyle", "borderBottomStyle", "borderTopStyle" ], function( _, prop ) {
10051
$.fx.step[ prop ] = function( fx ) {
10052
if ( fx.end !== "none" && !fx.setAttr || fx.pos === 1 && !fx.setAttr ) {
10053
jQuery.style( fx.elem, prop, fx.end );
10059
function getElementStyles( elem ) {
10061
style = elem.ownerDocument.defaultView ?
10062
elem.ownerDocument.defaultView.getComputedStyle( elem, null ) :
10066
if ( style && style.length && style[ 0 ] && style[ style[ 0 ] ] ) {
10067
len = style.length;
10069
key = style[ len ];
10070
if ( typeof style[ key ] === "string" ) {
10071
styles[ $.camelCase( key ) ] = style[ key ];
10074
// support: Opera, IE <9
10076
for ( key in style ) {
10077
if ( typeof style[ key ] === "string" ) {
10078
styles[ key ] = style[ key ];
10086
function styleDifference( oldStyle, newStyle ) {
10090
for ( name in newStyle ) {
10091
value = newStyle[ name ];
10092
if ( oldStyle[ name ] !== value ) {
10093
if ( !shorthandStyles[ name ] ) {
10094
if ( $.fx.step[ name ] || !isNaN( parseFloat( value ) ) ) {
10095
diff[ name ] = value;
10104
// support: jQuery <1.8
10105
if ( !$.fn.addBack ) {
10106
$.fn.addBack = function( selector ) {
10107
return this.add( selector == null ?
10108
this.prevObject : this.prevObject.filter( selector )
10113
$.effects.animateClass = function( value, duration, easing, callback ) {
10114
var o = $.speed( duration, easing, callback );
10116
return this.queue( function() {
10117
var animated = $( this ),
10118
baseClass = animated.attr( "class" ) || "",
10120
allAnimations = o.children ? animated.find( "*" ).addBack() : animated;
10122
// map the animated objects to store the original styles.
10123
allAnimations = allAnimations.map(function() {
10124
var el = $( this );
10127
start: getElementStyles( this )
10131
// apply class change
10132
applyClassChange = function() {
10133
$.each( classAnimationActions, function(i, action) {
10134
if ( value[ action ] ) {
10135
animated[ action + "Class" ]( value[ action ] );
10139
applyClassChange();
10141
// map all animated objects again - calculate new styles and diff
10142
allAnimations = allAnimations.map(function() {
10143
this.end = getElementStyles( this.el[ 0 ] );
10144
this.diff = styleDifference( this.start, this.end );
10148
// apply original class
10149
animated.attr( "class", baseClass );
10151
// map all animated objects again - this time collecting a promise
10152
allAnimations = allAnimations.map(function() {
10153
var styleInfo = this,
10154
dfd = $.Deferred(),
10155
opts = $.extend({}, o, {
10157
complete: function() {
10158
dfd.resolve( styleInfo );
10162
this.el.animate( this.diff, opts );
10163
return dfd.promise();
10166
// once all animations have completed:
10167
$.when.apply( $, allAnimations.get() ).done(function() {
10169
// set the final class
10170
applyClassChange();
10172
// for each animated element,
10173
// clear all css properties that were animated
10174
$.each( arguments, function() {
10176
$.each( this.diff, function(key) {
10181
// this is guarnteed to be there if you use jQuery.speed()
10182
// it also handles dequeuing the next anim...
10183
o.complete.call( animated[ 0 ] );
10189
addClass: (function( orig ) {
10190
return function( classNames, speed, easing, callback ) {
10192
$.effects.animateClass.call( this,
10193
{ add: classNames }, speed, easing, callback ) :
10194
orig.apply( this, arguments );
10196
})( $.fn.addClass ),
10198
removeClass: (function( orig ) {
10199
return function( classNames, speed, easing, callback ) {
10200
return arguments.length > 1 ?
10201
$.effects.animateClass.call( this,
10202
{ remove: classNames }, speed, easing, callback ) :
10203
orig.apply( this, arguments );
10205
})( $.fn.removeClass ),
10207
toggleClass: (function( orig ) {
10208
return function( classNames, force, speed, easing, callback ) {
10209
if ( typeof force === "boolean" || force === undefined ) {
10211
// without speed parameter
10212
return orig.apply( this, arguments );
10214
return $.effects.animateClass.call( this,
10215
(force ? { add: classNames } : { remove: classNames }),
10216
speed, easing, callback );
10219
// without force parameter
10220
return $.effects.animateClass.call( this,
10221
{ toggle: classNames }, force, speed, easing );
10224
})( $.fn.toggleClass ),
10226
switchClass: function( remove, add, speed, easing, callback) {
10227
return $.effects.animateClass.call( this, {
10230
}, speed, easing, callback );
10236
/******************************************************************************/
10237
/*********************************** EFFECTS **********************************/
10238
/******************************************************************************/
10242
$.extend( $.effects, {
10245
// Saves a set of properties in a data storage
10246
save: function( element, set ) {
10247
for ( var i = 0; i < set.length; i++ ) {
10248
if ( set[ i ] !== null ) {
10249
element.data( dataSpace + set[ i ], element[ 0 ].style[ set[ i ] ] );
10254
// Restores a set of previously saved properties from a data storage
10255
restore: function( element, set ) {
10257
for ( i = 0; i < set.length; i++ ) {
10258
if ( set[ i ] !== null ) {
10259
val = element.data( dataSpace + set[ i ] );
10260
// support: jQuery 1.6.2
10261
// http://bugs.jquery.com/ticket/9917
10262
// jQuery 1.6.2 incorrectly returns undefined for any falsy value.
10263
// We can't differentiate between "" and 0 here, so we just assume
10264
// empty string since it's likely to be a more common value...
10265
if ( val === undefined ) {
10268
element.css( set[ i ], val );
10273
setMode: function( el, mode ) {
10274
if (mode === "toggle") {
10275
mode = el.is( ":hidden" ) ? "show" : "hide";
10280
// Translates a [top,left] array into a baseline value
10281
// this should be a little more flexible in the future to handle a string & hash
10282
getBaseline: function( origin, original ) {
10284
switch ( origin[ 0 ] ) {
10285
case "top": y = 0; break;
10286
case "middle": y = 0.5; break;
10287
case "bottom": y = 1; break;
10288
default: y = origin[ 0 ] / original.height;
10290
switch ( origin[ 1 ] ) {
10291
case "left": x = 0; break;
10292
case "center": x = 0.5; break;
10293
case "right": x = 1; break;
10294
default: x = origin[ 1 ] / original.width;
10302
// Wraps the element around a wrapper that copies position properties
10303
createWrapper: function( element ) {
10305
// if the element is already wrapped, return it
10306
if ( element.parent().is( ".ui-effects-wrapper" )) {
10307
return element.parent();
10310
// wrap the element
10312
width: element.outerWidth(true),
10313
height: element.outerHeight(true),
10314
"float": element.css( "float" )
10316
wrapper = $( "<div></div>" )
10317
.addClass( "ui-effects-wrapper" )
10320
background: "transparent",
10325
// Store the size in case width/height are defined in % - Fixes #5245
10327
width: element.width(),
10328
height: element.height()
10330
active = document.activeElement;
10332
// support: Firefox
10333
// Firefox incorrectly exposes anonymous content
10334
// https://bugzilla.mozilla.org/show_bug.cgi?id=561664
10338
active = document.body;
10341
element.wrap( wrapper );
10343
// Fixes #7595 - Elements lose focus when wrapped.
10344
if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
10345
$( active ).focus();
10348
wrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually lose the reference to the wrapped element
10350
// transfer positioning properties to the wrapper
10351
if ( element.css( "position" ) === "static" ) {
10352
wrapper.css({ position: "relative" });
10353
element.css({ position: "relative" });
10356
position: element.css( "position" ),
10357
zIndex: element.css( "z-index" )
10359
$.each([ "top", "left", "bottom", "right" ], function(i, pos) {
10360
props[ pos ] = element.css( pos );
10361
if ( isNaN( parseInt( props[ pos ], 10 ) ) ) {
10362
props[ pos ] = "auto";
10366
position: "relative",
10375
return wrapper.css( props ).show();
10378
removeWrapper: function( element ) {
10379
var active = document.activeElement;
10381
if ( element.parent().is( ".ui-effects-wrapper" ) ) {
10382
element.parent().replaceWith( element );
10384
// Fixes #7595 - Elements lose focus when wrapped.
10385
if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
10386
$( active ).focus();
10393
setTransition: function( element, list, factor, value ) {
10394
value = value || {};
10395
$.each( list, function( i, x ) {
10396
var unit = element.cssUnit( x );
10397
if ( unit[ 0 ] > 0 ) {
10398
value[ x ] = unit[ 0 ] * factor + unit[ 1 ];
10405
// return an effect options object for the given parameters:
10406
function _normalizeArguments( effect, options, speed, callback ) {
10408
// allow passing all options as the first parameter
10409
if ( $.isPlainObject( effect ) ) {
10411
effect = effect.effect;
10414
// convert to an object
10415
effect = { effect: effect };
10417
// catch (effect, null, ...)
10418
if ( options == null ) {
10422
// catch (effect, callback)
10423
if ( $.isFunction( options ) ) {
10424
callback = options;
10429
// catch (effect, speed, ?)
10430
if ( typeof options === "number" || $.fx.speeds[ options ] ) {
10436
// catch (effect, options, callback)
10437
if ( $.isFunction( speed ) ) {
10442
// add options to effect
10444
$.extend( effect, options );
10447
speed = speed || options.duration;
10448
effect.duration = $.fx.off ? 0 :
10449
typeof speed === "number" ? speed :
10450
speed in $.fx.speeds ? $.fx.speeds[ speed ] :
10451
$.fx.speeds._default;
10453
effect.complete = callback || options.complete;
10458
function standardAnimationOption( option ) {
10459
// Valid standard speeds (nothing, number, named speed)
10460
if ( !option || typeof option === "number" || $.fx.speeds[ option ] ) {
10464
// Invalid strings - treat as "normal" speed
10465
if ( typeof option === "string" && !$.effects.effect[ option ] ) {
10469
// Complete callback
10470
if ( $.isFunction( option ) ) {
10474
// Options hash (but not naming an effect)
10475
if ( typeof option === "object" && !option.effect ) {
10479
// Didn't match any standard API
10484
effect: function( /* effect, options, speed, callback */ ) {
10485
var args = _normalizeArguments.apply( this, arguments ),
10487
queue = args.queue,
10488
effectMethod = $.effects.effect[ args.effect ];
10490
if ( $.fx.off || !effectMethod ) {
10491
// delegate to the original method (e.g., .show()) if possible
10493
return this[ mode ]( args.duration, args.complete );
10495
return this.each( function() {
10496
if ( args.complete ) {
10497
args.complete.call( this );
10503
function run( next ) {
10504
var elem = $( this ),
10505
complete = args.complete,
10509
if ( $.isFunction( complete ) ) {
10510
complete.call( elem[0] );
10512
if ( $.isFunction( next ) ) {
10517
// If the element already has the correct final state, delegate to
10518
// the core methods so the internal tracking of "olddisplay" works.
10519
if ( elem.is( ":hidden" ) ? mode === "hide" : mode === "show" ) {
10523
effectMethod.call( elem[0], args, done );
10527
return queue === false ? this.each( run ) : this.queue( queue || "fx", run );
10530
show: (function( orig ) {
10531
return function( option ) {
10532
if ( standardAnimationOption( option ) ) {
10533
return orig.apply( this, arguments );
10535
var args = _normalizeArguments.apply( this, arguments );
10536
args.mode = "show";
10537
return this.effect.call( this, args );
10542
hide: (function( orig ) {
10543
return function( option ) {
10544
if ( standardAnimationOption( option ) ) {
10545
return orig.apply( this, arguments );
10547
var args = _normalizeArguments.apply( this, arguments );
10548
args.mode = "hide";
10549
return this.effect.call( this, args );
10554
toggle: (function( orig ) {
10555
return function( option ) {
10556
if ( standardAnimationOption( option ) || typeof option === "boolean" ) {
10557
return orig.apply( this, arguments );
10559
var args = _normalizeArguments.apply( this, arguments );
10560
args.mode = "toggle";
10561
return this.effect.call( this, args );
10566
// helper functions
10567
cssUnit: function(key) {
10568
var style = this.css( key ),
10571
$.each( [ "em", "px", "%", "pt" ], function( i, unit ) {
10572
if ( style.indexOf( unit ) > 0 ) {
10573
val = [ parseFloat( style ), unit ];
10582
/******************************************************************************/
10583
/*********************************** EASING ***********************************/
10584
/******************************************************************************/
10588
// based on easing equations from Robert Penner (http://www.robertpenner.com/easing)
10590
var baseEasings = {};
10592
$.each( [ "Quad", "Cubic", "Quart", "Quint", "Expo" ], function( i, name ) {
10593
baseEasings[ name ] = function( p ) {
10594
return Math.pow( p, i + 2 );
10598
$.extend( baseEasings, {
10599
Sine: function( p ) {
10600
return 1 - Math.cos( p * Math.PI / 2 );
10602
Circ: function( p ) {
10603
return 1 - Math.sqrt( 1 - p * p );
10605
Elastic: function( p ) {
10606
return p === 0 || p === 1 ? p :
10607
-Math.pow( 2, 8 * (p - 1) ) * Math.sin( ( (p - 1) * 80 - 7.5 ) * Math.PI / 15 );
10609
Back: function( p ) {
10610
return p * p * ( 3 * p - 2 );
10612
Bounce: function( p ) {
10616
while ( p < ( ( pow2 = Math.pow( 2, --bounce ) ) - 1 ) / 11 ) {}
10617
return 1 / Math.pow( 4, 3 - bounce ) - 7.5625 * Math.pow( ( pow2 * 3 - 2 ) / 22 - p, 2 );
10621
$.each( baseEasings, function( name, easeIn ) {
10622
$.easing[ "easeIn" + name ] = easeIn;
10623
$.easing[ "easeOut" + name ] = function( p ) {
10624
return 1 - easeIn( 1 - p );
10626
$.easing[ "easeInOut" + name ] = function( p ) {
10628
easeIn( p * 2 ) / 2 :
10629
1 - easeIn( p * -2 + 2 ) / 2;
10635
var effect = $.effects;
10639
* jQuery UI Effects Blind 1.11.4
10640
* http://jqueryui.com
10642
* Copyright jQuery Foundation and other contributors
10643
* Released under the MIT license.
10644
* http://jquery.org/license
10646
* http://api.jqueryui.com/blind-effect/
10650
var effectBlind = $.effects.effect.blind = function( o, done ) {
10652
var el = $( this ),
10653
rvertical = /up|down|vertical/,
10654
rpositivemotion = /up|left|vertical|horizontal/,
10655
props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
10656
mode = $.effects.setMode( el, o.mode || "hide" ),
10657
direction = o.direction || "up",
10658
vertical = rvertical.test( direction ),
10659
ref = vertical ? "height" : "width",
10660
ref2 = vertical ? "top" : "left",
10661
motion = rpositivemotion.test( direction ),
10663
show = mode === "show",
10664
wrapper, distance, margin;
10666
// if already wrapped, the wrapper's properties are my property. #6245
10667
if ( el.parent().is( ".ui-effects-wrapper" ) ) {
10668
$.effects.save( el.parent(), props );
10670
$.effects.save( el, props );
10673
wrapper = $.effects.createWrapper( el ).css({
10677
distance = wrapper[ ref ]();
10678
margin = parseFloat( wrapper.css( ref2 ) ) || 0;
10680
animation[ ref ] = show ? distance : 0;
10683
.css( vertical ? "bottom" : "right", 0 )
10684
.css( vertical ? "top" : "left", "auto" )
10685
.css({ position: "absolute" });
10687
animation[ ref2 ] = show ? margin : distance + margin;
10690
// start at 0 if we are showing
10692
wrapper.css( ref, 0 );
10694
wrapper.css( ref2, margin + distance );
10699
wrapper.animate( animation, {
10700
duration: o.duration,
10703
complete: function() {
10704
if ( mode === "hide" ) {
10707
$.effects.restore( el, props );
10708
$.effects.removeWrapper( el );
10716
* jQuery UI Effects Bounce 1.11.4
10717
* http://jqueryui.com
10719
* Copyright jQuery Foundation and other contributors
10720
* Released under the MIT license.
10721
* http://jquery.org/license
10723
* http://api.jqueryui.com/bounce-effect/
10727
var effectBounce = $.effects.effect.bounce = function( o, done ) {
10728
var el = $( this ),
10729
props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
10732
mode = $.effects.setMode( el, o.mode || "effect" ),
10733
hide = mode === "hide",
10734
show = mode === "show",
10735
direction = o.direction || "up",
10736
distance = o.distance,
10737
times = o.times || 5,
10739
// number of internal animations
10740
anims = times * 2 + ( show || hide ? 1 : 0 ),
10741
speed = o.duration / anims,
10745
ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
10746
motion = ( direction === "up" || direction === "left" ),
10751
// we will need to re-assemble the queue to stack our animations in place
10752
queue = el.queue(),
10753
queuelen = queue.length;
10755
// Avoid touching opacity to prevent clearType and PNG issues in IE
10756
if ( show || hide ) {
10757
props.push( "opacity" );
10760
$.effects.save( el, props );
10762
$.effects.createWrapper( el ); // Create Wrapper
10764
// default distance for the BIGGEST bounce is the outer Distance / 3
10766
distance = el[ ref === "top" ? "outerHeight" : "outerWidth" ]() / 3;
10770
downAnim = { opacity: 1 };
10771
downAnim[ ref ] = 0;
10773
// if we are showing, force opacity 0 and set the initial position
10774
// then do the "first" animation
10775
el.css( "opacity", 0 )
10776
.css( ref, motion ? -distance * 2 : distance * 2 )
10777
.animate( downAnim, speed, easing );
10780
// start at the smallest distance if we are hiding
10782
distance = distance / Math.pow( 2, times - 1 );
10786
downAnim[ ref ] = 0;
10787
// Bounces up/down/left/right then back to 0 -- times * 2 animations happen here
10788
for ( i = 0; i < times; i++ ) {
10790
upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance;
10792
el.animate( upAnim, speed, easing )
10793
.animate( downAnim, speed, easing );
10795
distance = hide ? distance * 2 : distance / 2;
10798
// Last Bounce when Hiding
10800
upAnim = { opacity: 0 };
10801
upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance;
10803
el.animate( upAnim, speed, easing );
10806
el.queue(function() {
10810
$.effects.restore( el, props );
10811
$.effects.removeWrapper( el );
10815
// inject all the animations we just queued to be first in line (after "inprogress")
10816
if ( queuelen > 1) {
10817
queue.splice.apply( queue,
10818
[ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) );
10826
* jQuery UI Effects Clip 1.11.4
10827
* http://jqueryui.com
10829
* Copyright jQuery Foundation and other contributors
10830
* Released under the MIT license.
10831
* http://jquery.org/license
10833
* http://api.jqueryui.com/clip-effect/
10837
var effectClip = $.effects.effect.clip = function( o, done ) {
10839
var el = $( this ),
10840
props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
10841
mode = $.effects.setMode( el, o.mode || "hide" ),
10842
show = mode === "show",
10843
direction = o.direction || "vertical",
10844
vert = direction === "vertical",
10845
size = vert ? "height" : "width",
10846
position = vert ? "top" : "left",
10848
wrapper, animate, distance;
10851
$.effects.save( el, props );
10855
wrapper = $.effects.createWrapper( el ).css({
10858
animate = ( el[0].tagName === "IMG" ) ? wrapper : el;
10859
distance = animate[ size ]();
10863
animate.css( size, 0 );
10864
animate.css( position, distance / 2 );
10867
// Create Animation Object:
10868
animation[ size ] = show ? distance : 0;
10869
animation[ position ] = show ? 0 : distance / 2;
10872
animate.animate( animation, {
10874
duration: o.duration,
10876
complete: function() {
10880
$.effects.restore( el, props );
10881
$.effects.removeWrapper( el );
10890
* jQuery UI Effects Drop 1.11.4
10891
* http://jqueryui.com
10893
* Copyright jQuery Foundation and other contributors
10894
* Released under the MIT license.
10895
* http://jquery.org/license
10897
* http://api.jqueryui.com/drop-effect/
10901
var effectDrop = $.effects.effect.drop = function( o, done ) {
10903
var el = $( this ),
10904
props = [ "position", "top", "bottom", "left", "right", "opacity", "height", "width" ],
10905
mode = $.effects.setMode( el, o.mode || "hide" ),
10906
show = mode === "show",
10907
direction = o.direction || "left",
10908
ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
10909
motion = ( direction === "up" || direction === "left" ) ? "pos" : "neg",
10911
opacity: show ? 1 : 0
10916
$.effects.save( el, props );
10918
$.effects.createWrapper( el );
10920
distance = o.distance || el[ ref === "top" ? "outerHeight" : "outerWidth" ]( true ) / 2;
10924
.css( "opacity", 0 )
10925
.css( ref, motion === "pos" ? -distance : distance );
10929
animation[ ref ] = ( show ?
10930
( motion === "pos" ? "+=" : "-=" ) :
10931
( motion === "pos" ? "-=" : "+=" ) ) +
10935
el.animate( animation, {
10937
duration: o.duration,
10939
complete: function() {
10940
if ( mode === "hide" ) {
10943
$.effects.restore( el, props );
10944
$.effects.removeWrapper( el );
10952
* jQuery UI Effects Explode 1.11.4
10953
* http://jqueryui.com
10955
* Copyright jQuery Foundation and other contributors
10956
* Released under the MIT license.
10957
* http://jquery.org/license
10959
* http://api.jqueryui.com/explode-effect/
10963
var effectExplode = $.effects.effect.explode = function( o, done ) {
10965
var rows = o.pieces ? Math.round( Math.sqrt( o.pieces ) ) : 3,
10968
mode = $.effects.setMode( el, o.mode || "hide" ),
10969
show = mode === "show",
10971
// show and then visibility:hidden the element before calculating offset
10972
offset = el.show().css( "visibility", "hidden" ).offset(),
10974
// width and height of a piece
10975
width = Math.ceil( el.outerWidth() / cells ),
10976
height = Math.ceil( el.outerHeight() / rows ),
10980
i, j, left, top, mx, my;
10982
// children animate complete:
10983
function childComplete() {
10984
pieces.push( this );
10985
if ( pieces.length === rows * cells ) {
10990
// clone the element for each row and cell.
10991
for ( i = 0; i < rows ; i++ ) { // ===>
10992
top = offset.top + i * height;
10993
my = i - ( rows - 1 ) / 2 ;
10995
for ( j = 0; j < cells ; j++ ) { // |||
10996
left = offset.left + j * width;
10997
mx = j - ( cells - 1 ) / 2 ;
10999
// Create a clone of the now hidden main element that will be absolute positioned
11000
// within a wrapper div off the -left and -top equal to size of our pieces
11003
.appendTo( "body" )
11004
.wrap( "<div></div>" )
11006
position: "absolute",
11007
visibility: "visible",
11012
// select the wrapper - make it overflow: hidden and absolute positioned based on
11013
// where the original was located +left and +top equal to the size of pieces
11015
.addClass( "ui-effects-explode" )
11017
position: "absolute",
11018
overflow: "hidden",
11021
left: left + ( show ? mx * width : 0 ),
11022
top: top + ( show ? my * height : 0 ),
11023
opacity: show ? 0 : 1
11025
left: left + ( show ? 0 : mx * width ),
11026
top: top + ( show ? 0 : my * height ),
11027
opacity: show ? 1 : 0
11028
}, o.duration || 500, o.easing, childComplete );
11032
function animComplete() {
11034
visibility: "visible"
11036
$( pieces ).remove();
11046
* jQuery UI Effects Fade 1.11.4
11047
* http://jqueryui.com
11049
* Copyright jQuery Foundation and other contributors
11050
* Released under the MIT license.
11051
* http://jquery.org/license
11053
* http://api.jqueryui.com/fade-effect/
11057
var effectFade = $.effects.effect.fade = function( o, done ) {
11058
var el = $( this ),
11059
mode = $.effects.setMode( el, o.mode || "toggle" );
11065
duration: o.duration,
11073
* jQuery UI Effects Fold 1.11.4
11074
* http://jqueryui.com
11076
* Copyright jQuery Foundation and other contributors
11077
* Released under the MIT license.
11078
* http://jquery.org/license
11080
* http://api.jqueryui.com/fold-effect/
11084
var effectFold = $.effects.effect.fold = function( o, done ) {
11087
var el = $( this ),
11088
props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
11089
mode = $.effects.setMode( el, o.mode || "hide" ),
11090
show = mode === "show",
11091
hide = mode === "hide",
11092
size = o.size || 15,
11093
percent = /([0-9]+)%/.exec( size ),
11094
horizFirst = !!o.horizFirst,
11095
widthFirst = show !== horizFirst,
11096
ref = widthFirst ? [ "width", "height" ] : [ "height", "width" ],
11097
duration = o.duration / 2,
11102
$.effects.save( el, props );
11106
wrapper = $.effects.createWrapper( el ).css({
11109
distance = widthFirst ?
11110
[ wrapper.width(), wrapper.height() ] :
11111
[ wrapper.height(), wrapper.width() ];
11114
size = parseInt( percent[ 1 ], 10 ) / 100 * distance[ hide ? 0 : 1 ];
11117
wrapper.css( horizFirst ? {
11127
animation1[ ref[ 0 ] ] = show ? distance[ 0 ] : size;
11128
animation2[ ref[ 1 ] ] = show ? distance[ 1 ] : 0;
11132
.animate( animation1, duration, o.easing )
11133
.animate( animation2, duration, o.easing, function() {
11137
$.effects.restore( el, props );
11138
$.effects.removeWrapper( el );
11146
* jQuery UI Effects Highlight 1.11.4
11147
* http://jqueryui.com
11149
* Copyright jQuery Foundation and other contributors
11150
* Released under the MIT license.
11151
* http://jquery.org/license
11153
* http://api.jqueryui.com/highlight-effect/
11157
var effectHighlight = $.effects.effect.highlight = function( o, done ) {
11158
var elem = $( this ),
11159
props = [ "backgroundImage", "backgroundColor", "opacity" ],
11160
mode = $.effects.setMode( elem, o.mode || "show" ),
11162
backgroundColor: elem.css( "backgroundColor" )
11165
if (mode === "hide") {
11166
animation.opacity = 0;
11169
$.effects.save( elem, props );
11174
backgroundImage: "none",
11175
backgroundColor: o.color || "#ffff99"
11177
.animate( animation, {
11179
duration: o.duration,
11181
complete: function() {
11182
if ( mode === "hide" ) {
11185
$.effects.restore( elem, props );
11193
* jQuery UI Effects Size 1.11.4
11194
* http://jqueryui.com
11196
* Copyright jQuery Foundation and other contributors
11197
* Released under the MIT license.
11198
* http://jquery.org/license
11200
* http://api.jqueryui.com/size-effect/
11204
var effectSize = $.effects.effect.size = function( o, done ) {
11207
var original, baseline, factor,
11209
props0 = [ "position", "top", "bottom", "left", "right", "width", "height", "overflow", "opacity" ],
11212
props1 = [ "position", "top", "bottom", "left", "right", "overflow", "opacity" ],
11214
// Copy for children
11215
props2 = [ "width", "height", "overflow" ],
11216
cProps = [ "fontSize" ],
11217
vProps = [ "borderTopWidth", "borderBottomWidth", "paddingTop", "paddingBottom" ],
11218
hProps = [ "borderLeftWidth", "borderRightWidth", "paddingLeft", "paddingRight" ],
11221
mode = $.effects.setMode( el, o.mode || "effect" ),
11222
restore = o.restore || mode !== "effect",
11223
scale = o.scale || "both",
11224
origin = o.origin || [ "middle", "center" ],
11225
position = el.css( "position" ),
11226
props = restore ? props0 : props1,
11234
if ( mode === "show" ) {
11238
height: el.height(),
11240
outerHeight: el.outerHeight(),
11241
outerWidth: el.outerWidth()
11244
if ( o.mode === "toggle" && mode === "show" ) {
11245
el.from = o.to || zero;
11246
el.to = o.from || original;
11248
el.from = o.from || ( mode === "show" ? zero : original );
11249
el.to = o.to || ( mode === "hide" ? zero : original );
11252
// Set scaling factor
11255
y: el.from.height / original.height,
11256
x: el.from.width / original.width
11259
y: el.to.height / original.height,
11260
x: el.to.width / original.width
11264
// Scale the css box
11265
if ( scale === "box" || scale === "both" ) {
11267
// Vertical props scaling
11268
if ( factor.from.y !== factor.to.y ) {
11269
props = props.concat( vProps );
11270
el.from = $.effects.setTransition( el, vProps, factor.from.y, el.from );
11271
el.to = $.effects.setTransition( el, vProps, factor.to.y, el.to );
11274
// Horizontal props scaling
11275
if ( factor.from.x !== factor.to.x ) {
11276
props = props.concat( hProps );
11277
el.from = $.effects.setTransition( el, hProps, factor.from.x, el.from );
11278
el.to = $.effects.setTransition( el, hProps, factor.to.x, el.to );
11282
// Scale the content
11283
if ( scale === "content" || scale === "both" ) {
11285
// Vertical props scaling
11286
if ( factor.from.y !== factor.to.y ) {
11287
props = props.concat( cProps ).concat( props2 );
11288
el.from = $.effects.setTransition( el, cProps, factor.from.y, el.from );
11289
el.to = $.effects.setTransition( el, cProps, factor.to.y, el.to );
11293
$.effects.save( el, props );
11295
$.effects.createWrapper( el );
11296
el.css( "overflow", "hidden" ).css( el.from );
11299
if (origin) { // Calculate baseline shifts
11300
baseline = $.effects.getBaseline( origin, original );
11301
el.from.top = ( original.outerHeight - el.outerHeight() ) * baseline.y;
11302
el.from.left = ( original.outerWidth - el.outerWidth() ) * baseline.x;
11303
el.to.top = ( original.outerHeight - el.to.outerHeight ) * baseline.y;
11304
el.to.left = ( original.outerWidth - el.to.outerWidth ) * baseline.x;
11306
el.css( el.from ); // set top & left
11309
if ( scale === "content" || scale === "both" ) { // Scale the children
11311
// Add margins/font-size
11312
vProps = vProps.concat([ "marginTop", "marginBottom" ]).concat(cProps);
11313
hProps = hProps.concat([ "marginLeft", "marginRight" ]);
11314
props2 = props0.concat(vProps).concat(hProps);
11316
el.find( "*[width]" ).each( function() {
11317
var child = $( this ),
11319
height: child.height(),
11320
width: child.width(),
11321
outerHeight: child.outerHeight(),
11322
outerWidth: child.outerWidth()
11325
$.effects.save(child, props2);
11329
height: c_original.height * factor.from.y,
11330
width: c_original.width * factor.from.x,
11331
outerHeight: c_original.outerHeight * factor.from.y,
11332
outerWidth: c_original.outerWidth * factor.from.x
11335
height: c_original.height * factor.to.y,
11336
width: c_original.width * factor.to.x,
11337
outerHeight: c_original.height * factor.to.y,
11338
outerWidth: c_original.width * factor.to.x
11341
// Vertical props scaling
11342
if ( factor.from.y !== factor.to.y ) {
11343
child.from = $.effects.setTransition( child, vProps, factor.from.y, child.from );
11344
child.to = $.effects.setTransition( child, vProps, factor.to.y, child.to );
11347
// Horizontal props scaling
11348
if ( factor.from.x !== factor.to.x ) {
11349
child.from = $.effects.setTransition( child, hProps, factor.from.x, child.from );
11350
child.to = $.effects.setTransition( child, hProps, factor.to.x, child.to );
11353
// Animate children
11354
child.css( child.from );
11355
child.animate( child.to, o.duration, o.easing, function() {
11357
// Restore children
11359
$.effects.restore( child, props2 );
11366
el.animate( el.to, {
11368
duration: o.duration,
11370
complete: function() {
11371
if ( el.to.opacity === 0 ) {
11372
el.css( "opacity", el.from.opacity );
11374
if ( mode === "hide" ) {
11377
$.effects.restore( el, props );
11380
// we need to calculate our new positioning based on the scaling
11381
if ( position === "static" ) {
11383
position: "relative",
11388
$.each([ "top", "left" ], function( idx, pos ) {
11389
el.css( pos, function( _, str ) {
11390
var val = parseInt( str, 10 ),
11391
toRef = idx ? el.to.left : el.to.top;
11393
// if original was "auto", recalculate the new value from wrapper
11394
if ( str === "auto" ) {
11395
return toRef + "px";
11398
return val + toRef + "px";
11404
$.effects.removeWrapper( el );
11413
* jQuery UI Effects Scale 1.11.4
11414
* http://jqueryui.com
11416
* Copyright jQuery Foundation and other contributors
11417
* Released under the MIT license.
11418
* http://jquery.org/license
11420
* http://api.jqueryui.com/scale-effect/
11424
var effectScale = $.effects.effect.scale = function( o, done ) {
11427
var el = $( this ),
11428
options = $.extend( true, {}, o ),
11429
mode = $.effects.setMode( el, o.mode || "effect" ),
11430
percent = parseInt( o.percent, 10 ) ||
11431
( parseInt( o.percent, 10 ) === 0 ? 0 : ( mode === "hide" ? 0 : 100 ) ),
11432
direction = o.direction || "both",
11435
height: el.height(),
11437
outerHeight: el.outerHeight(),
11438
outerWidth: el.outerWidth()
11441
y: direction !== "horizontal" ? (percent / 100) : 1,
11442
x: direction !== "vertical" ? (percent / 100) : 1
11445
// We are going to pass this effect to the size effect:
11446
options.effect = "size";
11447
options.queue = false;
11448
options.complete = done;
11450
// Set default origin and restore for show/hide
11451
if ( mode !== "effect" ) {
11452
options.origin = origin || [ "middle", "center" ];
11453
options.restore = true;
11456
options.from = o.from || ( mode === "show" ? {
11463
height: original.height * factor.y,
11464
width: original.width * factor.x,
11465
outerHeight: original.outerHeight * factor.y,
11466
outerWidth: original.outerWidth * factor.x
11469
// Fade option to support puff
11470
if ( options.fade ) {
11471
if ( mode === "show" ) {
11472
options.from.opacity = 0;
11473
options.to.opacity = 1;
11475
if ( mode === "hide" ) {
11476
options.from.opacity = 1;
11477
options.to.opacity = 0;
11482
el.effect( options );
11488
* jQuery UI Effects Puff 1.11.4
11489
* http://jqueryui.com
11491
* Copyright jQuery Foundation and other contributors
11492
* Released under the MIT license.
11493
* http://jquery.org/license
11495
* http://api.jqueryui.com/puff-effect/
11499
var effectPuff = $.effects.effect.puff = function( o, done ) {
11500
var elem = $( this ),
11501
mode = $.effects.setMode( elem, o.mode || "hide" ),
11502
hide = mode === "hide",
11503
percent = parseInt( o.percent, 10 ) || 150,
11504
factor = percent / 100,
11506
height: elem.height(),
11507
width: elem.width(),
11508
outerHeight: elem.outerHeight(),
11509
outerWidth: elem.outerWidth()
11518
percent: hide ? percent : 100,
11522
height: original.height * factor,
11523
width: original.width * factor,
11524
outerHeight: original.outerHeight * factor,
11525
outerWidth: original.outerWidth * factor
11534
* jQuery UI Effects Pulsate 1.11.4
11535
* http://jqueryui.com
11537
* Copyright jQuery Foundation and other contributors
11538
* Released under the MIT license.
11539
* http://jquery.org/license
11541
* http://api.jqueryui.com/pulsate-effect/
11545
var effectPulsate = $.effects.effect.pulsate = function( o, done ) {
11546
var elem = $( this ),
11547
mode = $.effects.setMode( elem, o.mode || "show" ),
11548
show = mode === "show",
11549
hide = mode === "hide",
11550
showhide = ( show || mode === "hide" ),
11552
// showing or hiding leaves of the "last" animation
11553
anims = ( ( o.times || 5 ) * 2 ) + ( showhide ? 1 : 0 ),
11554
duration = o.duration / anims,
11556
queue = elem.queue(),
11557
queuelen = queue.length,
11560
if ( show || !elem.is(":visible")) {
11561
elem.css( "opacity", 0 ).show();
11565
// anims - 1 opacity "toggles"
11566
for ( i = 1; i < anims; i++ ) {
11569
}, duration, o.easing );
11570
animateTo = 1 - animateTo;
11575
}, duration, o.easing);
11577
elem.queue(function() {
11584
// We just queued up "anims" animations, we need to put them next in the queue
11585
if ( queuelen > 1 ) {
11586
queue.splice.apply( queue,
11587
[ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) );
11594
* jQuery UI Effects Shake 1.11.4
11595
* http://jqueryui.com
11597
* Copyright jQuery Foundation and other contributors
11598
* Released under the MIT license.
11599
* http://jquery.org/license
11601
* http://api.jqueryui.com/shake-effect/
11605
var effectShake = $.effects.effect.shake = function( o, done ) {
11607
var el = $( this ),
11608
props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
11609
mode = $.effects.setMode( el, o.mode || "effect" ),
11610
direction = o.direction || "left",
11611
distance = o.distance || 20,
11612
times = o.times || 3,
11613
anims = times * 2 + 1,
11614
speed = Math.round( o.duration / anims ),
11615
ref = (direction === "up" || direction === "down") ? "top" : "left",
11616
positiveMotion = (direction === "up" || direction === "left"),
11622
// we will need to re-assemble the queue to stack our animations in place
11623
queue = el.queue(),
11624
queuelen = queue.length;
11626
$.effects.save( el, props );
11628
$.effects.createWrapper( el );
11631
animation[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance;
11632
animation1[ ref ] = ( positiveMotion ? "+=" : "-=" ) + distance * 2;
11633
animation2[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance * 2;
11636
el.animate( animation, speed, o.easing );
11639
for ( i = 1; i < times; i++ ) {
11640
el.animate( animation1, speed, o.easing ).animate( animation2, speed, o.easing );
11643
.animate( animation1, speed, o.easing )
11644
.animate( animation, speed / 2, o.easing )
11645
.queue(function() {
11646
if ( mode === "hide" ) {
11649
$.effects.restore( el, props );
11650
$.effects.removeWrapper( el );
11654
// inject all the animations we just queued to be first in line (after "inprogress")
11655
if ( queuelen > 1) {
11656
queue.splice.apply( queue,
11657
[ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) );
11665
* jQuery UI Effects Slide 1.11.4
11666
* http://jqueryui.com
11668
* Copyright jQuery Foundation and other contributors
11669
* Released under the MIT license.
11670
* http://jquery.org/license
11672
* http://api.jqueryui.com/slide-effect/
11676
var effectSlide = $.effects.effect.slide = function( o, done ) {
11679
var el = $( this ),
11680
props = [ "position", "top", "bottom", "left", "right", "width", "height" ],
11681
mode = $.effects.setMode( el, o.mode || "show" ),
11682
show = mode === "show",
11683
direction = o.direction || "left",
11684
ref = (direction === "up" || direction === "down") ? "top" : "left",
11685
positiveMotion = (direction === "up" || direction === "left"),
11690
$.effects.save( el, props );
11692
distance = o.distance || el[ ref === "top" ? "outerHeight" : "outerWidth" ]( true );
11694
$.effects.createWrapper( el ).css({
11699
el.css( ref, positiveMotion ? (isNaN(distance) ? "-" + distance : -distance) : distance );
11703
animation[ ref ] = ( show ?
11704
( positiveMotion ? "+=" : "-=") :
11705
( positiveMotion ? "-=" : "+=")) +
11709
el.animate( animation, {
11711
duration: o.duration,
11713
complete: function() {
11714
if ( mode === "hide" ) {
11717
$.effects.restore( el, props );
11718
$.effects.removeWrapper( el );
11726
* jQuery UI Effects Transfer 1.11.4
11727
* http://jqueryui.com
11729
* Copyright jQuery Foundation and other contributors
11730
* Released under the MIT license.
11731
* http://jquery.org/license
11733
* http://api.jqueryui.com/transfer-effect/
11737
var effectTransfer = $.effects.effect.transfer = function( o, done ) {
11738
var elem = $( this ),
11739
target = $( o.to ),
11740
targetFixed = target.css( "position" ) === "fixed",
11742
fixTop = targetFixed ? body.scrollTop() : 0,
11743
fixLeft = targetFixed ? body.scrollLeft() : 0,
11744
endPosition = target.offset(),
11746
top: endPosition.top - fixTop,
11747
left: endPosition.left - fixLeft,
11748
height: target.innerHeight(),
11749
width: target.innerWidth()
11751
startPosition = elem.offset(),
11752
transfer = $( "<div class='ui-effects-transfer'></div>" )
11753
.appendTo( document.body )
11754
.addClass( o.className )
11756
top: startPosition.top - fixTop,
11757
left: startPosition.left - fixLeft,
11758
height: elem.innerHeight(),
11759
width: elem.innerWidth(),
11760
position: targetFixed ? "fixed" : "absolute"
11762
.animate( animation, o.duration, o.easing, function() {
11770
* jQuery UI Progressbar 1.11.4
11771
* http://jqueryui.com
11773
* Copyright jQuery Foundation and other contributors
11774
* Released under the MIT license.
11775
* http://jquery.org/license
11777
* http://api.jqueryui.com/progressbar/
11781
var progressbar = $.widget( "ui.progressbar", {
11793
_create: function() {
11794
// Constrain initial value
11795
this.oldValue = this.options.value = this._constrainedValue();
11798
.addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
11800
// Only set static values, aria-valuenow and aria-valuemax are
11801
// set inside _refreshValue()
11802
role: "progressbar",
11803
"aria-valuemin": this.min
11806
this.valueDiv = $( "<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>" )
11807
.appendTo( this.element );
11809
this._refreshValue();
11812
_destroy: function() {
11814
.removeClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
11815
.removeAttr( "role" )
11816
.removeAttr( "aria-valuemin" )
11817
.removeAttr( "aria-valuemax" )
11818
.removeAttr( "aria-valuenow" );
11820
this.valueDiv.remove();
11823
value: function( newValue ) {
11824
if ( newValue === undefined ) {
11825
return this.options.value;
11828
this.options.value = this._constrainedValue( newValue );
11829
this._refreshValue();
11832
_constrainedValue: function( newValue ) {
11833
if ( newValue === undefined ) {
11834
newValue = this.options.value;
11837
this.indeterminate = newValue === false;
11840
if ( typeof newValue !== "number" ) {
11844
return this.indeterminate ? false :
11845
Math.min( this.options.max, Math.max( this.min, newValue ) );
11848
_setOptions: function( options ) {
11849
// Ensure "value" option is set after other values (like max)
11850
var value = options.value;
11851
delete options.value;
11853
this._super( options );
11855
this.options.value = this._constrainedValue( value );
11856
this._refreshValue();
11859
_setOption: function( key, value ) {
11860
if ( key === "max" ) {
11861
// Don't allow a max less than min
11862
value = Math.max( this.min, value );
11864
if ( key === "disabled" ) {
11866
.toggleClass( "ui-state-disabled", !!value )
11867
.attr( "aria-disabled", value );
11869
this._super( key, value );
11872
_percentage: function() {
11873
return this.indeterminate ? 100 : 100 * ( this.options.value - this.min ) / ( this.options.max - this.min );
11876
_refreshValue: function() {
11877
var value = this.options.value,
11878
percentage = this._percentage();
11881
.toggle( this.indeterminate || value > this.min )
11882
.toggleClass( "ui-corner-right", value === this.options.max )
11883
.width( percentage.toFixed(0) + "%" );
11885
this.element.toggleClass( "ui-progressbar-indeterminate", this.indeterminate );
11887
if ( this.indeterminate ) {
11888
this.element.removeAttr( "aria-valuenow" );
11889
if ( !this.overlayDiv ) {
11890
this.overlayDiv = $( "<div class='ui-progressbar-overlay'></div>" ).appendTo( this.valueDiv );
11893
this.element.attr({
11894
"aria-valuemax": this.options.max,
11895
"aria-valuenow": value
11897
if ( this.overlayDiv ) {
11898
this.overlayDiv.remove();
11899
this.overlayDiv = null;
11903
if ( this.oldValue !== value ) {
11904
this.oldValue = value;
11905
this._trigger( "change" );
11907
if ( value === this.options.max ) {
11908
this._trigger( "complete" );
11915
* jQuery UI Selectable 1.11.4
11916
* http://jqueryui.com
11918
* Copyright jQuery Foundation and other contributors
11919
* Released under the MIT license.
11920
* http://jquery.org/license
11922
* http://api.jqueryui.com/selectable/
11926
var selectable = $.widget("ui.selectable", $.ui.mouse, {
11933
tolerance: "touch",
11943
_create: function() {
11947
this.element.addClass("ui-selectable");
11949
this.dragged = false;
11951
// cache selectee children based on filter
11952
this.refresh = function() {
11953
selectees = $(that.options.filter, that.element[0]);
11954
selectees.addClass("ui-selectee");
11955
selectees.each(function() {
11956
var $this = $(this),
11957
pos = $this.offset();
11958
$.data(this, "selectable-item", {
11963
right: pos.left + $this.outerWidth(),
11964
bottom: pos.top + $this.outerHeight(),
11965
startselected: false,
11966
selected: $this.hasClass("ui-selected"),
11967
selecting: $this.hasClass("ui-selecting"),
11968
unselecting: $this.hasClass("ui-unselecting")
11974
this.selectees = selectees.addClass("ui-selectee");
11978
this.helper = $("<div class='ui-selectable-helper'></div>");
11981
_destroy: function() {
11983
.removeClass("ui-selectee")
11984
.removeData("selectable-item");
11986
.removeClass("ui-selectable ui-selectable-disabled");
11987
this._mouseDestroy();
11990
_mouseStart: function(event) {
11992
options = this.options;
11994
this.opos = [ event.pageX, event.pageY ];
11996
if (this.options.disabled) {
12000
this.selectees = $(options.filter, this.element[0]);
12002
this._trigger("start", event);
12004
$(options.appendTo).append(this.helper);
12005
// position helper (lasso)
12007
"left": event.pageX,
12008
"top": event.pageY,
12013
if (options.autoRefresh) {
12017
this.selectees.filter(".ui-selected").each(function() {
12018
var selectee = $.data(this, "selectable-item");
12019
selectee.startselected = true;
12020
if (!event.metaKey && !event.ctrlKey) {
12021
selectee.$element.removeClass("ui-selected");
12022
selectee.selected = false;
12023
selectee.$element.addClass("ui-unselecting");
12024
selectee.unselecting = true;
12025
// selectable UNSELECTING callback
12026
that._trigger("unselecting", event, {
12027
unselecting: selectee.element
12032
$(event.target).parents().addBack().each(function() {
12034
selectee = $.data(this, "selectable-item");
12036
doSelect = (!event.metaKey && !event.ctrlKey) || !selectee.$element.hasClass("ui-selected");
12038
.removeClass(doSelect ? "ui-unselecting" : "ui-selected")
12039
.addClass(doSelect ? "ui-selecting" : "ui-unselecting");
12040
selectee.unselecting = !doSelect;
12041
selectee.selecting = doSelect;
12042
selectee.selected = doSelect;
12043
// selectable (UN)SELECTING callback
12045
that._trigger("selecting", event, {
12046
selecting: selectee.element
12049
that._trigger("unselecting", event, {
12050
unselecting: selectee.element
12059
_mouseDrag: function(event) {
12061
this.dragged = true;
12063
if (this.options.disabled) {
12069
options = this.options,
12075
if (x1 > x2) { tmp = x2; x2 = x1; x1 = tmp; }
12076
if (y1 > y2) { tmp = y2; y2 = y1; y1 = tmp; }
12077
this.helper.css({ left: x1, top: y1, width: x2 - x1, height: y2 - y1 });
12079
this.selectees.each(function() {
12080
var selectee = $.data(this, "selectable-item"),
12083
//prevent helper from being selected if appendTo: selectable
12084
if (!selectee || selectee.element === that.element[0]) {
12088
if (options.tolerance === "touch") {
12089
hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) );
12090
} else if (options.tolerance === "fit") {
12091
hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2);
12096
if (selectee.selected) {
12097
selectee.$element.removeClass("ui-selected");
12098
selectee.selected = false;
12100
if (selectee.unselecting) {
12101
selectee.$element.removeClass("ui-unselecting");
12102
selectee.unselecting = false;
12104
if (!selectee.selecting) {
12105
selectee.$element.addClass("ui-selecting");
12106
selectee.selecting = true;
12107
// selectable SELECTING callback
12108
that._trigger("selecting", event, {
12109
selecting: selectee.element
12114
if (selectee.selecting) {
12115
if ((event.metaKey || event.ctrlKey) && selectee.startselected) {
12116
selectee.$element.removeClass("ui-selecting");
12117
selectee.selecting = false;
12118
selectee.$element.addClass("ui-selected");
12119
selectee.selected = true;
12121
selectee.$element.removeClass("ui-selecting");
12122
selectee.selecting = false;
12123
if (selectee.startselected) {
12124
selectee.$element.addClass("ui-unselecting");
12125
selectee.unselecting = true;
12127
// selectable UNSELECTING callback
12128
that._trigger("unselecting", event, {
12129
unselecting: selectee.element
12133
if (selectee.selected) {
12134
if (!event.metaKey && !event.ctrlKey && !selectee.startselected) {
12135
selectee.$element.removeClass("ui-selected");
12136
selectee.selected = false;
12138
selectee.$element.addClass("ui-unselecting");
12139
selectee.unselecting = true;
12140
// selectable UNSELECTING callback
12141
that._trigger("unselecting", event, {
12142
unselecting: selectee.element
12152
_mouseStop: function(event) {
12155
this.dragged = false;
12157
$(".ui-unselecting", this.element[0]).each(function() {
12158
var selectee = $.data(this, "selectable-item");
12159
selectee.$element.removeClass("ui-unselecting");
12160
selectee.unselecting = false;
12161
selectee.startselected = false;
12162
that._trigger("unselected", event, {
12163
unselected: selectee.element
12166
$(".ui-selecting", this.element[0]).each(function() {
12167
var selectee = $.data(this, "selectable-item");
12168
selectee.$element.removeClass("ui-selecting").addClass("ui-selected");
12169
selectee.selecting = false;
12170
selectee.selected = true;
12171
selectee.startselected = true;
12172
that._trigger("selected", event, {
12173
selected: selectee.element
12176
this._trigger("stop", event);
12178
this.helper.remove();
12187
* jQuery UI Selectmenu 1.11.4
12188
* http://jqueryui.com
12190
* Copyright jQuery Foundation and other contributors
12191
* Released under the MIT license.
12192
* http://jquery.org/license
12194
* http://api.jqueryui.com/selectmenu
12198
var selectmenu = $.widget( "ui.selectmenu", {
12200
defaultElement: "<select>",
12205
button: "ui-icon-triangle-1-s"
12222
_create: function() {
12223
var selectmenuId = this.element.uniqueId().attr( "id" );
12225
element: selectmenuId,
12226
button: selectmenuId + "-button",
12227
menu: selectmenuId + "-menu"
12230
this._drawButton();
12233
if ( this.options.disabled ) {
12238
_drawButton: function() {
12241
// Associate existing label with the new button
12242
this.label = $( "label[for='" + this.ids.element + "']" ).attr( "for", this.ids.button );
12243
this._on( this.label, {
12244
click: function( event ) {
12245
this.button.focus();
12246
event.preventDefault();
12250
// Hide original select element
12251
this.element.hide();
12254
this.button = $( "<span>", {
12255
"class": "ui-selectmenu-button ui-widget ui-state-default ui-corner-all",
12256
tabindex: this.options.disabled ? -1 : 0,
12257
id: this.ids.button,
12259
"aria-expanded": "false",
12260
"aria-autocomplete": "list",
12261
"aria-owns": this.ids.menu,
12262
"aria-haspopup": "true"
12264
.insertAfter( this.element );
12267
"class": "ui-icon " + this.options.icons.button
12269
.prependTo( this.button );
12271
this.buttonText = $( "<span>", {
12272
"class": "ui-selectmenu-text"
12274
.appendTo( this.button );
12276
this._setText( this.buttonText, this.element.find( "option:selected" ).text() );
12277
this._resizeButton();
12279
this._on( this.button, this._buttonEvents );
12280
this.button.one( "focusin", function() {
12282
// Delay rendering the menu items until the button receives focus.
12283
// The menu may have already been rendered via a programmatic open.
12284
if ( !that.menuItems ) {
12285
that._refreshMenu();
12288
this._hoverable( this.button );
12289
this._focusable( this.button );
12292
_drawMenu: function() {
12296
this.menu = $( "<ul>", {
12297
"aria-hidden": "true",
12298
"aria-labelledby": this.ids.button,
12303
this.menuWrap = $( "<div>", {
12304
"class": "ui-selectmenu-menu ui-front"
12306
.append( this.menu )
12307
.appendTo( this._appendTo() );
12309
// Initialize menu widget
12310
this.menuInstance = this.menu
12313
select: function( event, ui ) {
12314
event.preventDefault();
12317
// If the item was selected via a click, the text selection
12318
// will be destroyed in IE
12319
that._setSelection();
12321
that._select( ui.item.data( "ui-selectmenu-item" ), event );
12323
focus: function( event, ui ) {
12324
var item = ui.item.data( "ui-selectmenu-item" );
12326
// Prevent inital focus from firing and check if its a newly focused item
12327
if ( that.focusIndex != null && item.index !== that.focusIndex ) {
12328
that._trigger( "focus", event, { item: item } );
12329
if ( !that.isOpen ) {
12330
that._select( item, event );
12333
that.focusIndex = item.index;
12335
that.button.attr( "aria-activedescendant",
12336
that.menuItems.eq( item.index ).attr( "id" ) );
12339
.menu( "instance" );
12341
// Adjust menu styles to dropdown
12343
.addClass( "ui-corner-bottom" )
12344
.removeClass( "ui-corner-all" );
12346
// Don't close the menu on mouseleave
12347
this.menuInstance._off( this.menu, "mouseleave" );
12349
// Cancel the menu's collapseAll on document click
12350
this.menuInstance._closeOnDocumentClick = function() {
12354
// Selects often contain empty items, but never contain dividers
12355
this.menuInstance._isDivider = function() {
12360
refresh: function() {
12361
this._refreshMenu();
12362
this._setText( this.buttonText, this._getSelectedItem().text() );
12363
if ( !this.options.width ) {
12364
this._resizeButton();
12368
_refreshMenu: function() {
12372
options = this.element.find( "option" );
12374
if ( !options.length ) {
12378
this._parseOptions( options );
12379
this._renderMenu( this.menu, this.items );
12381
this.menuInstance.refresh();
12382
this.menuItems = this.menu.find( "li" ).not( ".ui-selectmenu-optgroup" );
12384
item = this._getSelectedItem();
12386
// Update the menu to have the correct item focused
12387
this.menuInstance.focus( null, item );
12388
this._setAria( item.data( "ui-selectmenu-item" ) );
12390
// Set disabled state
12391
this._setOption( "disabled", this.element.prop( "disabled" ) );
12394
open: function( event ) {
12395
if ( this.options.disabled ) {
12399
// If this is the first time the menu is being opened, render the items
12400
if ( !this.menuItems ) {
12401
this._refreshMenu();
12404
// Menu clears focus on close, reset focus to selected item
12405
this.menu.find( ".ui-state-focus" ).removeClass( "ui-state-focus" );
12406
this.menuInstance.focus( null, this._getSelectedItem() );
12409
this.isOpen = true;
12410
this._toggleAttr();
12411
this._resizeMenu();
12414
this._on( this.document, this._documentClick );
12416
this._trigger( "open", event );
12419
_position: function() {
12420
this.menuWrap.position( $.extend( { of: this.button }, this.options.position ) );
12423
close: function( event ) {
12424
if ( !this.isOpen ) {
12428
this.isOpen = false;
12429
this._toggleAttr();
12432
this._off( this.document );
12434
this._trigger( "close", event );
12437
widget: function() {
12438
return this.button;
12441
menuWidget: function() {
12445
_renderMenu: function( ul, items ) {
12447
currentOptgroup = "";
12449
$.each( items, function( index, item ) {
12450
if ( item.optgroup !== currentOptgroup ) {
12452
"class": "ui-selectmenu-optgroup ui-menu-divider" +
12453
( item.element.parent( "optgroup" ).prop( "disabled" ) ?
12454
" ui-state-disabled" :
12456
text: item.optgroup
12460
currentOptgroup = item.optgroup;
12463
that._renderItemData( ul, item );
12467
_renderItemData: function( ul, item ) {
12468
return this._renderItem( ul, item ).data( "ui-selectmenu-item", item );
12471
_renderItem: function( ul, item ) {
12472
var li = $( "<li>" );
12474
if ( item.disabled ) {
12475
li.addClass( "ui-state-disabled" );
12477
this._setText( li, item.label );
12479
return li.appendTo( ul );
12482
_setText: function( element, value ) {
12484
element.text( value );
12486
element.html( " " );
12490
_move: function( direction, event ) {
12492
filter = ".ui-menu-item";
12494
if ( this.isOpen ) {
12495
item = this.menuItems.eq( this.focusIndex );
12497
item = this.menuItems.eq( this.element[ 0 ].selectedIndex );
12498
filter += ":not(.ui-state-disabled)";
12501
if ( direction === "first" || direction === "last" ) {
12502
next = item[ direction === "first" ? "prevAll" : "nextAll" ]( filter ).eq( -1 );
12504
next = item[ direction + "All" ]( filter ).eq( 0 );
12507
if ( next.length ) {
12508
this.menuInstance.focus( event, next );
12512
_getSelectedItem: function() {
12513
return this.menuItems.eq( this.element[ 0 ].selectedIndex );
12516
_toggle: function( event ) {
12517
this[ this.isOpen ? "close" : "open" ]( event );
12520
_setSelection: function() {
12523
if ( !this.range ) {
12527
if ( window.getSelection ) {
12528
selection = window.getSelection();
12529
selection.removeAllRanges();
12530
selection.addRange( this.range );
12534
this.range.select();
12538
// Setting the text selection kills the button focus in IE, but
12539
// restoring the focus doesn't kill the selection.
12540
this.button.focus();
12544
mousedown: function( event ) {
12545
if ( !this.isOpen ) {
12549
if ( !$( event.target ).closest( ".ui-selectmenu-menu, #" + this.ids.button ).length ) {
12550
this.close( event );
12557
// Prevent text selection from being reset when interacting with the selectmenu (#10144)
12558
mousedown: function() {
12561
if ( window.getSelection ) {
12562
selection = window.getSelection();
12563
if ( selection.rangeCount ) {
12564
this.range = selection.getRangeAt( 0 );
12569
this.range = document.selection.createRange();
12573
click: function( event ) {
12574
this._setSelection();
12575
this._toggle( event );
12578
keydown: function( event ) {
12579
var preventDefault = true;
12580
switch ( event.keyCode ) {
12581
case $.ui.keyCode.TAB:
12582
case $.ui.keyCode.ESCAPE:
12583
this.close( event );
12584
preventDefault = false;
12586
case $.ui.keyCode.ENTER:
12587
if ( this.isOpen ) {
12588
this._selectFocusedItem( event );
12591
case $.ui.keyCode.UP:
12592
if ( event.altKey ) {
12593
this._toggle( event );
12595
this._move( "prev", event );
12598
case $.ui.keyCode.DOWN:
12599
if ( event.altKey ) {
12600
this._toggle( event );
12602
this._move( "next", event );
12605
case $.ui.keyCode.SPACE:
12606
if ( this.isOpen ) {
12607
this._selectFocusedItem( event );
12609
this._toggle( event );
12612
case $.ui.keyCode.LEFT:
12613
this._move( "prev", event );
12615
case $.ui.keyCode.RIGHT:
12616
this._move( "next", event );
12618
case $.ui.keyCode.HOME:
12619
case $.ui.keyCode.PAGE_UP:
12620
this._move( "first", event );
12622
case $.ui.keyCode.END:
12623
case $.ui.keyCode.PAGE_DOWN:
12624
this._move( "last", event );
12627
this.menu.trigger( event );
12628
preventDefault = false;
12631
if ( preventDefault ) {
12632
event.preventDefault();
12637
_selectFocusedItem: function( event ) {
12638
var item = this.menuItems.eq( this.focusIndex );
12639
if ( !item.hasClass( "ui-state-disabled" ) ) {
12640
this._select( item.data( "ui-selectmenu-item" ), event );
12644
_select: function( item, event ) {
12645
var oldIndex = this.element[ 0 ].selectedIndex;
12647
// Change native select element
12648
this.element[ 0 ].selectedIndex = item.index;
12649
this._setText( this.buttonText, item.label );
12650
this._setAria( item );
12651
this._trigger( "select", event, { item: item } );
12653
if ( item.index !== oldIndex ) {
12654
this._trigger( "change", event, { item: item } );
12657
this.close( event );
12660
_setAria: function( item ) {
12661
var id = this.menuItems.eq( item.index ).attr( "id" );
12664
"aria-labelledby": id,
12665
"aria-activedescendant": id
12667
this.menu.attr( "aria-activedescendant", id );
12670
_setOption: function( key, value ) {
12671
if ( key === "icons" ) {
12672
this.button.find( "span.ui-icon" )
12673
.removeClass( this.options.icons.button )
12674
.addClass( value.button );
12677
this._super( key, value );
12679
if ( key === "appendTo" ) {
12680
this.menuWrap.appendTo( this._appendTo() );
12683
if ( key === "disabled" ) {
12684
this.menuInstance.option( "disabled", value );
12686
.toggleClass( "ui-state-disabled", value )
12687
.attr( "aria-disabled", value );
12689
this.element.prop( "disabled", value );
12691
this.button.attr( "tabindex", -1 );
12694
this.button.attr( "tabindex", 0 );
12698
if ( key === "width" ) {
12699
this._resizeButton();
12703
_appendTo: function() {
12704
var element = this.options.appendTo;
12707
element = element.jquery || element.nodeType ?
12709
this.document.find( element ).eq( 0 );
12712
if ( !element || !element[ 0 ] ) {
12713
element = this.element.closest( ".ui-front" );
12716
if ( !element.length ) {
12717
element = this.document[ 0 ].body;
12723
_toggleAttr: function() {
12725
.toggleClass( "ui-corner-top", this.isOpen )
12726
.toggleClass( "ui-corner-all", !this.isOpen )
12727
.attr( "aria-expanded", this.isOpen );
12728
this.menuWrap.toggleClass( "ui-selectmenu-open", this.isOpen );
12729
this.menu.attr( "aria-hidden", !this.isOpen );
12732
_resizeButton: function() {
12733
var width = this.options.width;
12736
width = this.element.show().outerWidth();
12737
this.element.hide();
12740
this.button.outerWidth( width );
12743
_resizeMenu: function() {
12744
this.menu.outerWidth( Math.max(
12745
this.button.outerWidth(),
12748
// IE10 wraps long text (possibly a rounding bug)
12749
// so we add 1px to avoid the wrapping
12750
this.menu.width( "" ).outerWidth() + 1
12754
_getCreateOptions: function() {
12755
return { disabled: this.element.prop( "disabled" ) };
12758
_parseOptions: function( options ) {
12760
options.each(function( index, item ) {
12761
var option = $( item ),
12762
optgroup = option.parent( "optgroup" );
12766
value: option.val(),
12767
label: option.text(),
12768
optgroup: optgroup.attr( "label" ) || "",
12769
disabled: optgroup.prop( "disabled" ) || option.prop( "disabled" )
12775
_destroy: function() {
12776
this.menuWrap.remove();
12777
this.button.remove();
12778
this.element.show();
12779
this.element.removeUniqueId();
12780
this.label.attr( "for", this.ids.element );
12786
* jQuery UI Slider 1.11.4
12787
* http://jqueryui.com
12789
* Copyright jQuery Foundation and other contributors
12790
* Released under the MIT license.
12791
* http://jquery.org/license
12793
* http://api.jqueryui.com/slider/
12797
var slider = $.widget( "ui.slider", $.ui.mouse, {
12799
widgetEventPrefix: "slide",
12806
orientation: "horizontal",
12819
// number of pages in a slider
12820
// (how many times can you page up/down to go through the whole range)
12823
_create: function() {
12824
this._keySliding = false;
12825
this._mouseSliding = false;
12826
this._animateOff = true;
12827
this._handleIndex = null;
12828
this._detectOrientation();
12830
this._calculateNewMax();
12833
.addClass( "ui-slider" +
12834
" ui-slider-" + this.orientation +
12836
" ui-widget-content" +
12840
this._setOption( "disabled", this.options.disabled );
12842
this._animateOff = false;
12845
_refresh: function() {
12846
this._createRange();
12847
this._createHandles();
12848
this._setupEvents();
12849
this._refreshValue();
12852
_createHandles: function() {
12853
var i, handleCount,
12854
options = this.options,
12855
existingHandles = this.element.find( ".ui-slider-handle" ).addClass( "ui-state-default ui-corner-all" ),
12856
handle = "<span class='ui-slider-handle ui-state-default ui-corner-all' tabindex='0'></span>",
12859
handleCount = ( options.values && options.values.length ) || 1;
12861
if ( existingHandles.length > handleCount ) {
12862
existingHandles.slice( handleCount ).remove();
12863
existingHandles = existingHandles.slice( 0, handleCount );
12866
for ( i = existingHandles.length; i < handleCount; i++ ) {
12867
handles.push( handle );
12870
this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( this.element ) );
12872
this.handle = this.handles.eq( 0 );
12874
this.handles.each(function( i ) {
12875
$( this ).data( "ui-slider-handle-index", i );
12879
_createRange: function() {
12880
var options = this.options,
12883
if ( options.range ) {
12884
if ( options.range === true ) {
12885
if ( !options.values ) {
12886
options.values = [ this._valueMin(), this._valueMin() ];
12887
} else if ( options.values.length && options.values.length !== 2 ) {
12888
options.values = [ options.values[0], options.values[0] ];
12889
} else if ( $.isArray( options.values ) ) {
12890
options.values = options.values.slice(0);
12894
if ( !this.range || !this.range.length ) {
12895
this.range = $( "<div></div>" )
12896
.appendTo( this.element );
12898
classes = "ui-slider-range" +
12899
// note: this isn't the most fittingly semantic framework class for this element,
12900
// but worked best visually with a variety of themes
12901
" ui-widget-header ui-corner-all";
12903
this.range.removeClass( "ui-slider-range-min ui-slider-range-max" )
12904
// Handle range switching from true to min/max
12911
this.range.addClass( classes +
12912
( ( options.range === "min" || options.range === "max" ) ? " ui-slider-range-" + options.range : "" ) );
12914
if ( this.range ) {
12915
this.range.remove();
12921
_setupEvents: function() {
12922
this._off( this.handles );
12923
this._on( this.handles, this._handleEvents );
12924
this._hoverable( this.handles );
12925
this._focusable( this.handles );
12928
_destroy: function() {
12929
this.handles.remove();
12930
if ( this.range ) {
12931
this.range.remove();
12935
.removeClass( "ui-slider" +
12936
" ui-slider-horizontal" +
12937
" ui-slider-vertical" +
12939
" ui-widget-content" +
12940
" ui-corner-all" );
12942
this._mouseDestroy();
12945
_mouseCapture: function( event ) {
12946
var position, normValue, distance, closestHandle, index, allowed, offset, mouseOverHandle,
12950
if ( o.disabled ) {
12954
this.elementSize = {
12955
width: this.element.outerWidth(),
12956
height: this.element.outerHeight()
12958
this.elementOffset = this.element.offset();
12960
position = { x: event.pageX, y: event.pageY };
12961
normValue = this._normValueFromMouse( position );
12962
distance = this._valueMax() - this._valueMin() + 1;
12963
this.handles.each(function( i ) {
12964
var thisDistance = Math.abs( normValue - that.values(i) );
12965
if (( distance > thisDistance ) ||
12966
( distance === thisDistance &&
12967
(i === that._lastChangedValue || that.values(i) === o.min ))) {
12968
distance = thisDistance;
12969
closestHandle = $( this );
12974
allowed = this._start( event, index );
12975
if ( allowed === false ) {
12978
this._mouseSliding = true;
12980
this._handleIndex = index;
12983
.addClass( "ui-state-active" )
12986
offset = closestHandle.offset();
12987
mouseOverHandle = !$( event.target ).parents().addBack().is( ".ui-slider-handle" );
12988
this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
12989
left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
12990
top: event.pageY - offset.top -
12991
( closestHandle.height() / 2 ) -
12992
( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) -
12993
( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) +
12994
( parseInt( closestHandle.css("marginTop"), 10 ) || 0)
12997
if ( !this.handles.hasClass( "ui-state-hover" ) ) {
12998
this._slide( event, index, normValue );
13000
this._animateOff = true;
13004
_mouseStart: function() {
13008
_mouseDrag: function( event ) {
13009
var position = { x: event.pageX, y: event.pageY },
13010
normValue = this._normValueFromMouse( position );
13012
this._slide( event, this._handleIndex, normValue );
13017
_mouseStop: function( event ) {
13018
this.handles.removeClass( "ui-state-active" );
13019
this._mouseSliding = false;
13021
this._stop( event, this._handleIndex );
13022
this._change( event, this._handleIndex );
13024
this._handleIndex = null;
13025
this._clickOffset = null;
13026
this._animateOff = false;
13031
_detectOrientation: function() {
13032
this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
13035
_normValueFromMouse: function( position ) {
13042
if ( this.orientation === "horizontal" ) {
13043
pixelTotal = this.elementSize.width;
13044
pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 );
13046
pixelTotal = this.elementSize.height;
13047
pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 );
13050
percentMouse = ( pixelMouse / pixelTotal );
13051
if ( percentMouse > 1 ) {
13054
if ( percentMouse < 0 ) {
13057
if ( this.orientation === "vertical" ) {
13058
percentMouse = 1 - percentMouse;
13061
valueTotal = this._valueMax() - this._valueMin();
13062
valueMouse = this._valueMin() + percentMouse * valueTotal;
13064
return this._trimAlignValue( valueMouse );
13067
_start: function( event, index ) {
13069
handle: this.handles[ index ],
13070
value: this.value()
13072
if ( this.options.values && this.options.values.length ) {
13073
uiHash.value = this.values( index );
13074
uiHash.values = this.values();
13076
return this._trigger( "start", event, uiHash );
13079
_slide: function( event, index, newVal ) {
13084
if ( this.options.values && this.options.values.length ) {
13085
otherVal = this.values( index ? 0 : 1 );
13087
if ( ( this.options.values.length === 2 && this.options.range === true ) &&
13088
( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) )
13093
if ( newVal !== this.values( index ) ) {
13094
newValues = this.values();
13095
newValues[ index ] = newVal;
13096
// A slide can be canceled by returning false from the slide callback
13097
allowed = this._trigger( "slide", event, {
13098
handle: this.handles[ index ],
13102
otherVal = this.values( index ? 0 : 1 );
13103
if ( allowed !== false ) {
13104
this.values( index, newVal );
13108
if ( newVal !== this.value() ) {
13109
// A slide can be canceled by returning false from the slide callback
13110
allowed = this._trigger( "slide", event, {
13111
handle: this.handles[ index ],
13114
if ( allowed !== false ) {
13115
this.value( newVal );
13121
_stop: function( event, index ) {
13123
handle: this.handles[ index ],
13124
value: this.value()
13126
if ( this.options.values && this.options.values.length ) {
13127
uiHash.value = this.values( index );
13128
uiHash.values = this.values();
13131
this._trigger( "stop", event, uiHash );
13134
_change: function( event, index ) {
13135
if ( !this._keySliding && !this._mouseSliding ) {
13137
handle: this.handles[ index ],
13138
value: this.value()
13140
if ( this.options.values && this.options.values.length ) {
13141
uiHash.value = this.values( index );
13142
uiHash.values = this.values();
13145
//store the last changed value index for reference when handles overlap
13146
this._lastChangedValue = index;
13148
this._trigger( "change", event, uiHash );
13152
value: function( newValue ) {
13153
if ( arguments.length ) {
13154
this.options.value = this._trimAlignValue( newValue );
13155
this._refreshValue();
13156
this._change( null, 0 );
13160
return this._value();
13163
values: function( index, newValue ) {
13168
if ( arguments.length > 1 ) {
13169
this.options.values[ index ] = this._trimAlignValue( newValue );
13170
this._refreshValue();
13171
this._change( null, index );
13175
if ( arguments.length ) {
13176
if ( $.isArray( arguments[ 0 ] ) ) {
13177
vals = this.options.values;
13178
newValues = arguments[ 0 ];
13179
for ( i = 0; i < vals.length; i += 1 ) {
13180
vals[ i ] = this._trimAlignValue( newValues[ i ] );
13181
this._change( null, i );
13183
this._refreshValue();
13185
if ( this.options.values && this.options.values.length ) {
13186
return this._values( index );
13188
return this.value();
13192
return this._values();
13196
_setOption: function( key, value ) {
13200
if ( key === "range" && this.options.range === true ) {
13201
if ( value === "min" ) {
13202
this.options.value = this._values( 0 );
13203
this.options.values = null;
13204
} else if ( value === "max" ) {
13205
this.options.value = this._values( this.options.values.length - 1 );
13206
this.options.values = null;
13210
if ( $.isArray( this.options.values ) ) {
13211
valsLength = this.options.values.length;
13214
if ( key === "disabled" ) {
13215
this.element.toggleClass( "ui-state-disabled", !!value );
13218
this._super( key, value );
13221
case "orientation":
13222
this._detectOrientation();
13224
.removeClass( "ui-slider-horizontal ui-slider-vertical" )
13225
.addClass( "ui-slider-" + this.orientation );
13226
this._refreshValue();
13228
// Reset positioning from previous orientation
13229
this.handles.css( value === "horizontal" ? "bottom" : "left", "" );
13232
this._animateOff = true;
13233
this._refreshValue();
13234
this._change( null, 0 );
13235
this._animateOff = false;
13238
this._animateOff = true;
13239
this._refreshValue();
13240
for ( i = 0; i < valsLength; i += 1 ) {
13241
this._change( null, i );
13243
this._animateOff = false;
13248
this._animateOff = true;
13249
this._calculateNewMax();
13250
this._refreshValue();
13251
this._animateOff = false;
13254
this._animateOff = true;
13256
this._animateOff = false;
13261
//internal value getter
13262
// _value() returns value trimmed by min and max, aligned by step
13263
_value: function() {
13264
var val = this.options.value;
13265
val = this._trimAlignValue( val );
13270
//internal values getter
13271
// _values() returns array of values trimmed by min and max, aligned by step
13272
// _values( index ) returns single value trimmed by min and max, aligned by step
13273
_values: function( index ) {
13278
if ( arguments.length ) {
13279
val = this.options.values[ index ];
13280
val = this._trimAlignValue( val );
13283
} else if ( this.options.values && this.options.values.length ) {
13284
// .slice() creates a copy of the array
13285
// this copy gets trimmed by min and max and then returned
13286
vals = this.options.values.slice();
13287
for ( i = 0; i < vals.length; i += 1) {
13288
vals[ i ] = this._trimAlignValue( vals[ i ] );
13297
// returns the step-aligned value that val is closest to, between (inclusive) min and max
13298
_trimAlignValue: function( val ) {
13299
if ( val <= this._valueMin() ) {
13300
return this._valueMin();
13302
if ( val >= this._valueMax() ) {
13303
return this._valueMax();
13305
var step = ( this.options.step > 0 ) ? this.options.step : 1,
13306
valModStep = (val - this._valueMin()) % step,
13307
alignValue = val - valModStep;
13309
if ( Math.abs(valModStep) * 2 >= step ) {
13310
alignValue += ( valModStep > 0 ) ? step : ( -step );
13313
// Since JavaScript has problems with large floats, round
13314
// the final value to 5 digits after the decimal point (see #4124)
13315
return parseFloat( alignValue.toFixed(5) );
13318
_calculateNewMax: function() {
13319
var max = this.options.max,
13320
min = this._valueMin(),
13321
step = this.options.step,
13322
aboveMin = Math.floor( ( +( max - min ).toFixed( this._precision() ) ) / step ) * step;
13323
max = aboveMin + min;
13324
this.max = parseFloat( max.toFixed( this._precision() ) );
13327
_precision: function() {
13328
var precision = this._precisionOf( this.options.step );
13329
if ( this.options.min !== null ) {
13330
precision = Math.max( precision, this._precisionOf( this.options.min ) );
13335
_precisionOf: function( num ) {
13336
var str = num.toString(),
13337
decimal = str.indexOf( "." );
13338
return decimal === -1 ? 0 : str.length - decimal - 1;
13341
_valueMin: function() {
13342
return this.options.min;
13345
_valueMax: function() {
13349
_refreshValue: function() {
13350
var lastValPercent, valPercent, value, valueMin, valueMax,
13351
oRange = this.options.range,
13354
animate = ( !this._animateOff ) ? o.animate : false,
13357
if ( this.options.values && this.options.values.length ) {
13358
this.handles.each(function( i ) {
13359
valPercent = ( that.values(i) - that._valueMin() ) / ( that._valueMax() - that._valueMin() ) * 100;
13360
_set[ that.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
13361
$( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
13362
if ( that.options.range === true ) {
13363
if ( that.orientation === "horizontal" ) {
13365
that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate );
13368
that.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
13372
that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate );
13375
that.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
13379
lastValPercent = valPercent;
13382
value = this.value();
13383
valueMin = this._valueMin();
13384
valueMax = this._valueMax();
13385
valPercent = ( valueMax !== valueMin ) ?
13386
( value - valueMin ) / ( valueMax - valueMin ) * 100 :
13388
_set[ this.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
13389
this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
13391
if ( oRange === "min" && this.orientation === "horizontal" ) {
13392
this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate );
13394
if ( oRange === "max" && this.orientation === "horizontal" ) {
13395
this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
13397
if ( oRange === "min" && this.orientation === "vertical" ) {
13398
this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate );
13400
if ( oRange === "max" && this.orientation === "vertical" ) {
13401
this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
13407
keydown: function( event ) {
13408
var allowed, curVal, newVal, step,
13409
index = $( event.target ).data( "ui-slider-handle-index" );
13411
switch ( event.keyCode ) {
13412
case $.ui.keyCode.HOME:
13413
case $.ui.keyCode.END:
13414
case $.ui.keyCode.PAGE_UP:
13415
case $.ui.keyCode.PAGE_DOWN:
13416
case $.ui.keyCode.UP:
13417
case $.ui.keyCode.RIGHT:
13418
case $.ui.keyCode.DOWN:
13419
case $.ui.keyCode.LEFT:
13420
event.preventDefault();
13421
if ( !this._keySliding ) {
13422
this._keySliding = true;
13423
$( event.target ).addClass( "ui-state-active" );
13424
allowed = this._start( event, index );
13425
if ( allowed === false ) {
13432
step = this.options.step;
13433
if ( this.options.values && this.options.values.length ) {
13434
curVal = newVal = this.values( index );
13436
curVal = newVal = this.value();
13439
switch ( event.keyCode ) {
13440
case $.ui.keyCode.HOME:
13441
newVal = this._valueMin();
13443
case $.ui.keyCode.END:
13444
newVal = this._valueMax();
13446
case $.ui.keyCode.PAGE_UP:
13447
newVal = this._trimAlignValue(
13448
curVal + ( ( this._valueMax() - this._valueMin() ) / this.numPages )
13451
case $.ui.keyCode.PAGE_DOWN:
13452
newVal = this._trimAlignValue(
13453
curVal - ( (this._valueMax() - this._valueMin()) / this.numPages ) );
13455
case $.ui.keyCode.UP:
13456
case $.ui.keyCode.RIGHT:
13457
if ( curVal === this._valueMax() ) {
13460
newVal = this._trimAlignValue( curVal + step );
13462
case $.ui.keyCode.DOWN:
13463
case $.ui.keyCode.LEFT:
13464
if ( curVal === this._valueMin() ) {
13467
newVal = this._trimAlignValue( curVal - step );
13471
this._slide( event, index, newVal );
13473
keyup: function( event ) {
13474
var index = $( event.target ).data( "ui-slider-handle-index" );
13476
if ( this._keySliding ) {
13477
this._keySliding = false;
13478
this._stop( event, index );
13479
this._change( event, index );
13480
$( event.target ).removeClass( "ui-state-active" );
13488
* jQuery UI Sortable 1.11.4
13489
* http://jqueryui.com
13491
* Copyright jQuery Foundation and other contributors
13492
* Released under the MIT license.
13493
* http://jquery.org/license
13495
* http://api.jqueryui.com/sortable/
13499
var sortable = $.widget("ui.sortable", $.ui.mouse, {
13501
widgetEventPrefix: "sort",
13504
appendTo: "parent",
13506
connectWith: false,
13507
containment: false,
13511
forcePlaceholderSize: false,
13512
forceHelperSize: false,
13515
helper: "original",
13518
placeholder: false,
13521
scrollSensitivity: 20,
13524
tolerance: "intersect",
13542
_isOverAxis: function( x, reference, size ) {
13543
return ( x >= reference ) && ( x < ( reference + size ) );
13546
_isFloating: function( item ) {
13547
return (/left|right/).test(item.css("float")) || (/inline|table-cell/).test(item.css("display"));
13550
_create: function() {
13551
this.containerCache = {};
13552
this.element.addClass("ui-sortable");
13557
//Let's determine the parent's offset
13558
this.offset = this.element.offset();
13560
//Initialize mouse events for interaction
13563
this._setHandleClassName();
13565
//We're ready to go
13570
_setOption: function( key, value ) {
13571
this._super( key, value );
13573
if ( key === "handle" ) {
13574
this._setHandleClassName();
13578
_setHandleClassName: function() {
13579
this.element.find( ".ui-sortable-handle" ).removeClass( "ui-sortable-handle" );
13580
$.each( this.items, function() {
13581
( this.instance.options.handle ?
13582
this.item.find( this.instance.options.handle ) : this.item )
13583
.addClass( "ui-sortable-handle" );
13587
_destroy: function() {
13589
.removeClass( "ui-sortable ui-sortable-disabled" )
13590
.find( ".ui-sortable-handle" )
13591
.removeClass( "ui-sortable-handle" );
13592
this._mouseDestroy();
13594
for ( var i = this.items.length - 1; i >= 0; i-- ) {
13595
this.items[i].item.removeData(this.widgetName + "-item");
13601
_mouseCapture: function(event, overrideHandle) {
13602
var currentItem = null,
13603
validHandle = false,
13606
if (this.reverting) {
13610
if(this.options.disabled || this.options.type === "static") {
13614
//We have to refresh the items data once first
13615
this._refreshItems(event);
13617
//Find out if the clicked node (or one of its parents) is a actual item in this.items
13618
$(event.target).parents().each(function() {
13619
if($.data(this, that.widgetName + "-item") === that) {
13620
currentItem = $(this);
13624
if($.data(event.target, that.widgetName + "-item") === that) {
13625
currentItem = $(event.target);
13631
if(this.options.handle && !overrideHandle) {
13632
$(this.options.handle, currentItem).find("*").addBack().each(function() {
13633
if(this === event.target) {
13634
validHandle = true;
13642
this.currentItem = currentItem;
13643
this._removeCurrentsFromItems();
13648
_mouseStart: function(event, overrideHandle, noActivation) {
13653
this.currentContainer = this;
13655
//We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture
13656
this.refreshPositions();
13658
//Create and append the visible helper
13659
this.helper = this._createHelper(event);
13661
//Cache the helper size
13662
this._cacheHelperProportions();
13665
* - Position generation -
13666
* This block generates everything position related - it's the core of draggables.
13669
//Cache the margins of the original element
13670
this._cacheMargins();
13672
//Get the next scrolling parent
13673
this.scrollParent = this.helper.scrollParent();
13675
//The element's absolute position on the page minus margins
13676
this.offset = this.currentItem.offset();
13678
top: this.offset.top - this.margins.top,
13679
left: this.offset.left - this.margins.left
13682
$.extend(this.offset, {
13683
click: { //Where the click happened, relative to the element
13684
left: event.pageX - this.offset.left,
13685
top: event.pageY - this.offset.top
13687
parent: this._getParentOffset(),
13688
relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
13691
// Only after we got the offset, we can change the helper's position to absolute
13692
// TODO: Still need to figure out a way to make relative sorting possible
13693
this.helper.css("position", "absolute");
13694
this.cssPosition = this.helper.css("position");
13696
//Generate the original position
13697
this.originalPosition = this._generatePosition(event);
13698
this.originalPageX = event.pageX;
13699
this.originalPageY = event.pageY;
13701
//Adjust the mouse offset relative to the helper if "cursorAt" is supplied
13702
(o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
13704
//Cache the former DOM position
13705
this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] };
13707
//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
13708
if(this.helper[0] !== this.currentItem[0]) {
13709
this.currentItem.hide();
13712
//Create the placeholder
13713
this._createPlaceholder();
13715
//Set a containment if given in the options
13716
if(o.containment) {
13717
this._setContainment();
13720
if( o.cursor && o.cursor !== "auto" ) { // cursor option
13721
body = this.document.find( "body" );
13724
this.storedCursor = body.css( "cursor" );
13725
body.css( "cursor", o.cursor );
13727
this.storedStylesheet = $( "<style>*{ cursor: "+o.cursor+" !important; }</style>" ).appendTo( body );
13730
if(o.opacity) { // opacity option
13731
if (this.helper.css("opacity")) {
13732
this._storedOpacity = this.helper.css("opacity");
13734
this.helper.css("opacity", o.opacity);
13737
if(o.zIndex) { // zIndex option
13738
if (this.helper.css("zIndex")) {
13739
this._storedZIndex = this.helper.css("zIndex");
13741
this.helper.css("zIndex", o.zIndex);
13744
//Prepare scrolling
13745
if(this.scrollParent[0] !== this.document[0] && this.scrollParent[0].tagName !== "HTML") {
13746
this.overflowOffset = this.scrollParent.offset();
13750
this._trigger("start", event, this._uiHash());
13752
//Recache the helper size
13753
if(!this._preserveHelperProportions) {
13754
this._cacheHelperProportions();
13758
//Post "activate" events to possible containers
13759
if( !noActivation ) {
13760
for ( i = this.containers.length - 1; i >= 0; i-- ) {
13761
this.containers[ i ]._trigger( "activate", event, this._uiHash( this ) );
13765
//Prepare possible droppables
13766
if($.ui.ddmanager) {
13767
$.ui.ddmanager.current = this;
13770
if ($.ui.ddmanager && !o.dropBehaviour) {
13771
$.ui.ddmanager.prepareOffsets(this, event);
13774
this.dragging = true;
13776
this.helper.addClass("ui-sortable-helper");
13777
this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position
13782
_mouseDrag: function(event) {
13783
var i, item, itemElement, intersection,
13787
//Compute the helpers position
13788
this.position = this._generatePosition(event);
13789
this.positionAbs = this._convertPositionTo("absolute");
13791
if (!this.lastPositionAbs) {
13792
this.lastPositionAbs = this.positionAbs;
13796
if(this.options.scroll) {
13797
if(this.scrollParent[0] !== this.document[0] && this.scrollParent[0].tagName !== "HTML") {
13799
if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) {
13800
this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed;
13801
} else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity) {
13802
this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed;
13805
if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) {
13806
this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed;
13807
} else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity) {
13808
this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed;
13813
if(event.pageY - this.document.scrollTop() < o.scrollSensitivity) {
13814
scrolled = this.document.scrollTop(this.document.scrollTop() - o.scrollSpeed);
13815
} else if(this.window.height() - (event.pageY - this.document.scrollTop()) < o.scrollSensitivity) {
13816
scrolled = this.document.scrollTop(this.document.scrollTop() + o.scrollSpeed);
13819
if(event.pageX - this.document.scrollLeft() < o.scrollSensitivity) {
13820
scrolled = this.document.scrollLeft(this.document.scrollLeft() - o.scrollSpeed);
13821
} else if(this.window.width() - (event.pageX - this.document.scrollLeft()) < o.scrollSensitivity) {
13822
scrolled = this.document.scrollLeft(this.document.scrollLeft() + o.scrollSpeed);
13827
if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) {
13828
$.ui.ddmanager.prepareOffsets(this, event);
13832
//Regenerate the absolute position used for position checks
13833
this.positionAbs = this._convertPositionTo("absolute");
13835
//Set the helper position
13836
if(!this.options.axis || this.options.axis !== "y") {
13837
this.helper[0].style.left = this.position.left+"px";
13839
if(!this.options.axis || this.options.axis !== "x") {
13840
this.helper[0].style.top = this.position.top+"px";
13844
for (i = this.items.length - 1; i >= 0; i--) {
13846
//Cache variables and intersection, continue if no intersection
13847
item = this.items[i];
13848
itemElement = item.item[0];
13849
intersection = this._intersectsWithPointer(item);
13850
if (!intersection) {
13854
// Only put the placeholder inside the current Container, skip all
13855
// items from other containers. This works because when moving
13856
// an item from one container to another the
13857
// currentContainer is switched before the placeholder is moved.
13859
// Without this, moving items in "sub-sortables" can cause
13860
// the placeholder to jitter between the outer and inner container.
13861
if (item.instance !== this.currentContainer) {
13865
// cannot intersect with itself
13866
// no useless actions that have been done before
13867
// no action if the item moved is the parent of the item checked
13868
if (itemElement !== this.currentItem[0] &&
13869
this.placeholder[intersection === 1 ? "next" : "prev"]()[0] !== itemElement &&
13870
!$.contains(this.placeholder[0], itemElement) &&
13871
(this.options.type === "semi-dynamic" ? !$.contains(this.element[0], itemElement) : true)
13874
this.direction = intersection === 1 ? "down" : "up";
13876
if (this.options.tolerance === "pointer" || this._intersectsWithSides(item)) {
13877
this._rearrange(event, item);
13882
this._trigger("change", event, this._uiHash());
13887
//Post events to containers
13888
this._contactContainers(event);
13890
//Interconnect with droppables
13891
if($.ui.ddmanager) {
13892
$.ui.ddmanager.drag(this, event);
13896
this._trigger("sort", event, this._uiHash());
13898
this.lastPositionAbs = this.positionAbs;
13903
_mouseStop: function(event, noPropagation) {
13909
//If we are using droppables, inform the manager about the drop
13910
if ($.ui.ddmanager && !this.options.dropBehaviour) {
13911
$.ui.ddmanager.drop(this, event);
13914
if(this.options.revert) {
13916
cur = this.placeholder.offset(),
13917
axis = this.options.axis,
13920
if ( !axis || axis === "x" ) {
13921
animation.left = cur.left - this.offset.parent.left - this.margins.left + (this.offsetParent[0] === this.document[0].body ? 0 : this.offsetParent[0].scrollLeft);
13923
if ( !axis || axis === "y" ) {
13924
animation.top = cur.top - this.offset.parent.top - this.margins.top + (this.offsetParent[0] === this.document[0].body ? 0 : this.offsetParent[0].scrollTop);
13926
this.reverting = true;
13927
$(this.helper).animate( animation, parseInt(this.options.revert, 10) || 500, function() {
13928
that._clear(event);
13931
this._clear(event, noPropagation);
13938
cancel: function() {
13940
if(this.dragging) {
13942
this._mouseUp({ target: null });
13944
if(this.options.helper === "original") {
13945
this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
13947
this.currentItem.show();
13950
//Post deactivating events to containers
13951
for (var i = this.containers.length - 1; i >= 0; i--){
13952
this.containers[i]._trigger("deactivate", null, this._uiHash(this));
13953
if(this.containers[i].containerCache.over) {
13954
this.containers[i]._trigger("out", null, this._uiHash(this));
13955
this.containers[i].containerCache.over = 0;
13961
if (this.placeholder) {
13962
//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
13963
if(this.placeholder[0].parentNode) {
13964
this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
13966
if(this.options.helper !== "original" && this.helper && this.helper[0].parentNode) {
13967
this.helper.remove();
13977
if(this.domPosition.prev) {
13978
$(this.domPosition.prev).after(this.currentItem);
13980
$(this.domPosition.parent).prepend(this.currentItem);
13988
serialize: function(o) {
13990
var items = this._getItemsAsjQuery(o && o.connected),
13994
$(items).each(function() {
13995
var res = ($(o.item || this).attr(o.attribute || "id") || "").match(o.expression || (/(.+)[\-=_](.+)/));
13997
str.push((o.key || res[1]+"[]")+"="+(o.key && o.expression ? res[1] : res[2]));
14001
if(!str.length && o.key) {
14002
str.push(o.key + "=");
14005
return str.join("&");
14009
toArray: function(o) {
14011
var items = this._getItemsAsjQuery(o && o.connected),
14016
items.each(function() { ret.push($(o.item || this).attr(o.attribute || "id") || ""); });
14021
/* Be careful with the following core functions */
14022
_intersectsWith: function(item) {
14024
var x1 = this.positionAbs.left,
14025
x2 = x1 + this.helperProportions.width,
14026
y1 = this.positionAbs.top,
14027
y2 = y1 + this.helperProportions.height,
14029
r = l + item.width,
14031
b = t + item.height,
14032
dyClick = this.offset.click.top,
14033
dxClick = this.offset.click.left,
14034
isOverElementHeight = ( this.options.axis === "x" ) || ( ( y1 + dyClick ) > t && ( y1 + dyClick ) < b ),
14035
isOverElementWidth = ( this.options.axis === "y" ) || ( ( x1 + dxClick ) > l && ( x1 + dxClick ) < r ),
14036
isOverElement = isOverElementHeight && isOverElementWidth;
14038
if ( this.options.tolerance === "pointer" ||
14039
this.options.forcePointerForContainers ||
14040
(this.options.tolerance !== "pointer" && this.helperProportions[this.floating ? "width" : "height"] > item[this.floating ? "width" : "height"])
14042
return isOverElement;
14045
return (l < x1 + (this.helperProportions.width / 2) && // Right Half
14046
x2 - (this.helperProportions.width / 2) < r && // Left Half
14047
t < y1 + (this.helperProportions.height / 2) && // Bottom Half
14048
y2 - (this.helperProportions.height / 2) < b ); // Top Half
14053
_intersectsWithPointer: function(item) {
14055
var isOverElementHeight = (this.options.axis === "x") || this._isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height),
14056
isOverElementWidth = (this.options.axis === "y") || this._isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width),
14057
isOverElement = isOverElementHeight && isOverElementWidth,
14058
verticalDirection = this._getDragVerticalDirection(),
14059
horizontalDirection = this._getDragHorizontalDirection();
14061
if (!isOverElement) {
14065
return this.floating ?
14066
( ((horizontalDirection && horizontalDirection === "right") || verticalDirection === "down") ? 2 : 1 )
14067
: ( verticalDirection && (verticalDirection === "down" ? 2 : 1) );
14071
_intersectsWithSides: function(item) {
14073
var isOverBottomHalf = this._isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height),
14074
isOverRightHalf = this._isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width),
14075
verticalDirection = this._getDragVerticalDirection(),
14076
horizontalDirection = this._getDragHorizontalDirection();
14078
if (this.floating && horizontalDirection) {
14079
return ((horizontalDirection === "right" && isOverRightHalf) || (horizontalDirection === "left" && !isOverRightHalf));
14081
return verticalDirection && ((verticalDirection === "down" && isOverBottomHalf) || (verticalDirection === "up" && !isOverBottomHalf));
14086
_getDragVerticalDirection: function() {
14087
var delta = this.positionAbs.top - this.lastPositionAbs.top;
14088
return delta !== 0 && (delta > 0 ? "down" : "up");
14091
_getDragHorizontalDirection: function() {
14092
var delta = this.positionAbs.left - this.lastPositionAbs.left;
14093
return delta !== 0 && (delta > 0 ? "right" : "left");
14096
refresh: function(event) {
14097
this._refreshItems(event);
14098
this._setHandleClassName();
14099
this.refreshPositions();
14103
_connectWith: function() {
14104
var options = this.options;
14105
return options.connectWith.constructor === String ? [options.connectWith] : options.connectWith;
14108
_getItemsAsjQuery: function(connected) {
14110
var i, j, cur, inst,
14113
connectWith = this._connectWith();
14115
if(connectWith && connected) {
14116
for (i = connectWith.length - 1; i >= 0; i--){
14117
cur = $(connectWith[i], this.document[0]);
14118
for ( j = cur.length - 1; j >= 0; j--){
14119
inst = $.data(cur[j], this.widgetFullName);
14120
if(inst && inst !== this && !inst.options.disabled) {
14121
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]);
14127
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]);
14129
function addItems() {
14130
items.push( this );
14132
for (i = queries.length - 1; i >= 0; i--){
14133
queries[i][0].each( addItems );
14140
_removeCurrentsFromItems: function() {
14142
var list = this.currentItem.find(":data(" + this.widgetName + "-item)");
14144
this.items = $.grep(this.items, function (item) {
14145
for (var j=0; j < list.length; j++) {
14146
if(list[j] === item.item[0]) {
14155
_refreshItems: function(event) {
14158
this.containers = [this];
14160
var i, j, cur, inst, targetData, _queries, item, queriesLength,
14161
items = this.items,
14162
queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]],
14163
connectWith = this._connectWith();
14165
if(connectWith && this.ready) { //Shouldn't be run the first time through due to massive slow-down
14166
for (i = connectWith.length - 1; i >= 0; i--){
14167
cur = $(connectWith[i], this.document[0]);
14168
for (j = cur.length - 1; j >= 0; j--){
14169
inst = $.data(cur[j], this.widgetFullName);
14170
if(inst && inst !== this && !inst.options.disabled) {
14171
queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]);
14172
this.containers.push(inst);
14178
for (i = queries.length - 1; i >= 0; i--) {
14179
targetData = queries[i][1];
14180
_queries = queries[i][0];
14182
for (j=0, queriesLength = _queries.length; j < queriesLength; j++) {
14183
item = $(_queries[j]);
14185
item.data(this.widgetName + "-item", targetData); // Data for target checking (mouse manager)
14189
instance: targetData,
14190
width: 0, height: 0,
14198
refreshPositions: function(fast) {
14200
// Determine whether items are being displayed horizontally
14201
this.floating = this.items.length ?
14202
this.options.axis === "x" || this._isFloating( this.items[ 0 ].item ) :
14205
//This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change
14206
if(this.offsetParent && this.helper) {
14207
this.offset.parent = this._getParentOffset();
14212
for (i = this.items.length - 1; i >= 0; i--){
14213
item = this.items[i];
14215
//We ignore calculating positions of all connected containers when we're not over them
14216
if(item.instance !== this.currentContainer && this.currentContainer && item.item[0] !== this.currentItem[0]) {
14220
t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item;
14223
item.width = t.outerWidth();
14224
item.height = t.outerHeight();
14228
item.left = p.left;
14232
if(this.options.custom && this.options.custom.refreshContainers) {
14233
this.options.custom.refreshContainers.call(this);
14235
for (i = this.containers.length - 1; i >= 0; i--){
14236
p = this.containers[i].element.offset();
14237
this.containers[i].containerCache.left = p.left;
14238
this.containers[i].containerCache.top = p.top;
14239
this.containers[i].containerCache.width = this.containers[i].element.outerWidth();
14240
this.containers[i].containerCache.height = this.containers[i].element.outerHeight();
14247
_createPlaceholder: function(that) {
14248
that = that || this;
14252
if(!o.placeholder || o.placeholder.constructor === String) {
14253
className = o.placeholder;
14255
element: function() {
14257
var nodeName = that.currentItem[0].nodeName.toLowerCase(),
14258
element = $( "<" + nodeName + ">", that.document[0] )
14259
.addClass(className || that.currentItem[0].className+" ui-sortable-placeholder")
14260
.removeClass("ui-sortable-helper");
14262
if ( nodeName === "tbody" ) {
14263
that._createTrPlaceholder(
14264
that.currentItem.find( "tr" ).eq( 0 ),
14265
$( "<tr>", that.document[ 0 ] ).appendTo( element )
14267
} else if ( nodeName === "tr" ) {
14268
that._createTrPlaceholder( that.currentItem, element );
14269
} else if ( nodeName === "img" ) {
14270
element.attr( "src", that.currentItem.attr( "src" ) );
14273
if ( !className ) {
14274
element.css( "visibility", "hidden" );
14279
update: function(container, p) {
14281
// 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that
14282
// 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified
14283
if(className && !o.forcePlaceholderSize) {
14287
//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
14288
if(!p.height()) { p.height(that.currentItem.innerHeight() - parseInt(that.currentItem.css("paddingTop")||0, 10) - parseInt(that.currentItem.css("paddingBottom")||0, 10)); }
14289
if(!p.width()) { p.width(that.currentItem.innerWidth() - parseInt(that.currentItem.css("paddingLeft")||0, 10) - parseInt(that.currentItem.css("paddingRight")||0, 10)); }
14294
//Create the placeholder
14295
that.placeholder = $(o.placeholder.element.call(that.element, that.currentItem));
14297
//Append it after the actual current item
14298
that.currentItem.after(that.placeholder);
14300
//Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
14301
o.placeholder.update(that, that.placeholder);
14305
_createTrPlaceholder: function( sourceTr, targetTr ) {
14308
sourceTr.children().each(function() {
14309
$( "<td> </td>", that.document[ 0 ] )
14310
.attr( "colspan", $( this ).attr( "colspan" ) || 1 )
14311
.appendTo( targetTr );
14315
_contactContainers: function(event) {
14316
var i, j, dist, itemWithLeastDistance, posProperty, sizeProperty, cur, nearBottom, floating, axis,
14317
innermostContainer = null,
14318
innermostIndex = null;
14320
// get innermost container that intersects with item
14321
for (i = this.containers.length - 1; i >= 0; i--) {
14323
// never consider a container that's located within the item itself
14324
if($.contains(this.currentItem[0], this.containers[i].element[0])) {
14328
if(this._intersectsWith(this.containers[i].containerCache)) {
14330
// if we've already found a container and it's more "inner" than this, then continue
14331
if(innermostContainer && $.contains(this.containers[i].element[0], innermostContainer.element[0])) {
14335
innermostContainer = this.containers[i];
14336
innermostIndex = i;
14339
// container doesn't intersect. trigger "out" event if necessary
14340
if(this.containers[i].containerCache.over) {
14341
this.containers[i]._trigger("out", event, this._uiHash(this));
14342
this.containers[i].containerCache.over = 0;
14348
// if no intersecting containers found, return
14349
if(!innermostContainer) {
14353
// move the item into the container if it's not there already
14354
if(this.containers.length === 1) {
14355
if (!this.containers[innermostIndex].containerCache.over) {
14356
this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
14357
this.containers[innermostIndex].containerCache.over = 1;
14361
//When entering a new container, we will find the item with the least distance and append our item near it
14363
itemWithLeastDistance = null;
14364
floating = innermostContainer.floating || this._isFloating(this.currentItem);
14365
posProperty = floating ? "left" : "top";
14366
sizeProperty = floating ? "width" : "height";
14367
axis = floating ? "clientX" : "clientY";
14369
for (j = this.items.length - 1; j >= 0; j--) {
14370
if(!$.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) {
14373
if(this.items[j].item[0] === this.currentItem[0]) {
14377
cur = this.items[j].item.offset()[posProperty];
14378
nearBottom = false;
14379
if ( event[ axis ] - cur > this.items[ j ][ sizeProperty ] / 2 ) {
14383
if ( Math.abs( event[ axis ] - cur ) < dist ) {
14384
dist = Math.abs( event[ axis ] - cur );
14385
itemWithLeastDistance = this.items[ j ];
14386
this.direction = nearBottom ? "up": "down";
14390
//Check if dropOnEmpty is enabled
14391
if(!itemWithLeastDistance && !this.options.dropOnEmpty) {
14395
if(this.currentContainer === this.containers[innermostIndex]) {
14396
if ( !this.currentContainer.containerCache.over ) {
14397
this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash() );
14398
this.currentContainer.containerCache.over = 1;
14403
itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true);
14404
this._trigger("change", event, this._uiHash());
14405
this.containers[innermostIndex]._trigger("change", event, this._uiHash(this));
14406
this.currentContainer = this.containers[innermostIndex];
14408
//Update the placeholder
14409
this.options.placeholder.update(this.currentContainer, this.placeholder);
14411
this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
14412
this.containers[innermostIndex].containerCache.over = 1;
14418
_createHelper: function(event) {
14420
var o = this.options,
14421
helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper === "clone" ? this.currentItem.clone() : this.currentItem);
14423
//Add the helper to the DOM if that didn't happen already
14424
if(!helper.parents("body").length) {
14425
$(o.appendTo !== "parent" ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]);
14428
if(helper[0] === this.currentItem[0]) {
14429
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") };
14432
if(!helper[0].style.width || o.forceHelperSize) {
14433
helper.width(this.currentItem.width());
14435
if(!helper[0].style.height || o.forceHelperSize) {
14436
helper.height(this.currentItem.height());
14443
_adjustOffsetFromHelper: function(obj) {
14444
if (typeof obj === "string") {
14445
obj = obj.split(" ");
14447
if ($.isArray(obj)) {
14448
obj = {left: +obj[0], top: +obj[1] || 0};
14450
if ("left" in obj) {
14451
this.offset.click.left = obj.left + this.margins.left;
14453
if ("right" in obj) {
14454
this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
14456
if ("top" in obj) {
14457
this.offset.click.top = obj.top + this.margins.top;
14459
if ("bottom" in obj) {
14460
this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
14464
_getParentOffset: function() {
14467
//Get the offsetParent and cache its position
14468
this.offsetParent = this.helper.offsetParent();
14469
var po = this.offsetParent.offset();
14471
// This is a special case where we need to modify a offset calculated on start, since the following happened:
14472
// 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
14473
// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
14474
// the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
14475
if(this.cssPosition === "absolute" && this.scrollParent[0] !== this.document[0] && $.contains(this.scrollParent[0], this.offsetParent[0])) {
14476
po.left += this.scrollParent.scrollLeft();
14477
po.top += this.scrollParent.scrollTop();
14480
// This needs to be actually done for all browsers, since pageX/pageY includes this information
14481
// with an ugly IE fix
14482
if( this.offsetParent[0] === this.document[0].body || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() === "html" && $.ui.ie)) {
14483
po = { top: 0, left: 0 };
14487
top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
14488
left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
14493
_getRelativeOffset: function() {
14495
if(this.cssPosition === "relative") {
14496
var p = this.currentItem.position();
14498
top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
14499
left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
14502
return { top: 0, left: 0 };
14507
_cacheMargins: function() {
14509
left: (parseInt(this.currentItem.css("marginLeft"),10) || 0),
14510
top: (parseInt(this.currentItem.css("marginTop"),10) || 0)
14514
_cacheHelperProportions: function() {
14515
this.helperProportions = {
14516
width: this.helper.outerWidth(),
14517
height: this.helper.outerHeight()
14521
_setContainment: function() {
14525
if(o.containment === "parent") {
14526
o.containment = this.helper[0].parentNode;
14528
if(o.containment === "document" || o.containment === "window") {
14529
this.containment = [
14530
0 - this.offset.relative.left - this.offset.parent.left,
14531
0 - this.offset.relative.top - this.offset.parent.top,
14532
o.containment === "document" ? this.document.width() : this.window.width() - this.helperProportions.width - this.margins.left,
14533
(o.containment === "document" ? this.document.width() : this.window.height() || this.document[0].body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
14537
if(!(/^(document|window|parent)$/).test(o.containment)) {
14538
ce = $(o.containment)[0];
14539
co = $(o.containment).offset();
14540
over = ($(ce).css("overflow") !== "hidden");
14542
this.containment = [
14543
co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
14544
co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
14545
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,
14546
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
14552
_convertPositionTo: function(d, pos) {
14555
pos = this.position;
14557
var mod = d === "absolute" ? 1 : -1,
14558
scroll = this.cssPosition === "absolute" && !(this.scrollParent[0] !== this.document[0] && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent,
14559
scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
14563
pos.top + // The absolute mouse position
14564
this.offset.relative.top * mod + // Only for relative positioned nodes: Relative offset from element to offset parent
14565
this.offset.parent.top * mod - // The offsetParent's offset without borders (offset + border)
14566
( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
14569
pos.left + // The absolute mouse position
14570
this.offset.relative.left * mod + // Only for relative positioned nodes: Relative offset from element to offset parent
14571
this.offset.parent.left * mod - // The offsetParent's offset without borders (offset + border)
14572
( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
14578
_generatePosition: function(event) {
14582
pageX = event.pageX,
14583
pageY = event.pageY,
14584
scroll = this.cssPosition === "absolute" && !(this.scrollParent[0] !== this.document[0] && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
14586
// This is another very weird special case that only happens for relative elements:
14587
// 1. If the css position is relative
14588
// 2. and the scroll parent is the document or similar to the offset parent
14589
// we have to refresh the relative offset during the scroll so there are no jumps
14590
if(this.cssPosition === "relative" && !(this.scrollParent[0] !== this.document[0] && this.scrollParent[0] !== this.offsetParent[0])) {
14591
this.offset.relative = this._getRelativeOffset();
14595
* - Position constraining -
14596
* Constrain the position to a mix of grid, containment.
14599
if(this.originalPosition) { //If we are not dragging yet, we won't check for options
14601
if(this.containment) {
14602
if(event.pageX - this.offset.click.left < this.containment[0]) {
14603
pageX = this.containment[0] + this.offset.click.left;
14605
if(event.pageY - this.offset.click.top < this.containment[1]) {
14606
pageY = this.containment[1] + this.offset.click.top;
14608
if(event.pageX - this.offset.click.left > this.containment[2]) {
14609
pageX = this.containment[2] + this.offset.click.left;
14611
if(event.pageY - this.offset.click.top > this.containment[3]) {
14612
pageY = this.containment[3] + this.offset.click.top;
14617
top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
14618
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;
14620
left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
14621
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;
14628
pageY - // The absolute mouse position
14629
this.offset.click.top - // Click offset (relative to the element)
14630
this.offset.relative.top - // Only for relative positioned nodes: Relative offset from element to offset parent
14631
this.offset.parent.top + // The offsetParent's offset without borders (offset + border)
14632
( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
14635
pageX - // The absolute mouse position
14636
this.offset.click.left - // Click offset (relative to the element)
14637
this.offset.relative.left - // Only for relative positioned nodes: Relative offset from element to offset parent
14638
this.offset.parent.left + // The offsetParent's offset without borders (offset + border)
14639
( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
14645
_rearrange: function(event, i, a, hardRefresh) {
14647
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));
14649
//Various things done here to improve the performance:
14650
// 1. we create a setTimeout, that calls refreshPositions
14651
// 2. on the instance, we have a counter variable, that get's higher after every append
14652
// 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same
14653
// 4. this lets only the last addition to the timeout stack through
14654
this.counter = this.counter ? ++this.counter : 1;
14655
var counter = this.counter;
14657
this._delay(function() {
14658
if(counter === this.counter) {
14659
this.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove
14665
_clear: function(event, noPropagation) {
14667
this.reverting = false;
14668
// We delay all events that have to be triggered to after the point where the placeholder has been removed and
14669
// everything else normalized again
14671
delayedTriggers = [];
14673
// We first have to update the dom position of the actual currentItem
14674
// Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088)
14675
if(!this._noFinalSort && this.currentItem.parent().length) {
14676
this.placeholder.before(this.currentItem);
14678
this._noFinalSort = null;
14680
if(this.helper[0] === this.currentItem[0]) {
14681
for(i in this._storedCSS) {
14682
if(this._storedCSS[i] === "auto" || this._storedCSS[i] === "static") {
14683
this._storedCSS[i] = "";
14686
this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
14688
this.currentItem.show();
14691
if(this.fromOutside && !noPropagation) {
14692
delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); });
14694
if((this.fromOutside || this.domPosition.prev !== this.currentItem.prev().not(".ui-sortable-helper")[0] || this.domPosition.parent !== this.currentItem.parent()[0]) && !noPropagation) {
14695
delayedTriggers.push(function(event) { this._trigger("update", event, this._uiHash()); }); //Trigger update callback if the DOM position has changed
14698
// Check if the items Container has Changed and trigger appropriate
14700
if (this !== this.currentContainer) {
14701
if(!noPropagation) {
14702
delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); });
14703
delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); }; }).call(this, this.currentContainer));
14704
delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this)); }; }).call(this, this.currentContainer));
14709
//Post events to containers
14710
function delayEvent( type, instance, container ) {
14711
return function( event ) {
14712
container._trigger( type, event, instance._uiHash( instance ) );
14715
for (i = this.containers.length - 1; i >= 0; i--){
14716
if (!noPropagation) {
14717
delayedTriggers.push( delayEvent( "deactivate", this, this.containers[ i ] ) );
14719
if(this.containers[i].containerCache.over) {
14720
delayedTriggers.push( delayEvent( "out", this, this.containers[ i ] ) );
14721
this.containers[i].containerCache.over = 0;
14725
//Do what was originally in plugins
14726
if ( this.storedCursor ) {
14727
this.document.find( "body" ).css( "cursor", this.storedCursor );
14728
this.storedStylesheet.remove();
14730
if(this._storedOpacity) {
14731
this.helper.css("opacity", this._storedOpacity);
14733
if(this._storedZIndex) {
14734
this.helper.css("zIndex", this._storedZIndex === "auto" ? "" : this._storedZIndex);
14737
this.dragging = false;
14739
if(!noPropagation) {
14740
this._trigger("beforeStop", event, this._uiHash());
14743
//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
14744
this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
14746
if ( !this.cancelHelperRemoval ) {
14747
if ( this.helper[ 0 ] !== this.currentItem[ 0 ] ) {
14748
this.helper.remove();
14750
this.helper = null;
14753
if(!noPropagation) {
14754
for (i=0; i < delayedTriggers.length; i++) {
14755
delayedTriggers[i].call(this, event);
14756
} //Trigger all delayed events
14757
this._trigger("stop", event, this._uiHash());
14760
this.fromOutside = false;
14761
return !this.cancelHelperRemoval;
14765
_trigger: function() {
14766
if ($.Widget.prototype._trigger.apply(this, arguments) === false) {
14771
_uiHash: function(_inst) {
14772
var inst = _inst || this;
14774
helper: inst.helper,
14775
placeholder: inst.placeholder || $([]),
14776
position: inst.position,
14777
originalPosition: inst.originalPosition,
14778
offset: inst.positionAbs,
14779
item: inst.currentItem,
14780
sender: _inst ? _inst.element : null
14788
* jQuery UI Spinner 1.11.4
14789
* http://jqueryui.com
14791
* Copyright jQuery Foundation and other contributors
14792
* Released under the MIT license.
14793
* http://jquery.org/license
14795
* http://api.jqueryui.com/spinner/
14799
function spinner_modifier( fn ) {
14800
return function() {
14801
var previous = this.element.val();
14802
fn.apply( this, arguments );
14804
if ( previous !== this.element.val() ) {
14805
this._trigger( "change" );
14810
var spinner = $.widget( "ui.spinner", {
14812
defaultElement: "<input>",
14813
widgetEventPrefix: "spin",
14817
down: "ui-icon-triangle-1-s",
14818
up: "ui-icon-triangle-1-n"
14823
numberFormat: null,
14833
_create: function() {
14834
// handle string values that need to be parsed
14835
this._setOption( "max", this.options.max );
14836
this._setOption( "min", this.options.min );
14837
this._setOption( "step", this.options.step );
14839
// Only format if there is a value, prevents the field from being marked
14840
// as invalid in Firefox, see #9573.
14841
if ( this.value() !== "" ) {
14842
// Format the value, but don't constrain.
14843
this._value( this.element.val(), true );
14847
this._on( this._events );
14850
// turning off autocomplete prevents the browser from remembering the
14851
// value when navigating through history, so we re-enable autocomplete
14852
// if the page is unloaded before the widget is destroyed. #7790
14853
this._on( this.window, {
14854
beforeunload: function() {
14855
this.element.removeAttr( "autocomplete" );
14860
_getCreateOptions: function() {
14862
element = this.element;
14864
$.each( [ "min", "max", "step" ], function( i, option ) {
14865
var value = element.attr( option );
14866
if ( value !== undefined && value.length ) {
14867
options[ option ] = value;
14875
keydown: function( event ) {
14876
if ( this._start( event ) && this._keydown( event ) ) {
14877
event.preventDefault();
14881
focus: function() {
14882
this.previous = this.element.val();
14884
blur: function( event ) {
14885
if ( this.cancelBlur ) {
14886
delete this.cancelBlur;
14892
if ( this.previous !== this.element.val() ) {
14893
this._trigger( "change", event );
14896
mousewheel: function( event, delta ) {
14900
if ( !this.spinning && !this._start( event ) ) {
14904
this._spin( (delta > 0 ? 1 : -1) * this.options.step, event );
14905
clearTimeout( this.mousewheelTimer );
14906
this.mousewheelTimer = this._delay(function() {
14907
if ( this.spinning ) {
14908
this._stop( event );
14911
event.preventDefault();
14913
"mousedown .ui-spinner-button": function( event ) {
14916
// We never want the buttons to have focus; whenever the user is
14917
// interacting with the spinner, the focus should be on the input.
14918
// If the input is focused then this.previous is properly set from
14919
// when the input first received focus. If the input is not focused
14920
// then we need to set this.previous based on the value before spinning.
14921
previous = this.element[0] === this.document[0].activeElement ?
14922
this.previous : this.element.val();
14923
function checkFocus() {
14924
var isActive = this.element[0] === this.document[0].activeElement;
14926
this.element.focus();
14927
this.previous = previous;
14929
// IE sets focus asynchronously, so we need to check if focus
14930
// moved off of the input because the user clicked on the button.
14931
this._delay(function() {
14932
this.previous = previous;
14937
// ensure focus is on (or stays on) the text field
14938
event.preventDefault();
14939
checkFocus.call( this );
14942
// IE doesn't prevent moving focus even with event.preventDefault()
14943
// so we set a flag to know when we should ignore the blur event
14944
// and check (again) if focus moved off of the input.
14945
this.cancelBlur = true;
14946
this._delay(function() {
14947
delete this.cancelBlur;
14948
checkFocus.call( this );
14951
if ( this._start( event ) === false ) {
14955
this._repeat( null, $( event.currentTarget ).hasClass( "ui-spinner-up" ) ? 1 : -1, event );
14957
"mouseup .ui-spinner-button": "_stop",
14958
"mouseenter .ui-spinner-button": function( event ) {
14959
// button will add ui-state-active if mouse was down while mouseleave and kept down
14960
if ( !$( event.currentTarget ).hasClass( "ui-state-active" ) ) {
14964
if ( this._start( event ) === false ) {
14967
this._repeat( null, $( event.currentTarget ).hasClass( "ui-spinner-up" ) ? 1 : -1, event );
14969
// TODO: do we really want to consider this a stop?
14970
// shouldn't we just stop the repeater and wait until mouseup before
14971
// we trigger the stop event?
14972
"mouseleave .ui-spinner-button": "_stop"
14975
_draw: function() {
14976
var uiSpinner = this.uiSpinner = this.element
14977
.addClass( "ui-spinner-input" )
14978
.attr( "autocomplete", "off" )
14979
.wrap( this._uiSpinnerHtml() )
14982
.append( this._buttonHtml() );
14984
this.element.attr( "role", "spinbutton" );
14987
this.buttons = uiSpinner.find( ".ui-spinner-button" )
14988
.attr( "tabIndex", -1 )
14990
.removeClass( "ui-corner-all" );
14992
// IE 6 doesn't understand height: 50% for the buttons
14993
// unless the wrapper has an explicit height
14994
if ( this.buttons.height() > Math.ceil( uiSpinner.height() * 0.5 ) &&
14995
uiSpinner.height() > 0 ) {
14996
uiSpinner.height( uiSpinner.height() );
14999
// disable spinner if element was already disabled
15000
if ( this.options.disabled ) {
15005
_keydown: function( event ) {
15006
var options = this.options,
15007
keyCode = $.ui.keyCode;
15009
switch ( event.keyCode ) {
15011
this._repeat( null, 1, event );
15014
this._repeat( null, -1, event );
15016
case keyCode.PAGE_UP:
15017
this._repeat( null, options.page, event );
15019
case keyCode.PAGE_DOWN:
15020
this._repeat( null, -options.page, event );
15027
_uiSpinnerHtml: function() {
15028
return "<span class='ui-spinner ui-widget ui-widget-content ui-corner-all'></span>";
15031
_buttonHtml: function() {
15033
"<a class='ui-spinner-button ui-spinner-up ui-corner-tr'>" +
15034
"<span class='ui-icon " + this.options.icons.up + "'>▲</span>" +
15036
"<a class='ui-spinner-button ui-spinner-down ui-corner-br'>" +
15037
"<span class='ui-icon " + this.options.icons.down + "'>▼</span>" +
15041
_start: function( event ) {
15042
if ( !this.spinning && this._trigger( "start", event ) === false ) {
15046
if ( !this.counter ) {
15049
this.spinning = true;
15053
_repeat: function( i, steps, event ) {
15056
clearTimeout( this.timer );
15057
this.timer = this._delay(function() {
15058
this._repeat( 40, steps, event );
15061
this._spin( steps * this.options.step, event );
15064
_spin: function( step, event ) {
15065
var value = this.value() || 0;
15067
if ( !this.counter ) {
15071
value = this._adjustValue( value + step * this._increment( this.counter ) );
15073
if ( !this.spinning || this._trigger( "spin", event, { value: value } ) !== false) {
15074
this._value( value );
15079
_increment: function( i ) {
15080
var incremental = this.options.incremental;
15082
if ( incremental ) {
15083
return $.isFunction( incremental ) ?
15085
Math.floor( i * i * i / 50000 - i * i / 500 + 17 * i / 200 + 1 );
15091
_precision: function() {
15092
var precision = this._precisionOf( this.options.step );
15093
if ( this.options.min !== null ) {
15094
precision = Math.max( precision, this._precisionOf( this.options.min ) );
15099
_precisionOf: function( num ) {
15100
var str = num.toString(),
15101
decimal = str.indexOf( "." );
15102
return decimal === -1 ? 0 : str.length - decimal - 1;
15105
_adjustValue: function( value ) {
15106
var base, aboveMin,
15107
options = this.options;
15109
// make sure we're at a valid step
15110
// - find out where we are relative to the base (min or 0)
15111
base = options.min !== null ? options.min : 0;
15112
aboveMin = value - base;
15113
// - round to the nearest step
15114
aboveMin = Math.round(aboveMin / options.step) * options.step;
15115
// - rounding is based on 0, so adjust back to our base
15116
value = base + aboveMin;
15118
// fix precision from bad JS floating point math
15119
value = parseFloat( value.toFixed( this._precision() ) );
15122
if ( options.max !== null && value > options.max) {
15123
return options.max;
15125
if ( options.min !== null && value < options.min ) {
15126
return options.min;
15132
_stop: function( event ) {
15133
if ( !this.spinning ) {
15137
clearTimeout( this.timer );
15138
clearTimeout( this.mousewheelTimer );
15140
this.spinning = false;
15141
this._trigger( "stop", event );
15144
_setOption: function( key, value ) {
15145
if ( key === "culture" || key === "numberFormat" ) {
15146
var prevValue = this._parse( this.element.val() );
15147
this.options[ key ] = value;
15148
this.element.val( this._format( prevValue ) );
15152
if ( key === "max" || key === "min" || key === "step" ) {
15153
if ( typeof value === "string" ) {
15154
value = this._parse( value );
15157
if ( key === "icons" ) {
15158
this.buttons.first().find( ".ui-icon" )
15159
.removeClass( this.options.icons.up )
15160
.addClass( value.up );
15161
this.buttons.last().find( ".ui-icon" )
15162
.removeClass( this.options.icons.down )
15163
.addClass( value.down );
15166
this._super( key, value );
15168
if ( key === "disabled" ) {
15169
this.widget().toggleClass( "ui-state-disabled", !!value );
15170
this.element.prop( "disabled", !!value );
15171
this.buttons.button( value ? "disable" : "enable" );
15175
_setOptions: spinner_modifier(function( options ) {
15176
this._super( options );
15179
_parse: function( val ) {
15180
if ( typeof val === "string" && val !== "" ) {
15181
val = window.Globalize && this.options.numberFormat ?
15182
Globalize.parseFloat( val, 10, this.options.culture ) : +val;
15184
return val === "" || isNaN( val ) ? null : val;
15187
_format: function( value ) {
15188
if ( value === "" ) {
15191
return window.Globalize && this.options.numberFormat ?
15192
Globalize.format( value, this.options.numberFormat, this.options.culture ) :
15196
_refresh: function() {
15197
this.element.attr({
15198
"aria-valuemin": this.options.min,
15199
"aria-valuemax": this.options.max,
15200
// TODO: what should we do with values that can't be parsed?
15201
"aria-valuenow": this._parse( this.element.val() )
15205
isValid: function() {
15206
var value = this.value();
15209
if ( value === null ) {
15213
// if value gets adjusted, it's invalid
15214
return value === this._adjustValue( value );
15217
// update the value without triggering change
15218
_value: function( value, allowAny ) {
15220
if ( value !== "" ) {
15221
parsed = this._parse( value );
15222
if ( parsed !== null ) {
15224
parsed = this._adjustValue( parsed );
15226
value = this._format( parsed );
15229
this.element.val( value );
15233
_destroy: function() {
15235
.removeClass( "ui-spinner-input" )
15236
.prop( "disabled", false )
15237
.removeAttr( "autocomplete" )
15238
.removeAttr( "role" )
15239
.removeAttr( "aria-valuemin" )
15240
.removeAttr( "aria-valuemax" )
15241
.removeAttr( "aria-valuenow" );
15242
this.uiSpinner.replaceWith( this.element );
15245
stepUp: spinner_modifier(function( steps ) {
15246
this._stepUp( steps );
15248
_stepUp: function( steps ) {
15249
if ( this._start() ) {
15250
this._spin( (steps || 1) * this.options.step );
15255
stepDown: spinner_modifier(function( steps ) {
15256
this._stepDown( steps );
15258
_stepDown: function( steps ) {
15259
if ( this._start() ) {
15260
this._spin( (steps || 1) * -this.options.step );
15265
pageUp: spinner_modifier(function( pages ) {
15266
this._stepUp( (pages || 1) * this.options.page );
15269
pageDown: spinner_modifier(function( pages ) {
15270
this._stepDown( (pages || 1) * this.options.page );
15273
value: function( newVal ) {
15274
if ( !arguments.length ) {
15275
return this._parse( this.element.val() );
15277
spinner_modifier( this._value ).call( this, newVal );
15280
widget: function() {
15281
return this.uiSpinner;
15287
* jQuery UI Tabs 1.11.4
15288
* http://jqueryui.com
15290
* Copyright jQuery Foundation and other contributors
15291
* Released under the MIT license.
15292
* http://jquery.org/license
15294
* http://api.jqueryui.com/tabs/
15298
var tabs = $.widget( "ui.tabs", {
15303
collapsible: false,
15305
heightStyle: "content",
15311
beforeActivate: null,
15316
_isLocal: (function() {
15317
var rhash = /#.*$/;
15319
return function( anchor ) {
15320
var anchorUrl, locationUrl;
15323
// IE7 doesn't normalize the href property when set via script (#9317)
15324
anchor = anchor.cloneNode( false );
15326
anchorUrl = anchor.href.replace( rhash, "" );
15327
locationUrl = location.href.replace( rhash, "" );
15329
// decoding may throw an error if the URL isn't UTF-8 (#9518)
15331
anchorUrl = decodeURIComponent( anchorUrl );
15332
} catch ( error ) {}
15334
locationUrl = decodeURIComponent( locationUrl );
15335
} catch ( error ) {}
15337
return anchor.hash.length > 1 && anchorUrl === locationUrl;
15341
_create: function() {
15343
options = this.options;
15345
this.running = false;
15348
.addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" )
15349
.toggleClass( "ui-tabs-collapsible", options.collapsible );
15351
this._processTabs();
15352
options.active = this._initialActive();
15354
// Take disabling tabs via class attribute from HTML
15355
// into account and update option properly.
15356
if ( $.isArray( options.disabled ) ) {
15357
options.disabled = $.unique( options.disabled.concat(
15358
$.map( this.tabs.filter( ".ui-state-disabled" ), function( li ) {
15359
return that.tabs.index( li );
15364
// check for length avoids error when initializing empty list
15365
if ( this.options.active !== false && this.anchors.length ) {
15366
this.active = this._findActive( options.active );
15373
if ( this.active.length ) {
15374
this.load( options.active );
15378
_initialActive: function() {
15379
var active = this.options.active,
15380
collapsible = this.options.collapsible,
15381
locationHash = location.hash.substring( 1 );
15383
if ( active === null ) {
15384
// check the fragment identifier in the URL
15385
if ( locationHash ) {
15386
this.tabs.each(function( i, tab ) {
15387
if ( $( tab ).attr( "aria-controls" ) === locationHash ) {
15394
// check for a tab marked active via a class
15395
if ( active === null ) {
15396
active = this.tabs.index( this.tabs.filter( ".ui-tabs-active" ) );
15399
// no active tab, set to false
15400
if ( active === null || active === -1 ) {
15401
active = this.tabs.length ? 0 : false;
15405
// handle numbers: negative, out of range
15406
if ( active !== false ) {
15407
active = this.tabs.index( this.tabs.eq( active ) );
15408
if ( active === -1 ) {
15409
active = collapsible ? false : 0;
15413
// don't allow collapsible: false and active: false
15414
if ( !collapsible && active === false && this.anchors.length ) {
15421
_getCreateEventData: function() {
15424
panel: !this.active.length ? $() : this._getPanelForTab( this.active )
15428
_tabKeydown: function( event ) {
15429
var focusedTab = $( this.document[0].activeElement ).closest( "li" ),
15430
selectedIndex = this.tabs.index( focusedTab ),
15431
goingForward = true;
15433
if ( this._handlePageNav( event ) ) {
15437
switch ( event.keyCode ) {
15438
case $.ui.keyCode.RIGHT:
15439
case $.ui.keyCode.DOWN:
15442
case $.ui.keyCode.UP:
15443
case $.ui.keyCode.LEFT:
15444
goingForward = false;
15447
case $.ui.keyCode.END:
15448
selectedIndex = this.anchors.length - 1;
15450
case $.ui.keyCode.HOME:
15453
case $.ui.keyCode.SPACE:
15454
// Activate only, no collapsing
15455
event.preventDefault();
15456
clearTimeout( this.activating );
15457
this._activate( selectedIndex );
15459
case $.ui.keyCode.ENTER:
15460
// Toggle (cancel delayed activation, allow collapsing)
15461
event.preventDefault();
15462
clearTimeout( this.activating );
15463
// Determine if we should collapse or activate
15464
this._activate( selectedIndex === this.options.active ? false : selectedIndex );
15470
// Focus the appropriate tab, based on which key was pressed
15471
event.preventDefault();
15472
clearTimeout( this.activating );
15473
selectedIndex = this._focusNextTab( selectedIndex, goingForward );
15475
// Navigating with control/command key will prevent automatic activation
15476
if ( !event.ctrlKey && !event.metaKey ) {
15478
// Update aria-selected immediately so that AT think the tab is already selected.
15479
// Otherwise AT may confuse the user by stating that they need to activate the tab,
15480
// but the tab will already be activated by the time the announcement finishes.
15481
focusedTab.attr( "aria-selected", "false" );
15482
this.tabs.eq( selectedIndex ).attr( "aria-selected", "true" );
15484
this.activating = this._delay(function() {
15485
this.option( "active", selectedIndex );
15490
_panelKeydown: function( event ) {
15491
if ( this._handlePageNav( event ) ) {
15495
// Ctrl+up moves focus to the current tab
15496
if ( event.ctrlKey && event.keyCode === $.ui.keyCode.UP ) {
15497
event.preventDefault();
15498
this.active.focus();
15502
// Alt+page up/down moves focus to the previous/next tab (and activates)
15503
_handlePageNav: function( event ) {
15504
if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_UP ) {
15505
this._activate( this._focusNextTab( this.options.active - 1, false ) );
15508
if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_DOWN ) {
15509
this._activate( this._focusNextTab( this.options.active + 1, true ) );
15514
_findNextTab: function( index, goingForward ) {
15515
var lastTabIndex = this.tabs.length - 1;
15517
function constrain() {
15518
if ( index > lastTabIndex ) {
15522
index = lastTabIndex;
15527
while ( $.inArray( constrain(), this.options.disabled ) !== -1 ) {
15528
index = goingForward ? index + 1 : index - 1;
15534
_focusNextTab: function( index, goingForward ) {
15535
index = this._findNextTab( index, goingForward );
15536
this.tabs.eq( index ).focus();
15540
_setOption: function( key, value ) {
15541
if ( key === "active" ) {
15542
// _activate() will handle invalid values and update this.options
15543
this._activate( value );
15547
if ( key === "disabled" ) {
15548
// don't use the widget factory's disabled handling
15549
this._setupDisabled( value );
15553
this._super( key, value);
15555
if ( key === "collapsible" ) {
15556
this.element.toggleClass( "ui-tabs-collapsible", value );
15557
// Setting collapsible: false while collapsed; open first panel
15558
if ( !value && this.options.active === false ) {
15559
this._activate( 0 );
15563
if ( key === "event" ) {
15564
this._setupEvents( value );
15567
if ( key === "heightStyle" ) {
15568
this._setupHeightStyle( value );
15572
_sanitizeSelector: function( hash ) {
15573
return hash ? hash.replace( /[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g, "\\$&" ) : "";
15576
refresh: function() {
15577
var options = this.options,
15578
lis = this.tablist.children( ":has(a[href])" );
15580
// get disabled tabs from class attribute from HTML
15581
// this will get converted to a boolean if needed in _refresh()
15582
options.disabled = $.map( lis.filter( ".ui-state-disabled" ), function( tab ) {
15583
return lis.index( tab );
15586
this._processTabs();
15588
// was collapsed or no tabs
15589
if ( options.active === false || !this.anchors.length ) {
15590
options.active = false;
15592
// was active, but active tab is gone
15593
} else if ( this.active.length && !$.contains( this.tablist[ 0 ], this.active[ 0 ] ) ) {
15594
// all remaining tabs are disabled
15595
if ( this.tabs.length === options.disabled.length ) {
15596
options.active = false;
15598
// activate previous tab
15600
this._activate( this._findNextTab( Math.max( 0, options.active - 1 ), false ) );
15602
// was active, active tab still exists
15604
// make sure active index is correct
15605
options.active = this.tabs.index( this.active );
15611
_refresh: function() {
15612
this._setupDisabled( this.options.disabled );
15613
this._setupEvents( this.options.event );
15614
this._setupHeightStyle( this.options.heightStyle );
15616
this.tabs.not( this.active ).attr({
15617
"aria-selected": "false",
15618
"aria-expanded": "false",
15621
this.panels.not( this._getPanelForTab( this.active ) )
15624
"aria-hidden": "true"
15627
// Make sure one tab is in the tab order
15628
if ( !this.active.length ) {
15629
this.tabs.eq( 0 ).attr( "tabIndex", 0 );
15632
.addClass( "ui-tabs-active ui-state-active" )
15634
"aria-selected": "true",
15635
"aria-expanded": "true",
15638
this._getPanelForTab( this.active )
15641
"aria-hidden": "false"
15646
_processTabs: function() {
15648
prevTabs = this.tabs,
15649
prevAnchors = this.anchors,
15650
prevPanels = this.panels;
15652
this.tablist = this._getList()
15653
.addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" )
15654
.attr( "role", "tablist" )
15656
// Prevent users from focusing disabled tabs via click
15657
.delegate( "> li", "mousedown" + this.eventNamespace, function( event ) {
15658
if ( $( this ).is( ".ui-state-disabled" ) ) {
15659
event.preventDefault();
15664
// Preventing the default action in mousedown doesn't prevent IE
15665
// from focusing the element, so if the anchor gets focused, blur.
15666
// We don't have to worry about focusing the previously focused
15667
// element since clicking on a non-focusable element should focus
15668
// the body anyway.
15669
.delegate( ".ui-tabs-anchor", "focus" + this.eventNamespace, function() {
15670
if ( $( this ).closest( "li" ).is( ".ui-state-disabled" ) ) {
15675
this.tabs = this.tablist.find( "> li:has(a[href])" )
15676
.addClass( "ui-state-default ui-corner-top" )
15682
this.anchors = this.tabs.map(function() {
15683
return $( "a", this )[ 0 ];
15685
.addClass( "ui-tabs-anchor" )
15687
role: "presentation",
15693
this.anchors.each(function( i, anchor ) {
15694
var selector, panel, panelId,
15695
anchorId = $( anchor ).uniqueId().attr( "id" ),
15696
tab = $( anchor ).closest( "li" ),
15697
originalAriaControls = tab.attr( "aria-controls" );
15700
if ( that._isLocal( anchor ) ) {
15701
selector = anchor.hash;
15702
panelId = selector.substring( 1 );
15703
panel = that.element.find( that._sanitizeSelector( selector ) );
15706
// If the tab doesn't already have aria-controls,
15707
// generate an id by using a throw-away element
15708
panelId = tab.attr( "aria-controls" ) || $( {} ).uniqueId()[ 0 ].id;
15709
selector = "#" + panelId;
15710
panel = that.element.find( selector );
15711
if ( !panel.length ) {
15712
panel = that._createPanel( panelId );
15713
panel.insertAfter( that.panels[ i - 1 ] || that.tablist );
15715
panel.attr( "aria-live", "polite" );
15718
if ( panel.length) {
15719
that.panels = that.panels.add( panel );
15721
if ( originalAriaControls ) {
15722
tab.data( "ui-tabs-aria-controls", originalAriaControls );
15725
"aria-controls": panelId,
15726
"aria-labelledby": anchorId
15728
panel.attr( "aria-labelledby", anchorId );
15732
.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
15733
.attr( "role", "tabpanel" );
15735
// Avoid memory leaks (#10056)
15737
this._off( prevTabs.not( this.tabs ) );
15738
this._off( prevAnchors.not( this.anchors ) );
15739
this._off( prevPanels.not( this.panels ) );
15743
// allow overriding how to find the list for rare usage scenarios (#7715)
15744
_getList: function() {
15745
return this.tablist || this.element.find( "ol,ul" ).eq( 0 );
15748
_createPanel: function( id ) {
15749
return $( "<div>" )
15751
.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
15752
.data( "ui-tabs-destroy", true );
15755
_setupDisabled: function( disabled ) {
15756
if ( $.isArray( disabled ) ) {
15757
if ( !disabled.length ) {
15759
} else if ( disabled.length === this.anchors.length ) {
15765
for ( var i = 0, li; ( li = this.tabs[ i ] ); i++ ) {
15766
if ( disabled === true || $.inArray( i, disabled ) !== -1 ) {
15768
.addClass( "ui-state-disabled" )
15769
.attr( "aria-disabled", "true" );
15772
.removeClass( "ui-state-disabled" )
15773
.removeAttr( "aria-disabled" );
15777
this.options.disabled = disabled;
15780
_setupEvents: function( event ) {
15783
$.each( event.split(" "), function( index, eventName ) {
15784
events[ eventName ] = "_eventHandler";
15788
this._off( this.anchors.add( this.tabs ).add( this.panels ) );
15789
// Always prevent the default action, even when disabled
15790
this._on( true, this.anchors, {
15791
click: function( event ) {
15792
event.preventDefault();
15795
this._on( this.anchors, events );
15796
this._on( this.tabs, { keydown: "_tabKeydown" } );
15797
this._on( this.panels, { keydown: "_panelKeydown" } );
15799
this._focusable( this.tabs );
15800
this._hoverable( this.tabs );
15803
_setupHeightStyle: function( heightStyle ) {
15805
parent = this.element.parent();
15807
if ( heightStyle === "fill" ) {
15808
maxHeight = parent.height();
15809
maxHeight -= this.element.outerHeight() - this.element.height();
15811
this.element.siblings( ":visible" ).each(function() {
15812
var elem = $( this ),
15813
position = elem.css( "position" );
15815
if ( position === "absolute" || position === "fixed" ) {
15818
maxHeight -= elem.outerHeight( true );
15821
this.element.children().not( this.panels ).each(function() {
15822
maxHeight -= $( this ).outerHeight( true );
15825
this.panels.each(function() {
15826
$( this ).height( Math.max( 0, maxHeight -
15827
$( this ).innerHeight() + $( this ).height() ) );
15829
.css( "overflow", "auto" );
15830
} else if ( heightStyle === "auto" ) {
15832
this.panels.each(function() {
15833
maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() );
15834
}).height( maxHeight );
15838
_eventHandler: function( event ) {
15839
var options = this.options,
15840
active = this.active,
15841
anchor = $( event.currentTarget ),
15842
tab = anchor.closest( "li" ),
15843
clickedIsActive = tab[ 0 ] === active[ 0 ],
15844
collapsing = clickedIsActive && options.collapsible,
15845
toShow = collapsing ? $() : this._getPanelForTab( tab ),
15846
toHide = !active.length ? $() : this._getPanelForTab( active ),
15850
newTab: collapsing ? $() : tab,
15854
event.preventDefault();
15856
if ( tab.hasClass( "ui-state-disabled" ) ||
15857
// tab is already loading
15858
tab.hasClass( "ui-tabs-loading" ) ||
15859
// can't switch durning an animation
15861
// click on active header, but not collapsible
15862
( clickedIsActive && !options.collapsible ) ||
15863
// allow canceling activation
15864
( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
15868
options.active = collapsing ? false : this.tabs.index( tab );
15870
this.active = clickedIsActive ? $() : tab;
15875
if ( !toHide.length && !toShow.length ) {
15876
$.error( "jQuery UI Tabs: Mismatching fragment identifier." );
15879
if ( toShow.length ) {
15880
this.load( this.tabs.index( tab ), event );
15882
this._toggle( event, eventData );
15885
// handles show/hide for selecting tabs
15886
_toggle: function( event, eventData ) {
15888
toShow = eventData.newPanel,
15889
toHide = eventData.oldPanel;
15891
this.running = true;
15893
function complete() {
15894
that.running = false;
15895
that._trigger( "activate", event, eventData );
15899
eventData.newTab.closest( "li" ).addClass( "ui-tabs-active ui-state-active" );
15901
if ( toShow.length && that.options.show ) {
15902
that._show( toShow, that.options.show, complete );
15909
// start out by hiding, then showing, then completing
15910
if ( toHide.length && this.options.hide ) {
15911
this._hide( toHide, this.options.hide, function() {
15912
eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" );
15916
eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" );
15921
toHide.attr( "aria-hidden", "true" );
15922
eventData.oldTab.attr({
15923
"aria-selected": "false",
15924
"aria-expanded": "false"
15926
// If we're switching tabs, remove the old tab from the tab order.
15927
// If we're opening from collapsed state, remove the previous tab from the tab order.
15928
// If we're collapsing, then keep the collapsing tab in the tab order.
15929
if ( toShow.length && toHide.length ) {
15930
eventData.oldTab.attr( "tabIndex", -1 );
15931
} else if ( toShow.length ) {
15932
this.tabs.filter(function() {
15933
return $( this ).attr( "tabIndex" ) === 0;
15935
.attr( "tabIndex", -1 );
15938
toShow.attr( "aria-hidden", "false" );
15939
eventData.newTab.attr({
15940
"aria-selected": "true",
15941
"aria-expanded": "true",
15946
_activate: function( index ) {
15948
active = this._findActive( index );
15950
// trying to activate the already active panel
15951
if ( active[ 0 ] === this.active[ 0 ] ) {
15955
// trying to collapse, simulate a click on the current active header
15956
if ( !active.length ) {
15957
active = this.active;
15960
anchor = active.find( ".ui-tabs-anchor" )[ 0 ];
15961
this._eventHandler({
15963
currentTarget: anchor,
15964
preventDefault: $.noop
15968
_findActive: function( index ) {
15969
return index === false ? $() : this.tabs.eq( index );
15972
_getIndex: function( index ) {
15973
// meta-function to give users option to provide a href string instead of a numerical index.
15974
if ( typeof index === "string" ) {
15975
index = this.anchors.index( this.anchors.filter( "[href$='" + index + "']" ) );
15981
_destroy: function() {
15986
this.element.removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" );
15989
.removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" )
15990
.removeAttr( "role" );
15993
.removeClass( "ui-tabs-anchor" )
15994
.removeAttr( "role" )
15995
.removeAttr( "tabIndex" )
15998
this.tablist.unbind( this.eventNamespace );
16000
this.tabs.add( this.panels ).each(function() {
16001
if ( $.data( this, "ui-tabs-destroy" ) ) {
16002
$( this ).remove();
16005
.removeClass( "ui-state-default ui-state-active ui-state-disabled " +
16006
"ui-corner-top ui-corner-bottom ui-widget-content ui-tabs-active ui-tabs-panel" )
16007
.removeAttr( "tabIndex" )
16008
.removeAttr( "aria-live" )
16009
.removeAttr( "aria-busy" )
16010
.removeAttr( "aria-selected" )
16011
.removeAttr( "aria-labelledby" )
16012
.removeAttr( "aria-hidden" )
16013
.removeAttr( "aria-expanded" )
16014
.removeAttr( "role" );
16018
this.tabs.each(function() {
16019
var li = $( this ),
16020
prev = li.data( "ui-tabs-aria-controls" );
16023
.attr( "aria-controls", prev )
16024
.removeData( "ui-tabs-aria-controls" );
16026
li.removeAttr( "aria-controls" );
16030
this.panels.show();
16032
if ( this.options.heightStyle !== "content" ) {
16033
this.panels.css( "height", "" );
16037
enable: function( index ) {
16038
var disabled = this.options.disabled;
16039
if ( disabled === false ) {
16043
if ( index === undefined ) {
16046
index = this._getIndex( index );
16047
if ( $.isArray( disabled ) ) {
16048
disabled = $.map( disabled, function( num ) {
16049
return num !== index ? num : null;
16052
disabled = $.map( this.tabs, function( li, num ) {
16053
return num !== index ? num : null;
16057
this._setupDisabled( disabled );
16060
disable: function( index ) {
16061
var disabled = this.options.disabled;
16062
if ( disabled === true ) {
16066
if ( index === undefined ) {
16069
index = this._getIndex( index );
16070
if ( $.inArray( index, disabled ) !== -1 ) {
16073
if ( $.isArray( disabled ) ) {
16074
disabled = $.merge( [ index ], disabled ).sort();
16076
disabled = [ index ];
16079
this._setupDisabled( disabled );
16082
load: function( index, event ) {
16083
index = this._getIndex( index );
16085
tab = this.tabs.eq( index ),
16086
anchor = tab.find( ".ui-tabs-anchor" ),
16087
panel = this._getPanelForTab( tab ),
16092
complete = function( jqXHR, status ) {
16093
if ( status === "abort" ) {
16094
that.panels.stop( false, true );
16097
tab.removeClass( "ui-tabs-loading" );
16098
panel.removeAttr( "aria-busy" );
16100
if ( jqXHR === that.xhr ) {
16106
if ( this._isLocal( anchor[ 0 ] ) ) {
16110
this.xhr = $.ajax( this._ajaxSettings( anchor, event, eventData ) );
16112
// support: jQuery <1.8
16113
// jQuery <1.8 returns false if the request is canceled in beforeSend,
16114
// but as of 1.8, $.ajax() always returns a jqXHR object.
16115
if ( this.xhr && this.xhr.statusText !== "canceled" ) {
16116
tab.addClass( "ui-tabs-loading" );
16117
panel.attr( "aria-busy", "true" );
16120
.done(function( response, status, jqXHR ) {
16121
// support: jQuery <1.8
16122
// http://bugs.jquery.com/ticket/11778
16123
setTimeout(function() {
16124
panel.html( response );
16125
that._trigger( "load", event, eventData );
16127
complete( jqXHR, status );
16130
.fail(function( jqXHR, status ) {
16131
// support: jQuery <1.8
16132
// http://bugs.jquery.com/ticket/11778
16133
setTimeout(function() {
16134
complete( jqXHR, status );
16140
_ajaxSettings: function( anchor, event, eventData ) {
16143
url: anchor.attr( "href" ),
16144
beforeSend: function( jqXHR, settings ) {
16145
return that._trigger( "beforeLoad", event,
16146
$.extend( { jqXHR: jqXHR, ajaxSettings: settings }, eventData ) );
16151
_getPanelForTab: function( tab ) {
16152
var id = $( tab ).attr( "aria-controls" );
16153
return this.element.find( this._sanitizeSelector( "#" + id ) );
16159
* jQuery UI Tooltip 1.11.4
16160
* http://jqueryui.com
16162
* Copyright jQuery Foundation and other contributors
16163
* Released under the MIT license.
16164
* http://jquery.org/license
16166
* http://api.jqueryui.com/tooltip/
16170
var tooltip = $.widget( "ui.tooltip", {
16173
content: function() {
16174
// support: IE<9, Opera in jQuery <1.7
16175
// .text() can't accept undefined, so coerce to a string
16176
var title = $( this ).attr( "title" ) || "";
16177
// Escape title, since we're going from an attribute to raw HTML
16178
return $( "<a>" ).text( title ).html();
16181
// Disabled elements have inconsistent behavior across browsers (#8661)
16182
items: "[title]:not([disabled])",
16186
collision: "flipfit flip"
16189
tooltipClass: null,
16197
_addDescribedBy: function( elem, id ) {
16198
var describedby = (elem.attr( "aria-describedby" ) || "").split( /\s+/ );
16199
describedby.push( id );
16201
.data( "ui-tooltip-id", id )
16202
.attr( "aria-describedby", $.trim( describedby.join( " " ) ) );
16205
_removeDescribedBy: function( elem ) {
16206
var id = elem.data( "ui-tooltip-id" ),
16207
describedby = (elem.attr( "aria-describedby" ) || "").split( /\s+/ ),
16208
index = $.inArray( id, describedby );
16210
if ( index !== -1 ) {
16211
describedby.splice( index, 1 );
16214
elem.removeData( "ui-tooltip-id" );
16215
describedby = $.trim( describedby.join( " " ) );
16216
if ( describedby ) {
16217
elem.attr( "aria-describedby", describedby );
16219
elem.removeAttr( "aria-describedby" );
16223
_create: function() {
16229
// IDs of generated tooltips, needed for destroy
16230
this.tooltips = {};
16232
// IDs of parent tooltips where we removed the title attribute
16235
if ( this.options.disabled ) {
16239
// Append the aria-live region so tooltips announce correctly
16240
this.liveRegion = $( "<div>" )
16243
"aria-live": "assertive",
16244
"aria-relevant": "additions"
16246
.addClass( "ui-helper-hidden-accessible" )
16247
.appendTo( this.document[ 0 ].body );
16250
_setOption: function( key, value ) {
16253
if ( key === "disabled" ) {
16254
this[ value ? "_disable" : "_enable" ]();
16255
this.options[ key ] = value;
16256
// disable element style changes
16260
this._super( key, value );
16262
if ( key === "content" ) {
16263
$.each( this.tooltips, function( id, tooltipData ) {
16264
that._updateContent( tooltipData.element );
16269
_disable: function() {
16272
// close open tooltips
16273
$.each( this.tooltips, function( id, tooltipData ) {
16274
var event = $.Event( "blur" );
16275
event.target = event.currentTarget = tooltipData.element[ 0 ];
16276
that.close( event, true );
16279
// remove title attributes to prevent native tooltips
16280
this.element.find( this.options.items ).addBack().each(function() {
16281
var element = $( this );
16282
if ( element.is( "[title]" ) ) {
16284
.data( "ui-tooltip-title", element.attr( "title" ) )
16285
.removeAttr( "title" );
16290
_enable: function() {
16291
// restore title attributes
16292
this.element.find( this.options.items ).addBack().each(function() {
16293
var element = $( this );
16294
if ( element.data( "ui-tooltip-title" ) ) {
16295
element.attr( "title", element.data( "ui-tooltip-title" ) );
16300
open: function( event ) {
16302
target = $( event ? event.target : this.element )
16303
// we need closest here due to mouseover bubbling,
16304
// but always pointing at the same event target
16305
.closest( this.options.items );
16307
// No element to show a tooltip for or the tooltip is already open
16308
if ( !target.length || target.data( "ui-tooltip-id" ) ) {
16312
if ( target.attr( "title" ) ) {
16313
target.data( "ui-tooltip-title", target.attr( "title" ) );
16316
target.data( "ui-tooltip-open", true );
16318
// kill parent tooltips, custom or native, for hover
16319
if ( event && event.type === "mouseover" ) {
16320
target.parents().each(function() {
16321
var parent = $( this ),
16323
if ( parent.data( "ui-tooltip-open" ) ) {
16324
blurEvent = $.Event( "blur" );
16325
blurEvent.target = blurEvent.currentTarget = this;
16326
that.close( blurEvent, true );
16328
if ( parent.attr( "title" ) ) {
16330
that.parents[ this.id ] = {
16332
title: parent.attr( "title" )
16334
parent.attr( "title", "" );
16339
this._registerCloseHandlers( event, target );
16340
this._updateContent( target, event );
16343
_updateContent: function( target, event ) {
16345
contentOption = this.options.content,
16347
eventType = event ? event.type : null;
16349
if ( typeof contentOption === "string" ) {
16350
return this._open( event, target, contentOption );
16353
content = contentOption.call( target[0], function( response ) {
16355
// IE may instantly serve a cached response for ajax requests
16356
// delay this call to _open so the other call to _open runs first
16357
that._delay(function() {
16359
// Ignore async response if tooltip was closed already
16360
if ( !target.data( "ui-tooltip-open" ) ) {
16364
// jQuery creates a special event for focusin when it doesn't
16365
// exist natively. To improve performance, the native event
16366
// object is reused and the type is changed. Therefore, we can't
16367
// rely on the type being correct after the event finished
16368
// bubbling, so we set it back to the previous value. (#8740)
16370
event.type = eventType;
16372
this._open( event, target, response );
16376
this._open( event, target, content );
16380
_open: function( event, target, content ) {
16381
var tooltipData, tooltip, delayedShow, a11yContent,
16382
positionOption = $.extend( {}, this.options.position );
16388
// Content can be updated multiple times. If the tooltip already
16389
// exists, then just update the content and bail.
16390
tooltipData = this._find( target );
16391
if ( tooltipData ) {
16392
tooltipData.tooltip.find( ".ui-tooltip-content" ).html( content );
16396
// if we have a title, clear it to prevent the native tooltip
16397
// we have to check first to avoid defining a title if none exists
16398
// (we don't want to cause an element to start matching [title])
16400
// We use removeAttr only for key events, to allow IE to export the correct
16401
// accessible attributes. For mouse events, set to empty string to avoid
16402
// native tooltip showing up (happens only when removing inside mouseover).
16403
if ( target.is( "[title]" ) ) {
16404
if ( event && event.type === "mouseover" ) {
16405
target.attr( "title", "" );
16407
target.removeAttr( "title" );
16411
tooltipData = this._tooltip( target );
16412
tooltip = tooltipData.tooltip;
16413
this._addDescribedBy( target, tooltip.attr( "id" ) );
16414
tooltip.find( ".ui-tooltip-content" ).html( content );
16416
// Support: Voiceover on OS X, JAWS on IE <= 9
16417
// JAWS announces deletions even when aria-relevant="additions"
16418
// Voiceover will sometimes re-read the entire log region's contents from the beginning
16419
this.liveRegion.children().hide();
16420
if ( content.clone ) {
16421
a11yContent = content.clone();
16422
a11yContent.removeAttr( "id" ).find( "[id]" ).removeAttr( "id" );
16424
a11yContent = content;
16426
$( "<div>" ).html( a11yContent ).appendTo( this.liveRegion );
16428
function position( event ) {
16429
positionOption.of = event;
16430
if ( tooltip.is( ":hidden" ) ) {
16433
tooltip.position( positionOption );
16435
if ( this.options.track && event && /^mouse/.test( event.type ) ) {
16436
this._on( this.document, {
16437
mousemove: position
16439
// trigger once to override element-relative positioning
16442
tooltip.position( $.extend({
16444
}, this.options.position ) );
16449
this._show( tooltip, this.options.show );
16450
// Handle tracking tooltips that are shown with a delay (#8644). As soon
16451
// as the tooltip is visible, position the tooltip using the most recent
16453
if ( this.options.show && this.options.show.delay ) {
16454
delayedShow = this.delayedShow = setInterval(function() {
16455
if ( tooltip.is( ":visible" ) ) {
16456
position( positionOption.of );
16457
clearInterval( delayedShow );
16459
}, $.fx.interval );
16462
this._trigger( "open", event, { tooltip: tooltip } );
16465
_registerCloseHandlers: function( event, target ) {
16467
keyup: function( event ) {
16468
if ( event.keyCode === $.ui.keyCode.ESCAPE ) {
16469
var fakeEvent = $.Event(event);
16470
fakeEvent.currentTarget = target[0];
16471
this.close( fakeEvent, true );
16476
// Only bind remove handler for delegated targets. Non-delegated
16477
// tooltips will handle this in destroy.
16478
if ( target[ 0 ] !== this.element[ 0 ] ) {
16479
events.remove = function() {
16480
this._removeTooltip( this._find( target ).tooltip );
16484
if ( !event || event.type === "mouseover" ) {
16485
events.mouseleave = "close";
16487
if ( !event || event.type === "focusin" ) {
16488
events.focusout = "close";
16490
this._on( true, target, events );
16493
close: function( event ) {
16496
target = $( event ? event.currentTarget : this.element ),
16497
tooltipData = this._find( target );
16499
// The tooltip may already be closed
16500
if ( !tooltipData ) {
16502
// We set ui-tooltip-open immediately upon open (in open()), but only set the
16503
// additional data once there's actually content to show (in _open()). So even if the
16504
// tooltip doesn't have full data, we always remove ui-tooltip-open in case we're in
16505
// the period between open() and _open().
16506
target.removeData( "ui-tooltip-open" );
16510
tooltip = tooltipData.tooltip;
16512
// disabling closes the tooltip, so we need to track when we're closing
16513
// to avoid an infinite loop in case the tooltip becomes disabled on close
16514
if ( tooltipData.closing ) {
16518
// Clear the interval for delayed tracking tooltips
16519
clearInterval( this.delayedShow );
16521
// only set title if we had one before (see comment in _open())
16522
// If the title attribute has changed since open(), don't restore
16523
if ( target.data( "ui-tooltip-title" ) && !target.attr( "title" ) ) {
16524
target.attr( "title", target.data( "ui-tooltip-title" ) );
16527
this._removeDescribedBy( target );
16529
tooltipData.hiding = true;
16530
tooltip.stop( true );
16531
this._hide( tooltip, this.options.hide, function() {
16532
that._removeTooltip( $( this ) );
16535
target.removeData( "ui-tooltip-open" );
16536
this._off( target, "mouseleave focusout keyup" );
16538
// Remove 'remove' binding only on delegated targets
16539
if ( target[ 0 ] !== this.element[ 0 ] ) {
16540
this._off( target, "remove" );
16542
this._off( this.document, "mousemove" );
16544
if ( event && event.type === "mouseleave" ) {
16545
$.each( this.parents, function( id, parent ) {
16546
$( parent.element ).attr( "title", parent.title );
16547
delete that.parents[ id ];
16551
tooltipData.closing = true;
16552
this._trigger( "close", event, { tooltip: tooltip } );
16553
if ( !tooltipData.hiding ) {
16554
tooltipData.closing = false;
16558
_tooltip: function( element ) {
16559
var tooltip = $( "<div>" )
16560
.attr( "role", "tooltip" )
16561
.addClass( "ui-tooltip ui-widget ui-corner-all ui-widget-content " +
16562
( this.options.tooltipClass || "" ) ),
16563
id = tooltip.uniqueId().attr( "id" );
16566
.addClass( "ui-tooltip-content" )
16567
.appendTo( tooltip );
16569
tooltip.appendTo( this.document[0].body );
16571
return this.tooltips[ id ] = {
16577
_find: function( target ) {
16578
var id = target.data( "ui-tooltip-id" );
16579
return id ? this.tooltips[ id ] : null;
16582
_removeTooltip: function( tooltip ) {
16584
delete this.tooltips[ tooltip.attr( "id" ) ];
16587
_destroy: function() {
16590
// close open tooltips
16591
$.each( this.tooltips, function( id, tooltipData ) {
16592
// Delegate to close method to handle common cleanup
16593
var event = $.Event( "blur" ),
16594
element = tooltipData.element;
16595
event.target = event.currentTarget = element[ 0 ];
16596
that.close( event, true );
16598
// Remove immediately; destroying an open tooltip doesn't use the
16600
$( "#" + id ).remove();
16602
// Restore the title
16603
if ( element.data( "ui-tooltip-title" ) ) {
16604
// If the title attribute has changed since open(), don't restore
16605
if ( !element.attr( "title" ) ) {
16606
element.attr( "title", element.data( "ui-tooltip-title" ) );
16608
element.removeData( "ui-tooltip-title" );
16611
this.liveRegion.remove();
b'\\ No newline at end of file'