1
/*! jQuery UI - v1.11.0 - 2014-06-26
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 2014 jQuery Foundation and other contributors; Licensed MIT */
7
if ( typeof define === "function" && define.amd ) {
9
// AMD. Register as an anonymous module.
10
define([ "jquery" ], factory );
18
* jQuery UI Core 1.11.0
21
* Copyright 2014 jQuery Foundation and other contributors
22
* Released under the MIT license.
23
* http://jquery.org/license
25
* http://api.jqueryui.com/category/ui-core/
29
// $.ui might exist from components with no dependencies, e.g., $.ui.position
57
scrollParent: function() {
58
var position = this.css( "position" ),
59
excludeStaticParent = position === "absolute",
60
scrollParent = this.parents().filter( function() {
61
var parent = $( this );
62
if ( excludeStaticParent && parent.css( "position" ) === "static" ) {
65
return (/(auto|scroll)/).test( parent.css( "overflow" ) + parent.css( "overflow-y" ) + parent.css( "overflow-x" ) );
68
return position === "fixed" || !scrollParent.length ? $( this[ 0 ].ownerDocument || document ) : scrollParent;
71
uniqueId: (function() {
75
return this.each(function() {
77
this.id = "ui-id-" + ( ++uuid );
83
removeUniqueId: function() {
84
return this.each(function() {
85
if ( /^ui-id-\d+$/.test( this.id ) ) {
86
$( this ).removeAttr( "id" );
93
function focusable( element, isTabIndexNotNaN ) {
94
var map, mapName, img,
95
nodeName = element.nodeName.toLowerCase();
96
if ( "area" === nodeName ) {
97
map = element.parentNode;
99
if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
102
img = $( "img[usemap=#" + mapName + "]" )[0];
103
return !!img && visible( img );
105
return ( /input|select|textarea|button|object/.test( nodeName ) ?
108
element.href || isTabIndexNotNaN :
110
// the element and all of its ancestors must be visible
114
function visible( element ) {
115
return $.expr.filters.visible( element ) &&
116
!$( element ).parents().addBack().filter(function() {
117
return $.css( this, "visibility" ) === "hidden";
121
$.extend( $.expr[ ":" ], {
122
data: $.expr.createPseudo ?
123
$.expr.createPseudo(function( dataName ) {
124
return function( elem ) {
125
return !!$.data( elem, dataName );
128
// support: jQuery <1.8
129
function( elem, i, match ) {
130
return !!$.data( elem, match[ 3 ] );
133
focusable: function( element ) {
134
return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) );
137
tabbable: function( element ) {
138
var tabIndex = $.attr( element, "tabindex" ),
139
isTabIndexNaN = isNaN( tabIndex );
140
return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN );
144
// support: jQuery <1.8
145
if ( !$( "<a>" ).outerWidth( 1 ).jquery ) {
146
$.each( [ "Width", "Height" ], function( i, name ) {
147
var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
148
type = name.toLowerCase(),
150
innerWidth: $.fn.innerWidth,
151
innerHeight: $.fn.innerHeight,
152
outerWidth: $.fn.outerWidth,
153
outerHeight: $.fn.outerHeight
156
function reduce( elem, size, border, margin ) {
157
$.each( side, function() {
158
size -= parseFloat( $.css( elem, "padding" + this ) ) || 0;
160
size -= parseFloat( $.css( elem, "border" + this + "Width" ) ) || 0;
163
size -= parseFloat( $.css( elem, "margin" + this ) ) || 0;
169
$.fn[ "inner" + name ] = function( size ) {
170
if ( size === undefined ) {
171
return orig[ "inner" + name ].call( this );
174
return this.each(function() {
175
$( this ).css( type, reduce( this, size ) + "px" );
179
$.fn[ "outer" + name] = function( size, margin ) {
180
if ( typeof size !== "number" ) {
181
return orig[ "outer" + name ].call( this, size );
184
return this.each(function() {
185
$( this).css( type, reduce( this, size, true, margin ) + "px" );
191
// support: jQuery <1.8
192
if ( !$.fn.addBack ) {
193
$.fn.addBack = function( selector ) {
194
return this.add( selector == null ?
195
this.prevObject : this.prevObject.filter( selector )
200
// support: jQuery 1.6.1, 1.6.2 (http://bugs.jquery.com/ticket/9413)
201
if ( $( "<a>" ).data( "a-b", "a" ).removeData( "a-b" ).data( "a-b" ) ) {
202
$.fn.removeData = (function( removeData ) {
203
return function( key ) {
204
if ( arguments.length ) {
205
return removeData.call( this, $.camelCase( key ) );
207
return removeData.call( this );
210
})( $.fn.removeData );
214
$.ui.ie = !!/msie [\w.]+/.exec( navigator.userAgent.toLowerCase() );
217
focus: (function( orig ) {
218
return function( delay, fn ) {
219
return typeof delay === "number" ?
220
this.each(function() {
222
setTimeout(function() {
229
orig.apply( this, arguments );
233
disableSelection: (function() {
234
var eventType = "onselectstart" in document.createElement( "div" ) ?
239
return this.bind( eventType + ".ui-disableSelection", function( event ) {
240
event.preventDefault();
245
enableSelection: function() {
246
return this.unbind( ".ui-disableSelection" );
249
zIndex: function( zIndex ) {
250
if ( zIndex !== undefined ) {
251
return this.css( "zIndex", zIndex );
255
var elem = $( this[ 0 ] ), position, value;
256
while ( elem.length && elem[ 0 ] !== document ) {
257
// Ignore z-index if position is set to a value where z-index is ignored by the browser
258
// This makes behavior of this function consistent across browsers
259
// WebKit always returns auto if the element is positioned
260
position = elem.css( "position" );
261
if ( position === "absolute" || position === "relative" || position === "fixed" ) {
262
// IE returns 0 when zIndex is not specified
263
// other browsers return a string
264
// we ignore the case of nested elements with an explicit value of 0
265
// <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
266
value = parseInt( elem.css( "zIndex" ), 10 );
267
if ( !isNaN( value ) && value !== 0 ) {
271
elem = elem.parent();
279
// $.ui.plugin is deprecated. Use $.widget() extensions instead.
281
add: function( module, option, set ) {
283
proto = $.ui[ module ].prototype;
285
proto.plugins[ i ] = proto.plugins[ i ] || [];
286
proto.plugins[ i ].push( [ option, set[ i ] ] );
289
call: function( instance, name, args, allowDisconnected ) {
291
set = instance.plugins[ name ];
297
if ( !allowDisconnected && ( !instance.element[ 0 ].parentNode || instance.element[ 0 ].parentNode.nodeType === 11 ) ) {
301
for ( i = 0; i < set.length; i++ ) {
302
if ( instance.options[ set[ i ][ 0 ] ] ) {
303
set[ i ][ 1 ].apply( instance.element, args );
311
* jQuery UI Widget 1.11.0
312
* http://jqueryui.com
314
* Copyright 2014 jQuery Foundation and other contributors
315
* Released under the MIT license.
316
* http://jquery.org/license
318
* http://api.jqueryui.com/jQuery.widget/
323
widget_slice = Array.prototype.slice;
325
$.cleanData = (function( orig ) {
326
return function( elems ) {
327
for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
329
$( elem ).triggerHandler( "remove" );
330
// http://bugs.jquery.com/ticket/8235
337
$.widget = function( name, base, prototype ) {
338
var fullName, existingConstructor, constructor, basePrototype,
339
// proxiedPrototype allows the provided prototype to remain unmodified
340
// so that it can be used as a mixin for multiple widgets (#8876)
341
proxiedPrototype = {},
342
namespace = name.split( "." )[ 0 ];
344
name = name.split( "." )[ 1 ];
345
fullName = namespace + "-" + name;
352
// create selector for plugin
353
$.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) {
354
return !!$.data( elem, fullName );
357
$[ namespace ] = $[ namespace ] || {};
358
existingConstructor = $[ namespace ][ name ];
359
constructor = $[ namespace ][ name ] = function( options, element ) {
360
// allow instantiation without "new" keyword
361
if ( !this._createWidget ) {
362
return new constructor( options, element );
365
// allow instantiation without initializing for simple inheritance
366
// must use "new" keyword (the code above always passes args)
367
if ( arguments.length ) {
368
this._createWidget( options, element );
371
// extend with the existing constructor to carry over any static properties
372
$.extend( constructor, existingConstructor, {
373
version: prototype.version,
374
// copy the object used to create the prototype in case we need to
375
// redefine the widget later
376
_proto: $.extend( {}, prototype ),
377
// track widgets that inherit from this widget in case this widget is
378
// redefined after a widget inherits from it
379
_childConstructors: []
382
basePrototype = new base();
383
// we need to make the options hash a property directly on the new instance
384
// otherwise we'll modify the options hash on the prototype that we're
386
basePrototype.options = $.widget.extend( {}, basePrototype.options );
387
$.each( prototype, function( prop, value ) {
388
if ( !$.isFunction( value ) ) {
389
proxiedPrototype[ prop ] = value;
392
proxiedPrototype[ prop ] = (function() {
393
var _super = function() {
394
return base.prototype[ prop ].apply( this, arguments );
396
_superApply = function( args ) {
397
return base.prototype[ prop ].apply( this, args );
400
var __super = this._super,
401
__superApply = this._superApply,
404
this._super = _super;
405
this._superApply = _superApply;
407
returnValue = value.apply( this, arguments );
409
this._super = __super;
410
this._superApply = __superApply;
416
constructor.prototype = $.widget.extend( basePrototype, {
417
// TODO: remove support for widgetEventPrefix
418
// always use the name + a colon as the prefix, e.g., draggable:start
419
// don't prefix for widgets that aren't DOM-based
420
widgetEventPrefix: existingConstructor ? (basePrototype.widgetEventPrefix || name) : name
421
}, proxiedPrototype, {
422
constructor: constructor,
423
namespace: namespace,
425
widgetFullName: fullName
428
// If this widget is being redefined then we need to find all widgets that
429
// are inheriting from it and redefine all of them so that they inherit from
430
// the new version of this widget. We're essentially trying to replace one
431
// level in the prototype chain.
432
if ( existingConstructor ) {
433
$.each( existingConstructor._childConstructors, function( i, child ) {
434
var childPrototype = child.prototype;
436
// redefine the child widget using the same prototype that was
437
// originally used, but inherit from the new version of the base
438
$.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, child._proto );
440
// remove the list of existing child constructors from the old constructor
441
// so the old child constructors can be garbage collected
442
delete existingConstructor._childConstructors;
444
base._childConstructors.push( constructor );
447
$.widget.bridge( name, constructor );
452
$.widget.extend = function( target ) {
453
var input = widget_slice.call( arguments, 1 ),
455
inputLength = input.length,
458
for ( ; inputIndex < inputLength; inputIndex++ ) {
459
for ( key in input[ inputIndex ] ) {
460
value = input[ inputIndex ][ key ];
461
if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) {
463
if ( $.isPlainObject( value ) ) {
464
target[ key ] = $.isPlainObject( target[ key ] ) ?
465
$.widget.extend( {}, target[ key ], value ) :
466
// Don't extend strings, arrays, etc. with objects
467
$.widget.extend( {}, value );
468
// Copy everything else by reference
470
target[ key ] = value;
478
$.widget.bridge = function( name, object ) {
479
var fullName = object.prototype.widgetFullName || name;
480
$.fn[ name ] = function( options ) {
481
var isMethodCall = typeof options === "string",
482
args = widget_slice.call( arguments, 1 ),
485
// allow multiple hashes to be passed on init
486
options = !isMethodCall && args.length ?
487
$.widget.extend.apply( null, [ options ].concat(args) ) :
490
if ( isMethodCall ) {
491
this.each(function() {
493
instance = $.data( this, fullName );
494
if ( options === "instance" ) {
495
returnValue = instance;
499
return $.error( "cannot call methods on " + name + " prior to initialization; " +
500
"attempted to call method '" + options + "'" );
502
if ( !$.isFunction( instance[options] ) || options.charAt( 0 ) === "_" ) {
503
return $.error( "no such method '" + options + "' for " + name + " widget instance" );
505
methodValue = instance[ options ].apply( instance, args );
506
if ( methodValue !== instance && methodValue !== undefined ) {
507
returnValue = methodValue && methodValue.jquery ?
508
returnValue.pushStack( methodValue.get() ) :
514
this.each(function() {
515
var instance = $.data( this, fullName );
517
instance.option( options || {} );
518
if ( instance._init ) {
522
$.data( this, fullName, new object( options, this ) );
531
$.Widget = function( /* options, element */ ) {};
532
$.Widget._childConstructors = [];
534
$.Widget.prototype = {
535
widgetName: "widget",
536
widgetEventPrefix: "",
537
defaultElement: "<div>",
544
_createWidget: function( options, element ) {
545
element = $( element || this.defaultElement || this )[ 0 ];
546
this.element = $( element );
547
this.uuid = widget_uuid++;
548
this.eventNamespace = "." + this.widgetName + this.uuid;
549
this.options = $.widget.extend( {},
551
this._getCreateOptions(),
555
this.hoverable = $();
556
this.focusable = $();
558
if ( element !== this ) {
559
$.data( element, this.widgetFullName, this );
560
this._on( true, this.element, {
561
remove: function( event ) {
562
if ( event.target === element ) {
567
this.document = $( element.style ?
568
// element within the document
569
element.ownerDocument :
570
// element is window or document
571
element.document || element );
572
this.window = $( this.document[0].defaultView || this.document[0].parentWindow );
576
this._trigger( "create", null, this._getCreateEventData() );
579
_getCreateOptions: $.noop,
580
_getCreateEventData: $.noop,
584
destroy: function() {
586
// we can probably remove the unbind calls in 2.0
587
// all event bindings should go through this._on()
589
.unbind( this.eventNamespace )
590
.removeData( this.widgetFullName )
591
// support: jquery <1.6.3
592
// http://bugs.jquery.com/ticket/9413
593
.removeData( $.camelCase( this.widgetFullName ) );
595
.unbind( this.eventNamespace )
596
.removeAttr( "aria-disabled" )
598
this.widgetFullName + "-disabled " +
599
"ui-state-disabled" );
601
// clean up events and states
602
this.bindings.unbind( this.eventNamespace );
603
this.hoverable.removeClass( "ui-state-hover" );
604
this.focusable.removeClass( "ui-state-focus" );
612
option: function( key, value ) {
618
if ( arguments.length === 0 ) {
619
// don't return a reference to the internal hash
620
return $.widget.extend( {}, this.options );
623
if ( typeof key === "string" ) {
624
// handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
626
parts = key.split( "." );
628
if ( parts.length ) {
629
curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );
630
for ( i = 0; i < parts.length - 1; i++ ) {
631
curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};
632
curOption = curOption[ parts[ i ] ];
635
if ( arguments.length === 1 ) {
636
return curOption[ key ] === undefined ? null : curOption[ key ];
638
curOption[ key ] = value;
640
if ( arguments.length === 1 ) {
641
return this.options[ key ] === undefined ? null : this.options[ key ];
643
options[ key ] = value;
647
this._setOptions( options );
651
_setOptions: function( options ) {
654
for ( key in options ) {
655
this._setOption( key, options[ key ] );
660
_setOption: function( key, value ) {
661
this.options[ key ] = value;
663
if ( key === "disabled" ) {
665
.toggleClass( this.widgetFullName + "-disabled", !!value );
667
// If the widget is becoming disabled, then nothing is interactive
669
this.hoverable.removeClass( "ui-state-hover" );
670
this.focusable.removeClass( "ui-state-focus" );
678
return this._setOptions({ disabled: false });
680
disable: function() {
681
return this._setOptions({ disabled: true });
684
_on: function( suppressDisabledCheck, element, handlers ) {
688
// no suppressDisabledCheck flag, shuffle arguments
689
if ( typeof suppressDisabledCheck !== "boolean" ) {
691
element = suppressDisabledCheck;
692
suppressDisabledCheck = false;
695
// no element argument, shuffle and use this.element
698
element = this.element;
699
delegateElement = this.widget();
701
element = delegateElement = $( element );
702
this.bindings = this.bindings.add( element );
705
$.each( handlers, function( event, handler ) {
706
function handlerProxy() {
707
// allow widgets to customize the disabled handling
708
// - disabled as an array instead of boolean
709
// - disabled class as method for disabling individual parts
710
if ( !suppressDisabledCheck &&
711
( instance.options.disabled === true ||
712
$( this ).hasClass( "ui-state-disabled" ) ) ) {
715
return ( typeof handler === "string" ? instance[ handler ] : handler )
716
.apply( instance, arguments );
719
// copy the guid so direct unbinding works
720
if ( typeof handler !== "string" ) {
721
handlerProxy.guid = handler.guid =
722
handler.guid || handlerProxy.guid || $.guid++;
725
var match = event.match( /^([\w:-]*)\s*(.*)$/ ),
726
eventName = match[1] + instance.eventNamespace,
729
delegateElement.delegate( selector, eventName, handlerProxy );
731
element.bind( eventName, handlerProxy );
736
_off: function( element, eventName ) {
737
eventName = (eventName || "").split( " " ).join( this.eventNamespace + " " ) + this.eventNamespace;
738
element.unbind( eventName ).undelegate( eventName );
741
_delay: function( handler, delay ) {
742
function handlerProxy() {
743
return ( typeof handler === "string" ? instance[ handler ] : handler )
744
.apply( instance, arguments );
747
return setTimeout( handlerProxy, delay || 0 );
750
_hoverable: function( element ) {
751
this.hoverable = this.hoverable.add( element );
753
mouseenter: function( event ) {
754
$( event.currentTarget ).addClass( "ui-state-hover" );
756
mouseleave: function( event ) {
757
$( event.currentTarget ).removeClass( "ui-state-hover" );
762
_focusable: function( element ) {
763
this.focusable = this.focusable.add( element );
765
focusin: function( event ) {
766
$( event.currentTarget ).addClass( "ui-state-focus" );
768
focusout: function( event ) {
769
$( event.currentTarget ).removeClass( "ui-state-focus" );
774
_trigger: function( type, event, data ) {
776
callback = this.options[ type ];
779
event = $.Event( event );
780
event.type = ( type === this.widgetEventPrefix ?
782
this.widgetEventPrefix + type ).toLowerCase();
783
// the original event may come from any element
784
// so we need to reset the target on the new event
785
event.target = this.element[ 0 ];
787
// copy original event properties over to the new event
788
orig = event.originalEvent;
790
for ( prop in orig ) {
791
if ( !( prop in event ) ) {
792
event[ prop ] = orig[ prop ];
797
this.element.trigger( event, data );
798
return !( $.isFunction( callback ) &&
799
callback.apply( this.element[0], [ event ].concat( data ) ) === false ||
800
event.isDefaultPrevented() );
804
$.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {
805
$.Widget.prototype[ "_" + method ] = function( element, options, callback ) {
806
if ( typeof options === "string" ) {
807
options = { effect: options };
810
effectName = !options ?
812
options === true || typeof options === "number" ?
814
options.effect || defaultEffect;
815
options = options || {};
816
if ( typeof options === "number" ) {
817
options = { duration: options };
819
hasOptions = !$.isEmptyObject( options );
820
options.complete = callback;
821
if ( options.delay ) {
822
element.delay( options.delay );
824
if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) {
825
element[ method ]( options );
826
} else if ( effectName !== method && element[ effectName ] ) {
827
element[ effectName ]( options.duration, options.easing, callback );
829
element.queue(function( next ) {
830
$( this )[ method ]();
832
callback.call( element[ 0 ] );
840
var widget = $.widget;
844
* jQuery UI Mouse 1.11.0
845
* http://jqueryui.com
847
* Copyright 2014 jQuery Foundation and other contributors
848
* Released under the MIT license.
849
* http://jquery.org/license
851
* http://api.jqueryui.com/mouse/
855
var mouseHandled = false;
856
$( document ).mouseup( function() {
857
mouseHandled = false;
860
var mouse = $.widget("ui.mouse", {
863
cancel: "input,textarea,button,select,option",
867
_mouseInit: function() {
871
.bind("mousedown." + this.widgetName, function(event) {
872
return that._mouseDown(event);
874
.bind("click." + this.widgetName, function(event) {
875
if (true === $.data(event.target, that.widgetName + ".preventClickEvent")) {
876
$.removeData(event.target, that.widgetName + ".preventClickEvent");
877
event.stopImmediatePropagation();
882
this.started = false;
885
// TODO: make sure destroying one instance of mouse doesn't mess with
886
// other instances of mouse
887
_mouseDestroy: function() {
888
this.element.unbind("." + this.widgetName);
889
if ( this._mouseMoveDelegate ) {
891
.unbind("mousemove." + this.widgetName, this._mouseMoveDelegate)
892
.unbind("mouseup." + this.widgetName, this._mouseUpDelegate);
896
_mouseDown: function(event) {
897
// don't let more than one widget handle mouseStart
898
if ( mouseHandled ) {
902
// we may have missed mouseup (out of window)
903
(this._mouseStarted && this._mouseUp(event));
905
this._mouseDownEvent = event;
908
btnIsLeft = (event.which === 1),
909
// event.target.nodeName works around a bug in IE 8 with
910
// disabled inputs (#7620)
911
elIsCancel = (typeof this.options.cancel === "string" && event.target.nodeName ? $(event.target).closest(this.options.cancel).length : false);
912
if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
916
this.mouseDelayMet = !this.options.delay;
917
if (!this.mouseDelayMet) {
918
this._mouseDelayTimer = setTimeout(function() {
919
that.mouseDelayMet = true;
920
}, this.options.delay);
923
if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
924
this._mouseStarted = (this._mouseStart(event) !== false);
925
if (!this._mouseStarted) {
926
event.preventDefault();
931
// Click event may never have fired (Gecko & Opera)
932
if (true === $.data(event.target, this.widgetName + ".preventClickEvent")) {
933
$.removeData(event.target, this.widgetName + ".preventClickEvent");
936
// these delegates are required to keep context
937
this._mouseMoveDelegate = function(event) {
938
return that._mouseMove(event);
940
this._mouseUpDelegate = function(event) {
941
return that._mouseUp(event);
945
.bind( "mousemove." + this.widgetName, this._mouseMoveDelegate )
946
.bind( "mouseup." + this.widgetName, this._mouseUpDelegate );
948
event.preventDefault();
954
_mouseMove: function(event) {
955
// IE mouseup check - mouseup happened when mouse was out of window
956
if ($.ui.ie && ( !document.documentMode || document.documentMode < 9 ) && !event.button) {
957
return this._mouseUp(event);
959
// Iframe mouseup check - mouseup occurred in another document
960
} else if ( !event.which ) {
961
return this._mouseUp( event );
964
if (this._mouseStarted) {
965
this._mouseDrag(event);
966
return event.preventDefault();
969
if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
971
(this._mouseStart(this._mouseDownEvent, event) !== false);
972
(this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
975
return !this._mouseStarted;
978
_mouseUp: function(event) {
980
.unbind( "mousemove." + this.widgetName, this._mouseMoveDelegate )
981
.unbind( "mouseup." + this.widgetName, this._mouseUpDelegate );
983
if (this._mouseStarted) {
984
this._mouseStarted = false;
986
if (event.target === this._mouseDownEvent.target) {
987
$.data(event.target, this.widgetName + ".preventClickEvent", true);
990
this._mouseStop(event);
993
mouseHandled = false;
997
_mouseDistanceMet: function(event) {
999
Math.abs(this._mouseDownEvent.pageX - event.pageX),
1000
Math.abs(this._mouseDownEvent.pageY - event.pageY)
1001
) >= this.options.distance
1005
_mouseDelayMet: function(/* event */) {
1006
return this.mouseDelayMet;
1009
// These are placeholder methods, to be overriden by extending plugin
1010
_mouseStart: function(/* event */) {},
1011
_mouseDrag: function(/* event */) {},
1012
_mouseStop: function(/* event */) {},
1013
_mouseCapture: function(/* event */) { return true; }
1018
* jQuery UI Position 1.11.0
1019
* http://jqueryui.com
1021
* Copyright 2014 jQuery Foundation and other contributors
1022
* Released under the MIT license.
1023
* http://jquery.org/license
1025
* http://api.jqueryui.com/position/
1032
var cachedScrollbarWidth, supportsOffsetFractions,
1036
rhorizontal = /left|center|right/,
1037
rvertical = /top|center|bottom/,
1038
roffset = /[\+\-]\d+(\.[\d]+)?%?/,
1041
_position = $.fn.position;
1043
function getOffsets( offsets, width, height ) {
1045
parseFloat( offsets[ 0 ] ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ),
1046
parseFloat( offsets[ 1 ] ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 )
1050
function parseCss( element, property ) {
1051
return parseInt( $.css( element, property ), 10 ) || 0;
1054
function getDimensions( elem ) {
1056
if ( raw.nodeType === 9 ) {
1058
width: elem.width(),
1059
height: elem.height(),
1060
offset: { top: 0, left: 0 }
1063
if ( $.isWindow( raw ) ) {
1065
width: elem.width(),
1066
height: elem.height(),
1067
offset: { top: elem.scrollTop(), left: elem.scrollLeft() }
1070
if ( raw.preventDefault ) {
1074
offset: { top: raw.pageY, left: raw.pageX }
1078
width: elem.outerWidth(),
1079
height: elem.outerHeight(),
1080
offset: elem.offset()
1085
scrollbarWidth: function() {
1086
if ( cachedScrollbarWidth !== undefined ) {
1087
return cachedScrollbarWidth;
1090
div = $( "<div style='display:block;position:absolute;width:50px;height:50px;overflow:hidden;'><div style='height:100px;width:auto;'></div></div>" ),
1091
innerDiv = div.children()[0];
1093
$( "body" ).append( div );
1094
w1 = innerDiv.offsetWidth;
1095
div.css( "overflow", "scroll" );
1097
w2 = innerDiv.offsetWidth;
1100
w2 = div[0].clientWidth;
1105
return (cachedScrollbarWidth = w1 - w2);
1107
getScrollInfo: function( within ) {
1108
var overflowX = within.isWindow || within.isDocument ? "" :
1109
within.element.css( "overflow-x" ),
1110
overflowY = within.isWindow || within.isDocument ? "" :
1111
within.element.css( "overflow-y" ),
1112
hasOverflowX = overflowX === "scroll" ||
1113
( overflowX === "auto" && within.width < within.element[0].scrollWidth ),
1114
hasOverflowY = overflowY === "scroll" ||
1115
( overflowY === "auto" && within.height < within.element[0].scrollHeight );
1117
width: hasOverflowY ? $.position.scrollbarWidth() : 0,
1118
height: hasOverflowX ? $.position.scrollbarWidth() : 0
1121
getWithinInfo: function( element ) {
1122
var withinElement = $( element || window ),
1123
isWindow = $.isWindow( withinElement[0] ),
1124
isDocument = !!withinElement[ 0 ] && withinElement[ 0 ].nodeType === 9;
1126
element: withinElement,
1128
isDocument: isDocument,
1129
offset: withinElement.offset() || { left: 0, top: 0 },
1130
scrollLeft: withinElement.scrollLeft(),
1131
scrollTop: withinElement.scrollTop(),
1132
width: isWindow ? withinElement.width() : withinElement.outerWidth(),
1133
height: isWindow ? withinElement.height() : withinElement.outerHeight()
1138
$.fn.position = function( options ) {
1139
if ( !options || !options.of ) {
1140
return _position.apply( this, arguments );
1143
// make a copy, we don't want to modify arguments
1144
options = $.extend( {}, options );
1146
var atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions,
1147
target = $( options.of ),
1148
within = $.position.getWithinInfo( options.within ),
1149
scrollInfo = $.position.getScrollInfo( within ),
1150
collision = ( options.collision || "flip" ).split( " " ),
1153
dimensions = getDimensions( target );
1154
if ( target[0].preventDefault ) {
1155
// force left top to allow flipping
1156
options.at = "left top";
1158
targetWidth = dimensions.width;
1159
targetHeight = dimensions.height;
1160
targetOffset = dimensions.offset;
1161
// clone to reuse original targetOffset later
1162
basePosition = $.extend( {}, targetOffset );
1164
// force my and at to have valid horizontal and vertical positions
1165
// if a value is missing or invalid, it will be converted to center
1166
$.each( [ "my", "at" ], function() {
1167
var pos = ( options[ this ] || "" ).split( " " ),
1171
if ( pos.length === 1) {
1172
pos = rhorizontal.test( pos[ 0 ] ) ?
1173
pos.concat( [ "center" ] ) :
1174
rvertical.test( pos[ 0 ] ) ?
1175
[ "center" ].concat( pos ) :
1176
[ "center", "center" ];
1178
pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center";
1179
pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center";
1181
// calculate offsets
1182
horizontalOffset = roffset.exec( pos[ 0 ] );
1183
verticalOffset = roffset.exec( pos[ 1 ] );
1185
horizontalOffset ? horizontalOffset[ 0 ] : 0,
1186
verticalOffset ? verticalOffset[ 0 ] : 0
1189
// reduce to just the positions without the offsets
1191
rposition.exec( pos[ 0 ] )[ 0 ],
1192
rposition.exec( pos[ 1 ] )[ 0 ]
1196
// normalize collision option
1197
if ( collision.length === 1 ) {
1198
collision[ 1 ] = collision[ 0 ];
1201
if ( options.at[ 0 ] === "right" ) {
1202
basePosition.left += targetWidth;
1203
} else if ( options.at[ 0 ] === "center" ) {
1204
basePosition.left += targetWidth / 2;
1207
if ( options.at[ 1 ] === "bottom" ) {
1208
basePosition.top += targetHeight;
1209
} else if ( options.at[ 1 ] === "center" ) {
1210
basePosition.top += targetHeight / 2;
1213
atOffset = getOffsets( offsets.at, targetWidth, targetHeight );
1214
basePosition.left += atOffset[ 0 ];
1215
basePosition.top += atOffset[ 1 ];
1217
return this.each(function() {
1218
var collisionPosition, using,
1220
elemWidth = elem.outerWidth(),
1221
elemHeight = elem.outerHeight(),
1222
marginLeft = parseCss( this, "marginLeft" ),
1223
marginTop = parseCss( this, "marginTop" ),
1224
collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) + scrollInfo.width,
1225
collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) + scrollInfo.height,
1226
position = $.extend( {}, basePosition ),
1227
myOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() );
1229
if ( options.my[ 0 ] === "right" ) {
1230
position.left -= elemWidth;
1231
} else if ( options.my[ 0 ] === "center" ) {
1232
position.left -= elemWidth / 2;
1235
if ( options.my[ 1 ] === "bottom" ) {
1236
position.top -= elemHeight;
1237
} else if ( options.my[ 1 ] === "center" ) {
1238
position.top -= elemHeight / 2;
1241
position.left += myOffset[ 0 ];
1242
position.top += myOffset[ 1 ];
1244
// if the browser doesn't support fractions, then round for consistent results
1245
if ( !supportsOffsetFractions ) {
1246
position.left = round( position.left );
1247
position.top = round( position.top );
1250
collisionPosition = {
1251
marginLeft: marginLeft,
1252
marginTop: marginTop
1255
$.each( [ "left", "top" ], function( i, dir ) {
1256
if ( $.ui.position[ collision[ i ] ] ) {
1257
$.ui.position[ collision[ i ] ][ dir ]( position, {
1258
targetWidth: targetWidth,
1259
targetHeight: targetHeight,
1260
elemWidth: elemWidth,
1261
elemHeight: elemHeight,
1262
collisionPosition: collisionPosition,
1263
collisionWidth: collisionWidth,
1264
collisionHeight: collisionHeight,
1265
offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ],
1274
if ( options.using ) {
1275
// adds feedback as second argument to using callback, if present
1276
using = function( props ) {
1277
var left = targetOffset.left - position.left,
1278
right = left + targetWidth - elemWidth,
1279
top = targetOffset.top - position.top,
1280
bottom = top + targetHeight - elemHeight,
1284
left: targetOffset.left,
1285
top: targetOffset.top,
1287
height: targetHeight
1291
left: position.left,
1296
horizontal: right < 0 ? "left" : left > 0 ? "right" : "center",
1297
vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle"
1299
if ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) {
1300
feedback.horizontal = "center";
1302
if ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) {
1303
feedback.vertical = "middle";
1305
if ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) {
1306
feedback.important = "horizontal";
1308
feedback.important = "vertical";
1310
options.using.call( this, props, feedback );
1314
elem.offset( $.extend( position, { using: using } ) );
1320
left: function( position, data ) {
1321
var within = data.within,
1322
withinOffset = within.isWindow ? within.scrollLeft : within.offset.left,
1323
outerWidth = within.width,
1324
collisionPosLeft = position.left - data.collisionPosition.marginLeft,
1325
overLeft = withinOffset - collisionPosLeft,
1326
overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset,
1329
// element is wider than within
1330
if ( data.collisionWidth > outerWidth ) {
1331
// element is initially over the left side of within
1332
if ( overLeft > 0 && overRight <= 0 ) {
1333
newOverRight = position.left + overLeft + data.collisionWidth - outerWidth - withinOffset;
1334
position.left += overLeft - newOverRight;
1335
// element is initially over right side of within
1336
} else if ( overRight > 0 && overLeft <= 0 ) {
1337
position.left = withinOffset;
1338
// element is initially over both left and right sides of within
1340
if ( overLeft > overRight ) {
1341
position.left = withinOffset + outerWidth - data.collisionWidth;
1343
position.left = withinOffset;
1346
// too far left -> align with left edge
1347
} else if ( overLeft > 0 ) {
1348
position.left += overLeft;
1349
// too far right -> align with right edge
1350
} else if ( overRight > 0 ) {
1351
position.left -= overRight;
1352
// adjust based on position and margin
1354
position.left = max( position.left - collisionPosLeft, position.left );
1357
top: function( position, data ) {
1358
var within = data.within,
1359
withinOffset = within.isWindow ? within.scrollTop : within.offset.top,
1360
outerHeight = data.within.height,
1361
collisionPosTop = position.top - data.collisionPosition.marginTop,
1362
overTop = withinOffset - collisionPosTop,
1363
overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset,
1366
// element is taller than within
1367
if ( data.collisionHeight > outerHeight ) {
1368
// element is initially over the top of within
1369
if ( overTop > 0 && overBottom <= 0 ) {
1370
newOverBottom = position.top + overTop + data.collisionHeight - outerHeight - withinOffset;
1371
position.top += overTop - newOverBottom;
1372
// element is initially over bottom of within
1373
} else if ( overBottom > 0 && overTop <= 0 ) {
1374
position.top = withinOffset;
1375
// element is initially over both top and bottom of within
1377
if ( overTop > overBottom ) {
1378
position.top = withinOffset + outerHeight - data.collisionHeight;
1380
position.top = withinOffset;
1383
// too far up -> align with top
1384
} else if ( overTop > 0 ) {
1385
position.top += overTop;
1386
// too far down -> align with bottom edge
1387
} else if ( overBottom > 0 ) {
1388
position.top -= overBottom;
1389
// adjust based on position and margin
1391
position.top = max( position.top - collisionPosTop, position.top );
1396
left: function( position, data ) {
1397
var within = data.within,
1398
withinOffset = within.offset.left + within.scrollLeft,
1399
outerWidth = within.width,
1400
offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left,
1401
collisionPosLeft = position.left - data.collisionPosition.marginLeft,
1402
overLeft = collisionPosLeft - offsetLeft,
1403
overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft,
1404
myOffset = data.my[ 0 ] === "left" ?
1406
data.my[ 0 ] === "right" ?
1409
atOffset = data.at[ 0 ] === "left" ?
1411
data.at[ 0 ] === "right" ?
1414
offset = -2 * data.offset[ 0 ],
1418
if ( overLeft < 0 ) {
1419
newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth - outerWidth - withinOffset;
1420
if ( newOverRight < 0 || newOverRight < abs( overLeft ) ) {
1421
position.left += myOffset + atOffset + offset;
1423
} else if ( overRight > 0 ) {
1424
newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset + atOffset + offset - offsetLeft;
1425
if ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) {
1426
position.left += myOffset + atOffset + offset;
1430
top: function( position, data ) {
1431
var within = data.within,
1432
withinOffset = within.offset.top + within.scrollTop,
1433
outerHeight = within.height,
1434
offsetTop = within.isWindow ? within.scrollTop : within.offset.top,
1435
collisionPosTop = position.top - data.collisionPosition.marginTop,
1436
overTop = collisionPosTop - offsetTop,
1437
overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop,
1438
top = data.my[ 1 ] === "top",
1441
data.my[ 1 ] === "bottom" ?
1444
atOffset = data.at[ 1 ] === "top" ?
1446
data.at[ 1 ] === "bottom" ?
1447
-data.targetHeight :
1449
offset = -2 * data.offset[ 1 ],
1452
if ( overTop < 0 ) {
1453
newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight - outerHeight - withinOffset;
1454
if ( ( position.top + myOffset + atOffset + offset) > overTop && ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) ) {
1455
position.top += myOffset + atOffset + offset;
1457
} else if ( overBottom > 0 ) {
1458
newOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset + offset - offsetTop;
1459
if ( ( position.top + myOffset + atOffset + offset) > overBottom && ( newOverTop > 0 || abs( newOverTop ) < overBottom ) ) {
1460
position.top += myOffset + atOffset + offset;
1467
$.ui.position.flip.left.apply( this, arguments );
1468
$.ui.position.fit.left.apply( this, arguments );
1471
$.ui.position.flip.top.apply( this, arguments );
1472
$.ui.position.fit.top.apply( this, arguments );
1477
// fraction support test
1479
var testElement, testElementParent, testElementStyle, offsetLeft, i,
1480
body = document.getElementsByTagName( "body" )[ 0 ],
1481
div = document.createElement( "div" );
1483
//Create a "fake body" for testing based on method used in jQuery.support
1484
testElement = document.createElement( body ? "div" : "body" );
1485
testElementStyle = {
1486
visibility: "hidden",
1494
$.extend( testElementStyle, {
1495
position: "absolute",
1500
for ( i in testElementStyle ) {
1501
testElement.style[ i ] = testElementStyle[ i ];
1503
testElement.appendChild( div );
1504
testElementParent = body || document.documentElement;
1505
testElementParent.insertBefore( testElement, testElementParent.firstChild );
1507
div.style.cssText = "position: absolute; left: 10.7432222px;";
1509
offsetLeft = $( div ).offset().left;
1510
supportsOffsetFractions = offsetLeft > 10 && offsetLeft < 11;
1512
testElement.innerHTML = "";
1513
testElementParent.removeChild( testElement );
1518
var position = $.ui.position;
1522
* jQuery UI Accordion 1.11.0
1523
* http://jqueryui.com
1525
* Copyright 2014 jQuery Foundation and other contributors
1526
* Released under the MIT license.
1527
* http://jquery.org/license
1529
* http://api.jqueryui.com/accordion/
1533
var accordion = $.widget( "ui.accordion", {
1540
header: "> li > :first-child,> :not(li):even",
1541
heightStyle: "auto",
1543
activeHeader: "ui-icon-triangle-1-s",
1544
header: "ui-icon-triangle-1-e"
1549
beforeActivate: null
1553
borderTopWidth: "hide",
1554
borderBottomWidth: "hide",
1556
paddingBottom: "hide",
1561
borderTopWidth: "show",
1562
borderBottomWidth: "show",
1564
paddingBottom: "show",
1568
_create: function() {
1569
var options = this.options;
1570
this.prevShow = this.prevHide = $();
1571
this.element.addClass( "ui-accordion ui-widget ui-helper-reset" )
1573
.attr( "role", "tablist" );
1575
// don't allow collapsible: false and active: false / null
1576
if ( !options.collapsible && (options.active === false || options.active == null) ) {
1580
this._processPanels();
1581
// handle negative values
1582
if ( options.active < 0 ) {
1583
options.active += this.headers.length;
1588
_getCreateEventData: function() {
1590
header: this.active,
1591
panel: !this.active.length ? $() : this.active.next()
1595
_createIcons: function() {
1596
var icons = this.options.icons;
1599
.addClass( "ui-accordion-header-icon ui-icon " + icons.header )
1600
.prependTo( this.headers );
1601
this.active.children( ".ui-accordion-header-icon" )
1602
.removeClass( icons.header )
1603
.addClass( icons.activeHeader );
1604
this.headers.addClass( "ui-accordion-icons" );
1608
_destroyIcons: function() {
1610
.removeClass( "ui-accordion-icons" )
1611
.children( ".ui-accordion-header-icon" )
1615
_destroy: function() {
1618
// clean up main element
1620
.removeClass( "ui-accordion ui-widget ui-helper-reset" )
1621
.removeAttr( "role" );
1625
.removeClass( "ui-accordion-header ui-accordion-header-active ui-state-default " +
1626
"ui-corner-all ui-state-active ui-state-disabled ui-corner-top" )
1627
.removeAttr( "role" )
1628
.removeAttr( "aria-expanded" )
1629
.removeAttr( "aria-selected" )
1630
.removeAttr( "aria-controls" )
1631
.removeAttr( "tabIndex" )
1634
this._destroyIcons();
1636
// clean up content panels
1637
contents = this.headers.next()
1638
.removeClass( "ui-helper-reset ui-widget-content ui-corner-bottom " +
1639
"ui-accordion-content ui-accordion-content-active ui-state-disabled" )
1640
.css( "display", "" )
1641
.removeAttr( "role" )
1642
.removeAttr( "aria-hidden" )
1643
.removeAttr( "aria-labelledby" )
1646
if ( this.options.heightStyle !== "content" ) {
1647
contents.css( "height", "" );
1651
_setOption: function( key, value ) {
1652
if ( key === "active" ) {
1653
// _activate() will handle invalid values and update this.options
1654
this._activate( value );
1658
if ( key === "event" ) {
1659
if ( this.options.event ) {
1660
this._off( this.headers, this.options.event );
1662
this._setupEvents( value );
1665
this._super( key, value );
1667
// setting collapsible: false while collapsed; open first panel
1668
if ( key === "collapsible" && !value && this.options.active === false ) {
1669
this._activate( 0 );
1672
if ( key === "icons" ) {
1673
this._destroyIcons();
1675
this._createIcons();
1679
// #5332 - opacity doesn't cascade to positioned elements in IE
1680
// so we need to add the disabled class to the headers and panels
1681
if ( key === "disabled" ) {
1683
.toggleClass( "ui-state-disabled", !!value )
1684
.attr( "aria-disabled", value );
1685
this.headers.add( this.headers.next() )
1686
.toggleClass( "ui-state-disabled", !!value );
1690
_keydown: function( event ) {
1691
if ( event.altKey || event.ctrlKey ) {
1695
var keyCode = $.ui.keyCode,
1696
length = this.headers.length,
1697
currentIndex = this.headers.index( event.target ),
1700
switch ( event.keyCode ) {
1703
toFocus = this.headers[ ( currentIndex + 1 ) % length ];
1707
toFocus = this.headers[ ( currentIndex - 1 + length ) % length ];
1711
this._eventHandler( event );
1714
toFocus = this.headers[ 0 ];
1717
toFocus = this.headers[ length - 1 ];
1722
$( event.target ).attr( "tabIndex", -1 );
1723
$( toFocus ).attr( "tabIndex", 0 );
1725
event.preventDefault();
1729
_panelKeyDown: function( event ) {
1730
if ( event.keyCode === $.ui.keyCode.UP && event.ctrlKey ) {
1731
$( event.currentTarget ).prev().focus();
1735
refresh: function() {
1736
var options = this.options;
1737
this._processPanels();
1739
// was collapsed or no panel
1740
if ( ( options.active === false && options.collapsible === true ) || !this.headers.length ) {
1741
options.active = false;
1743
// active false only when collapsible is true
1744
} else if ( options.active === false ) {
1745
this._activate( 0 );
1746
// was active, but active panel is gone
1747
} else if ( this.active.length && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
1748
// all remaining panel are disabled
1749
if ( this.headers.length === this.headers.find(".ui-state-disabled").length ) {
1750
options.active = false;
1752
// activate previous panel
1754
this._activate( Math.max( 0, options.active - 1 ) );
1756
// was active, active panel still exists
1758
// make sure active index is correct
1759
options.active = this.headers.index( this.active );
1762
this._destroyIcons();
1767
_processPanels: function() {
1768
this.headers = this.element.find( this.options.header )
1769
.addClass( "ui-accordion-header ui-state-default ui-corner-all" );
1772
.addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" )
1773
.filter( ":not(.ui-accordion-content-active)" )
1777
_refresh: function() {
1779
options = this.options,
1780
heightStyle = options.heightStyle,
1781
parent = this.element.parent();
1783
this.active = this._findActive( options.active )
1784
.addClass( "ui-accordion-header-active ui-state-active ui-corner-top" )
1785
.removeClass( "ui-corner-all" );
1787
.addClass( "ui-accordion-content-active" )
1791
.attr( "role", "tab" )
1793
var header = $( this ),
1794
headerId = header.uniqueId().attr( "id" ),
1795
panel = header.next(),
1796
panelId = panel.uniqueId().attr( "id" );
1797
header.attr( "aria-controls", panelId );
1798
panel.attr( "aria-labelledby", headerId );
1801
.attr( "role", "tabpanel" );
1806
"aria-selected": "false",
1807
"aria-expanded": "false",
1812
"aria-hidden": "true"
1816
// make sure at least one header is in the tab order
1817
if ( !this.active.length ) {
1818
this.headers.eq( 0 ).attr( "tabIndex", 0 );
1821
"aria-selected": "true",
1822
"aria-expanded": "true",
1827
"aria-hidden": "false"
1831
this._createIcons();
1833
this._setupEvents( options.event );
1835
if ( heightStyle === "fill" ) {
1836
maxHeight = parent.height();
1837
this.element.siblings( ":visible" ).each(function() {
1838
var elem = $( this ),
1839
position = elem.css( "position" );
1841
if ( position === "absolute" || position === "fixed" ) {
1844
maxHeight -= elem.outerHeight( true );
1847
this.headers.each(function() {
1848
maxHeight -= $( this ).outerHeight( true );
1853
$( this ).height( Math.max( 0, maxHeight -
1854
$( this ).innerHeight() + $( this ).height() ) );
1856
.css( "overflow", "auto" );
1857
} else if ( heightStyle === "auto" ) {
1861
maxHeight = Math.max( maxHeight, $( this ).css( "height", "" ).height() );
1863
.height( maxHeight );
1867
_activate: function( index ) {
1868
var active = this._findActive( index )[ 0 ];
1870
// trying to activate the already active panel
1871
if ( active === this.active[ 0 ] ) {
1875
// trying to collapse, simulate a click on the currently active header
1876
active = active || this.active[ 0 ];
1878
this._eventHandler({
1880
currentTarget: active,
1881
preventDefault: $.noop
1885
_findActive: function( selector ) {
1886
return typeof selector === "number" ? this.headers.eq( selector ) : $();
1889
_setupEvents: function( event ) {
1894
$.each( event.split( " " ), function( index, eventName ) {
1895
events[ eventName ] = "_eventHandler";
1899
this._off( this.headers.add( this.headers.next() ) );
1900
this._on( this.headers, events );
1901
this._on( this.headers.next(), { keydown: "_panelKeyDown" });
1902
this._hoverable( this.headers );
1903
this._focusable( this.headers );
1906
_eventHandler: function( event ) {
1907
var options = this.options,
1908
active = this.active,
1909
clicked = $( event.currentTarget ),
1910
clickedIsActive = clicked[ 0 ] === active[ 0 ],
1911
collapsing = clickedIsActive && options.collapsible,
1912
toShow = collapsing ? $() : clicked.next(),
1913
toHide = active.next(),
1917
newHeader: collapsing ? $() : clicked,
1921
event.preventDefault();
1924
// click on active header, but not collapsible
1925
( clickedIsActive && !options.collapsible ) ||
1926
// allow canceling activation
1927
( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
1931
options.active = collapsing ? false : this.headers.index( clicked );
1933
// when the call to ._toggle() comes after the class changes
1934
// it causes a very odd bug in IE 8 (see #6720)
1935
this.active = clickedIsActive ? $() : clicked;
1936
this._toggle( eventData );
1939
// corner classes on the previously active header stay after the animation
1940
active.removeClass( "ui-accordion-header-active ui-state-active" );
1941
if ( options.icons ) {
1942
active.children( ".ui-accordion-header-icon" )
1943
.removeClass( options.icons.activeHeader )
1944
.addClass( options.icons.header );
1947
if ( !clickedIsActive ) {
1949
.removeClass( "ui-corner-all" )
1950
.addClass( "ui-accordion-header-active ui-state-active ui-corner-top" );
1951
if ( options.icons ) {
1952
clicked.children( ".ui-accordion-header-icon" )
1953
.removeClass( options.icons.header )
1954
.addClass( options.icons.activeHeader );
1959
.addClass( "ui-accordion-content-active" );
1963
_toggle: function( data ) {
1964
var toShow = data.newPanel,
1965
toHide = this.prevShow.length ? this.prevShow : data.oldPanel;
1967
// handle activating a panel during the animation for another activation
1968
this.prevShow.add( this.prevHide ).stop( true, true );
1969
this.prevShow = toShow;
1970
this.prevHide = toHide;
1972
if ( this.options.animate ) {
1973
this._animate( toShow, toHide, data );
1977
this._toggleComplete( data );
1981
"aria-hidden": "true"
1983
toHide.prev().attr( "aria-selected", "false" );
1984
// if we're switching panels, remove the old header from the tab order
1985
// if we're opening from collapsed state, remove the previous header from the tab order
1986
// if we're collapsing, then keep the collapsing header in the tab order
1987
if ( toShow.length && toHide.length ) {
1988
toHide.prev().attr({
1990
"aria-expanded": "false"
1992
} else if ( toShow.length ) {
1993
this.headers.filter(function() {
1994
return $( this ).attr( "tabIndex" ) === 0;
1996
.attr( "tabIndex", -1 );
2000
.attr( "aria-hidden", "false" )
2003
"aria-selected": "true",
2005
"aria-expanded": "true"
2009
_animate: function( toShow, toHide, data ) {
2010
var total, easing, duration,
2013
down = toShow.length &&
2014
( !toHide.length || ( toShow.index() < toHide.index() ) ),
2015
animate = this.options.animate || {},
2016
options = down && animate.down || animate,
2017
complete = function() {
2018
that._toggleComplete( data );
2021
if ( typeof options === "number" ) {
2024
if ( typeof options === "string" ) {
2027
// fall back from options to animation in case of partial down settings
2028
easing = easing || options.easing || animate.easing;
2029
duration = duration || options.duration || animate.duration;
2031
if ( !toHide.length ) {
2032
return toShow.animate( this.showProps, duration, easing, complete );
2034
if ( !toShow.length ) {
2035
return toHide.animate( this.hideProps, duration, easing, complete );
2038
total = toShow.show().outerHeight();
2039
toHide.animate( this.hideProps, {
2042
step: function( now, fx ) {
2043
fx.now = Math.round( now );
2048
.animate( this.showProps, {
2052
step: function( now, fx ) {
2053
fx.now = Math.round( now );
2054
if ( fx.prop !== "height" ) {
2056
} else if ( that.options.heightStyle !== "content" ) {
2057
fx.now = Math.round( total - toHide.outerHeight() - adjust );
2064
_toggleComplete: function( data ) {
2065
var toHide = data.oldPanel;
2068
.removeClass( "ui-accordion-content-active" )
2070
.removeClass( "ui-corner-top" )
2071
.addClass( "ui-corner-all" );
2073
// Work around for rendering bug in IE (#5421)
2074
if ( toHide.length ) {
2075
toHide.parent()[ 0 ].className = toHide.parent()[ 0 ].className;
2077
this._trigger( "activate", null, data );
2083
* jQuery UI Menu 1.11.0
2084
* http://jqueryui.com
2086
* Copyright 2014 jQuery Foundation and other contributors
2087
* Released under the MIT license.
2088
* http://jquery.org/license
2090
* http://api.jqueryui.com/menu/
2094
var menu = $.widget( "ui.menu", {
2096
defaultElement: "<ul>",
2100
submenu: "ui-icon-carat-1-e"
2116
_create: function() {
2117
this.activeMenu = this.element;
2119
// Flag used to prevent firing of the click handler
2120
// as the event bubbles up through nested menus
2121
this.mouseHandled = false;
2124
.addClass( "ui-menu ui-widget ui-widget-content" )
2125
.toggleClass( "ui-menu-icons", !!this.element.find( ".ui-icon" ).length )
2127
role: this.options.role,
2131
if ( this.options.disabled ) {
2133
.addClass( "ui-state-disabled" )
2134
.attr( "aria-disabled", "true" );
2138
// Prevent focus from sticking to links inside menu after clicking
2139
// them (focus should always stay on UL during navigation).
2140
"mousedown .ui-menu-item": function( event ) {
2141
event.preventDefault();
2143
"click .ui-menu-item": function( event ) {
2144
var target = $( event.target );
2145
if ( !this.mouseHandled && target.not( ".ui-state-disabled" ).length ) {
2146
this.select( event );
2148
// Only set the mouseHandled flag if the event will bubble, see #9469.
2149
if ( !event.isPropagationStopped() ) {
2150
this.mouseHandled = true;
2153
// Open submenu on click
2154
if ( target.has( ".ui-menu" ).length ) {
2155
this.expand( event );
2156
} else if ( !this.element.is( ":focus" ) && $( this.document[ 0 ].activeElement ).closest( ".ui-menu" ).length ) {
2158
// Redirect focus to the menu
2159
this.element.trigger( "focus", [ true ] );
2161
// If the active item is on the top level, let it stay active.
2162
// Otherwise, blur the active item since it is no longer visible.
2163
if ( this.active && this.active.parents( ".ui-menu" ).length === 1 ) {
2164
clearTimeout( this.timer );
2169
"mouseenter .ui-menu-item": function( event ) {
2170
var target = $( event.currentTarget );
2171
// Remove ui-state-active class from siblings of the newly focused menu item
2172
// to avoid a jump caused by adjacent elements both having a class with a border
2173
target.siblings( ".ui-state-active" ).removeClass( "ui-state-active" );
2174
this.focus( event, target );
2176
mouseleave: "collapseAll",
2177
"mouseleave .ui-menu": "collapseAll",
2178
focus: function( event, keepActiveItem ) {
2179
// If there's already an active item, keep it active
2180
// If not, activate the first item
2181
var item = this.active || this.element.find( this.options.items ).eq( 0 );
2183
if ( !keepActiveItem ) {
2184
this.focus( event, item );
2187
blur: function( event ) {
2188
this._delay(function() {
2189
if ( !$.contains( this.element[0], this.document[0].activeElement ) ) {
2190
this.collapseAll( event );
2199
// Clicks outside of a menu collapse any open menus
2200
this._on( this.document, {
2201
click: function( event ) {
2202
if ( this._closeOnDocumentClick( event ) ) {
2203
this.collapseAll( event );
2206
// Reset the mouseHandled flag
2207
this.mouseHandled = false;
2212
_destroy: function() {
2213
// Destroy (sub)menus
2215
.removeAttr( "aria-activedescendant" )
2216
.find( ".ui-menu" ).addBack()
2217
.removeClass( "ui-menu ui-widget ui-widget-content ui-menu-icons ui-front" )
2218
.removeAttr( "role" )
2219
.removeAttr( "tabIndex" )
2220
.removeAttr( "aria-labelledby" )
2221
.removeAttr( "aria-expanded" )
2222
.removeAttr( "aria-hidden" )
2223
.removeAttr( "aria-disabled" )
2227
// Destroy menu items
2228
this.element.find( ".ui-menu-item" )
2229
.removeClass( "ui-menu-item" )
2230
.removeAttr( "role" )
2231
.removeAttr( "aria-disabled" )
2233
.removeClass( "ui-state-hover" )
2234
.removeAttr( "tabIndex" )
2235
.removeAttr( "role" )
2236
.removeAttr( "aria-haspopup" )
2237
.children().each( function() {
2238
var elem = $( this );
2239
if ( elem.data( "ui-menu-submenu-carat" ) ) {
2244
// Destroy menu dividers
2245
this.element.find( ".ui-menu-divider" ).removeClass( "ui-menu-divider ui-widget-content" );
2248
_keydown: function( event ) {
2249
var match, prev, character, skip, regex,
2250
preventDefault = true;
2252
function escape( value ) {
2253
return value.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" );
2256
switch ( event.keyCode ) {
2257
case $.ui.keyCode.PAGE_UP:
2258
this.previousPage( event );
2260
case $.ui.keyCode.PAGE_DOWN:
2261
this.nextPage( event );
2263
case $.ui.keyCode.HOME:
2264
this._move( "first", "first", event );
2266
case $.ui.keyCode.END:
2267
this._move( "last", "last", event );
2269
case $.ui.keyCode.UP:
2270
this.previous( event );
2272
case $.ui.keyCode.DOWN:
2275
case $.ui.keyCode.LEFT:
2276
this.collapse( event );
2278
case $.ui.keyCode.RIGHT:
2279
if ( this.active && !this.active.is( ".ui-state-disabled" ) ) {
2280
this.expand( event );
2283
case $.ui.keyCode.ENTER:
2284
case $.ui.keyCode.SPACE:
2285
this._activate( event );
2287
case $.ui.keyCode.ESCAPE:
2288
this.collapse( event );
2291
preventDefault = false;
2292
prev = this.previousFilter || "";
2293
character = String.fromCharCode( event.keyCode );
2296
clearTimeout( this.filterTimer );
2298
if ( character === prev ) {
2301
character = prev + character;
2304
regex = new RegExp( "^" + escape( character ), "i" );
2305
match = this.activeMenu.find( this.options.items ).filter(function() {
2306
return regex.test( $( this ).text() );
2308
match = skip && match.index( this.active.next() ) !== -1 ?
2309
this.active.nextAll( ".ui-menu-item" ) :
2312
// If no matches on the current filter, reset to the last character pressed
2313
// to move down the menu to the first item that starts with that character
2314
if ( !match.length ) {
2315
character = String.fromCharCode( event.keyCode );
2316
regex = new RegExp( "^" + escape( character ), "i" );
2317
match = this.activeMenu.find( this.options.items ).filter(function() {
2318
return regex.test( $( this ).text() );
2322
if ( match.length ) {
2323
this.focus( event, match );
2324
if ( match.length > 1 ) {
2325
this.previousFilter = character;
2326
this.filterTimer = this._delay(function() {
2327
delete this.previousFilter;
2330
delete this.previousFilter;
2333
delete this.previousFilter;
2337
if ( preventDefault ) {
2338
event.preventDefault();
2342
_activate: function( event ) {
2343
if ( !this.active.is( ".ui-state-disabled" ) ) {
2344
if ( this.active.is( "[aria-haspopup='true']" ) ) {
2345
this.expand( event );
2347
this.select( event );
2352
refresh: function() {
2355
icon = this.options.icons.submenu,
2356
submenus = this.element.find( this.options.menus );
2358
this.element.toggleClass( "ui-menu-icons", !!this.element.find( ".ui-icon" ).length );
2360
// Initialize nested menus
2361
submenus.filter( ":not(.ui-menu)" )
2362
.addClass( "ui-menu ui-widget ui-widget-content ui-front" )
2365
role: this.options.role,
2366
"aria-hidden": "true",
2367
"aria-expanded": "false"
2370
var menu = $( this ),
2371
item = menu.parent(),
2372
submenuCarat = $( "<span>" )
2373
.addClass( "ui-menu-icon ui-icon " + icon )
2374
.data( "ui-menu-submenu-carat", true );
2377
.attr( "aria-haspopup", "true" )
2378
.prepend( submenuCarat );
2379
menu.attr( "aria-labelledby", item.attr( "id" ) );
2382
menus = submenus.add( this.element );
2383
items = menus.find( this.options.items );
2385
// Initialize menu-items containing spaces and/or dashes only as dividers
2386
items.not( ".ui-menu-item" ).each(function() {
2387
var item = $( this );
2388
if ( that._isDivider( item ) ) {
2389
item.addClass( "ui-widget-content ui-menu-divider" );
2393
// Don't refresh list items that are already adapted
2394
items.not( ".ui-menu-item, .ui-menu-divider" )
2395
.addClass( "ui-menu-item" )
2399
role: this._itemRole()
2402
// Add aria-disabled attribute to any disabled menu item
2403
items.filter( ".ui-state-disabled" ).attr( "aria-disabled", "true" );
2405
// If the active item has been removed, blur the menu
2406
if ( this.active && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
2411
_itemRole: function() {
2415
}[ this.options.role ];
2418
_setOption: function( key, value ) {
2419
if ( key === "icons" ) {
2420
this.element.find( ".ui-menu-icon" )
2421
.removeClass( this.options.icons.submenu )
2422
.addClass( value.submenu );
2424
if ( key === "disabled" ) {
2426
.toggleClass( "ui-state-disabled", !!value )
2427
.attr( "aria-disabled", value );
2429
this._super( key, value );
2432
focus: function( event, item ) {
2433
var nested, focused;
2434
this.blur( event, event && event.type === "focus" );
2436
this._scrollIntoView( item );
2438
this.active = item.first();
2439
focused = this.active.addClass( "ui-state-focus" ).removeClass( "ui-state-active" );
2440
// Only update aria-activedescendant if there's a role
2441
// otherwise we assume focus is managed elsewhere
2442
if ( this.options.role ) {
2443
this.element.attr( "aria-activedescendant", focused.attr( "id" ) );
2446
// Highlight active parent menu item, if any
2449
.closest( ".ui-menu-item" )
2450
.addClass( "ui-state-active" );
2452
if ( event && event.type === "keydown" ) {
2455
this.timer = this._delay(function() {
2460
nested = item.children( ".ui-menu" );
2461
if ( nested.length && event && ( /^mouse/.test( event.type ) ) ) {
2462
this._startOpening(nested);
2464
this.activeMenu = item.parent();
2466
this._trigger( "focus", event, { item: item } );
2469
_scrollIntoView: function( item ) {
2470
var borderTop, paddingTop, offset, scroll, elementHeight, itemHeight;
2471
if ( this._hasScroll() ) {
2472
borderTop = parseFloat( $.css( this.activeMenu[0], "borderTopWidth" ) ) || 0;
2473
paddingTop = parseFloat( $.css( this.activeMenu[0], "paddingTop" ) ) || 0;
2474
offset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop;
2475
scroll = this.activeMenu.scrollTop();
2476
elementHeight = this.activeMenu.height();
2477
itemHeight = item.outerHeight();
2480
this.activeMenu.scrollTop( scroll + offset );
2481
} else if ( offset + itemHeight > elementHeight ) {
2482
this.activeMenu.scrollTop( scroll + offset - elementHeight + itemHeight );
2487
blur: function( event, fromFocus ) {
2489
clearTimeout( this.timer );
2492
if ( !this.active ) {
2496
this.active.removeClass( "ui-state-focus" );
2499
this._trigger( "blur", event, { item: this.active } );
2502
_startOpening: function( submenu ) {
2503
clearTimeout( this.timer );
2505
// Don't open if already open fixes a Firefox bug that caused a .5 pixel
2506
// shift in the submenu position when mousing over the carat icon
2507
if ( submenu.attr( "aria-hidden" ) !== "true" ) {
2511
this.timer = this._delay(function() {
2513
this._open( submenu );
2517
_open: function( submenu ) {
2518
var position = $.extend({
2520
}, this.options.position );
2522
clearTimeout( this.timer );
2523
this.element.find( ".ui-menu" ).not( submenu.parents( ".ui-menu" ) )
2525
.attr( "aria-hidden", "true" );
2529
.removeAttr( "aria-hidden" )
2530
.attr( "aria-expanded", "true" )
2531
.position( position );
2534
collapseAll: function( event, all ) {
2535
clearTimeout( this.timer );
2536
this.timer = this._delay(function() {
2537
// If we were passed an event, look for the submenu that contains the event
2538
var currentMenu = all ? this.element :
2539
$( event && event.target ).closest( this.element.find( ".ui-menu" ) );
2541
// If we found no valid submenu ancestor, use the main menu to close all sub menus anyway
2542
if ( !currentMenu.length ) {
2543
currentMenu = this.element;
2546
this._close( currentMenu );
2549
this.activeMenu = currentMenu;
2553
// With no arguments, closes the currently active menu - if nothing is active
2554
// it closes all menus. If passed an argument, it will search for menus BELOW
2555
_close: function( startMenu ) {
2557
startMenu = this.active ? this.active.parent() : this.element;
2563
.attr( "aria-hidden", "true" )
2564
.attr( "aria-expanded", "false" )
2566
.find( ".ui-state-active" ).not( ".ui-state-focus" )
2567
.removeClass( "ui-state-active" );
2570
_closeOnDocumentClick: function( event ) {
2571
return !$( event.target ).closest( ".ui-menu" ).length;
2574
_isDivider: function( item ) {
2576
// Match hyphen, em dash, en dash
2577
return !/[^\-\u2014\u2013\s]/.test( item.text() );
2580
collapse: function( event ) {
2581
var newItem = this.active &&
2582
this.active.parent().closest( ".ui-menu-item", this.element );
2583
if ( newItem && newItem.length ) {
2585
this.focus( event, newItem );
2589
expand: function( event ) {
2590
var newItem = this.active &&
2592
.children( ".ui-menu " )
2593
.find( this.options.items )
2596
if ( newItem && newItem.length ) {
2597
this._open( newItem.parent() );
2599
// Delay so Firefox will not hide activedescendant change in expanding submenu from AT
2600
this._delay(function() {
2601
this.focus( event, newItem );
2606
next: function( event ) {
2607
this._move( "next", "first", event );
2610
previous: function( event ) {
2611
this._move( "prev", "last", event );
2614
isFirstItem: function() {
2615
return this.active && !this.active.prevAll( ".ui-menu-item" ).length;
2618
isLastItem: function() {
2619
return this.active && !this.active.nextAll( ".ui-menu-item" ).length;
2622
_move: function( direction, filter, event ) {
2624
if ( this.active ) {
2625
if ( direction === "first" || direction === "last" ) {
2627
[ direction === "first" ? "prevAll" : "nextAll" ]( ".ui-menu-item" )
2631
[ direction + "All" ]( ".ui-menu-item" )
2635
if ( !next || !next.length || !this.active ) {
2636
next = this.activeMenu.find( this.options.items )[ filter ]();
2639
this.focus( event, next );
2642
nextPage: function( event ) {
2643
var item, base, height;
2645
if ( !this.active ) {
2649
if ( this.isLastItem() ) {
2652
if ( this._hasScroll() ) {
2653
base = this.active.offset().top;
2654
height = this.element.height();
2655
this.active.nextAll( ".ui-menu-item" ).each(function() {
2657
return item.offset().top - base - height < 0;
2660
this.focus( event, item );
2662
this.focus( event, this.activeMenu.find( this.options.items )
2663
[ !this.active ? "first" : "last" ]() );
2667
previousPage: function( event ) {
2668
var item, base, height;
2669
if ( !this.active ) {
2673
if ( this.isFirstItem() ) {
2676
if ( this._hasScroll() ) {
2677
base = this.active.offset().top;
2678
height = this.element.height();
2679
this.active.prevAll( ".ui-menu-item" ).each(function() {
2681
return item.offset().top - base + height > 0;
2684
this.focus( event, item );
2686
this.focus( event, this.activeMenu.find( this.options.items ).first() );
2690
_hasScroll: function() {
2691
return this.element.outerHeight() < this.element.prop( "scrollHeight" );
2694
select: function( event ) {
2695
// TODO: It should never be possible to not have an active item at this
2696
// point, but the tests don't trigger mouseenter before click.
2697
this.active = this.active || $( event.target ).closest( ".ui-menu-item" );
2698
var ui = { item: this.active };
2699
if ( !this.active.has( ".ui-menu" ).length ) {
2700
this.collapseAll( event, true );
2702
this._trigger( "select", event, ui );
2708
* jQuery UI Autocomplete 1.11.0
2709
* http://jqueryui.com
2711
* Copyright 2014 jQuery Foundation and other contributors
2712
* Released under the MIT license.
2713
* http://jquery.org/license
2715
* http://api.jqueryui.com/autocomplete/
2719
$.widget( "ui.autocomplete", {
2721
defaultElement: "<input>",
2747
_create: function() {
2748
// Some browsers only repeat keydown events, not keypress events,
2749
// so we use the suppressKeyPress flag to determine if we've already
2750
// handled the keydown event. #7269
2751
// Unfortunately the code for & in keypress is the same as the up arrow,
2752
// so we use the suppressKeyPressRepeat flag to avoid handling keypress
2753
// events when we know the keydown event was used to modify the
2754
// search term. #7799
2755
var suppressKeyPress, suppressKeyPressRepeat, suppressInput,
2756
nodeName = this.element[ 0 ].nodeName.toLowerCase(),
2757
isTextarea = nodeName === "textarea",
2758
isInput = nodeName === "input";
2761
// Textareas are always multi-line
2763
// Inputs are always single-line, even if inside a contentEditable element
2764
// IE also treats inputs as contentEditable
2766
// All other element types are determined by whether or not they're contentEditable
2767
this.element.prop( "isContentEditable" );
2769
this.valueMethod = this.element[ isTextarea || isInput ? "val" : "text" ];
2770
this.isNewMenu = true;
2773
.addClass( "ui-autocomplete-input" )
2774
.attr( "autocomplete", "off" );
2776
this._on( this.element, {
2777
keydown: function( event ) {
2778
if ( this.element.prop( "readOnly" ) ) {
2779
suppressKeyPress = true;
2780
suppressInput = true;
2781
suppressKeyPressRepeat = true;
2785
suppressKeyPress = false;
2786
suppressInput = false;
2787
suppressKeyPressRepeat = false;
2788
var keyCode = $.ui.keyCode;
2789
switch ( event.keyCode ) {
2790
case keyCode.PAGE_UP:
2791
suppressKeyPress = true;
2792
this._move( "previousPage", event );
2794
case keyCode.PAGE_DOWN:
2795
suppressKeyPress = true;
2796
this._move( "nextPage", event );
2799
suppressKeyPress = true;
2800
this._keyEvent( "previous", event );
2803
suppressKeyPress = true;
2804
this._keyEvent( "next", event );
2807
// when menu is open and has focus
2808
if ( this.menu.active ) {
2809
// #6055 - Opera still allows the keypress to occur
2810
// which causes forms to submit
2811
suppressKeyPress = true;
2812
event.preventDefault();
2813
this.menu.select( event );
2817
if ( this.menu.active ) {
2818
this.menu.select( event );
2821
case keyCode.ESCAPE:
2822
if ( this.menu.element.is( ":visible" ) ) {
2823
this._value( this.term );
2824
this.close( event );
2825
// Different browsers have different default behavior for escape
2826
// Single press can mean undo or clear
2827
// Double press in IE means clear the whole form
2828
event.preventDefault();
2832
suppressKeyPressRepeat = true;
2833
// search timeout should be triggered before the input value is changed
2834
this._searchTimeout( event );
2838
keypress: function( event ) {
2839
if ( suppressKeyPress ) {
2840
suppressKeyPress = false;
2841
if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
2842
event.preventDefault();
2846
if ( suppressKeyPressRepeat ) {
2850
// replicate some key handlers to allow them to repeat in Firefox and Opera
2851
var keyCode = $.ui.keyCode;
2852
switch ( event.keyCode ) {
2853
case keyCode.PAGE_UP:
2854
this._move( "previousPage", event );
2856
case keyCode.PAGE_DOWN:
2857
this._move( "nextPage", event );
2860
this._keyEvent( "previous", event );
2863
this._keyEvent( "next", event );
2867
input: function( event ) {
2868
if ( suppressInput ) {
2869
suppressInput = false;
2870
event.preventDefault();
2873
this._searchTimeout( event );
2876
this.selectedItem = null;
2877
this.previous = this._value();
2879
blur: function( event ) {
2880
if ( this.cancelBlur ) {
2881
delete this.cancelBlur;
2885
clearTimeout( this.searching );
2886
this.close( event );
2887
this._change( event );
2892
this.menu = $( "<ul>" )
2893
.addClass( "ui-autocomplete ui-front" )
2894
.appendTo( this._appendTo() )
2896
// disable ARIA support, the live region takes care of that
2900
.menu( "instance" );
2902
this._on( this.menu.element, {
2903
mousedown: function( event ) {
2904
// prevent moving focus out of the text field
2905
event.preventDefault();
2907
// IE doesn't prevent moving focus even with event.preventDefault()
2908
// so we set a flag to know when we should ignore the blur event
2909
this.cancelBlur = true;
2910
this._delay(function() {
2911
delete this.cancelBlur;
2914
// clicking on the scrollbar causes focus to shift to the body
2915
// but we can't detect a mouseup or a click immediately afterward
2916
// so we have to track the next mousedown and close the menu if
2917
// the user clicks somewhere outside of the autocomplete
2918
var menuElement = this.menu.element[ 0 ];
2919
if ( !$( event.target ).closest( ".ui-menu-item" ).length ) {
2920
this._delay(function() {
2922
this.document.one( "mousedown", function( event ) {
2923
if ( event.target !== that.element[ 0 ] &&
2924
event.target !== menuElement &&
2925
!$.contains( menuElement, event.target ) ) {
2932
menufocus: function( event, ui ) {
2935
// Prevent accidental activation of menu items in Firefox (#7024 #9118)
2936
if ( this.isNewMenu ) {
2937
this.isNewMenu = false;
2938
if ( event.originalEvent && /^mouse/.test( event.originalEvent.type ) ) {
2941
this.document.one( "mousemove", function() {
2942
$( event.target ).trigger( event.originalEvent );
2949
item = ui.item.data( "ui-autocomplete-item" );
2950
if ( false !== this._trigger( "focus", event, { item: item } ) ) {
2951
// use value to match what will end up in the input, if it was a key event
2952
if ( event.originalEvent && /^key/.test( event.originalEvent.type ) ) {
2953
this._value( item.value );
2957
// Announce the value in the liveRegion
2958
label = ui.item.attr( "aria-label" ) || item.value;
2959
if ( label && jQuery.trim( label ).length ) {
2960
this.liveRegion.children().hide();
2961
$( "<div>" ).text( label ).appendTo( this.liveRegion );
2964
menuselect: function( event, ui ) {
2965
var item = ui.item.data( "ui-autocomplete-item" ),
2966
previous = this.previous;
2968
// only trigger when focus was lost (click on menu)
2969
if ( this.element[ 0 ] !== this.document[ 0 ].activeElement ) {
2970
this.element.focus();
2971
this.previous = previous;
2972
// #6109 - IE triggers two focus events and the second
2973
// is asynchronous, so we need to reset the previous
2974
// term synchronously and asynchronously :-(
2975
this._delay(function() {
2976
this.previous = previous;
2977
this.selectedItem = item;
2981
if ( false !== this._trigger( "select", event, { item: item } ) ) {
2982
this._value( item.value );
2984
// reset the term after the select event
2985
// this allows custom select handling to work properly
2986
this.term = this._value();
2988
this.close( event );
2989
this.selectedItem = item;
2993
this.liveRegion = $( "<span>", {
2995
"aria-live": "assertive",
2996
"aria-relevant": "additions"
2998
.addClass( "ui-helper-hidden-accessible" )
2999
.appendTo( this.document[ 0 ].body );
3001
// turning off autocomplete prevents the browser from remembering the
3002
// value when navigating through history, so we re-enable autocomplete
3003
// if the page is unloaded before the widget is destroyed. #7790
3004
this._on( this.window, {
3005
beforeunload: function() {
3006
this.element.removeAttr( "autocomplete" );
3011
_destroy: function() {
3012
clearTimeout( this.searching );
3014
.removeClass( "ui-autocomplete-input" )
3015
.removeAttr( "autocomplete" );
3016
this.menu.element.remove();
3017
this.liveRegion.remove();
3020
_setOption: function( key, value ) {
3021
this._super( key, value );
3022
if ( key === "source" ) {
3025
if ( key === "appendTo" ) {
3026
this.menu.element.appendTo( this._appendTo() );
3028
if ( key === "disabled" && value && this.xhr ) {
3033
_appendTo: function() {
3034
var element = this.options.appendTo;
3037
element = element.jquery || element.nodeType ?
3039
this.document.find( element ).eq( 0 );
3042
if ( !element || !element[ 0 ] ) {
3043
element = this.element.closest( ".ui-front" );
3046
if ( !element.length ) {
3047
element = this.document[ 0 ].body;
3053
_initSource: function() {
3056
if ( $.isArray( this.options.source ) ) {
3057
array = this.options.source;
3058
this.source = function( request, response ) {
3059
response( $.ui.autocomplete.filter( array, request.term ) );
3061
} else if ( typeof this.options.source === "string" ) {
3062
url = this.options.source;
3063
this.source = function( request, response ) {
3071
success: function( data ) {
3080
this.source = this.options.source;
3084
_searchTimeout: function( event ) {
3085
clearTimeout( this.searching );
3086
this.searching = this._delay(function() {
3088
// Search if the value has changed, or if the user retypes the same value (see #7434)
3089
var equalValues = this.term === this._value(),
3090
menuVisible = this.menu.element.is( ":visible" ),
3091
modifierKey = event.altKey || event.ctrlKey || event.metaKey || event.shiftKey;
3093
if ( !equalValues || ( equalValues && !menuVisible && !modifierKey ) ) {
3094
this.selectedItem = null;
3095
this.search( null, event );
3097
}, this.options.delay );
3100
search: function( value, event ) {
3101
value = value != null ? value : this._value();
3103
// always save the actual value, not the one passed as an argument
3104
this.term = this._value();
3106
if ( value.length < this.options.minLength ) {
3107
return this.close( event );
3110
if ( this._trigger( "search", event ) === false ) {
3114
return this._search( value );
3117
_search: function( value ) {
3119
this.element.addClass( "ui-autocomplete-loading" );
3120
this.cancelSearch = false;
3122
this.source( { term: value }, this._response() );
3125
_response: function() {
3126
var index = ++this.requestIndex;
3128
return $.proxy(function( content ) {
3129
if ( index === this.requestIndex ) {
3130
this.__response( content );
3134
if ( !this.pending ) {
3135
this.element.removeClass( "ui-autocomplete-loading" );
3140
__response: function( content ) {
3142
content = this._normalize( content );
3144
this._trigger( "response", null, { content: content } );
3145
if ( !this.options.disabled && content && content.length && !this.cancelSearch ) {
3146
this._suggest( content );
3147
this._trigger( "open" );
3149
// use ._close() instead of .close() so we don't cancel future searches
3154
close: function( event ) {
3155
this.cancelSearch = true;
3156
this._close( event );
3159
_close: function( event ) {
3160
if ( this.menu.element.is( ":visible" ) ) {
3161
this.menu.element.hide();
3163
this.isNewMenu = true;
3164
this._trigger( "close", event );
3168
_change: function( event ) {
3169
if ( this.previous !== this._value() ) {
3170
this._trigger( "change", event, { item: this.selectedItem } );
3174
_normalize: function( items ) {
3175
// assume all items have the right format when the first item is complete
3176
if ( items.length && items[ 0 ].label && items[ 0 ].value ) {
3179
return $.map( items, function( item ) {
3180
if ( typeof item === "string" ) {
3186
return $.extend( {}, item, {
3187
label: item.label || item.value,
3188
value: item.value || item.label
3193
_suggest: function( items ) {
3194
var ul = this.menu.element.empty();
3195
this._renderMenu( ul, items );
3196
this.isNewMenu = true;
3197
this.menu.refresh();
3199
// size and position menu
3202
ul.position( $.extend({
3204
}, this.options.position ) );
3206
if ( this.options.autoFocus ) {
3211
_resizeMenu: function() {
3212
var ul = this.menu.element;
3213
ul.outerWidth( Math.max(
3214
// Firefox wraps long text (possibly a rounding bug)
3215
// so we add 1px to avoid the wrapping (#7513)
3216
ul.width( "" ).outerWidth() + 1,
3217
this.element.outerWidth()
3221
_renderMenu: function( ul, items ) {
3223
$.each( items, function( index, item ) {
3224
that._renderItemData( ul, item );
3228
_renderItemData: function( ul, item ) {
3229
return this._renderItem( ul, item ).data( "ui-autocomplete-item", item );
3232
_renderItem: function( ul, item ) {
3233
return $( "<li>" ).text( item.label ).appendTo( ul );
3236
_move: function( direction, event ) {
3237
if ( !this.menu.element.is( ":visible" ) ) {
3238
this.search( null, event );
3241
if ( this.menu.isFirstItem() && /^previous/.test( direction ) ||
3242
this.menu.isLastItem() && /^next/.test( direction ) ) {
3244
if ( !this.isMultiLine ) {
3245
this._value( this.term );
3251
this.menu[ direction ]( event );
3254
widget: function() {
3255
return this.menu.element;
3258
_value: function() {
3259
return this.valueMethod.apply( this.element, arguments );
3262
_keyEvent: function( keyEvent, event ) {
3263
if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
3264
this._move( keyEvent, event );
3266
// prevents moving cursor to beginning/end of the text field in some browsers
3267
event.preventDefault();
3272
$.extend( $.ui.autocomplete, {
3273
escapeRegex: function( value ) {
3274
return value.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" );
3276
filter: function( array, term ) {
3277
var matcher = new RegExp( $.ui.autocomplete.escapeRegex( term ), "i" );
3278
return $.grep( array, function( value ) {
3279
return matcher.test( value.label || value.value || value );
3284
// live region extension, adding a `messages` option
3285
// NOTE: This is an experimental API. We are still investigating
3286
// a full solution for string manipulation and internationalization.
3287
$.widget( "ui.autocomplete", $.ui.autocomplete, {
3290
noResults: "No search results.",
3291
results: function( amount ) {
3292
return amount + ( amount > 1 ? " results are" : " result is" ) +
3293
" available, use up and down arrow keys to navigate.";
3298
__response: function( content ) {
3300
this._superApply( arguments );
3301
if ( this.options.disabled || this.cancelSearch ) {
3304
if ( content && content.length ) {
3305
message = this.options.messages.results( content.length );
3307
message = this.options.messages.noResults;
3309
this.liveRegion.children().hide();
3310
$( "<div>" ).text( message ).appendTo( this.liveRegion );
3314
var autocomplete = $.ui.autocomplete;
3318
* jQuery UI Button 1.11.0
3319
* http://jqueryui.com
3321
* Copyright 2014 jQuery Foundation and other contributors
3322
* Released under the MIT license.
3323
* http://jquery.org/license
3325
* http://api.jqueryui.com/button/
3330
baseClasses = "ui-button ui-widget ui-state-default ui-corner-all",
3331
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",
3332
formResetHandler = function() {
3333
var form = $( this );
3334
setTimeout(function() {
3335
form.find( ":ui-button" ).button( "refresh" );
3338
radioGroup = function( radio ) {
3339
var name = radio.name,
3343
name = name.replace( /'/g, "\\'" );
3345
radios = $( form ).find( "[name='" + name + "'][type=radio]" );
3347
radios = $( "[name='" + name + "'][type=radio]", radio.ownerDocument )
3348
.filter(function() {
3356
$.widget( "ui.button", {
3358
defaultElement: "<button>",
3368
_create: function() {
3369
this.element.closest( "form" )
3370
.unbind( "reset" + this.eventNamespace )
3371
.bind( "reset" + this.eventNamespace, formResetHandler );
3373
if ( typeof this.options.disabled !== "boolean" ) {
3374
this.options.disabled = !!this.element.prop( "disabled" );
3376
this.element.prop( "disabled", this.options.disabled );
3379
this._determineButtonType();
3380
this.hasTitle = !!this.buttonElement.attr( "title" );
3383
options = this.options,
3384
toggleButton = this.type === "checkbox" || this.type === "radio",
3385
activeClass = !toggleButton ? "ui-state-active" : "";
3387
if ( options.label === null ) {
3388
options.label = (this.type === "input" ? this.buttonElement.val() : this.buttonElement.html());
3391
this._hoverable( this.buttonElement );
3394
.addClass( baseClasses )
3395
.attr( "role", "button" )
3396
.bind( "mouseenter" + this.eventNamespace, function() {
3397
if ( options.disabled ) {
3400
if ( this === lastActive ) {
3401
$( this ).addClass( "ui-state-active" );
3404
.bind( "mouseleave" + this.eventNamespace, function() {
3405
if ( options.disabled ) {
3408
$( this ).removeClass( activeClass );
3410
.bind( "click" + this.eventNamespace, function( event ) {
3411
if ( options.disabled ) {
3412
event.preventDefault();
3413
event.stopImmediatePropagation();
3417
// Can't use _focusable() because the element that receives focus
3418
// and the element that gets the ui-state-focus class are different
3421
this.buttonElement.addClass( "ui-state-focus" );
3424
this.buttonElement.removeClass( "ui-state-focus" );
3428
if ( toggleButton ) {
3429
this.element.bind( "change" + this.eventNamespace, function() {
3434
if ( this.type === "checkbox" ) {
3435
this.buttonElement.bind( "click" + this.eventNamespace, function() {
3436
if ( options.disabled ) {
3440
} else if ( this.type === "radio" ) {
3441
this.buttonElement.bind( "click" + this.eventNamespace, function() {
3442
if ( options.disabled ) {
3445
$( this ).addClass( "ui-state-active" );
3446
that.buttonElement.attr( "aria-pressed", "true" );
3448
var radio = that.element[ 0 ];
3452
return $( this ).button( "widget" )[ 0 ];
3454
.removeClass( "ui-state-active" )
3455
.attr( "aria-pressed", "false" );
3459
.bind( "mousedown" + this.eventNamespace, function() {
3460
if ( options.disabled ) {
3463
$( this ).addClass( "ui-state-active" );
3465
that.document.one( "mouseup", function() {
3469
.bind( "mouseup" + this.eventNamespace, function() {
3470
if ( options.disabled ) {
3473
$( this ).removeClass( "ui-state-active" );
3475
.bind( "keydown" + this.eventNamespace, function(event) {
3476
if ( options.disabled ) {
3479
if ( event.keyCode === $.ui.keyCode.SPACE || event.keyCode === $.ui.keyCode.ENTER ) {
3480
$( this ).addClass( "ui-state-active" );
3483
// see #8559, we bind to blur here in case the button element loses
3484
// focus between keydown and keyup, it would be left in an "active" state
3485
.bind( "keyup" + this.eventNamespace + " blur" + this.eventNamespace, function() {
3486
$( this ).removeClass( "ui-state-active" );
3489
if ( this.buttonElement.is("a") ) {
3490
this.buttonElement.keyup(function(event) {
3491
if ( event.keyCode === $.ui.keyCode.SPACE ) {
3492
// TODO pass through original event correctly (just as 2nd argument doesn't work)
3499
this._setOption( "disabled", options.disabled );
3500
this._resetButton();
3503
_determineButtonType: function() {
3504
var ancestor, labelSelector, checked;
3506
if ( this.element.is("[type=checkbox]") ) {
3507
this.type = "checkbox";
3508
} else if ( this.element.is("[type=radio]") ) {
3509
this.type = "radio";
3510
} else if ( this.element.is("input") ) {
3511
this.type = "input";
3513
this.type = "button";
3516
if ( this.type === "checkbox" || this.type === "radio" ) {
3517
// we don't search against the document in case the element
3518
// is disconnected from the DOM
3519
ancestor = this.element.parents().last();
3520
labelSelector = "label[for='" + this.element.attr("id") + "']";
3521
this.buttonElement = ancestor.find( labelSelector );
3522
if ( !this.buttonElement.length ) {
3523
ancestor = ancestor.length ? ancestor.siblings() : this.element.siblings();
3524
this.buttonElement = ancestor.filter( labelSelector );
3525
if ( !this.buttonElement.length ) {
3526
this.buttonElement = ancestor.find( labelSelector );
3529
this.element.addClass( "ui-helper-hidden-accessible" );
3531
checked = this.element.is( ":checked" );
3533
this.buttonElement.addClass( "ui-state-active" );
3535
this.buttonElement.prop( "aria-pressed", checked );
3537
this.buttonElement = this.element;
3541
widget: function() {
3542
return this.buttonElement;
3545
_destroy: function() {
3547
.removeClass( "ui-helper-hidden-accessible" );
3549
.removeClass( baseClasses + " ui-state-active " + typeClasses )
3550
.removeAttr( "role" )
3551
.removeAttr( "aria-pressed" )
3552
.html( this.buttonElement.find(".ui-button-text").html() );
3554
if ( !this.hasTitle ) {
3555
this.buttonElement.removeAttr( "title" );
3559
_setOption: function( key, value ) {
3560
this._super( key, value );
3561
if ( key === "disabled" ) {
3562
this.widget().toggleClass( "ui-state-disabled", !!value );
3563
this.element.prop( "disabled", !!value );
3565
if ( this.type === "checkbox" || this.type === "radio" ) {
3566
this.buttonElement.removeClass( "ui-state-focus" );
3568
this.buttonElement.removeClass( "ui-state-focus ui-state-active" );
3573
this._resetButton();
3576
refresh: function() {
3578
var isDisabled = this.element.is( "input, button" ) ? this.element.is( ":disabled" ) : this.element.hasClass( "ui-button-disabled" );
3580
if ( isDisabled !== this.options.disabled ) {
3581
this._setOption( "disabled", isDisabled );
3583
if ( this.type === "radio" ) {
3584
radioGroup( this.element[0] ).each(function() {
3585
if ( $( this ).is( ":checked" ) ) {
3586
$( this ).button( "widget" )
3587
.addClass( "ui-state-active" )
3588
.attr( "aria-pressed", "true" );
3590
$( this ).button( "widget" )
3591
.removeClass( "ui-state-active" )
3592
.attr( "aria-pressed", "false" );
3595
} else if ( this.type === "checkbox" ) {
3596
if ( this.element.is( ":checked" ) ) {
3598
.addClass( "ui-state-active" )
3599
.attr( "aria-pressed", "true" );
3602
.removeClass( "ui-state-active" )
3603
.attr( "aria-pressed", "false" );
3608
_resetButton: function() {
3609
if ( this.type === "input" ) {
3610
if ( this.options.label ) {
3611
this.element.val( this.options.label );
3615
var buttonElement = this.buttonElement.removeClass( typeClasses ),
3616
buttonText = $( "<span></span>", this.document[0] )
3617
.addClass( "ui-button-text" )
3618
.html( this.options.label )
3619
.appendTo( buttonElement.empty() )
3621
icons = this.options.icons,
3622
multipleIcons = icons.primary && icons.secondary,
3625
if ( icons.primary || icons.secondary ) {
3626
if ( this.options.text ) {
3627
buttonClasses.push( "ui-button-text-icon" + ( multipleIcons ? "s" : ( icons.primary ? "-primary" : "-secondary" ) ) );
3630
if ( icons.primary ) {
3631
buttonElement.prepend( "<span class='ui-button-icon-primary ui-icon " + icons.primary + "'></span>" );
3634
if ( icons.secondary ) {
3635
buttonElement.append( "<span class='ui-button-icon-secondary ui-icon " + icons.secondary + "'></span>" );
3638
if ( !this.options.text ) {
3639
buttonClasses.push( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" );
3641
if ( !this.hasTitle ) {
3642
buttonElement.attr( "title", $.trim( buttonText ) );
3646
buttonClasses.push( "ui-button-text-only" );
3648
buttonElement.addClass( buttonClasses.join( " " ) );
3652
$.widget( "ui.buttonset", {
3655
items: "button, input[type=button], input[type=submit], input[type=reset], input[type=checkbox], input[type=radio], a, :data(ui-button)"
3658
_create: function() {
3659
this.element.addClass( "ui-buttonset" );
3666
_setOption: function( key, value ) {
3667
if ( key === "disabled" ) {
3668
this.buttons.button( "option", key, value );
3671
this._super( key, value );
3674
refresh: function() {
3675
var rtl = this.element.css( "direction" ) === "rtl",
3676
allButtons = this.element.find( this.options.items ),
3677
existingButtons = allButtons.filter( ":ui-button" );
3679
// Initialize new buttons
3680
allButtons.not( ":ui-button" ).button();
3682
// Refresh existing buttons
3683
existingButtons.button( "refresh" );
3685
this.buttons = allButtons
3687
return $( this ).button( "widget" )[ 0 ];
3689
.removeClass( "ui-corner-all ui-corner-left ui-corner-right" )
3691
.addClass( rtl ? "ui-corner-right" : "ui-corner-left" )
3694
.addClass( rtl ? "ui-corner-left" : "ui-corner-right" )
3699
_destroy: function() {
3700
this.element.removeClass( "ui-buttonset" );
3703
return $( this ).button( "widget" )[ 0 ];
3705
.removeClass( "ui-corner-left ui-corner-right" )
3707
.button( "destroy" );
3711
var button = $.ui.button;
3715
* jQuery UI Datepicker 1.11.0
3716
* http://jqueryui.com
3718
* Copyright 2014 jQuery Foundation and other contributors
3719
* Released under the MIT license.
3720
* http://jquery.org/license
3722
* http://api.jqueryui.com/datepicker/
3726
$.extend($.ui, { datepicker: { version: "1.11.0" } });
3728
var datepicker_instActive;
3730
function datepicker_getZindex( elem ) {
3731
var position, value;
3732
while ( elem.length && elem[ 0 ] !== document ) {
3733
// Ignore z-index if position is set to a value where z-index is ignored by the browser
3734
// This makes behavior of this function consistent across browsers
3735
// WebKit always returns auto if the element is positioned
3736
position = elem.css( "position" );
3737
if ( position === "absolute" || position === "relative" || position === "fixed" ) {
3738
// IE returns 0 when zIndex is not specified
3739
// other browsers return a string
3740
// we ignore the case of nested elements with an explicit value of 0
3741
// <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
3742
value = parseInt( elem.css( "zIndex" ), 10 );
3743
if ( !isNaN( value ) && value !== 0 ) {
3747
elem = elem.parent();
3752
/* Date picker manager.
3753
Use the singleton instance of this class, $.datepicker, to interact with the date picker.
3754
Settings for (groups of) date pickers are maintained in an instance object,
3755
allowing multiple different settings on the same page. */
3757
function Datepicker() {
3758
this._curInst = null; // The current instance in use
3759
this._keyEvent = false; // If the last event was a key event
3760
this._disabledInputs = []; // List of date picker inputs that have been disabled
3761
this._datepickerShowing = false; // True if the popup picker is showing , false if not
3762
this._inDialog = false; // True if showing within a "dialog", false if not
3763
this._mainDivId = "ui-datepicker-div"; // The ID of the main datepicker division
3764
this._inlineClass = "ui-datepicker-inline"; // The name of the inline marker class
3765
this._appendClass = "ui-datepicker-append"; // The name of the append marker class
3766
this._triggerClass = "ui-datepicker-trigger"; // The name of the trigger marker class
3767
this._dialogClass = "ui-datepicker-dialog"; // The name of the dialog marker class
3768
this._disableClass = "ui-datepicker-disabled"; // The name of the disabled covering marker class
3769
this._unselectableClass = "ui-datepicker-unselectable"; // The name of the unselectable cell marker class
3770
this._currentClass = "ui-datepicker-current-day"; // The name of the current day marker class
3771
this._dayOverClass = "ui-datepicker-days-cell-over"; // The name of the day hover marker class
3772
this.regional = []; // Available regional settings, indexed by language code
3773
this.regional[""] = { // Default regional settings
3774
closeText: "Done", // Display text for close link
3775
prevText: "Prev", // Display text for previous month link
3776
nextText: "Next", // Display text for next month link
3777
currentText: "Today", // Display text for current month link
3778
monthNames: ["January","February","March","April","May","June",
3779
"July","August","September","October","November","December"], // Names of months for drop-down and formatting
3780
monthNamesShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], // For formatting
3781
dayNames: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], // For formatting
3782
dayNamesShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], // For formatting
3783
dayNamesMin: ["Su","Mo","Tu","We","Th","Fr","Sa"], // Column headings for days starting at Sunday
3784
weekHeader: "Wk", // Column header for week of the year
3785
dateFormat: "mm/dd/yy", // See format options on parseDate
3786
firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
3787
isRTL: false, // True if right-to-left language, false if left-to-right
3788
showMonthAfterYear: false, // True if the year select precedes month, false for month then year
3789
yearSuffix: "" // Additional text to append to the year in the month headers
3791
this._defaults = { // Global defaults for all the date picker instances
3792
showOn: "focus", // "focus" for popup on focus,
3793
// "button" for trigger button, or "both" for either
3794
showAnim: "fadeIn", // Name of jQuery animation for popup
3795
showOptions: {}, // Options for enhanced animations
3796
defaultDate: null, // Used when field is blank: actual date,
3797
// +/-number for offset from today, null for today
3798
appendText: "", // Display text following the input box, e.g. showing the format
3799
buttonText: "...", // Text for trigger button
3800
buttonImage: "", // URL for trigger button image
3801
buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
3802
hideIfNoPrevNext: false, // True to hide next/previous month links
3803
// if not applicable, false to just disable them
3804
navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
3805
gotoCurrent: false, // True if today link goes back to current selection instead
3806
changeMonth: false, // True if month can be selected directly, false if only prev/next
3807
changeYear: false, // True if year can be selected directly, false if only prev/next
3808
yearRange: "c-10:c+10", // Range of years to display in drop-down,
3809
// either relative to today's year (-nn:+nn), relative to currently displayed year
3810
// (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
3811
showOtherMonths: false, // True to show dates in other months, false to leave blank
3812
selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
3813
showWeek: false, // True to show week of the year, false to not show it
3814
calculateWeek: this.iso8601Week, // How to calculate the week of the year,
3815
// takes a Date and returns the number of the week for it
3816
shortYearCutoff: "+10", // Short year values < this are in the current century,
3817
// > this are in the previous century,
3818
// string value starting with "+" for current year + value
3819
minDate: null, // The earliest selectable date, or null for no limit
3820
maxDate: null, // The latest selectable date, or null for no limit
3821
duration: "fast", // Duration of display/closure
3822
beforeShowDay: null, // Function that takes a date and returns an array with
3823
// [0] = true if selectable, false if not, [1] = custom CSS class name(s) or "",
3824
// [2] = cell title (optional), e.g. $.datepicker.noWeekends
3825
beforeShow: null, // Function that takes an input field and
3826
// returns a set of custom settings for the date picker
3827
onSelect: null, // Define a callback function when a date is selected
3828
onChangeMonthYear: null, // Define a callback function when the month or year is changed
3829
onClose: null, // Define a callback function when the datepicker is closed
3830
numberOfMonths: 1, // Number of months to show at a time
3831
showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
3832
stepMonths: 1, // Number of months to step back/forward
3833
stepBigMonths: 12, // Number of months to step back/forward for the big links
3834
altField: "", // Selector for an alternate field to store selected dates into
3835
altFormat: "", // The date format to use for the alternate field
3836
constrainInput: true, // The input is constrained by the current date format
3837
showButtonPanel: false, // True to show button panel, false to not show it
3838
autoSize: false, // True to size the input for the date format, false to leave as is
3839
disabled: false // The initial disabled state
3841
$.extend(this._defaults, this.regional[""]);
3842
this.regional.en = $.extend( true, {}, this.regional[ "" ]);
3843
this.regional[ "en-US" ] = $.extend( true, {}, this.regional.en );
3844
this.dpDiv = datepicker_bindHover($("<div id='" + this._mainDivId + "' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>"));
3847
$.extend(Datepicker.prototype, {
3848
/* Class name added to elements to indicate already configured with a date picker. */
3849
markerClassName: "hasDatepicker",
3851
//Keep track of the maximum number of rows displayed (see #7043)
3854
// TODO rename to "widget" when switching to widget factory
3855
_widgetDatepicker: function() {
3859
/* Override the default settings for all instances of the date picker.
3860
* @param settings object - the new settings to use as defaults (anonymous object)
3861
* @return the manager object
3863
setDefaults: function(settings) {
3864
datepicker_extendRemove(this._defaults, settings || {});
3868
/* Attach the date picker to a jQuery selection.
3869
* @param target element - the target input field or division or span
3870
* @param settings object - the new settings to use for this date picker instance (anonymous)
3872
_attachDatepicker: function(target, settings) {
3873
var nodeName, inline, inst;
3874
nodeName = target.nodeName.toLowerCase();
3875
inline = (nodeName === "div" || nodeName === "span");
3878
target.id = "dp" + this.uuid;
3880
inst = this._newInst($(target), inline);
3881
inst.settings = $.extend({}, settings || {});
3882
if (nodeName === "input") {
3883
this._connectDatepicker(target, inst);
3884
} else if (inline) {
3885
this._inlineDatepicker(target, inst);
3889
/* Create a new instance object. */
3890
_newInst: function(target, inline) {
3891
var id = target[0].id.replace(/([^A-Za-z0-9_\-])/g, "\\\\$1"); // escape jQuery meta chars
3892
return {id: id, input: target, // associated target
3893
selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
3894
drawMonth: 0, drawYear: 0, // month being drawn
3895
inline: inline, // is datepicker inline or not
3896
dpDiv: (!inline ? this.dpDiv : // presentation div
3897
datepicker_bindHover($("<div class='" + this._inlineClass + " ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>")))};
3900
/* Attach the date picker to an input field. */
3901
_connectDatepicker: function(target, inst) {
3902
var input = $(target);
3903
inst.append = $([]);
3904
inst.trigger = $([]);
3905
if (input.hasClass(this.markerClassName)) {
3908
this._attachments(input, inst);
3909
input.addClass(this.markerClassName).keydown(this._doKeyDown).
3910
keypress(this._doKeyPress).keyup(this._doKeyUp);
3911
this._autoSize(inst);
3912
$.data(target, "datepicker", inst);
3913
//If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665)
3914
if( inst.settings.disabled ) {
3915
this._disableDatepicker( target );
3919
/* Make attachments based on settings. */
3920
_attachments: function(input, inst) {
3921
var showOn, buttonText, buttonImage,
3922
appendText = this._get(inst, "appendText"),
3923
isRTL = this._get(inst, "isRTL");
3926
inst.append.remove();
3929
inst.append = $("<span class='" + this._appendClass + "'>" + appendText + "</span>");
3930
input[isRTL ? "before" : "after"](inst.append);
3933
input.unbind("focus", this._showDatepicker);
3936
inst.trigger.remove();
3939
showOn = this._get(inst, "showOn");
3940
if (showOn === "focus" || showOn === "both") { // pop-up date picker when in the marked field
3941
input.focus(this._showDatepicker);
3943
if (showOn === "button" || showOn === "both") { // pop-up date picker when button clicked
3944
buttonText = this._get(inst, "buttonText");
3945
buttonImage = this._get(inst, "buttonImage");
3946
inst.trigger = $(this._get(inst, "buttonImageOnly") ?
3947
$("<img/>").addClass(this._triggerClass).
3948
attr({ src: buttonImage, alt: buttonText, title: buttonText }) :
3949
$("<button type='button'></button>").addClass(this._triggerClass).
3950
html(!buttonImage ? buttonText : $("<img/>").attr(
3951
{ src:buttonImage, alt:buttonText, title:buttonText })));
3952
input[isRTL ? "before" : "after"](inst.trigger);
3953
inst.trigger.click(function() {
3954
if ($.datepicker._datepickerShowing && $.datepicker._lastInput === input[0]) {
3955
$.datepicker._hideDatepicker();
3956
} else if ($.datepicker._datepickerShowing && $.datepicker._lastInput !== input[0]) {
3957
$.datepicker._hideDatepicker();
3958
$.datepicker._showDatepicker(input[0]);
3960
$.datepicker._showDatepicker(input[0]);
3967
/* Apply the maximum length for the date format. */
3968
_autoSize: function(inst) {
3969
if (this._get(inst, "autoSize") && !inst.inline) {
3970
var findMax, max, maxI, i,
3971
date = new Date(2009, 12 - 1, 20), // Ensure double digits
3972
dateFormat = this._get(inst, "dateFormat");
3974
if (dateFormat.match(/[DM]/)) {
3975
findMax = function(names) {
3978
for (i = 0; i < names.length; i++) {
3979
if (names[i].length > max) {
3980
max = names[i].length;
3986
date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ?
3987
"monthNames" : "monthNamesShort"))));
3988
date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ?
3989
"dayNames" : "dayNamesShort"))) + 20 - date.getDay());
3991
inst.input.attr("size", this._formatDate(inst, date).length);
3995
/* Attach an inline date picker to a div. */
3996
_inlineDatepicker: function(target, inst) {
3997
var divSpan = $(target);
3998
if (divSpan.hasClass(this.markerClassName)) {
4001
divSpan.addClass(this.markerClassName).append(inst.dpDiv);
4002
$.data(target, "datepicker", inst);
4003
this._setDate(inst, this._getDefaultDate(inst), true);
4004
this._updateDatepicker(inst);
4005
this._updateAlternate(inst);
4006
//If disabled option is true, disable the datepicker before showing it (see ticket #5665)
4007
if( inst.settings.disabled ) {
4008
this._disableDatepicker( target );
4010
// Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements
4011
// http://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height
4012
inst.dpDiv.css( "display", "block" );
4015
/* Pop-up the date picker in a "dialog" box.
4016
* @param input element - ignored
4017
* @param date string or Date - the initial date to display
4018
* @param onSelect function - the function to call when a date is selected
4019
* @param settings object - update the dialog date picker instance's settings (anonymous object)
4020
* @param pos int[2] - coordinates for the dialog's position within the screen or
4021
* event - with x/y coordinates or
4022
* leave empty for default (screen centre)
4023
* @return the manager object
4025
_dialogDatepicker: function(input, date, onSelect, settings, pos) {
4026
var id, browserWidth, browserHeight, scrollX, scrollY,
4027
inst = this._dialogInst; // internal instance
4031
id = "dp" + this.uuid;
4032
this._dialogInput = $("<input type='text' id='" + id +
4033
"' style='position: absolute; top: -100px; width: 0px;'/>");
4034
this._dialogInput.keydown(this._doKeyDown);
4035
$("body").append(this._dialogInput);
4036
inst = this._dialogInst = this._newInst(this._dialogInput, false);
4038
$.data(this._dialogInput[0], "datepicker", inst);
4040
datepicker_extendRemove(inst.settings, settings || {});
4041
date = (date && date.constructor === Date ? this._formatDate(inst, date) : date);
4042
this._dialogInput.val(date);
4044
this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);
4046
browserWidth = document.documentElement.clientWidth;
4047
browserHeight = document.documentElement.clientHeight;
4048
scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
4049
scrollY = document.documentElement.scrollTop || document.body.scrollTop;
4050
this._pos = // should use actual width/height below
4051
[(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY];
4054
// move input on screen for focus, but hidden behind dialog
4055
this._dialogInput.css("left", (this._pos[0] + 20) + "px").css("top", this._pos[1] + "px");
4056
inst.settings.onSelect = onSelect;
4057
this._inDialog = true;
4058
this.dpDiv.addClass(this._dialogClass);
4059
this._showDatepicker(this._dialogInput[0]);
4061
$.blockUI(this.dpDiv);
4063
$.data(this._dialogInput[0], "datepicker", inst);
4067
/* Detach a datepicker from its control.
4068
* @param target element - the target input field or division or span
4070
_destroyDatepicker: function(target) {
4072
$target = $(target),
4073
inst = $.data(target, "datepicker");
4075
if (!$target.hasClass(this.markerClassName)) {
4079
nodeName = target.nodeName.toLowerCase();
4080
$.removeData(target, "datepicker");
4081
if (nodeName === "input") {
4082
inst.append.remove();
4083
inst.trigger.remove();
4084
$target.removeClass(this.markerClassName).
4085
unbind("focus", this._showDatepicker).
4086
unbind("keydown", this._doKeyDown).
4087
unbind("keypress", this._doKeyPress).
4088
unbind("keyup", this._doKeyUp);
4089
} else if (nodeName === "div" || nodeName === "span") {
4090
$target.removeClass(this.markerClassName).empty();
4094
/* Enable the date picker to a jQuery selection.
4095
* @param target element - the target input field or division or span
4097
_enableDatepicker: function(target) {
4098
var nodeName, inline,
4099
$target = $(target),
4100
inst = $.data(target, "datepicker");
4102
if (!$target.hasClass(this.markerClassName)) {
4106
nodeName = target.nodeName.toLowerCase();
4107
if (nodeName === "input") {
4108
target.disabled = false;
4109
inst.trigger.filter("button").
4110
each(function() { this.disabled = false; }).end().
4111
filter("img").css({opacity: "1.0", cursor: ""});
4112
} else if (nodeName === "div" || nodeName === "span") {
4113
inline = $target.children("." + this._inlineClass);
4114
inline.children().removeClass("ui-state-disabled");
4115
inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
4116
prop("disabled", false);
4118
this._disabledInputs = $.map(this._disabledInputs,
4119
function(value) { return (value === target ? null : value); }); // delete entry
4122
/* Disable the date picker to a jQuery selection.
4123
* @param target element - the target input field or division or span
4125
_disableDatepicker: function(target) {
4126
var nodeName, inline,
4127
$target = $(target),
4128
inst = $.data(target, "datepicker");
4130
if (!$target.hasClass(this.markerClassName)) {
4134
nodeName = target.nodeName.toLowerCase();
4135
if (nodeName === "input") {
4136
target.disabled = true;
4137
inst.trigger.filter("button").
4138
each(function() { this.disabled = true; }).end().
4139
filter("img").css({opacity: "0.5", cursor: "default"});
4140
} else if (nodeName === "div" || nodeName === "span") {
4141
inline = $target.children("." + this._inlineClass);
4142
inline.children().addClass("ui-state-disabled");
4143
inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
4144
prop("disabled", true);
4146
this._disabledInputs = $.map(this._disabledInputs,
4147
function(value) { return (value === target ? null : value); }); // delete entry
4148
this._disabledInputs[this._disabledInputs.length] = target;
4151
/* Is the first field in a jQuery collection disabled as a datepicker?
4152
* @param target element - the target input field or division or span
4153
* @return boolean - true if disabled, false if enabled
4155
_isDisabledDatepicker: function(target) {
4159
for (var i = 0; i < this._disabledInputs.length; i++) {
4160
if (this._disabledInputs[i] === target) {
4167
/* Retrieve the instance data for the target control.
4168
* @param target element - the target input field or division or span
4169
* @return object - the associated instance data
4170
* @throws error if a jQuery problem getting data
4172
_getInst: function(target) {
4174
return $.data(target, "datepicker");
4177
throw "Missing instance data for this datepicker";
4181
/* Update or retrieve the settings for a date picker attached to an input field or division.
4182
* @param target element - the target input field or division or span
4183
* @param name object - the new settings to update or
4184
* string - the name of the setting to change or retrieve,
4185
* when retrieving also "all" for all instance settings or
4186
* "defaults" for all global defaults
4187
* @param value any - the new value for the setting
4188
* (omit if above is an object or to retrieve a value)
4190
_optionDatepicker: function(target, name, value) {
4191
var settings, date, minDate, maxDate,
4192
inst = this._getInst(target);
4194
if (arguments.length === 2 && typeof name === "string") {
4195
return (name === "defaults" ? $.extend({}, $.datepicker._defaults) :
4196
(inst ? (name === "all" ? $.extend({}, inst.settings) :
4197
this._get(inst, name)) : null));
4200
settings = name || {};
4201
if (typeof name === "string") {
4203
settings[name] = value;
4207
if (this._curInst === inst) {
4208
this._hideDatepicker();
4211
date = this._getDateDatepicker(target, true);
4212
minDate = this._getMinMaxDate(inst, "min");
4213
maxDate = this._getMinMaxDate(inst, "max");
4214
datepicker_extendRemove(inst.settings, settings);
4215
// reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided
4216
if (minDate !== null && settings.dateFormat !== undefined && settings.minDate === undefined) {
4217
inst.settings.minDate = this._formatDate(inst, minDate);
4219
if (maxDate !== null && settings.dateFormat !== undefined && settings.maxDate === undefined) {
4220
inst.settings.maxDate = this._formatDate(inst, maxDate);
4222
if ( "disabled" in settings ) {
4223
if ( settings.disabled ) {
4224
this._disableDatepicker(target);
4226
this._enableDatepicker(target);
4229
this._attachments($(target), inst);
4230
this._autoSize(inst);
4231
this._setDate(inst, date);
4232
this._updateAlternate(inst);
4233
this._updateDatepicker(inst);
4237
// change method deprecated
4238
_changeDatepicker: function(target, name, value) {
4239
this._optionDatepicker(target, name, value);
4242
/* Redraw the date picker attached to an input field or division.
4243
* @param target element - the target input field or division or span
4245
_refreshDatepicker: function(target) {
4246
var inst = this._getInst(target);
4248
this._updateDatepicker(inst);
4252
/* Set the dates for a jQuery selection.
4253
* @param target element - the target input field or division or span
4254
* @param date Date - the new date
4256
_setDateDatepicker: function(target, date) {
4257
var inst = this._getInst(target);
4259
this._setDate(inst, date);
4260
this._updateDatepicker(inst);
4261
this._updateAlternate(inst);
4265
/* Get the date(s) for the first entry in a jQuery selection.
4266
* @param target element - the target input field or division or span
4267
* @param noDefault boolean - true if no default date is to be used
4268
* @return Date - the current date
4270
_getDateDatepicker: function(target, noDefault) {
4271
var inst = this._getInst(target);
4272
if (inst && !inst.inline) {
4273
this._setDateFromField(inst, noDefault);
4275
return (inst ? this._getDate(inst) : null);
4278
/* Handle keystrokes. */
4279
_doKeyDown: function(event) {
4280
var onSelect, dateStr, sel,
4281
inst = $.datepicker._getInst(event.target),
4283
isRTL = inst.dpDiv.is(".ui-datepicker-rtl");
4285
inst._keyEvent = true;
4286
if ($.datepicker._datepickerShowing) {
4287
switch (event.keyCode) {
4288
case 9: $.datepicker._hideDatepicker();
4290
break; // hide on tab out
4291
case 13: sel = $("td." + $.datepicker._dayOverClass + ":not(." +
4292
$.datepicker._currentClass + ")", inst.dpDiv);
4294
$.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);
4297
onSelect = $.datepicker._get(inst, "onSelect");
4299
dateStr = $.datepicker._formatDate(inst);
4301
// trigger custom callback
4302
onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);
4304
$.datepicker._hideDatepicker();
4307
return false; // don't submit the form
4308
case 27: $.datepicker._hideDatepicker();
4309
break; // hide on escape
4310
case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
4311
-$.datepicker._get(inst, "stepBigMonths") :
4312
-$.datepicker._get(inst, "stepMonths")), "M");
4313
break; // previous month/year on page up/+ ctrl
4314
case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
4315
+$.datepicker._get(inst, "stepBigMonths") :
4316
+$.datepicker._get(inst, "stepMonths")), "M");
4317
break; // next month/year on page down/+ ctrl
4318
case 35: if (event.ctrlKey || event.metaKey) {
4319
$.datepicker._clearDate(event.target);
4321
handled = event.ctrlKey || event.metaKey;
4322
break; // clear on ctrl or command +end
4323
case 36: if (event.ctrlKey || event.metaKey) {
4324
$.datepicker._gotoToday(event.target);
4326
handled = event.ctrlKey || event.metaKey;
4327
break; // current on ctrl or command +home
4328
case 37: if (event.ctrlKey || event.metaKey) {
4329
$.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), "D");
4331
handled = event.ctrlKey || event.metaKey;
4332
// -1 day on ctrl or command +left
4333
if (event.originalEvent.altKey) {
4334
$.datepicker._adjustDate(event.target, (event.ctrlKey ?
4335
-$.datepicker._get(inst, "stepBigMonths") :
4336
-$.datepicker._get(inst, "stepMonths")), "M");
4338
// next month/year on alt +left on Mac
4340
case 38: if (event.ctrlKey || event.metaKey) {
4341
$.datepicker._adjustDate(event.target, -7, "D");
4343
handled = event.ctrlKey || event.metaKey;
4344
break; // -1 week on ctrl or command +up
4345
case 39: if (event.ctrlKey || event.metaKey) {
4346
$.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), "D");
4348
handled = event.ctrlKey || event.metaKey;
4349
// +1 day on ctrl or command +right
4350
if (event.originalEvent.altKey) {
4351
$.datepicker._adjustDate(event.target, (event.ctrlKey ?
4352
+$.datepicker._get(inst, "stepBigMonths") :
4353
+$.datepicker._get(inst, "stepMonths")), "M");
4355
// next month/year on alt +right
4357
case 40: if (event.ctrlKey || event.metaKey) {
4358
$.datepicker._adjustDate(event.target, +7, "D");
4360
handled = event.ctrlKey || event.metaKey;
4361
break; // +1 week on ctrl or command +down
4362
default: handled = false;
4364
} else if (event.keyCode === 36 && event.ctrlKey) { // display the date picker on ctrl+home
4365
$.datepicker._showDatepicker(this);
4371
event.preventDefault();
4372
event.stopPropagation();
4376
/* Filter entered characters - based on date format. */
4377
_doKeyPress: function(event) {
4379
inst = $.datepicker._getInst(event.target);
4381
if ($.datepicker._get(inst, "constrainInput")) {
4382
chars = $.datepicker._possibleChars($.datepicker._get(inst, "dateFormat"));
4383
chr = String.fromCharCode(event.charCode == null ? event.keyCode : event.charCode);
4384
return event.ctrlKey || event.metaKey || (chr < " " || !chars || chars.indexOf(chr) > -1);
4388
/* Synchronise manual entry and field/alternate field. */
4389
_doKeyUp: function(event) {
4391
inst = $.datepicker._getInst(event.target);
4393
if (inst.input.val() !== inst.lastVal) {
4395
date = $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"),
4396
(inst.input ? inst.input.val() : null),
4397
$.datepicker._getFormatConfig(inst));
4399
if (date) { // only if valid
4400
$.datepicker._setDateFromField(inst);
4401
$.datepicker._updateAlternate(inst);
4402
$.datepicker._updateDatepicker(inst);
4411
/* Pop-up the date picker for a given input field.
4412
* If false returned from beforeShow event handler do not show.
4413
* @param input element - the input field attached to the date picker or
4414
* event - if triggered by focus
4416
_showDatepicker: function(input) {
4417
input = input.target || input;
4418
if (input.nodeName.toLowerCase() !== "input") { // find from button/image trigger
4419
input = $("input", input.parentNode)[0];
4422
if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput === input) { // already here
4426
var inst, beforeShow, beforeShowSettings, isFixed,
4427
offset, showAnim, duration;
4429
inst = $.datepicker._getInst(input);
4430
if ($.datepicker._curInst && $.datepicker._curInst !== inst) {
4431
$.datepicker._curInst.dpDiv.stop(true, true);
4432
if ( inst && $.datepicker._datepickerShowing ) {
4433
$.datepicker._hideDatepicker( $.datepicker._curInst.input[0] );
4437
beforeShow = $.datepicker._get(inst, "beforeShow");
4438
beforeShowSettings = beforeShow ? beforeShow.apply(input, [input, inst]) : {};
4439
if(beforeShowSettings === false){
4442
datepicker_extendRemove(inst.settings, beforeShowSettings);
4444
inst.lastVal = null;
4445
$.datepicker._lastInput = input;
4446
$.datepicker._setDateFromField(inst);
4448
if ($.datepicker._inDialog) { // hide cursor
4451
if (!$.datepicker._pos) { // position below input
4452
$.datepicker._pos = $.datepicker._findPos(input);
4453
$.datepicker._pos[1] += input.offsetHeight; // add the height
4457
$(input).parents().each(function() {
4458
isFixed |= $(this).css("position") === "fixed";
4462
offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]};
4463
$.datepicker._pos = null;
4464
//to avoid flashes on Firefox
4466
// determine sizing offscreen
4467
inst.dpDiv.css({position: "absolute", display: "block", top: "-1000px"});
4468
$.datepicker._updateDatepicker(inst);
4469
// fix width for dynamic number of date pickers
4470
// and adjust position before showing
4471
offset = $.datepicker._checkOffset(inst, offset, isFixed);
4472
inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ?
4473
"static" : (isFixed ? "fixed" : "absolute")), display: "none",
4474
left: offset.left + "px", top: offset.top + "px"});
4477
showAnim = $.datepicker._get(inst, "showAnim");
4478
duration = $.datepicker._get(inst, "duration");
4479
inst.dpDiv.css( "z-index", datepicker_getZindex( $( input ) ) + 1 );
4480
$.datepicker._datepickerShowing = true;
4482
if ( $.effects && $.effects.effect[ showAnim ] ) {
4483
inst.dpDiv.show(showAnim, $.datepicker._get(inst, "showOptions"), duration);
4485
inst.dpDiv[showAnim || "show"](showAnim ? duration : null);
4488
if ( $.datepicker._shouldFocusInput( inst ) ) {
4492
$.datepicker._curInst = inst;
4496
/* Generate the date picker content. */
4497
_updateDatepicker: function(inst) {
4498
this.maxRows = 4; //Reset the max number of rows being displayed (see #7043)
4499
datepicker_instActive = inst; // for delegate hover events
4500
inst.dpDiv.empty().append(this._generateHTML(inst));
4501
this._attachHandlers(inst);
4502
inst.dpDiv.find("." + this._dayOverClass + " a");
4505
numMonths = this._getNumberOfMonths(inst),
4506
cols = numMonths[1],
4509
inst.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width("");
4511
inst.dpDiv.addClass("ui-datepicker-multi-" + cols).css("width", (width * cols) + "em");
4513
inst.dpDiv[(numMonths[0] !== 1 || numMonths[1] !== 1 ? "add" : "remove") +
4514
"Class"]("ui-datepicker-multi");
4515
inst.dpDiv[(this._get(inst, "isRTL") ? "add" : "remove") +
4516
"Class"]("ui-datepicker-rtl");
4518
if (inst === $.datepicker._curInst && $.datepicker._datepickerShowing && $.datepicker._shouldFocusInput( inst ) ) {
4522
// deffered render of the years select (to avoid flashes on Firefox)
4523
if( inst.yearshtml ){
4524
origyearshtml = inst.yearshtml;
4525
setTimeout(function(){
4526
//assure that inst.yearshtml didn't change.
4527
if( origyearshtml === inst.yearshtml && inst.yearshtml ){
4528
inst.dpDiv.find("select.ui-datepicker-year:first").replaceWith(inst.yearshtml);
4530
origyearshtml = inst.yearshtml = null;
4535
// #6694 - don't focus the input if it's already focused
4536
// this breaks the change event in IE
4537
// Support: IE and jQuery <1.9
4538
_shouldFocusInput: function( inst ) {
4539
return inst.input && inst.input.is( ":visible" ) && !inst.input.is( ":disabled" ) && !inst.input.is( ":focus" );
4542
/* Check positioning to remain on screen. */
4543
_checkOffset: function(inst, offset, isFixed) {
4544
var dpWidth = inst.dpDiv.outerWidth(),
4545
dpHeight = inst.dpDiv.outerHeight(),
4546
inputWidth = inst.input ? inst.input.outerWidth() : 0,
4547
inputHeight = inst.input ? inst.input.outerHeight() : 0,
4548
viewWidth = document.documentElement.clientWidth + (isFixed ? 0 : $(document).scrollLeft()),
4549
viewHeight = document.documentElement.clientHeight + (isFixed ? 0 : $(document).scrollTop());
4551
offset.left -= (this._get(inst, "isRTL") ? (dpWidth - inputWidth) : 0);
4552
offset.left -= (isFixed && offset.left === inst.input.offset().left) ? $(document).scrollLeft() : 0;
4553
offset.top -= (isFixed && offset.top === (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;
4555
// now check if datepicker is showing outside window viewport - move to a better place if so.
4556
offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?
4557
Math.abs(offset.left + dpWidth - viewWidth) : 0);
4558
offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?
4559
Math.abs(dpHeight + inputHeight) : 0);
4564
/* Find an object's position on the screen. */
4565
_findPos: function(obj) {
4567
inst = this._getInst(obj),
4568
isRTL = this._get(inst, "isRTL");
4570
while (obj && (obj.type === "hidden" || obj.nodeType !== 1 || $.expr.filters.hidden(obj))) {
4571
obj = obj[isRTL ? "previousSibling" : "nextSibling"];
4574
position = $(obj).offset();
4575
return [position.left, position.top];
4578
/* Hide the date picker from view.
4579
* @param input element - the input field attached to the date picker
4581
_hideDatepicker: function(input) {
4582
var showAnim, duration, postProcess, onClose,
4583
inst = this._curInst;
4585
if (!inst || (input && inst !== $.data(input, "datepicker"))) {
4589
if (this._datepickerShowing) {
4590
showAnim = this._get(inst, "showAnim");
4591
duration = this._get(inst, "duration");
4592
postProcess = function() {
4593
$.datepicker._tidyDialog(inst);
4596
// DEPRECATED: after BC for 1.8.x $.effects[ showAnim ] is not needed
4597
if ( $.effects && ( $.effects.effect[ showAnim ] || $.effects[ showAnim ] ) ) {
4598
inst.dpDiv.hide(showAnim, $.datepicker._get(inst, "showOptions"), duration, postProcess);
4600
inst.dpDiv[(showAnim === "slideDown" ? "slideUp" :
4601
(showAnim === "fadeIn" ? "fadeOut" : "hide"))]((showAnim ? duration : null), postProcess);
4607
this._datepickerShowing = false;
4609
onClose = this._get(inst, "onClose");
4611
onClose.apply((inst.input ? inst.input[0] : null), [(inst.input ? inst.input.val() : ""), inst]);
4614
this._lastInput = null;
4615
if (this._inDialog) {
4616
this._dialogInput.css({ position: "absolute", left: "0", top: "-100px" });
4619
$("body").append(this.dpDiv);
4622
this._inDialog = false;
4626
/* Tidy up after a dialog display. */
4627
_tidyDialog: function(inst) {
4628
inst.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar");
4631
/* Close date picker if clicked elsewhere. */
4632
_checkExternalClick: function(event) {
4633
if (!$.datepicker._curInst) {
4637
var $target = $(event.target),
4638
inst = $.datepicker._getInst($target[0]);
4640
if ( ( ( $target[0].id !== $.datepicker._mainDivId &&
4641
$target.parents("#" + $.datepicker._mainDivId).length === 0 &&
4642
!$target.hasClass($.datepicker.markerClassName) &&
4643
!$target.closest("." + $.datepicker._triggerClass).length &&
4644
$.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI) ) ) ||
4645
( $target.hasClass($.datepicker.markerClassName) && $.datepicker._curInst !== inst ) ) {
4646
$.datepicker._hideDatepicker();
4650
/* Adjust one of the date sub-fields. */
4651
_adjustDate: function(id, offset, period) {
4653
inst = this._getInst(target[0]);
4655
if (this._isDisabledDatepicker(target[0])) {
4658
this._adjustInstDate(inst, offset +
4659
(period === "M" ? this._get(inst, "showCurrentAtPos") : 0), // undo positioning
4661
this._updateDatepicker(inst);
4664
/* Action for current link. */
4665
_gotoToday: function(id) {
4668
inst = this._getInst(target[0]);
4670
if (this._get(inst, "gotoCurrent") && inst.currentDay) {
4671
inst.selectedDay = inst.currentDay;
4672
inst.drawMonth = inst.selectedMonth = inst.currentMonth;
4673
inst.drawYear = inst.selectedYear = inst.currentYear;
4676
inst.selectedDay = date.getDate();
4677
inst.drawMonth = inst.selectedMonth = date.getMonth();
4678
inst.drawYear = inst.selectedYear = date.getFullYear();
4680
this._notifyChange(inst);
4681
this._adjustDate(target);
4684
/* Action for selecting a new month/year. */
4685
_selectMonthYear: function(id, select, period) {
4687
inst = this._getInst(target[0]);
4689
inst["selected" + (period === "M" ? "Month" : "Year")] =
4690
inst["draw" + (period === "M" ? "Month" : "Year")] =
4691
parseInt(select.options[select.selectedIndex].value,10);
4693
this._notifyChange(inst);
4694
this._adjustDate(target);
4697
/* Action for selecting a day. */
4698
_selectDay: function(id, month, year, td) {
4702
if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) {
4706
inst = this._getInst(target[0]);
4707
inst.selectedDay = inst.currentDay = $("a", td).html();
4708
inst.selectedMonth = inst.currentMonth = month;
4709
inst.selectedYear = inst.currentYear = year;
4710
this._selectDate(id, this._formatDate(inst,
4711
inst.currentDay, inst.currentMonth, inst.currentYear));
4714
/* Erase the input field and hide the date picker. */
4715
_clearDate: function(id) {
4717
this._selectDate(target, "");
4720
/* Update the input field with the selected date. */
4721
_selectDate: function(id, dateStr) {
4724
inst = this._getInst(target[0]);
4726
dateStr = (dateStr != null ? dateStr : this._formatDate(inst));
4728
inst.input.val(dateStr);
4730
this._updateAlternate(inst);
4732
onSelect = this._get(inst, "onSelect");
4734
onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); // trigger custom callback
4735
} else if (inst.input) {
4736
inst.input.trigger("change"); // fire the change event
4740
this._updateDatepicker(inst);
4742
this._hideDatepicker();
4743
this._lastInput = inst.input[0];
4744
if (typeof(inst.input[0]) !== "object") {
4745
inst.input.focus(); // restore focus
4747
this._lastInput = null;
4751
/* Update any alternate field to synchronise with the main field. */
4752
_updateAlternate: function(inst) {
4753
var altFormat, date, dateStr,
4754
altField = this._get(inst, "altField");
4756
if (altField) { // update alternate field too
4757
altFormat = this._get(inst, "altFormat") || this._get(inst, "dateFormat");
4758
date = this._getDate(inst);
4759
dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst));
4760
$(altField).each(function() { $(this).val(dateStr); });
4764
/* Set as beforeShowDay function to prevent selection of weekends.
4765
* @param date Date - the date to customise
4766
* @return [boolean, string] - is this date selectable?, what is its CSS class?
4768
noWeekends: function(date) {
4769
var day = date.getDay();
4770
return [(day > 0 && day < 6), ""];
4773
/* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
4774
* @param date Date - the date to get the week for
4775
* @return number - the number of the week within the year that contains this date
4777
iso8601Week: function(date) {
4779
checkDate = new Date(date.getTime());
4781
// Find Thursday of this week starting on Monday
4782
checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7));
4784
time = checkDate.getTime();
4785
checkDate.setMonth(0); // Compare with Jan 1
4786
checkDate.setDate(1);
4787
return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
4790
/* Parse a string value into a date object.
4791
* See formatDate below for the possible formats.
4793
* @param format string - the expected format of the date
4794
* @param value string - the date in the above format
4795
* @param settings Object - attributes include:
4796
* shortYearCutoff number - the cutoff year for determining the century (optional)
4797
* dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
4798
* dayNames string[7] - names of the days from Sunday (optional)
4799
* monthNamesShort string[12] - abbreviated names of the months (optional)
4800
* monthNames string[12] - names of the months (optional)
4801
* @return Date - the extracted date value or null if value is blank
4803
parseDate: function (format, value, settings) {
4804
if (format == null || value == null) {
4805
throw "Invalid arguments";
4808
value = (typeof value === "object" ? value.toString() : value + "");
4813
var iFormat, dim, extra,
4815
shortYearCutoffTemp = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff,
4816
shortYearCutoff = (typeof shortYearCutoffTemp !== "string" ? shortYearCutoffTemp :
4817
new Date().getFullYear() % 100 + parseInt(shortYearCutoffTemp, 10)),
4818
dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort,
4819
dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames,
4820
monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort,
4821
monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames,
4828
// Check whether a format character is doubled
4829
lookAhead = function(match) {
4830
var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match);
4836
// Extract a number from the string value
4837
getNumber = function(match) {
4838
var isDoubled = lookAhead(match),
4839
size = (match === "@" ? 14 : (match === "!" ? 20 :
4840
(match === "y" && isDoubled ? 4 : (match === "o" ? 3 : 2)))),
4841
digits = new RegExp("^\\d{1," + size + "}"),
4842
num = value.substring(iValue).match(digits);
4844
throw "Missing number at position " + iValue;
4846
iValue += num[0].length;
4847
return parseInt(num[0], 10);
4849
// Extract a name from the string value and convert to an index
4850
getName = function(match, shortNames, longNames) {
4852
names = $.map(lookAhead(match) ? longNames : shortNames, function (v, k) {
4854
}).sort(function (a, b) {
4855
return -(a[1].length - b[1].length);
4858
$.each(names, function (i, pair) {
4860
if (value.substr(iValue, name.length).toLowerCase() === name.toLowerCase()) {
4862
iValue += name.length;
4869
throw "Unknown name at position " + iValue;
4872
// Confirm that a literal character matches the string value
4873
checkLiteral = function() {
4874
if (value.charAt(iValue) !== format.charAt(iFormat)) {
4875
throw "Unexpected literal at position " + iValue;
4880
for (iFormat = 0; iFormat < format.length; iFormat++) {
4882
if (format.charAt(iFormat) === "'" && !lookAhead("'")) {
4888
switch (format.charAt(iFormat)) {
4890
day = getNumber("d");
4893
getName("D", dayNamesShort, dayNames);
4896
doy = getNumber("o");
4899
month = getNumber("m");
4902
month = getName("M", monthNamesShort, monthNames);
4905
year = getNumber("y");
4908
date = new Date(getNumber("@"));
4909
year = date.getFullYear();
4910
month = date.getMonth() + 1;
4911
day = date.getDate();
4914
date = new Date((getNumber("!") - this._ticksTo1970) / 10000);
4915
year = date.getFullYear();
4916
month = date.getMonth() + 1;
4917
day = date.getDate();
4920
if (lookAhead("'")){
4932
if (iValue < value.length){
4933
extra = value.substr(iValue);
4934
if (!/^\s+/.test(extra)) {
4935
throw "Extra/unparsed characters found in date: " + extra;
4940
year = new Date().getFullYear();
4941
} else if (year < 100) {
4942
year += new Date().getFullYear() - new Date().getFullYear() % 100 +
4943
(year <= shortYearCutoff ? 0 : -100);
4950
dim = this._getDaysInMonth(year, month - 1);
4959
date = this._daylightSavingAdjust(new Date(year, month - 1, day));
4960
if (date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day) {
4961
throw "Invalid date"; // E.g. 31/02/00
4966
/* Standard date formats. */
4967
ATOM: "yy-mm-dd", // RFC 3339 (ISO 8601)
4968
COOKIE: "D, dd M yy",
4969
ISO_8601: "yy-mm-dd",
4970
RFC_822: "D, d M y",
4971
RFC_850: "DD, dd-M-y",
4972
RFC_1036: "D, d M y",
4973
RFC_1123: "D, d M yy",
4974
RFC_2822: "D, d M yy",
4975
RSS: "D, d M y", // RFC 822
4978
W3C: "yy-mm-dd", // ISO 8601
4980
_ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) +
4981
Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000),
4983
/* Format a date object into a string value.
4984
* The format can be combinations of the following:
4985
* d - day of month (no leading zero)
4986
* dd - day of month (two digit)
4987
* o - day of year (no leading zeros)
4988
* oo - day of year (three digit)
4989
* D - day name short
4990
* DD - day name long
4991
* m - month of year (no leading zero)
4992
* mm - month of year (two digit)
4993
* M - month name short
4994
* MM - month name long
4995
* y - year (two digit)
4996
* yy - year (four digit)
4997
* @ - Unix timestamp (ms since 01/01/1970)
4998
* ! - Windows ticks (100ns since 01/01/0001)
4999
* "..." - literal text
5002
* @param format string - the desired format of the date
5003
* @param date Date - the date value to format
5004
* @param settings Object - attributes include:
5005
* dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
5006
* dayNames string[7] - names of the days from Sunday (optional)
5007
* monthNamesShort string[12] - abbreviated names of the months (optional)
5008
* monthNames string[12] - names of the months (optional)
5009
* @return string - the date in the above format
5011
formatDate: function (format, date, settings) {
5017
dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort,
5018
dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames,
5019
monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort,
5020
monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames,
5021
// Check whether a format character is doubled
5022
lookAhead = function(match) {
5023
var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match);
5029
// Format a number, with leading zero if necessary
5030
formatNumber = function(match, value, len) {
5031
var num = "" + value;
5032
if (lookAhead(match)) {
5033
while (num.length < len) {
5039
// Format a name, short or long as requested
5040
formatName = function(match, value, shortNames, longNames) {
5041
return (lookAhead(match) ? longNames[value] : shortNames[value]);
5047
for (iFormat = 0; iFormat < format.length; iFormat++) {
5049
if (format.charAt(iFormat) === "'" && !lookAhead("'")) {
5052
output += format.charAt(iFormat);
5055
switch (format.charAt(iFormat)) {
5057
output += formatNumber("d", date.getDate(), 2);
5060
output += formatName("D", date.getDay(), dayNamesShort, dayNames);
5063
output += formatNumber("o",
5064
Math.round((new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000), 3);
5067
output += formatNumber("m", date.getMonth() + 1, 2);
5070
output += formatName("M", date.getMonth(), monthNamesShort, monthNames);
5073
output += (lookAhead("y") ? date.getFullYear() :
5074
(date.getYear() % 100 < 10 ? "0" : "") + date.getYear() % 100);
5077
output += date.getTime();
5080
output += date.getTime() * 10000 + this._ticksTo1970;
5083
if (lookAhead("'")) {
5090
output += format.charAt(iFormat);
5098
/* Extract all possible characters from the date format. */
5099
_possibleChars: function (format) {
5103
// Check whether a format character is doubled
5104
lookAhead = function(match) {
5105
var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match);
5112
for (iFormat = 0; iFormat < format.length; iFormat++) {
5114
if (format.charAt(iFormat) === "'" && !lookAhead("'")) {
5117
chars += format.charAt(iFormat);
5120
switch (format.charAt(iFormat)) {
5121
case "d": case "m": case "y": case "@":
5122
chars += "0123456789";
5125
return null; // Accept anything
5127
if (lookAhead("'")) {
5134
chars += format.charAt(iFormat);
5141
/* Get a setting value, defaulting if necessary. */
5142
_get: function(inst, name) {
5143
return inst.settings[name] !== undefined ?
5144
inst.settings[name] : this._defaults[name];
5147
/* Parse existing date and initialise date picker. */
5148
_setDateFromField: function(inst, noDefault) {
5149
if (inst.input.val() === inst.lastVal) {
5153
var dateFormat = this._get(inst, "dateFormat"),
5154
dates = inst.lastVal = inst.input ? inst.input.val() : null,
5155
defaultDate = this._getDefaultDate(inst),
5157
settings = this._getFormatConfig(inst);
5160
date = this.parseDate(dateFormat, dates, settings) || defaultDate;
5162
dates = (noDefault ? "" : dates);
5164
inst.selectedDay = date.getDate();
5165
inst.drawMonth = inst.selectedMonth = date.getMonth();
5166
inst.drawYear = inst.selectedYear = date.getFullYear();
5167
inst.currentDay = (dates ? date.getDate() : 0);
5168
inst.currentMonth = (dates ? date.getMonth() : 0);
5169
inst.currentYear = (dates ? date.getFullYear() : 0);
5170
this._adjustInstDate(inst);
5173
/* Retrieve the default date shown on opening. */
5174
_getDefaultDate: function(inst) {
5175
return this._restrictMinMax(inst,
5176
this._determineDate(inst, this._get(inst, "defaultDate"), new Date()));
5179
/* A date may be specified as an exact value or a relative one. */
5180
_determineDate: function(inst, date, defaultDate) {
5181
var offsetNumeric = function(offset) {
5182
var date = new Date();
5183
date.setDate(date.getDate() + offset);
5186
offsetString = function(offset) {
5188
return $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"),
5189
offset, $.datepicker._getFormatConfig(inst));
5195
var date = (offset.toLowerCase().match(/^c/) ?
5196
$.datepicker._getDate(inst) : null) || new Date(),
5197
year = date.getFullYear(),
5198
month = date.getMonth(),
5199
day = date.getDate(),
5200
pattern = /([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,
5201
matches = pattern.exec(offset);
5204
switch (matches[2] || "d") {
5205
case "d" : case "D" :
5206
day += parseInt(matches[1],10); break;
5207
case "w" : case "W" :
5208
day += parseInt(matches[1],10) * 7; break;
5209
case "m" : case "M" :
5210
month += parseInt(matches[1],10);
5211
day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
5213
case "y": case "Y" :
5214
year += parseInt(matches[1],10);
5215
day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
5218
matches = pattern.exec(offset);
5220
return new Date(year, month, day);
5222
newDate = (date == null || date === "" ? defaultDate : (typeof date === "string" ? offsetString(date) :
5223
(typeof date === "number" ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : new Date(date.getTime()))));
5225
newDate = (newDate && newDate.toString() === "Invalid Date" ? defaultDate : newDate);
5227
newDate.setHours(0);
5228
newDate.setMinutes(0);
5229
newDate.setSeconds(0);
5230
newDate.setMilliseconds(0);
5232
return this._daylightSavingAdjust(newDate);
5235
/* Handle switch to/from daylight saving.
5236
* Hours may be non-zero on daylight saving cut-over:
5237
* > 12 when midnight changeover, but then cannot generate
5238
* midnight datetime, so jump to 1AM, otherwise reset.
5239
* @param date (Date) the date to check
5240
* @return (Date) the corrected date
5242
_daylightSavingAdjust: function(date) {
5246
date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
5250
/* Set the date(s) directly. */
5251
_setDate: function(inst, date, noChange) {
5253
origMonth = inst.selectedMonth,
5254
origYear = inst.selectedYear,
5255
newDate = this._restrictMinMax(inst, this._determineDate(inst, date, new Date()));
5257
inst.selectedDay = inst.currentDay = newDate.getDate();
5258
inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth();
5259
inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear();
5260
if ((origMonth !== inst.selectedMonth || origYear !== inst.selectedYear) && !noChange) {
5261
this._notifyChange(inst);
5263
this._adjustInstDate(inst);
5265
inst.input.val(clear ? "" : this._formatDate(inst));
5269
/* Retrieve the date(s) directly. */
5270
_getDate: function(inst) {
5271
var startDate = (!inst.currentYear || (inst.input && inst.input.val() === "") ? null :
5272
this._daylightSavingAdjust(new Date(
5273
inst.currentYear, inst.currentMonth, inst.currentDay)));
5277
/* Attach the onxxx handlers. These are declared statically so
5278
* they work with static code transformers like Caja.
5280
_attachHandlers: function(inst) {
5281
var stepMonths = this._get(inst, "stepMonths"),
5282
id = "#" + inst.id.replace( /\\\\/g, "\\" );
5283
inst.dpDiv.find("[data-handler]").map(function () {
5286
$.datepicker._adjustDate(id, -stepMonths, "M");
5289
$.datepicker._adjustDate(id, +stepMonths, "M");
5292
$.datepicker._hideDatepicker();
5294
today: function () {
5295
$.datepicker._gotoToday(id);
5297
selectDay: function () {
5298
$.datepicker._selectDay(id, +this.getAttribute("data-month"), +this.getAttribute("data-year"), this);
5301
selectMonth: function () {
5302
$.datepicker._selectMonthYear(id, this, "M");
5305
selectYear: function () {
5306
$.datepicker._selectMonthYear(id, this, "Y");
5310
$(this).bind(this.getAttribute("data-event"), handler[this.getAttribute("data-handler")]);
5314
/* Generate the HTML for the current state of the date picker. */
5315
_generateHTML: function(inst) {
5316
var maxDraw, prevText, prev, nextText, next, currentText, gotoDate,
5317
controls, buttonPanel, firstDay, showWeek, dayNames, dayNamesMin,
5318
monthNames, monthNamesShort, beforeShowDay, showOtherMonths,
5319
selectOtherMonths, defaultDate, html, dow, row, group, col, selectedDate,
5320
cornerClass, calender, thead, day, daysInMonth, leadDays, curRows, numRows,
5321
printDate, dRow, tbody, daySettings, otherMonth, unselectable,
5322
tempDate = new Date(),
5323
today = this._daylightSavingAdjust(
5324
new Date(tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate())), // clear time
5325
isRTL = this._get(inst, "isRTL"),
5326
showButtonPanel = this._get(inst, "showButtonPanel"),
5327
hideIfNoPrevNext = this._get(inst, "hideIfNoPrevNext"),
5328
navigationAsDateFormat = this._get(inst, "navigationAsDateFormat"),
5329
numMonths = this._getNumberOfMonths(inst),
5330
showCurrentAtPos = this._get(inst, "showCurrentAtPos"),
5331
stepMonths = this._get(inst, "stepMonths"),
5332
isMultiMonth = (numMonths[0] !== 1 || numMonths[1] !== 1),
5333
currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) :
5334
new Date(inst.currentYear, inst.currentMonth, inst.currentDay))),
5335
minDate = this._getMinMaxDate(inst, "min"),
5336
maxDate = this._getMinMaxDate(inst, "max"),
5337
drawMonth = inst.drawMonth - showCurrentAtPos,
5338
drawYear = inst.drawYear;
5340
if (drawMonth < 0) {
5345
maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),
5346
maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate()));
5347
maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);
5348
while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {
5350
if (drawMonth < 0) {
5356
inst.drawMonth = drawMonth;
5357
inst.drawYear = drawYear;
5359
prevText = this._get(inst, "prevText");
5360
prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText,
5361
this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),
5362
this._getFormatConfig(inst)));
5364
prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?
5365
"<a class='ui-datepicker-prev ui-corner-all' data-handler='prev' data-event='click'" +
5366
" title='" + prevText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "e" : "w") + "'>" + prevText + "</span></a>" :
5367
(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>"));
5369
nextText = this._get(inst, "nextText");
5370
nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText,
5371
this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),
5372
this._getFormatConfig(inst)));
5374
next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?
5375
"<a class='ui-datepicker-next ui-corner-all' data-handler='next' data-event='click'" +
5376
" title='" + nextText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "w" : "e") + "'>" + nextText + "</span></a>" :
5377
(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>"));
5379
currentText = this._get(inst, "currentText");
5380
gotoDate = (this._get(inst, "gotoCurrent") && inst.currentDay ? currentDate : today);
5381
currentText = (!navigationAsDateFormat ? currentText :
5382
this.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));
5384
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'>" +
5385
this._get(inst, "closeText") + "</button>" : "");
5387
buttonPanel = (showButtonPanel) ? "<div class='ui-datepicker-buttonpane ui-widget-content'>" + (isRTL ? controls : "") +
5388
(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'" +
5389
">" + currentText + "</button>" : "") + (isRTL ? "" : controls) + "</div>" : "";
5391
firstDay = parseInt(this._get(inst, "firstDay"),10);
5392
firstDay = (isNaN(firstDay) ? 0 : firstDay);
5394
showWeek = this._get(inst, "showWeek");
5395
dayNames = this._get(inst, "dayNames");
5396
dayNamesMin = this._get(inst, "dayNamesMin");
5397
monthNames = this._get(inst, "monthNames");
5398
monthNamesShort = this._get(inst, "monthNamesShort");
5399
beforeShowDay = this._get(inst, "beforeShowDay");
5400
showOtherMonths = this._get(inst, "showOtherMonths");
5401
selectOtherMonths = this._get(inst, "selectOtherMonths");
5402
defaultDate = this._getDefaultDate(inst);
5405
for (row = 0; row < numMonths[0]; row++) {
5408
for (col = 0; col < numMonths[1]; col++) {
5409
selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay));
5410
cornerClass = " ui-corner-all";
5413
calender += "<div class='ui-datepicker-group";
5414
if (numMonths[1] > 1) {
5416
case 0: calender += " ui-datepicker-group-first";
5417
cornerClass = " ui-corner-" + (isRTL ? "right" : "left"); break;
5418
case numMonths[1]-1: calender += " ui-datepicker-group-last";
5419
cornerClass = " ui-corner-" + (isRTL ? "left" : "right"); break;
5420
default: calender += " ui-datepicker-group-middle"; cornerClass = ""; break;
5425
calender += "<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix" + cornerClass + "'>" +
5426
(/all|left/.test(cornerClass) && row === 0 ? (isRTL ? next : prev) : "") +
5427
(/all|right/.test(cornerClass) && row === 0 ? (isRTL ? prev : next) : "") +
5428
this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,
5429
row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers
5430
"</div><table class='ui-datepicker-calendar'><thead>" +
5432
thead = (showWeek ? "<th class='ui-datepicker-week-col'>" + this._get(inst, "weekHeader") + "</th>" : "");
5433
for (dow = 0; dow < 7; dow++) { // days of the week
5434
day = (dow + firstDay) % 7;
5435
thead += "<th scope='col'" + ((dow + firstDay + 6) % 7 >= 5 ? " class='ui-datepicker-week-end'" : "") + ">" +
5436
"<span title='" + dayNames[day] + "'>" + dayNamesMin[day] + "</span></th>";
5438
calender += thead + "</tr></thead><tbody>";
5439
daysInMonth = this._getDaysInMonth(drawYear, drawMonth);
5440
if (drawYear === inst.selectedYear && drawMonth === inst.selectedMonth) {
5441
inst.selectedDay = Math.min(inst.selectedDay, daysInMonth);
5443
leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;
5444
curRows = Math.ceil((leadDays + daysInMonth) / 7); // calculate the number of rows to generate
5445
numRows = (isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows); //If multiple months, use the higher number of rows (see #7043)
5446
this.maxRows = numRows;
5447
printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
5448
for (dRow = 0; dRow < numRows; dRow++) { // create date picker rows
5450
tbody = (!showWeek ? "" : "<td class='ui-datepicker-week-col'>" +
5451
this._get(inst, "calculateWeek")(printDate) + "</td>");
5452
for (dow = 0; dow < 7; dow++) { // create date picker days
5453
daySettings = (beforeShowDay ?
5454
beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, ""]);
5455
otherMonth = (printDate.getMonth() !== drawMonth);
5456
unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] ||
5457
(minDate && printDate < minDate) || (maxDate && printDate > maxDate);
5458
tbody += "<td class='" +
5459
((dow + firstDay + 6) % 7 >= 5 ? " ui-datepicker-week-end" : "") + // highlight weekends
5460
(otherMonth ? " ui-datepicker-other-month" : "") + // highlight days from other months
5461
((printDate.getTime() === selectedDate.getTime() && drawMonth === inst.selectedMonth && inst._keyEvent) || // user pressed key
5462
(defaultDate.getTime() === printDate.getTime() && defaultDate.getTime() === selectedDate.getTime()) ?
5463
// or defaultDate is current printedDate and defaultDate is selectedDate
5464
" " + this._dayOverClass : "") + // highlight selected day
5465
(unselectable ? " " + this._unselectableClass + " ui-state-disabled": "") + // highlight unselectable days
5466
(otherMonth && !showOtherMonths ? "" : " " + daySettings[1] + // highlight custom dates
5467
(printDate.getTime() === currentDate.getTime() ? " " + this._currentClass : "") + // highlight selected day
5468
(printDate.getTime() === today.getTime() ? " ui-datepicker-today" : "")) + "'" + // highlight today (if different)
5469
((!otherMonth || showOtherMonths) && daySettings[2] ? " title='" + daySettings[2].replace(/'/g, "'") + "'" : "") + // cell title
5470
(unselectable ? "" : " data-handler='selectDay' data-event='click' data-month='" + printDate.getMonth() + "' data-year='" + printDate.getFullYear() + "'") + ">" + // actions
5471
(otherMonth && !showOtherMonths ? " " : // display for other months
5472
(unselectable ? "<span class='ui-state-default'>" + printDate.getDate() + "</span>" : "<a class='ui-state-default" +
5473
(printDate.getTime() === today.getTime() ? " ui-state-highlight" : "") +
5474
(printDate.getTime() === currentDate.getTime() ? " ui-state-active" : "") + // highlight selected day
5475
(otherMonth ? " ui-priority-secondary" : "") + // distinguish dates from other months
5476
"' href='#'>" + printDate.getDate() + "</a>")) + "</td>"; // display selectable date
5477
printDate.setDate(printDate.getDate() + 1);
5478
printDate = this._daylightSavingAdjust(printDate);
5480
calender += tbody + "</tr>";
5483
if (drawMonth > 11) {
5487
calender += "</tbody></table>" + (isMultiMonth ? "</div>" +
5488
((numMonths[0] > 0 && col === numMonths[1]-1) ? "<div class='ui-datepicker-row-break'></div>" : "") : "");
5493
html += buttonPanel;
5494
inst._keyEvent = false;
5498
/* Generate the month and year header. */
5499
_generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate,
5500
secondary, monthNames, monthNamesShort) {
5502
var inMinYear, inMaxYear, month, years, thisYear, determineYear, year, endYear,
5503
changeMonth = this._get(inst, "changeMonth"),
5504
changeYear = this._get(inst, "changeYear"),
5505
showMonthAfterYear = this._get(inst, "showMonthAfterYear"),
5506
html = "<div class='ui-datepicker-title'>",
5510
if (secondary || !changeMonth) {
5511
monthHtml += "<span class='ui-datepicker-month'>" + monthNames[drawMonth] + "</span>";
5513
inMinYear = (minDate && minDate.getFullYear() === drawYear);
5514
inMaxYear = (maxDate && maxDate.getFullYear() === drawYear);
5515
monthHtml += "<select class='ui-datepicker-month' data-handler='selectMonth' data-event='change'>";
5516
for ( month = 0; month < 12; month++) {
5517
if ((!inMinYear || month >= minDate.getMonth()) && (!inMaxYear || month <= maxDate.getMonth())) {
5518
monthHtml += "<option value='" + month + "'" +
5519
(month === drawMonth ? " selected='selected'" : "") +
5520
">" + monthNamesShort[month] + "</option>";
5523
monthHtml += "</select>";
5526
if (!showMonthAfterYear) {
5527
html += monthHtml + (secondary || !(changeMonth && changeYear) ? " " : "");
5531
if ( !inst.yearshtml ) {
5532
inst.yearshtml = "";
5533
if (secondary || !changeYear) {
5534
html += "<span class='ui-datepicker-year'>" + drawYear + "</span>";
5536
// determine range of years to display
5537
years = this._get(inst, "yearRange").split(":");
5538
thisYear = new Date().getFullYear();
5539
determineYear = function(value) {
5540
var year = (value.match(/c[+\-].*/) ? drawYear + parseInt(value.substring(1), 10) :
5541
(value.match(/[+\-].*/) ? thisYear + parseInt(value, 10) :
5542
parseInt(value, 10)));
5543
return (isNaN(year) ? thisYear : year);
5545
year = determineYear(years[0]);
5546
endYear = Math.max(year, determineYear(years[1] || ""));
5547
year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
5548
endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
5549
inst.yearshtml += "<select class='ui-datepicker-year' data-handler='selectYear' data-event='change'>";
5550
for (; year <= endYear; year++) {
5551
inst.yearshtml += "<option value='" + year + "'" +
5552
(year === drawYear ? " selected='selected'" : "") +
5553
">" + year + "</option>";
5555
inst.yearshtml += "</select>";
5557
html += inst.yearshtml;
5558
inst.yearshtml = null;
5562
html += this._get(inst, "yearSuffix");
5563
if (showMonthAfterYear) {
5564
html += (secondary || !(changeMonth && changeYear) ? " " : "") + monthHtml;
5566
html += "</div>"; // Close datepicker_header
5570
/* Adjust one of the date sub-fields. */
5571
_adjustInstDate: function(inst, offset, period) {
5572
var year = inst.drawYear + (period === "Y" ? offset : 0),
5573
month = inst.drawMonth + (period === "M" ? offset : 0),
5574
day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) + (period === "D" ? offset : 0),
5575
date = this._restrictMinMax(inst, this._daylightSavingAdjust(new Date(year, month, day)));
5577
inst.selectedDay = date.getDate();
5578
inst.drawMonth = inst.selectedMonth = date.getMonth();
5579
inst.drawYear = inst.selectedYear = date.getFullYear();
5580
if (period === "M" || period === "Y") {
5581
this._notifyChange(inst);
5585
/* Ensure a date is within any min/max bounds. */
5586
_restrictMinMax: function(inst, date) {
5587
var minDate = this._getMinMaxDate(inst, "min"),
5588
maxDate = this._getMinMaxDate(inst, "max"),
5589
newDate = (minDate && date < minDate ? minDate : date);
5590
return (maxDate && newDate > maxDate ? maxDate : newDate);
5593
/* Notify change of month/year. */
5594
_notifyChange: function(inst) {
5595
var onChange = this._get(inst, "onChangeMonthYear");
5597
onChange.apply((inst.input ? inst.input[0] : null),
5598
[inst.selectedYear, inst.selectedMonth + 1, inst]);
5602
/* Determine the number of months to show. */
5603
_getNumberOfMonths: function(inst) {
5604
var numMonths = this._get(inst, "numberOfMonths");
5605
return (numMonths == null ? [1, 1] : (typeof numMonths === "number" ? [1, numMonths] : numMonths));
5608
/* Determine the current maximum date - ensure no time components are set. */
5609
_getMinMaxDate: function(inst, minMax) {
5610
return this._determineDate(inst, this._get(inst, minMax + "Date"), null);
5613
/* Find the number of days in a given month. */
5614
_getDaysInMonth: function(year, month) {
5615
return 32 - this._daylightSavingAdjust(new Date(year, month, 32)).getDate();
5618
/* Find the day of the week of the first of a month. */
5619
_getFirstDayOfMonth: function(year, month) {
5620
return new Date(year, month, 1).getDay();
5623
/* Determines if we should allow a "next/prev" month display change. */
5624
_canAdjustMonth: function(inst, offset, curYear, curMonth) {
5625
var numMonths = this._getNumberOfMonths(inst),
5626
date = this._daylightSavingAdjust(new Date(curYear,
5627
curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1));
5630
date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
5632
return this._isInRange(inst, date);
5635
/* Is the given date in the accepted range? */
5636
_isInRange: function(inst, date) {
5637
var yearSplit, currentYear,
5638
minDate = this._getMinMaxDate(inst, "min"),
5639
maxDate = this._getMinMaxDate(inst, "max"),
5642
years = this._get(inst, "yearRange");
5644
yearSplit = years.split(":");
5645
currentYear = new Date().getFullYear();
5646
minYear = parseInt(yearSplit[0], 10);
5647
maxYear = parseInt(yearSplit[1], 10);
5648
if ( yearSplit[0].match(/[+\-].*/) ) {
5649
minYear += currentYear;
5651
if ( yearSplit[1].match(/[+\-].*/) ) {
5652
maxYear += currentYear;
5656
return ((!minDate || date.getTime() >= minDate.getTime()) &&
5657
(!maxDate || date.getTime() <= maxDate.getTime()) &&
5658
(!minYear || date.getFullYear() >= minYear) &&
5659
(!maxYear || date.getFullYear() <= maxYear));
5662
/* Provide the configuration settings for formatting/parsing. */
5663
_getFormatConfig: function(inst) {
5664
var shortYearCutoff = this._get(inst, "shortYearCutoff");
5665
shortYearCutoff = (typeof shortYearCutoff !== "string" ? shortYearCutoff :
5666
new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
5667
return {shortYearCutoff: shortYearCutoff,
5668
dayNamesShort: this._get(inst, "dayNamesShort"), dayNames: this._get(inst, "dayNames"),
5669
monthNamesShort: this._get(inst, "monthNamesShort"), monthNames: this._get(inst, "monthNames")};
5672
/* Format the given date for display. */
5673
_formatDate: function(inst, day, month, year) {
5675
inst.currentDay = inst.selectedDay;
5676
inst.currentMonth = inst.selectedMonth;
5677
inst.currentYear = inst.selectedYear;
5679
var date = (day ? (typeof day === "object" ? day :
5680
this._daylightSavingAdjust(new Date(year, month, day))) :
5681
this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
5682
return this.formatDate(this._get(inst, "dateFormat"), date, this._getFormatConfig(inst));
5687
* Bind hover events for datepicker elements.
5688
* Done via delegate so the binding only occurs once in the lifetime of the parent div.
5689
* Global datepicker_instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker.
5691
function datepicker_bindHover(dpDiv) {
5692
var selector = "button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";
5693
return dpDiv.delegate(selector, "mouseout", function() {
5694
$(this).removeClass("ui-state-hover");
5695
if (this.className.indexOf("ui-datepicker-prev") !== -1) {
5696
$(this).removeClass("ui-datepicker-prev-hover");
5698
if (this.className.indexOf("ui-datepicker-next") !== -1) {
5699
$(this).removeClass("ui-datepicker-next-hover");
5702
.delegate(selector, "mouseover", function(){
5703
if (!$.datepicker._isDisabledDatepicker( datepicker_instActive.inline ? dpDiv.parent()[0] : datepicker_instActive.input[0])) {
5704
$(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover");
5705
$(this).addClass("ui-state-hover");
5706
if (this.className.indexOf("ui-datepicker-prev") !== -1) {
5707
$(this).addClass("ui-datepicker-prev-hover");
5709
if (this.className.indexOf("ui-datepicker-next") !== -1) {
5710
$(this).addClass("ui-datepicker-next-hover");
5716
/* jQuery extend now ignores nulls! */
5717
function datepicker_extendRemove(target, props) {
5718
$.extend(target, props);
5719
for (var name in props) {
5720
if (props[name] == null) {
5721
target[name] = props[name];
5727
/* Invoke the datepicker functionality.
5728
@param options string - a command, optionally followed by additional parameters or
5729
Object - settings for attaching new datepicker functionality
5730
@return jQuery object */
5731
$.fn.datepicker = function(options){
5733
/* Verify an empty collection wasn't passed - Fixes #6976 */
5734
if ( !this.length ) {
5738
/* Initialise the date picker. */
5739
if (!$.datepicker.initialized) {
5740
$(document).mousedown($.datepicker._checkExternalClick);
5741
$.datepicker.initialized = true;
5744
/* Append datepicker main container to body if not exist. */
5745
if ($("#"+$.datepicker._mainDivId).length === 0) {
5746
$("body").append($.datepicker.dpDiv);
5749
var otherArgs = Array.prototype.slice.call(arguments, 1);
5750
if (typeof options === "string" && (options === "isDisabled" || options === "getDate" || options === "widget")) {
5751
return $.datepicker["_" + options + "Datepicker"].
5752
apply($.datepicker, [this[0]].concat(otherArgs));
5754
if (options === "option" && arguments.length === 2 && typeof arguments[1] === "string") {
5755
return $.datepicker["_" + options + "Datepicker"].
5756
apply($.datepicker, [this[0]].concat(otherArgs));
5758
return this.each(function() {
5759
typeof options === "string" ?
5760
$.datepicker["_" + options + "Datepicker"].
5761
apply($.datepicker, [this].concat(otherArgs)) :
5762
$.datepicker._attachDatepicker(this, options);
5766
$.datepicker = new Datepicker(); // singleton instance
5767
$.datepicker.initialized = false;
5768
$.datepicker.uuid = new Date().getTime();
5769
$.datepicker.version = "1.11.0";
5771
var datepicker = $.datepicker;
5775
* jQuery UI Draggable 1.11.0
5776
* http://jqueryui.com
5778
* Copyright 2014 jQuery Foundation and other contributors
5779
* Released under the MIT license.
5780
* http://jquery.org/license
5782
* http://api.jqueryui.com/draggable/
5786
$.widget("ui.draggable", $.ui.mouse, {
5788
widgetEventPrefix: "drag",
5793
connectToSortable: false,
5802
refreshPositions: false,
5804
revertDuration: 500,
5807
scrollSensitivity: 20,
5820
_create: function() {
5822
if (this.options.helper === "original" && !(/^(?:r|a|f)/).test(this.element.css("position"))) {
5823
this.element[0].style.position = "relative";
5825
if (this.options.addClasses){
5826
this.element.addClass("ui-draggable");
5828
if (this.options.disabled){
5829
this.element.addClass("ui-draggable-disabled");
5831
this._setHandleClassName();
5836
_setOption: function( key, value ) {
5837
this._super( key, value );
5838
if ( key === "handle" ) {
5839
this._setHandleClassName();
5843
_destroy: function() {
5844
if ( ( this.helper || this.element ).is( ".ui-draggable-dragging" ) ) {
5845
this.destroyOnClear = true;
5848
this.element.removeClass( "ui-draggable ui-draggable-dragging ui-draggable-disabled" );
5849
this._removeHandleClassName();
5850
this._mouseDestroy();
5853
_mouseCapture: function(event) {
5855
var document = this.document[ 0 ],
5859
// IE9 throws an "Unspecified error" accessing document.activeElement from an <iframe>
5862
// If the <body> is blurred, IE will switch windows, see #9520
5863
if ( document.activeElement && document.activeElement.nodeName.toLowerCase() !== "body" ) {
5864
// Blur any element that currently has focus, see #4261
5865
$( document.activeElement ).blur();
5867
} catch ( error ) {}
5869
// among others, prevent a drag on a resizable-handle
5870
if (this.helper || o.disabled || $(event.target).closest(".ui-resizable-handle").length > 0) {
5874
//Quit if we're not on a valid handle
5875
this.handle = this._getHandle(event);
5880
$(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() {
5881
$("<div class='ui-draggable-iframeFix' style='background: #fff;'></div>")
5883
width: this.offsetWidth + "px", height: this.offsetHeight + "px",
5884
position: "absolute", opacity: "0.001", zIndex: 1000
5886
.css($(this).offset())
5894
_mouseStart: function(event) {
5896
var o = this.options;
5898
//Create and append the visible helper
5899
this.helper = this._createHelper(event);
5901
this.helper.addClass("ui-draggable-dragging");
5903
//Cache the helper size
5904
this._cacheHelperProportions();
5906
//If ddmanager is used for droppables, set the global draggable
5907
if ($.ui.ddmanager) {
5908
$.ui.ddmanager.current = this;
5912
* - Position generation -
5913
* This block generates everything position related - it's the core of draggables.
5916
//Cache the margins of the original element
5917
this._cacheMargins();
5919
//Store the helper's css position
5920
this.cssPosition = this.helper.css( "position" );
5921
this.scrollParent = this.helper.scrollParent();
5922
this.offsetParent = this.helper.offsetParent();
5923
this.offsetParentCssPosition = this.offsetParent.css( "position" );
5925
//The element's absolute position on the page minus margins
5926
this.offset = this.positionAbs = this.element.offset();
5928
top: this.offset.top - this.margins.top,
5929
left: this.offset.left - this.margins.left
5932
//Reset scroll cache
5933
this.offset.scroll = false;
5935
$.extend(this.offset, {
5936
click: { //Where the click happened, relative to the element
5937
left: event.pageX - this.offset.left,
5938
top: event.pageY - this.offset.top
5940
parent: this._getParentOffset(),
5941
relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
5944
//Generate the original position
5945
this.originalPosition = this.position = this._generatePosition( event, false );
5946
this.originalPageX = event.pageX;
5947
this.originalPageY = event.pageY;
5949
//Adjust the mouse offset relative to the helper if "cursorAt" is supplied
5950
(o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
5952
//Set a containment if given in the options
5953
this._setContainment();
5955
//Trigger event + callbacks
5956
if (this._trigger("start", event) === false) {
5961
//Recache the helper size
5962
this._cacheHelperProportions();
5964
//Prepare the droppable offsets
5965
if ($.ui.ddmanager && !o.dropBehaviour) {
5966
$.ui.ddmanager.prepareOffsets(this, event);
5969
this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position
5971
//If the ddmanager is used for droppables, inform the manager that dragging has started (see #5003)
5972
if ( $.ui.ddmanager ) {
5973
$.ui.ddmanager.dragStart(this, event);
5979
_mouseDrag: function(event, noPropagation) {
5980
// reset any necessary cached properties (see #5009)
5981
if ( this.offsetParentCssPosition === "fixed" ) {
5982
this.offset.parent = this._getParentOffset();
5985
//Compute the helpers position
5986
this.position = this._generatePosition( event, true );
5987
this.positionAbs = this._convertPositionTo("absolute");
5989
//Call plugins and callbacks and use the resulting position if something is returned
5990
if (!noPropagation) {
5991
var ui = this._uiHash();
5992
if (this._trigger("drag", event, ui) === false) {
5996
this.position = ui.position;
5999
this.helper[ 0 ].style.left = this.position.left + "px";
6000
this.helper[ 0 ].style.top = this.position.top + "px";
6002
if ($.ui.ddmanager) {
6003
$.ui.ddmanager.drag(this, event);
6009
_mouseStop: function(event) {
6011
//If we are using droppables, inform the manager about the drop
6014
if ($.ui.ddmanager && !this.options.dropBehaviour) {
6015
dropped = $.ui.ddmanager.drop(this, event);
6018
//if a drop comes from outside (a sortable)
6020
dropped = this.dropped;
6021
this.dropped = false;
6024
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))) {
6025
$(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() {
6026
if (that._trigger("stop", event) !== false) {
6031
if (this._trigger("stop", event) !== false) {
6039
_mouseUp: function(event) {
6040
//Remove frame helpers
6041
$("div.ui-draggable-iframeFix").each(function() {
6042
this.parentNode.removeChild(this);
6045
//If the ddmanager is used for droppables, inform the manager that dragging has stopped (see #5003)
6046
if ( $.ui.ddmanager ) {
6047
$.ui.ddmanager.dragStop(this, event);
6050
// The interaction is over; whether or not the click resulted in a drag, focus the element
6051
this.element.focus();
6053
return $.ui.mouse.prototype._mouseUp.call(this, event);
6056
cancel: function() {
6058
if (this.helper.is(".ui-draggable-dragging")) {
6068
_getHandle: function(event) {
6069
return this.options.handle ?
6070
!!$( event.target ).closest( this.element.find( this.options.handle ) ).length :
6074
_setHandleClassName: function() {
6075
this._removeHandleClassName();
6076
$( this.options.handle || this.element ).addClass( "ui-draggable-handle" );
6079
_removeHandleClassName: function() {
6080
this.element.find( ".ui-draggable-handle" )
6082
.removeClass( "ui-draggable-handle" );
6085
_createHelper: function(event) {
6087
var o = this.options,
6088
helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[ 0 ], [ event ])) : (o.helper === "clone" ? this.element.clone().removeAttr("id") : this.element);
6090
if (!helper.parents("body").length) {
6091
helper.appendTo((o.appendTo === "parent" ? this.element[0].parentNode : o.appendTo));
6094
if (helper[0] !== this.element[0] && !(/(fixed|absolute)/).test(helper.css("position"))) {
6095
helper.css("position", "absolute");
6102
_adjustOffsetFromHelper: function(obj) {
6103
if (typeof obj === "string") {
6104
obj = obj.split(" ");
6106
if ($.isArray(obj)) {
6107
obj = { left: +obj[0], top: +obj[1] || 0 };
6109
if ("left" in obj) {
6110
this.offset.click.left = obj.left + this.margins.left;
6112
if ("right" in obj) {
6113
this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
6116
this.offset.click.top = obj.top + this.margins.top;
6118
if ("bottom" in obj) {
6119
this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
6123
_isRootNode: function( element ) {
6124
return ( /(html|body)/i ).test( element.tagName ) || element === this.document[ 0 ];
6127
_getParentOffset: function() {
6129
//Get the offsetParent and cache its position
6130
var po = this.offsetParent.offset(),
6131
document = this.document[ 0 ];
6133
// This is a special case where we need to modify a offset calculated on start, since the following happened:
6134
// 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
6135
// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
6136
// the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
6137
if (this.cssPosition === "absolute" && this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) {
6138
po.left += this.scrollParent.scrollLeft();
6139
po.top += this.scrollParent.scrollTop();
6142
if ( this._isRootNode( this.offsetParent[ 0 ] ) ) {
6143
po = { top: 0, left: 0 };
6147
top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
6148
left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
6153
_getRelativeOffset: function() {
6154
if ( this.cssPosition !== "relative" ) {
6155
return { top: 0, left: 0 };
6158
var p = this.element.position(),
6159
scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] );
6162
top: p.top - ( parseInt(this.helper.css( "top" ), 10) || 0 ) + ( !scrollIsRootNode ? this.scrollParent.scrollTop() : 0 ),
6163
left: p.left - ( parseInt(this.helper.css( "left" ), 10) || 0 ) + ( !scrollIsRootNode ? this.scrollParent.scrollLeft() : 0 )
6168
_cacheMargins: function() {
6170
left: (parseInt(this.element.css("marginLeft"),10) || 0),
6171
top: (parseInt(this.element.css("marginTop"),10) || 0),
6172
right: (parseInt(this.element.css("marginRight"),10) || 0),
6173
bottom: (parseInt(this.element.css("marginBottom"),10) || 0)
6177
_cacheHelperProportions: function() {
6178
this.helperProportions = {
6179
width: this.helper.outerWidth(),
6180
height: this.helper.outerHeight()
6184
_setContainment: function() {
6188
document = this.document[ 0 ];
6190
this.relative_container = null;
6192
if ( !o.containment ) {
6193
this.containment = null;
6197
if ( o.containment === "window" ) {
6198
this.containment = [
6199
$( window ).scrollLeft() - this.offset.relative.left - this.offset.parent.left,
6200
$( window ).scrollTop() - this.offset.relative.top - this.offset.parent.top,
6201
$( window ).scrollLeft() + $( window ).width() - this.helperProportions.width - this.margins.left,
6202
$( window ).scrollTop() + ( $( window ).height() || document.body.parentNode.scrollHeight ) - this.helperProportions.height - this.margins.top
6207
if ( o.containment === "document") {
6208
this.containment = [
6211
$( document ).width() - this.helperProportions.width - this.margins.left,
6212
( $( document ).height() || document.body.parentNode.scrollHeight ) - this.helperProportions.height - this.margins.top
6217
if ( o.containment.constructor === Array ) {
6218
this.containment = o.containment;
6222
if ( o.containment === "parent" ) {
6223
o.containment = this.helper[ 0 ].parentNode;
6226
c = $( o.containment );
6233
over = c.css( "overflow" ) !== "hidden";
6235
this.containment = [
6236
( parseInt( c.css( "borderLeftWidth" ), 10 ) || 0 ) + ( parseInt( c.css( "paddingLeft" ), 10 ) || 0 ),
6237
( parseInt( c.css( "borderTopWidth" ), 10 ) || 0 ) + ( parseInt( c.css( "paddingTop" ), 10 ) || 0 ),
6238
( over ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) - ( parseInt( c.css( "borderRightWidth" ), 10 ) || 0 ) - ( parseInt( c.css( "paddingRight" ), 10 ) || 0 ) - this.helperProportions.width - this.margins.left - this.margins.right,
6239
( over ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) - ( parseInt( c.css( "borderBottomWidth" ), 10 ) || 0 ) - ( parseInt( c.css( "paddingBottom" ), 10 ) || 0 ) - this.helperProportions.height - this.margins.top - this.margins.bottom
6241
this.relative_container = c;
6244
_convertPositionTo: function(d, pos) {
6247
pos = this.position;
6250
var mod = d === "absolute" ? 1 : -1,
6251
scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] );
6255
pos.top + // The absolute mouse position
6256
this.offset.relative.top * mod + // Only for relative positioned nodes: Relative offset from element to offset parent
6257
this.offset.parent.top * mod - // The offsetParent's offset without borders (offset + border)
6258
( ( this.cssPosition === "fixed" ? -this.offset.scroll.top : ( scrollIsRootNode ? 0 : this.offset.scroll.top ) ) * mod)
6261
pos.left + // The absolute mouse position
6262
this.offset.relative.left * mod + // Only for relative positioned nodes: Relative offset from element to offset parent
6263
this.offset.parent.left * mod - // The offsetParent's offset without borders (offset + border)
6264
( ( this.cssPosition === "fixed" ? -this.offset.scroll.left : ( scrollIsRootNode ? 0 : this.offset.scroll.left ) ) * mod)
6270
_generatePosition: function( event, constrainPosition ) {
6272
var containment, co, top, left,
6274
scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] ),
6275
pageX = event.pageX,
6276
pageY = event.pageY;
6279
if ( !scrollIsRootNode || !this.offset.scroll ) {
6280
this.offset.scroll = {
6281
top: this.scrollParent.scrollTop(),
6282
left: this.scrollParent.scrollLeft()
6287
* - Position constraining -
6288
* Constrain the position to a mix of grid, containment.
6291
// If we are not dragging yet, we won't check for options
6292
if ( constrainPosition ) {
6293
if ( this.containment ) {
6294
if ( this.relative_container ){
6295
co = this.relative_container.offset();
6297
this.containment[ 0 ] + co.left,
6298
this.containment[ 1 ] + co.top,
6299
this.containment[ 2 ] + co.left,
6300
this.containment[ 3 ] + co.top
6303
containment = this.containment;
6306
if (event.pageX - this.offset.click.left < containment[0]) {
6307
pageX = containment[0] + this.offset.click.left;
6309
if (event.pageY - this.offset.click.top < containment[1]) {
6310
pageY = containment[1] + this.offset.click.top;
6312
if (event.pageX - this.offset.click.left > containment[2]) {
6313
pageX = containment[2] + this.offset.click.left;
6315
if (event.pageY - this.offset.click.top > containment[3]) {
6316
pageY = containment[3] + this.offset.click.top;
6321
//Check for grid elements set to 0 to prevent divide by 0 error causing invalid argument errors in IE (see ticket #6950)
6322
top = o.grid[1] ? this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1] : this.originalPageY;
6323
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;
6325
left = o.grid[0] ? this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0] : this.originalPageX;
6326
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;
6329
if ( o.axis === "y" ) {
6330
pageX = this.originalPageX;
6333
if ( o.axis === "x" ) {
6334
pageY = this.originalPageY;
6340
pageY - // The absolute mouse position
6341
this.offset.click.top - // Click offset (relative to the element)
6342
this.offset.relative.top - // Only for relative positioned nodes: Relative offset from element to offset parent
6343
this.offset.parent.top + // The offsetParent's offset without borders (offset + border)
6344
( this.cssPosition === "fixed" ? -this.offset.scroll.top : ( scrollIsRootNode ? 0 : this.offset.scroll.top ) )
6347
pageX - // The absolute mouse position
6348
this.offset.click.left - // Click offset (relative to the element)
6349
this.offset.relative.left - // Only for relative positioned nodes: Relative offset from element to offset parent
6350
this.offset.parent.left + // The offsetParent's offset without borders (offset + border)
6351
( this.cssPosition === "fixed" ? -this.offset.scroll.left : ( scrollIsRootNode ? 0 : this.offset.scroll.left ) )
6357
_clear: function() {
6358
this.helper.removeClass("ui-draggable-dragging");
6359
if (this.helper[0] !== this.element[0] && !this.cancelHelperRemoval) {
6360
this.helper.remove();
6363
this.cancelHelperRemoval = false;
6364
if ( this.destroyOnClear ) {
6369
// From now on bulk stuff - mainly helpers
6371
_trigger: function(type, event, ui) {
6372
ui = ui || this._uiHash();
6373
$.ui.plugin.call( this, type, [ event, ui, this ], true );
6374
//The absolute position has to be recalculated after plugins
6375
if (type === "drag") {
6376
this.positionAbs = this._convertPositionTo("absolute");
6378
return $.Widget.prototype._trigger.call(this, type, event, ui);
6383
_uiHash: function() {
6385
helper: this.helper,
6386
position: this.position,
6387
originalPosition: this.originalPosition,
6388
offset: this.positionAbs
6394
$.ui.plugin.add("draggable", "connectToSortable", {
6395
start: function( event, ui, inst ) {
6397
var o = inst.options,
6398
uiSortable = $.extend({}, ui, { item: inst.element });
6399
inst.sortables = [];
6400
$(o.connectToSortable).each(function() {
6401
var sortable = $( this ).sortable( "instance" );
6402
if (sortable && !sortable.options.disabled) {
6403
inst.sortables.push({
6405
shouldRevert: sortable.options.revert
6407
sortable.refreshPositions(); // Call the sortable's refreshPositions at drag start to refresh the containerCache since the sortable container cache is used in drag and needs to be up to date (this will ensure it's initialised as well as being kept in step with any changes that might have happened on the page).
6408
sortable._trigger("activate", event, uiSortable);
6413
stop: function( event, ui, inst ) {
6415
//If we are still over the sortable, we fake the stop event of the sortable, but also remove helper
6416
var uiSortable = $.extend( {}, ui, {
6420
$.each(inst.sortables, function() {
6421
if (this.instance.isOver) {
6423
this.instance.isOver = 0;
6425
inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance
6426
this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work)
6428
//The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: "valid/invalid"
6429
if (this.shouldRevert) {
6430
this.instance.options.revert = this.shouldRevert;
6433
//Trigger the stop of the sortable
6434
this.instance._mouseStop(event);
6436
this.instance.options.helper = this.instance.options._helper;
6438
//If the helper has been the original item, restore properties in the sortable
6439
if (inst.options.helper === "original") {
6440
this.instance.currentItem.css({ top: "auto", left: "auto" });
6444
this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance
6445
this.instance._trigger("deactivate", event, uiSortable);
6451
drag: function( event, ui, inst ) {
6455
$.each(inst.sortables, function() {
6457
var innermostIntersecting = false,
6458
thisSortable = this;
6460
//Copy over some variables to allow calling the sortable's native _intersectsWith
6461
this.instance.positionAbs = inst.positionAbs;
6462
this.instance.helperProportions = inst.helperProportions;
6463
this.instance.offset.click = inst.offset.click;
6465
if (this.instance._intersectsWith(this.instance.containerCache)) {
6466
innermostIntersecting = true;
6467
$.each(inst.sortables, function() {
6468
this.instance.positionAbs = inst.positionAbs;
6469
this.instance.helperProportions = inst.helperProportions;
6470
this.instance.offset.click = inst.offset.click;
6471
if (this !== thisSortable &&
6472
this.instance._intersectsWith(this.instance.containerCache) &&
6473
$.contains(thisSortable.instance.element[0], this.instance.element[0])
6475
innermostIntersecting = false;
6477
return innermostIntersecting;
6481
if (innermostIntersecting) {
6482
//If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once
6483
if (!this.instance.isOver) {
6485
this.instance.isOver = 1;
6486
//Now we fake the start of dragging for the sortable instance,
6487
//by cloning the list group item, appending it to the sortable and using it as inst.currentItem
6488
//We can then fire the start event of the sortable with our passed browser event, and our own helper (so it doesn't create a new one)
6489
this.instance.currentItem = $(that).clone().removeAttr("id").appendTo(this.instance.element).data("ui-sortable-item", true);
6490
this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it
6491
this.instance.options.helper = function() { return ui.helper[0]; };
6493
event.target = this.instance.currentItem[0];
6494
this.instance._mouseCapture(event, true);
6495
this.instance._mouseStart(event, true, true);
6497
//Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes
6498
this.instance.offset.click.top = inst.offset.click.top;
6499
this.instance.offset.click.left = inst.offset.click.left;
6500
this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left;
6501
this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top;
6503
inst._trigger("toSortable", event);
6504
inst.dropped = this.instance.element; //draggable revert needs that
6505
//hack so receive/update callbacks work (mostly)
6506
inst.currentItem = inst.element;
6507
this.instance.fromOutside = inst;
6511
//Provided we did all the previous steps, we can fire the drag event of the sortable on every draggable drag, when it intersects with the sortable
6512
if (this.instance.currentItem) {
6513
this.instance._mouseDrag(event);
6518
//If it doesn't intersect with the sortable, and it intersected before,
6519
//we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval
6520
if (this.instance.isOver) {
6522
this.instance.isOver = 0;
6523
this.instance.cancelHelperRemoval = true;
6525
//Prevent reverting on this forced stop
6526
this.instance.options.revert = false;
6528
// The out event needs to be triggered independently
6529
this.instance._trigger("out", event, this.instance._uiHash(this.instance));
6531
this.instance._mouseStop(event, true);
6532
this.instance.options.helper = this.instance.options._helper;
6534
//Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size
6535
this.instance.currentItem.remove();
6536
if (this.instance.placeholder) {
6537
this.instance.placeholder.remove();
6540
inst._trigger("fromSortable", event);
6541
inst.dropped = false; //draggable revert needs that
6551
$.ui.plugin.add("draggable", "cursor", {
6552
start: function( event, ui, instance ) {
6553
var t = $( "body" ),
6554
o = instance.options;
6556
if (t.css("cursor")) {
6557
o._cursor = t.css("cursor");
6559
t.css("cursor", o.cursor);
6561
stop: function( event, ui, instance ) {
6562
var o = instance.options;
6564
$("body").css("cursor", o._cursor);
6569
$.ui.plugin.add("draggable", "opacity", {
6570
start: function( event, ui, instance ) {
6571
var t = $( ui.helper ),
6572
o = instance.options;
6573
if (t.css("opacity")) {
6574
o._opacity = t.css("opacity");
6576
t.css("opacity", o.opacity);
6578
stop: function( event, ui, instance ) {
6579
var o = instance.options;
6581
$(ui.helper).css("opacity", o._opacity);
6586
$.ui.plugin.add("draggable", "scroll", {
6587
start: function( event, ui, i ) {
6588
if ( i.scrollParent[ 0 ] !== i.document[ 0 ] && i.scrollParent[ 0 ].tagName !== "HTML" ) {
6589
i.overflowOffset = i.scrollParent.offset();
6592
drag: function( event, ui, i ) {
6596
document = i.document[ 0 ];
6598
if ( i.scrollParent[ 0 ] !== document && i.scrollParent[ 0 ].tagName !== "HTML" ) {
6599
if (!o.axis || o.axis !== "x") {
6600
if ((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) {
6601
i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed;
6602
} else if (event.pageY - i.overflowOffset.top < o.scrollSensitivity) {
6603
i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed;
6607
if (!o.axis || o.axis !== "y") {
6608
if ((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) {
6609
i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed;
6610
} else if (event.pageX - i.overflowOffset.left < o.scrollSensitivity) {
6611
i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed;
6617
if (!o.axis || o.axis !== "x") {
6618
if (event.pageY - $(document).scrollTop() < o.scrollSensitivity) {
6619
scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
6620
} else if ($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) {
6621
scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
6625
if (!o.axis || o.axis !== "y") {
6626
if (event.pageX - $(document).scrollLeft() < o.scrollSensitivity) {
6627
scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
6628
} else if ($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) {
6629
scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
6635
if (scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) {
6636
$.ui.ddmanager.prepareOffsets(i, event);
6642
$.ui.plugin.add("draggable", "snap", {
6643
start: function( event, ui, i ) {
6647
i.snapElements = [];
6649
$(o.snap.constructor !== String ? ( o.snap.items || ":data(ui-draggable)" ) : o.snap).each(function() {
6652
if (this !== i.element[0]) {
6653
i.snapElements.push({
6655
width: $t.outerWidth(), height: $t.outerHeight(),
6656
top: $o.top, left: $o.left
6662
drag: function( event, ui, inst ) {
6664
var ts, bs, ls, rs, l, r, t, b, i, first,
6666
d = o.snapTolerance,
6667
x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
6668
y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
6670
for (i = inst.snapElements.length - 1; i >= 0; i--){
6672
l = inst.snapElements[i].left;
6673
r = l + inst.snapElements[i].width;
6674
t = inst.snapElements[i].top;
6675
b = t + inst.snapElements[i].height;
6677
if ( x2 < l - d || x1 > r + d || y2 < t - d || y1 > b + d || !$.contains( inst.snapElements[ i ].item.ownerDocument, inst.snapElements[ i ].item ) ) {
6678
if (inst.snapElements[i].snapping) {
6679
(inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
6681
inst.snapElements[i].snapping = false;
6685
if (o.snapMode !== "inner") {
6686
ts = Math.abs(t - y2) <= d;
6687
bs = Math.abs(b - y1) <= d;
6688
ls = Math.abs(l - x2) <= d;
6689
rs = Math.abs(r - x1) <= d;
6691
ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
6694
ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top;
6697
ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left;
6700
ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left;
6704
first = (ts || bs || ls || rs);
6706
if (o.snapMode !== "outer") {
6707
ts = Math.abs(t - y1) <= d;
6708
bs = Math.abs(b - y2) <= d;
6709
ls = Math.abs(l - x1) <= d;
6710
rs = Math.abs(r - x2) <= d;
6712
ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top;
6715
ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
6718
ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left;
6721
ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left;
6725
if (!inst.snapElements[i].snapping && (ts || bs || ls || rs || first)) {
6726
(inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
6728
inst.snapElements[i].snapping = (ts || bs || ls || rs || first);
6735
$.ui.plugin.add("draggable", "stack", {
6736
start: function( event, ui, instance ) {
6738
o = instance.options,
6739
group = $.makeArray($(o.stack)).sort(function(a,b) {
6740
return (parseInt($(a).css("zIndex"),10) || 0) - (parseInt($(b).css("zIndex"),10) || 0);
6743
if (!group.length) { return; }
6745
min = parseInt($(group[0]).css("zIndex"), 10) || 0;
6746
$(group).each(function(i) {
6747
$(this).css("zIndex", min + i);
6749
this.css("zIndex", (min + group.length));
6753
$.ui.plugin.add("draggable", "zIndex", {
6754
start: function( event, ui, instance ) {
6755
var t = $( ui.helper ),
6756
o = instance.options;
6758
if (t.css("zIndex")) {
6759
o._zIndex = t.css("zIndex");
6761
t.css("zIndex", o.zIndex);
6763
stop: function( event, ui, instance ) {
6764
var o = instance.options;
6767
$(ui.helper).css("zIndex", o._zIndex);
6772
var draggable = $.ui.draggable;
6776
* jQuery UI Resizable 1.11.0
6777
* http://jqueryui.com
6779
* Copyright 2014 jQuery Foundation and other contributors
6780
* Released under the MIT license.
6781
* http://jquery.org/license
6783
* http://api.jqueryui.com/resizable/
6787
$.widget("ui.resizable", $.ui.mouse, {
6789
widgetEventPrefix: "resize",
6793
animateDuration: "slow",
6794
animateEasing: "swing",
6815
_num: function( value ) {
6816
return parseInt( value, 10 ) || 0;
6819
_isNumber: function( value ) {
6820
return !isNaN( parseInt( value , 10 ) );
6823
_hasScroll: function( el, a ) {
6825
if ( $( el ).css( "overflow" ) === "hidden") {
6829
var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
6832
if ( el[ scroll ] > 0 ) {
6836
// TODO: determine which cases actually cause this to happen
6837
// if the element doesn't have the scroll set, see if it's possible to
6840
has = ( el[ scroll ] > 0 );
6845
_create: function() {
6847
var n, i, handle, axis, hname,
6850
this.element.addClass("ui-resizable");
6853
_aspectRatio: !!(o.aspectRatio),
6854
aspectRatio: o.aspectRatio,
6855
originalElement: this.element,
6856
_proportionallyResizeElements: [],
6857
_helper: o.helper || o.ghost || o.animate ? o.helper || "ui-resizable-helper" : null
6860
// Wrap the element if it cannot hold child nodes
6861
if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) {
6864
$("<div class='ui-wrapper' style='overflow: hidden;'></div>").css({
6865
position: this.element.css("position"),
6866
width: this.element.outerWidth(),
6867
height: this.element.outerHeight(),
6868
top: this.element.css("top"),
6869
left: this.element.css("left")
6873
this.element = this.element.parent().data(
6874
"ui-resizable", this.element.resizable( "instance" )
6877
this.elementIsWrapper = true;
6879
this.element.css({ marginLeft: this.originalElement.css("marginLeft"), marginTop: this.originalElement.css("marginTop"), marginRight: this.originalElement.css("marginRight"), marginBottom: this.originalElement.css("marginBottom") });
6880
this.originalElement.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0});
6882
// Prevent Safari textarea resize
6883
this.originalResizeStyle = this.originalElement.css("resize");
6884
this.originalElement.css("resize", "none");
6886
this._proportionallyResizeElements.push(this.originalElement.css({ position: "static", zoom: 1, display: "block" }));
6889
// avoid IE jump (hard set the margin)
6890
this.originalElement.css({ margin: this.originalElement.css("margin") });
6892
this._proportionallyResize();
6895
this.handles = o.handles || (!$(".ui-resizable-handle", this.element).length ? "e,s,se" : { n: ".ui-resizable-n", e: ".ui-resizable-e", s: ".ui-resizable-s", w: ".ui-resizable-w", se: ".ui-resizable-se", sw: ".ui-resizable-sw", ne: ".ui-resizable-ne", nw: ".ui-resizable-nw" });
6896
if(this.handles.constructor === String) {
6898
if ( this.handles === "all") {
6899
this.handles = "n,e,s,w,se,sw,ne,nw";
6902
n = this.handles.split(",");
6905
for(i = 0; i < n.length; i++) {
6907
handle = $.trim(n[i]);
6908
hname = "ui-resizable-"+handle;
6909
axis = $("<div class='ui-resizable-handle " + hname + "'></div>");
6911
axis.css({ zIndex: o.zIndex });
6913
// TODO : What's going on here?
6914
if ("se" === handle) {
6915
axis.addClass("ui-icon ui-icon-gripsmall-diagonal-se");
6918
this.handles[handle] = ".ui-resizable-"+handle;
6919
this.element.append(axis);
6924
this._renderAxis = function(target) {
6926
var i, axis, padPos, padWrapper;
6928
target = target || this.element;
6930
for(i in this.handles) {
6932
if(this.handles[i].constructor === String) {
6933
this.handles[i] = this.element.children( this.handles[ i ] ).first().show();
6936
if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) {
6938
axis = $(this.handles[i], this.element);
6940
padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth();
6942
padPos = [ "padding",
6943
/ne|nw|n/.test(i) ? "Top" :
6944
/se|sw|s/.test(i) ? "Bottom" :
6945
/^e$/.test(i) ? "Right" : "Left" ].join("");
6947
target.css(padPos, padWrapper);
6949
this._proportionallyResize();
6953
// TODO: What's that good for? There's not anything to be executed left
6954
if(!$(this.handles[i]).length) {
6960
// TODO: make renderAxis a prototype function
6961
this._renderAxis(this.element);
6963
this._handles = $(".ui-resizable-handle", this.element)
6964
.disableSelection();
6966
this._handles.mouseover(function() {
6967
if (!that.resizing) {
6968
if (this.className) {
6969
axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);
6971
that.axis = axis && axis[1] ? axis[1] : "se";
6976
this._handles.hide();
6978
.addClass("ui-resizable-autohide")
6979
.mouseenter(function() {
6983
$(this).removeClass("ui-resizable-autohide");
6984
that._handles.show();
6986
.mouseleave(function(){
6990
if (!that.resizing) {
6991
$(this).addClass("ui-resizable-autohide");
6992
that._handles.hide();
7001
_destroy: function() {
7003
this._mouseDestroy();
7006
_destroy = function(exp) {
7007
$(exp).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing")
7008
.removeData("resizable").removeData("ui-resizable").unbind(".resizable").find(".ui-resizable-handle").remove();
7011
// TODO: Unwrap at same DOM position
7012
if (this.elementIsWrapper) {
7013
_destroy(this.element);
7014
wrapper = this.element;
7015
this.originalElement.css({
7016
position: wrapper.css("position"),
7017
width: wrapper.outerWidth(),
7018
height: wrapper.outerHeight(),
7019
top: wrapper.css("top"),
7020
left: wrapper.css("left")
7021
}).insertAfter( wrapper );
7025
this.originalElement.css("resize", this.originalResizeStyle);
7026
_destroy(this.originalElement);
7031
_mouseCapture: function(event) {
7035
for (i in this.handles) {
7036
handle = $(this.handles[i])[0];
7037
if (handle === event.target || $.contains(handle, event.target)) {
7042
return !this.options.disabled && capture;
7045
_mouseStart: function(event) {
7047
var curleft, curtop, cursor,
7051
this.resizing = true;
7053
this._renderProxy();
7055
curleft = this._num(this.helper.css("left"));
7056
curtop = this._num(this.helper.css("top"));
7058
if (o.containment) {
7059
curleft += $(o.containment).scrollLeft() || 0;
7060
curtop += $(o.containment).scrollTop() || 0;
7063
this.offset = this.helper.offset();
7064
this.position = { left: curleft, top: curtop };
7065
this.size = this._helper ? { width: this.helper.width(), height: this.helper.height() } : { width: el.width(), height: el.height() };
7066
this.originalSize = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
7067
this.originalPosition = { left: curleft, top: curtop };
7068
this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() };
7069
this.originalMousePosition = { left: event.pageX, top: event.pageY };
7071
this.aspectRatio = (typeof o.aspectRatio === "number") ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1);
7073
cursor = $(".ui-resizable-" + this.axis).css("cursor");
7074
$("body").css("cursor", cursor === "auto" ? this.axis + "-resize" : cursor);
7076
el.addClass("ui-resizable-resizing");
7077
this._propagate("start", event);
7081
_mouseDrag: function(event) {
7084
el = this.helper, props = {},
7085
smp = this.originalMousePosition,
7087
dx = (event.pageX-smp.left)||0,
7088
dy = (event.pageY-smp.top)||0,
7089
trigger = this._change[a];
7091
this.prevPosition = {
7092
top: this.position.top,
7093
left: this.position.left
7096
width: this.size.width,
7097
height: this.size.height
7104
data = trigger.apply(this, [event, dx, dy]);
7106
this._updateVirtualBoundaries(event.shiftKey);
7107
if (this._aspectRatio || event.shiftKey) {
7108
data = this._updateRatio(data, event);
7111
data = this._respectSize(data, event);
7113
this._updateCache(data);
7115
this._propagate("resize", event);
7117
if ( this.position.top !== this.prevPosition.top ) {
7118
props.top = this.position.top + "px";
7120
if ( this.position.left !== this.prevPosition.left ) {
7121
props.left = this.position.left + "px";
7123
if ( this.size.width !== this.prevSize.width ) {
7124
props.width = this.size.width + "px";
7126
if ( this.size.height !== this.prevSize.height ) {
7127
props.height = this.size.height + "px";
7131
if ( !this._helper && this._proportionallyResizeElements.length ) {
7132
this._proportionallyResize();
7135
if ( !$.isEmptyObject( props ) ) {
7136
this._trigger( "resize", event, this.ui() );
7142
_mouseStop: function(event) {
7144
this.resizing = false;
7145
var pr, ista, soffseth, soffsetw, s, left, top,
7146
o = this.options, that = this;
7150
pr = this._proportionallyResizeElements;
7151
ista = pr.length && (/textarea/i).test(pr[0].nodeName);
7152
soffseth = ista && this._hasScroll(pr[0], "left") /* TODO - jump height */ ? 0 : that.sizeDiff.height;
7153
soffsetw = ista ? 0 : that.sizeDiff.width;
7155
s = { width: (that.helper.width() - soffsetw), height: (that.helper.height() - soffseth) };
7156
left = (parseInt(that.element.css("left"), 10) + (that.position.left - that.originalPosition.left)) || null;
7157
top = (parseInt(that.element.css("top"), 10) + (that.position.top - that.originalPosition.top)) || null;
7160
this.element.css($.extend(s, { top: top, left: left }));
7163
that.helper.height(that.size.height);
7164
that.helper.width(that.size.width);
7166
if (this._helper && !o.animate) {
7167
this._proportionallyResize();
7171
$("body").css("cursor", "auto");
7173
this.element.removeClass("ui-resizable-resizing");
7175
this._propagate("stop", event);
7178
this.helper.remove();
7185
_updateVirtualBoundaries: function(forceAspectRatio) {
7186
var pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b,
7190
minWidth: this._isNumber(o.minWidth) ? o.minWidth : 0,
7191
maxWidth: this._isNumber(o.maxWidth) ? o.maxWidth : Infinity,
7192
minHeight: this._isNumber(o.minHeight) ? o.minHeight : 0,
7193
maxHeight: this._isNumber(o.maxHeight) ? o.maxHeight : Infinity
7196
if(this._aspectRatio || forceAspectRatio) {
7197
pMinWidth = b.minHeight * this.aspectRatio;
7198
pMinHeight = b.minWidth / this.aspectRatio;
7199
pMaxWidth = b.maxHeight * this.aspectRatio;
7200
pMaxHeight = b.maxWidth / this.aspectRatio;
7202
if(pMinWidth > b.minWidth) {
7203
b.minWidth = pMinWidth;
7205
if(pMinHeight > b.minHeight) {
7206
b.minHeight = pMinHeight;
7208
if(pMaxWidth < b.maxWidth) {
7209
b.maxWidth = pMaxWidth;
7211
if(pMaxHeight < b.maxHeight) {
7212
b.maxHeight = pMaxHeight;
7215
this._vBoundaries = b;
7218
_updateCache: function(data) {
7219
this.offset = this.helper.offset();
7220
if (this._isNumber(data.left)) {
7221
this.position.left = data.left;
7223
if (this._isNumber(data.top)) {
7224
this.position.top = data.top;
7226
if (this._isNumber(data.height)) {
7227
this.size.height = data.height;
7229
if (this._isNumber(data.width)) {
7230
this.size.width = data.width;
7234
_updateRatio: function( data ) {
7236
var cpos = this.position,
7240
if (this._isNumber(data.height)) {
7241
data.width = (data.height * this.aspectRatio);
7242
} else if (this._isNumber(data.width)) {
7243
data.height = (data.width / this.aspectRatio);
7247
data.left = cpos.left + (csize.width - data.width);
7251
data.top = cpos.top + (csize.height - data.height);
7252
data.left = cpos.left + (csize.width - data.width);
7258
_respectSize: function( data ) {
7260
var o = this._vBoundaries,
7262
ismaxw = this._isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh = this._isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height),
7263
isminw = this._isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh = this._isNumber(data.height) && o.minHeight && (o.minHeight > data.height),
7264
dw = this.originalPosition.left + this.originalSize.width,
7265
dh = this.position.top + this.size.height,
7266
cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a);
7268
data.width = o.minWidth;
7271
data.height = o.minHeight;
7274
data.width = o.maxWidth;
7277
data.height = o.maxHeight;
7281
data.left = dw - o.minWidth;
7284
data.left = dw - o.maxWidth;
7287
data.top = dh - o.minHeight;
7290
data.top = dh - o.maxHeight;
7293
// Fixing jump error on top/left - bug #2330
7294
if (!data.width && !data.height && !data.left && data.top) {
7296
} else if (!data.width && !data.height && !data.top && data.left) {
7303
_proportionallyResize: function() {
7305
if (!this._proportionallyResizeElements.length) {
7309
var i, j, borders, paddings, prel,
7310
element = this.helper || this.element;
7312
for ( i=0; i < this._proportionallyResizeElements.length; i++) {
7314
prel = this._proportionallyResizeElements[i];
7316
if (!this.borderDif) {
7317
this.borderDif = [];
7318
borders = [prel.css("borderTopWidth"), prel.css("borderRightWidth"), prel.css("borderBottomWidth"), prel.css("borderLeftWidth")];
7319
paddings = [prel.css("paddingTop"), prel.css("paddingRight"), prel.css("paddingBottom"), prel.css("paddingLeft")];
7321
for ( j = 0; j < borders.length; j++ ) {
7322
this.borderDif[ j ] = ( parseInt( borders[ j ], 10 ) || 0 ) + ( parseInt( paddings[ j ], 10 ) || 0 );
7327
height: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0,
7328
width: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0
7335
_renderProxy: function() {
7337
var el = this.element, o = this.options;
7338
this.elementOffset = el.offset();
7342
this.helper = this.helper || $("<div style='overflow:hidden;'></div>");
7344
this.helper.addClass(this._helper).css({
7345
width: this.element.outerWidth() - 1,
7346
height: this.element.outerHeight() - 1,
7347
position: "absolute",
7348
left: this.elementOffset.left +"px",
7349
top: this.elementOffset.top +"px",
7350
zIndex: ++o.zIndex //TODO: Don't modify option
7355
.disableSelection();
7358
this.helper = this.element;
7364
e: function(event, dx) {
7365
return { width: this.originalSize.width + dx };
7367
w: function(event, dx) {
7368
var cs = this.originalSize, sp = this.originalPosition;
7369
return { left: sp.left + dx, width: cs.width - dx };
7371
n: function(event, dx, dy) {
7372
var cs = this.originalSize, sp = this.originalPosition;
7373
return { top: sp.top + dy, height: cs.height - dy };
7375
s: function(event, dx, dy) {
7376
return { height: this.originalSize.height + dy };
7378
se: function(event, dx, dy) {
7379
return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
7381
sw: function(event, dx, dy) {
7382
return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
7384
ne: function(event, dx, dy) {
7385
return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
7387
nw: function(event, dx, dy) {
7388
return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
7392
_propagate: function(n, event) {
7393
$.ui.plugin.call(this, n, [event, this.ui()]);
7394
(n !== "resize" && this._trigger(n, event, this.ui()));
7401
originalElement: this.originalElement,
7402
element: this.element,
7403
helper: this.helper,
7404
position: this.position,
7406
originalSize: this.originalSize,
7407
originalPosition: this.originalPosition,
7408
prevSize: this.prevSize,
7409
prevPosition: this.prevPosition
7416
* Resizable Extensions
7419
$.ui.plugin.add("resizable", "animate", {
7421
stop: function( event ) {
7422
var that = $(this).resizable( "instance" ),
7424
pr = that._proportionallyResizeElements,
7425
ista = pr.length && (/textarea/i).test(pr[0].nodeName),
7426
soffseth = ista && that._hasScroll(pr[0], "left") /* TODO - jump height */ ? 0 : that.sizeDiff.height,
7427
soffsetw = ista ? 0 : that.sizeDiff.width,
7428
style = { width: (that.size.width - soffsetw), height: (that.size.height - soffseth) },
7429
left = (parseInt(that.element.css("left"), 10) + (that.position.left - that.originalPosition.left)) || null,
7430
top = (parseInt(that.element.css("top"), 10) + (that.position.top - that.originalPosition.top)) || null;
7432
that.element.animate(
7433
$.extend(style, top && left ? { top: top, left: left } : {}), {
7434
duration: o.animateDuration,
7435
easing: o.animateEasing,
7439
width: parseInt(that.element.css("width"), 10),
7440
height: parseInt(that.element.css("height"), 10),
7441
top: parseInt(that.element.css("top"), 10),
7442
left: parseInt(that.element.css("left"), 10)
7445
if (pr && pr.length) {
7446
$(pr[0]).css({ width: data.width, height: data.height });
7449
// propagating resize, and updating values for each animation step
7450
that._updateCache(data);
7451
that._propagate("resize", event);
7460
$.ui.plugin.add( "resizable", "containment", {
7463
var element, p, co, ch, cw, width, height,
7464
that = $( this ).resizable( "instance" ),
7468
ce = ( oc instanceof $ ) ? oc.get( 0 ) : ( /parent/.test( oc ) ) ? el.parent().get( 0 ) : oc;
7474
that.containerElement = $( ce );
7476
if ( /document/.test( oc ) || oc === document ) {
7477
that.containerOffset = {
7481
that.containerPosition = {
7487
element: $( document ),
7490
width: $( document ).width(),
7491
height: $( document ).height() || document.body.parentNode.scrollHeight
7496
$([ "Top", "Right", "Left", "Bottom" ]).each(function( i, name ) {
7497
p[ i ] = that._num( element.css( "padding" + name ) );
7500
that.containerOffset = element.offset();
7501
that.containerPosition = element.position();
7502
that.containerSize = {
7503
height: ( element.innerHeight() - p[ 3 ] ),
7504
width: ( element.innerWidth() - p[ 1 ] )
7507
co = that.containerOffset;
7508
ch = that.containerSize.height;
7509
cw = that.containerSize.width;
7510
width = ( that._hasScroll ( ce, "left" ) ? ce.scrollWidth : cw );
7511
height = ( that._hasScroll ( ce ) ? ce.scrollHeight : ch ) ;
7523
resize: function( event, ui ) {
7524
var woset, hoset, isParent, isOffsetRelative,
7525
that = $( this ).resizable( "instance" ),
7527
co = that.containerOffset,
7529
pRatio = that._aspectRatio || event.shiftKey,
7534
ce = that.containerElement,
7535
continueResize = true;
7537
if ( ce[ 0 ] !== document && ( /static/ ).test( ce.css( "position" ) ) ) {
7541
if ( cp.left < ( that._helper ? co.left : 0 ) ) {
7542
that.size.width = that.size.width + ( that._helper ? ( that.position.left - co.left ) : ( that.position.left - cop.left ) );
7544
that.size.height = that.size.width / that.aspectRatio;
7545
continueResize = false;
7547
that.position.left = o.helper ? co.left : 0;
7550
if ( cp.top < ( that._helper ? co.top : 0 ) ) {
7551
that.size.height = that.size.height + ( that._helper ? ( that.position.top - co.top ) : that.position.top );
7553
that.size.width = that.size.height * that.aspectRatio;
7554
continueResize = false;
7556
that.position.top = that._helper ? co.top : 0;
7559
that.offset.left = that.parentData.left + that.position.left;
7560
that.offset.top = that.parentData.top + that.position.top;
7562
woset = Math.abs( ( that._helper ? that.offset.left - cop.left : ( that.offset.left - co.left ) ) + that.sizeDiff.width );
7563
hoset = Math.abs( ( that._helper ? that.offset.top - cop.top : ( that.offset.top - co.top ) ) + that.sizeDiff.height );
7565
isParent = that.containerElement.get( 0 ) === that.element.parent().get( 0 );
7566
isOffsetRelative = /relative|absolute/.test( that.containerElement.css( "position" ) );
7568
if ( isParent && isOffsetRelative ) {
7569
woset -= Math.abs( that.parentData.left );
7572
if ( woset + that.size.width >= that.parentData.width ) {
7573
that.size.width = that.parentData.width - woset;
7575
that.size.height = that.size.width / that.aspectRatio;
7576
continueResize = false;
7580
if ( hoset + that.size.height >= that.parentData.height ) {
7581
that.size.height = that.parentData.height - hoset;
7583
that.size.width = that.size.height * that.aspectRatio;
7584
continueResize = false;
7588
if ( !continueResize ){
7589
that.position.left = ui.prevPosition.left;
7590
that.position.top = ui.prevPosition.top;
7591
that.size.width = ui.prevSize.width;
7592
that.size.height = ui.prevSize.height;
7597
var that = $( this ).resizable( "instance" ),
7599
co = that.containerOffset,
7600
cop = that.containerPosition,
7601
ce = that.containerElement,
7602
helper = $( that.helper ),
7603
ho = helper.offset(),
7604
w = helper.outerWidth() - that.sizeDiff.width,
7605
h = helper.outerHeight() - that.sizeDiff.height;
7607
if ( that._helper && !o.animate && ( /relative/ ).test( ce.css( "position" ) ) ) {
7609
left: ho.left - cop.left - co.left,
7615
if ( that._helper && !o.animate && ( /static/ ).test( ce.css( "position" ) ) ) {
7617
left: ho.left - cop.left - co.left,
7625
$.ui.plugin.add("resizable", "alsoResize", {
7627
start: function () {
7628
var that = $(this).resizable( "instance" ),
7630
_store = function (exp) {
7631
$(exp).each(function() {
7633
el.data("ui-resizable-alsoresize", {
7634
width: parseInt(el.width(), 10), height: parseInt(el.height(), 10),
7635
left: parseInt(el.css("left"), 10), top: parseInt(el.css("top"), 10)
7640
if (typeof(o.alsoResize) === "object" && !o.alsoResize.parentNode) {
7641
if (o.alsoResize.length) { o.alsoResize = o.alsoResize[0]; _store(o.alsoResize); }
7642
else { $.each(o.alsoResize, function (exp) { _store(exp); }); }
7644
_store(o.alsoResize);
7648
resize: function (event, ui) {
7649
var that = $(this).resizable( "instance" ),
7651
os = that.originalSize,
7652
op = that.originalPosition,
7654
height: (that.size.height - os.height) || 0, width: (that.size.width - os.width) || 0,
7655
top: (that.position.top - op.top) || 0, left: (that.position.left - op.left) || 0
7658
_alsoResize = function (exp, c) {
7659
$(exp).each(function() {
7660
var el = $(this), start = $(this).data("ui-resizable-alsoresize"), style = {},
7661
css = c && c.length ? c : el.parents(ui.originalElement[0]).length ? ["width", "height"] : ["width", "height", "top", "left"];
7663
$.each(css, function (i, prop) {
7664
var sum = (start[prop]||0) + (delta[prop]||0);
7665
if (sum && sum >= 0) {
7666
style[prop] = sum || null;
7674
if (typeof(o.alsoResize) === "object" && !o.alsoResize.nodeType) {
7675
$.each(o.alsoResize, function (exp, c) { _alsoResize(exp, c); });
7677
_alsoResize(o.alsoResize);
7682
$(this).removeData("resizable-alsoresize");
7686
$.ui.plugin.add("resizable", "ghost", {
7690
var that = $(this).resizable( "instance" ), o = that.options, cs = that.size;
7692
that.ghost = that.originalElement.clone();
7694
.css({ opacity: 0.25, display: "block", position: "relative", height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 })
7695
.addClass("ui-resizable-ghost")
7696
.addClass(typeof o.ghost === "string" ? o.ghost : "");
7698
that.ghost.appendTo(that.helper);
7703
var that = $(this).resizable( "instance" );
7705
that.ghost.css({ position: "relative", height: that.size.height, width: that.size.width });
7710
var that = $(this).resizable( "instance" );
7711
if (that.ghost && that.helper) {
7712
that.helper.get(0).removeChild(that.ghost.get(0));
7718
$.ui.plugin.add("resizable", "grid", {
7720
resize: function() {
7721
var that = $(this).resizable( "instance" ),
7724
os = that.originalSize,
7725
op = that.originalPosition,
7727
grid = typeof o.grid === "number" ? [o.grid, o.grid] : o.grid,
7728
gridX = (grid[0]||1),
7729
gridY = (grid[1]||1),
7730
ox = Math.round((cs.width - os.width) / gridX) * gridX,
7731
oy = Math.round((cs.height - os.height) / gridY) * gridY,
7732
newWidth = os.width + ox,
7733
newHeight = os.height + oy,
7734
isMaxWidth = o.maxWidth && (o.maxWidth < newWidth),
7735
isMaxHeight = o.maxHeight && (o.maxHeight < newHeight),
7736
isMinWidth = o.minWidth && (o.minWidth > newWidth),
7737
isMinHeight = o.minHeight && (o.minHeight > newHeight);
7742
newWidth = newWidth + gridX;
7745
newHeight = newHeight + gridY;
7748
newWidth = newWidth - gridX;
7751
newHeight = newHeight - gridY;
7754
if (/^(se|s|e)$/.test(a)) {
7755
that.size.width = newWidth;
7756
that.size.height = newHeight;
7757
} else if (/^(ne)$/.test(a)) {
7758
that.size.width = newWidth;
7759
that.size.height = newHeight;
7760
that.position.top = op.top - oy;
7761
} else if (/^(sw)$/.test(a)) {
7762
that.size.width = newWidth;
7763
that.size.height = newHeight;
7764
that.position.left = op.left - ox;
7766
if ( newHeight - gridY > 0 ) {
7767
that.size.height = newHeight;
7768
that.position.top = op.top - oy;
7770
that.size.height = gridY;
7771
that.position.top = op.top + os.height - gridY;
7773
if ( newWidth - gridX > 0 ) {
7774
that.size.width = newWidth;
7775
that.position.left = op.left - ox;
7777
that.size.width = gridX;
7778
that.position.left = op.left + os.width - gridX;
7785
var resizable = $.ui.resizable;
7789
* jQuery UI Dialog 1.11.0
7790
* http://jqueryui.com
7792
* Copyright 2014 jQuery Foundation and other contributors
7793
* Released under the MIT license.
7794
* http://jquery.org/license
7796
* http://api.jqueryui.com/dialog/
7800
var dialog = $.widget( "ui.dialog", {
7806
closeOnEscape: true,
7822
// Ensure the titlebar is always visible
7823
using: function( pos ) {
7824
var topOffset = $( this ).css( pos ).offset().top;
7825
if ( topOffset < 0 ) {
7826
$( this ).css( "top", pos.top - topOffset );
7848
sizeRelatedOptions: {
7858
resizableRelatedOptions: {
7865
_create: function() {
7866
this.originalCss = {
7867
display: this.element[ 0 ].style.display,
7868
width: this.element[ 0 ].style.width,
7869
minHeight: this.element[ 0 ].style.minHeight,
7870
maxHeight: this.element[ 0 ].style.maxHeight,
7871
height: this.element[ 0 ].style.height
7873
this.originalPosition = {
7874
parent: this.element.parent(),
7875
index: this.element.parent().children().index( this.element )
7877
this.originalTitle = this.element.attr( "title" );
7878
this.options.title = this.options.title || this.originalTitle;
7880
this._createWrapper();
7884
.removeAttr( "title" )
7885
.addClass( "ui-dialog-content ui-widget-content" )
7886
.appendTo( this.uiDialog );
7888
this._createTitlebar();
7889
this._createButtonPane();
7891
if ( this.options.draggable && $.fn.draggable ) {
7892
this._makeDraggable();
7894
if ( this.options.resizable && $.fn.resizable ) {
7895
this._makeResizable();
7898
this._isOpen = false;
7904
if ( this.options.autoOpen ) {
7909
_appendTo: function() {
7910
var element = this.options.appendTo;
7911
if ( element && (element.jquery || element.nodeType) ) {
7912
return $( element );
7914
return this.document.find( element || "body" ).eq( 0 );
7917
_destroy: function() {
7919
originalPosition = this.originalPosition;
7921
this._destroyOverlay();
7925
.removeClass( "ui-dialog-content ui-widget-content" )
7926
.css( this.originalCss )
7927
// Without detaching first, the following becomes really slow
7930
this.uiDialog.stop( true, true ).remove();
7932
if ( this.originalTitle ) {
7933
this.element.attr( "title", this.originalTitle );
7936
next = originalPosition.parent.children().eq( originalPosition.index );
7937
// Don't try to place the dialog next to itself (#8613)
7938
if ( next.length && next[ 0 ] !== this.element[ 0 ] ) {
7939
next.before( this.element );
7941
originalPosition.parent.append( this.element );
7945
widget: function() {
7946
return this.uiDialog;
7952
close: function( event ) {
7956
if ( !this._isOpen || this._trigger( "beforeClose", event ) === false ) {
7960
this._isOpen = false;
7961
this._focusedElement = null;
7962
this._destroyOverlay();
7963
this._untrackInstance();
7965
if ( !this.opener.filter( ":focusable" ).focus().length ) {
7968
// IE9 throws an "Unspecified error" accessing document.activeElement from an <iframe>
7970
activeElement = this.document[ 0 ].activeElement;
7972
// Support: IE9, IE10
7973
// If the <body> is blurred, IE will switch windows, see #4520
7974
if ( activeElement && activeElement.nodeName.toLowerCase() !== "body" ) {
7976
// Hiding a focused element doesn't trigger blur in WebKit
7977
// so in case we have nothing to focus on, explicitly blur the active element
7978
// https://bugs.webkit.org/show_bug.cgi?id=47182
7979
$( activeElement ).blur();
7981
} catch ( error ) {}
7984
this._hide( this.uiDialog, this.options.hide, function() {
7985
that._trigger( "close", event );
7989
isOpen: function() {
7990
return this._isOpen;
7993
moveToTop: function() {
7997
_moveToTop: function( event, silent ) {
7999
zIndicies = this.uiDialog.siblings( ".ui-front:visible" ).map(function() {
8000
return +$( this ).css( "z-index" );
8002
zIndexMax = Math.max.apply( null, zIndicies );
8004
if ( zIndexMax >= +this.uiDialog.css( "z-index" ) ) {
8005
this.uiDialog.css( "z-index", zIndexMax + 1 );
8009
if ( moved && !silent ) {
8010
this._trigger( "focus", event );
8017
if ( this._isOpen ) {
8018
if ( this._moveToTop() ) {
8019
this._focusTabbable();
8024
this._isOpen = true;
8025
this.opener = $( this.document[ 0 ].activeElement );
8029
this._createOverlay();
8030
this._moveToTop( null, true );
8031
this._show( this.uiDialog, this.options.show, function() {
8032
that._focusTabbable();
8033
that._trigger( "focus" );
8036
this._trigger( "open" );
8039
_focusTabbable: function() {
8040
// Set focus to the first match:
8041
// 1. An element that was focused previously
8042
// 2. First element inside the dialog matching [autofocus]
8043
// 3. Tabbable element inside the content element
8044
// 4. Tabbable element inside the buttonpane
8045
// 5. The close button
8046
// 6. The dialog itself
8047
var hasFocus = this._focusedElement;
8049
hasFocus = this.element.find( "[autofocus]" );
8051
if ( !hasFocus.length ) {
8052
hasFocus = this.element.find( ":tabbable" );
8054
if ( !hasFocus.length ) {
8055
hasFocus = this.uiDialogButtonPane.find( ":tabbable" );
8057
if ( !hasFocus.length ) {
8058
hasFocus = this.uiDialogTitlebarClose.filter( ":tabbable" );
8060
if ( !hasFocus.length ) {
8061
hasFocus = this.uiDialog;
8063
hasFocus.eq( 0 ).focus();
8066
_keepFocus: function( event ) {
8067
function checkFocus() {
8068
var activeElement = this.document[0].activeElement,
8069
isActive = this.uiDialog[0] === activeElement ||
8070
$.contains( this.uiDialog[0], activeElement );
8072
this._focusTabbable();
8075
event.preventDefault();
8076
checkFocus.call( this );
8078
// IE <= 8 doesn't prevent moving focus even with event.preventDefault()
8079
// so we check again later
8080
this._delay( checkFocus );
8083
_createWrapper: function() {
8084
this.uiDialog = $("<div>")
8085
.addClass( "ui-dialog ui-widget ui-widget-content ui-corner-all ui-front " +
8086
this.options.dialogClass )
8089
// Setting tabIndex makes the div focusable
8093
.appendTo( this._appendTo() );
8095
this._on( this.uiDialog, {
8096
keydown: function( event ) {
8097
if ( this.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode &&
8098
event.keyCode === $.ui.keyCode.ESCAPE ) {
8099
event.preventDefault();
8100
this.close( event );
8104
// prevent tabbing out of dialogs
8105
if ( event.keyCode !== $.ui.keyCode.TAB || event.isDefaultPrevented() ) {
8108
var tabbables = this.uiDialog.find( ":tabbable" ),
8109
first = tabbables.filter( ":first" ),
8110
last = tabbables.filter( ":last" );
8112
if ( ( event.target === last[0] || event.target === this.uiDialog[0] ) && !event.shiftKey ) {
8113
this._delay(function() {
8116
event.preventDefault();
8117
} else if ( ( event.target === first[0] || event.target === this.uiDialog[0] ) && event.shiftKey ) {
8118
this._delay(function() {
8121
event.preventDefault();
8124
mousedown: function( event ) {
8125
if ( this._moveToTop( event ) ) {
8126
this._focusTabbable();
8131
// We assume that any existing aria-describedby attribute means
8132
// that the dialog content is marked up properly
8133
// otherwise we brute force the content as the description
8134
if ( !this.element.find( "[aria-describedby]" ).length ) {
8135
this.uiDialog.attr({
8136
"aria-describedby": this.element.uniqueId().attr( "id" )
8141
_createTitlebar: function() {
8144
this.uiDialogTitlebar = $( "<div>" )
8145
.addClass( "ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix" )
8146
.prependTo( this.uiDialog );
8147
this._on( this.uiDialogTitlebar, {
8148
mousedown: function( event ) {
8149
// Don't prevent click on close button (#8838)
8150
// Focusing a dialog that is partially scrolled out of view
8151
// causes the browser to scroll it into view, preventing the click event
8152
if ( !$( event.target ).closest( ".ui-dialog-titlebar-close" ) ) {
8153
// Dialog isn't getting focus when dragging (#8063)
8154
this.uiDialog.focus();
8160
// Use type="button" to prevent enter keypresses in textboxes from closing the
8161
// dialog in IE (#9312)
8162
this.uiDialogTitlebarClose = $( "<button type='button'></button>" )
8164
label: this.options.closeText,
8166
primary: "ui-icon-closethick"
8170
.addClass( "ui-dialog-titlebar-close" )
8171
.appendTo( this.uiDialogTitlebar );
8172
this._on( this.uiDialogTitlebarClose, {
8173
click: function( event ) {
8174
event.preventDefault();
8175
this.close( event );
8179
uiDialogTitle = $( "<span>" )
8181
.addClass( "ui-dialog-title" )
8182
.prependTo( this.uiDialogTitlebar );
8183
this._title( uiDialogTitle );
8185
this.uiDialog.attr({
8186
"aria-labelledby": uiDialogTitle.attr( "id" )
8190
_title: function( title ) {
8191
if ( !this.options.title ) {
8192
title.html( " " );
8194
title.text( this.options.title );
8197
_createButtonPane: function() {
8198
this.uiDialogButtonPane = $( "<div>" )
8199
.addClass( "ui-dialog-buttonpane ui-widget-content ui-helper-clearfix" );
8201
this.uiButtonSet = $( "<div>" )
8202
.addClass( "ui-dialog-buttonset" )
8203
.appendTo( this.uiDialogButtonPane );
8205
this._createButtons();
8208
_createButtons: function() {
8210
buttons = this.options.buttons;
8212
// if we already have a button pane, remove it
8213
this.uiDialogButtonPane.remove();
8214
this.uiButtonSet.empty();
8216
if ( $.isEmptyObject( buttons ) || ($.isArray( buttons ) && !buttons.length) ) {
8217
this.uiDialog.removeClass( "ui-dialog-buttons" );
8221
$.each( buttons, function( name, props ) {
8222
var click, buttonOptions;
8223
props = $.isFunction( props ) ?
8224
{ click: props, text: name } :
8226
// Default to a non-submitting button
8227
props = $.extend( { type: "button" }, props );
8228
// Change the context for the click callback to be the main element
8229
click = props.click;
8230
props.click = function() {
8231
click.apply( that.element[ 0 ], arguments );
8235
text: props.showText
8238
delete props.showText;
8239
$( "<button></button>", props )
8240
.button( buttonOptions )
8241
.appendTo( that.uiButtonSet );
8243
this.uiDialog.addClass( "ui-dialog-buttons" );
8244
this.uiDialogButtonPane.appendTo( this.uiDialog );
8247
_makeDraggable: function() {
8249
options = this.options;
8251
function filteredUi( ui ) {
8253
position: ui.position,
8258
this.uiDialog.draggable({
8259
cancel: ".ui-dialog-content, .ui-dialog-titlebar-close",
8260
handle: ".ui-dialog-titlebar",
8261
containment: "document",
8262
start: function( event, ui ) {
8263
$( this ).addClass( "ui-dialog-dragging" );
8264
that._blockFrames();
8265
that._trigger( "dragStart", event, filteredUi( ui ) );
8267
drag: function( event, ui ) {
8268
that._trigger( "drag", event, filteredUi( ui ) );
8270
stop: function( event, ui ) {
8271
var left = ui.offset.left - that.document.scrollLeft(),
8272
top = ui.offset.top - that.document.scrollTop();
8274
options.position = {
8276
at: "left" + (left >= 0 ? "+" : "") + left + " " +
8277
"top" + (top >= 0 ? "+" : "") + top,
8280
$( this ).removeClass( "ui-dialog-dragging" );
8281
that._unblockFrames();
8282
that._trigger( "dragStop", event, filteredUi( ui ) );
8287
_makeResizable: function() {
8289
options = this.options,
8290
handles = options.resizable,
8291
// .ui-resizable has position: relative defined in the stylesheet
8292
// but dialogs have to use absolute or fixed positioning
8293
position = this.uiDialog.css("position"),
8294
resizeHandles = typeof handles === "string" ?
8296
"n,e,s,w,se,sw,ne,nw";
8298
function filteredUi( ui ) {
8300
originalPosition: ui.originalPosition,
8301
originalSize: ui.originalSize,
8302
position: ui.position,
8307
this.uiDialog.resizable({
8308
cancel: ".ui-dialog-content",
8309
containment: "document",
8310
alsoResize: this.element,
8311
maxWidth: options.maxWidth,
8312
maxHeight: options.maxHeight,
8313
minWidth: options.minWidth,
8314
minHeight: this._minHeight(),
8315
handles: resizeHandles,
8316
start: function( event, ui ) {
8317
$( this ).addClass( "ui-dialog-resizing" );
8318
that._blockFrames();
8319
that._trigger( "resizeStart", event, filteredUi( ui ) );
8321
resize: function( event, ui ) {
8322
that._trigger( "resize", event, filteredUi( ui ) );
8324
stop: function( event, ui ) {
8325
var offset = that.uiDialog.offset(),
8326
left = offset.left - that.document.scrollLeft(),
8327
top = offset.top - that.document.scrollTop();
8329
options.height = that.uiDialog.height();
8330
options.width = that.uiDialog.width();
8331
options.position = {
8333
at: "left" + (left >= 0 ? "+" : "") + left + " " +
8334
"top" + (top >= 0 ? "+" : "") + top,
8337
$( this ).removeClass( "ui-dialog-resizing" );
8338
that._unblockFrames();
8339
that._trigger( "resizeStop", event, filteredUi( ui ) );
8342
.css( "position", position );
8345
_trackFocus: function() {
8346
this._on( this.widget(), {
8347
"focusin": function( event ) {
8348
this._untrackInstance();
8349
this._trackingInstances().unshift( this );
8350
this._focusedElement = $( event.target );
8355
_untrackInstance: function() {
8356
var instances = this._trackingInstances(),
8357
exists = $.inArray( this, instances );
8358
if ( exists !== -1 ) {
8359
instances.splice( exists, 1 );
8363
_trackingInstances: function() {
8364
var instances = this.document.data( "ui-dialog-instances" );
8367
this.document.data( "ui-dialog-instances", instances );
8372
_minHeight: function() {
8373
var options = this.options;
8375
return options.height === "auto" ?
8377
Math.min( options.minHeight, options.height );
8380
_position: function() {
8381
// Need to show the dialog to get the actual offset in the position plugin
8382
var isVisible = this.uiDialog.is( ":visible" );
8384
this.uiDialog.show();
8386
this.uiDialog.position( this.options.position );
8388
this.uiDialog.hide();
8392
_setOptions: function( options ) {
8395
resizableOptions = {};
8397
$.each( options, function( key, value ) {
8398
that._setOption( key, value );
8400
if ( key in that.sizeRelatedOptions ) {
8403
if ( key in that.resizableRelatedOptions ) {
8404
resizableOptions[ key ] = value;
8412
if ( this.uiDialog.is( ":data(ui-resizable)" ) ) {
8413
this.uiDialog.resizable( "option", resizableOptions );
8417
_setOption: function( key, value ) {
8418
var isDraggable, isResizable,
8419
uiDialog = this.uiDialog;
8421
if ( key === "dialogClass" ) {
8423
.removeClass( this.options.dialogClass )
8427
if ( key === "disabled" ) {
8431
this._super( key, value );
8433
if ( key === "appendTo" ) {
8434
this.uiDialog.appendTo( this._appendTo() );
8437
if ( key === "buttons" ) {
8438
this._createButtons();
8441
if ( key === "closeText" ) {
8442
this.uiDialogTitlebarClose.button({
8443
// Ensure that we always pass a string
8448
if ( key === "draggable" ) {
8449
isDraggable = uiDialog.is( ":data(ui-draggable)" );
8450
if ( isDraggable && !value ) {
8451
uiDialog.draggable( "destroy" );
8454
if ( !isDraggable && value ) {
8455
this._makeDraggable();
8459
if ( key === "position" ) {
8463
if ( key === "resizable" ) {
8464
// currently resizable, becoming non-resizable
8465
isResizable = uiDialog.is( ":data(ui-resizable)" );
8466
if ( isResizable && !value ) {
8467
uiDialog.resizable( "destroy" );
8470
// currently resizable, changing handles
8471
if ( isResizable && typeof value === "string" ) {
8472
uiDialog.resizable( "option", "handles", value );
8475
// currently non-resizable, becoming resizable
8476
if ( !isResizable && value !== false ) {
8477
this._makeResizable();
8481
if ( key === "title" ) {
8482
this._title( this.uiDialogTitlebar.find( ".ui-dialog-title" ) );
8487
// If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
8488
// divs will both have width and height set, so we need to reset them
8489
var nonContentHeight, minContentHeight, maxContentHeight,
8490
options = this.options;
8492
// Reset content sizing
8493
this.element.show().css({
8500
if ( options.minWidth > options.width ) {
8501
options.width = options.minWidth;
8504
// reset wrapper sizing
8505
// determine the height of all the non-content elements
8506
nonContentHeight = this.uiDialog.css({
8508
width: options.width
8511
minContentHeight = Math.max( 0, options.minHeight - nonContentHeight );
8512
maxContentHeight = typeof options.maxHeight === "number" ?
8513
Math.max( 0, options.maxHeight - nonContentHeight ) :
8516
if ( options.height === "auto" ) {
8518
minHeight: minContentHeight,
8519
maxHeight: maxContentHeight,
8523
this.element.height( Math.max( 0, options.height - nonContentHeight ) );
8526
if ( this.uiDialog.is( ":data(ui-resizable)" ) ) {
8527
this.uiDialog.resizable( "option", "minHeight", this._minHeight() );
8531
_blockFrames: function() {
8532
this.iframeBlocks = this.document.find( "iframe" ).map(function() {
8533
var iframe = $( this );
8537
position: "absolute",
8538
width: iframe.outerWidth(),
8539
height: iframe.outerHeight()
8541
.appendTo( iframe.parent() )
8542
.offset( iframe.offset() )[0];
8546
_unblockFrames: function() {
8547
if ( this.iframeBlocks ) {
8548
this.iframeBlocks.remove();
8549
delete this.iframeBlocks;
8553
_allowInteraction: function( event ) {
8554
if ( $( event.target ).closest( ".ui-dialog" ).length ) {
8558
// TODO: Remove hack when datepicker implements
8559
// the .ui-front logic (#8989)
8560
return !!$( event.target ).closest( ".ui-datepicker" ).length;
8563
_createOverlay: function() {
8564
if ( !this.options.modal ) {
8568
// We use a delay in case the overlay is created from an
8569
// event that we're going to be cancelling (#2804)
8570
var isOpening = true;
8571
this._delay(function() {
8575
if ( !this.document.data( "ui-dialog-overlays" ) ) {
8577
// Prevent use of anchors and inputs
8578
// Using _on() for an event handler shared across many instances is
8579
// safe because the dialogs stack and must be closed in reverse order
8580
this._on( this.document, {
8581
focusin: function( event ) {
8586
if ( !this._allowInteraction( event ) ) {
8587
event.preventDefault();
8588
this._trackingInstances()[ 0 ]._focusTabbable();
8594
this.overlay = $( "<div>" )
8595
.addClass( "ui-widget-overlay ui-front" )
8596
.appendTo( this._appendTo() );
8597
this._on( this.overlay, {
8598
mousedown: "_keepFocus"
8600
this.document.data( "ui-dialog-overlays",
8601
(this.document.data( "ui-dialog-overlays" ) || 0) + 1 );
8604
_destroyOverlay: function() {
8605
if ( !this.options.modal ) {
8609
if ( this.overlay ) {
8610
var overlays = this.document.data( "ui-dialog-overlays" ) - 1;
8614
.unbind( "focusin" )
8615
.removeData( "ui-dialog-overlays" );
8617
this.document.data( "ui-dialog-overlays", overlays );
8620
this.overlay.remove();
8621
this.overlay = null;
8628
* jQuery UI Droppable 1.11.0
8629
* http://jqueryui.com
8631
* Copyright 2014 jQuery Foundation and other contributors
8632
* Released under the MIT license.
8633
* http://jquery.org/license
8635
* http://api.jqueryui.com/droppable/
8639
$.widget( "ui.droppable", {
8641
widgetEventPrefix: "drop",
8649
tolerance: "intersect",
8658
_create: function() {
8664
this.isover = false;
8667
this.accept = $.isFunction( accept ) ? accept : function( d ) {
8668
return d.is( accept );
8671
this.proportions = function( /* valueToWrite */ ) {
8672
if ( arguments.length ) {
8673
// Store the droppable's proportions
8674
proportions = arguments[ 0 ];
8676
// Retrieve or derive the droppable's proportions
8677
return proportions ?
8680
width: this.element[ 0 ].offsetWidth,
8681
height: this.element[ 0 ].offsetHeight
8686
this._addToManager( o.scope );
8688
o.addClasses && this.element.addClass( "ui-droppable" );
8692
_addToManager: function( scope ) {
8693
// Add the reference and positions to the manager
8694
$.ui.ddmanager.droppables[ scope ] = $.ui.ddmanager.droppables[ scope ] || [];
8695
$.ui.ddmanager.droppables[ scope ].push( this );
8698
_splice: function( drop ) {
8700
for ( ; i < drop.length; i++ ) {
8701
if ( drop[ i ] === this ) {
8702
drop.splice( i, 1 );
8707
_destroy: function() {
8708
var drop = $.ui.ddmanager.droppables[ this.options.scope ];
8710
this._splice( drop );
8712
this.element.removeClass( "ui-droppable ui-droppable-disabled" );
8715
_setOption: function( key, value ) {
8717
if ( key === "accept" ) {
8718
this.accept = $.isFunction( value ) ? value : function( d ) {
8719
return d.is( value );
8721
} else if ( key === "scope" ) {
8722
var drop = $.ui.ddmanager.droppables[ this.options.scope ];
8724
this._splice( drop );
8725
this._addToManager( value );
8728
this._super( key, value );
8731
_activate: function( event ) {
8732
var draggable = $.ui.ddmanager.current;
8733
if ( this.options.activeClass ) {
8734
this.element.addClass( this.options.activeClass );
8737
this._trigger( "activate", event, this.ui( draggable ) );
8741
_deactivate: function( event ) {
8742
var draggable = $.ui.ddmanager.current;
8743
if ( this.options.activeClass ) {
8744
this.element.removeClass( this.options.activeClass );
8747
this._trigger( "deactivate", event, this.ui( draggable ) );
8751
_over: function( event ) {
8753
var draggable = $.ui.ddmanager.current;
8755
// Bail if draggable and droppable are same element
8756
if ( !draggable || ( draggable.currentItem || draggable.element )[ 0 ] === this.element[ 0 ] ) {
8760
if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem || draggable.element ) ) ) {
8761
if ( this.options.hoverClass ) {
8762
this.element.addClass( this.options.hoverClass );
8764
this._trigger( "over", event, this.ui( draggable ) );
8769
_out: function( event ) {
8771
var draggable = $.ui.ddmanager.current;
8773
// Bail if draggable and droppable are same element
8774
if ( !draggable || ( draggable.currentItem || draggable.element )[ 0 ] === this.element[ 0 ] ) {
8778
if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem || draggable.element ) ) ) {
8779
if ( this.options.hoverClass ) {
8780
this.element.removeClass( this.options.hoverClass );
8782
this._trigger( "out", event, this.ui( draggable ) );
8787
_drop: function( event, custom ) {
8789
var draggable = custom || $.ui.ddmanager.current,
8790
childrenIntersection = false;
8792
// Bail if draggable and droppable are same element
8793
if ( !draggable || ( draggable.currentItem || draggable.element )[ 0 ] === this.element[ 0 ] ) {
8797
this.element.find( ":data(ui-droppable)" ).not( ".ui-draggable-dragging" ).each(function() {
8798
var inst = $( this ).droppable( "instance" );
8800
inst.options.greedy &&
8801
!inst.options.disabled &&
8802
inst.options.scope === draggable.options.scope &&
8803
inst.accept.call( inst.element[ 0 ], ( draggable.currentItem || draggable.element ) ) &&
8804
$.ui.intersect( draggable, $.extend( inst, { offset: inst.element.offset() } ), inst.options.tolerance )
8805
) { childrenIntersection = true; return false; }
8807
if ( childrenIntersection ) {
8811
if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem || draggable.element ) ) ) {
8812
if ( this.options.activeClass ) {
8813
this.element.removeClass( this.options.activeClass );
8815
if ( this.options.hoverClass ) {
8816
this.element.removeClass( this.options.hoverClass );
8818
this._trigger( "drop", event, this.ui( draggable ) );
8819
return this.element;
8828
draggable: ( c.currentItem || c.element ),
8830
position: c.position,
8831
offset: c.positionAbs
8837
$.ui.intersect = (function() {
8838
function isOverAxis( x, reference, size ) {
8839
return ( x >= reference ) && ( x < ( reference + size ) );
8842
return function( draggable, droppable, toleranceMode ) {
8844
if ( !droppable.offset ) {
8848
var draggableLeft, draggableTop,
8849
x1 = ( draggable.positionAbs || draggable.position.absolute ).left,
8850
y1 = ( draggable.positionAbs || draggable.position.absolute ).top,
8851
x2 = x1 + draggable.helperProportions.width,
8852
y2 = y1 + draggable.helperProportions.height,
8853
l = droppable.offset.left,
8854
t = droppable.offset.top,
8855
r = l + droppable.proportions().width,
8856
b = t + droppable.proportions().height;
8858
switch ( toleranceMode ) {
8860
return ( l <= x1 && x2 <= r && t <= y1 && y2 <= b );
8862
return ( l < x1 + ( draggable.helperProportions.width / 2 ) && // Right Half
8863
x2 - ( draggable.helperProportions.width / 2 ) < r && // Left Half
8864
t < y1 + ( draggable.helperProportions.height / 2 ) && // Bottom Half
8865
y2 - ( draggable.helperProportions.height / 2 ) < b ); // Top Half
8867
draggableLeft = ( ( draggable.positionAbs || draggable.position.absolute ).left + ( draggable.clickOffset || draggable.offset.click ).left );
8868
draggableTop = ( ( draggable.positionAbs || draggable.position.absolute ).top + ( draggable.clickOffset || draggable.offset.click ).top );
8869
return isOverAxis( draggableTop, t, droppable.proportions().height ) && isOverAxis( draggableLeft, l, droppable.proportions().width );
8872
( y1 >= t && y1 <= b ) || // Top edge touching
8873
( y2 >= t && y2 <= b ) || // Bottom edge touching
8874
( y1 < t && y2 > b ) // Surrounded vertically
8876
( x1 >= l && x1 <= r ) || // Left edge touching
8877
( x2 >= l && x2 <= r ) || // Right edge touching
8878
( x1 < l && x2 > r ) // Surrounded horizontally
8887
This manager tracks offsets of draggables and droppables
8891
droppables: { "default": [] },
8892
prepareOffsets: function( t, event ) {
8895
m = $.ui.ddmanager.droppables[ t.options.scope ] || [],
8896
type = event ? event.type : null, // workaround for #2317
8897
list = ( t.currentItem || t.element ).find( ":data(ui-droppable)" ).addBack();
8899
droppablesLoop: for ( i = 0; i < m.length; i++ ) {
8901
// No disabled and non-accepted
8902
if ( m[ i ].options.disabled || ( t && !m[ i ].accept.call( m[ i ].element[ 0 ], ( t.currentItem || t.element ) ) ) ) {
8906
// Filter out elements in the current dragged item
8907
for ( j = 0; j < list.length; j++ ) {
8908
if ( list[ j ] === m[ i ].element[ 0 ] ) {
8909
m[ i ].proportions().height = 0;
8910
continue droppablesLoop;
8914
m[ i ].visible = m[ i ].element.css( "display" ) !== "none";
8915
if ( !m[ i ].visible ) {
8919
// Activate the droppable if used directly from draggables
8920
if ( type === "mousedown" ) {
8921
m[ i ]._activate.call( m[ i ], event );
8924
m[ i ].offset = m[ i ].element.offset();
8925
m[ i ].proportions({ width: m[ i ].element[ 0 ].offsetWidth, height: m[ i ].element[ 0 ].offsetHeight });
8930
drop: function( draggable, event ) {
8932
var dropped = false;
8933
// Create a copy of the droppables in case the list changes during the drop (#9116)
8934
$.each( ( $.ui.ddmanager.droppables[ draggable.options.scope ] || [] ).slice(), function() {
8936
if ( !this.options ) {
8939
if ( !this.options.disabled && this.visible && $.ui.intersect( draggable, this, this.options.tolerance ) ) {
8940
dropped = this._drop.call( this, event ) || dropped;
8943
if ( !this.options.disabled && this.visible && this.accept.call( this.element[ 0 ], ( draggable.currentItem || draggable.element ) ) ) {
8945
this.isover = false;
8946
this._deactivate.call( this, event );
8953
dragStart: function( draggable, event ) {
8954
// Listen for scrolling so that if the dragging causes scrolling the position of the droppables can be recalculated (see #5003)
8955
draggable.element.parentsUntil( "body" ).bind( "scroll.droppable", function() {
8956
if ( !draggable.options.refreshPositions ) {
8957
$.ui.ddmanager.prepareOffsets( draggable, event );
8961
drag: function( draggable, event ) {
8963
// If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse.
8964
if ( draggable.options.refreshPositions ) {
8965
$.ui.ddmanager.prepareOffsets( draggable, event );
8968
// Run through all droppables and check their positions based on specific tolerance options
8969
$.each( $.ui.ddmanager.droppables[ draggable.options.scope ] || [], function() {
8971
if ( this.options.disabled || this.greedyChild || !this.visible ) {
8975
var parentInstance, scope, parent,
8976
intersects = $.ui.intersect( draggable, this, this.options.tolerance ),
8977
c = !intersects && this.isover ? "isout" : ( intersects && !this.isover ? "isover" : null );
8982
if ( this.options.greedy ) {
8983
// find droppable parents with same scope
8984
scope = this.options.scope;
8985
parent = this.element.parents( ":data(ui-droppable)" ).filter(function() {
8986
return $( this ).droppable( "instance" ).options.scope === scope;
8989
if ( parent.length ) {
8990
parentInstance = $( parent[ 0 ] ).droppable( "instance" );
8991
parentInstance.greedyChild = ( c === "isover" );
8995
// we just moved into a greedy child
8996
if ( parentInstance && c === "isover" ) {
8997
parentInstance.isover = false;
8998
parentInstance.isout = true;
8999
parentInstance._out.call( parentInstance, event );
9003
this[c === "isout" ? "isover" : "isout"] = false;
9004
this[c === "isover" ? "_over" : "_out"].call( this, event );
9006
// we just moved out of a greedy child
9007
if ( parentInstance && c === "isout" ) {
9008
parentInstance.isout = false;
9009
parentInstance.isover = true;
9010
parentInstance._over.call( parentInstance, event );
9015
dragStop: function( draggable, event ) {
9016
draggable.element.parentsUntil( "body" ).unbind( "scroll.droppable" );
9017
// Call prepareOffsets one final time since IE does not fire return scroll events when overflow was caused by drag (see #5003)
9018
if ( !draggable.options.refreshPositions ) {
9019
$.ui.ddmanager.prepareOffsets( draggable, event );
9024
var droppable = $.ui.droppable;
9028
* jQuery UI Effects 1.11.0
9029
* http://jqueryui.com
9031
* Copyright 2014 jQuery Foundation and other contributors
9032
* Released under the MIT license.
9033
* http://jquery.org/license
9035
* http://api.jqueryui.com/category/effects-core/
9039
var dataSpace = "ui-effects-";
9046
* jQuery Color Animations v2.1.2
9047
* https://github.com/jquery/jquery-color
9049
* Copyright 2014 jQuery Foundation and other contributors
9050
* Released under the MIT license.
9051
* http://jquery.org/license
9053
* Date: Wed Jan 16 08:47:09 2013 -0600
9055
(function( jQuery, undefined ) {
9057
var stepHooks = "backgroundColor borderBottomColor borderLeftColor borderRightColor borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor",
9059
// plusequals test for += 100 -= 100
9060
rplusequals = /^([\-+])=\s*(\d+\.?\d*)/,
9061
// a set of RE's that can match strings and generate color tuples.
9063
re: /rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
9064
parse: function( execResult ) {
9073
re: /rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
9074
parse: function( execResult ) {
9076
execResult[ 1 ] * 2.55,
9077
execResult[ 2 ] * 2.55,
9078
execResult[ 3 ] * 2.55,
9083
// this regex ignores A-F because it's compared against an already lowercased string
9084
re: /#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/,
9085
parse: function( execResult ) {
9087
parseInt( execResult[ 1 ], 16 ),
9088
parseInt( execResult[ 2 ], 16 ),
9089
parseInt( execResult[ 3 ], 16 )
9093
// this regex ignores A-F because it's compared against an already lowercased string
9094
re: /#([a-f0-9])([a-f0-9])([a-f0-9])/,
9095
parse: function( execResult ) {
9097
parseInt( execResult[ 1 ] + execResult[ 1 ], 16 ),
9098
parseInt( execResult[ 2 ] + execResult[ 2 ], 16 ),
9099
parseInt( execResult[ 3 ] + execResult[ 3 ], 16 )
9103
re: /hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
9105
parse: function( execResult ) {
9108
execResult[ 2 ] / 100,
9109
execResult[ 3 ] / 100,
9116
color = jQuery.Color = function( color, green, blue, alpha ) {
9117
return new jQuery.Color.fn.parse( color, green, blue, alpha );
9167
support = color.support = {},
9169
// element for support tests
9170
supportElem = jQuery( "<p>" )[ 0 ],
9172
// colors = jQuery.Color.names
9175
// local aliases of functions called often
9178
// determine rgba support immediately
9179
supportElem.style.cssText = "background-color:rgba(1,1,1,.5)";
9180
support.rgba = supportElem.style.backgroundColor.indexOf( "rgba" ) > -1;
9182
// define cache name and alpha properties
9183
// for rgba and hsla spaces
9184
each( spaces, function( spaceName, space ) {
9185
space.cache = "_" + spaceName;
9186
space.props.alpha = {
9193
function clamp( value, prop, allowEmpty ) {
9194
var type = propTypes[ prop.type ] || {};
9196
if ( value == null ) {
9197
return (allowEmpty || !prop.def) ? null : prop.def;
9200
// ~~ is an short way of doing floor for positive numbers
9201
value = type.floor ? ~~value : parseFloat( value );
9203
// IE will pass in empty strings as value for alpha,
9204
// which will hit this case
9205
if ( isNaN( value ) ) {
9210
// we add mod before modding to make sure that negatives values
9211
// get converted properly: -10 -> 350
9212
return (value + type.mod) % type.mod;
9215
// for now all property types without mod have min and max
9216
return 0 > value ? 0 : type.max < value ? type.max : value;
9219
function stringParse( string ) {
9221
rgba = inst._rgba = [];
9223
string = string.toLowerCase();
9225
each( stringParsers, function( i, parser ) {
9227
match = parser.re.exec( string ),
9228
values = match && parser.parse( match ),
9229
spaceName = parser.space || "rgba";
9232
parsed = inst[ spaceName ]( values );
9234
// if this was an rgba parse the assignment might happen twice
9236
inst[ spaces[ spaceName ].cache ] = parsed[ spaces[ spaceName ].cache ];
9237
rgba = inst._rgba = parsed._rgba;
9239
// exit each( stringParsers ) here because we matched
9244
// Found a stringParser that handled it
9245
if ( rgba.length ) {
9247
// if this came from a parsed string, force "transparent" when alpha is 0
9248
// chrome, (and maybe others) return "transparent" as rgba(0,0,0,0)
9249
if ( rgba.join() === "0,0,0,0" ) {
9250
jQuery.extend( rgba, colors.transparent );
9256
return colors[ string ];
9259
color.fn = jQuery.extend( color.prototype, {
9260
parse: function( red, green, blue, alpha ) {
9261
if ( red === undefined ) {
9262
this._rgba = [ null, null, null, null ];
9265
if ( red.jquery || red.nodeType ) {
9266
red = jQuery( red ).css( green );
9271
type = jQuery.type( red ),
9272
rgba = this._rgba = [];
9274
// more than 1 argument specified - assume ( red, green, blue, alpha )
9275
if ( green !== undefined ) {
9276
red = [ red, green, blue, alpha ];
9280
if ( type === "string" ) {
9281
return this.parse( stringParse( red ) || colors._default );
9284
if ( type === "array" ) {
9285
each( spaces.rgba.props, function( key, prop ) {
9286
rgba[ prop.idx ] = clamp( red[ prop.idx ], prop );
9291
if ( type === "object" ) {
9292
if ( red instanceof color ) {
9293
each( spaces, function( spaceName, space ) {
9294
if ( red[ space.cache ] ) {
9295
inst[ space.cache ] = red[ space.cache ].slice();
9299
each( spaces, function( spaceName, space ) {
9300
var cache = space.cache;
9301
each( space.props, function( key, prop ) {
9303
// if the cache doesn't exist, and we know how to convert
9304
if ( !inst[ cache ] && space.to ) {
9306
// if the value was null, we don't need to copy it
9307
// if the key was alpha, we don't need to copy it either
9308
if ( key === "alpha" || red[ key ] == null ) {
9311
inst[ cache ] = space.to( inst._rgba );
9314
// this is the only case where we allow nulls for ALL properties.
9315
// call clamp with alwaysAllowEmpty
9316
inst[ cache ][ prop.idx ] = clamp( red[ key ], prop, true );
9319
// everything defined but alpha?
9320
if ( inst[ cache ] && jQuery.inArray( null, inst[ cache ].slice( 0, 3 ) ) < 0 ) {
9321
// use the default of 1
9322
inst[ cache ][ 3 ] = 1;
9324
inst._rgba = space.from( inst[ cache ] );
9332
is: function( compare ) {
9333
var is = color( compare ),
9337
each( spaces, function( _, space ) {
9339
isCache = is[ space.cache ];
9341
localCache = inst[ space.cache ] || space.to && space.to( inst._rgba ) || [];
9342
each( space.props, function( _, prop ) {
9343
if ( isCache[ prop.idx ] != null ) {
9344
same = ( isCache[ prop.idx ] === localCache[ prop.idx ] );
9353
_space: function() {
9356
each( spaces, function( spaceName, space ) {
9357
if ( inst[ space.cache ] ) {
9358
used.push( spaceName );
9363
transition: function( other, distance ) {
9364
var end = color( other ),
9365
spaceName = end._space(),
9366
space = spaces[ spaceName ],
9367
startColor = this.alpha() === 0 ? color( "transparent" ) : this,
9368
start = startColor[ space.cache ] || space.to( startColor._rgba ),
9369
result = start.slice();
9371
end = end[ space.cache ];
9372
each( space.props, function( key, prop ) {
9373
var index = prop.idx,
9374
startValue = start[ index ],
9375
endValue = end[ index ],
9376
type = propTypes[ prop.type ] || {};
9378
// if null, don't override start value
9379
if ( endValue === null ) {
9382
// if null - use end
9383
if ( startValue === null ) {
9384
result[ index ] = endValue;
9387
if ( endValue - startValue > type.mod / 2 ) {
9388
startValue += type.mod;
9389
} else if ( startValue - endValue > type.mod / 2 ) {
9390
startValue -= type.mod;
9393
result[ index ] = clamp( ( endValue - startValue ) * distance + startValue, prop );
9396
return this[ spaceName ]( result );
9398
blend: function( opaque ) {
9399
// if we are already opaque - return ourself
9400
if ( this._rgba[ 3 ] === 1 ) {
9404
var rgb = this._rgba.slice(),
9406
blend = color( opaque )._rgba;
9408
return color( jQuery.map( rgb, function( v, i ) {
9409
return ( 1 - a ) * blend[ i ] + a * v;
9412
toRgbaString: function() {
9413
var prefix = "rgba(",
9414
rgba = jQuery.map( this._rgba, function( v, i ) {
9415
return v == null ? ( i > 2 ? 1 : 0 ) : v;
9418
if ( rgba[ 3 ] === 1 ) {
9423
return prefix + rgba.join() + ")";
9425
toHslaString: function() {
9426
var prefix = "hsla(",
9427
hsla = jQuery.map( this.hsla(), function( v, i ) {
9434
v = Math.round( v * 100 ) + "%";
9439
if ( hsla[ 3 ] === 1 ) {
9443
return prefix + hsla.join() + ")";
9445
toHexString: function( includeAlpha ) {
9446
var rgba = this._rgba.slice(),
9449
if ( includeAlpha ) {
9450
rgba.push( ~~( alpha * 255 ) );
9453
return "#" + jQuery.map( rgba, function( v ) {
9455
// default to 0 when nulls exist
9456
v = ( v || 0 ).toString( 16 );
9457
return v.length === 1 ? "0" + v : v;
9460
toString: function() {
9461
return this._rgba[ 3 ] === 0 ? "transparent" : this.toRgbaString();
9464
color.fn.parse.prototype = color.fn;
9466
// hsla conversions adapted from:
9467
// https://code.google.com/p/maashaack/source/browse/packages/graphics/trunk/src/graphics/colors/HUE2RGB.as?r=5021
9469
function hue2rgb( p, q, h ) {
9472
return p + ( q - p ) * h * 6;
9478
return p + ( q - p ) * ( ( 2 / 3 ) - h ) * 6;
9483
spaces.hsla.to = function( rgba ) {
9484
if ( rgba[ 0 ] == null || rgba[ 1 ] == null || rgba[ 2 ] == null ) {
9485
return [ null, null, null, rgba[ 3 ] ];
9487
var r = rgba[ 0 ] / 255,
9488
g = rgba[ 1 ] / 255,
9489
b = rgba[ 2 ] / 255,
9491
max = Math.max( r, g, b ),
9492
min = Math.min( r, g, b ),
9498
if ( min === max ) {
9500
} else if ( r === max ) {
9501
h = ( 60 * ( g - b ) / diff ) + 360;
9502
} else if ( g === max ) {
9503
h = ( 60 * ( b - r ) / diff ) + 120;
9505
h = ( 60 * ( r - g ) / diff ) + 240;
9508
// chroma (diff) == 0 means greyscale which, by definition, saturation = 0%
9509
// otherwise, saturation is based on the ratio of chroma (diff) to lightness (add)
9512
} else if ( l <= 0.5 ) {
9515
s = diff / ( 2 - add );
9517
return [ Math.round(h) % 360, s, l, a == null ? 1 : a ];
9520
spaces.hsla.from = function( hsla ) {
9521
if ( hsla[ 0 ] == null || hsla[ 1 ] == null || hsla[ 2 ] == null ) {
9522
return [ null, null, null, hsla[ 3 ] ];
9524
var h = hsla[ 0 ] / 360,
9528
q = l <= 0.5 ? l * ( 1 + s ) : l + s - l * s,
9532
Math.round( hue2rgb( p, q, h + ( 1 / 3 ) ) * 255 ),
9533
Math.round( hue2rgb( p, q, h ) * 255 ),
9534
Math.round( hue2rgb( p, q, h - ( 1 / 3 ) ) * 255 ),
9539
each( spaces, function( spaceName, space ) {
9540
var props = space.props,
9541
cache = space.cache,
9545
// makes rgba() and hsla()
9546
color.fn[ spaceName ] = function( value ) {
9548
// generate a cache for this space if it doesn't exist
9549
if ( to && !this[ cache ] ) {
9550
this[ cache ] = to( this._rgba );
9552
if ( value === undefined ) {
9553
return this[ cache ].slice();
9557
type = jQuery.type( value ),
9558
arr = ( type === "array" || type === "object" ) ? value : arguments,
9559
local = this[ cache ].slice();
9561
each( props, function( key, prop ) {
9562
var val = arr[ type === "object" ? key : prop.idx ];
9563
if ( val == null ) {
9564
val = local[ prop.idx ];
9566
local[ prop.idx ] = clamp( val, prop );
9570
ret = color( from( local ) );
9571
ret[ cache ] = local;
9574
return color( local );
9578
// makes red() green() blue() alpha() hue() saturation() lightness()
9579
each( props, function( key, prop ) {
9580
// alpha is included in more than one space
9581
if ( color.fn[ key ] ) {
9584
color.fn[ key ] = function( value ) {
9585
var vtype = jQuery.type( value ),
9586
fn = ( key === "alpha" ? ( this._hsla ? "hsla" : "rgba" ) : spaceName ),
9587
local = this[ fn ](),
9588
cur = local[ prop.idx ],
9591
if ( vtype === "undefined" ) {
9595
if ( vtype === "function" ) {
9596
value = value.call( this, cur );
9597
vtype = jQuery.type( value );
9599
if ( value == null && prop.empty ) {
9602
if ( vtype === "string" ) {
9603
match = rplusequals.exec( value );
9605
value = cur + parseFloat( match[ 2 ] ) * ( match[ 1 ] === "+" ? 1 : -1 );
9608
local[ prop.idx ] = value;
9609
return this[ fn ]( local );
9614
// add cssHook and .fx.step function for each named hook.
9615
// accept a space separated string of properties
9616
color.hook = function( hook ) {
9617
var hooks = hook.split( " " );
9618
each( hooks, function( i, hook ) {
9619
jQuery.cssHooks[ hook ] = {
9620
set: function( elem, value ) {
9621
var parsed, curElem,
9622
backgroundColor = "";
9624
if ( value !== "transparent" && ( jQuery.type( value ) !== "string" || ( parsed = stringParse( value ) ) ) ) {
9625
value = color( parsed || value );
9626
if ( !support.rgba && value._rgba[ 3 ] !== 1 ) {
9627
curElem = hook === "backgroundColor" ? elem.parentNode : elem;
9629
(backgroundColor === "" || backgroundColor === "transparent") &&
9630
curElem && curElem.style
9633
backgroundColor = jQuery.css( curElem, "backgroundColor" );
9634
curElem = curElem.parentNode;
9639
value = value.blend( backgroundColor && backgroundColor !== "transparent" ?
9644
value = value.toRgbaString();
9647
elem.style[ hook ] = value;
9649
// wrapped to prevent IE from throwing errors on "invalid" values like 'auto' or 'inherit'
9653
jQuery.fx.step[ hook ] = function( fx ) {
9654
if ( !fx.colorInit ) {
9655
fx.start = color( fx.elem, hook );
9656
fx.end = color( fx.end );
9657
fx.colorInit = true;
9659
jQuery.cssHooks[ hook ].set( fx.elem, fx.start.transition( fx.end, fx.pos ) );
9665
color.hook( stepHooks );
9667
jQuery.cssHooks.borderColor = {
9668
expand: function( value ) {
9671
each( [ "Top", "Right", "Bottom", "Left" ], function( i, part ) {
9672
expanded[ "border" + part + "Color" ] = value;
9678
// Basic color names only.
9679
// Usage of any of the other color names requires adding yourself or including
9680
// jquery.color.svg-names.js.
9681
colors = jQuery.Color.names = {
9682
// 4.1. Basic color keywords
9700
// 4.2.3. "transparent" color keyword
9701
transparent: [ null, null, null, 0 ],
9708
/******************************************************************************/
9709
/****************************** CLASS ANIMATIONS ******************************/
9710
/******************************************************************************/
9713
var classAnimationActions = [ "add", "remove", "toggle" ],
9726
$.each([ "borderLeftStyle", "borderRightStyle", "borderBottomStyle", "borderTopStyle" ], function( _, prop ) {
9727
$.fx.step[ prop ] = function( fx ) {
9728
if ( fx.end !== "none" && !fx.setAttr || fx.pos === 1 && !fx.setAttr ) {
9729
jQuery.style( fx.elem, prop, fx.end );
9735
function getElementStyles( elem ) {
9737
style = elem.ownerDocument.defaultView ?
9738
elem.ownerDocument.defaultView.getComputedStyle( elem, null ) :
9742
if ( style && style.length && style[ 0 ] && style[ style[ 0 ] ] ) {
9746
if ( typeof style[ key ] === "string" ) {
9747
styles[ $.camelCase( key ) ] = style[ key ];
9750
// support: Opera, IE <9
9752
for ( key in style ) {
9753
if ( typeof style[ key ] === "string" ) {
9754
styles[ key ] = style[ key ];
9762
function styleDifference( oldStyle, newStyle ) {
9766
for ( name in newStyle ) {
9767
value = newStyle[ name ];
9768
if ( oldStyle[ name ] !== value ) {
9769
if ( !shorthandStyles[ name ] ) {
9770
if ( $.fx.step[ name ] || !isNaN( parseFloat( value ) ) ) {
9771
diff[ name ] = value;
9780
// support: jQuery <1.8
9781
if ( !$.fn.addBack ) {
9782
$.fn.addBack = function( selector ) {
9783
return this.add( selector == null ?
9784
this.prevObject : this.prevObject.filter( selector )
9789
$.effects.animateClass = function( value, duration, easing, callback ) {
9790
var o = $.speed( duration, easing, callback );
9792
return this.queue( function() {
9793
var animated = $( this ),
9794
baseClass = animated.attr( "class" ) || "",
9796
allAnimations = o.children ? animated.find( "*" ).addBack() : animated;
9798
// map the animated objects to store the original styles.
9799
allAnimations = allAnimations.map(function() {
9803
start: getElementStyles( this )
9807
// apply class change
9808
applyClassChange = function() {
9809
$.each( classAnimationActions, function(i, action) {
9810
if ( value[ action ] ) {
9811
animated[ action + "Class" ]( value[ action ] );
9817
// map all animated objects again - calculate new styles and diff
9818
allAnimations = allAnimations.map(function() {
9819
this.end = getElementStyles( this.el[ 0 ] );
9820
this.diff = styleDifference( this.start, this.end );
9824
// apply original class
9825
animated.attr( "class", baseClass );
9827
// map all animated objects again - this time collecting a promise
9828
allAnimations = allAnimations.map(function() {
9829
var styleInfo = this,
9831
opts = $.extend({}, o, {
9833
complete: function() {
9834
dfd.resolve( styleInfo );
9838
this.el.animate( this.diff, opts );
9839
return dfd.promise();
9842
// once all animations have completed:
9843
$.when.apply( $, allAnimations.get() ).done(function() {
9845
// set the final class
9848
// for each animated element,
9849
// clear all css properties that were animated
9850
$.each( arguments, function() {
9852
$.each( this.diff, function(key) {
9857
// this is guarnteed to be there if you use jQuery.speed()
9858
// it also handles dequeuing the next anim...
9859
o.complete.call( animated[ 0 ] );
9865
addClass: (function( orig ) {
9866
return function( classNames, speed, easing, callback ) {
9868
$.effects.animateClass.call( this,
9869
{ add: classNames }, speed, easing, callback ) :
9870
orig.apply( this, arguments );
9872
})( $.fn.addClass ),
9874
removeClass: (function( orig ) {
9875
return function( classNames, speed, easing, callback ) {
9876
return arguments.length > 1 ?
9877
$.effects.animateClass.call( this,
9878
{ remove: classNames }, speed, easing, callback ) :
9879
orig.apply( this, arguments );
9881
})( $.fn.removeClass ),
9883
toggleClass: (function( orig ) {
9884
return function( classNames, force, speed, easing, callback ) {
9885
if ( typeof force === "boolean" || force === undefined ) {
9887
// without speed parameter
9888
return orig.apply( this, arguments );
9890
return $.effects.animateClass.call( this,
9891
(force ? { add: classNames } : { remove: classNames }),
9892
speed, easing, callback );
9895
// without force parameter
9896
return $.effects.animateClass.call( this,
9897
{ toggle: classNames }, force, speed, easing );
9900
})( $.fn.toggleClass ),
9902
switchClass: function( remove, add, speed, easing, callback) {
9903
return $.effects.animateClass.call( this, {
9906
}, speed, easing, callback );
9912
/******************************************************************************/
9913
/*********************************** EFFECTS **********************************/
9914
/******************************************************************************/
9918
$.extend( $.effects, {
9921
// Saves a set of properties in a data storage
9922
save: function( element, set ) {
9923
for ( var i = 0; i < set.length; i++ ) {
9924
if ( set[ i ] !== null ) {
9925
element.data( dataSpace + set[ i ], element[ 0 ].style[ set[ i ] ] );
9930
// Restores a set of previously saved properties from a data storage
9931
restore: function( element, set ) {
9933
for ( i = 0; i < set.length; i++ ) {
9934
if ( set[ i ] !== null ) {
9935
val = element.data( dataSpace + set[ i ] );
9936
// support: jQuery 1.6.2
9937
// http://bugs.jquery.com/ticket/9917
9938
// jQuery 1.6.2 incorrectly returns undefined for any falsy value.
9939
// We can't differentiate between "" and 0 here, so we just assume
9940
// empty string since it's likely to be a more common value...
9941
if ( val === undefined ) {
9944
element.css( set[ i ], val );
9949
setMode: function( el, mode ) {
9950
if (mode === "toggle") {
9951
mode = el.is( ":hidden" ) ? "show" : "hide";
9956
// Translates a [top,left] array into a baseline value
9957
// this should be a little more flexible in the future to handle a string & hash
9958
getBaseline: function( origin, original ) {
9960
switch ( origin[ 0 ] ) {
9961
case "top": y = 0; break;
9962
case "middle": y = 0.5; break;
9963
case "bottom": y = 1; break;
9964
default: y = origin[ 0 ] / original.height;
9966
switch ( origin[ 1 ] ) {
9967
case "left": x = 0; break;
9968
case "center": x = 0.5; break;
9969
case "right": x = 1; break;
9970
default: x = origin[ 1 ] / original.width;
9978
// Wraps the element around a wrapper that copies position properties
9979
createWrapper: function( element ) {
9981
// if the element is already wrapped, return it
9982
if ( element.parent().is( ".ui-effects-wrapper" )) {
9983
return element.parent();
9988
width: element.outerWidth(true),
9989
height: element.outerHeight(true),
9990
"float": element.css( "float" )
9992
wrapper = $( "<div></div>" )
9993
.addClass( "ui-effects-wrapper" )
9996
background: "transparent",
10001
// Store the size in case width/height are defined in % - Fixes #5245
10003
width: element.width(),
10004
height: element.height()
10006
active = document.activeElement;
10008
// support: Firefox
10009
// Firefox incorrectly exposes anonymous content
10010
// https://bugzilla.mozilla.org/show_bug.cgi?id=561664
10014
active = document.body;
10017
element.wrap( wrapper );
10019
// Fixes #7595 - Elements lose focus when wrapped.
10020
if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
10021
$( active ).focus();
10024
wrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually lose the reference to the wrapped element
10026
// transfer positioning properties to the wrapper
10027
if ( element.css( "position" ) === "static" ) {
10028
wrapper.css({ position: "relative" });
10029
element.css({ position: "relative" });
10032
position: element.css( "position" ),
10033
zIndex: element.css( "z-index" )
10035
$.each([ "top", "left", "bottom", "right" ], function(i, pos) {
10036
props[ pos ] = element.css( pos );
10037
if ( isNaN( parseInt( props[ pos ], 10 ) ) ) {
10038
props[ pos ] = "auto";
10042
position: "relative",
10051
return wrapper.css( props ).show();
10054
removeWrapper: function( element ) {
10055
var active = document.activeElement;
10057
if ( element.parent().is( ".ui-effects-wrapper" ) ) {
10058
element.parent().replaceWith( element );
10060
// Fixes #7595 - Elements lose focus when wrapped.
10061
if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
10062
$( active ).focus();
10069
setTransition: function( element, list, factor, value ) {
10070
value = value || {};
10071
$.each( list, function( i, x ) {
10072
var unit = element.cssUnit( x );
10073
if ( unit[ 0 ] > 0 ) {
10074
value[ x ] = unit[ 0 ] * factor + unit[ 1 ];
10081
// return an effect options object for the given parameters:
10082
function _normalizeArguments( effect, options, speed, callback ) {
10084
// allow passing all options as the first parameter
10085
if ( $.isPlainObject( effect ) ) {
10087
effect = effect.effect;
10090
// convert to an object
10091
effect = { effect: effect };
10093
// catch (effect, null, ...)
10094
if ( options == null ) {
10098
// catch (effect, callback)
10099
if ( $.isFunction( options ) ) {
10100
callback = options;
10105
// catch (effect, speed, ?)
10106
if ( typeof options === "number" || $.fx.speeds[ options ] ) {
10112
// catch (effect, options, callback)
10113
if ( $.isFunction( speed ) ) {
10118
// add options to effect
10120
$.extend( effect, options );
10123
speed = speed || options.duration;
10124
effect.duration = $.fx.off ? 0 :
10125
typeof speed === "number" ? speed :
10126
speed in $.fx.speeds ? $.fx.speeds[ speed ] :
10127
$.fx.speeds._default;
10129
effect.complete = callback || options.complete;
10134
function standardAnimationOption( option ) {
10135
// Valid standard speeds (nothing, number, named speed)
10136
if ( !option || typeof option === "number" || $.fx.speeds[ option ] ) {
10140
// Invalid strings - treat as "normal" speed
10141
if ( typeof option === "string" && !$.effects.effect[ option ] ) {
10145
// Complete callback
10146
if ( $.isFunction( option ) ) {
10150
// Options hash (but not naming an effect)
10151
if ( typeof option === "object" && !option.effect ) {
10155
// Didn't match any standard API
10160
effect: function( /* effect, options, speed, callback */ ) {
10161
var args = _normalizeArguments.apply( this, arguments ),
10163
queue = args.queue,
10164
effectMethod = $.effects.effect[ args.effect ];
10166
if ( $.fx.off || !effectMethod ) {
10167
// delegate to the original method (e.g., .show()) if possible
10169
return this[ mode ]( args.duration, args.complete );
10171
return this.each( function() {
10172
if ( args.complete ) {
10173
args.complete.call( this );
10179
function run( next ) {
10180
var elem = $( this ),
10181
complete = args.complete,
10185
if ( $.isFunction( complete ) ) {
10186
complete.call( elem[0] );
10188
if ( $.isFunction( next ) ) {
10193
// If the element already has the correct final state, delegate to
10194
// the core methods so the internal tracking of "olddisplay" works.
10195
if ( elem.is( ":hidden" ) ? mode === "hide" : mode === "show" ) {
10199
effectMethod.call( elem[0], args, done );
10203
return queue === false ? this.each( run ) : this.queue( queue || "fx", run );
10206
show: (function( orig ) {
10207
return function( option ) {
10208
if ( standardAnimationOption( option ) ) {
10209
return orig.apply( this, arguments );
10211
var args = _normalizeArguments.apply( this, arguments );
10212
args.mode = "show";
10213
return this.effect.call( this, args );
10218
hide: (function( orig ) {
10219
return function( option ) {
10220
if ( standardAnimationOption( option ) ) {
10221
return orig.apply( this, arguments );
10223
var args = _normalizeArguments.apply( this, arguments );
10224
args.mode = "hide";
10225
return this.effect.call( this, args );
10230
toggle: (function( orig ) {
10231
return function( option ) {
10232
if ( standardAnimationOption( option ) || typeof option === "boolean" ) {
10233
return orig.apply( this, arguments );
10235
var args = _normalizeArguments.apply( this, arguments );
10236
args.mode = "toggle";
10237
return this.effect.call( this, args );
10242
// helper functions
10243
cssUnit: function(key) {
10244
var style = this.css( key ),
10247
$.each( [ "em", "px", "%", "pt" ], function( i, unit ) {
10248
if ( style.indexOf( unit ) > 0 ) {
10249
val = [ parseFloat( style ), unit ];
10258
/******************************************************************************/
10259
/*********************************** EASING ***********************************/
10260
/******************************************************************************/
10264
// based on easing equations from Robert Penner (http://www.robertpenner.com/easing)
10266
var baseEasings = {};
10268
$.each( [ "Quad", "Cubic", "Quart", "Quint", "Expo" ], function( i, name ) {
10269
baseEasings[ name ] = function( p ) {
10270
return Math.pow( p, i + 2 );
10274
$.extend( baseEasings, {
10275
Sine: function( p ) {
10276
return 1 - Math.cos( p * Math.PI / 2 );
10278
Circ: function( p ) {
10279
return 1 - Math.sqrt( 1 - p * p );
10281
Elastic: function( p ) {
10282
return p === 0 || p === 1 ? p :
10283
-Math.pow( 2, 8 * (p - 1) ) * Math.sin( ( (p - 1) * 80 - 7.5 ) * Math.PI / 15 );
10285
Back: function( p ) {
10286
return p * p * ( 3 * p - 2 );
10288
Bounce: function( p ) {
10292
while ( p < ( ( pow2 = Math.pow( 2, --bounce ) ) - 1 ) / 11 ) {}
10293
return 1 / Math.pow( 4, 3 - bounce ) - 7.5625 * Math.pow( ( pow2 * 3 - 2 ) / 22 - p, 2 );
10297
$.each( baseEasings, function( name, easeIn ) {
10298
$.easing[ "easeIn" + name ] = easeIn;
10299
$.easing[ "easeOut" + name ] = function( p ) {
10300
return 1 - easeIn( 1 - p );
10302
$.easing[ "easeInOut" + name ] = function( p ) {
10304
easeIn( p * 2 ) / 2 :
10305
1 - easeIn( p * -2 + 2 ) / 2;
10311
var effect = $.effects;
10315
* jQuery UI Effects Blind 1.11.0
10316
* http://jqueryui.com
10318
* Copyright 2014 jQuery Foundation and other contributors
10319
* Released under the MIT license.
10320
* http://jquery.org/license
10322
* http://api.jqueryui.com/blind-effect/
10326
var effectBlind = $.effects.effect.blind = function( o, done ) {
10328
var el = $( this ),
10329
rvertical = /up|down|vertical/,
10330
rpositivemotion = /up|left|vertical|horizontal/,
10331
props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
10332
mode = $.effects.setMode( el, o.mode || "hide" ),
10333
direction = o.direction || "up",
10334
vertical = rvertical.test( direction ),
10335
ref = vertical ? "height" : "width",
10336
ref2 = vertical ? "top" : "left",
10337
motion = rpositivemotion.test( direction ),
10339
show = mode === "show",
10340
wrapper, distance, margin;
10342
// if already wrapped, the wrapper's properties are my property. #6245
10343
if ( el.parent().is( ".ui-effects-wrapper" ) ) {
10344
$.effects.save( el.parent(), props );
10346
$.effects.save( el, props );
10349
wrapper = $.effects.createWrapper( el ).css({
10353
distance = wrapper[ ref ]();
10354
margin = parseFloat( wrapper.css( ref2 ) ) || 0;
10356
animation[ ref ] = show ? distance : 0;
10359
.css( vertical ? "bottom" : "right", 0 )
10360
.css( vertical ? "top" : "left", "auto" )
10361
.css({ position: "absolute" });
10363
animation[ ref2 ] = show ? margin : distance + margin;
10366
// start at 0 if we are showing
10368
wrapper.css( ref, 0 );
10370
wrapper.css( ref2, margin + distance );
10375
wrapper.animate( animation, {
10376
duration: o.duration,
10379
complete: function() {
10380
if ( mode === "hide" ) {
10383
$.effects.restore( el, props );
10384
$.effects.removeWrapper( el );
10392
* jQuery UI Effects Bounce 1.11.0
10393
* http://jqueryui.com
10395
* Copyright 2014 jQuery Foundation and other contributors
10396
* Released under the MIT license.
10397
* http://jquery.org/license
10399
* http://api.jqueryui.com/bounce-effect/
10403
var effectBounce = $.effects.effect.bounce = function( o, done ) {
10404
var el = $( this ),
10405
props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
10408
mode = $.effects.setMode( el, o.mode || "effect" ),
10409
hide = mode === "hide",
10410
show = mode === "show",
10411
direction = o.direction || "up",
10412
distance = o.distance,
10413
times = o.times || 5,
10415
// number of internal animations
10416
anims = times * 2 + ( show || hide ? 1 : 0 ),
10417
speed = o.duration / anims,
10421
ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
10422
motion = ( direction === "up" || direction === "left" ),
10427
// we will need to re-assemble the queue to stack our animations in place
10428
queue = el.queue(),
10429
queuelen = queue.length;
10431
// Avoid touching opacity to prevent clearType and PNG issues in IE
10432
if ( show || hide ) {
10433
props.push( "opacity" );
10436
$.effects.save( el, props );
10438
$.effects.createWrapper( el ); // Create Wrapper
10440
// default distance for the BIGGEST bounce is the outer Distance / 3
10442
distance = el[ ref === "top" ? "outerHeight" : "outerWidth" ]() / 3;
10446
downAnim = { opacity: 1 };
10447
downAnim[ ref ] = 0;
10449
// if we are showing, force opacity 0 and set the initial position
10450
// then do the "first" animation
10451
el.css( "opacity", 0 )
10452
.css( ref, motion ? -distance * 2 : distance * 2 )
10453
.animate( downAnim, speed, easing );
10456
// start at the smallest distance if we are hiding
10458
distance = distance / Math.pow( 2, times - 1 );
10462
downAnim[ ref ] = 0;
10463
// Bounces up/down/left/right then back to 0 -- times * 2 animations happen here
10464
for ( i = 0; i < times; i++ ) {
10466
upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance;
10468
el.animate( upAnim, speed, easing )
10469
.animate( downAnim, speed, easing );
10471
distance = hide ? distance * 2 : distance / 2;
10474
// Last Bounce when Hiding
10476
upAnim = { opacity: 0 };
10477
upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance;
10479
el.animate( upAnim, speed, easing );
10482
el.queue(function() {
10486
$.effects.restore( el, props );
10487
$.effects.removeWrapper( el );
10491
// inject all the animations we just queued to be first in line (after "inprogress")
10492
if ( queuelen > 1) {
10493
queue.splice.apply( queue,
10494
[ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) );
10502
* jQuery UI Effects Clip 1.11.0
10503
* http://jqueryui.com
10505
* Copyright 2014 jQuery Foundation and other contributors
10506
* Released under the MIT license.
10507
* http://jquery.org/license
10509
* http://api.jqueryui.com/clip-effect/
10513
var effectClip = $.effects.effect.clip = function( o, done ) {
10515
var el = $( this ),
10516
props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
10517
mode = $.effects.setMode( el, o.mode || "hide" ),
10518
show = mode === "show",
10519
direction = o.direction || "vertical",
10520
vert = direction === "vertical",
10521
size = vert ? "height" : "width",
10522
position = vert ? "top" : "left",
10524
wrapper, animate, distance;
10527
$.effects.save( el, props );
10531
wrapper = $.effects.createWrapper( el ).css({
10534
animate = ( el[0].tagName === "IMG" ) ? wrapper : el;
10535
distance = animate[ size ]();
10539
animate.css( size, 0 );
10540
animate.css( position, distance / 2 );
10543
// Create Animation Object:
10544
animation[ size ] = show ? distance : 0;
10545
animation[ position ] = show ? 0 : distance / 2;
10548
animate.animate( animation, {
10550
duration: o.duration,
10552
complete: function() {
10556
$.effects.restore( el, props );
10557
$.effects.removeWrapper( el );
10566
* jQuery UI Effects Drop 1.11.0
10567
* http://jqueryui.com
10569
* Copyright 2014 jQuery Foundation and other contributors
10570
* Released under the MIT license.
10571
* http://jquery.org/license
10573
* http://api.jqueryui.com/drop-effect/
10577
var effectDrop = $.effects.effect.drop = function( o, done ) {
10579
var el = $( this ),
10580
props = [ "position", "top", "bottom", "left", "right", "opacity", "height", "width" ],
10581
mode = $.effects.setMode( el, o.mode || "hide" ),
10582
show = mode === "show",
10583
direction = o.direction || "left",
10584
ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
10585
motion = ( direction === "up" || direction === "left" ) ? "pos" : "neg",
10587
opacity: show ? 1 : 0
10592
$.effects.save( el, props );
10594
$.effects.createWrapper( el );
10596
distance = o.distance || el[ ref === "top" ? "outerHeight": "outerWidth" ]( true ) / 2;
10600
.css( "opacity", 0 )
10601
.css( ref, motion === "pos" ? -distance : distance );
10605
animation[ ref ] = ( show ?
10606
( motion === "pos" ? "+=" : "-=" ) :
10607
( motion === "pos" ? "-=" : "+=" ) ) +
10611
el.animate( animation, {
10613
duration: o.duration,
10615
complete: function() {
10616
if ( mode === "hide" ) {
10619
$.effects.restore( el, props );
10620
$.effects.removeWrapper( el );
10628
* jQuery UI Effects Explode 1.11.0
10629
* http://jqueryui.com
10631
* Copyright 2014 jQuery Foundation and other contributors
10632
* Released under the MIT license.
10633
* http://jquery.org/license
10635
* http://api.jqueryui.com/explode-effect/
10639
var effectExplode = $.effects.effect.explode = function( o, done ) {
10641
var rows = o.pieces ? Math.round( Math.sqrt( o.pieces ) ) : 3,
10644
mode = $.effects.setMode( el, o.mode || "hide" ),
10645
show = mode === "show",
10647
// show and then visibility:hidden the element before calculating offset
10648
offset = el.show().css( "visibility", "hidden" ).offset(),
10650
// width and height of a piece
10651
width = Math.ceil( el.outerWidth() / cells ),
10652
height = Math.ceil( el.outerHeight() / rows ),
10656
i, j, left, top, mx, my;
10658
// children animate complete:
10659
function childComplete() {
10660
pieces.push( this );
10661
if ( pieces.length === rows * cells ) {
10666
// clone the element for each row and cell.
10667
for ( i = 0; i < rows ; i++ ) { // ===>
10668
top = offset.top + i * height;
10669
my = i - ( rows - 1 ) / 2 ;
10671
for ( j = 0; j < cells ; j++ ) { // |||
10672
left = offset.left + j * width;
10673
mx = j - ( cells - 1 ) / 2 ;
10675
// Create a clone of the now hidden main element that will be absolute positioned
10676
// within a wrapper div off the -left and -top equal to size of our pieces
10679
.appendTo( "body" )
10680
.wrap( "<div></div>" )
10682
position: "absolute",
10683
visibility: "visible",
10688
// select the wrapper - make it overflow: hidden and absolute positioned based on
10689
// where the original was located +left and +top equal to the size of pieces
10691
.addClass( "ui-effects-explode" )
10693
position: "absolute",
10694
overflow: "hidden",
10697
left: left + ( show ? mx * width : 0 ),
10698
top: top + ( show ? my * height : 0 ),
10699
opacity: show ? 0 : 1
10701
left: left + ( show ? 0 : mx * width ),
10702
top: top + ( show ? 0 : my * height ),
10703
opacity: show ? 1 : 0
10704
}, o.duration || 500, o.easing, childComplete );
10708
function animComplete() {
10710
visibility: "visible"
10712
$( pieces ).remove();
10722
* jQuery UI Effects Fade 1.11.0
10723
* http://jqueryui.com
10725
* Copyright 2014 jQuery Foundation and other contributors
10726
* Released under the MIT license.
10727
* http://jquery.org/license
10729
* http://api.jqueryui.com/fade-effect/
10733
var effectFade = $.effects.effect.fade = function( o, done ) {
10734
var el = $( this ),
10735
mode = $.effects.setMode( el, o.mode || "toggle" );
10741
duration: o.duration,
10749
* jQuery UI Effects Fold 1.11.0
10750
* http://jqueryui.com
10752
* Copyright 2014 jQuery Foundation and other contributors
10753
* Released under the MIT license.
10754
* http://jquery.org/license
10756
* http://api.jqueryui.com/fold-effect/
10760
var effectFold = $.effects.effect.fold = function( o, done ) {
10763
var el = $( this ),
10764
props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
10765
mode = $.effects.setMode( el, o.mode || "hide" ),
10766
show = mode === "show",
10767
hide = mode === "hide",
10768
size = o.size || 15,
10769
percent = /([0-9]+)%/.exec( size ),
10770
horizFirst = !!o.horizFirst,
10771
widthFirst = show !== horizFirst,
10772
ref = widthFirst ? [ "width", "height" ] : [ "height", "width" ],
10773
duration = o.duration / 2,
10778
$.effects.save( el, props );
10782
wrapper = $.effects.createWrapper( el ).css({
10785
distance = widthFirst ?
10786
[ wrapper.width(), wrapper.height() ] :
10787
[ wrapper.height(), wrapper.width() ];
10790
size = parseInt( percent[ 1 ], 10 ) / 100 * distance[ hide ? 0 : 1 ];
10793
wrapper.css( horizFirst ? {
10803
animation1[ ref[ 0 ] ] = show ? distance[ 0 ] : size;
10804
animation2[ ref[ 1 ] ] = show ? distance[ 1 ] : 0;
10808
.animate( animation1, duration, o.easing )
10809
.animate( animation2, duration, o.easing, function() {
10813
$.effects.restore( el, props );
10814
$.effects.removeWrapper( el );
10822
* jQuery UI Effects Highlight 1.11.0
10823
* http://jqueryui.com
10825
* Copyright 2014 jQuery Foundation and other contributors
10826
* Released under the MIT license.
10827
* http://jquery.org/license
10829
* http://api.jqueryui.com/highlight-effect/
10833
var effectHighlight = $.effects.effect.highlight = function( o, done ) {
10834
var elem = $( this ),
10835
props = [ "backgroundImage", "backgroundColor", "opacity" ],
10836
mode = $.effects.setMode( elem, o.mode || "show" ),
10838
backgroundColor: elem.css( "backgroundColor" )
10841
if (mode === "hide") {
10842
animation.opacity = 0;
10845
$.effects.save( elem, props );
10850
backgroundImage: "none",
10851
backgroundColor: o.color || "#ffff99"
10853
.animate( animation, {
10855
duration: o.duration,
10857
complete: function() {
10858
if ( mode === "hide" ) {
10861
$.effects.restore( elem, props );
10869
* jQuery UI Effects Size 1.11.0
10870
* http://jqueryui.com
10872
* Copyright 2014 jQuery Foundation and other contributors
10873
* Released under the MIT license.
10874
* http://jquery.org/license
10876
* http://api.jqueryui.com/size-effect/
10880
var effectSize = $.effects.effect.size = function( o, done ) {
10883
var original, baseline, factor,
10885
props0 = [ "position", "top", "bottom", "left", "right", "width", "height", "overflow", "opacity" ],
10888
props1 = [ "position", "top", "bottom", "left", "right", "overflow", "opacity" ],
10890
// Copy for children
10891
props2 = [ "width", "height", "overflow" ],
10892
cProps = [ "fontSize" ],
10893
vProps = [ "borderTopWidth", "borderBottomWidth", "paddingTop", "paddingBottom" ],
10894
hProps = [ "borderLeftWidth", "borderRightWidth", "paddingLeft", "paddingRight" ],
10897
mode = $.effects.setMode( el, o.mode || "effect" ),
10898
restore = o.restore || mode !== "effect",
10899
scale = o.scale || "both",
10900
origin = o.origin || [ "middle", "center" ],
10901
position = el.css( "position" ),
10902
props = restore ? props0 : props1,
10910
if ( mode === "show" ) {
10914
height: el.height(),
10916
outerHeight: el.outerHeight(),
10917
outerWidth: el.outerWidth()
10920
if ( o.mode === "toggle" && mode === "show" ) {
10921
el.from = o.to || zero;
10922
el.to = o.from || original;
10924
el.from = o.from || ( mode === "show" ? zero : original );
10925
el.to = o.to || ( mode === "hide" ? zero : original );
10928
// Set scaling factor
10931
y: el.from.height / original.height,
10932
x: el.from.width / original.width
10935
y: el.to.height / original.height,
10936
x: el.to.width / original.width
10940
// Scale the css box
10941
if ( scale === "box" || scale === "both" ) {
10943
// Vertical props scaling
10944
if ( factor.from.y !== factor.to.y ) {
10945
props = props.concat( vProps );
10946
el.from = $.effects.setTransition( el, vProps, factor.from.y, el.from );
10947
el.to = $.effects.setTransition( el, vProps, factor.to.y, el.to );
10950
// Horizontal props scaling
10951
if ( factor.from.x !== factor.to.x ) {
10952
props = props.concat( hProps );
10953
el.from = $.effects.setTransition( el, hProps, factor.from.x, el.from );
10954
el.to = $.effects.setTransition( el, hProps, factor.to.x, el.to );
10958
// Scale the content
10959
if ( scale === "content" || scale === "both" ) {
10961
// Vertical props scaling
10962
if ( factor.from.y !== factor.to.y ) {
10963
props = props.concat( cProps ).concat( props2 );
10964
el.from = $.effects.setTransition( el, cProps, factor.from.y, el.from );
10965
el.to = $.effects.setTransition( el, cProps, factor.to.y, el.to );
10969
$.effects.save( el, props );
10971
$.effects.createWrapper( el );
10972
el.css( "overflow", "hidden" ).css( el.from );
10975
if (origin) { // Calculate baseline shifts
10976
baseline = $.effects.getBaseline( origin, original );
10977
el.from.top = ( original.outerHeight - el.outerHeight() ) * baseline.y;
10978
el.from.left = ( original.outerWidth - el.outerWidth() ) * baseline.x;
10979
el.to.top = ( original.outerHeight - el.to.outerHeight ) * baseline.y;
10980
el.to.left = ( original.outerWidth - el.to.outerWidth ) * baseline.x;
10982
el.css( el.from ); // set top & left
10985
if ( scale === "content" || scale === "both" ) { // Scale the children
10987
// Add margins/font-size
10988
vProps = vProps.concat([ "marginTop", "marginBottom" ]).concat(cProps);
10989
hProps = hProps.concat([ "marginLeft", "marginRight" ]);
10990
props2 = props0.concat(vProps).concat(hProps);
10992
el.find( "*[width]" ).each( function() {
10993
var child = $( this ),
10995
height: child.height(),
10996
width: child.width(),
10997
outerHeight: child.outerHeight(),
10998
outerWidth: child.outerWidth()
11001
$.effects.save(child, props2);
11005
height: c_original.height * factor.from.y,
11006
width: c_original.width * factor.from.x,
11007
outerHeight: c_original.outerHeight * factor.from.y,
11008
outerWidth: c_original.outerWidth * factor.from.x
11011
height: c_original.height * factor.to.y,
11012
width: c_original.width * factor.to.x,
11013
outerHeight: c_original.height * factor.to.y,
11014
outerWidth: c_original.width * factor.to.x
11017
// Vertical props scaling
11018
if ( factor.from.y !== factor.to.y ) {
11019
child.from = $.effects.setTransition( child, vProps, factor.from.y, child.from );
11020
child.to = $.effects.setTransition( child, vProps, factor.to.y, child.to );
11023
// Horizontal props scaling
11024
if ( factor.from.x !== factor.to.x ) {
11025
child.from = $.effects.setTransition( child, hProps, factor.from.x, child.from );
11026
child.to = $.effects.setTransition( child, hProps, factor.to.x, child.to );
11029
// Animate children
11030
child.css( child.from );
11031
child.animate( child.to, o.duration, o.easing, function() {
11033
// Restore children
11035
$.effects.restore( child, props2 );
11042
el.animate( el.to, {
11044
duration: o.duration,
11046
complete: function() {
11047
if ( el.to.opacity === 0 ) {
11048
el.css( "opacity", el.from.opacity );
11050
if ( mode === "hide" ) {
11053
$.effects.restore( el, props );
11056
// we need to calculate our new positioning based on the scaling
11057
if ( position === "static" ) {
11059
position: "relative",
11064
$.each([ "top", "left" ], function( idx, pos ) {
11065
el.css( pos, function( _, str ) {
11066
var val = parseInt( str, 10 ),
11067
toRef = idx ? el.to.left : el.to.top;
11069
// if original was "auto", recalculate the new value from wrapper
11070
if ( str === "auto" ) {
11071
return toRef + "px";
11074
return val + toRef + "px";
11080
$.effects.removeWrapper( el );
11089
* jQuery UI Effects Scale 1.11.0
11090
* http://jqueryui.com
11092
* Copyright 2014 jQuery Foundation and other contributors
11093
* Released under the MIT license.
11094
* http://jquery.org/license
11096
* http://api.jqueryui.com/scale-effect/
11100
var effectScale = $.effects.effect.scale = function( o, done ) {
11103
var el = $( this ),
11104
options = $.extend( true, {}, o ),
11105
mode = $.effects.setMode( el, o.mode || "effect" ),
11106
percent = parseInt( o.percent, 10 ) ||
11107
( parseInt( o.percent, 10 ) === 0 ? 0 : ( mode === "hide" ? 0 : 100 ) ),
11108
direction = o.direction || "both",
11111
height: el.height(),
11113
outerHeight: el.outerHeight(),
11114
outerWidth: el.outerWidth()
11117
y: direction !== "horizontal" ? (percent / 100) : 1,
11118
x: direction !== "vertical" ? (percent / 100) : 1
11121
// We are going to pass this effect to the size effect:
11122
options.effect = "size";
11123
options.queue = false;
11124
options.complete = done;
11126
// Set default origin and restore for show/hide
11127
if ( mode !== "effect" ) {
11128
options.origin = origin || [ "middle", "center" ];
11129
options.restore = true;
11132
options.from = o.from || ( mode === "show" ? {
11139
height: original.height * factor.y,
11140
width: original.width * factor.x,
11141
outerHeight: original.outerHeight * factor.y,
11142
outerWidth: original.outerWidth * factor.x
11145
// Fade option to support puff
11146
if ( options.fade ) {
11147
if ( mode === "show" ) {
11148
options.from.opacity = 0;
11149
options.to.opacity = 1;
11151
if ( mode === "hide" ) {
11152
options.from.opacity = 1;
11153
options.to.opacity = 0;
11158
el.effect( options );
11164
* jQuery UI Effects Puff 1.11.0
11165
* http://jqueryui.com
11167
* Copyright 2014 jQuery Foundation and other contributors
11168
* Released under the MIT license.
11169
* http://jquery.org/license
11171
* http://api.jqueryui.com/puff-effect/
11175
var effectPuff = $.effects.effect.puff = function( o, done ) {
11176
var elem = $( this ),
11177
mode = $.effects.setMode( elem, o.mode || "hide" ),
11178
hide = mode === "hide",
11179
percent = parseInt( o.percent, 10 ) || 150,
11180
factor = percent / 100,
11182
height: elem.height(),
11183
width: elem.width(),
11184
outerHeight: elem.outerHeight(),
11185
outerWidth: elem.outerWidth()
11194
percent: hide ? percent : 100,
11198
height: original.height * factor,
11199
width: original.width * factor,
11200
outerHeight: original.outerHeight * factor,
11201
outerWidth: original.outerWidth * factor
11210
* jQuery UI Effects Pulsate 1.11.0
11211
* http://jqueryui.com
11213
* Copyright 2014 jQuery Foundation and other contributors
11214
* Released under the MIT license.
11215
* http://jquery.org/license
11217
* http://api.jqueryui.com/pulsate-effect/
11221
var effectPulsate = $.effects.effect.pulsate = function( o, done ) {
11222
var elem = $( this ),
11223
mode = $.effects.setMode( elem, o.mode || "show" ),
11224
show = mode === "show",
11225
hide = mode === "hide",
11226
showhide = ( show || mode === "hide" ),
11228
// showing or hiding leaves of the "last" animation
11229
anims = ( ( o.times || 5 ) * 2 ) + ( showhide ? 1 : 0 ),
11230
duration = o.duration / anims,
11232
queue = elem.queue(),
11233
queuelen = queue.length,
11236
if ( show || !elem.is(":visible")) {
11237
elem.css( "opacity", 0 ).show();
11241
// anims - 1 opacity "toggles"
11242
for ( i = 1; i < anims; i++ ) {
11245
}, duration, o.easing );
11246
animateTo = 1 - animateTo;
11251
}, duration, o.easing);
11253
elem.queue(function() {
11260
// We just queued up "anims" animations, we need to put them next in the queue
11261
if ( queuelen > 1 ) {
11262
queue.splice.apply( queue,
11263
[ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) );
11270
* jQuery UI Effects Shake 1.11.0
11271
* http://jqueryui.com
11273
* Copyright 2014 jQuery Foundation and other contributors
11274
* Released under the MIT license.
11275
* http://jquery.org/license
11277
* http://api.jqueryui.com/shake-effect/
11281
var effectShake = $.effects.effect.shake = function( o, done ) {
11283
var el = $( this ),
11284
props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
11285
mode = $.effects.setMode( el, o.mode || "effect" ),
11286
direction = o.direction || "left",
11287
distance = o.distance || 20,
11288
times = o.times || 3,
11289
anims = times * 2 + 1,
11290
speed = Math.round( o.duration / anims ),
11291
ref = (direction === "up" || direction === "down") ? "top" : "left",
11292
positiveMotion = (direction === "up" || direction === "left"),
11298
// we will need to re-assemble the queue to stack our animations in place
11299
queue = el.queue(),
11300
queuelen = queue.length;
11302
$.effects.save( el, props );
11304
$.effects.createWrapper( el );
11307
animation[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance;
11308
animation1[ ref ] = ( positiveMotion ? "+=" : "-=" ) + distance * 2;
11309
animation2[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance * 2;
11312
el.animate( animation, speed, o.easing );
11315
for ( i = 1; i < times; i++ ) {
11316
el.animate( animation1, speed, o.easing ).animate( animation2, speed, o.easing );
11319
.animate( animation1, speed, o.easing )
11320
.animate( animation, speed / 2, o.easing )
11321
.queue(function() {
11322
if ( mode === "hide" ) {
11325
$.effects.restore( el, props );
11326
$.effects.removeWrapper( el );
11330
// inject all the animations we just queued to be first in line (after "inprogress")
11331
if ( queuelen > 1) {
11332
queue.splice.apply( queue,
11333
[ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) );
11341
* jQuery UI Effects Slide 1.11.0
11342
* http://jqueryui.com
11344
* Copyright 2014 jQuery Foundation and other contributors
11345
* Released under the MIT license.
11346
* http://jquery.org/license
11348
* http://api.jqueryui.com/slide-effect/
11352
var effectSlide = $.effects.effect.slide = function( o, done ) {
11355
var el = $( this ),
11356
props = [ "position", "top", "bottom", "left", "right", "width", "height" ],
11357
mode = $.effects.setMode( el, o.mode || "show" ),
11358
show = mode === "show",
11359
direction = o.direction || "left",
11360
ref = (direction === "up" || direction === "down") ? "top" : "left",
11361
positiveMotion = (direction === "up" || direction === "left"),
11366
$.effects.save( el, props );
11368
distance = o.distance || el[ ref === "top" ? "outerHeight" : "outerWidth" ]( true );
11370
$.effects.createWrapper( el ).css({
11375
el.css( ref, positiveMotion ? (isNaN(distance) ? "-" + distance : -distance) : distance );
11379
animation[ ref ] = ( show ?
11380
( positiveMotion ? "+=" : "-=") :
11381
( positiveMotion ? "-=" : "+=")) +
11385
el.animate( animation, {
11387
duration: o.duration,
11389
complete: function() {
11390
if ( mode === "hide" ) {
11393
$.effects.restore( el, props );
11394
$.effects.removeWrapper( el );
11402
* jQuery UI Effects Transfer 1.11.0
11403
* http://jqueryui.com
11405
* Copyright 2014 jQuery Foundation and other contributors
11406
* Released under the MIT license.
11407
* http://jquery.org/license
11409
* http://api.jqueryui.com/transfer-effect/
11413
var effectTransfer = $.effects.effect.transfer = function( o, done ) {
11414
var elem = $( this ),
11415
target = $( o.to ),
11416
targetFixed = target.css( "position" ) === "fixed",
11418
fixTop = targetFixed ? body.scrollTop() : 0,
11419
fixLeft = targetFixed ? body.scrollLeft() : 0,
11420
endPosition = target.offset(),
11422
top: endPosition.top - fixTop,
11423
left: endPosition.left - fixLeft,
11424
height: target.innerHeight(),
11425
width: target.innerWidth()
11427
startPosition = elem.offset(),
11428
transfer = $( "<div class='ui-effects-transfer'></div>" )
11429
.appendTo( document.body )
11430
.addClass( o.className )
11432
top: startPosition.top - fixTop,
11433
left: startPosition.left - fixLeft,
11434
height: elem.innerHeight(),
11435
width: elem.innerWidth(),
11436
position: targetFixed ? "fixed" : "absolute"
11438
.animate( animation, o.duration, o.easing, function() {
11446
* jQuery UI Progressbar 1.11.0
11447
* http://jqueryui.com
11449
* Copyright 2014 jQuery Foundation and other contributors
11450
* Released under the MIT license.
11451
* http://jquery.org/license
11453
* http://api.jqueryui.com/progressbar/
11457
var progressbar = $.widget( "ui.progressbar", {
11469
_create: function() {
11470
// Constrain initial value
11471
this.oldValue = this.options.value = this._constrainedValue();
11474
.addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
11476
// Only set static values, aria-valuenow and aria-valuemax are
11477
// set inside _refreshValue()
11478
role: "progressbar",
11479
"aria-valuemin": this.min
11482
this.valueDiv = $( "<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>" )
11483
.appendTo( this.element );
11485
this._refreshValue();
11488
_destroy: function() {
11490
.removeClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
11491
.removeAttr( "role" )
11492
.removeAttr( "aria-valuemin" )
11493
.removeAttr( "aria-valuemax" )
11494
.removeAttr( "aria-valuenow" );
11496
this.valueDiv.remove();
11499
value: function( newValue ) {
11500
if ( newValue === undefined ) {
11501
return this.options.value;
11504
this.options.value = this._constrainedValue( newValue );
11505
this._refreshValue();
11508
_constrainedValue: function( newValue ) {
11509
if ( newValue === undefined ) {
11510
newValue = this.options.value;
11513
this.indeterminate = newValue === false;
11516
if ( typeof newValue !== "number" ) {
11520
return this.indeterminate ? false :
11521
Math.min( this.options.max, Math.max( this.min, newValue ) );
11524
_setOptions: function( options ) {
11525
// Ensure "value" option is set after other values (like max)
11526
var value = options.value;
11527
delete options.value;
11529
this._super( options );
11531
this.options.value = this._constrainedValue( value );
11532
this._refreshValue();
11535
_setOption: function( key, value ) {
11536
if ( key === "max" ) {
11537
// Don't allow a max less than min
11538
value = Math.max( this.min, value );
11540
if ( key === "disabled" ) {
11542
.toggleClass( "ui-state-disabled", !!value )
11543
.attr( "aria-disabled", value );
11545
this._super( key, value );
11548
_percentage: function() {
11549
return this.indeterminate ? 100 : 100 * ( this.options.value - this.min ) / ( this.options.max - this.min );
11552
_refreshValue: function() {
11553
var value = this.options.value,
11554
percentage = this._percentage();
11557
.toggle( this.indeterminate || value > this.min )
11558
.toggleClass( "ui-corner-right", value === this.options.max )
11559
.width( percentage.toFixed(0) + "%" );
11561
this.element.toggleClass( "ui-progressbar-indeterminate", this.indeterminate );
11563
if ( this.indeterminate ) {
11564
this.element.removeAttr( "aria-valuenow" );
11565
if ( !this.overlayDiv ) {
11566
this.overlayDiv = $( "<div class='ui-progressbar-overlay'></div>" ).appendTo( this.valueDiv );
11569
this.element.attr({
11570
"aria-valuemax": this.options.max,
11571
"aria-valuenow": value
11573
if ( this.overlayDiv ) {
11574
this.overlayDiv.remove();
11575
this.overlayDiv = null;
11579
if ( this.oldValue !== value ) {
11580
this.oldValue = value;
11581
this._trigger( "change" );
11583
if ( value === this.options.max ) {
11584
this._trigger( "complete" );
11591
* jQuery UI Selectable 1.11.0
11592
* http://jqueryui.com
11594
* Copyright 2014 jQuery Foundation and other contributors
11595
* Released under the MIT license.
11596
* http://jquery.org/license
11598
* http://api.jqueryui.com/selectable/
11602
var selectable = $.widget("ui.selectable", $.ui.mouse, {
11609
tolerance: "touch",
11619
_create: function() {
11623
this.element.addClass("ui-selectable");
11625
this.dragged = false;
11627
// cache selectee children based on filter
11628
this.refresh = function() {
11629
selectees = $(that.options.filter, that.element[0]);
11630
selectees.addClass("ui-selectee");
11631
selectees.each(function() {
11632
var $this = $(this),
11633
pos = $this.offset();
11634
$.data(this, "selectable-item", {
11639
right: pos.left + $this.outerWidth(),
11640
bottom: pos.top + $this.outerHeight(),
11641
startselected: false,
11642
selected: $this.hasClass("ui-selected"),
11643
selecting: $this.hasClass("ui-selecting"),
11644
unselecting: $this.hasClass("ui-unselecting")
11650
this.selectees = selectees.addClass("ui-selectee");
11654
this.helper = $("<div class='ui-selectable-helper'></div>");
11657
_destroy: function() {
11659
.removeClass("ui-selectee")
11660
.removeData("selectable-item");
11662
.removeClass("ui-selectable ui-selectable-disabled");
11663
this._mouseDestroy();
11666
_mouseStart: function(event) {
11668
options = this.options;
11670
this.opos = [ event.pageX, event.pageY ];
11672
if (this.options.disabled) {
11676
this.selectees = $(options.filter, this.element[0]);
11678
this._trigger("start", event);
11680
$(options.appendTo).append(this.helper);
11681
// position helper (lasso)
11683
"left": event.pageX,
11684
"top": event.pageY,
11689
if (options.autoRefresh) {
11693
this.selectees.filter(".ui-selected").each(function() {
11694
var selectee = $.data(this, "selectable-item");
11695
selectee.startselected = true;
11696
if (!event.metaKey && !event.ctrlKey) {
11697
selectee.$element.removeClass("ui-selected");
11698
selectee.selected = false;
11699
selectee.$element.addClass("ui-unselecting");
11700
selectee.unselecting = true;
11701
// selectable UNSELECTING callback
11702
that._trigger("unselecting", event, {
11703
unselecting: selectee.element
11708
$(event.target).parents().addBack().each(function() {
11710
selectee = $.data(this, "selectable-item");
11712
doSelect = (!event.metaKey && !event.ctrlKey) || !selectee.$element.hasClass("ui-selected");
11714
.removeClass(doSelect ? "ui-unselecting" : "ui-selected")
11715
.addClass(doSelect ? "ui-selecting" : "ui-unselecting");
11716
selectee.unselecting = !doSelect;
11717
selectee.selecting = doSelect;
11718
selectee.selected = doSelect;
11719
// selectable (UN)SELECTING callback
11721
that._trigger("selecting", event, {
11722
selecting: selectee.element
11725
that._trigger("unselecting", event, {
11726
unselecting: selectee.element
11735
_mouseDrag: function(event) {
11737
this.dragged = true;
11739
if (this.options.disabled) {
11745
options = this.options,
11751
if (x1 > x2) { tmp = x2; x2 = x1; x1 = tmp; }
11752
if (y1 > y2) { tmp = y2; y2 = y1; y1 = tmp; }
11753
this.helper.css({ left: x1, top: y1, width: x2 - x1, height: y2 - y1 });
11755
this.selectees.each(function() {
11756
var selectee = $.data(this, "selectable-item"),
11759
//prevent helper from being selected if appendTo: selectable
11760
if (!selectee || selectee.element === that.element[0]) {
11764
if (options.tolerance === "touch") {
11765
hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) );
11766
} else if (options.tolerance === "fit") {
11767
hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2);
11772
if (selectee.selected) {
11773
selectee.$element.removeClass("ui-selected");
11774
selectee.selected = false;
11776
if (selectee.unselecting) {
11777
selectee.$element.removeClass("ui-unselecting");
11778
selectee.unselecting = false;
11780
if (!selectee.selecting) {
11781
selectee.$element.addClass("ui-selecting");
11782
selectee.selecting = true;
11783
// selectable SELECTING callback
11784
that._trigger("selecting", event, {
11785
selecting: selectee.element
11790
if (selectee.selecting) {
11791
if ((event.metaKey || event.ctrlKey) && selectee.startselected) {
11792
selectee.$element.removeClass("ui-selecting");
11793
selectee.selecting = false;
11794
selectee.$element.addClass("ui-selected");
11795
selectee.selected = true;
11797
selectee.$element.removeClass("ui-selecting");
11798
selectee.selecting = false;
11799
if (selectee.startselected) {
11800
selectee.$element.addClass("ui-unselecting");
11801
selectee.unselecting = true;
11803
// selectable UNSELECTING callback
11804
that._trigger("unselecting", event, {
11805
unselecting: selectee.element
11809
if (selectee.selected) {
11810
if (!event.metaKey && !event.ctrlKey && !selectee.startselected) {
11811
selectee.$element.removeClass("ui-selected");
11812
selectee.selected = false;
11814
selectee.$element.addClass("ui-unselecting");
11815
selectee.unselecting = true;
11816
// selectable UNSELECTING callback
11817
that._trigger("unselecting", event, {
11818
unselecting: selectee.element
11828
_mouseStop: function(event) {
11831
this.dragged = false;
11833
$(".ui-unselecting", this.element[0]).each(function() {
11834
var selectee = $.data(this, "selectable-item");
11835
selectee.$element.removeClass("ui-unselecting");
11836
selectee.unselecting = false;
11837
selectee.startselected = false;
11838
that._trigger("unselected", event, {
11839
unselected: selectee.element
11842
$(".ui-selecting", this.element[0]).each(function() {
11843
var selectee = $.data(this, "selectable-item");
11844
selectee.$element.removeClass("ui-selecting").addClass("ui-selected");
11845
selectee.selecting = false;
11846
selectee.selected = true;
11847
selectee.startselected = true;
11848
that._trigger("selected", event, {
11849
selected: selectee.element
11852
this._trigger("stop", event);
11854
this.helper.remove();
11863
* jQuery UI Selectmenu 1.11.0
11864
* http://jqueryui.com
11866
* Copyright 2014 jQuery Foundation and other contributors
11867
* Released under the MIT license.
11868
* http://jquery.org/license
11870
* http://api.jqueryui.com/selectmenu
11874
var selectmenu = $.widget( "ui.selectmenu", {
11876
defaultElement: "<select>",
11881
button: "ui-icon-triangle-1-s"
11898
_create: function() {
11899
var selectmenuId = this.element.uniqueId().attr( "id" );
11901
element: selectmenuId,
11902
button: selectmenuId + "-button",
11903
menu: selectmenuId + "-menu"
11906
this._drawButton();
11909
if ( this.options.disabled ) {
11914
_drawButton: function() {
11916
tabindex = this.element.attr( "tabindex" );
11918
// Associate existing label with the new button
11919
this.label = $( "label[for='" + this.ids.element + "']" ).attr( "for", this.ids.button );
11920
this._on( this.label, {
11921
click: function( event ) {
11922
this.button.focus();
11923
event.preventDefault();
11927
// Hide original select element
11928
this.element.hide();
11931
this.button = $( "<span>", {
11932
"class": "ui-selectmenu-button ui-widget ui-state-default ui-corner-all",
11933
tabindex: tabindex || this.options.disabled ? -1 : 0,
11934
id: this.ids.button,
11936
"aria-expanded": "false",
11937
"aria-autocomplete": "list",
11938
"aria-owns": this.ids.menu,
11939
"aria-haspopup": "true"
11941
.insertAfter( this.element );
11944
"class": "ui-icon " + this.options.icons.button
11946
.prependTo( this.button );
11948
this.buttonText = $( "<span>", {
11949
"class": "ui-selectmenu-text"
11951
.appendTo( this.button );
11953
this._setText( this.buttonText, this.element.find( "option:selected" ).text() );
11954
this._setOption( "width", this.options.width );
11956
this._on( this.button, this._buttonEvents );
11957
this.button.one( "focusin", function() {
11959
// Delay rendering the menu items until the button receives focus.
11960
// The menu may have already been rendered via a programmatic open.
11961
if ( !that.menuItems ) {
11962
that._refreshMenu();
11965
this._hoverable( this.button );
11966
this._focusable( this.button );
11969
_drawMenu: function() {
11973
this.menu = $( "<ul>", {
11974
"aria-hidden": "true",
11975
"aria-labelledby": this.ids.button,
11980
this.menuWrap = $( "<div>", {
11981
"class": "ui-selectmenu-menu ui-front"
11983
.append( this.menu )
11984
.appendTo( this._appendTo() );
11986
// Initialize menu widget
11987
this.menuInstance = this.menu
11990
select: function( event, ui ) {
11991
event.preventDefault();
11992
that._select( ui.item.data( "ui-selectmenu-item" ), event );
11994
focus: function( event, ui ) {
11995
var item = ui.item.data( "ui-selectmenu-item" );
11997
// Prevent inital focus from firing and check if its a newly focused item
11998
if ( that.focusIndex != null && item.index !== that.focusIndex ) {
11999
that._trigger( "focus", event, { item: item } );
12000
if ( !that.isOpen ) {
12001
that._select( item, event );
12004
that.focusIndex = item.index;
12006
that.button.attr( "aria-activedescendant",
12007
that.menuItems.eq( item.index ).attr( "id" ) );
12010
.menu( "instance" );
12012
// Adjust menu styles to dropdown
12014
.addClass( "ui-corner-bottom" )
12015
.removeClass( "ui-corner-all" );
12017
// Don't close the menu on mouseleave
12018
this.menuInstance._off( this.menu, "mouseleave" );
12020
// Cancel the menu's collapseAll on document click
12021
this.menuInstance._closeOnDocumentClick = function() {
12025
// Selects often contain empty items, but never contain dividers
12026
this.menuInstance._isDivider = function() {
12031
refresh: function() {
12032
this._refreshMenu();
12033
this._setText( this.buttonText, this._getSelectedItem().text() );
12034
this._setOption( "width", this.options.width );
12037
_refreshMenu: function() {
12041
options = this.element.find( "option" );
12043
if ( !options.length ) {
12047
this._parseOptions( options );
12048
this._renderMenu( this.menu, this.items );
12050
this.menuInstance.refresh();
12051
this.menuItems = this.menu.find( "li" ).not( ".ui-selectmenu-optgroup" );
12053
item = this._getSelectedItem();
12055
// Update the menu to have the correct item focused
12056
this.menuInstance.focus( null, item );
12057
this._setAria( item.data( "ui-selectmenu-item" ) );
12059
// Set disabled state
12060
this._setOption( "disabled", this.element.prop( "disabled" ) );
12063
open: function( event ) {
12064
if ( this.options.disabled ) {
12068
// If this is the first time the menu is being opened, render the items
12069
if ( !this.menuItems ) {
12070
this._refreshMenu();
12073
// Menu clears focus on close, reset focus to selected item
12074
this.menu.find( ".ui-state-focus" ).removeClass( "ui-state-focus" );
12075
this.menuInstance.focus( null, this._getSelectedItem() );
12078
this.isOpen = true;
12079
this._toggleAttr();
12080
this._resizeMenu();
12083
this._on( this.document, this._documentClick );
12085
this._trigger( "open", event );
12088
_position: function() {
12089
this.menuWrap.position( $.extend( { of: this.button }, this.options.position ) );
12092
close: function( event ) {
12093
if ( !this.isOpen ) {
12097
this.isOpen = false;
12098
this._toggleAttr();
12100
this._off( this.document );
12102
this._trigger( "close", event );
12105
widget: function() {
12106
return this.button;
12109
menuWidget: function() {
12113
_renderMenu: function( ul, items ) {
12115
currentOptgroup = "";
12117
$.each( items, function( index, item ) {
12118
if ( item.optgroup !== currentOptgroup ) {
12120
"class": "ui-selectmenu-optgroup ui-menu-divider" +
12121
( item.element.parent( "optgroup" ).prop( "disabled" ) ?
12122
" ui-state-disabled" :
12124
text: item.optgroup
12128
currentOptgroup = item.optgroup;
12131
that._renderItemData( ul, item );
12135
_renderItemData: function( ul, item ) {
12136
return this._renderItem( ul, item ).data( "ui-selectmenu-item", item );
12139
_renderItem: function( ul, item ) {
12140
var li = $( "<li>" );
12142
if ( item.disabled ) {
12143
li.addClass( "ui-state-disabled" );
12145
this._setText( li, item.label );
12147
return li.appendTo( ul );
12150
_setText: function( element, value ) {
12152
element.text( value );
12154
element.html( " " );
12158
_move: function( direction, event ) {
12160
filter = ".ui-menu-item";
12162
if ( this.isOpen ) {
12163
item = this.menuItems.eq( this.focusIndex );
12165
item = this.menuItems.eq( this.element[ 0 ].selectedIndex );
12166
filter += ":not(.ui-state-disabled)";
12169
if ( direction === "first" || direction === "last" ) {
12170
next = item[ direction === "first" ? "prevAll" : "nextAll" ]( filter ).eq( -1 );
12172
next = item[ direction + "All" ]( filter ).eq( 0 );
12175
if ( next.length ) {
12176
this.menuInstance.focus( event, next );
12180
_getSelectedItem: function() {
12181
return this.menuItems.eq( this.element[ 0 ].selectedIndex );
12184
_toggle: function( event ) {
12185
this[ this.isOpen ? "close" : "open" ]( event );
12189
mousedown: function( event ) {
12190
if ( !this.isOpen ) {
12194
if ( !$( event.target ).closest( ".ui-selectmenu-menu, #" + this.ids.button ).length ) {
12195
this.close( event );
12202
keydown: function( event ) {
12203
var preventDefault = true;
12204
switch ( event.keyCode ) {
12205
case $.ui.keyCode.TAB:
12206
case $.ui.keyCode.ESCAPE:
12207
this.close( event );
12208
preventDefault = false;
12210
case $.ui.keyCode.ENTER:
12211
if ( this.isOpen ) {
12212
this._selectFocusedItem( event );
12215
case $.ui.keyCode.UP:
12216
if ( event.altKey ) {
12217
this._toggle( event );
12219
this._move( "prev", event );
12222
case $.ui.keyCode.DOWN:
12223
if ( event.altKey ) {
12224
this._toggle( event );
12226
this._move( "next", event );
12229
case $.ui.keyCode.SPACE:
12230
if ( this.isOpen ) {
12231
this._selectFocusedItem( event );
12233
this._toggle( event );
12236
case $.ui.keyCode.LEFT:
12237
this._move( "prev", event );
12239
case $.ui.keyCode.RIGHT:
12240
this._move( "next", event );
12242
case $.ui.keyCode.HOME:
12243
case $.ui.keyCode.PAGE_UP:
12244
this._move( "first", event );
12246
case $.ui.keyCode.END:
12247
case $.ui.keyCode.PAGE_DOWN:
12248
this._move( "last", event );
12251
this.menu.trigger( event );
12252
preventDefault = false;
12255
if ( preventDefault ) {
12256
event.preventDefault();
12261
_selectFocusedItem: function( event ) {
12262
var item = this.menuItems.eq( this.focusIndex );
12263
if ( !item.hasClass( "ui-state-disabled" ) ) {
12264
this._select( item.data( "ui-selectmenu-item" ), event );
12268
_select: function( item, event ) {
12269
var oldIndex = this.element[ 0 ].selectedIndex;
12271
// Change native select element
12272
this.element[ 0 ].selectedIndex = item.index;
12273
this._setText( this.buttonText, item.label );
12274
this._setAria( item );
12275
this._trigger( "select", event, { item: item } );
12277
if ( item.index !== oldIndex ) {
12278
this._trigger( "change", event, { item: item } );
12281
this.close( event );
12284
_setAria: function( item ) {
12285
var id = this.menuItems.eq( item.index ).attr( "id" );
12288
"aria-labelledby": id,
12289
"aria-activedescendant": id
12291
this.menu.attr( "aria-activedescendant", id );
12294
_setOption: function( key, value ) {
12295
if ( key === "icons" ) {
12296
this.button.find( "span.ui-icon" )
12297
.removeClass( this.options.icons.button )
12298
.addClass( value.button );
12301
this._super( key, value );
12303
if ( key === "appendTo" ) {
12304
this.menuWrap.appendTo( this._appendTo() );
12307
if ( key === "disabled" ) {
12308
this.menuInstance.option( "disabled", value );
12310
.toggleClass( "ui-state-disabled", value )
12311
.attr( "aria-disabled", value );
12313
this.element.prop( "disabled", value );
12315
this.button.attr( "tabindex", -1 );
12318
this.button.attr( "tabindex", 0 );
12322
if ( key === "width" ) {
12324
value = this.element.outerWidth();
12326
this.button.outerWidth( value );
12330
_appendTo: function() {
12331
var element = this.options.appendTo;
12334
element = element.jquery || element.nodeType ?
12336
this.document.find( element ).eq( 0 );
12339
if ( !element || !element[ 0 ] ) {
12340
element = this.element.closest( ".ui-front" );
12343
if ( !element.length ) {
12344
element = this.document[ 0 ].body;
12350
_toggleAttr: function() {
12352
.toggleClass( "ui-corner-top", this.isOpen )
12353
.toggleClass( "ui-corner-all", !this.isOpen )
12354
.attr( "aria-expanded", this.isOpen );
12355
this.menuWrap.toggleClass( "ui-selectmenu-open", this.isOpen );
12356
this.menu.attr( "aria-hidden", !this.isOpen );
12359
_resizeMenu: function() {
12360
this.menu.outerWidth( Math.max(
12361
this.button.outerWidth(),
12364
// IE10 wraps long text (possibly a rounding bug)
12365
// so we add 1px to avoid the wrapping
12366
this.menu.width( "" ).outerWidth() + 1
12370
_getCreateOptions: function() {
12371
return { disabled: this.element.prop( "disabled" ) };
12374
_parseOptions: function( options ) {
12376
options.each(function( index, item ) {
12377
var option = $( item ),
12378
optgroup = option.parent( "optgroup" );
12382
value: option.attr( "value" ),
12383
label: option.text(),
12384
optgroup: optgroup.attr( "label" ) || "",
12385
disabled: optgroup.prop( "disabled" ) || option.prop( "disabled" )
12391
_destroy: function() {
12392
this.menuWrap.remove();
12393
this.button.remove();
12394
this.element.show();
12395
this.element.removeUniqueId();
12396
this.label.attr( "for", this.ids.element );
12402
* jQuery UI Slider 1.11.0
12403
* http://jqueryui.com
12405
* Copyright 2014 jQuery Foundation and other contributors
12406
* Released under the MIT license.
12407
* http://jquery.org/license
12409
* http://api.jqueryui.com/slider/
12413
var slider = $.widget( "ui.slider", $.ui.mouse, {
12415
widgetEventPrefix: "slide",
12422
orientation: "horizontal",
12435
// number of pages in a slider
12436
// (how many times can you page up/down to go through the whole range)
12439
_create: function() {
12440
this._keySliding = false;
12441
this._mouseSliding = false;
12442
this._animateOff = true;
12443
this._handleIndex = null;
12444
this._detectOrientation();
12448
.addClass( "ui-slider" +
12449
" ui-slider-" + this.orientation +
12451
" ui-widget-content" +
12455
this._setOption( "disabled", this.options.disabled );
12457
this._animateOff = false;
12460
_refresh: function() {
12461
this._createRange();
12462
this._createHandles();
12463
this._setupEvents();
12464
this._refreshValue();
12467
_createHandles: function() {
12468
var i, handleCount,
12469
options = this.options,
12470
existingHandles = this.element.find( ".ui-slider-handle" ).addClass( "ui-state-default ui-corner-all" ),
12471
handle = "<span class='ui-slider-handle ui-state-default ui-corner-all' tabindex='0'></span>",
12474
handleCount = ( options.values && options.values.length ) || 1;
12476
if ( existingHandles.length > handleCount ) {
12477
existingHandles.slice( handleCount ).remove();
12478
existingHandles = existingHandles.slice( 0, handleCount );
12481
for ( i = existingHandles.length; i < handleCount; i++ ) {
12482
handles.push( handle );
12485
this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( this.element ) );
12487
this.handle = this.handles.eq( 0 );
12489
this.handles.each(function( i ) {
12490
$( this ).data( "ui-slider-handle-index", i );
12494
_createRange: function() {
12495
var options = this.options,
12498
if ( options.range ) {
12499
if ( options.range === true ) {
12500
if ( !options.values ) {
12501
options.values = [ this._valueMin(), this._valueMin() ];
12502
} else if ( options.values.length && options.values.length !== 2 ) {
12503
options.values = [ options.values[0], options.values[0] ];
12504
} else if ( $.isArray( options.values ) ) {
12505
options.values = options.values.slice(0);
12509
if ( !this.range || !this.range.length ) {
12510
this.range = $( "<div></div>" )
12511
.appendTo( this.element );
12513
classes = "ui-slider-range" +
12514
// note: this isn't the most fittingly semantic framework class for this element,
12515
// but worked best visually with a variety of themes
12516
" ui-widget-header ui-corner-all";
12518
this.range.removeClass( "ui-slider-range-min ui-slider-range-max" )
12519
// Handle range switching from true to min/max
12526
this.range.addClass( classes +
12527
( ( options.range === "min" || options.range === "max" ) ? " ui-slider-range-" + options.range : "" ) );
12529
if ( this.range ) {
12530
this.range.remove();
12536
_setupEvents: function() {
12537
this._off( this.handles );
12538
this._on( this.handles, this._handleEvents );
12539
this._hoverable( this.handles );
12540
this._focusable( this.handles );
12543
_destroy: function() {
12544
this.handles.remove();
12545
if ( this.range ) {
12546
this.range.remove();
12550
.removeClass( "ui-slider" +
12551
" ui-slider-horizontal" +
12552
" ui-slider-vertical" +
12554
" ui-widget-content" +
12555
" ui-corner-all" );
12557
this._mouseDestroy();
12560
_mouseCapture: function( event ) {
12561
var position, normValue, distance, closestHandle, index, allowed, offset, mouseOverHandle,
12565
if ( o.disabled ) {
12569
this.elementSize = {
12570
width: this.element.outerWidth(),
12571
height: this.element.outerHeight()
12573
this.elementOffset = this.element.offset();
12575
position = { x: event.pageX, y: event.pageY };
12576
normValue = this._normValueFromMouse( position );
12577
distance = this._valueMax() - this._valueMin() + 1;
12578
this.handles.each(function( i ) {
12579
var thisDistance = Math.abs( normValue - that.values(i) );
12580
if (( distance > thisDistance ) ||
12581
( distance === thisDistance &&
12582
(i === that._lastChangedValue || that.values(i) === o.min ))) {
12583
distance = thisDistance;
12584
closestHandle = $( this );
12589
allowed = this._start( event, index );
12590
if ( allowed === false ) {
12593
this._mouseSliding = true;
12595
this._handleIndex = index;
12598
.addClass( "ui-state-active" )
12601
offset = closestHandle.offset();
12602
mouseOverHandle = !$( event.target ).parents().addBack().is( ".ui-slider-handle" );
12603
this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
12604
left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
12605
top: event.pageY - offset.top -
12606
( closestHandle.height() / 2 ) -
12607
( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) -
12608
( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) +
12609
( parseInt( closestHandle.css("marginTop"), 10 ) || 0)
12612
if ( !this.handles.hasClass( "ui-state-hover" ) ) {
12613
this._slide( event, index, normValue );
12615
this._animateOff = true;
12619
_mouseStart: function() {
12623
_mouseDrag: function( event ) {
12624
var position = { x: event.pageX, y: event.pageY },
12625
normValue = this._normValueFromMouse( position );
12627
this._slide( event, this._handleIndex, normValue );
12632
_mouseStop: function( event ) {
12633
this.handles.removeClass( "ui-state-active" );
12634
this._mouseSliding = false;
12636
this._stop( event, this._handleIndex );
12637
this._change( event, this._handleIndex );
12639
this._handleIndex = null;
12640
this._clickOffset = null;
12641
this._animateOff = false;
12646
_detectOrientation: function() {
12647
this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
12650
_normValueFromMouse: function( position ) {
12657
if ( this.orientation === "horizontal" ) {
12658
pixelTotal = this.elementSize.width;
12659
pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 );
12661
pixelTotal = this.elementSize.height;
12662
pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 );
12665
percentMouse = ( pixelMouse / pixelTotal );
12666
if ( percentMouse > 1 ) {
12669
if ( percentMouse < 0 ) {
12672
if ( this.orientation === "vertical" ) {
12673
percentMouse = 1 - percentMouse;
12676
valueTotal = this._valueMax() - this._valueMin();
12677
valueMouse = this._valueMin() + percentMouse * valueTotal;
12679
return this._trimAlignValue( valueMouse );
12682
_start: function( event, index ) {
12684
handle: this.handles[ index ],
12685
value: this.value()
12687
if ( this.options.values && this.options.values.length ) {
12688
uiHash.value = this.values( index );
12689
uiHash.values = this.values();
12691
return this._trigger( "start", event, uiHash );
12694
_slide: function( event, index, newVal ) {
12699
if ( this.options.values && this.options.values.length ) {
12700
otherVal = this.values( index ? 0 : 1 );
12702
if ( ( this.options.values.length === 2 && this.options.range === true ) &&
12703
( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) )
12708
if ( newVal !== this.values( index ) ) {
12709
newValues = this.values();
12710
newValues[ index ] = newVal;
12711
// A slide can be canceled by returning false from the slide callback
12712
allowed = this._trigger( "slide", event, {
12713
handle: this.handles[ index ],
12717
otherVal = this.values( index ? 0 : 1 );
12718
if ( allowed !== false ) {
12719
this.values( index, newVal );
12723
if ( newVal !== this.value() ) {
12724
// A slide can be canceled by returning false from the slide callback
12725
allowed = this._trigger( "slide", event, {
12726
handle: this.handles[ index ],
12729
if ( allowed !== false ) {
12730
this.value( newVal );
12736
_stop: function( event, index ) {
12738
handle: this.handles[ index ],
12739
value: this.value()
12741
if ( this.options.values && this.options.values.length ) {
12742
uiHash.value = this.values( index );
12743
uiHash.values = this.values();
12746
this._trigger( "stop", event, uiHash );
12749
_change: function( event, index ) {
12750
if ( !this._keySliding && !this._mouseSliding ) {
12752
handle: this.handles[ index ],
12753
value: this.value()
12755
if ( this.options.values && this.options.values.length ) {
12756
uiHash.value = this.values( index );
12757
uiHash.values = this.values();
12760
//store the last changed value index for reference when handles overlap
12761
this._lastChangedValue = index;
12763
this._trigger( "change", event, uiHash );
12767
value: function( newValue ) {
12768
if ( arguments.length ) {
12769
this.options.value = this._trimAlignValue( newValue );
12770
this._refreshValue();
12771
this._change( null, 0 );
12775
return this._value();
12778
values: function( index, newValue ) {
12783
if ( arguments.length > 1 ) {
12784
this.options.values[ index ] = this._trimAlignValue( newValue );
12785
this._refreshValue();
12786
this._change( null, index );
12790
if ( arguments.length ) {
12791
if ( $.isArray( arguments[ 0 ] ) ) {
12792
vals = this.options.values;
12793
newValues = arguments[ 0 ];
12794
for ( i = 0; i < vals.length; i += 1 ) {
12795
vals[ i ] = this._trimAlignValue( newValues[ i ] );
12796
this._change( null, i );
12798
this._refreshValue();
12800
if ( this.options.values && this.options.values.length ) {
12801
return this._values( index );
12803
return this.value();
12807
return this._values();
12811
_setOption: function( key, value ) {
12815
if ( key === "range" && this.options.range === true ) {
12816
if ( value === "min" ) {
12817
this.options.value = this._values( 0 );
12818
this.options.values = null;
12819
} else if ( value === "max" ) {
12820
this.options.value = this._values( this.options.values.length - 1 );
12821
this.options.values = null;
12825
if ( $.isArray( this.options.values ) ) {
12826
valsLength = this.options.values.length;
12829
if ( key === "disabled" ) {
12830
this.element.toggleClass( "ui-state-disabled", !!value );
12833
this._super( key, value );
12836
case "orientation":
12837
this._detectOrientation();
12839
.removeClass( "ui-slider-horizontal ui-slider-vertical" )
12840
.addClass( "ui-slider-" + this.orientation );
12841
this._refreshValue();
12844
this._animateOff = true;
12845
this._refreshValue();
12846
this._change( null, 0 );
12847
this._animateOff = false;
12850
this._animateOff = true;
12851
this._refreshValue();
12852
for ( i = 0; i < valsLength; i += 1 ) {
12853
this._change( null, i );
12855
this._animateOff = false;
12859
this._animateOff = true;
12860
this._refreshValue();
12861
this._animateOff = false;
12864
this._animateOff = true;
12866
this._animateOff = false;
12871
//internal value getter
12872
// _value() returns value trimmed by min and max, aligned by step
12873
_value: function() {
12874
var val = this.options.value;
12875
val = this._trimAlignValue( val );
12880
//internal values getter
12881
// _values() returns array of values trimmed by min and max, aligned by step
12882
// _values( index ) returns single value trimmed by min and max, aligned by step
12883
_values: function( index ) {
12888
if ( arguments.length ) {
12889
val = this.options.values[ index ];
12890
val = this._trimAlignValue( val );
12893
} else if ( this.options.values && this.options.values.length ) {
12894
// .slice() creates a copy of the array
12895
// this copy gets trimmed by min and max and then returned
12896
vals = this.options.values.slice();
12897
for ( i = 0; i < vals.length; i+= 1) {
12898
vals[ i ] = this._trimAlignValue( vals[ i ] );
12907
// returns the step-aligned value that val is closest to, between (inclusive) min and max
12908
_trimAlignValue: function( val ) {
12909
if ( val <= this._valueMin() ) {
12910
return this._valueMin();
12912
if ( val >= this._valueMax() ) {
12913
return this._valueMax();
12915
var step = ( this.options.step > 0 ) ? this.options.step : 1,
12916
valModStep = (val - this._valueMin()) % step,
12917
alignValue = val - valModStep;
12919
if ( Math.abs(valModStep) * 2 >= step ) {
12920
alignValue += ( valModStep > 0 ) ? step : ( -step );
12923
// Since JavaScript has problems with large floats, round
12924
// the final value to 5 digits after the decimal point (see #4124)
12925
return parseFloat( alignValue.toFixed(5) );
12928
_valueMin: function() {
12929
return this.options.min;
12932
_valueMax: function() {
12933
return this.options.max;
12936
_refreshValue: function() {
12937
var lastValPercent, valPercent, value, valueMin, valueMax,
12938
oRange = this.options.range,
12941
animate = ( !this._animateOff ) ? o.animate : false,
12944
if ( this.options.values && this.options.values.length ) {
12945
this.handles.each(function( i ) {
12946
valPercent = ( that.values(i) - that._valueMin() ) / ( that._valueMax() - that._valueMin() ) * 100;
12947
_set[ that.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
12948
$( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
12949
if ( that.options.range === true ) {
12950
if ( that.orientation === "horizontal" ) {
12952
that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate );
12955
that.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
12959
that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate );
12962
that.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
12966
lastValPercent = valPercent;
12969
value = this.value();
12970
valueMin = this._valueMin();
12971
valueMax = this._valueMax();
12972
valPercent = ( valueMax !== valueMin ) ?
12973
( value - valueMin ) / ( valueMax - valueMin ) * 100 :
12975
_set[ this.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
12976
this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
12978
if ( oRange === "min" && this.orientation === "horizontal" ) {
12979
this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate );
12981
if ( oRange === "max" && this.orientation === "horizontal" ) {
12982
this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
12984
if ( oRange === "min" && this.orientation === "vertical" ) {
12985
this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate );
12987
if ( oRange === "max" && this.orientation === "vertical" ) {
12988
this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
12994
keydown: function( event ) {
12995
var allowed, curVal, newVal, step,
12996
index = $( event.target ).data( "ui-slider-handle-index" );
12998
switch ( event.keyCode ) {
12999
case $.ui.keyCode.HOME:
13000
case $.ui.keyCode.END:
13001
case $.ui.keyCode.PAGE_UP:
13002
case $.ui.keyCode.PAGE_DOWN:
13003
case $.ui.keyCode.UP:
13004
case $.ui.keyCode.RIGHT:
13005
case $.ui.keyCode.DOWN:
13006
case $.ui.keyCode.LEFT:
13007
event.preventDefault();
13008
if ( !this._keySliding ) {
13009
this._keySliding = true;
13010
$( event.target ).addClass( "ui-state-active" );
13011
allowed = this._start( event, index );
13012
if ( allowed === false ) {
13019
step = this.options.step;
13020
if ( this.options.values && this.options.values.length ) {
13021
curVal = newVal = this.values( index );
13023
curVal = newVal = this.value();
13026
switch ( event.keyCode ) {
13027
case $.ui.keyCode.HOME:
13028
newVal = this._valueMin();
13030
case $.ui.keyCode.END:
13031
newVal = this._valueMax();
13033
case $.ui.keyCode.PAGE_UP:
13034
newVal = this._trimAlignValue(
13035
curVal + ( ( this._valueMax() - this._valueMin() ) / this.numPages )
13038
case $.ui.keyCode.PAGE_DOWN:
13039
newVal = this._trimAlignValue(
13040
curVal - ( (this._valueMax() - this._valueMin()) / this.numPages ) );
13042
case $.ui.keyCode.UP:
13043
case $.ui.keyCode.RIGHT:
13044
if ( curVal === this._valueMax() ) {
13047
newVal = this._trimAlignValue( curVal + step );
13049
case $.ui.keyCode.DOWN:
13050
case $.ui.keyCode.LEFT:
13051
if ( curVal === this._valueMin() ) {
13054
newVal = this._trimAlignValue( curVal - step );
13058
this._slide( event, index, newVal );
13060
keyup: function( event ) {
13061
var index = $( event.target ).data( "ui-slider-handle-index" );
13063
if ( this._keySliding ) {
13064
this._keySliding = false;
13065
this._stop( event, index );
13066
this._change( event, index );
13067
$( event.target ).removeClass( "ui-state-active" );
13075
* jQuery UI Sortable 1.11.0
13076
* http://jqueryui.com
13078
* Copyright 2014 jQuery Foundation and other contributors
13079
* Released under the MIT license.
13080
* http://jquery.org/license
13082
* http://api.jqueryui.com/sortable/
13086
var sortable = $.widget("ui.sortable", $.ui.mouse, {
13088
widgetEventPrefix: "sort",
13091
appendTo: "parent",
13093
connectWith: false,
13094
containment: false,
13098
forcePlaceholderSize: false,
13099
forceHelperSize: false,
13102
helper: "original",
13105
placeholder: false,
13108
scrollSensitivity: 20,
13111
tolerance: "intersect",
13129
_isOverAxis: function( x, reference, size ) {
13130
return ( x >= reference ) && ( x < ( reference + size ) );
13133
_isFloating: function( item ) {
13134
return (/left|right/).test(item.css("float")) || (/inline|table-cell/).test(item.css("display"));
13137
_create: function() {
13139
var o = this.options;
13140
this.containerCache = {};
13141
this.element.addClass("ui-sortable");
13146
//Let's determine if the items are being displayed horizontally
13147
this.floating = this.items.length ? o.axis === "x" || this._isFloating(this.items[0].item) : false;
13149
//Let's determine the parent's offset
13150
this.offset = this.element.offset();
13152
//Initialize mouse events for interaction
13155
this._setHandleClassName();
13157
//We're ready to go
13162
_setOption: function( key, value ) {
13163
this._super( key, value );
13165
if ( key === "handle" ) {
13166
this._setHandleClassName();
13170
_setHandleClassName: function() {
13171
this.element.find( ".ui-sortable-handle" ).removeClass( "ui-sortable-handle" );
13172
$.each( this.items, function() {
13173
( this.instance.options.handle ?
13174
this.item.find( this.instance.options.handle ) : this.item )
13175
.addClass( "ui-sortable-handle" );
13179
_destroy: function() {
13181
.removeClass( "ui-sortable ui-sortable-disabled" )
13182
.find( ".ui-sortable-handle" )
13183
.removeClass( "ui-sortable-handle" );
13184
this._mouseDestroy();
13186
for ( var i = this.items.length - 1; i >= 0; i-- ) {
13187
this.items[i].item.removeData(this.widgetName + "-item");
13193
_mouseCapture: function(event, overrideHandle) {
13194
var currentItem = null,
13195
validHandle = false,
13198
if (this.reverting) {
13202
if(this.options.disabled || this.options.type === "static") {
13206
//We have to refresh the items data once first
13207
this._refreshItems(event);
13209
//Find out if the clicked node (or one of its parents) is a actual item in this.items
13210
$(event.target).parents().each(function() {
13211
if($.data(this, that.widgetName + "-item") === that) {
13212
currentItem = $(this);
13216
if($.data(event.target, that.widgetName + "-item") === that) {
13217
currentItem = $(event.target);
13223
if(this.options.handle && !overrideHandle) {
13224
$(this.options.handle, currentItem).find("*").addBack().each(function() {
13225
if(this === event.target) {
13226
validHandle = true;
13234
this.currentItem = currentItem;
13235
this._removeCurrentsFromItems();
13240
_mouseStart: function(event, overrideHandle, noActivation) {
13245
this.currentContainer = this;
13247
//We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture
13248
this.refreshPositions();
13250
//Create and append the visible helper
13251
this.helper = this._createHelper(event);
13253
//Cache the helper size
13254
this._cacheHelperProportions();
13257
* - Position generation -
13258
* This block generates everything position related - it's the core of draggables.
13261
//Cache the margins of the original element
13262
this._cacheMargins();
13264
//Get the next scrolling parent
13265
this.scrollParent = this.helper.scrollParent();
13267
//The element's absolute position on the page minus margins
13268
this.offset = this.currentItem.offset();
13270
top: this.offset.top - this.margins.top,
13271
left: this.offset.left - this.margins.left
13274
$.extend(this.offset, {
13275
click: { //Where the click happened, relative to the element
13276
left: event.pageX - this.offset.left,
13277
top: event.pageY - this.offset.top
13279
parent: this._getParentOffset(),
13280
relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
13283
// Only after we got the offset, we can change the helper's position to absolute
13284
// TODO: Still need to figure out a way to make relative sorting possible
13285
this.helper.css("position", "absolute");
13286
this.cssPosition = this.helper.css("position");
13288
//Generate the original position
13289
this.originalPosition = this._generatePosition(event);
13290
this.originalPageX = event.pageX;
13291
this.originalPageY = event.pageY;
13293
//Adjust the mouse offset relative to the helper if "cursorAt" is supplied
13294
(o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
13296
//Cache the former DOM position
13297
this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] };
13299
//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
13300
if(this.helper[0] !== this.currentItem[0]) {
13301
this.currentItem.hide();
13304
//Create the placeholder
13305
this._createPlaceholder();
13307
//Set a containment if given in the options
13308
if(o.containment) {
13309
this._setContainment();
13312
if( o.cursor && o.cursor !== "auto" ) { // cursor option
13313
body = this.document.find( "body" );
13316
this.storedCursor = body.css( "cursor" );
13317
body.css( "cursor", o.cursor );
13319
this.storedStylesheet = $( "<style>*{ cursor: "+o.cursor+" !important; }</style>" ).appendTo( body );
13322
if(o.opacity) { // opacity option
13323
if (this.helper.css("opacity")) {
13324
this._storedOpacity = this.helper.css("opacity");
13326
this.helper.css("opacity", o.opacity);
13329
if(o.zIndex) { // zIndex option
13330
if (this.helper.css("zIndex")) {
13331
this._storedZIndex = this.helper.css("zIndex");
13333
this.helper.css("zIndex", o.zIndex);
13336
//Prepare scrolling
13337
if(this.scrollParent[0] !== document && this.scrollParent[0].tagName !== "HTML") {
13338
this.overflowOffset = this.scrollParent.offset();
13342
this._trigger("start", event, this._uiHash());
13344
//Recache the helper size
13345
if(!this._preserveHelperProportions) {
13346
this._cacheHelperProportions();
13350
//Post "activate" events to possible containers
13351
if( !noActivation ) {
13352
for ( i = this.containers.length - 1; i >= 0; i-- ) {
13353
this.containers[ i ]._trigger( "activate", event, this._uiHash( this ) );
13357
//Prepare possible droppables
13358
if($.ui.ddmanager) {
13359
$.ui.ddmanager.current = this;
13362
if ($.ui.ddmanager && !o.dropBehaviour) {
13363
$.ui.ddmanager.prepareOffsets(this, event);
13366
this.dragging = true;
13368
this.helper.addClass("ui-sortable-helper");
13369
this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position
13374
_mouseDrag: function(event) {
13375
var i, item, itemElement, intersection,
13379
//Compute the helpers position
13380
this.position = this._generatePosition(event);
13381
this.positionAbs = this._convertPositionTo("absolute");
13383
if (!this.lastPositionAbs) {
13384
this.lastPositionAbs = this.positionAbs;
13388
if(this.options.scroll) {
13389
if(this.scrollParent[0] !== document && this.scrollParent[0].tagName !== "HTML") {
13391
if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) {
13392
this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed;
13393
} else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity) {
13394
this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed;
13397
if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) {
13398
this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed;
13399
} else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity) {
13400
this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed;
13405
if(event.pageY - $(document).scrollTop() < o.scrollSensitivity) {
13406
scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
13407
} else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) {
13408
scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
13411
if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity) {
13412
scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
13413
} else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) {
13414
scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
13419
if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) {
13420
$.ui.ddmanager.prepareOffsets(this, event);
13424
//Regenerate the absolute position used for position checks
13425
this.positionAbs = this._convertPositionTo("absolute");
13427
//Set the helper position
13428
if(!this.options.axis || this.options.axis !== "y") {
13429
this.helper[0].style.left = this.position.left+"px";
13431
if(!this.options.axis || this.options.axis !== "x") {
13432
this.helper[0].style.top = this.position.top+"px";
13436
for (i = this.items.length - 1; i >= 0; i--) {
13438
//Cache variables and intersection, continue if no intersection
13439
item = this.items[i];
13440
itemElement = item.item[0];
13441
intersection = this._intersectsWithPointer(item);
13442
if (!intersection) {
13446
// Only put the placeholder inside the current Container, skip all
13447
// items from other containers. This works because when moving
13448
// an item from one container to another the
13449
// currentContainer is switched before the placeholder is moved.
13451
// Without this, moving items in "sub-sortables" can cause
13452
// the placeholder to jitter between the outer and inner container.
13453
if (item.instance !== this.currentContainer) {
13457
// cannot intersect with itself
13458
// no useless actions that have been done before
13459
// no action if the item moved is the parent of the item checked
13460
if (itemElement !== this.currentItem[0] &&
13461
this.placeholder[intersection === 1 ? "next" : "prev"]()[0] !== itemElement &&
13462
!$.contains(this.placeholder[0], itemElement) &&
13463
(this.options.type === "semi-dynamic" ? !$.contains(this.element[0], itemElement) : true)
13466
this.direction = intersection === 1 ? "down" : "up";
13468
if (this.options.tolerance === "pointer" || this._intersectsWithSides(item)) {
13469
this._rearrange(event, item);
13474
this._trigger("change", event, this._uiHash());
13479
//Post events to containers
13480
this._contactContainers(event);
13482
//Interconnect with droppables
13483
if($.ui.ddmanager) {
13484
$.ui.ddmanager.drag(this, event);
13488
this._trigger("sort", event, this._uiHash());
13490
this.lastPositionAbs = this.positionAbs;
13495
_mouseStop: function(event, noPropagation) {
13501
//If we are using droppables, inform the manager about the drop
13502
if ($.ui.ddmanager && !this.options.dropBehaviour) {
13503
$.ui.ddmanager.drop(this, event);
13506
if(this.options.revert) {
13508
cur = this.placeholder.offset(),
13509
axis = this.options.axis,
13512
if ( !axis || axis === "x" ) {
13513
animation.left = cur.left - this.offset.parent.left - this.margins.left + (this.offsetParent[0] === document.body ? 0 : this.offsetParent[0].scrollLeft);
13515
if ( !axis || axis === "y" ) {
13516
animation.top = cur.top - this.offset.parent.top - this.margins.top + (this.offsetParent[0] === document.body ? 0 : this.offsetParent[0].scrollTop);
13518
this.reverting = true;
13519
$(this.helper).animate( animation, parseInt(this.options.revert, 10) || 500, function() {
13520
that._clear(event);
13523
this._clear(event, noPropagation);
13530
cancel: function() {
13532
if(this.dragging) {
13534
this._mouseUp({ target: null });
13536
if(this.options.helper === "original") {
13537
this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
13539
this.currentItem.show();
13542
//Post deactivating events to containers
13543
for (var i = this.containers.length - 1; i >= 0; i--){
13544
this.containers[i]._trigger("deactivate", null, this._uiHash(this));
13545
if(this.containers[i].containerCache.over) {
13546
this.containers[i]._trigger("out", null, this._uiHash(this));
13547
this.containers[i].containerCache.over = 0;
13553
if (this.placeholder) {
13554
//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
13555
if(this.placeholder[0].parentNode) {
13556
this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
13558
if(this.options.helper !== "original" && this.helper && this.helper[0].parentNode) {
13559
this.helper.remove();
13569
if(this.domPosition.prev) {
13570
$(this.domPosition.prev).after(this.currentItem);
13572
$(this.domPosition.parent).prepend(this.currentItem);
13580
serialize: function(o) {
13582
var items = this._getItemsAsjQuery(o && o.connected),
13586
$(items).each(function() {
13587
var res = ($(o.item || this).attr(o.attribute || "id") || "").match(o.expression || (/(.+)[\-=_](.+)/));
13589
str.push((o.key || res[1]+"[]")+"="+(o.key && o.expression ? res[1] : res[2]));
13593
if(!str.length && o.key) {
13594
str.push(o.key + "=");
13597
return str.join("&");
13601
toArray: function(o) {
13603
var items = this._getItemsAsjQuery(o && o.connected),
13608
items.each(function() { ret.push($(o.item || this).attr(o.attribute || "id") || ""); });
13613
/* Be careful with the following core functions */
13614
_intersectsWith: function(item) {
13616
var x1 = this.positionAbs.left,
13617
x2 = x1 + this.helperProportions.width,
13618
y1 = this.positionAbs.top,
13619
y2 = y1 + this.helperProportions.height,
13621
r = l + item.width,
13623
b = t + item.height,
13624
dyClick = this.offset.click.top,
13625
dxClick = this.offset.click.left,
13626
isOverElementHeight = ( this.options.axis === "x" ) || ( ( y1 + dyClick ) > t && ( y1 + dyClick ) < b ),
13627
isOverElementWidth = ( this.options.axis === "y" ) || ( ( x1 + dxClick ) > l && ( x1 + dxClick ) < r ),
13628
isOverElement = isOverElementHeight && isOverElementWidth;
13630
if ( this.options.tolerance === "pointer" ||
13631
this.options.forcePointerForContainers ||
13632
(this.options.tolerance !== "pointer" && this.helperProportions[this.floating ? "width" : "height"] > item[this.floating ? "width" : "height"])
13634
return isOverElement;
13637
return (l < x1 + (this.helperProportions.width / 2) && // Right Half
13638
x2 - (this.helperProportions.width / 2) < r && // Left Half
13639
t < y1 + (this.helperProportions.height / 2) && // Bottom Half
13640
y2 - (this.helperProportions.height / 2) < b ); // Top Half
13645
_intersectsWithPointer: function(item) {
13647
var isOverElementHeight = (this.options.axis === "x") || this._isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height),
13648
isOverElementWidth = (this.options.axis === "y") || this._isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width),
13649
isOverElement = isOverElementHeight && isOverElementWidth,
13650
verticalDirection = this._getDragVerticalDirection(),
13651
horizontalDirection = this._getDragHorizontalDirection();
13653
if (!isOverElement) {
13657
return this.floating ?
13658
( ((horizontalDirection && horizontalDirection === "right") || verticalDirection === "down") ? 2 : 1 )
13659
: ( verticalDirection && (verticalDirection === "down" ? 2 : 1) );
13663
_intersectsWithSides: function(item) {
13665
var isOverBottomHalf = this._isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height),
13666
isOverRightHalf = this._isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width),
13667
verticalDirection = this._getDragVerticalDirection(),
13668
horizontalDirection = this._getDragHorizontalDirection();
13670
if (this.floating && horizontalDirection) {
13671
return ((horizontalDirection === "right" && isOverRightHalf) || (horizontalDirection === "left" && !isOverRightHalf));
13673
return verticalDirection && ((verticalDirection === "down" && isOverBottomHalf) || (verticalDirection === "up" && !isOverBottomHalf));
13678
_getDragVerticalDirection: function() {
13679
var delta = this.positionAbs.top - this.lastPositionAbs.top;
13680
return delta !== 0 && (delta > 0 ? "down" : "up");
13683
_getDragHorizontalDirection: function() {
13684
var delta = this.positionAbs.left - this.lastPositionAbs.left;
13685
return delta !== 0 && (delta > 0 ? "right" : "left");
13688
refresh: function(event) {
13689
this._refreshItems(event);
13690
this._setHandleClassName();
13691
this.refreshPositions();
13695
_connectWith: function() {
13696
var options = this.options;
13697
return options.connectWith.constructor === String ? [options.connectWith] : options.connectWith;
13700
_getItemsAsjQuery: function(connected) {
13702
var i, j, cur, inst,
13705
connectWith = this._connectWith();
13707
if(connectWith && connected) {
13708
for (i = connectWith.length - 1; i >= 0; i--){
13709
cur = $(connectWith[i]);
13710
for ( j = cur.length - 1; j >= 0; j--){
13711
inst = $.data(cur[j], this.widgetFullName);
13712
if(inst && inst !== this && !inst.options.disabled) {
13713
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]);
13719
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]);
13721
function addItems() {
13722
items.push( this );
13724
for (i = queries.length - 1; i >= 0; i--){
13725
queries[i][0].each( addItems );
13732
_removeCurrentsFromItems: function() {
13734
var list = this.currentItem.find(":data(" + this.widgetName + "-item)");
13736
this.items = $.grep(this.items, function (item) {
13737
for (var j=0; j < list.length; j++) {
13738
if(list[j] === item.item[0]) {
13747
_refreshItems: function(event) {
13750
this.containers = [this];
13752
var i, j, cur, inst, targetData, _queries, item, queriesLength,
13753
items = this.items,
13754
queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]],
13755
connectWith = this._connectWith();
13757
if(connectWith && this.ready) { //Shouldn't be run the first time through due to massive slow-down
13758
for (i = connectWith.length - 1; i >= 0; i--){
13759
cur = $(connectWith[i]);
13760
for (j = cur.length - 1; j >= 0; j--){
13761
inst = $.data(cur[j], this.widgetFullName);
13762
if(inst && inst !== this && !inst.options.disabled) {
13763
queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]);
13764
this.containers.push(inst);
13770
for (i = queries.length - 1; i >= 0; i--) {
13771
targetData = queries[i][1];
13772
_queries = queries[i][0];
13774
for (j=0, queriesLength = _queries.length; j < queriesLength; j++) {
13775
item = $(_queries[j]);
13777
item.data(this.widgetName + "-item", targetData); // Data for target checking (mouse manager)
13781
instance: targetData,
13782
width: 0, height: 0,
13790
refreshPositions: function(fast) {
13792
//This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change
13793
if(this.offsetParent && this.helper) {
13794
this.offset.parent = this._getParentOffset();
13799
for (i = this.items.length - 1; i >= 0; i--){
13800
item = this.items[i];
13802
//We ignore calculating positions of all connected containers when we're not over them
13803
if(item.instance !== this.currentContainer && this.currentContainer && item.item[0] !== this.currentItem[0]) {
13807
t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item;
13810
item.width = t.outerWidth();
13811
item.height = t.outerHeight();
13815
item.left = p.left;
13819
if(this.options.custom && this.options.custom.refreshContainers) {
13820
this.options.custom.refreshContainers.call(this);
13822
for (i = this.containers.length - 1; i >= 0; i--){
13823
p = this.containers[i].element.offset();
13824
this.containers[i].containerCache.left = p.left;
13825
this.containers[i].containerCache.top = p.top;
13826
this.containers[i].containerCache.width = this.containers[i].element.outerWidth();
13827
this.containers[i].containerCache.height = this.containers[i].element.outerHeight();
13834
_createPlaceholder: function(that) {
13835
that = that || this;
13839
if(!o.placeholder || o.placeholder.constructor === String) {
13840
className = o.placeholder;
13842
element: function() {
13844
var nodeName = that.currentItem[0].nodeName.toLowerCase(),
13845
element = $( "<" + nodeName + ">", that.document[0] )
13846
.addClass(className || that.currentItem[0].className+" ui-sortable-placeholder")
13847
.removeClass("ui-sortable-helper");
13849
if ( nodeName === "tr" ) {
13850
that.currentItem.children().each(function() {
13851
$( "<td> </td>", that.document[0] )
13852
.attr( "colspan", $( this ).attr( "colspan" ) || 1 )
13853
.appendTo( element );
13855
} else if ( nodeName === "img" ) {
13856
element.attr( "src", that.currentItem.attr( "src" ) );
13859
if ( !className ) {
13860
element.css( "visibility", "hidden" );
13865
update: function(container, p) {
13867
// 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that
13868
// 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified
13869
if(className && !o.forcePlaceholderSize) {
13873
//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
13874
if(!p.height()) { p.height(that.currentItem.innerHeight() - parseInt(that.currentItem.css("paddingTop")||0, 10) - parseInt(that.currentItem.css("paddingBottom")||0, 10)); }
13875
if(!p.width()) { p.width(that.currentItem.innerWidth() - parseInt(that.currentItem.css("paddingLeft")||0, 10) - parseInt(that.currentItem.css("paddingRight")||0, 10)); }
13880
//Create the placeholder
13881
that.placeholder = $(o.placeholder.element.call(that.element, that.currentItem));
13883
//Append it after the actual current item
13884
that.currentItem.after(that.placeholder);
13886
//Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
13887
o.placeholder.update(that, that.placeholder);
13891
_contactContainers: function(event) {
13892
var i, j, dist, itemWithLeastDistance, posProperty, sizeProperty, cur, nearBottom, floating, axis,
13893
innermostContainer = null,
13894
innermostIndex = null;
13896
// get innermost container that intersects with item
13897
for (i = this.containers.length - 1; i >= 0; i--) {
13899
// never consider a container that's located within the item itself
13900
if($.contains(this.currentItem[0], this.containers[i].element[0])) {
13904
if(this._intersectsWith(this.containers[i].containerCache)) {
13906
// if we've already found a container and it's more "inner" than this, then continue
13907
if(innermostContainer && $.contains(this.containers[i].element[0], innermostContainer.element[0])) {
13911
innermostContainer = this.containers[i];
13912
innermostIndex = i;
13915
// container doesn't intersect. trigger "out" event if necessary
13916
if(this.containers[i].containerCache.over) {
13917
this.containers[i]._trigger("out", event, this._uiHash(this));
13918
this.containers[i].containerCache.over = 0;
13924
// if no intersecting containers found, return
13925
if(!innermostContainer) {
13929
// move the item into the container if it's not there already
13930
if(this.containers.length === 1) {
13931
if (!this.containers[innermostIndex].containerCache.over) {
13932
this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
13933
this.containers[innermostIndex].containerCache.over = 1;
13937
//When entering a new container, we will find the item with the least distance and append our item near it
13939
itemWithLeastDistance = null;
13940
floating = innermostContainer.floating || this._isFloating(this.currentItem);
13941
posProperty = floating ? "left" : "top";
13942
sizeProperty = floating ? "width" : "height";
13943
axis = floating ? "clientX" : "clientY";
13945
for (j = this.items.length - 1; j >= 0; j--) {
13946
if(!$.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) {
13949
if(this.items[j].item[0] === this.currentItem[0]) {
13953
cur = this.items[j].item.offset()[posProperty];
13954
nearBottom = false;
13955
if ( event[ axis ] - cur > this.items[ j ][ sizeProperty ] / 2 ) {
13959
if ( Math.abs( event[ axis ] - cur ) < dist ) {
13960
dist = Math.abs( event[ axis ] - cur );
13961
itemWithLeastDistance = this.items[ j ];
13962
this.direction = nearBottom ? "up": "down";
13966
//Check if dropOnEmpty is enabled
13967
if(!itemWithLeastDistance && !this.options.dropOnEmpty) {
13971
if(this.currentContainer === this.containers[innermostIndex]) {
13975
itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true);
13976
this._trigger("change", event, this._uiHash());
13977
this.containers[innermostIndex]._trigger("change", event, this._uiHash(this));
13978
this.currentContainer = this.containers[innermostIndex];
13980
//Update the placeholder
13981
this.options.placeholder.update(this.currentContainer, this.placeholder);
13983
this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
13984
this.containers[innermostIndex].containerCache.over = 1;
13990
_createHelper: function(event) {
13992
var o = this.options,
13993
helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper === "clone" ? this.currentItem.clone() : this.currentItem);
13995
//Add the helper to the DOM if that didn't happen already
13996
if(!helper.parents("body").length) {
13997
$(o.appendTo !== "parent" ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]);
14000
if(helper[0] === this.currentItem[0]) {
14001
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") };
14004
if(!helper[0].style.width || o.forceHelperSize) {
14005
helper.width(this.currentItem.width());
14007
if(!helper[0].style.height || o.forceHelperSize) {
14008
helper.height(this.currentItem.height());
14015
_adjustOffsetFromHelper: function(obj) {
14016
if (typeof obj === "string") {
14017
obj = obj.split(" ");
14019
if ($.isArray(obj)) {
14020
obj = {left: +obj[0], top: +obj[1] || 0};
14022
if ("left" in obj) {
14023
this.offset.click.left = obj.left + this.margins.left;
14025
if ("right" in obj) {
14026
this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
14028
if ("top" in obj) {
14029
this.offset.click.top = obj.top + this.margins.top;
14031
if ("bottom" in obj) {
14032
this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
14036
_getParentOffset: function() {
14039
//Get the offsetParent and cache its position
14040
this.offsetParent = this.helper.offsetParent();
14041
var po = this.offsetParent.offset();
14043
// This is a special case where we need to modify a offset calculated on start, since the following happened:
14044
// 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
14045
// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
14046
// the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
14047
if(this.cssPosition === "absolute" && this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) {
14048
po.left += this.scrollParent.scrollLeft();
14049
po.top += this.scrollParent.scrollTop();
14052
// This needs to be actually done for all browsers, since pageX/pageY includes this information
14053
// with an ugly IE fix
14054
if( this.offsetParent[0] === document.body || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() === "html" && $.ui.ie)) {
14055
po = { top: 0, left: 0 };
14059
top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
14060
left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
14065
_getRelativeOffset: function() {
14067
if(this.cssPosition === "relative") {
14068
var p = this.currentItem.position();
14070
top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
14071
left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
14074
return { top: 0, left: 0 };
14079
_cacheMargins: function() {
14081
left: (parseInt(this.currentItem.css("marginLeft"),10) || 0),
14082
top: (parseInt(this.currentItem.css("marginTop"),10) || 0)
14086
_cacheHelperProportions: function() {
14087
this.helperProportions = {
14088
width: this.helper.outerWidth(),
14089
height: this.helper.outerHeight()
14093
_setContainment: function() {
14097
if(o.containment === "parent") {
14098
o.containment = this.helper[0].parentNode;
14100
if(o.containment === "document" || o.containment === "window") {
14101
this.containment = [
14102
0 - this.offset.relative.left - this.offset.parent.left,
14103
0 - this.offset.relative.top - this.offset.parent.top,
14104
$(o.containment === "document" ? document : window).width() - this.helperProportions.width - this.margins.left,
14105
($(o.containment === "document" ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
14109
if(!(/^(document|window|parent)$/).test(o.containment)) {
14110
ce = $(o.containment)[0];
14111
co = $(o.containment).offset();
14112
over = ($(ce).css("overflow") !== "hidden");
14114
this.containment = [
14115
co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
14116
co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
14117
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,
14118
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
14124
_convertPositionTo: function(d, pos) {
14127
pos = this.position;
14129
var mod = d === "absolute" ? 1 : -1,
14130
scroll = this.cssPosition === "absolute" && !(this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent,
14131
scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
14135
pos.top + // The absolute mouse position
14136
this.offset.relative.top * mod + // Only for relative positioned nodes: Relative offset from element to offset parent
14137
this.offset.parent.top * mod - // The offsetParent's offset without borders (offset + border)
14138
( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
14141
pos.left + // The absolute mouse position
14142
this.offset.relative.left * mod + // Only for relative positioned nodes: Relative offset from element to offset parent
14143
this.offset.parent.left * mod - // The offsetParent's offset without borders (offset + border)
14144
( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
14150
_generatePosition: function(event) {
14154
pageX = event.pageX,
14155
pageY = event.pageY,
14156
scroll = this.cssPosition === "absolute" && !(this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
14158
// This is another very weird special case that only happens for relative elements:
14159
// 1. If the css position is relative
14160
// 2. and the scroll parent is the document or similar to the offset parent
14161
// we have to refresh the relative offset during the scroll so there are no jumps
14162
if(this.cssPosition === "relative" && !(this.scrollParent[0] !== document && this.scrollParent[0] !== this.offsetParent[0])) {
14163
this.offset.relative = this._getRelativeOffset();
14167
* - Position constraining -
14168
* Constrain the position to a mix of grid, containment.
14171
if(this.originalPosition) { //If we are not dragging yet, we won't check for options
14173
if(this.containment) {
14174
if(event.pageX - this.offset.click.left < this.containment[0]) {
14175
pageX = this.containment[0] + this.offset.click.left;
14177
if(event.pageY - this.offset.click.top < this.containment[1]) {
14178
pageY = this.containment[1] + this.offset.click.top;
14180
if(event.pageX - this.offset.click.left > this.containment[2]) {
14181
pageX = this.containment[2] + this.offset.click.left;
14183
if(event.pageY - this.offset.click.top > this.containment[3]) {
14184
pageY = this.containment[3] + this.offset.click.top;
14189
top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
14190
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;
14192
left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
14193
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;
14200
pageY - // The absolute mouse position
14201
this.offset.click.top - // Click offset (relative to the element)
14202
this.offset.relative.top - // Only for relative positioned nodes: Relative offset from element to offset parent
14203
this.offset.parent.top + // The offsetParent's offset without borders (offset + border)
14204
( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
14207
pageX - // The absolute mouse position
14208
this.offset.click.left - // Click offset (relative to the element)
14209
this.offset.relative.left - // Only for relative positioned nodes: Relative offset from element to offset parent
14210
this.offset.parent.left + // The offsetParent's offset without borders (offset + border)
14211
( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
14217
_rearrange: function(event, i, a, hardRefresh) {
14219
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));
14221
//Various things done here to improve the performance:
14222
// 1. we create a setTimeout, that calls refreshPositions
14223
// 2. on the instance, we have a counter variable, that get's higher after every append
14224
// 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same
14225
// 4. this lets only the last addition to the timeout stack through
14226
this.counter = this.counter ? ++this.counter : 1;
14227
var counter = this.counter;
14229
this._delay(function() {
14230
if(counter === this.counter) {
14231
this.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove
14237
_clear: function(event, noPropagation) {
14239
this.reverting = false;
14240
// We delay all events that have to be triggered to after the point where the placeholder has been removed and
14241
// everything else normalized again
14243
delayedTriggers = [];
14245
// We first have to update the dom position of the actual currentItem
14246
// Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088)
14247
if(!this._noFinalSort && this.currentItem.parent().length) {
14248
this.placeholder.before(this.currentItem);
14250
this._noFinalSort = null;
14252
if(this.helper[0] === this.currentItem[0]) {
14253
for(i in this._storedCSS) {
14254
if(this._storedCSS[i] === "auto" || this._storedCSS[i] === "static") {
14255
this._storedCSS[i] = "";
14258
this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
14260
this.currentItem.show();
14263
if(this.fromOutside && !noPropagation) {
14264
delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); });
14266
if((this.fromOutside || this.domPosition.prev !== this.currentItem.prev().not(".ui-sortable-helper")[0] || this.domPosition.parent !== this.currentItem.parent()[0]) && !noPropagation) {
14267
delayedTriggers.push(function(event) { this._trigger("update", event, this._uiHash()); }); //Trigger update callback if the DOM position has changed
14270
// Check if the items Container has Changed and trigger appropriate
14272
if (this !== this.currentContainer) {
14273
if(!noPropagation) {
14274
delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); });
14275
delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); }; }).call(this, this.currentContainer));
14276
delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this)); }; }).call(this, this.currentContainer));
14281
//Post events to containers
14282
function delayEvent( type, instance, container ) {
14283
return function( event ) {
14284
container._trigger( type, event, instance._uiHash( instance ) );
14287
for (i = this.containers.length - 1; i >= 0; i--){
14288
if (!noPropagation) {
14289
delayedTriggers.push( delayEvent( "deactivate", this, this.containers[ i ] ) );
14291
if(this.containers[i].containerCache.over) {
14292
delayedTriggers.push( delayEvent( "out", this, this.containers[ i ] ) );
14293
this.containers[i].containerCache.over = 0;
14297
//Do what was originally in plugins
14298
if ( this.storedCursor ) {
14299
this.document.find( "body" ).css( "cursor", this.storedCursor );
14300
this.storedStylesheet.remove();
14302
if(this._storedOpacity) {
14303
this.helper.css("opacity", this._storedOpacity);
14305
if(this._storedZIndex) {
14306
this.helper.css("zIndex", this._storedZIndex === "auto" ? "" : this._storedZIndex);
14309
this.dragging = false;
14310
if(this.cancelHelperRemoval) {
14311
if(!noPropagation) {
14312
this._trigger("beforeStop", event, this._uiHash());
14313
for (i=0; i < delayedTriggers.length; i++) {
14314
delayedTriggers[i].call(this, event);
14315
} //Trigger all delayed events
14316
this._trigger("stop", event, this._uiHash());
14319
this.fromOutside = false;
14323
if(!noPropagation) {
14324
this._trigger("beforeStop", event, this._uiHash());
14327
//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
14328
this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
14330
if(this.helper[0] !== this.currentItem[0]) {
14331
this.helper.remove();
14333
this.helper = null;
14335
if(!noPropagation) {
14336
for (i=0; i < delayedTriggers.length; i++) {
14337
delayedTriggers[i].call(this, event);
14338
} //Trigger all delayed events
14339
this._trigger("stop", event, this._uiHash());
14342
this.fromOutside = false;
14347
_trigger: function() {
14348
if ($.Widget.prototype._trigger.apply(this, arguments) === false) {
14353
_uiHash: function(_inst) {
14354
var inst = _inst || this;
14356
helper: inst.helper,
14357
placeholder: inst.placeholder || $([]),
14358
position: inst.position,
14359
originalPosition: inst.originalPosition,
14360
offset: inst.positionAbs,
14361
item: inst.currentItem,
14362
sender: _inst ? _inst.element : null
14370
* jQuery UI Spinner 1.11.0
14371
* http://jqueryui.com
14373
* Copyright 2014 jQuery Foundation and other contributors
14374
* Released under the MIT license.
14375
* http://jquery.org/license
14377
* http://api.jqueryui.com/spinner/
14381
function spinner_modifier( fn ) {
14382
return function() {
14383
var previous = this.element.val();
14384
fn.apply( this, arguments );
14386
if ( previous !== this.element.val() ) {
14387
this._trigger( "change" );
14392
var spinner = $.widget( "ui.spinner", {
14394
defaultElement: "<input>",
14395
widgetEventPrefix: "spin",
14399
down: "ui-icon-triangle-1-s",
14400
up: "ui-icon-triangle-1-n"
14405
numberFormat: null,
14415
_create: function() {
14416
// handle string values that need to be parsed
14417
this._setOption( "max", this.options.max );
14418
this._setOption( "min", this.options.min );
14419
this._setOption( "step", this.options.step );
14421
// Only format if there is a value, prevents the field from being marked
14422
// as invalid in Firefox, see #9573.
14423
if ( this.value() !== "" ) {
14424
// Format the value, but don't constrain.
14425
this._value( this.element.val(), true );
14429
this._on( this._events );
14432
// turning off autocomplete prevents the browser from remembering the
14433
// value when navigating through history, so we re-enable autocomplete
14434
// if the page is unloaded before the widget is destroyed. #7790
14435
this._on( this.window, {
14436
beforeunload: function() {
14437
this.element.removeAttr( "autocomplete" );
14442
_getCreateOptions: function() {
14444
element = this.element;
14446
$.each( [ "min", "max", "step" ], function( i, option ) {
14447
var value = element.attr( option );
14448
if ( value !== undefined && value.length ) {
14449
options[ option ] = value;
14457
keydown: function( event ) {
14458
if ( this._start( event ) && this._keydown( event ) ) {
14459
event.preventDefault();
14463
focus: function() {
14464
this.previous = this.element.val();
14466
blur: function( event ) {
14467
if ( this.cancelBlur ) {
14468
delete this.cancelBlur;
14474
if ( this.previous !== this.element.val() ) {
14475
this._trigger( "change", event );
14478
mousewheel: function( event, delta ) {
14482
if ( !this.spinning && !this._start( event ) ) {
14486
this._spin( (delta > 0 ? 1 : -1) * this.options.step, event );
14487
clearTimeout( this.mousewheelTimer );
14488
this.mousewheelTimer = this._delay(function() {
14489
if ( this.spinning ) {
14490
this._stop( event );
14493
event.preventDefault();
14495
"mousedown .ui-spinner-button": function( event ) {
14498
// We never want the buttons to have focus; whenever the user is
14499
// interacting with the spinner, the focus should be on the input.
14500
// If the input is focused then this.previous is properly set from
14501
// when the input first received focus. If the input is not focused
14502
// then we need to set this.previous based on the value before spinning.
14503
previous = this.element[0] === this.document[0].activeElement ?
14504
this.previous : this.element.val();
14505
function checkFocus() {
14506
var isActive = this.element[0] === this.document[0].activeElement;
14508
this.element.focus();
14509
this.previous = previous;
14511
// IE sets focus asynchronously, so we need to check if focus
14512
// moved off of the input because the user clicked on the button.
14513
this._delay(function() {
14514
this.previous = previous;
14519
// ensure focus is on (or stays on) the text field
14520
event.preventDefault();
14521
checkFocus.call( this );
14524
// IE doesn't prevent moving focus even with event.preventDefault()
14525
// so we set a flag to know when we should ignore the blur event
14526
// and check (again) if focus moved off of the input.
14527
this.cancelBlur = true;
14528
this._delay(function() {
14529
delete this.cancelBlur;
14530
checkFocus.call( this );
14533
if ( this._start( event ) === false ) {
14537
this._repeat( null, $( event.currentTarget ).hasClass( "ui-spinner-up" ) ? 1 : -1, event );
14539
"mouseup .ui-spinner-button": "_stop",
14540
"mouseenter .ui-spinner-button": function( event ) {
14541
// button will add ui-state-active if mouse was down while mouseleave and kept down
14542
if ( !$( event.currentTarget ).hasClass( "ui-state-active" ) ) {
14546
if ( this._start( event ) === false ) {
14549
this._repeat( null, $( event.currentTarget ).hasClass( "ui-spinner-up" ) ? 1 : -1, event );
14551
// TODO: do we really want to consider this a stop?
14552
// shouldn't we just stop the repeater and wait until mouseup before
14553
// we trigger the stop event?
14554
"mouseleave .ui-spinner-button": "_stop"
14557
_draw: function() {
14558
var uiSpinner = this.uiSpinner = this.element
14559
.addClass( "ui-spinner-input" )
14560
.attr( "autocomplete", "off" )
14561
.wrap( this._uiSpinnerHtml() )
14564
.append( this._buttonHtml() );
14566
this.element.attr( "role", "spinbutton" );
14569
this.buttons = uiSpinner.find( ".ui-spinner-button" )
14570
.attr( "tabIndex", -1 )
14572
.removeClass( "ui-corner-all" );
14574
// IE 6 doesn't understand height: 50% for the buttons
14575
// unless the wrapper has an explicit height
14576
if ( this.buttons.height() > Math.ceil( uiSpinner.height() * 0.5 ) &&
14577
uiSpinner.height() > 0 ) {
14578
uiSpinner.height( uiSpinner.height() );
14581
// disable spinner if element was already disabled
14582
if ( this.options.disabled ) {
14587
_keydown: function( event ) {
14588
var options = this.options,
14589
keyCode = $.ui.keyCode;
14591
switch ( event.keyCode ) {
14593
this._repeat( null, 1, event );
14596
this._repeat( null, -1, event );
14598
case keyCode.PAGE_UP:
14599
this._repeat( null, options.page, event );
14601
case keyCode.PAGE_DOWN:
14602
this._repeat( null, -options.page, event );
14609
_uiSpinnerHtml: function() {
14610
return "<span class='ui-spinner ui-widget ui-widget-content ui-corner-all'></span>";
14613
_buttonHtml: function() {
14615
"<a class='ui-spinner-button ui-spinner-up ui-corner-tr'>" +
14616
"<span class='ui-icon " + this.options.icons.up + "'>▲</span>" +
14618
"<a class='ui-spinner-button ui-spinner-down ui-corner-br'>" +
14619
"<span class='ui-icon " + this.options.icons.down + "'>▼</span>" +
14623
_start: function( event ) {
14624
if ( !this.spinning && this._trigger( "start", event ) === false ) {
14628
if ( !this.counter ) {
14631
this.spinning = true;
14635
_repeat: function( i, steps, event ) {
14638
clearTimeout( this.timer );
14639
this.timer = this._delay(function() {
14640
this._repeat( 40, steps, event );
14643
this._spin( steps * this.options.step, event );
14646
_spin: function( step, event ) {
14647
var value = this.value() || 0;
14649
if ( !this.counter ) {
14653
value = this._adjustValue( value + step * this._increment( this.counter ) );
14655
if ( !this.spinning || this._trigger( "spin", event, { value: value } ) !== false) {
14656
this._value( value );
14661
_increment: function( i ) {
14662
var incremental = this.options.incremental;
14664
if ( incremental ) {
14665
return $.isFunction( incremental ) ?
14667
Math.floor( i * i * i / 50000 - i * i / 500 + 17 * i / 200 + 1 );
14673
_precision: function() {
14674
var precision = this._precisionOf( this.options.step );
14675
if ( this.options.min !== null ) {
14676
precision = Math.max( precision, this._precisionOf( this.options.min ) );
14681
_precisionOf: function( num ) {
14682
var str = num.toString(),
14683
decimal = str.indexOf( "." );
14684
return decimal === -1 ? 0 : str.length - decimal - 1;
14687
_adjustValue: function( value ) {
14688
var base, aboveMin,
14689
options = this.options;
14691
// make sure we're at a valid step
14692
// - find out where we are relative to the base (min or 0)
14693
base = options.min !== null ? options.min : 0;
14694
aboveMin = value - base;
14695
// - round to the nearest step
14696
aboveMin = Math.round(aboveMin / options.step) * options.step;
14697
// - rounding is based on 0, so adjust back to our base
14698
value = base + aboveMin;
14700
// fix precision from bad JS floating point math
14701
value = parseFloat( value.toFixed( this._precision() ) );
14704
if ( options.max !== null && value > options.max) {
14705
return options.max;
14707
if ( options.min !== null && value < options.min ) {
14708
return options.min;
14714
_stop: function( event ) {
14715
if ( !this.spinning ) {
14719
clearTimeout( this.timer );
14720
clearTimeout( this.mousewheelTimer );
14722
this.spinning = false;
14723
this._trigger( "stop", event );
14726
_setOption: function( key, value ) {
14727
if ( key === "culture" || key === "numberFormat" ) {
14728
var prevValue = this._parse( this.element.val() );
14729
this.options[ key ] = value;
14730
this.element.val( this._format( prevValue ) );
14734
if ( key === "max" || key === "min" || key === "step" ) {
14735
if ( typeof value === "string" ) {
14736
value = this._parse( value );
14739
if ( key === "icons" ) {
14740
this.buttons.first().find( ".ui-icon" )
14741
.removeClass( this.options.icons.up )
14742
.addClass( value.up );
14743
this.buttons.last().find( ".ui-icon" )
14744
.removeClass( this.options.icons.down )
14745
.addClass( value.down );
14748
this._super( key, value );
14750
if ( key === "disabled" ) {
14751
this.widget().toggleClass( "ui-state-disabled", !!value );
14752
this.element.prop( "disabled", !!value );
14753
this.buttons.button( value ? "disable" : "enable" );
14757
_setOptions: spinner_modifier(function( options ) {
14758
this._super( options );
14761
_parse: function( val ) {
14762
if ( typeof val === "string" && val !== "" ) {
14763
val = window.Globalize && this.options.numberFormat ?
14764
Globalize.parseFloat( val, 10, this.options.culture ) : +val;
14766
return val === "" || isNaN( val ) ? null : val;
14769
_format: function( value ) {
14770
if ( value === "" ) {
14773
return window.Globalize && this.options.numberFormat ?
14774
Globalize.format( value, this.options.numberFormat, this.options.culture ) :
14778
_refresh: function() {
14779
this.element.attr({
14780
"aria-valuemin": this.options.min,
14781
"aria-valuemax": this.options.max,
14782
// TODO: what should we do with values that can't be parsed?
14783
"aria-valuenow": this._parse( this.element.val() )
14787
isValid: function() {
14788
var value = this.value();
14791
if ( value === null ) {
14795
// if value gets adjusted, it's invalid
14796
return value === this._adjustValue( value );
14799
// update the value without triggering change
14800
_value: function( value, allowAny ) {
14802
if ( value !== "" ) {
14803
parsed = this._parse( value );
14804
if ( parsed !== null ) {
14806
parsed = this._adjustValue( parsed );
14808
value = this._format( parsed );
14811
this.element.val( value );
14815
_destroy: function() {
14817
.removeClass( "ui-spinner-input" )
14818
.prop( "disabled", false )
14819
.removeAttr( "autocomplete" )
14820
.removeAttr( "role" )
14821
.removeAttr( "aria-valuemin" )
14822
.removeAttr( "aria-valuemax" )
14823
.removeAttr( "aria-valuenow" );
14824
this.uiSpinner.replaceWith( this.element );
14827
stepUp: spinner_modifier(function( steps ) {
14828
this._stepUp( steps );
14830
_stepUp: function( steps ) {
14831
if ( this._start() ) {
14832
this._spin( (steps || 1) * this.options.step );
14837
stepDown: spinner_modifier(function( steps ) {
14838
this._stepDown( steps );
14840
_stepDown: function( steps ) {
14841
if ( this._start() ) {
14842
this._spin( (steps || 1) * -this.options.step );
14847
pageUp: spinner_modifier(function( pages ) {
14848
this._stepUp( (pages || 1) * this.options.page );
14851
pageDown: spinner_modifier(function( pages ) {
14852
this._stepDown( (pages || 1) * this.options.page );
14855
value: function( newVal ) {
14856
if ( !arguments.length ) {
14857
return this._parse( this.element.val() );
14859
spinner_modifier( this._value ).call( this, newVal );
14862
widget: function() {
14863
return this.uiSpinner;
14869
* jQuery UI Tabs 1.11.0
14870
* http://jqueryui.com
14872
* Copyright 2014 jQuery Foundation and other contributors
14873
* Released under the MIT license.
14874
* http://jquery.org/license
14876
* http://api.jqueryui.com/tabs/
14880
var tabs = $.widget( "ui.tabs", {
14885
collapsible: false,
14887
heightStyle: "content",
14893
beforeActivate: null,
14898
_isLocal: (function() {
14899
var rhash = /#.*$/;
14901
return function( anchor ) {
14902
var anchorUrl, locationUrl;
14905
// IE7 doesn't normalize the href property when set via script (#9317)
14906
anchor = anchor.cloneNode( false );
14908
anchorUrl = anchor.href.replace( rhash, "" );
14909
locationUrl = location.href.replace( rhash, "" );
14911
// decoding may throw an error if the URL isn't UTF-8 (#9518)
14913
anchorUrl = decodeURIComponent( anchorUrl );
14914
} catch ( error ) {}
14916
locationUrl = decodeURIComponent( locationUrl );
14917
} catch ( error ) {}
14919
return anchor.hash.length > 1 && anchorUrl === locationUrl;
14923
_create: function() {
14925
options = this.options;
14927
this.running = false;
14930
.addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" )
14931
.toggleClass( "ui-tabs-collapsible", options.collapsible )
14932
// Prevent users from focusing disabled tabs via click
14933
.delegate( ".ui-tabs-nav > li", "mousedown" + this.eventNamespace, function( event ) {
14934
if ( $( this ).is( ".ui-state-disabled" ) ) {
14935
event.preventDefault();
14939
// Preventing the default action in mousedown doesn't prevent IE
14940
// from focusing the element, so if the anchor gets focused, blur.
14941
// We don't have to worry about focusing the previously focused
14942
// element since clicking on a non-focusable element should focus
14943
// the body anyway.
14944
.delegate( ".ui-tabs-anchor", "focus" + this.eventNamespace, function() {
14945
if ( $( this ).closest( "li" ).is( ".ui-state-disabled" ) ) {
14950
this._processTabs();
14951
options.active = this._initialActive();
14953
// Take disabling tabs via class attribute from HTML
14954
// into account and update option properly.
14955
if ( $.isArray( options.disabled ) ) {
14956
options.disabled = $.unique( options.disabled.concat(
14957
$.map( this.tabs.filter( ".ui-state-disabled" ), function( li ) {
14958
return that.tabs.index( li );
14963
// check for length avoids error when initializing empty list
14964
if ( this.options.active !== false && this.anchors.length ) {
14965
this.active = this._findActive( options.active );
14972
if ( this.active.length ) {
14973
this.load( options.active );
14977
_initialActive: function() {
14978
var active = this.options.active,
14979
collapsible = this.options.collapsible,
14980
locationHash = location.hash.substring( 1 );
14982
if ( active === null ) {
14983
// check the fragment identifier in the URL
14984
if ( locationHash ) {
14985
this.tabs.each(function( i, tab ) {
14986
if ( $( tab ).attr( "aria-controls" ) === locationHash ) {
14993
// check for a tab marked active via a class
14994
if ( active === null ) {
14995
active = this.tabs.index( this.tabs.filter( ".ui-tabs-active" ) );
14998
// no active tab, set to false
14999
if ( active === null || active === -1 ) {
15000
active = this.tabs.length ? 0 : false;
15004
// handle numbers: negative, out of range
15005
if ( active !== false ) {
15006
active = this.tabs.index( this.tabs.eq( active ) );
15007
if ( active === -1 ) {
15008
active = collapsible ? false : 0;
15012
// don't allow collapsible: false and active: false
15013
if ( !collapsible && active === false && this.anchors.length ) {
15020
_getCreateEventData: function() {
15023
panel: !this.active.length ? $() : this._getPanelForTab( this.active )
15027
_tabKeydown: function( event ) {
15028
var focusedTab = $( this.document[0].activeElement ).closest( "li" ),
15029
selectedIndex = this.tabs.index( focusedTab ),
15030
goingForward = true;
15032
if ( this._handlePageNav( event ) ) {
15036
switch ( event.keyCode ) {
15037
case $.ui.keyCode.RIGHT:
15038
case $.ui.keyCode.DOWN:
15041
case $.ui.keyCode.UP:
15042
case $.ui.keyCode.LEFT:
15043
goingForward = false;
15046
case $.ui.keyCode.END:
15047
selectedIndex = this.anchors.length - 1;
15049
case $.ui.keyCode.HOME:
15052
case $.ui.keyCode.SPACE:
15053
// Activate only, no collapsing
15054
event.preventDefault();
15055
clearTimeout( this.activating );
15056
this._activate( selectedIndex );
15058
case $.ui.keyCode.ENTER:
15059
// Toggle (cancel delayed activation, allow collapsing)
15060
event.preventDefault();
15061
clearTimeout( this.activating );
15062
// Determine if we should collapse or activate
15063
this._activate( selectedIndex === this.options.active ? false : selectedIndex );
15069
// Focus the appropriate tab, based on which key was pressed
15070
event.preventDefault();
15071
clearTimeout( this.activating );
15072
selectedIndex = this._focusNextTab( selectedIndex, goingForward );
15074
// Navigating with control key will prevent automatic activation
15075
if ( !event.ctrlKey ) {
15076
// Update aria-selected immediately so that AT think the tab is already selected.
15077
// Otherwise AT may confuse the user by stating that they need to activate the tab,
15078
// but the tab will already be activated by the time the announcement finishes.
15079
focusedTab.attr( "aria-selected", "false" );
15080
this.tabs.eq( selectedIndex ).attr( "aria-selected", "true" );
15082
this.activating = this._delay(function() {
15083
this.option( "active", selectedIndex );
15088
_panelKeydown: function( event ) {
15089
if ( this._handlePageNav( event ) ) {
15093
// Ctrl+up moves focus to the current tab
15094
if ( event.ctrlKey && event.keyCode === $.ui.keyCode.UP ) {
15095
event.preventDefault();
15096
this.active.focus();
15100
// Alt+page up/down moves focus to the previous/next tab (and activates)
15101
_handlePageNav: function( event ) {
15102
if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_UP ) {
15103
this._activate( this._focusNextTab( this.options.active - 1, false ) );
15106
if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_DOWN ) {
15107
this._activate( this._focusNextTab( this.options.active + 1, true ) );
15112
_findNextTab: function( index, goingForward ) {
15113
var lastTabIndex = this.tabs.length - 1;
15115
function constrain() {
15116
if ( index > lastTabIndex ) {
15120
index = lastTabIndex;
15125
while ( $.inArray( constrain(), this.options.disabled ) !== -1 ) {
15126
index = goingForward ? index + 1 : index - 1;
15132
_focusNextTab: function( index, goingForward ) {
15133
index = this._findNextTab( index, goingForward );
15134
this.tabs.eq( index ).focus();
15138
_setOption: function( key, value ) {
15139
if ( key === "active" ) {
15140
// _activate() will handle invalid values and update this.options
15141
this._activate( value );
15145
if ( key === "disabled" ) {
15146
// don't use the widget factory's disabled handling
15147
this._setupDisabled( value );
15151
this._super( key, value);
15153
if ( key === "collapsible" ) {
15154
this.element.toggleClass( "ui-tabs-collapsible", value );
15155
// Setting collapsible: false while collapsed; open first panel
15156
if ( !value && this.options.active === false ) {
15157
this._activate( 0 );
15161
if ( key === "event" ) {
15162
this._setupEvents( value );
15165
if ( key === "heightStyle" ) {
15166
this._setupHeightStyle( value );
15170
_sanitizeSelector: function( hash ) {
15171
return hash ? hash.replace( /[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g, "\\$&" ) : "";
15174
refresh: function() {
15175
var options = this.options,
15176
lis = this.tablist.children( ":has(a[href])" );
15178
// get disabled tabs from class attribute from HTML
15179
// this will get converted to a boolean if needed in _refresh()
15180
options.disabled = $.map( lis.filter( ".ui-state-disabled" ), function( tab ) {
15181
return lis.index( tab );
15184
this._processTabs();
15186
// was collapsed or no tabs
15187
if ( options.active === false || !this.anchors.length ) {
15188
options.active = false;
15190
// was active, but active tab is gone
15191
} else if ( this.active.length && !$.contains( this.tablist[ 0 ], this.active[ 0 ] ) ) {
15192
// all remaining tabs are disabled
15193
if ( this.tabs.length === options.disabled.length ) {
15194
options.active = false;
15196
// activate previous tab
15198
this._activate( this._findNextTab( Math.max( 0, options.active - 1 ), false ) );
15200
// was active, active tab still exists
15202
// make sure active index is correct
15203
options.active = this.tabs.index( this.active );
15209
_refresh: function() {
15210
this._setupDisabled( this.options.disabled );
15211
this._setupEvents( this.options.event );
15212
this._setupHeightStyle( this.options.heightStyle );
15214
this.tabs.not( this.active ).attr({
15215
"aria-selected": "false",
15216
"aria-expanded": "false",
15219
this.panels.not( this._getPanelForTab( this.active ) )
15222
"aria-hidden": "true"
15225
// Make sure one tab is in the tab order
15226
if ( !this.active.length ) {
15227
this.tabs.eq( 0 ).attr( "tabIndex", 0 );
15230
.addClass( "ui-tabs-active ui-state-active" )
15232
"aria-selected": "true",
15233
"aria-expanded": "true",
15236
this._getPanelForTab( this.active )
15239
"aria-hidden": "false"
15244
_processTabs: function() {
15247
this.tablist = this._getList()
15248
.addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" )
15249
.attr( "role", "tablist" );
15251
this.tabs = this.tablist.find( "> li:has(a[href])" )
15252
.addClass( "ui-state-default ui-corner-top" )
15258
this.anchors = this.tabs.map(function() {
15259
return $( "a", this )[ 0 ];
15261
.addClass( "ui-tabs-anchor" )
15263
role: "presentation",
15269
this.anchors.each(function( i, anchor ) {
15270
var selector, panel, panelId,
15271
anchorId = $( anchor ).uniqueId().attr( "id" ),
15272
tab = $( anchor ).closest( "li" ),
15273
originalAriaControls = tab.attr( "aria-controls" );
15276
if ( that._isLocal( anchor ) ) {
15277
selector = anchor.hash;
15278
panelId = selector.substring( 1 );
15279
panel = that.element.find( that._sanitizeSelector( selector ) );
15282
// If the tab doesn't already have aria-controls,
15283
// generate an id by using a throw-away element
15284
panelId = tab.attr( "aria-controls" ) || $( {} ).uniqueId()[ 0 ].id;
15285
selector = "#" + panelId;
15286
panel = that.element.find( selector );
15287
if ( !panel.length ) {
15288
panel = that._createPanel( panelId );
15289
panel.insertAfter( that.panels[ i - 1 ] || that.tablist );
15291
panel.attr( "aria-live", "polite" );
15294
if ( panel.length) {
15295
that.panels = that.panels.add( panel );
15297
if ( originalAriaControls ) {
15298
tab.data( "ui-tabs-aria-controls", originalAriaControls );
15301
"aria-controls": panelId,
15302
"aria-labelledby": anchorId
15304
panel.attr( "aria-labelledby", anchorId );
15308
.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
15309
.attr( "role", "tabpanel" );
15312
// allow overriding how to find the list for rare usage scenarios (#7715)
15313
_getList: function() {
15314
return this.tablist || this.element.find( "ol,ul" ).eq( 0 );
15317
_createPanel: function( id ) {
15318
return $( "<div>" )
15320
.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
15321
.data( "ui-tabs-destroy", true );
15324
_setupDisabled: function( disabled ) {
15325
if ( $.isArray( disabled ) ) {
15326
if ( !disabled.length ) {
15328
} else if ( disabled.length === this.anchors.length ) {
15334
for ( var i = 0, li; ( li = this.tabs[ i ] ); i++ ) {
15335
if ( disabled === true || $.inArray( i, disabled ) !== -1 ) {
15337
.addClass( "ui-state-disabled" )
15338
.attr( "aria-disabled", "true" );
15341
.removeClass( "ui-state-disabled" )
15342
.removeAttr( "aria-disabled" );
15346
this.options.disabled = disabled;
15349
_setupEvents: function( event ) {
15352
$.each( event.split(" "), function( index, eventName ) {
15353
events[ eventName ] = "_eventHandler";
15357
this._off( this.anchors.add( this.tabs ).add( this.panels ) );
15358
// Always prevent the default action, even when disabled
15359
this._on( true, this.anchors, {
15360
click: function( event ) {
15361
event.preventDefault();
15364
this._on( this.anchors, events );
15365
this._on( this.tabs, { keydown: "_tabKeydown" } );
15366
this._on( this.panels, { keydown: "_panelKeydown" } );
15368
this._focusable( this.tabs );
15369
this._hoverable( this.tabs );
15372
_setupHeightStyle: function( heightStyle ) {
15374
parent = this.element.parent();
15376
if ( heightStyle === "fill" ) {
15377
maxHeight = parent.height();
15378
maxHeight -= this.element.outerHeight() - this.element.height();
15380
this.element.siblings( ":visible" ).each(function() {
15381
var elem = $( this ),
15382
position = elem.css( "position" );
15384
if ( position === "absolute" || position === "fixed" ) {
15387
maxHeight -= elem.outerHeight( true );
15390
this.element.children().not( this.panels ).each(function() {
15391
maxHeight -= $( this ).outerHeight( true );
15394
this.panels.each(function() {
15395
$( this ).height( Math.max( 0, maxHeight -
15396
$( this ).innerHeight() + $( this ).height() ) );
15398
.css( "overflow", "auto" );
15399
} else if ( heightStyle === "auto" ) {
15401
this.panels.each(function() {
15402
maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() );
15403
}).height( maxHeight );
15407
_eventHandler: function( event ) {
15408
var options = this.options,
15409
active = this.active,
15410
anchor = $( event.currentTarget ),
15411
tab = anchor.closest( "li" ),
15412
clickedIsActive = tab[ 0 ] === active[ 0 ],
15413
collapsing = clickedIsActive && options.collapsible,
15414
toShow = collapsing ? $() : this._getPanelForTab( tab ),
15415
toHide = !active.length ? $() : this._getPanelForTab( active ),
15419
newTab: collapsing ? $() : tab,
15423
event.preventDefault();
15425
if ( tab.hasClass( "ui-state-disabled" ) ||
15426
// tab is already loading
15427
tab.hasClass( "ui-tabs-loading" ) ||
15428
// can't switch durning an animation
15430
// click on active header, but not collapsible
15431
( clickedIsActive && !options.collapsible ) ||
15432
// allow canceling activation
15433
( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
15437
options.active = collapsing ? false : this.tabs.index( tab );
15439
this.active = clickedIsActive ? $() : tab;
15444
if ( !toHide.length && !toShow.length ) {
15445
$.error( "jQuery UI Tabs: Mismatching fragment identifier." );
15448
if ( toShow.length ) {
15449
this.load( this.tabs.index( tab ), event );
15451
this._toggle( event, eventData );
15454
// handles show/hide for selecting tabs
15455
_toggle: function( event, eventData ) {
15457
toShow = eventData.newPanel,
15458
toHide = eventData.oldPanel;
15460
this.running = true;
15462
function complete() {
15463
that.running = false;
15464
that._trigger( "activate", event, eventData );
15468
eventData.newTab.closest( "li" ).addClass( "ui-tabs-active ui-state-active" );
15470
if ( toShow.length && that.options.show ) {
15471
that._show( toShow, that.options.show, complete );
15478
// start out by hiding, then showing, then completing
15479
if ( toHide.length && this.options.hide ) {
15480
this._hide( toHide, this.options.hide, function() {
15481
eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" );
15485
eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" );
15490
toHide.attr( "aria-hidden", "true" );
15491
eventData.oldTab.attr({
15492
"aria-selected": "false",
15493
"aria-expanded": "false"
15495
// If we're switching tabs, remove the old tab from the tab order.
15496
// If we're opening from collapsed state, remove the previous tab from the tab order.
15497
// If we're collapsing, then keep the collapsing tab in the tab order.
15498
if ( toShow.length && toHide.length ) {
15499
eventData.oldTab.attr( "tabIndex", -1 );
15500
} else if ( toShow.length ) {
15501
this.tabs.filter(function() {
15502
return $( this ).attr( "tabIndex" ) === 0;
15504
.attr( "tabIndex", -1 );
15507
toShow.attr( "aria-hidden", "false" );
15508
eventData.newTab.attr({
15509
"aria-selected": "true",
15510
"aria-expanded": "true",
15515
_activate: function( index ) {
15517
active = this._findActive( index );
15519
// trying to activate the already active panel
15520
if ( active[ 0 ] === this.active[ 0 ] ) {
15524
// trying to collapse, simulate a click on the current active header
15525
if ( !active.length ) {
15526
active = this.active;
15529
anchor = active.find( ".ui-tabs-anchor" )[ 0 ];
15530
this._eventHandler({
15532
currentTarget: anchor,
15533
preventDefault: $.noop
15537
_findActive: function( index ) {
15538
return index === false ? $() : this.tabs.eq( index );
15541
_getIndex: function( index ) {
15542
// meta-function to give users option to provide a href string instead of a numerical index.
15543
if ( typeof index === "string" ) {
15544
index = this.anchors.index( this.anchors.filter( "[href$='" + index + "']" ) );
15550
_destroy: function() {
15555
this.element.removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" );
15558
.removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" )
15559
.removeAttr( "role" );
15562
.removeClass( "ui-tabs-anchor" )
15563
.removeAttr( "role" )
15564
.removeAttr( "tabIndex" )
15567
this.tabs.add( this.panels ).each(function() {
15568
if ( $.data( this, "ui-tabs-destroy" ) ) {
15569
$( this ).remove();
15572
.removeClass( "ui-state-default ui-state-active ui-state-disabled " +
15573
"ui-corner-top ui-corner-bottom ui-widget-content ui-tabs-active ui-tabs-panel" )
15574
.removeAttr( "tabIndex" )
15575
.removeAttr( "aria-live" )
15576
.removeAttr( "aria-busy" )
15577
.removeAttr( "aria-selected" )
15578
.removeAttr( "aria-labelledby" )
15579
.removeAttr( "aria-hidden" )
15580
.removeAttr( "aria-expanded" )
15581
.removeAttr( "role" );
15585
this.tabs.each(function() {
15586
var li = $( this ),
15587
prev = li.data( "ui-tabs-aria-controls" );
15590
.attr( "aria-controls", prev )
15591
.removeData( "ui-tabs-aria-controls" );
15593
li.removeAttr( "aria-controls" );
15597
this.panels.show();
15599
if ( this.options.heightStyle !== "content" ) {
15600
this.panels.css( "height", "" );
15604
enable: function( index ) {
15605
var disabled = this.options.disabled;
15606
if ( disabled === false ) {
15610
if ( index === undefined ) {
15613
index = this._getIndex( index );
15614
if ( $.isArray( disabled ) ) {
15615
disabled = $.map( disabled, function( num ) {
15616
return num !== index ? num : null;
15619
disabled = $.map( this.tabs, function( li, num ) {
15620
return num !== index ? num : null;
15624
this._setupDisabled( disabled );
15627
disable: function( index ) {
15628
var disabled = this.options.disabled;
15629
if ( disabled === true ) {
15633
if ( index === undefined ) {
15636
index = this._getIndex( index );
15637
if ( $.inArray( index, disabled ) !== -1 ) {
15640
if ( $.isArray( disabled ) ) {
15641
disabled = $.merge( [ index ], disabled ).sort();
15643
disabled = [ index ];
15646
this._setupDisabled( disabled );
15649
load: function( index, event ) {
15650
index = this._getIndex( index );
15652
tab = this.tabs.eq( index ),
15653
anchor = tab.find( ".ui-tabs-anchor" ),
15654
panel = this._getPanelForTab( tab ),
15661
if ( this._isLocal( anchor[ 0 ] ) ) {
15665
this.xhr = $.ajax( this._ajaxSettings( anchor, event, eventData ) );
15667
// support: jQuery <1.8
15668
// jQuery <1.8 returns false if the request is canceled in beforeSend,
15669
// but as of 1.8, $.ajax() always returns a jqXHR object.
15670
if ( this.xhr && this.xhr.statusText !== "canceled" ) {
15671
tab.addClass( "ui-tabs-loading" );
15672
panel.attr( "aria-busy", "true" );
15675
.success(function( response ) {
15676
// support: jQuery <1.8
15677
// http://bugs.jquery.com/ticket/11778
15678
setTimeout(function() {
15679
panel.html( response );
15680
that._trigger( "load", event, eventData );
15683
.complete(function( jqXHR, status ) {
15684
// support: jQuery <1.8
15685
// http://bugs.jquery.com/ticket/11778
15686
setTimeout(function() {
15687
if ( status === "abort" ) {
15688
that.panels.stop( false, true );
15691
tab.removeClass( "ui-tabs-loading" );
15692
panel.removeAttr( "aria-busy" );
15694
if ( jqXHR === that.xhr ) {
15702
_ajaxSettings: function( anchor, event, eventData ) {
15705
url: anchor.attr( "href" ),
15706
beforeSend: function( jqXHR, settings ) {
15707
return that._trigger( "beforeLoad", event,
15708
$.extend( { jqXHR: jqXHR, ajaxSettings: settings }, eventData ) );
15713
_getPanelForTab: function( tab ) {
15714
var id = $( tab ).attr( "aria-controls" );
15715
return this.element.find( this._sanitizeSelector( "#" + id ) );
15721
* jQuery UI Tooltip 1.11.0
15722
* http://jqueryui.com
15724
* Copyright 2014 jQuery Foundation and other contributors
15725
* Released under the MIT license.
15726
* http://jquery.org/license
15728
* http://api.jqueryui.com/tooltip/
15732
var tooltip = $.widget( "ui.tooltip", {
15735
content: function() {
15736
// support: IE<9, Opera in jQuery <1.7
15737
// .text() can't accept undefined, so coerce to a string
15738
var title = $( this ).attr( "title" ) || "";
15739
// Escape title, since we're going from an attribute to raw HTML
15740
return $( "<a>" ).text( title ).html();
15743
// Disabled elements have inconsistent behavior across browsers (#8661)
15744
items: "[title]:not([disabled])",
15748
collision: "flipfit flip"
15751
tooltipClass: null,
15759
_addDescribedBy: function( elem, id ) {
15760
var describedby = (elem.attr( "aria-describedby" ) || "").split( /\s+/ );
15761
describedby.push( id );
15763
.data( "ui-tooltip-id", id )
15764
.attr( "aria-describedby", $.trim( describedby.join( " " ) ) );
15767
_removeDescribedBy: function( elem ) {
15768
var id = elem.data( "ui-tooltip-id" ),
15769
describedby = (elem.attr( "aria-describedby" ) || "").split( /\s+/ ),
15770
index = $.inArray( id, describedby );
15772
if ( index !== -1 ) {
15773
describedby.splice( index, 1 );
15776
elem.removeData( "ui-tooltip-id" );
15777
describedby = $.trim( describedby.join( " " ) );
15778
if ( describedby ) {
15779
elem.attr( "aria-describedby", describedby );
15781
elem.removeAttr( "aria-describedby" );
15785
_create: function() {
15791
// IDs of generated tooltips, needed for destroy
15792
this.tooltips = {};
15793
// IDs of parent tooltips where we removed the title attribute
15796
if ( this.options.disabled ) {
15800
// Append the aria-live region so tooltips announce correctly
15801
this.liveRegion = $( "<div>" )
15804
"aria-live": "assertive",
15805
"aria-relevant": "additions"
15807
.addClass( "ui-helper-hidden-accessible" )
15808
.appendTo( this.document[ 0 ].body );
15811
_setOption: function( key, value ) {
15814
if ( key === "disabled" ) {
15815
this[ value ? "_disable" : "_enable" ]();
15816
this.options[ key ] = value;
15817
// disable element style changes
15821
this._super( key, value );
15823
if ( key === "content" ) {
15824
$.each( this.tooltips, function( id, element ) {
15825
that._updateContent( element );
15830
_disable: function() {
15833
// close open tooltips
15834
$.each( this.tooltips, function( id, element ) {
15835
var event = $.Event( "blur" );
15836
event.target = event.currentTarget = element[0];
15837
that.close( event, true );
15840
// remove title attributes to prevent native tooltips
15841
this.element.find( this.options.items ).addBack().each(function() {
15842
var element = $( this );
15843
if ( element.is( "[title]" ) ) {
15845
.data( "ui-tooltip-title", element.attr( "title" ) )
15846
.removeAttr( "title" );
15851
_enable: function() {
15852
// restore title attributes
15853
this.element.find( this.options.items ).addBack().each(function() {
15854
var element = $( this );
15855
if ( element.data( "ui-tooltip-title" ) ) {
15856
element.attr( "title", element.data( "ui-tooltip-title" ) );
15861
open: function( event ) {
15863
target = $( event ? event.target : this.element )
15864
// we need closest here due to mouseover bubbling,
15865
// but always pointing at the same event target
15866
.closest( this.options.items );
15868
// No element to show a tooltip for or the tooltip is already open
15869
if ( !target.length || target.data( "ui-tooltip-id" ) ) {
15873
if ( target.attr( "title" ) ) {
15874
target.data( "ui-tooltip-title", target.attr( "title" ) );
15877
target.data( "ui-tooltip-open", true );
15879
// kill parent tooltips, custom or native, for hover
15880
if ( event && event.type === "mouseover" ) {
15881
target.parents().each(function() {
15882
var parent = $( this ),
15884
if ( parent.data( "ui-tooltip-open" ) ) {
15885
blurEvent = $.Event( "blur" );
15886
blurEvent.target = blurEvent.currentTarget = this;
15887
that.close( blurEvent, true );
15889
if ( parent.attr( "title" ) ) {
15891
that.parents[ this.id ] = {
15893
title: parent.attr( "title" )
15895
parent.attr( "title", "" );
15900
this._updateContent( target, event );
15903
_updateContent: function( target, event ) {
15905
contentOption = this.options.content,
15907
eventType = event ? event.type : null;
15909
if ( typeof contentOption === "string" ) {
15910
return this._open( event, target, contentOption );
15913
content = contentOption.call( target[0], function( response ) {
15914
// ignore async response if tooltip was closed already
15915
if ( !target.data( "ui-tooltip-open" ) ) {
15918
// IE may instantly serve a cached response for ajax requests
15919
// delay this call to _open so the other call to _open runs first
15920
that._delay(function() {
15921
// jQuery creates a special event for focusin when it doesn't
15922
// exist natively. To improve performance, the native event
15923
// object is reused and the type is changed. Therefore, we can't
15924
// rely on the type being correct after the event finished
15925
// bubbling, so we set it back to the previous value. (#8740)
15927
event.type = eventType;
15929
this._open( event, target, response );
15933
this._open( event, target, content );
15937
_open: function( event, target, content ) {
15938
var tooltip, events, delayedShow, a11yContent,
15939
positionOption = $.extend( {}, this.options.position );
15945
// Content can be updated multiple times. If the tooltip already
15946
// exists, then just update the content and bail.
15947
tooltip = this._find( target );
15948
if ( tooltip.length ) {
15949
tooltip.find( ".ui-tooltip-content" ).html( content );
15953
// if we have a title, clear it to prevent the native tooltip
15954
// we have to check first to avoid defining a title if none exists
15955
// (we don't want to cause an element to start matching [title])
15957
// We use removeAttr only for key events, to allow IE to export the correct
15958
// accessible attributes. For mouse events, set to empty string to avoid
15959
// native tooltip showing up (happens only when removing inside mouseover).
15960
if ( target.is( "[title]" ) ) {
15961
if ( event && event.type === "mouseover" ) {
15962
target.attr( "title", "" );
15964
target.removeAttr( "title" );
15968
tooltip = this._tooltip( target );
15969
this._addDescribedBy( target, tooltip.attr( "id" ) );
15970
tooltip.find( ".ui-tooltip-content" ).html( content );
15972
// Support: Voiceover on OS X, JAWS on IE <= 9
15973
// JAWS announces deletions even when aria-relevant="additions"
15974
// Voiceover will sometimes re-read the entire log region's contents from the beginning
15975
this.liveRegion.children().hide();
15976
if ( content.clone ) {
15977
a11yContent = content.clone();
15978
a11yContent.removeAttr( "id" ).find( "[id]" ).removeAttr( "id" );
15980
a11yContent = content;
15982
$( "<div>" ).html( a11yContent ).appendTo( this.liveRegion );
15984
function position( event ) {
15985
positionOption.of = event;
15986
if ( tooltip.is( ":hidden" ) ) {
15989
tooltip.position( positionOption );
15991
if ( this.options.track && event && /^mouse/.test( event.type ) ) {
15992
this._on( this.document, {
15993
mousemove: position
15995
// trigger once to override element-relative positioning
15998
tooltip.position( $.extend({
16000
}, this.options.position ) );
16005
this._show( tooltip, this.options.show );
16006
// Handle tracking tooltips that are shown with a delay (#8644). As soon
16007
// as the tooltip is visible, position the tooltip using the most recent
16009
if ( this.options.show && this.options.show.delay ) {
16010
delayedShow = this.delayedShow = setInterval(function() {
16011
if ( tooltip.is( ":visible" ) ) {
16012
position( positionOption.of );
16013
clearInterval( delayedShow );
16015
}, $.fx.interval );
16018
this._trigger( "open", event, { tooltip: tooltip } );
16021
keyup: function( event ) {
16022
if ( event.keyCode === $.ui.keyCode.ESCAPE ) {
16023
var fakeEvent = $.Event(event);
16024
fakeEvent.currentTarget = target[0];
16025
this.close( fakeEvent, true );
16030
// Only bind remove handler for delegated targets. Non-delegated
16031
// tooltips will handle this in destroy.
16032
if ( target[ 0 ] !== this.element[ 0 ] ) {
16033
events.remove = function() {
16034
this._removeTooltip( tooltip );
16038
if ( !event || event.type === "mouseover" ) {
16039
events.mouseleave = "close";
16041
if ( !event || event.type === "focusin" ) {
16042
events.focusout = "close";
16044
this._on( true, target, events );
16047
close: function( event ) {
16049
target = $( event ? event.currentTarget : this.element ),
16050
tooltip = this._find( target );
16052
// disabling closes the tooltip, so we need to track when we're closing
16053
// to avoid an infinite loop in case the tooltip becomes disabled on close
16054
if ( this.closing ) {
16058
// Clear the interval for delayed tracking tooltips
16059
clearInterval( this.delayedShow );
16061
// only set title if we had one before (see comment in _open())
16062
// If the title attribute has changed since open(), don't restore
16063
if ( target.data( "ui-tooltip-title" ) && !target.attr( "title" ) ) {
16064
target.attr( "title", target.data( "ui-tooltip-title" ) );
16067
this._removeDescribedBy( target );
16069
tooltip.stop( true );
16070
this._hide( tooltip, this.options.hide, function() {
16071
that._removeTooltip( $( this ) );
16074
target.removeData( "ui-tooltip-open" );
16075
this._off( target, "mouseleave focusout keyup" );
16077
// Remove 'remove' binding only on delegated targets
16078
if ( target[ 0 ] !== this.element[ 0 ] ) {
16079
this._off( target, "remove" );
16081
this._off( this.document, "mousemove" );
16083
if ( event && event.type === "mouseleave" ) {
16084
$.each( this.parents, function( id, parent ) {
16085
$( parent.element ).attr( "title", parent.title );
16086
delete that.parents[ id ];
16090
this.closing = true;
16091
this._trigger( "close", event, { tooltip: tooltip } );
16092
this.closing = false;
16095
_tooltip: function( element ) {
16096
var tooltip = $( "<div>" )
16097
.attr( "role", "tooltip" )
16098
.addClass( "ui-tooltip ui-widget ui-corner-all ui-widget-content " +
16099
( this.options.tooltipClass || "" ) ),
16100
id = tooltip.uniqueId().attr( "id" );
16103
.addClass( "ui-tooltip-content" )
16104
.appendTo( tooltip );
16106
tooltip.appendTo( this.document[0].body );
16107
this.tooltips[ id ] = element;
16111
_find: function( target ) {
16112
var id = target.data( "ui-tooltip-id" );
16113
return id ? $( "#" + id ) : $();
16116
_removeTooltip: function( tooltip ) {
16118
delete this.tooltips[ tooltip.attr( "id" ) ];
16121
_destroy: function() {
16124
// close open tooltips
16125
$.each( this.tooltips, function( id, element ) {
16126
// Delegate to close method to handle common cleanup
16127
var event = $.Event( "blur" );
16128
event.target = event.currentTarget = element[0];
16129
that.close( event, true );
16131
// Remove immediately; destroying an open tooltip doesn't use the
16133
$( "#" + id ).remove();
16135
// Restore the title
16136
if ( element.data( "ui-tooltip-title" ) ) {
16137
// If the title attribute has changed since open(), don't restore
16138
if ( !element.attr( "title" ) ) {
16139
element.attr( "title", element.data( "ui-tooltip-title" ) );
16141
element.removeData( "ui-tooltip-title" );
16144
this.liveRegion.remove();
b'\\ No newline at end of file'