4 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
5 * Dual licensed under the MIT or GPL Version 2 licenses.
6 * http://jquery.org/license
8 * http://docs.jquery.com/UI
10 (function( $, undefined ) {
12 // prevent duplicate loading
13 // this is only a problem because we proxy existing functions
14 // and we don't want to double proxy them
29 COMMAND_LEFT
: 91, // COMMAND
40 MENU
: 93, // COMMAND_RIGHT
55 WINDOWS
: 91 // COMMAND
61 propAttr
: $.fn
.prop
|| $.fn
.attr
,
64 focus: function( delay
, fn
) {
65 return typeof delay
=== "number" ?
66 this.each(function() {
68 setTimeout(function() {
75 this._focus
.apply( this, arguments
);
78 scrollParent: function() {
80 if (($.browser
.msie
&& (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) {
81 scrollParent
= this.parents().filter(function() {
82 return (/(relative|absolute|fixed)/).test($.curCSS(this,'position',1)) && (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
85 scrollParent
= this.parents().filter(function() {
86 return (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
90 return (/fixed/).test(this.css('position')) || !scrollParent
.length
? $(document
) : scrollParent
;
93 zIndex: function( zIndex
) {
94 if ( zIndex
!== undefined ) {
95 return this.css( "zIndex", zIndex
);
99 var elem
= $( this[ 0 ] ), position
, value
;
100 while ( elem
.length
&& elem
[ 0 ] !== document
) {
101 // Ignore z-index if position is set to a value where z-index is ignored by the browser
102 // This makes behavior of this function consistent across browsers
103 // WebKit always returns auto if the element is positioned
104 position
= elem
.css( "position" );
105 if ( position
=== "absolute" || position
=== "relative" || position
=== "fixed" ) {
106 // IE returns 0 when zIndex is not specified
107 // other browsers return a string
108 // we ignore the case of nested elements with an explicit value of 0
109 // <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
110 value
= parseInt( elem
.css( "zIndex" ), 10 );
111 if ( !isNaN( value
) && value
!== 0 ) {
115 elem
= elem
.parent();
122 disableSelection: function() {
123 return this.bind( ( $.support
.selectstart
? "selectstart" : "mousedown" ) +
124 ".ui-disableSelection", function( event
) {
125 event
.preventDefault();
129 enableSelection: function() {
130 return this.unbind( ".ui-disableSelection" );
134 $.each( [ "Width", "Height" ], function( i
, name
) {
135 var side
= name
=== "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
136 type
= name
.toLowerCase(),
138 innerWidth
: $.fn
.innerWidth
,
139 innerHeight
: $.fn
.innerHeight
,
140 outerWidth
: $.fn
.outerWidth
,
141 outerHeight
: $.fn
.outerHeight
144 function reduce( elem
, size
, border
, margin
) {
145 $.each( side
, function() {
146 size
-= parseFloat( $.curCSS( elem
, "padding" + this, true) ) || 0;
148 size
-= parseFloat( $.curCSS( elem
, "border" + this + "Width", true) ) || 0;
151 size
-= parseFloat( $.curCSS( elem
, "margin" + this, true) ) || 0;
157 $.fn
[ "inner" + name
] = function( size
) {
158 if ( size
=== undefined ) {
159 return orig
[ "inner" + name
].call( this );
162 return this.each(function() {
163 $( this ).css( type
, reduce( this, size
) + "px" );
167 $.fn
[ "outer" + name
] = function( size
, margin
) {
168 if ( typeof size
!== "number" ) {
169 return orig
[ "outer" + name
].call( this, size
);
172 return this.each(function() {
173 $( this).css( type
, reduce( this, size
, true, margin
) + "px" );
179 function focusable( element
, isTabIndexNotNaN
) {
180 var nodeName
= element
.nodeName
.toLowerCase();
181 if ( "area" === nodeName
) {
182 var map
= element
.parentNode
,
185 if ( !element
.href
|| !mapName
|| map
.nodeName
.toLowerCase() !== "map" ) {
188 img
= $( "img[usemap=#" + mapName
+ "]" )[0];
189 return !!img
&& visible( img
);
191 return ( /input|select|textarea|button|object/.test( nodeName
)
194 ? element
.href
|| isTabIndexNotNaN
196 // the element and all of its ancestors must be visible
197 && visible( element
);
200 function visible( element
) {
201 return !$( element
).parents().andSelf().filter(function() {
202 return $.curCSS( this, "visibility" ) === "hidden" ||
203 $.expr
.filters
.hidden( this );
207 $.extend( $.expr
[ ":" ], {
208 data: function( elem
, i
, match
) {
209 return !!$.data( elem
, match
[ 3 ] );
212 focusable: function( element
) {
213 return focusable( element
, !isNaN( $.attr( element
, "tabindex" ) ) );
216 tabbable: function( element
) {
217 var tabIndex
= $.attr( element
, "tabindex" ),
218 isTabIndexNaN
= isNaN( tabIndex
);
219 return ( isTabIndexNaN
|| tabIndex
>= 0 ) && focusable( element
, !isTabIndexNaN
);
225 var body
= document
.body
,
226 div
= body
.appendChild( div
= document
.createElement( "div" ) );
228 $.extend( div
.style
, {
235 $.support
.minHeight
= div
.offsetHeight
=== 100;
236 $.support
.selectstart
= "onselectstart" in div
;
238 // set display to none to avoid a layout bug in IE
239 // http://dev.jquery.com/ticket/4014
240 body
.removeChild( div
).style
.display
= "none";
249 // $.ui.plugin is deprecated. Use the proxy pattern instead.
251 add: function( module
, option
, set ) {
252 var proto
= $.ui
[ module
].prototype;
253 for ( var i
in set ) {
254 proto
.plugins
[ i
] = proto
.plugins
[ i
] || [];
255 proto
.plugins
[ i
].push( [ option
, set[ i
] ] );
258 call: function( instance
, name
, args
) {
259 var set = instance
.plugins
[ name
];
260 if ( !set || !instance
.element
[ 0 ].parentNode
) {
264 for ( var i
= 0; i
< set.length
; i
++ ) {
265 if ( instance
.options
[ set[ i
][ 0 ] ] ) {
266 set[ i
][ 1 ].apply( instance
.element
, args
);
272 // will be deprecated when we switch to jQuery 1.4 - use jQuery.contains()
273 contains: function( a
, b
) {
274 return document
.compareDocumentPosition
?
275 a
.compareDocumentPosition( b
) & 16 :
276 a
!== b
&& a
.contains( b
);
279 // only used by resizable
280 hasScroll: function( el
, a
) {
282 //If overflow is hidden, the element might have extra content, but the user wants to hide it
283 if ( $( el
).css( "overflow" ) === "hidden") {
287 var scroll
= ( a
&& a
=== "left" ) ? "scrollLeft" : "scrollTop",
290 if ( el
[ scroll
] > 0 ) {
294 // TODO: determine which cases actually cause this to happen
295 // if the element doesn't have the scroll set, see if it's possible to
298 has
= ( el
[ scroll
] > 0 );
303 // these are odd functions, fix the API or move into individual plugins
304 isOverAxis: function( x
, reference
, size
) {
305 //Determines when x coordinate is over "b" element axis
306 return ( x
> reference
) && ( x
< ( reference
+ size
) );
308 isOver: function( y
, x
, top
, left
, height
, width
) {
309 //Determines when x, y coordinates is over "b" element
310 return $.ui
.isOverAxis( y
, top
, height
) && $.ui
.isOverAxis( x
, left
, width
);
316 * jQuery UI Widget 1.8.16
318 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
319 * Dual licensed under the MIT or GPL Version 2 licenses.
320 * http://jquery.org/license
322 * http://docs.jquery.com/UI/Widget
324 (function( $, undefined ) {
328 var _cleanData
= $.cleanData
;
329 $.cleanData = function( elems
) {
330 for ( var i
= 0, elem
; (elem
= elems
[i
]) != null; i
++ ) {
332 $( elem
).triggerHandler( "remove" );
333 // http://bugs.jquery.com/ticket/8235
339 var _remove
= $.fn
.remove
;
340 $.fn
.remove = function( selector
, keepData
) {
341 return this.each(function() {
343 if ( !selector
|| $.filter( selector
, [ this ] ).length
) {
344 $( "*", this ).add( [ this ] ).each(function() {
346 $( this ).triggerHandler( "remove" );
347 // http://bugs.jquery.com/ticket/8235
352 return _remove
.call( $(this), selector
, keepData
);
357 $.widget = function( name
, base
, prototype ) {
358 var namespace = name
.split( "." )[ 0 ],
360 name
= name
.split( "." )[ 1 ];
361 fullName
= namespace + "-" + name
;
368 // create selector for plugin
369 $.expr
[ ":" ][ fullName
] = function( elem
) {
370 return !!$.data( elem
, name
);
373 $[ namespace ] = $[ namespace ] || {};
374 $[ namespace ][ name
] = function( options
, element
) {
375 // allow instantiation without initializing for simple inheritance
376 if ( arguments
.length
) {
377 this._createWidget( options
, element
);
381 var basePrototype
= new base();
382 // we need to make the options hash a property directly on the new instance
383 // otherwise we'll modify the options hash on the prototype that we're
385 // $.each( basePrototype, function( key, val ) {
386 // if ( $.isPlainObject(val) ) {
387 // basePrototype[ key ] = $.extend( {}, val );
390 basePrototype
.options
= $.extend( true, {}, basePrototype
.options
);
391 $[ namespace ][ name
].prototype = $.extend( true, basePrototype
, {
392 namespace: namespace,
394 widgetEventPrefix
: $[ namespace ][ name
].prototype.widgetEventPrefix
|| name
,
395 widgetBaseClass
: fullName
398 $.widget
.bridge( name
, $[ namespace ][ name
] );
401 $.widget
.bridge = function( name
, object
) {
402 $.fn
[ name
] = function( options
) {
403 var isMethodCall
= typeof options
=== "string",
404 args
= Array
.prototype.slice
.call( arguments
, 1 ),
407 // allow multiple hashes to be passed on init
408 options
= !isMethodCall
&& args
.length
?
409 $.extend
.apply( null, [ true, options
].concat(args
) ) :
412 // prevent calls to internal methods
413 if ( isMethodCall
&& options
.charAt( 0 ) === "_" ) {
417 if ( isMethodCall
) {
418 this.each(function() {
419 var instance
= $.data( this, name
),
420 methodValue
= instance
&& $.isFunction( instance
[options
] ) ?
421 instance
[ options
].apply( instance
, args
) :
423 // TODO: add this back in 1.9 and use $.error() (see #5972)
424 // if ( !instance ) {
425 // throw "cannot call methods on " + name + " prior to initialization; " +
426 // "attempted to call method '" + options + "'";
428 // if ( !$.isFunction( instance[options] ) ) {
429 // throw "no such method '" + options + "' for " + name + " widget instance";
431 // var methodValue = instance[ options ].apply( instance, args );
432 if ( methodValue
!== instance
&& methodValue
!== undefined ) {
433 returnValue
= methodValue
;
438 this.each(function() {
439 var instance
= $.data( this, name
);
441 instance
.option( options
|| {} )._init();
443 $.data( this, name
, new object( options
, this ) );
452 $.Widget = function( options
, element
) {
453 // allow instantiation without initializing for simple inheritance
454 if ( arguments
.length
) {
455 this._createWidget( options
, element
);
459 $.Widget
.prototype = {
460 widgetName
: "widget",
461 widgetEventPrefix
: "",
465 _createWidget: function( options
, element
) {
466 // $.widget.bridge stores the plugin instance, but we do it anyway
467 // so that it's stored even before the _create function runs
468 $.data( element
, this.widgetName
, this );
469 this.element
= $( element
);
470 this.options
= $.extend( true, {},
472 this._getCreateOptions(),
476 this.element
.bind( "remove." + this.widgetName
, function() {
481 this._trigger( "create" );
484 _getCreateOptions: function() {
485 return $.metadata
&& $.metadata
.get( this.element
[0] )[ this.widgetName
];
487 _create: function() {},
488 _init: function() {},
490 destroy: function() {
492 .unbind( "." + this.widgetName
)
493 .removeData( this.widgetName
);
495 .unbind( "." + this.widgetName
)
496 .removeAttr( "aria-disabled" )
498 this.widgetBaseClass
+ "-disabled " +
499 "ui-state-disabled" );
506 option: function( key
, value
) {
509 if ( arguments
.length
=== 0 ) {
510 // don't return a reference to the internal hash
511 return $.extend( {}, this.options
);
514 if (typeof key
=== "string" ) {
515 if ( value
=== undefined ) {
516 return this.options
[ key
];
519 options
[ key
] = value
;
522 this._setOptions( options
);
526 _setOptions: function( options
) {
528 $.each( options
, function( key
, value
) {
529 self
._setOption( key
, value
);
534 _setOption: function( key
, value
) {
535 this.options
[ key
] = value
;
537 if ( key
=== "disabled" ) {
539 [ value
? "addClass" : "removeClass"](
540 this.widgetBaseClass
+ "-disabled" + " " +
541 "ui-state-disabled" )
542 .attr( "aria-disabled", value
);
549 return this._setOption( "disabled", false );
551 disable: function() {
552 return this._setOption( "disabled", true );
555 _trigger: function( type
, event
, data
) {
556 var callback
= this.options
[ type
];
558 event
= $.Event( event
);
559 event
.type
= ( type
=== this.widgetEventPrefix
?
561 this.widgetEventPrefix
+ type
).toLowerCase();
564 // copy original event properties over to the new event
565 // this would happen if we could call $.event.fix instead of $.Event
566 // but we don't have a way to force an event to be fixed multiple times
567 if ( event
.originalEvent
) {
568 for ( var i
= $.event
.props
.length
, prop
; i
; ) {
569 prop
= $.event
.props
[ --i
];
570 event
[ prop
] = event
.originalEvent
[ prop
];
574 this.element
.trigger( event
, data
);
576 return !( $.isFunction(callback
) &&
577 callback
.call( this.element
[0], event
, data
) === false ||
578 event
.isDefaultPrevented() );
584 * jQuery UI Mouse 1.8.16
586 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
587 * Dual licensed under the MIT or GPL Version 2 licenses.
588 * http://jquery.org/license
590 * http://docs.jquery.com/UI/Mouse
593 * jquery.ui.widget.js
595 (function( $, undefined ) {
597 var mouseHandled
= false;
598 $( document
).mouseup( function( e
) {
599 mouseHandled
= false;
602 $.widget("ui.mouse", {
604 cancel
: ':input,option',
608 _mouseInit: function() {
612 .bind('mousedown.'+this.widgetName
, function(event
) {
613 return self
._mouseDown(event
);
615 .bind('click.'+this.widgetName
, function(event
) {
616 if (true === $.data(event
.target
, self
.widgetName
+ '.preventClickEvent')) {
617 $.removeData(event
.target
, self
.widgetName
+ '.preventClickEvent');
618 event
.stopImmediatePropagation();
623 this.started
= false;
626 // TODO: make sure destroying one instance of mouse doesn't mess with
627 // other instances of mouse
628 _mouseDestroy: function() {
629 this.element
.unbind('.'+this.widgetName
);
632 _mouseDown: function(event
) {
633 // don't let more than one widget handle mouseStart
634 if( mouseHandled
) { return };
636 // we may have missed mouseup (out of window)
637 (this._mouseStarted
&& this._mouseUp(event
));
639 this._mouseDownEvent
= event
;
642 btnIsLeft
= (event
.which
== 1),
643 // event.target.nodeName works around a bug in IE 8 with
644 // disabled inputs (#7620)
645 elIsCancel
= (typeof this.options
.cancel
== "string" && event
.target
.nodeName
? $(event
.target
).closest(this.options
.cancel
).length
: false);
646 if (!btnIsLeft
|| elIsCancel
|| !this._mouseCapture(event
)) {
650 this.mouseDelayMet
= !this.options
.delay
;
651 if (!this.mouseDelayMet
) {
652 this._mouseDelayTimer
= setTimeout(function() {
653 self
.mouseDelayMet
= true;
654 }, this.options
.delay
);
657 if (this._mouseDistanceMet(event
) && this._mouseDelayMet(event
)) {
658 this._mouseStarted
= (this._mouseStart(event
) !== false);
659 if (!this._mouseStarted
) {
660 event
.preventDefault();
665 // Click event may never have fired (Gecko & Opera)
666 if (true === $.data(event
.target
, this.widgetName
+ '.preventClickEvent')) {
667 $.removeData(event
.target
, this.widgetName
+ '.preventClickEvent');
670 // these delegates are required to keep context
671 this._mouseMoveDelegate = function(event
) {
672 return self
._mouseMove(event
);
674 this._mouseUpDelegate = function(event
) {
675 return self
._mouseUp(event
);
678 .bind('mousemove.'+this.widgetName
, this._mouseMoveDelegate
)
679 .bind('mouseup.'+this.widgetName
, this._mouseUpDelegate
);
681 event
.preventDefault();
687 _mouseMove: function(event
) {
688 // IE mouseup check - mouseup happened when mouse was out of window
689 if ($.browser
.msie
&& !(document
.documentMode
>= 9) && !event
.button
) {
690 return this._mouseUp(event
);
693 if (this._mouseStarted
) {
694 this._mouseDrag(event
);
695 return event
.preventDefault();
698 if (this._mouseDistanceMet(event
) && this._mouseDelayMet(event
)) {
700 (this._mouseStart(this._mouseDownEvent
, event
) !== false);
701 (this._mouseStarted
? this._mouseDrag(event
) : this._mouseUp(event
));
704 return !this._mouseStarted
;
707 _mouseUp: function(event
) {
709 .unbind('mousemove.'+this.widgetName
, this._mouseMoveDelegate
)
710 .unbind('mouseup.'+this.widgetName
, this._mouseUpDelegate
);
712 if (this._mouseStarted
) {
713 this._mouseStarted
= false;
715 if (event
.target
== this._mouseDownEvent
.target
) {
716 $.data(event
.target
, this.widgetName
+ '.preventClickEvent', true);
719 this._mouseStop(event
);
725 _mouseDistanceMet: function(event
) {
727 Math
.abs(this._mouseDownEvent
.pageX
- event
.pageX
),
728 Math
.abs(this._mouseDownEvent
.pageY
- event
.pageY
)
729 ) >= this.options
.distance
733 _mouseDelayMet: function(event
) {
734 return this.mouseDelayMet
;
737 // These are placeholder methods, to be overriden by extending plugin
738 _mouseStart: function(event
) {},
739 _mouseDrag: function(event
) {},
740 _mouseStop: function(event
) {},
741 _mouseCapture: function(event
) { return true; }
746 * jQuery UI Draggable 1.8.16
748 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
749 * Dual licensed under the MIT or GPL Version 2 licenses.
750 * http://jquery.org/license
752 * http://docs.jquery.com/UI/Draggables
757 * jquery.ui.widget.js
759 (function( $, undefined ) {
761 $.widget("ui.draggable", $.ui
.mouse
, {
762 widgetEventPrefix
: "drag",
767 connectToSortable
: false,
776 refreshPositions
: false,
781 scrollSensitivity
: 20,
789 _create: function() {
791 if (this.options
.helper
== 'original' && !(/^(?:r|a|f)/).test(this.element
.css("position")))
792 this.element
[0].style
.position
= 'relative';
794 (this.options
.addClasses
&& this.element
.addClass("ui-draggable"));
795 (this.options
.disabled
&& this.element
.addClass("ui-draggable-disabled"));
801 destroy: function() {
802 if(!this.element
.data('draggable')) return;
804 .removeData("draggable")
805 .unbind(".draggable")
806 .removeClass("ui-draggable"
807 + " ui-draggable-dragging"
808 + " ui-draggable-disabled");
809 this._mouseDestroy();
814 _mouseCapture: function(event
) {
816 var o
= this.options
;
818 // among others, prevent a drag on a resizable-handle
819 if (this.helper
|| o
.disabled
|| $(event
.target
).is('.ui-resizable-handle'))
822 //Quit if we're not on a valid handle
823 this.handle
= this._getHandle(event
);
828 $(o
.iframeFix
=== true ? "iframe" : o
.iframeFix
).each(function() {
829 $('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>')
831 width
: this.offsetWidth
+"px", height
: this.offsetHeight
+"px",
832 position
: "absolute", opacity
: "0.001", zIndex
: 1000
834 .css($(this).offset())
843 _mouseStart: function(event
) {
845 var o
= this.options
;
847 //Create and append the visible helper
848 this.helper
= this._createHelper(event
);
850 //Cache the helper size
851 this._cacheHelperProportions();
853 //If ddmanager is used for droppables, set the global draggable
855 $.ui
.ddmanager
.current
= this;
858 * - Position generation -
859 * This block generates everything position related - it's the core of draggables.
862 //Cache the margins of the original element
863 this._cacheMargins();
865 //Store the helper's css position
866 this.cssPosition
= this.helper
.css("position");
867 this.scrollParent
= this.helper
.scrollParent();
869 //The element's absolute position on the page minus margins
870 this.offset
= this.positionAbs
= this.element
.offset();
872 top
: this.offset
.top
- this.margins
.top
,
873 left
: this.offset
.left
- this.margins
.left
876 $.extend(this.offset
, {
877 click
: { //Where the click happened, relative to the element
878 left
: event
.pageX
- this.offset
.left
,
879 top
: event
.pageY
- this.offset
.top
881 parent
: this._getParentOffset(),
882 relative
: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
885 //Generate the original position
886 this.originalPosition
= this.position
= this._generatePosition(event
);
887 this.originalPageX
= event
.pageX
;
888 this.originalPageY
= event
.pageY
;
890 //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
891 (o
.cursorAt
&& this._adjustOffsetFromHelper(o
.cursorAt
));
893 //Set a containment if given in the options
895 this._setContainment();
897 //Trigger event + callbacks
898 if(this._trigger("start", event
) === false) {
903 //Recache the helper size
904 this._cacheHelperProportions();
906 //Prepare the droppable offsets
907 if ($.ui
.ddmanager
&& !o
.dropBehaviour
)
908 $.ui
.ddmanager
.prepareOffsets(this, event
);
910 this.helper
.addClass("ui-draggable-dragging");
911 this._mouseDrag(event
, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position
913 //If the ddmanager is used for droppables, inform the manager that dragging has started (see #5003)
914 if ( $.ui
.ddmanager
) $.ui
.ddmanager
.dragStart(this, event
);
919 _mouseDrag: function(event
, noPropagation
) {
921 //Compute the helpers position
922 this.position
= this._generatePosition(event
);
923 this.positionAbs
= this._convertPositionTo("absolute");
925 //Call plugins and callbacks and use the resulting position if something is returned
926 if (!noPropagation
) {
927 var ui
= this._uiHash();
928 if(this._trigger('drag', event
, ui
) === false) {
932 this.position
= ui
.position
;
935 if(!this.options
.axis
|| this.options
.axis
!= "y") this.helper
[0].style
.left
= this.position
.left
+'px';
936 if(!this.options
.axis
|| this.options
.axis
!= "x") this.helper
[0].style
.top
= this.position
.top
+'px';
937 if($.ui
.ddmanager
) $.ui
.ddmanager
.drag(this, event
);
942 _mouseStop: function(event
) {
944 //If we are using droppables, inform the manager about the drop
946 if ($.ui
.ddmanager
&& !this.options
.dropBehaviour
)
947 dropped
= $.ui
.ddmanager
.drop(this, event
);
949 //if a drop comes from outside (a sortable)
951 dropped
= this.dropped
;
952 this.dropped
= false;
955 //if the original element is removed, don't bother to continue if helper is set to "original"
956 if((!this.element
[0] || !this.element
[0].parentNode
) && this.options
.helper
== "original")
959 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
))) {
961 $(this.helper
).animate(this.originalPosition
, parseInt(this.options
.revertDuration
, 10), function() {
962 if(self
._trigger("stop", event
) !== false) {
967 if(this._trigger("stop", event
) !== false) {
975 _mouseUp: function(event
) {
976 if (this.options
.iframeFix
=== true) {
977 $("div.ui-draggable-iframeFix").each(function() {
978 this.parentNode
.removeChild(this);
979 }); //Remove frame helpers
982 //If the ddmanager is used for droppables, inform the manager that dragging has stopped (see #5003)
983 if( $.ui
.ddmanager
) $.ui
.ddmanager
.dragStop(this, event
);
985 return $.ui
.mouse
.prototype._mouseUp
.call(this, event
);
990 if(this.helper
.is(".ui-draggable-dragging")) {
1000 _getHandle: function(event
) {
1002 var handle
= !this.options
.handle
|| !$(this.options
.handle
, this.element
).length
? true : false;
1003 $(this.options
.handle
, this.element
)
1007 if(this == event
.target
) handle
= true;
1014 _createHelper: function(event
) {
1016 var o
= this.options
;
1017 var helper
= $.isFunction(o
.helper
) ? $(o
.helper
.apply(this.element
[0], [event
])) : (o
.helper
== 'clone' ? this.element
.clone().removeAttr('id') : this.element
);
1019 if(!helper
.parents('body').length
)
1020 helper
.appendTo((o
.appendTo
== 'parent' ? this.element
[0].parentNode
: o
.appendTo
));
1022 if(helper
[0] != this.element
[0] && !(/(fixed|absolute)/).test(helper
.css("position")))
1023 helper
.css("position", "absolute");
1029 _adjustOffsetFromHelper: function(obj
) {
1030 if (typeof obj
== 'string') {
1031 obj
= obj
.split(' ');
1033 if ($.isArray(obj
)) {
1034 obj
= {left
: +obj
[0], top
: +obj
[1] || 0};
1036 if ('left' in obj
) {
1037 this.offset
.click
.left
= obj
.left
+ this.margins
.left
;
1039 if ('right' in obj
) {
1040 this.offset
.click
.left
= this.helperProportions
.width
- obj
.right
+ this.margins
.left
;
1043 this.offset
.click
.top
= obj
.top
+ this.margins
.top
;
1045 if ('bottom' in obj
) {
1046 this.offset
.click
.top
= this.helperProportions
.height
- obj
.bottom
+ this.margins
.top
;
1050 _getParentOffset: function() {
1052 //Get the offsetParent and cache its position
1053 this.offsetParent
= this.helper
.offsetParent();
1054 var po
= this.offsetParent
.offset();
1056 // This is a special case where we need to modify a offset calculated on start, since the following happened:
1057 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
1058 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
1059 // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
1060 if(this.cssPosition
== 'absolute' && this.scrollParent
[0] != document
&& $.ui
.contains(this.scrollParent
[0], this.offsetParent
[0])) {
1061 po
.left
+= this.scrollParent
.scrollLeft();
1062 po
.top
+= this.scrollParent
.scrollTop();
1065 if((this.offsetParent
[0] == document
.body
) //This needs to be actually done for all browsers, since pageX/pageY includes this information
1066 || (this.offsetParent
[0].tagName
&& this.offsetParent
[0].tagName
.toLowerCase() == 'html' && $.browser
.msie
)) //Ugly IE fix
1067 po
= { top
: 0, left
: 0 };
1070 top
: po
.top
+ (parseInt(this.offsetParent
.css("borderTopWidth"),10) || 0),
1071 left
: po
.left
+ (parseInt(this.offsetParent
.css("borderLeftWidth"),10) || 0)
1076 _getRelativeOffset: function() {
1078 if(this.cssPosition
== "relative") {
1079 var p
= this.element
.position();
1081 top
: p
.top
- (parseInt(this.helper
.css("top"),10) || 0) + this.scrollParent
.scrollTop(),
1082 left
: p
.left
- (parseInt(this.helper
.css("left"),10) || 0) + this.scrollParent
.scrollLeft()
1085 return { top
: 0, left
: 0 };
1090 _cacheMargins: function() {
1092 left
: (parseInt(this.element
.css("marginLeft"),10) || 0),
1093 top
: (parseInt(this.element
.css("marginTop"),10) || 0),
1094 right
: (parseInt(this.element
.css("marginRight"),10) || 0),
1095 bottom
: (parseInt(this.element
.css("marginBottom"),10) || 0)
1099 _cacheHelperProportions: function() {
1100 this.helperProportions
= {
1101 width
: this.helper
.outerWidth(),
1102 height
: this.helper
.outerHeight()
1106 _setContainment: function() {
1108 var o
= this.options
;
1109 if(o
.containment
== 'parent') o
.containment
= this.helper
[0].parentNode
;
1110 if(o
.containment
== 'document' || o
.containment
== 'window') this.containment
= [
1111 o
.containment
== 'document' ? 0 : $(window
).scrollLeft() - this.offset
.relative
.left
- this.offset
.parent
.left
,
1112 o
.containment
== 'document' ? 0 : $(window
).scrollTop() - this.offset
.relative
.top
- this.offset
.parent
.top
,
1113 (o
.containment
== 'document' ? 0 : $(window
).scrollLeft()) + $(o
.containment
== 'document' ? document
: window
).width() - this.helperProportions
.width
- this.margins
.left
,
1114 (o
.containment
== 'document' ? 0 : $(window
).scrollTop()) + ($(o
.containment
== 'document' ? document
: window
).height() || document
.body
.parentNode
.scrollHeight
) - this.helperProportions
.height
- this.margins
.top
1117 if(!(/^(document|window|parent)$/).test(o
.containment
) && o
.containment
.constructor != Array
) {
1118 var c
= $(o
.containment
);
1119 var ce
= c
[0]; if(!ce
) return;
1120 var co
= c
.offset();
1121 var over
= ($(ce
).css("overflow") != 'hidden');
1123 this.containment
= [
1124 (parseInt($(ce
).css("borderLeftWidth"),10) || 0) + (parseInt($(ce
).css("paddingLeft"),10) || 0),
1125 (parseInt($(ce
).css("borderTopWidth"),10) || 0) + (parseInt($(ce
).css("paddingTop"),10) || 0),
1126 (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
- this.margins
.right
,
1127 (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
- this.margins
.bottom
1129 this.relative_container
= c
;
1131 } else if(o
.containment
.constructor == Array
) {
1132 this.containment
= o
.containment
;
1137 _convertPositionTo: function(d
, pos
) {
1139 if(!pos
) pos
= this.position
;
1140 var mod
= d
== "absolute" ? 1 : -1;
1141 var o
= this.options
, scroll
= this.cssPosition
== 'absolute' && !(this.scrollParent
[0] != document
&& $.ui
.contains(this.scrollParent
[0], this.offsetParent
[0])) ? this.offsetParent
: this.scrollParent
, scrollIsRootNode
= (/(html|body)/i).test(scroll
[0].tagName
);
1145 pos
.top
// The absolute mouse position
1146 + this.offset
.relative
.top
* mod
// Only for relative positioned nodes: Relative offset from element to offset parent
1147 + this.offset
.parent
.top
* mod
// The offsetParent's offset without borders (offset + border)
1148 - ($.browser
.safari
&& $.browser
.version
< 526 && this.cssPosition
== 'fixed' ? 0 : ( this.cssPosition
== 'fixed' ? -this.scrollParent
.scrollTop() : ( scrollIsRootNode
? 0 : scroll
.scrollTop() ) ) * mod
)
1151 pos
.left
// The absolute mouse position
1152 + this.offset
.relative
.left
* mod
// Only for relative positioned nodes: Relative offset from element to offset parent
1153 + this.offset
.parent
.left
* mod
// The offsetParent's offset without borders (offset + border)
1154 - ($.browser
.safari
&& $.browser
.version
< 526 && this.cssPosition
== 'fixed' ? 0 : ( this.cssPosition
== 'fixed' ? -this.scrollParent
.scrollLeft() : scrollIsRootNode
? 0 : scroll
.scrollLeft() ) * mod
)
1160 _generatePosition: function(event
) {
1162 var o
= this.options
, scroll
= this.cssPosition
== 'absolute' && !(this.scrollParent
[0] != document
&& $.ui
.contains(this.scrollParent
[0], this.offsetParent
[0])) ? this.offsetParent
: this.scrollParent
, scrollIsRootNode
= (/(html|body)/i).test(scroll
[0].tagName
);
1163 var pageX
= event
.pageX
;
1164 var pageY
= event
.pageY
;
1167 * - Position constraining -
1168 * Constrain the position to a mix of grid, containment.
1171 if(this.originalPosition
) { //If we are not dragging yet, we won't check for options
1173 if(this.containment
) {
1174 if (this.relative_container
){
1175 var co
= this.relative_container
.offset();
1176 containment
= [ this.containment
[0] + co
.left
,
1177 this.containment
[1] + co
.top
,
1178 this.containment
[2] + co
.left
,
1179 this.containment
[3] + co
.top
];
1182 containment
= this.containment
;
1185 if(event
.pageX
- this.offset
.click
.left
< containment
[0]) pageX
= containment
[0] + this.offset
.click
.left
;
1186 if(event
.pageY
- this.offset
.click
.top
< containment
[1]) pageY
= containment
[1] + this.offset
.click
.top
;
1187 if(event
.pageX
- this.offset
.click
.left
> containment
[2]) pageX
= containment
[2] + this.offset
.click
.left
;
1188 if(event
.pageY
- this.offset
.click
.top
> containment
[3]) pageY
= containment
[3] + this.offset
.click
.top
;
1192 //Check for grid elements set to 0 to prevent divide by 0 error causing invalid argument errors in IE (see ticket #6950)
1193 var top
= o
.grid
[1] ? this.originalPageY
+ Math
.round((pageY
- this.originalPageY
) / o
.grid
[1]) * o
.grid
[1] : this.originalPageY
;
1194 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
;
1196 var left
= o
.grid
[0] ? this.originalPageX
+ Math
.round((pageX
- this.originalPageX
) / o
.grid
[0]) * o
.grid
[0] : this.originalPageX
;
1197 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
;
1204 pageY
// The absolute mouse position
1205 - this.offset
.click
.top
// Click offset (relative to the element)
1206 - this.offset
.relative
.top
// Only for relative positioned nodes: Relative offset from element to offset parent
1207 - this.offset
.parent
.top
// The offsetParent's offset without borders (offset + border)
1208 + ($.browser
.safari
&& $.browser
.version
< 526 && this.cssPosition
== 'fixed' ? 0 : ( this.cssPosition
== 'fixed' ? -this.scrollParent
.scrollTop() : ( scrollIsRootNode
? 0 : scroll
.scrollTop() ) ))
1211 pageX
// The absolute mouse position
1212 - this.offset
.click
.left
// Click offset (relative to the element)
1213 - this.offset
.relative
.left
// Only for relative positioned nodes: Relative offset from element to offset parent
1214 - this.offset
.parent
.left
// The offsetParent's offset without borders (offset + border)
1215 + ($.browser
.safari
&& $.browser
.version
< 526 && this.cssPosition
== 'fixed' ? 0 : ( this.cssPosition
== 'fixed' ? -this.scrollParent
.scrollLeft() : scrollIsRootNode
? 0 : scroll
.scrollLeft() ))
1221 _clear: function() {
1222 this.helper
.removeClass("ui-draggable-dragging");
1223 if(this.helper
[0] != this.element
[0] && !this.cancelHelperRemoval
) this.helper
.remove();
1224 //if($.ui.ddmanager) $.ui.ddmanager.current = null;
1226 this.cancelHelperRemoval
= false;
1229 // From now on bulk stuff - mainly helpers
1231 _trigger: function(type
, event
, ui
) {
1232 ui
= ui
|| this._uiHash();
1233 $.ui
.plugin
.call(this, type
, [event
, ui
]);
1234 if(type
== "drag") this.positionAbs
= this._convertPositionTo("absolute"); //The absolute position has to be recalculated after plugins
1235 return $.Widget
.prototype._trigger
.call(this, type
, event
, ui
);
1240 _uiHash: function(event
) {
1242 helper
: this.helper
,
1243 position
: this.position
,
1244 originalPosition
: this.originalPosition
,
1245 offset
: this.positionAbs
1251 $.extend($.ui
.draggable
, {
1255 $.ui
.plugin
.add("draggable", "connectToSortable", {
1256 start: function(event
, ui
) {
1258 var inst
= $(this).data("draggable"), o
= inst
.options
,
1259 uiSortable
= $.extend({}, ui
, { item
: inst
.element
});
1260 inst
.sortables
= [];
1261 $(o
.connectToSortable
).each(function() {
1262 var sortable
= $.data(this, 'sortable');
1263 if (sortable
&& !sortable
.options
.disabled
) {
1264 inst
.sortables
.push({
1266 shouldRevert
: sortable
.options
.revert
1268 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).
1269 sortable
._trigger("activate", event
, uiSortable
);
1274 stop: function(event
, ui
) {
1276 //If we are still over the sortable, we fake the stop event of the sortable, but also remove helper
1277 var inst
= $(this).data("draggable"),
1278 uiSortable
= $.extend({}, ui
, { item
: inst
.element
});
1280 $.each(inst
.sortables
, function() {
1281 if(this.instance
.isOver
) {
1283 this.instance
.isOver
= 0;
1285 inst
.cancelHelperRemoval
= true; //Don't remove the helper in the draggable instance
1286 this.instance
.cancelHelperRemoval
= false; //Remove it in the sortable instance (so sortable plugins like revert still work)
1288 //The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: 'valid/invalid'
1289 if(this.shouldRevert
) this.instance
.options
.revert
= true;
1291 //Trigger the stop of the sortable
1292 this.instance
._mouseStop(event
);
1294 this.instance
.options
.helper
= this.instance
.options
._helper
;
1296 //If the helper has been the original item, restore properties in the sortable
1297 if(inst
.options
.helper
== 'original')
1298 this.instance
.currentItem
.css({ top
: 'auto', left
: 'auto' });
1301 this.instance
.cancelHelperRemoval
= false; //Remove the helper in the sortable instance
1302 this.instance
._trigger("deactivate", event
, uiSortable
);
1308 drag: function(event
, ui
) {
1310 var inst
= $(this).data("draggable"), self
= this;
1312 var checkPos = function(o
) {
1313 var dyClick
= this.offset
.click
.top
, dxClick
= this.offset
.click
.left
;
1314 var helperTop
= this.positionAbs
.top
, helperLeft
= this.positionAbs
.left
;
1315 var itemHeight
= o
.height
, itemWidth
= o
.width
;
1316 var itemTop
= o
.top
, itemLeft
= o
.left
;
1318 return $.ui
.isOver(helperTop
+ dyClick
, helperLeft
+ dxClick
, itemTop
, itemLeft
, itemHeight
, itemWidth
);
1321 $.each(inst
.sortables
, function(i
) {
1323 //Copy over some variables to allow calling the sortable's native _intersectsWith
1324 this.instance
.positionAbs
= inst
.positionAbs
;
1325 this.instance
.helperProportions
= inst
.helperProportions
;
1326 this.instance
.offset
.click
= inst
.offset
.click
;
1328 if(this.instance
._intersectsWith(this.instance
.containerCache
)) {
1330 //If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once
1331 if(!this.instance
.isOver
) {
1333 this.instance
.isOver
= 1;
1334 //Now we fake the start of dragging for the sortable instance,
1335 //by cloning the list group item, appending it to the sortable and using it as inst.currentItem
1336 //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)
1337 this.instance
.currentItem
= $(self
).clone().removeAttr('id').appendTo(this.instance
.element
).data("sortable-item", true);
1338 this.instance
.options
._helper
= this.instance
.options
.helper
; //Store helper option to later restore it
1339 this.instance
.options
.helper = function() { return ui
.helper
[0]; };
1341 event
.target
= this.instance
.currentItem
[0];
1342 this.instance
._mouseCapture(event
, true);
1343 this.instance
._mouseStart(event
, true, true);
1345 //Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes
1346 this.instance
.offset
.click
.top
= inst
.offset
.click
.top
;
1347 this.instance
.offset
.click
.left
= inst
.offset
.click
.left
;
1348 this.instance
.offset
.parent
.left
-= inst
.offset
.parent
.left
- this.instance
.offset
.parent
.left
;
1349 this.instance
.offset
.parent
.top
-= inst
.offset
.parent
.top
- this.instance
.offset
.parent
.top
;
1351 inst
._trigger("toSortable", event
);
1352 inst
.dropped
= this.instance
.element
; //draggable revert needs that
1353 //hack so receive/update callbacks work (mostly)
1354 inst
.currentItem
= inst
.element
;
1355 this.instance
.fromOutside
= inst
;
1359 //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
1360 if(this.instance
.currentItem
) this.instance
._mouseDrag(event
);
1364 //If it doesn't intersect with the sortable, and it intersected before,
1365 //we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval
1366 if(this.instance
.isOver
) {
1368 this.instance
.isOver
= 0;
1369 this.instance
.cancelHelperRemoval
= true;
1371 //Prevent reverting on this forced stop
1372 this.instance
.options
.revert
= false;
1374 // The out event needs to be triggered independently
1375 this.instance
._trigger('out', event
, this.instance
._uiHash(this.instance
));
1377 this.instance
._mouseStop(event
, true);
1378 this.instance
.options
.helper
= this.instance
.options
._helper
;
1380 //Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size
1381 this.instance
.currentItem
.remove();
1382 if(this.instance
.placeholder
) this.instance
.placeholder
.remove();
1384 inst
._trigger("fromSortable", event
);
1385 inst
.dropped
= false; //draggable revert needs that
1395 $.ui
.plugin
.add("draggable", "cursor", {
1396 start: function(event
, ui
) {
1397 var t
= $('body'), o
= $(this).data('draggable').options
;
1398 if (t
.css("cursor")) o
._cursor
= t
.css("cursor");
1399 t
.css("cursor", o
.cursor
);
1401 stop: function(event
, ui
) {
1402 var o
= $(this).data('draggable').options
;
1403 if (o
._cursor
) $('body').css("cursor", o
._cursor
);
1407 $.ui
.plugin
.add("draggable", "opacity", {
1408 start: function(event
, ui
) {
1409 var t
= $(ui
.helper
), o
= $(this).data('draggable').options
;
1410 if(t
.css("opacity")) o
._opacity
= t
.css("opacity");
1411 t
.css('opacity', o
.opacity
);
1413 stop: function(event
, ui
) {
1414 var o
= $(this).data('draggable').options
;
1415 if(o
._opacity
) $(ui
.helper
).css('opacity', o
._opacity
);
1419 $.ui
.plugin
.add("draggable", "scroll", {
1420 start: function(event
, ui
) {
1421 var i
= $(this).data("draggable");
1422 if(i
.scrollParent
[0] != document
&& i
.scrollParent
[0].tagName
!= 'HTML') i
.overflowOffset
= i
.scrollParent
.offset();
1424 drag: function(event
, ui
) {
1426 var i
= $(this).data("draggable"), o
= i
.options
, scrolled
= false;
1428 if(i
.scrollParent
[0] != document
&& i
.scrollParent
[0].tagName
!= 'HTML') {
1430 if(!o
.axis
|| o
.axis
!= 'x') {
1431 if((i
.overflowOffset
.top
+ i
.scrollParent
[0].offsetHeight
) - event
.pageY
< o
.scrollSensitivity
)
1432 i
.scrollParent
[0].scrollTop
= scrolled
= i
.scrollParent
[0].scrollTop
+ o
.scrollSpeed
;
1433 else if(event
.pageY
- i
.overflowOffset
.top
< o
.scrollSensitivity
)
1434 i
.scrollParent
[0].scrollTop
= scrolled
= i
.scrollParent
[0].scrollTop
- o
.scrollSpeed
;
1437 if(!o
.axis
|| o
.axis
!= 'y') {
1438 if((i
.overflowOffset
.left
+ i
.scrollParent
[0].offsetWidth
) - event
.pageX
< o
.scrollSensitivity
)
1439 i
.scrollParent
[0].scrollLeft
= scrolled
= i
.scrollParent
[0].scrollLeft
+ o
.scrollSpeed
;
1440 else if(event
.pageX
- i
.overflowOffset
.left
< o
.scrollSensitivity
)
1441 i
.scrollParent
[0].scrollLeft
= scrolled
= i
.scrollParent
[0].scrollLeft
- o
.scrollSpeed
;
1446 if(!o
.axis
|| o
.axis
!= 'x') {
1447 if(event
.pageY
- $(document
).scrollTop() < o
.scrollSensitivity
)
1448 scrolled
= $(document
).scrollTop($(document
).scrollTop() - o
.scrollSpeed
);
1449 else if($(window
).height() - (event
.pageY
- $(document
).scrollTop()) < o
.scrollSensitivity
)
1450 scrolled
= $(document
).scrollTop($(document
).scrollTop() + o
.scrollSpeed
);
1453 if(!o
.axis
|| o
.axis
!= 'y') {
1454 if(event
.pageX
- $(document
).scrollLeft() < o
.scrollSensitivity
)
1455 scrolled
= $(document
).scrollLeft($(document
).scrollLeft() - o
.scrollSpeed
);
1456 else if($(window
).width() - (event
.pageX
- $(document
).scrollLeft()) < o
.scrollSensitivity
)
1457 scrolled
= $(document
).scrollLeft($(document
).scrollLeft() + o
.scrollSpeed
);
1462 if(scrolled
!== false && $.ui
.ddmanager
&& !o
.dropBehaviour
)
1463 $.ui
.ddmanager
.prepareOffsets(i
, event
);
1468 $.ui
.plugin
.add("draggable", "snap", {
1469 start: function(event
, ui
) {
1471 var i
= $(this).data("draggable"), o
= i
.options
;
1472 i
.snapElements
= [];
1474 $(o
.snap
.constructor != String
? ( o
.snap
.items
|| ':data(draggable)' ) : o
.snap
).each(function() {
1475 var $t
= $(this); var $o
= $t
.offset();
1476 if(this != i
.element
[0]) i
.snapElements
.push({
1478 width
: $t
.outerWidth(), height
: $t
.outerHeight(),
1479 top
: $o
.top
, left
: $o
.left
1484 drag: function(event
, ui
) {
1486 var inst
= $(this).data("draggable"), o
= inst
.options
;
1487 var d
= o
.snapTolerance
;
1489 var x1
= ui
.offset
.left
, x2
= x1
+ inst
.helperProportions
.width
,
1490 y1
= ui
.offset
.top
, y2
= y1
+ inst
.helperProportions
.height
;
1492 for (var i
= inst
.snapElements
.length
- 1; i
>= 0; i
--){
1494 var l
= inst
.snapElements
[i
].left
, r
= l
+ inst
.snapElements
[i
].width
,
1495 t
= inst
.snapElements
[i
].top
, b
= t
+ inst
.snapElements
[i
].height
;
1497 //Yes, I know, this is insane ;)
1498 if(!((l
-d
< x1
&& x1
< r
+d
&& t
-d
< y1
&& y1
< b
+d
) || (l
-d
< x1
&& x1
< r
+d
&& t
-d
< y2
&& y2
< b
+d
) || (l
-d
< x2
&& x2
< r
+d
&& t
-d
< y1
&& y1
< b
+d
) || (l
-d
< x2
&& x2
< r
+d
&& t
-d
< y2
&& y2
< b
+d
))) {
1499 if(inst
.snapElements
[i
].snapping
) (inst
.options
.snap
.release
&& inst
.options
.snap
.release
.call(inst
.element
, event
, $.extend(inst
._uiHash(), { snapItem
: inst
.snapElements
[i
].item
})));
1500 inst
.snapElements
[i
].snapping
= false;
1504 if(o
.snapMode
!= 'inner') {
1505 var ts
= Math
.abs(t
- y2
) <= d
;
1506 var bs
= Math
.abs(b
- y1
) <= d
;
1507 var ls
= Math
.abs(l
- x2
) <= d
;
1508 var rs
= Math
.abs(r
- x1
) <= d
;
1509 if(ts
) ui
.position
.top
= inst
._convertPositionTo("relative", { top
: t
- inst
.helperProportions
.height
, left
: 0 }).top
- inst
.margins
.top
;
1510 if(bs
) ui
.position
.top
= inst
._convertPositionTo("relative", { top
: b
, left
: 0 }).top
- inst
.margins
.top
;
1511 if(ls
) ui
.position
.left
= inst
._convertPositionTo("relative", { top
: 0, left
: l
- inst
.helperProportions
.width
}).left
- inst
.margins
.left
;
1512 if(rs
) ui
.position
.left
= inst
._convertPositionTo("relative", { top
: 0, left
: r
}).left
- inst
.margins
.left
;
1515 var first
= (ts
|| bs
|| ls
|| rs
);
1517 if(o
.snapMode
!= 'outer') {
1518 var ts
= Math
.abs(t
- y1
) <= d
;
1519 var bs
= Math
.abs(b
- y2
) <= d
;
1520 var ls
= Math
.abs(l
- x1
) <= d
;
1521 var rs
= Math
.abs(r
- x2
) <= d
;
1522 if(ts
) ui
.position
.top
= inst
._convertPositionTo("relative", { top
: t
, left
: 0 }).top
- inst
.margins
.top
;
1523 if(bs
) ui
.position
.top
= inst
._convertPositionTo("relative", { top
: b
- inst
.helperProportions
.height
, left
: 0 }).top
- inst
.margins
.top
;
1524 if(ls
) ui
.position
.left
= inst
._convertPositionTo("relative", { top
: 0, left
: l
}).left
- inst
.margins
.left
;
1525 if(rs
) ui
.position
.left
= inst
._convertPositionTo("relative", { top
: 0, left
: r
- inst
.helperProportions
.width
}).left
- inst
.margins
.left
;
1528 if(!inst
.snapElements
[i
].snapping
&& (ts
|| bs
|| ls
|| rs
|| first
))
1529 (inst
.options
.snap
.snap
&& inst
.options
.snap
.snap
.call(inst
.element
, event
, $.extend(inst
._uiHash(), { snapItem
: inst
.snapElements
[i
].item
})));
1530 inst
.snapElements
[i
].snapping
= (ts
|| bs
|| ls
|| rs
|| first
);
1537 $.ui
.plugin
.add("draggable", "stack", {
1538 start: function(event
, ui
) {
1540 var o
= $(this).data("draggable").options
;
1542 var group
= $.makeArray($(o
.stack
)).sort(function(a
,b
) {
1543 return (parseInt($(a
).css("zIndex"),10) || 0) - (parseInt($(b
).css("zIndex"),10) || 0);
1545 if (!group
.length
) { return; }
1547 var min
= parseInt(group
[0].style
.zIndex
) || 0;
1548 $(group
).each(function(i
) {
1549 this.style
.zIndex
= min
+ i
;
1552 this[0].style
.zIndex
= min
+ group
.length
;
1557 $.ui
.plugin
.add("draggable", "zIndex", {
1558 start: function(event
, ui
) {
1559 var t
= $(ui
.helper
), o
= $(this).data("draggable").options
;
1560 if(t
.css("zIndex")) o
._zIndex
= t
.css("zIndex");
1561 t
.css('zIndex', o
.zIndex
);
1563 stop: function(event
, ui
) {
1564 var o
= $(this).data("draggable").options
;
1565 if(o
._zIndex
) $(ui
.helper
).css('zIndex', o
._zIndex
);
1571 * jQuery UI Droppable 1.8.16
1573 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
1574 * Dual licensed under the MIT or GPL Version 2 licenses.
1575 * http://jquery.org/license
1577 * http://docs.jquery.com/UI/Droppables
1581 * jquery.ui.widget.js
1582 * jquery.ui.mouse.js
1583 * jquery.ui.draggable.js
1585 (function( $, undefined ) {
1587 $.widget("ui.droppable", {
1588 widgetEventPrefix
: "drop",
1596 tolerance
: 'intersect'
1598 _create: function() {
1600 var o
= this.options
, accept
= o
.accept
;
1601 this.isover
= 0; this.isout
= 1;
1603 this.accept
= $.isFunction(accept
) ? accept : function(d
) {
1604 return d
.is(accept
);
1607 //Store the droppable's proportions
1608 this.proportions
= { width
: this.element
[0].offsetWidth
, height
: this.element
[0].offsetHeight
};
1610 // Add the reference and positions to the manager
1611 $.ui
.ddmanager
.droppables
[o
.scope
] = $.ui
.ddmanager
.droppables
[o
.scope
] || [];
1612 $.ui
.ddmanager
.droppables
[o
.scope
].push(this);
1614 (o
.addClasses
&& this.element
.addClass("ui-droppable"));
1618 destroy: function() {
1619 var drop
= $.ui
.ddmanager
.droppables
[this.options
.scope
];
1620 for ( var i
= 0; i
< drop
.length
; i
++ )
1621 if ( drop
[i
] == this )
1625 .removeClass("ui-droppable ui-droppable-disabled")
1626 .removeData("droppable")
1627 .unbind(".droppable");
1632 _setOption: function(key
, value
) {
1634 if(key
== 'accept') {
1635 this.accept
= $.isFunction(value
) ? value : function(d
) {
1639 $.Widget
.prototype._setOption
.apply(this, arguments
);
1642 _activate: function(event
) {
1643 var draggable
= $.ui
.ddmanager
.current
;
1644 if(this.options
.activeClass
) this.element
.addClass(this.options
.activeClass
);
1645 (draggable
&& this._trigger('activate', event
, this.ui(draggable
)));
1648 _deactivate: function(event
) {
1649 var draggable
= $.ui
.ddmanager
.current
;
1650 if(this.options
.activeClass
) this.element
.removeClass(this.options
.activeClass
);
1651 (draggable
&& this._trigger('deactivate', event
, this.ui(draggable
)));
1654 _over: function(event
) {
1656 var draggable
= $.ui
.ddmanager
.current
;
1657 if (!draggable
|| (draggable
.currentItem
|| draggable
.element
)[0] == this.element
[0]) return; // Bail if draggable and droppable are same element
1659 if (this.accept
.call(this.element
[0],(draggable
.currentItem
|| draggable
.element
))) {
1660 if(this.options
.hoverClass
) this.element
.addClass(this.options
.hoverClass
);
1661 this._trigger('over', event
, this.ui(draggable
));
1666 _out: function(event
) {
1668 var draggable
= $.ui
.ddmanager
.current
;
1669 if (!draggable
|| (draggable
.currentItem
|| draggable
.element
)[0] == this.element
[0]) return; // Bail if draggable and droppable are same element
1671 if (this.accept
.call(this.element
[0],(draggable
.currentItem
|| draggable
.element
))) {
1672 if(this.options
.hoverClass
) this.element
.removeClass(this.options
.hoverClass
);
1673 this._trigger('out', event
, this.ui(draggable
));
1678 _drop: function(event
,custom
) {
1680 var draggable
= custom
|| $.ui
.ddmanager
.current
;
1681 if (!draggable
|| (draggable
.currentItem
|| draggable
.element
)[0] == this.element
[0]) return false; // Bail if draggable and droppable are same element
1683 var childrenIntersection
= false;
1684 this.element
.find(":data(droppable)").not(".ui-draggable-dragging").each(function() {
1685 var inst
= $.data(this, 'droppable');
1688 && !inst
.options
.disabled
1689 && inst
.options
.scope
== draggable
.options
.scope
1690 && inst
.accept
.call(inst
.element
[0], (draggable
.currentItem
|| draggable
.element
))
1691 && $.ui
.intersect(draggable
, $.extend(inst
, { offset
: inst
.element
.offset() }), inst
.options
.tolerance
)
1692 ) { childrenIntersection
= true; return false; }
1694 if(childrenIntersection
) return false;
1696 if(this.accept
.call(this.element
[0],(draggable
.currentItem
|| draggable
.element
))) {
1697 if(this.options
.activeClass
) this.element
.removeClass(this.options
.activeClass
);
1698 if(this.options
.hoverClass
) this.element
.removeClass(this.options
.hoverClass
);
1699 this._trigger('drop', event
, this.ui(draggable
));
1700 return this.element
;
1709 draggable
: (c
.currentItem
|| c
.element
),
1711 position
: c
.position
,
1712 offset
: c
.positionAbs
1718 $.extend($.ui
.droppable
, {
1722 $.ui
.intersect = function(draggable
, droppable
, toleranceMode
) {
1724 if (!droppable
.offset
) return false;
1726 var x1
= (draggable
.positionAbs
|| draggable
.position
.absolute
).left
, x2
= x1
+ draggable
.helperProportions
.width
,
1727 y1
= (draggable
.positionAbs
|| draggable
.position
.absolute
).top
, y2
= y1
+ draggable
.helperProportions
.height
;
1728 var l
= droppable
.offset
.left
, r
= l
+ droppable
.proportions
.width
,
1729 t
= droppable
.offset
.top
, b
= t
+ droppable
.proportions
.height
;
1731 switch (toleranceMode
) {
1733 return (l
<= x1
&& x2
<= r
1734 && t
<= y1
&& y2
<= b
);
1737 return (l
< x1
+ (draggable
.helperProportions
.width
/ 2) // Right Half
1738 && x2
- (draggable
.helperProportions
.width
/ 2) < r
// Left Half
1739 && t
< y1
+ (draggable
.helperProportions
.height
/ 2) // Bottom Half
1740 && y2
- (draggable
.helperProportions
.height
/ 2) < b
); // Top Half
1743 var draggableLeft
= ((draggable
.positionAbs
|| draggable
.position
.absolute
).left
+ (draggable
.clickOffset
|| draggable
.offset
.click
).left
),
1744 draggableTop
= ((draggable
.positionAbs
|| draggable
.position
.absolute
).top
+ (draggable
.clickOffset
|| draggable
.offset
.click
).top
),
1745 isOver
= $.ui
.isOver(draggableTop
, draggableLeft
, t
, l
, droppable
.proportions
.height
, droppable
.proportions
.width
);
1750 (y1
>= t
&& y1
<= b
) || // Top edge touching
1751 (y2
>= t
&& y2
<= b
) || // Bottom edge touching
1752 (y1
< t
&& y2
> b
) // Surrounded vertically
1754 (x1
>= l
&& x1
<= r
) || // Left edge touching
1755 (x2
>= l
&& x2
<= r
) || // Right edge touching
1756 (x1
< l
&& x2
> r
) // Surrounded horizontally
1767 This manager tracks offsets of draggables and droppables
1771 droppables
: { 'default': [] },
1772 prepareOffsets: function(t
, event
) {
1774 var m
= $.ui
.ddmanager
.droppables
[t
.options
.scope
] || [];
1775 var type
= event
? event
.type
: null; // workaround for #2317
1776 var list
= (t
.currentItem
|| t
.element
).find(":data(droppable)").andSelf();
1778 droppablesLoop
: for (var i
= 0; i
< m
.length
; i
++) {
1780 if(m
[i
].options
.disabled
|| (t
&& !m
[i
].accept
.call(m
[i
].element
[0],(t
.currentItem
|| t
.element
)))) continue; //No disabled and non-accepted
1781 for (var j
=0; j
< list
.length
; j
++) { if(list
[j
] == m
[i
].element
[0]) { m
[i
].proportions
.height
= 0; continue droppablesLoop
; } }; //Filter out elements in the current dragged item
1782 m
[i
].visible
= m
[i
].element
.css("display") != "none"; if(!m
[i
].visible
) continue; //If the element is not visible, continue
1784 if(type
== "mousedown") m
[i
]._activate
.call(m
[i
], event
); //Activate the droppable if used directly from draggables
1786 m
[i
].offset
= m
[i
].element
.offset();
1787 m
[i
].proportions
= { width
: m
[i
].element
[0].offsetWidth
, height
: m
[i
].element
[0].offsetHeight
};
1792 drop: function(draggable
, event
) {
1794 var dropped
= false;
1795 $.each($.ui
.ddmanager
.droppables
[draggable
.options
.scope
] || [], function() {
1797 if(!this.options
) return;
1798 if (!this.options
.disabled
&& this.visible
&& $.ui
.intersect(draggable
, this, this.options
.tolerance
))
1799 dropped
= dropped
|| this._drop
.call(this, event
);
1801 if (!this.options
.disabled
&& this.visible
&& this.accept
.call(this.element
[0],(draggable
.currentItem
|| draggable
.element
))) {
1802 this.isout
= 1; this.isover
= 0;
1803 this._deactivate
.call(this, event
);
1810 dragStart: function( draggable
, event
) {
1811 //Listen for scrolling so that if the dragging causes scrolling the position of the droppables can be recalculated (see #5003)
1812 draggable
.element
.parents( ":not(body,html)" ).bind( "scroll.droppable", function() {
1813 if( !draggable
.options
.refreshPositions
) $.ui
.ddmanager
.prepareOffsets( draggable
, event
);
1816 drag: function(draggable
, event
) {
1818 //If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse.
1819 if(draggable
.options
.refreshPositions
) $.ui
.ddmanager
.prepareOffsets(draggable
, event
);
1821 //Run through all droppables and check their positions based on specific tolerance options
1822 $.each($.ui
.ddmanager
.droppables
[draggable
.options
.scope
] || [], function() {
1824 if(this.options
.disabled
|| this.greedyChild
|| !this.visible
) return;
1825 var intersects
= $.ui
.intersect(draggable
, this, this.options
.tolerance
);
1827 var c
= !intersects
&& this.isover
== 1 ? 'isout' : (intersects
&& this.isover
== 0 ? 'isover' : null);
1831 if (this.options
.greedy
) {
1832 var parent
= this.element
.parents(':data(droppable):eq(0)');
1833 if (parent
.length
) {
1834 parentInstance
= $.data(parent
[0], 'droppable');
1835 parentInstance
.greedyChild
= (c
== 'isover' ? 1 : 0);
1839 // we just moved into a greedy child
1840 if (parentInstance
&& c
== 'isover') {
1841 parentInstance
['isover'] = 0;
1842 parentInstance
['isout'] = 1;
1843 parentInstance
._out
.call(parentInstance
, event
);
1846 this[c
] = 1; this[c
== 'isout' ? 'isover' : 'isout'] = 0;
1847 this[c
== "isover" ? "_over" : "_out"].call(this, event
);
1849 // we just moved out of a greedy child
1850 if (parentInstance
&& c
== 'isout') {
1851 parentInstance
['isout'] = 0;
1852 parentInstance
['isover'] = 1;
1853 parentInstance
._over
.call(parentInstance
, event
);
1858 dragStop: function( draggable
, event
) {
1859 draggable
.element
.parents( ":not(body,html)" ).unbind( "scroll.droppable" );
1860 //Call prepareOffsets one final time since IE does not fire return scroll events when overflow was caused by drag (see #5003)
1861 if( !draggable
.options
.refreshPositions
) $.ui
.ddmanager
.prepareOffsets( draggable
, event
);
1867 * jQuery UI Resizable 1.8.16
1869 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
1870 * Dual licensed under the MIT or GPL Version 2 licenses.
1871 * http://jquery.org/license
1873 * http://docs.jquery.com/UI/Resizables
1877 * jquery.ui.mouse.js
1878 * jquery.ui.widget.js
1880 (function( $, undefined ) {
1882 $.widget("ui.resizable", $.ui
.mouse
, {
1883 widgetEventPrefix
: "resize",
1887 animateDuration
: "slow",
1888 animateEasing
: "swing",
1902 _create: function() {
1904 var self
= this, o
= this.options
;
1905 this.element
.addClass("ui-resizable");
1908 _aspectRatio
: !!(o
.aspectRatio
),
1909 aspectRatio
: o
.aspectRatio
,
1910 originalElement
: this.element
,
1911 _proportionallyResizeElements
: [],
1912 _helper
: o
.helper
|| o
.ghost
|| o
.animate
? o
.helper
|| 'ui-resizable-helper' : null
1915 //Wrap the element if it cannot hold child nodes
1916 if(this.element
[0].nodeName
.match(/canvas|textarea|input|select|button|img/i)) {
1918 //Opera fix for relative positioning
1919 if (/relative/.test(this.element
.css('position')) && $.browser
.opera
)
1920 this.element
.css({ position
: 'relative', top
: 'auto', left
: 'auto' });
1922 //Create a wrapper element and set the wrapper to the new current internal element
1924 $('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({
1925 position
: this.element
.css('position'),
1926 width
: this.element
.outerWidth(),
1927 height
: this.element
.outerHeight(),
1928 top
: this.element
.css('top'),
1929 left
: this.element
.css('left')
1933 //Overwrite the original this.element
1934 this.element
= this.element
.parent().data(
1935 "resizable", this.element
.data('resizable')
1938 this.elementIsWrapper
= true;
1940 //Move margins to the wrapper
1941 this.element
.css({ marginLeft
: this.originalElement
.css("marginLeft"), marginTop
: this.originalElement
.css("marginTop"), marginRight
: this.originalElement
.css("marginRight"), marginBottom
: this.originalElement
.css("marginBottom") });
1942 this.originalElement
.css({ marginLeft
: 0, marginTop
: 0, marginRight
: 0, marginBottom
: 0});
1944 //Prevent Safari textarea resize
1945 this.originalResizeStyle
= this.originalElement
.css('resize');
1946 this.originalElement
.css('resize', 'none');
1948 //Push the actual element to our proportionallyResize internal array
1949 this._proportionallyResizeElements
.push(this.originalElement
.css({ position
: 'static', zoom
: 1, display
: 'block' }));
1951 // avoid IE jump (hard set the margin)
1952 this.originalElement
.css({ margin
: this.originalElement
.css('margin') });
1954 // fix handlers offset
1955 this._proportionallyResize();
1959 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' });
1960 if(this.handles
.constructor == String
) {
1962 if(this.handles
== 'all') this.handles
= 'n,e,s,w,se,sw,ne,nw';
1963 var n
= this.handles
.split(","); this.handles
= {};
1965 for(var i
= 0; i
< n
.length
; i
++) {
1967 var handle
= $.trim(n
[i
]), hname
= 'ui-resizable-'+handle
;
1968 var axis
= $('<div class="ui-resizable-handle ' + hname
+ '"></div>');
1970 // increase zIndex of sw, se, ne, nw axis
1971 //TODO : this modifies original option
1972 if(/sw|se|ne|nw/.test(handle
)) axis
.css({ zIndex
: ++o
.zIndex
});
1974 //TODO : What's going on here?
1975 if ('se' == handle
) {
1976 axis
.addClass('ui-icon ui-icon-gripsmall-diagonal-se');
1979 //Insert into internal handles object and append to element
1980 this.handles
[handle
] = '.ui-resizable-'+handle
;
1981 this.element
.append(axis
);
1986 this._renderAxis = function(target
) {
1988 target
= target
|| this.element
;
1990 for(var i
in this.handles
) {
1992 if(this.handles
[i
].constructor == String
)
1993 this.handles
[i
] = $(this.handles
[i
], this.element
).show();
1995 //Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls)
1996 if (this.elementIsWrapper
&& this.originalElement
[0].nodeName
.match(/textarea|input|select|button/i)) {
1998 var axis
= $(this.handles
[i
], this.element
), padWrapper
= 0;
2000 //Checking the correct pad and border
2001 padWrapper
= /sw|ne|nw|se|n|s/.test(i
) ? axis
.outerHeight() : axis
.outerWidth();
2003 //The padding type i have to apply...
2004 var padPos
= [ 'padding',
2005 /ne|nw|n/.test(i
) ? 'Top' :
2006 /se|sw|s/.test(i
) ? 'Bottom' :
2007 /^e$/.test(i
) ? 'Right' : 'Left' ].join("");
2009 target
.css(padPos
, padWrapper
);
2011 this._proportionallyResize();
2015 //TODO: What's that good for? There's not anything to be executed left
2016 if(!$(this.handles
[i
]).length
)
2022 //TODO: make renderAxis a prototype function
2023 this._renderAxis(this.element
);
2025 this._handles
= $('.ui-resizable-handle', this.element
)
2026 .disableSelection();
2028 //Matching axis name
2029 this._handles
.mouseover(function() {
2030 if (!self
.resizing
) {
2032 var axis
= this.className
.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);
2033 //Axis, default = se
2034 self
.axis
= axis
&& axis
[1] ? axis
[1] : 'se';
2038 //If we want to auto hide the elements
2040 this._handles
.hide();
2042 .addClass("ui-resizable-autohide")
2044 if (o
.disabled
) return;
2045 $(this).removeClass("ui-resizable-autohide");
2046 self
._handles
.show();
2049 if (o
.disabled
) return;
2050 if (!self
.resizing
) {
2051 $(this).addClass("ui-resizable-autohide");
2052 self
._handles
.hide();
2057 //Initialize the mouse interaction
2062 destroy: function() {
2064 this._mouseDestroy();
2066 var _destroy = function(exp
) {
2067 $(exp
).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing")
2068 .removeData("resizable").unbind(".resizable").find('.ui-resizable-handle').remove();
2071 //TODO: Unwrap at same DOM position
2072 if (this.elementIsWrapper
) {
2073 _destroy(this.element
);
2074 var wrapper
= this.element
;
2076 this.originalElement
.css({
2077 position
: wrapper
.css('position'),
2078 width
: wrapper
.outerWidth(),
2079 height
: wrapper
.outerHeight(),
2080 top
: wrapper
.css('top'),
2081 left
: wrapper
.css('left')
2086 this.originalElement
.css('resize', this.originalResizeStyle
);
2087 _destroy(this.originalElement
);
2092 _mouseCapture: function(event
) {
2094 for (var i
in this.handles
) {
2095 if ($(this.handles
[i
])[0] == event
.target
) {
2100 return !this.options
.disabled
&& handle
;
2103 _mouseStart: function(event
) {
2105 var o
= this.options
, iniPos
= this.element
.position(), el
= this.element
;
2107 this.resizing
= true;
2108 this.documentScroll
= { top
: $(document
).scrollTop(), left
: $(document
).scrollLeft() };
2110 // bugfix for http://dev.jquery.com/ticket/1749
2111 if (el
.is('.ui-draggable') || (/absolute/).test(el
.css('position'))) {
2112 el
.css({ position
: 'absolute', top
: iniPos
.top
, left
: iniPos
.left
});
2115 //Opera fixing relative position
2116 if ($.browser
.opera
&& (/relative/).test(el
.css('position')))
2117 el
.css({ position
: 'relative', top
: 'auto', left
: 'auto' });
2119 this._renderProxy();
2121 var curleft
= num(this.helper
.css('left')), curtop
= num(this.helper
.css('top'));
2123 if (o
.containment
) {
2124 curleft
+= $(o
.containment
).scrollLeft() || 0;
2125 curtop
+= $(o
.containment
).scrollTop() || 0;
2128 //Store needed variables
2129 this.offset
= this.helper
.offset();
2130 this.position
= { left
: curleft
, top
: curtop
};
2131 this.size
= this._helper
? { width
: el
.outerWidth(), height
: el
.outerHeight() } : { width
: el
.width(), height
: el
.height() };
2132 this.originalSize
= this._helper
? { width
: el
.outerWidth(), height
: el
.outerHeight() } : { width
: el
.width(), height
: el
.height() };
2133 this.originalPosition
= { left
: curleft
, top
: curtop
};
2134 this.sizeDiff
= { width
: el
.outerWidth() - el
.width(), height
: el
.outerHeight() - el
.height() };
2135 this.originalMousePosition
= { left
: event
.pageX
, top
: event
.pageY
};
2138 this.aspectRatio
= (typeof o
.aspectRatio
== 'number') ? o
.aspectRatio
: ((this.originalSize
.width
/ this.originalSize
.height
) || 1);
2140 var cursor
= $('.ui-resizable-' + this.axis
).css('cursor');
2141 $('body').css('cursor', cursor
== 'auto' ? this.axis
+ '-resize' : cursor
);
2143 el
.addClass("ui-resizable-resizing");
2144 this._propagate("start", event
);
2148 _mouseDrag: function(event
) {
2150 //Increase performance, avoid regex
2151 var el
= this.helper
, o
= this.options
, props
= {},
2152 self
= this, smp
= this.originalMousePosition
, a
= this.axis
;
2154 var dx
= (event
.pageX
-smp
.left
)||0, dy
= (event
.pageY
-smp
.top
)||0;
2155 var trigger
= this._change
[a
];
2156 if (!trigger
) return false;
2158 // Calculate the attrs that will be change
2159 var data
= trigger
.apply(this, [event
, dx
, dy
]), ie6
= $.browser
.msie
&& $.browser
.version
< 7, csdif
= this.sizeDiff
;
2161 // Put this in the mouseDrag handler since the user can start pressing shift while resizing
2162 this._updateVirtualBoundaries(event
.shiftKey
);
2163 if (this._aspectRatio
|| event
.shiftKey
)
2164 data
= this._updateRatio(data
, event
);
2166 data
= this._respectSize(data
, event
);
2168 // plugins callbacks need to be called first
2169 this._propagate("resize", event
);
2172 top
: this.position
.top
+ "px", left
: this.position
.left
+ "px",
2173 width
: this.size
.width
+ "px", height
: this.size
.height
+ "px"
2176 if (!this._helper
&& this._proportionallyResizeElements
.length
)
2177 this._proportionallyResize();
2179 this._updateCache(data
);
2181 // calling the user callback at the end
2182 this._trigger('resize', event
, this.ui());
2187 _mouseStop: function(event
) {
2189 this.resizing
= false;
2190 var o
= this.options
, self
= this;
2193 var pr
= this._proportionallyResizeElements
, ista
= pr
.length
&& (/textarea/i).test(pr
[0].nodeName
),
2194 soffseth
= ista
&& $.ui
.hasScroll(pr
[0], 'left') /* TODO - jump height */ ? 0 : self
.sizeDiff
.height
,
2195 soffsetw
= ista
? 0 : self
.sizeDiff
.width
;
2197 var s
= { width
: (self
.helper
.width() - soffsetw
), height
: (self
.helper
.height() - soffseth
) },
2198 left
= (parseInt(self
.element
.css('left'), 10) + (self
.position
.left
- self
.originalPosition
.left
)) || null,
2199 top
= (parseInt(self
.element
.css('top'), 10) + (self
.position
.top
- self
.originalPosition
.top
)) || null;
2202 this.element
.css($.extend(s
, { top
: top
, left
: left
}));
2204 self
.helper
.height(self
.size
.height
);
2205 self
.helper
.width(self
.size
.width
);
2207 if (this._helper
&& !o
.animate
) this._proportionallyResize();
2210 $('body').css('cursor', 'auto');
2212 this.element
.removeClass("ui-resizable-resizing");
2214 this._propagate("stop", event
);
2216 if (this._helper
) this.helper
.remove();
2221 _updateVirtualBoundaries: function(forceAspectRatio
) {
2222 var o
= this.options
, pMinWidth
, pMaxWidth
, pMinHeight
, pMaxHeight
, b
;
2225 minWidth
: isNumber(o
.minWidth
) ? o
.minWidth
: 0,
2226 maxWidth
: isNumber(o
.maxWidth
) ? o
.maxWidth
: Infinity
,
2227 minHeight
: isNumber(o
.minHeight
) ? o
.minHeight
: 0,
2228 maxHeight
: isNumber(o
.maxHeight
) ? o
.maxHeight
: Infinity
2231 if(this._aspectRatio
|| forceAspectRatio
) {
2232 // We want to create an enclosing box whose aspect ration is the requested one
2233 // First, compute the "projected" size for each dimension based on the aspect ratio and other dimension
2234 pMinWidth
= b
.minHeight
* this.aspectRatio
;
2235 pMinHeight
= b
.minWidth
/ this.aspectRatio
;
2236 pMaxWidth
= b
.maxHeight
* this.aspectRatio
;
2237 pMaxHeight
= b
.maxWidth
/ this.aspectRatio
;
2239 if(pMinWidth
> b
.minWidth
) b
.minWidth
= pMinWidth
;
2240 if(pMinHeight
> b
.minHeight
) b
.minHeight
= pMinHeight
;
2241 if(pMaxWidth
< b
.maxWidth
) b
.maxWidth
= pMaxWidth
;
2242 if(pMaxHeight
< b
.maxHeight
) b
.maxHeight
= pMaxHeight
;
2244 this._vBoundaries
= b
;
2247 _updateCache: function(data
) {
2248 var o
= this.options
;
2249 this.offset
= this.helper
.offset();
2250 if (isNumber(data
.left
)) this.position
.left
= data
.left
;
2251 if (isNumber(data
.top
)) this.position
.top
= data
.top
;
2252 if (isNumber(data
.height
)) this.size
.height
= data
.height
;
2253 if (isNumber(data
.width
)) this.size
.width
= data
.width
;
2256 _updateRatio: function(data
, event
) {
2258 var o
= this.options
, cpos
= this.position
, csize
= this.size
, a
= this.axis
;
2260 if (isNumber(data
.height
)) data
.width
= (data
.height
* this.aspectRatio
);
2261 else if (isNumber(data
.width
)) data
.height
= (data
.width
/ this.aspectRatio
);
2264 data
.left
= cpos
.left
+ (csize
.width
- data
.width
);
2268 data
.top
= cpos
.top
+ (csize
.height
- data
.height
);
2269 data
.left
= cpos
.left
+ (csize
.width
- data
.width
);
2275 _respectSize: function(data
, event
) {
2277 var el
= this.helper
, o
= this._vBoundaries
, pRatio
= this._aspectRatio
|| event
.shiftKey
, a
= this.axis
,
2278 ismaxw
= isNumber(data
.width
) && o
.maxWidth
&& (o
.maxWidth
< data
.width
), ismaxh
= isNumber(data
.height
) && o
.maxHeight
&& (o
.maxHeight
< data
.height
),
2279 isminw
= isNumber(data
.width
) && o
.minWidth
&& (o
.minWidth
> data
.width
), isminh
= isNumber(data
.height
) && o
.minHeight
&& (o
.minHeight
> data
.height
);
2281 if (isminw
) data
.width
= o
.minWidth
;
2282 if (isminh
) data
.height
= o
.minHeight
;
2283 if (ismaxw
) data
.width
= o
.maxWidth
;
2284 if (ismaxh
) data
.height
= o
.maxHeight
;
2286 var dw
= this.originalPosition
.left
+ this.originalSize
.width
, dh
= this.position
.top
+ this.size
.height
;
2287 var cw
= /sw|nw|w/.test(a
), ch
= /nw|ne|n/.test(a
);
2289 if (isminw
&& cw
) data
.left
= dw
- o
.minWidth
;
2290 if (ismaxw
&& cw
) data
.left
= dw
- o
.maxWidth
;
2291 if (isminh
&& ch
) data
.top
= dh
- o
.minHeight
;
2292 if (ismaxh
&& ch
) data
.top
= dh
- o
.maxHeight
;
2294 // fixing jump error on top/left - bug #2330
2295 var isNotwh
= !data
.width
&& !data
.height
;
2296 if (isNotwh
&& !data
.left
&& data
.top
) data
.top
= null;
2297 else if (isNotwh
&& !data
.top
&& data
.left
) data
.left
= null;
2302 _proportionallyResize: function() {
2304 var o
= this.options
;
2305 if (!this._proportionallyResizeElements
.length
) return;
2306 var element
= this.helper
|| this.element
;
2308 for (var i
=0; i
< this._proportionallyResizeElements
.length
; i
++) {
2310 var prel
= this._proportionallyResizeElements
[i
];
2312 if (!this.borderDif
) {
2313 var b
= [prel
.css('borderTopWidth'), prel
.css('borderRightWidth'), prel
.css('borderBottomWidth'), prel
.css('borderLeftWidth')],
2314 p
= [prel
.css('paddingTop'), prel
.css('paddingRight'), prel
.css('paddingBottom'), prel
.css('paddingLeft')];
2316 this.borderDif
= $.map(b
, function(v
, i
) {
2317 var border
= parseInt(v
,10)||0, padding
= parseInt(p
[i
],10)||0;
2318 return border
+ padding
;
2322 if ($.browser
.msie
&& !(!($(element
).is(':hidden') || $(element
).parents(':hidden').length
)))
2326 height
: (element
.height() - this.borderDif
[0] - this.borderDif
[2]) || 0,
2327 width
: (element
.width() - this.borderDif
[1] - this.borderDif
[3]) || 0
2334 _renderProxy: function() {
2336 var el
= this.element
, o
= this.options
;
2337 this.elementOffset
= el
.offset();
2341 this.helper
= this.helper
|| $('<div style="overflow:hidden;"></div>');
2343 // fix ie6 offset TODO: This seems broken
2344 var ie6
= $.browser
.msie
&& $.browser
.version
< 7, ie6offset
= (ie6
? 1 : 0),
2345 pxyoffset
= ( ie6
? 2 : -1 );
2347 this.helper
.addClass(this._helper
).css({
2348 width
: this.element
.outerWidth() + pxyoffset
,
2349 height
: this.element
.outerHeight() + pxyoffset
,
2350 position
: 'absolute',
2351 left
: this.elementOffset
.left
- ie6offset
+'px',
2352 top
: this.elementOffset
.top
- ie6offset
+'px',
2353 zIndex
: ++o
.zIndex
//TODO: Don't modify option
2358 .disableSelection();
2361 this.helper
= this.element
;
2367 e: function(event
, dx
, dy
) {
2368 return { width
: this.originalSize
.width
+ dx
};
2370 w: function(event
, dx
, dy
) {
2371 var o
= this.options
, cs
= this.originalSize
, sp
= this.originalPosition
;
2372 return { left
: sp
.left
+ dx
, width
: cs
.width
- dx
};
2374 n: function(event
, dx
, dy
) {
2375 var o
= this.options
, cs
= this.originalSize
, sp
= this.originalPosition
;
2376 return { top
: sp
.top
+ dy
, height
: cs
.height
- dy
};
2378 s: function(event
, dx
, dy
) {
2379 return { height
: this.originalSize
.height
+ dy
};
2381 se: function(event
, dx
, dy
) {
2382 return $.extend(this._change
.s
.apply(this, arguments
), this._change
.e
.apply(this, [event
, dx
, dy
]));
2384 sw: function(event
, dx
, dy
) {
2385 return $.extend(this._change
.s
.apply(this, arguments
), this._change
.w
.apply(this, [event
, dx
, dy
]));
2387 ne: function(event
, dx
, dy
) {
2388 return $.extend(this._change
.n
.apply(this, arguments
), this._change
.e
.apply(this, [event
, dx
, dy
]));
2390 nw: function(event
, dx
, dy
) {
2391 return $.extend(this._change
.n
.apply(this, arguments
), this._change
.w
.apply(this, [event
, dx
, dy
]));
2395 _propagate: function(n
, event
) {
2396 $.ui
.plugin
.call(this, n
, [event
, this.ui()]);
2397 (n
!= "resize" && this._trigger(n
, event
, this.ui()));
2404 originalElement
: this.originalElement
,
2405 element
: this.element
,
2406 helper
: this.helper
,
2407 position
: this.position
,
2409 originalSize
: this.originalSize
,
2410 originalPosition
: this.originalPosition
2416 $.extend($.ui
.resizable
, {
2421 * Resizable Extensions
2424 $.ui
.plugin
.add("resizable", "alsoResize", {
2426 start: function (event
, ui
) {
2427 var self
= $(this).data("resizable"), o
= self
.options
;
2429 var _store = function (exp
) {
2430 $(exp
).each(function() {
2432 el
.data("resizable-alsoresize", {
2433 width
: parseInt(el
.width(), 10), height
: parseInt(el
.height(), 10),
2434 left
: parseInt(el
.css('left'), 10), top
: parseInt(el
.css('top'), 10),
2435 position
: el
.css('position') // to reset Opera on stop()
2440 if (typeof(o
.alsoResize
) == 'object' && !o
.alsoResize
.parentNode
) {
2441 if (o
.alsoResize
.length
) { o
.alsoResize
= o
.alsoResize
[0]; _store(o
.alsoResize
); }
2442 else { $.each(o
.alsoResize
, function (exp
) { _store(exp
); }); }
2444 _store(o
.alsoResize
);
2448 resize: function (event
, ui
) {
2449 var self
= $(this).data("resizable"), o
= self
.options
, os
= self
.originalSize
, op
= self
.originalPosition
;
2452 height
: (self
.size
.height
- os
.height
) || 0, width
: (self
.size
.width
- os
.width
) || 0,
2453 top
: (self
.position
.top
- op
.top
) || 0, left
: (self
.position
.left
- op
.left
) || 0
2456 _alsoResize = function (exp
, c
) {
2457 $(exp
).each(function() {
2458 var el
= $(this), start
= $(this).data("resizable-alsoresize"), style
= {},
2459 css
= c
&& c
.length
? c
: el
.parents(ui
.originalElement
[0]).length
? ['width', 'height'] : ['width', 'height', 'top', 'left'];
2461 $.each(css
, function (i
, prop
) {
2462 var sum
= (start
[prop
]||0) + (delta
[prop
]||0);
2463 if (sum
&& sum
>= 0)
2464 style
[prop
] = sum
|| null;
2467 // Opera fixing relative position
2468 if ($.browser
.opera
&& /relative/.test(el
.css('position'))) {
2469 self
._revertToRelativePosition
= true;
2470 el
.css({ position
: 'absolute', top
: 'auto', left
: 'auto' });
2477 if (typeof(o
.alsoResize
) == 'object' && !o
.alsoResize
.nodeType
) {
2478 $.each(o
.alsoResize
, function (exp
, c
) { _alsoResize(exp
, c
); });
2480 _alsoResize(o
.alsoResize
);
2484 stop: function (event
, ui
) {
2485 var self
= $(this).data("resizable"), o
= self
.options
;
2487 var _reset = function (exp
) {
2488 $(exp
).each(function() {
2490 // reset position for Opera - no need to verify it was changed
2491 el
.css({ position
: el
.data("resizable-alsoresize").position
});
2495 if (self
._revertToRelativePosition
) {
2496 self
._revertToRelativePosition
= false;
2497 if (typeof(o
.alsoResize
) == 'object' && !o
.alsoResize
.nodeType
) {
2498 $.each(o
.alsoResize
, function (exp
) { _reset(exp
); });
2500 _reset(o
.alsoResize
);
2504 $(this).removeData("resizable-alsoresize");
2508 $.ui
.plugin
.add("resizable", "animate", {
2510 stop: function(event
, ui
) {
2511 var self
= $(this).data("resizable"), o
= self
.options
;
2513 var pr
= self
._proportionallyResizeElements
, ista
= pr
.length
&& (/textarea/i).test(pr
[0].nodeName
),
2514 soffseth
= ista
&& $.ui
.hasScroll(pr
[0], 'left') /* TODO - jump height */ ? 0 : self
.sizeDiff
.height
,
2515 soffsetw
= ista
? 0 : self
.sizeDiff
.width
;
2517 var style
= { width
: (self
.size
.width
- soffsetw
), height
: (self
.size
.height
- soffseth
) },
2518 left
= (parseInt(self
.element
.css('left'), 10) + (self
.position
.left
- self
.originalPosition
.left
)) || null,
2519 top
= (parseInt(self
.element
.css('top'), 10) + (self
.position
.top
- self
.originalPosition
.top
)) || null;
2521 self
.element
.animate(
2522 $.extend(style
, top
&& left
? { top
: top
, left
: left
} : {}), {
2523 duration
: o
.animateDuration
,
2524 easing
: o
.animateEasing
,
2528 width
: parseInt(self
.element
.css('width'), 10),
2529 height
: parseInt(self
.element
.css('height'), 10),
2530 top
: parseInt(self
.element
.css('top'), 10),
2531 left
: parseInt(self
.element
.css('left'), 10)
2534 if (pr
&& pr
.length
) $(pr
[0]).css({ width
: data
.width
, height
: data
.height
});
2536 // propagating resize, and updating values for each animation step
2537 self
._updateCache(data
);
2538 self
._propagate("resize", event
);
2547 $.ui
.plugin
.add("resizable", "containment", {
2549 start: function(event
, ui
) {
2550 var self
= $(this).data("resizable"), o
= self
.options
, el
= self
.element
;
2551 var oc
= o
.containment
, ce
= (oc
instanceof $) ? oc
.get(0) : (/parent/.test(oc
)) ? el
.parent().get(0) : oc
;
2554 self
.containerElement
= $(ce
);
2556 if (/document/.test(oc
) || oc
== document
) {
2557 self
.containerOffset
= { left
: 0, top
: 0 };
2558 self
.containerPosition
= { left
: 0, top
: 0 };
2561 element
: $(document
), left
: 0, top
: 0,
2562 width
: $(document
).width(), height
: $(document
).height() || document
.body
.parentNode
.scrollHeight
2566 // i'm a node, so compute top, left, right, bottom
2568 var element
= $(ce
), p
= [];
2569 $([ "Top", "Right", "Left", "Bottom" ]).each(function(i
, name
) { p
[i
] = num(element
.css("padding" + name
)); });
2571 self
.containerOffset
= element
.offset();
2572 self
.containerPosition
= element
.position();
2573 self
.containerSize
= { height
: (element
.innerHeight() - p
[3]), width
: (element
.innerWidth() - p
[1]) };
2575 var co
= self
.containerOffset
, ch
= self
.containerSize
.height
, cw
= self
.containerSize
.width
,
2576 width
= ($.ui
.hasScroll(ce
, "left") ? ce
.scrollWidth
: cw
), height
= ($.ui
.hasScroll(ce
) ? ce
.scrollHeight
: ch
);
2579 element
: ce
, left
: co
.left
, top
: co
.top
, width
: width
, height
: height
2584 resize: function(event
, ui
) {
2585 var self
= $(this).data("resizable"), o
= self
.options
,
2586 ps
= self
.containerSize
, co
= self
.containerOffset
, cs
= self
.size
, cp
= self
.position
,
2587 pRatio
= self
._aspectRatio
|| event
.shiftKey
, cop
= { top
:0, left
:0 }, ce
= self
.containerElement
;
2589 if (ce
[0] != document
&& (/static/).test(ce
.css('position'))) cop
= co
;
2591 if (cp
.left
< (self
._helper
? co
.left
: 0)) {
2592 self
.size
.width
= self
.size
.width
+ (self
._helper
? (self
.position
.left
- co
.left
) : (self
.position
.left
- cop
.left
));
2593 if (pRatio
) self
.size
.height
= self
.size
.width
/ o
.aspectRatio
;
2594 self
.position
.left
= o
.helper
? co
.left
: 0;
2597 if (cp
.top
< (self
._helper
? co
.top
: 0)) {
2598 self
.size
.height
= self
.size
.height
+ (self
._helper
? (self
.position
.top
- co
.top
) : self
.position
.top
);
2599 if (pRatio
) self
.size
.width
= self
.size
.height
* o
.aspectRatio
;
2600 self
.position
.top
= self
._helper
? co
.top
: 0;
2603 self
.offset
.left
= self
.parentData
.left
+self
.position
.left
;
2604 self
.offset
.top
= self
.parentData
.top
+self
.position
.top
;
2606 var woset
= Math
.abs( (self
._helper
? self
.offset
.left
- cop
.left
: (self
.offset
.left
- cop
.left
)) + self
.sizeDiff
.width
),
2607 hoset
= Math
.abs( (self
._helper
? self
.offset
.top
- cop
.top
: (self
.offset
.top
- co
.top
)) + self
.sizeDiff
.height
);
2609 var isParent
= self
.containerElement
.get(0) == self
.element
.parent().get(0),
2610 isOffsetRelative
= /relative|absolute/.test(self
.containerElement
.css('position'));
2612 if(isParent
&& isOffsetRelative
) woset
-= self
.parentData
.left
;
2614 if (woset
+ self
.size
.width
>= self
.parentData
.width
) {
2615 self
.size
.width
= self
.parentData
.width
- woset
;
2616 if (pRatio
) self
.size
.height
= self
.size
.width
/ self
.aspectRatio
;
2619 if (hoset
+ self
.size
.height
>= self
.parentData
.height
) {
2620 self
.size
.height
= self
.parentData
.height
- hoset
;
2621 if (pRatio
) self
.size
.width
= self
.size
.height
* self
.aspectRatio
;
2625 stop: function(event
, ui
){
2626 var self
= $(this).data("resizable"), o
= self
.options
, cp
= self
.position
,
2627 co
= self
.containerOffset
, cop
= self
.containerPosition
, ce
= self
.containerElement
;
2629 var helper
= $(self
.helper
), ho
= helper
.offset(), w
= helper
.outerWidth() - self
.sizeDiff
.width
, h
= helper
.outerHeight() - self
.sizeDiff
.height
;
2631 if (self
._helper
&& !o
.animate
&& (/relative/).test(ce
.css('position')))
2632 $(this).css({ left
: ho
.left
- cop
.left
- co
.left
, width
: w
, height
: h
});
2634 if (self
._helper
&& !o
.animate
&& (/static/).test(ce
.css('position')))
2635 $(this).css({ left
: ho
.left
- cop
.left
- co
.left
, width
: w
, height
: h
});
2640 $.ui
.plugin
.add("resizable", "ghost", {
2642 start: function(event
, ui
) {
2644 var self
= $(this).data("resizable"), o
= self
.options
, cs
= self
.size
;
2646 self
.ghost
= self
.originalElement
.clone();
2648 .css({ opacity
: .25, display
: 'block', position
: 'relative', height
: cs
.height
, width
: cs
.width
, margin
: 0, left
: 0, top
: 0 })
2649 .addClass('ui-resizable-ghost')
2650 .addClass(typeof o
.ghost
== 'string' ? o
.ghost
: '');
2652 self
.ghost
.appendTo(self
.helper
);
2656 resize: function(event
, ui
){
2657 var self
= $(this).data("resizable"), o
= self
.options
;
2658 if (self
.ghost
) self
.ghost
.css({ position
: 'relative', height
: self
.size
.height
, width
: self
.size
.width
});
2661 stop: function(event
, ui
){
2662 var self
= $(this).data("resizable"), o
= self
.options
;
2663 if (self
.ghost
&& self
.helper
) self
.helper
.get(0).removeChild(self
.ghost
.get(0));
2668 $.ui
.plugin
.add("resizable", "grid", {
2670 resize: function(event
, ui
) {
2671 var self
= $(this).data("resizable"), o
= self
.options
, cs
= self
.size
, os
= self
.originalSize
, op
= self
.originalPosition
, a
= self
.axis
, ratio
= o
._aspectRatio
|| event
.shiftKey
;
2672 o
.grid
= typeof o
.grid
== "number" ? [o
.grid
, o
.grid
] : o
.grid
;
2673 var ox
= Math
.round((cs
.width
- os
.width
) / (o
.grid
[0]||1)) * (o
.grid
[0]||1), oy
= Math
.round((cs
.height
- os
.height
) / (o
.grid
[1]||1)) * (o
.grid
[1]||1);
2675 if (/^(se|s|e)$/.test(a
)) {
2676 self
.size
.width
= os
.width
+ ox
;
2677 self
.size
.height
= os
.height
+ oy
;
2679 else if (/^(ne)$/.test(a
)) {
2680 self
.size
.width
= os
.width
+ ox
;
2681 self
.size
.height
= os
.height
+ oy
;
2682 self
.position
.top
= op
.top
- oy
;
2684 else if (/^(sw)$/.test(a
)) {
2685 self
.size
.width
= os
.width
+ ox
;
2686 self
.size
.height
= os
.height
+ oy
;
2687 self
.position
.left
= op
.left
- ox
;
2690 self
.size
.width
= os
.width
+ ox
;
2691 self
.size
.height
= os
.height
+ oy
;
2692 self
.position
.top
= op
.top
- oy
;
2693 self
.position
.left
= op
.left
- ox
;
2699 var num = function(v
) {
2700 return parseInt(v
, 10) || 0;
2703 var isNumber = function(value
) {
2704 return !isNaN(parseInt(value
, 10));
2709 * jQuery UI Selectable 1.8.16
2711 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
2712 * Dual licensed under the MIT or GPL Version 2 licenses.
2713 * http://jquery.org/license
2715 * http://docs.jquery.com/UI/Selectables
2719 * jquery.ui.mouse.js
2720 * jquery.ui.widget.js
2722 (function( $, undefined ) {
2724 $.widget("ui.selectable", $.ui
.mouse
, {
2732 _create: function() {
2735 this.element
.addClass("ui-selectable");
2737 this.dragged
= false;
2739 // cache selectee children based on filter
2741 this.refresh = function() {
2742 selectees
= $(self
.options
.filter
, self
.element
[0]);
2743 selectees
.each(function() {
2744 var $this = $(this);
2745 var pos
= $this.offset();
2746 $.data(this, "selectable-item", {
2751 right
: pos
.left
+ $this.outerWidth(),
2752 bottom
: pos
.top
+ $this.outerHeight(),
2753 startselected
: false,
2754 selected
: $this.hasClass('ui-selected'),
2755 selecting
: $this.hasClass('ui-selecting'),
2756 unselecting
: $this.hasClass('ui-unselecting')
2762 this.selectees
= selectees
.addClass("ui-selectee");
2766 this.helper
= $("<div class='ui-selectable-helper'></div>");
2769 destroy: function() {
2771 .removeClass("ui-selectee")
2772 .removeData("selectable-item");
2774 .removeClass("ui-selectable ui-selectable-disabled")
2775 .removeData("selectable")
2776 .unbind(".selectable");
2777 this._mouseDestroy();
2782 _mouseStart: function(event
) {
2785 this.opos
= [event
.pageX
, event
.pageY
];
2787 if (this.options
.disabled
)
2790 var options
= this.options
;
2792 this.selectees
= $(options
.filter
, this.element
[0]);
2794 this._trigger("start", event
);
2796 $(options
.appendTo
).append(this.helper
);
2797 // position helper (lasso)
2799 "left": event
.clientX
,
2800 "top": event
.clientY
,
2805 if (options
.autoRefresh
) {
2809 this.selectees
.filter('.ui-selected').each(function() {
2810 var selectee
= $.data(this, "selectable-item");
2811 selectee
.startselected
= true;
2812 if (!event
.metaKey
) {
2813 selectee
.$element
.removeClass('ui-selected');
2814 selectee
.selected
= false;
2815 selectee
.$element
.addClass('ui-unselecting');
2816 selectee
.unselecting
= true;
2817 // selectable UNSELECTING callback
2818 self
._trigger("unselecting", event
, {
2819 unselecting
: selectee
.element
2824 $(event
.target
).parents().andSelf().each(function() {
2825 var selectee
= $.data(this, "selectable-item");
2827 var doSelect
= !event
.metaKey
|| !selectee
.$element
.hasClass('ui-selected');
2829 .removeClass(doSelect
? "ui-unselecting" : "ui-selected")
2830 .addClass(doSelect
? "ui-selecting" : "ui-unselecting");
2831 selectee
.unselecting
= !doSelect
;
2832 selectee
.selecting
= doSelect
;
2833 selectee
.selected
= doSelect
;
2834 // selectable (UN)SELECTING callback
2836 self
._trigger("selecting", event
, {
2837 selecting
: selectee
.element
2840 self
._trigger("unselecting", event
, {
2841 unselecting
: selectee
.element
2850 _mouseDrag: function(event
) {
2852 this.dragged
= true;
2854 if (this.options
.disabled
)
2857 var options
= this.options
;
2859 var x1
= this.opos
[0], y1
= this.opos
[1], x2
= event
.pageX
, y2
= event
.pageY
;
2860 if (x1
> x2
) { var tmp
= x2
; x2
= x1
; x1
= tmp
; }
2861 if (y1
> y2
) { var tmp
= y2
; y2
= y1
; y1
= tmp
; }
2862 this.helper
.css({left
: x1
, top
: y1
, width
: x2
-x1
, height
: y2
-y1
});
2864 this.selectees
.each(function() {
2865 var selectee
= $.data(this, "selectable-item");
2866 //prevent helper from being selected if appendTo: selectable
2867 if (!selectee
|| selectee
.element
== self
.element
[0])
2870 if (options
.tolerance
== 'touch') {
2871 hit
= ( !(selectee
.left
> x2
|| selectee
.right
< x1
|| selectee
.top
> y2
|| selectee
.bottom
< y1
) );
2872 } else if (options
.tolerance
== 'fit') {
2873 hit
= (selectee
.left
> x1
&& selectee
.right
< x2
&& selectee
.top
> y1
&& selectee
.bottom
< y2
);
2878 if (selectee
.selected
) {
2879 selectee
.$element
.removeClass('ui-selected');
2880 selectee
.selected
= false;
2882 if (selectee
.unselecting
) {
2883 selectee
.$element
.removeClass('ui-unselecting');
2884 selectee
.unselecting
= false;
2886 if (!selectee
.selecting
) {
2887 selectee
.$element
.addClass('ui-selecting');
2888 selectee
.selecting
= true;
2889 // selectable SELECTING callback
2890 self
._trigger("selecting", event
, {
2891 selecting
: selectee
.element
2896 if (selectee
.selecting
) {
2897 if (event
.metaKey
&& selectee
.startselected
) {
2898 selectee
.$element
.removeClass('ui-selecting');
2899 selectee
.selecting
= false;
2900 selectee
.$element
.addClass('ui-selected');
2901 selectee
.selected
= true;
2903 selectee
.$element
.removeClass('ui-selecting');
2904 selectee
.selecting
= false;
2905 if (selectee
.startselected
) {
2906 selectee
.$element
.addClass('ui-unselecting');
2907 selectee
.unselecting
= true;
2909 // selectable UNSELECTING callback
2910 self
._trigger("unselecting", event
, {
2911 unselecting
: selectee
.element
2915 if (selectee
.selected
) {
2916 if (!event
.metaKey
&& !selectee
.startselected
) {
2917 selectee
.$element
.removeClass('ui-selected');
2918 selectee
.selected
= false;
2920 selectee
.$element
.addClass('ui-unselecting');
2921 selectee
.unselecting
= true;
2922 // selectable UNSELECTING callback
2923 self
._trigger("unselecting", event
, {
2924 unselecting
: selectee
.element
2934 _mouseStop: function(event
) {
2937 this.dragged
= false;
2939 var options
= this.options
;
2941 $('.ui-unselecting', this.element
[0]).each(function() {
2942 var selectee
= $.data(this, "selectable-item");
2943 selectee
.$element
.removeClass('ui-unselecting');
2944 selectee
.unselecting
= false;
2945 selectee
.startselected
= false;
2946 self
._trigger("unselected", event
, {
2947 unselected
: selectee
.element
2950 $('.ui-selecting', this.element
[0]).each(function() {
2951 var selectee
= $.data(this, "selectable-item");
2952 selectee
.$element
.removeClass('ui-selecting').addClass('ui-selected');
2953 selectee
.selecting
= false;
2954 selectee
.selected
= true;
2955 selectee
.startselected
= true;
2956 self
._trigger("selected", event
, {
2957 selected
: selectee
.element
2960 this._trigger("stop", event
);
2962 this.helper
.remove();
2969 $.extend($.ui
.selectable
, {
2975 * jQuery UI Sortable 1.8.16
2977 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
2978 * Dual licensed under the MIT or GPL Version 2 licenses.
2979 * http://jquery.org/license
2981 * http://docs.jquery.com/UI/Sortables
2985 * jquery.ui.mouse.js
2986 * jquery.ui.widget.js
2988 (function( $, undefined ) {
2990 $.widget("ui.sortable", $.ui
.mouse
, {
2991 widgetEventPrefix
: "sort",
3000 forcePlaceholderSize
: false,
3001 forceHelperSize
: false,
3010 scrollSensitivity
: 20,
3013 tolerance
: "intersect",
3016 _create: function() {
3018 var o
= this.options
;
3019 this.containerCache
= {};
3020 this.element
.addClass("ui-sortable");
3025 //Let's determine if the items are being displayed horizontally
3026 this.floating
= this.items
.length
? o
.axis
=== 'x' || (/left|right/).test(this.items
[0].item
.css('float')) || (/inline|table-cell/).test(this.items
[0].item
.css('display')) : false;
3028 //Let's determine the parent's offset
3029 this.offset
= this.element
.offset();
3031 //Initialize mouse events for interaction
3036 destroy: function() {
3038 .removeClass("ui-sortable ui-sortable-disabled")
3039 .removeData("sortable")
3040 .unbind(".sortable");
3041 this._mouseDestroy();
3043 for ( var i
= this.items
.length
- 1; i
>= 0; i
-- )
3044 this.items
[i
].item
.removeData("sortable-item");
3049 _setOption: function(key
, value
){
3050 if ( key
=== "disabled" ) {
3051 this.options
[ key
] = value
;
3054 [ value
? "addClass" : "removeClass"]( "ui-sortable-disabled" );
3056 // Don't call widget base _setOption for disable as it adds ui-state-disabled class
3057 $.Widget
.prototype._setOption
.apply(this, arguments
);
3061 _mouseCapture: function(event
, overrideHandle
) {
3063 if (this.reverting
) {
3067 if(this.options
.disabled
|| this.options
.type
== 'static') return false;
3069 //We have to refresh the items data once first
3070 this._refreshItems(event
);
3072 //Find out if the clicked node (or one of its parents) is a actual item in this.items
3073 var currentItem
= null, self
= this, nodes
= $(event
.target
).parents().each(function() {
3074 if($.data(this, 'sortable-item') == self
) {
3075 currentItem
= $(this);
3079 if($.data(event
.target
, 'sortable-item') == self
) currentItem
= $(event
.target
);
3081 if(!currentItem
) return false;
3082 if(this.options
.handle
&& !overrideHandle
) {
3083 var validHandle
= false;
3085 $(this.options
.handle
, currentItem
).find("*").andSelf().each(function() { if(this == event
.target
) validHandle
= true; });
3086 if(!validHandle
) return false;
3089 this.currentItem
= currentItem
;
3090 this._removeCurrentsFromItems();
3095 _mouseStart: function(event
, overrideHandle
, noActivation
) {
3097 var o
= this.options
, self
= this;
3098 this.currentContainer
= this;
3100 //We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture
3101 this.refreshPositions();
3103 //Create and append the visible helper
3104 this.helper
= this._createHelper(event
);
3106 //Cache the helper size
3107 this._cacheHelperProportions();
3110 * - Position generation -
3111 * This block generates everything position related - it's the core of draggables.
3114 //Cache the margins of the original element
3115 this._cacheMargins();
3117 //Get the next scrolling parent
3118 this.scrollParent
= this.helper
.scrollParent();
3120 //The element's absolute position on the page minus margins
3121 this.offset
= this.currentItem
.offset();
3123 top
: this.offset
.top
- this.margins
.top
,
3124 left
: this.offset
.left
- this.margins
.left
3127 // Only after we got the offset, we can change the helper's position to absolute
3128 // TODO: Still need to figure out a way to make relative sorting possible
3129 this.helper
.css("position", "absolute");
3130 this.cssPosition
= this.helper
.css("position");
3132 $.extend(this.offset
, {
3133 click
: { //Where the click happened, relative to the element
3134 left
: event
.pageX
- this.offset
.left
,
3135 top
: event
.pageY
- this.offset
.top
3137 parent
: this._getParentOffset(),
3138 relative
: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
3141 //Generate the original position
3142 this.originalPosition
= this._generatePosition(event
);
3143 this.originalPageX
= event
.pageX
;
3144 this.originalPageY
= event
.pageY
;
3146 //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
3147 (o
.cursorAt
&& this._adjustOffsetFromHelper(o
.cursorAt
));
3149 //Cache the former DOM position
3150 this.domPosition
= { prev
: this.currentItem
.prev()[0], parent
: this.currentItem
.parent()[0] };
3152 //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
3153 if(this.helper
[0] != this.currentItem
[0]) {
3154 this.currentItem
.hide();
3157 //Create the placeholder
3158 this._createPlaceholder();
3160 //Set a containment if given in the options
3162 this._setContainment();
3164 if(o
.cursor
) { // cursor option
3165 if ($('body').css("cursor")) this._storedCursor
= $('body').css("cursor");
3166 $('body').css("cursor", o
.cursor
);
3169 if(o
.opacity
) { // opacity option
3170 if (this.helper
.css("opacity")) this._storedOpacity
= this.helper
.css("opacity");
3171 this.helper
.css("opacity", o
.opacity
);
3174 if(o
.zIndex
) { // zIndex option
3175 if (this.helper
.css("zIndex")) this._storedZIndex
= this.helper
.css("zIndex");
3176 this.helper
.css("zIndex", o
.zIndex
);
3180 if(this.scrollParent
[0] != document
&& this.scrollParent
[0].tagName
!= 'HTML')
3181 this.overflowOffset
= this.scrollParent
.offset();
3184 this._trigger("start", event
, this._uiHash());
3186 //Recache the helper size
3187 if(!this._preserveHelperProportions
)
3188 this._cacheHelperProportions();
3191 //Post 'activate' events to possible containers
3193 for (var i
= this.containers
.length
- 1; i
>= 0; i
--) { this.containers
[i
]._trigger("activate", event
, self
._uiHash(this)); }
3196 //Prepare possible droppables
3198 $.ui
.ddmanager
.current
= this;
3200 if ($.ui
.ddmanager
&& !o
.dropBehaviour
)
3201 $.ui
.ddmanager
.prepareOffsets(this, event
);
3203 this.dragging
= true;
3205 this.helper
.addClass("ui-sortable-helper");
3206 this._mouseDrag(event
); //Execute the drag once - this causes the helper not to be visible before getting its correct position
3211 _mouseDrag: function(event
) {
3213 //Compute the helpers position
3214 this.position
= this._generatePosition(event
);
3215 this.positionAbs
= this._convertPositionTo("absolute");
3217 if (!this.lastPositionAbs
) {
3218 this.lastPositionAbs
= this.positionAbs
;
3222 if(this.options
.scroll
) {
3223 var o
= this.options
, scrolled
= false;
3224 if(this.scrollParent
[0] != document
&& this.scrollParent
[0].tagName
!= 'HTML') {
3226 if((this.overflowOffset
.top
+ this.scrollParent
[0].offsetHeight
) - event
.pageY
< o
.scrollSensitivity
)
3227 this.scrollParent
[0].scrollTop
= scrolled
= this.scrollParent
[0].scrollTop
+ o
.scrollSpeed
;
3228 else if(event
.pageY
- this.overflowOffset
.top
< o
.scrollSensitivity
)
3229 this.scrollParent
[0].scrollTop
= scrolled
= this.scrollParent
[0].scrollTop
- o
.scrollSpeed
;
3231 if((this.overflowOffset
.left
+ this.scrollParent
[0].offsetWidth
) - event
.pageX
< o
.scrollSensitivity
)
3232 this.scrollParent
[0].scrollLeft
= scrolled
= this.scrollParent
[0].scrollLeft
+ o
.scrollSpeed
;
3233 else if(event
.pageX
- this.overflowOffset
.left
< o
.scrollSensitivity
)
3234 this.scrollParent
[0].scrollLeft
= scrolled
= this.scrollParent
[0].scrollLeft
- o
.scrollSpeed
;
3238 if(event
.pageY
- $(document
).scrollTop() < o
.scrollSensitivity
)
3239 scrolled
= $(document
).scrollTop($(document
).scrollTop() - o
.scrollSpeed
);
3240 else if($(window
).height() - (event
.pageY
- $(document
).scrollTop()) < o
.scrollSensitivity
)
3241 scrolled
= $(document
).scrollTop($(document
).scrollTop() + o
.scrollSpeed
);
3243 if(event
.pageX
- $(document
).scrollLeft() < o
.scrollSensitivity
)
3244 scrolled
= $(document
).scrollLeft($(document
).scrollLeft() - o
.scrollSpeed
);
3245 else if($(window
).width() - (event
.pageX
- $(document
).scrollLeft()) < o
.scrollSensitivity
)
3246 scrolled
= $(document
).scrollLeft($(document
).scrollLeft() + o
.scrollSpeed
);
3250 if(scrolled
!== false && $.ui
.ddmanager
&& !o
.dropBehaviour
)
3251 $.ui
.ddmanager
.prepareOffsets(this, event
);
3254 //Regenerate the absolute position used for position checks
3255 this.positionAbs
= this._convertPositionTo("absolute");
3257 //Set the helper position
3258 if(!this.options
.axis
|| this.options
.axis
!= "y") this.helper
[0].style
.left
= this.position
.left
+'px';
3259 if(!this.options
.axis
|| this.options
.axis
!= "x") this.helper
[0].style
.top
= this.position
.top
+'px';
3262 for (var i
= this.items
.length
- 1; i
>= 0; i
--) {
3264 //Cache variables and intersection, continue if no intersection
3265 var item
= this.items
[i
], itemElement
= item
.item
[0], intersection
= this._intersectsWithPointer(item
);
3266 if (!intersection
) continue;
3268 if(itemElement
!= this.currentItem
[0] //cannot intersect with itself
3269 && this.placeholder
[intersection
== 1 ? "next" : "prev"]()[0] != itemElement
//no useless actions that have been done before
3270 && !$.ui
.contains(this.placeholder
[0], itemElement
) //no action if the item moved is the parent of the item checked
3271 && (this.options
.type
== 'semi-dynamic' ? !$.ui
.contains(this.element
[0], itemElement
) : true)
3272 //&& itemElement.parentNode == this.placeholder[0].parentNode // only rearrange items within the same container
3275 this.direction
= intersection
== 1 ? "down" : "up";
3277 if (this.options
.tolerance
== "pointer" || this._intersectsWithSides(item
)) {
3278 this._rearrange(event
, item
);
3283 this._trigger("change", event
, this._uiHash());
3288 //Post events to containers
3289 this._contactContainers(event
);
3291 //Interconnect with droppables
3292 if($.ui
.ddmanager
) $.ui
.ddmanager
.drag(this, event
);
3295 this._trigger('sort', event
, this._uiHash());
3297 this.lastPositionAbs
= this.positionAbs
;
3302 _mouseStop: function(event
, noPropagation
) {
3306 //If we are using droppables, inform the manager about the drop
3307 if ($.ui
.ddmanager
&& !this.options
.dropBehaviour
)
3308 $.ui
.ddmanager
.drop(this, event
);
3310 if(this.options
.revert
) {
3312 var cur
= self
.placeholder
.offset();
3314 self
.reverting
= true;
3316 $(this.helper
).animate({
3317 left
: cur
.left
- this.offset
.parent
.left
- self
.margins
.left
+ (this.offsetParent
[0] == document
.body
? 0 : this.offsetParent
[0].scrollLeft
),
3318 top
: cur
.top
- this.offset
.parent
.top
- self
.margins
.top
+ (this.offsetParent
[0] == document
.body
? 0 : this.offsetParent
[0].scrollTop
)
3319 }, parseInt(this.options
.revert
, 10) || 500, function() {
3323 this._clear(event
, noPropagation
);
3330 cancel: function() {
3336 this._mouseUp({ target
: null });
3338 if(this.options
.helper
== "original")
3339 this.currentItem
.css(this._storedCSS
).removeClass("ui-sortable-helper");
3341 this.currentItem
.show();
3343 //Post deactivating events to containers
3344 for (var i
= this.containers
.length
- 1; i
>= 0; i
--){
3345 this.containers
[i
]._trigger("deactivate", null, self
._uiHash(this));
3346 if(this.containers
[i
].containerCache
.over
) {
3347 this.containers
[i
]._trigger("out", null, self
._uiHash(this));
3348 this.containers
[i
].containerCache
.over
= 0;
3354 if (this.placeholder
) {
3355 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
3356 if(this.placeholder
[0].parentNode
) this.placeholder
[0].parentNode
.removeChild(this.placeholder
[0]);
3357 if(this.options
.helper
!= "original" && this.helper
&& this.helper
[0].parentNode
) this.helper
.remove();
3366 if(this.domPosition
.prev
) {
3367 $(this.domPosition
.prev
).after(this.currentItem
);
3369 $(this.domPosition
.parent
).prepend(this.currentItem
);
3377 serialize: function(o
) {
3379 var items
= this._getItemsAsjQuery(o
&& o
.connected
);
3380 var str
= []; o
= o
|| {};
3382 $(items
).each(function() {
3383 var res
= ($(o
.item
|| this).attr(o
.attribute
|| 'id') || '').match(o
.expression
|| (/(.+)[-=_](.+)/));
3384 if(res
) str
.push((o
.key
|| res
[1]+'[]')+'='+(o
.key
&& o
.expression
? res
[1] : res
[2]));
3387 if(!str
.length
&& o
.key
) {
3388 str
.push(o
.key
+ '=');
3391 return str
.join('&');
3395 toArray: function(o
) {
3397 var items
= this._getItemsAsjQuery(o
&& o
.connected
);
3398 var ret
= []; o
= o
|| {};
3400 items
.each(function() { ret
.push($(o
.item
|| this).attr(o
.attribute
|| 'id') || ''); });
3405 /* Be careful with the following core functions */
3406 _intersectsWith: function(item
) {
3408 var x1
= this.positionAbs
.left
,
3409 x2
= x1
+ this.helperProportions
.width
,
3410 y1
= this.positionAbs
.top
,
3411 y2
= y1
+ this.helperProportions
.height
;
3416 b
= t
+ item
.height
;
3418 var dyClick
= this.offset
.click
.top
,
3419 dxClick
= this.offset
.click
.left
;
3421 var isOverElement
= (y1
+ dyClick
) > t
&& (y1
+ dyClick
) < b
&& (x1
+ dxClick
) > l
&& (x1
+ dxClick
) < r
;
3423 if( this.options
.tolerance
== "pointer"
3424 || this.options
.forcePointerForContainers
3425 || (this.options
.tolerance
!= "pointer" && this.helperProportions
[this.floating
? 'width' : 'height'] > item
[this.floating
? 'width' : 'height'])
3427 return isOverElement
;
3430 return (l
< x1
+ (this.helperProportions
.width
/ 2) // Right Half
3431 && x2
- (this.helperProportions
.width
/ 2) < r
// Left Half
3432 && t
< y1
+ (this.helperProportions
.height
/ 2) // Bottom Half
3433 && y2
- (this.helperProportions
.height
/ 2) < b
); // Top Half
3438 _intersectsWithPointer: function(item
) {
3440 var isOverElementHeight
= $.ui
.isOverAxis(this.positionAbs
.top
+ this.offset
.click
.top
, item
.top
, item
.height
),
3441 isOverElementWidth
= $.ui
.isOverAxis(this.positionAbs
.left
+ this.offset
.click
.left
, item
.left
, item
.width
),
3442 isOverElement
= isOverElementHeight
&& isOverElementWidth
,
3443 verticalDirection
= this._getDragVerticalDirection(),
3444 horizontalDirection
= this._getDragHorizontalDirection();
3449 return this.floating
?
3450 ( ((horizontalDirection
&& horizontalDirection
== "right") || verticalDirection
== "down") ? 2 : 1 )
3451 : ( verticalDirection
&& (verticalDirection
== "down" ? 2 : 1) );
3455 _intersectsWithSides: function(item
) {
3457 var isOverBottomHalf
= $.ui
.isOverAxis(this.positionAbs
.top
+ this.offset
.click
.top
, item
.top
+ (item
.height
/2), item
.height
),
3458 isOverRightHalf
= $.ui
.isOverAxis(this.positionAbs
.left
+ this.offset
.click
.left
, item
.left
+ (item
.width
/2), item
.width
),
3459 verticalDirection
= this._getDragVerticalDirection(),
3460 horizontalDirection
= this._getDragHorizontalDirection();
3462 if (this.floating
&& horizontalDirection
) {
3463 return ((horizontalDirection
== "right" && isOverRightHalf
) || (horizontalDirection
== "left" && !isOverRightHalf
));
3465 return verticalDirection
&& ((verticalDirection
== "down" && isOverBottomHalf
) || (verticalDirection
== "up" && !isOverBottomHalf
));
3470 _getDragVerticalDirection: function() {
3471 var delta
= this.positionAbs
.top
- this.lastPositionAbs
.top
;
3472 return delta
!= 0 && (delta
> 0 ? "down" : "up");
3475 _getDragHorizontalDirection: function() {
3476 var delta
= this.positionAbs
.left
- this.lastPositionAbs
.left
;
3477 return delta
!= 0 && (delta
> 0 ? "right" : "left");
3480 refresh: function(event
) {
3481 this._refreshItems(event
);
3482 this.refreshPositions();
3486 _connectWith: function() {
3487 var options
= this.options
;
3488 return options
.connectWith
.constructor == String
3489 ? [options
.connectWith
]
3490 : options
.connectWith
;
3493 _getItemsAsjQuery: function(connected
) {
3498 var connectWith
= this._connectWith();
3500 if(connectWith
&& connected
) {
3501 for (var i
= connectWith
.length
- 1; i
>= 0; i
--){
3502 var cur
= $(connectWith
[i
]);
3503 for (var j
= cur
.length
- 1; j
>= 0; j
--){
3504 var inst
= $.data(cur
[j
], 'sortable');
3505 if(inst
&& inst
!= this && !inst
.options
.disabled
) {
3506 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
]);
3512 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]);
3514 for (var i
= queries
.length
- 1; i
>= 0; i
--){
3515 queries
[i
][0].each(function() {
3524 _removeCurrentsFromItems: function() {
3526 var list
= this.currentItem
.find(":data(sortable-item)");
3528 for (var i
=0; i
< this.items
.length
; i
++) {
3530 for (var j
=0; j
< list
.length
; j
++) {
3531 if(list
[j
] == this.items
[i
].item
[0])
3532 this.items
.splice(i
,1);
3539 _refreshItems: function(event
) {
3542 this.containers
= [this];
3543 var items
= this.items
;
3545 var queries
= [[$.isFunction(this.options
.items
) ? this.options
.items
.call(this.element
[0], event
, { item
: this.currentItem
}) : $(this.options
.items
, this.element
), this]];
3546 var connectWith
= this._connectWith();
3549 for (var i
= connectWith
.length
- 1; i
>= 0; i
--){
3550 var cur
= $(connectWith
[i
]);
3551 for (var j
= cur
.length
- 1; j
>= 0; j
--){
3552 var inst
= $.data(cur
[j
], 'sortable');
3553 if(inst
&& inst
!= this && !inst
.options
.disabled
) {
3554 queries
.push([$.isFunction(inst
.options
.items
) ? inst
.options
.items
.call(inst
.element
[0], event
, { item
: this.currentItem
}) : $(inst
.options
.items
, inst
.element
), inst
]);
3555 this.containers
.push(inst
);
3561 for (var i
= queries
.length
- 1; i
>= 0; i
--) {
3562 var targetData
= queries
[i
][1];
3563 var _queries
= queries
[i
][0];
3565 for (var j
=0, queriesLength
= _queries
.length
; j
< queriesLength
; j
++) {
3566 var item
= $(_queries
[j
]);
3568 item
.data('sortable-item', targetData
); // Data for target checking (mouse manager)
3572 instance
: targetData
,
3573 width
: 0, height
: 0,
3581 refreshPositions: function(fast
) {
3583 //This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change
3584 if(this.offsetParent
&& this.helper
) {
3585 this.offset
.parent
= this._getParentOffset();
3588 for (var i
= this.items
.length
- 1; i
>= 0; i
--){
3589 var item
= this.items
[i
];
3591 //We ignore calculating positions of all connected containers when we're not over them
3592 if(item
.instance
!= this.currentContainer
&& this.currentContainer
&& item
.item
[0] != this.currentItem
[0])
3595 var t
= this.options
.toleranceElement
? $(this.options
.toleranceElement
, item
.item
) : item
.item
;
3598 item
.width
= t
.outerWidth();
3599 item
.height
= t
.outerHeight();
3607 if(this.options
.custom
&& this.options
.custom
.refreshContainers
) {
3608 this.options
.custom
.refreshContainers
.call(this);
3610 for (var i
= this.containers
.length
- 1; i
>= 0; i
--){
3611 var p
= this.containers
[i
].element
.offset();
3612 this.containers
[i
].containerCache
.left
= p
.left
;
3613 this.containers
[i
].containerCache
.top
= p
.top
;
3614 this.containers
[i
].containerCache
.width
= this.containers
[i
].element
.outerWidth();
3615 this.containers
[i
].containerCache
.height
= this.containers
[i
].element
.outerHeight();
3622 _createPlaceholder: function(that
) {
3624 var self
= that
|| this, o
= self
.options
;
3626 if(!o
.placeholder
|| o
.placeholder
.constructor == String
) {
3627 var className
= o
.placeholder
;
3629 element: function() {
3631 var el
= $(document
.createElement(self
.currentItem
[0].nodeName
))
3632 .addClass(className
|| self
.currentItem
[0].className
+" ui-sortable-placeholder")
3633 .removeClass("ui-sortable-helper")[0];
3636 el
.style
.visibility
= "hidden";
3640 update: function(container
, p
) {
3642 // 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that
3643 // 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified
3644 if(className
&& !o
.forcePlaceholderSize
) return;
3646 //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
3647 if(!p
.height()) { p
.height(self
.currentItem
.innerHeight() - parseInt(self
.currentItem
.css('paddingTop')||0, 10) - parseInt(self
.currentItem
.css('paddingBottom')||0, 10)); };
3648 if(!p
.width()) { p
.width(self
.currentItem
.innerWidth() - parseInt(self
.currentItem
.css('paddingLeft')||0, 10) - parseInt(self
.currentItem
.css('paddingRight')||0, 10)); };
3653 //Create the placeholder
3654 self
.placeholder
= $(o
.placeholder
.element
.call(self
.element
, self
.currentItem
));
3656 //Append it after the actual current item
3657 self
.currentItem
.after(self
.placeholder
);
3659 //Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
3660 o
.placeholder
.update(self
, self
.placeholder
);
3664 _contactContainers: function(event
) {
3666 // get innermost container that intersects with item
3667 var innermostContainer
= null, innermostIndex
= null;
3670 for (var i
= this.containers
.length
- 1; i
>= 0; i
--){
3672 // never consider a container that's located within the item itself
3673 if($.ui
.contains(this.currentItem
[0], this.containers
[i
].element
[0]))
3676 if(this._intersectsWith(this.containers
[i
].containerCache
)) {
3678 // if we've already found a container and it's more "inner" than this, then continue
3679 if(innermostContainer
&& $.ui
.contains(this.containers
[i
].element
[0], innermostContainer
.element
[0]))
3682 innermostContainer
= this.containers
[i
];
3686 // container doesn't intersect. trigger "out" event if necessary
3687 if(this.containers
[i
].containerCache
.over
) {
3688 this.containers
[i
]._trigger("out", event
, this._uiHash(this));
3689 this.containers
[i
].containerCache
.over
= 0;
3695 // if no intersecting containers found, return
3696 if(!innermostContainer
) return;
3698 // move the item into the container if it's not there already
3699 if(this.containers
.length
=== 1) {
3700 this.containers
[innermostIndex
]._trigger("over", event
, this._uiHash(this));
3701 this.containers
[innermostIndex
].containerCache
.over
= 1;
3702 } else if(this.currentContainer
!= this.containers
[innermostIndex
]) {
3704 //When entering a new container, we will find the item with the least distance and append our item near it
3705 var dist
= 10000; var itemWithLeastDistance
= null; var base
= this.positionAbs
[this.containers
[innermostIndex
].floating
? 'left' : 'top'];
3706 for (var j
= this.items
.length
- 1; j
>= 0; j
--) {
3707 if(!$.ui
.contains(this.containers
[innermostIndex
].element
[0], this.items
[j
].item
[0])) continue;
3708 var cur
= this.items
[j
][this.containers
[innermostIndex
].floating
? 'left' : 'top'];
3709 if(Math
.abs(cur
- base
) < dist
) {
3710 dist
= Math
.abs(cur
- base
); itemWithLeastDistance
= this.items
[j
];
3714 if(!itemWithLeastDistance
&& !this.options
.dropOnEmpty
) //Check if dropOnEmpty is enabled
3717 this.currentContainer
= this.containers
[innermostIndex
];
3718 itemWithLeastDistance
? this._rearrange(event
, itemWithLeastDistance
, null, true) : this._rearrange(event
, null, this.containers
[innermostIndex
].element
, true);
3719 this._trigger("change", event
, this._uiHash());
3720 this.containers
[innermostIndex
]._trigger("change", event
, this._uiHash(this));
3722 //Update the placeholder
3723 this.options
.placeholder
.update(this.currentContainer
, this.placeholder
);
3725 this.containers
[innermostIndex
]._trigger("over", event
, this._uiHash(this));
3726 this.containers
[innermostIndex
].containerCache
.over
= 1;
3732 _createHelper: function(event
) {
3734 var o
= this.options
;
3735 var helper
= $.isFunction(o
.helper
) ? $(o
.helper
.apply(this.element
[0], [event
, this.currentItem
])) : (o
.helper
== 'clone' ? this.currentItem
.clone() : this.currentItem
);
3737 if(!helper
.parents('body').length
) //Add the helper to the DOM if that didn't happen already
3738 $(o
.appendTo
!= 'parent' ? o
.appendTo
: this.currentItem
[0].parentNode
)[0].appendChild(helper
[0]);
3740 if(helper
[0] == this.currentItem
[0])
3741 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") };
3743 if(helper
[0].style
.width
== '' || o
.forceHelperSize
) helper
.width(this.currentItem
.width());
3744 if(helper
[0].style
.height
== '' || o
.forceHelperSize
) helper
.height(this.currentItem
.height());
3750 _adjustOffsetFromHelper: function(obj
) {
3751 if (typeof obj
== 'string') {
3752 obj
= obj
.split(' ');
3754 if ($.isArray(obj
)) {
3755 obj
= {left
: +obj
[0], top
: +obj
[1] || 0};
3757 if ('left' in obj
) {
3758 this.offset
.click
.left
= obj
.left
+ this.margins
.left
;
3760 if ('right' in obj
) {
3761 this.offset
.click
.left
= this.helperProportions
.width
- obj
.right
+ this.margins
.left
;
3764 this.offset
.click
.top
= obj
.top
+ this.margins
.top
;
3766 if ('bottom' in obj
) {
3767 this.offset
.click
.top
= this.helperProportions
.height
- obj
.bottom
+ this.margins
.top
;
3771 _getParentOffset: function() {
3774 //Get the offsetParent and cache its position
3775 this.offsetParent
= this.helper
.offsetParent();
3776 var po
= this.offsetParent
.offset();
3778 // This is a special case where we need to modify a offset calculated on start, since the following happened:
3779 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
3780 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
3781 // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
3782 if(this.cssPosition
== 'absolute' && this.scrollParent
[0] != document
&& $.ui
.contains(this.scrollParent
[0], this.offsetParent
[0])) {
3783 po
.left
+= this.scrollParent
.scrollLeft();
3784 po
.top
+= this.scrollParent
.scrollTop();
3787 if((this.offsetParent
[0] == document
.body
) //This needs to be actually done for all browsers, since pageX/pageY includes this information
3788 || (this.offsetParent
[0].tagName
&& this.offsetParent
[0].tagName
.toLowerCase() == 'html' && $.browser
.msie
)) //Ugly IE fix
3789 po
= { top
: 0, left
: 0 };
3792 top
: po
.top
+ (parseInt(this.offsetParent
.css("borderTopWidth"),10) || 0),
3793 left
: po
.left
+ (parseInt(this.offsetParent
.css("borderLeftWidth"),10) || 0)
3798 _getRelativeOffset: function() {
3800 if(this.cssPosition
== "relative") {
3801 var p
= this.currentItem
.position();
3803 top
: p
.top
- (parseInt(this.helper
.css("top"),10) || 0) + this.scrollParent
.scrollTop(),
3804 left
: p
.left
- (parseInt(this.helper
.css("left"),10) || 0) + this.scrollParent
.scrollLeft()
3807 return { top
: 0, left
: 0 };
3812 _cacheMargins: function() {
3814 left
: (parseInt(this.currentItem
.css("marginLeft"),10) || 0),
3815 top
: (parseInt(this.currentItem
.css("marginTop"),10) || 0)
3819 _cacheHelperProportions: function() {
3820 this.helperProportions
= {
3821 width
: this.helper
.outerWidth(),
3822 height
: this.helper
.outerHeight()
3826 _setContainment: function() {
3828 var o
= this.options
;
3829 if(o
.containment
== 'parent') o
.containment
= this.helper
[0].parentNode
;
3830 if(o
.containment
== 'document' || o
.containment
== 'window') this.containment
= [
3831 0 - this.offset
.relative
.left
- this.offset
.parent
.left
,
3832 0 - this.offset
.relative
.top
- this.offset
.parent
.top
,
3833 $(o
.containment
== 'document' ? document
: window
).width() - this.helperProportions
.width
- this.margins
.left
,
3834 ($(o
.containment
== 'document' ? document
: window
).height() || document
.body
.parentNode
.scrollHeight
) - this.helperProportions
.height
- this.margins
.top
3837 if(!(/^(document|window|parent)$/).test(o
.containment
)) {
3838 var ce
= $(o
.containment
)[0];
3839 var co
= $(o
.containment
).offset();
3840 var over
= ($(ce
).css("overflow") != 'hidden');
3842 this.containment
= [
3843 co
.left
+ (parseInt($(ce
).css("borderLeftWidth"),10) || 0) + (parseInt($(ce
).css("paddingLeft"),10) || 0) - this.margins
.left
,
3844 co
.top
+ (parseInt($(ce
).css("borderTopWidth"),10) || 0) + (parseInt($(ce
).css("paddingTop"),10) || 0) - this.margins
.top
,
3845 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
,
3846 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
3852 _convertPositionTo: function(d
, pos
) {
3854 if(!pos
) pos
= this.position
;
3855 var mod
= d
== "absolute" ? 1 : -1;
3856 var o
= this.options
, scroll
= this.cssPosition
== 'absolute' && !(this.scrollParent
[0] != document
&& $.ui
.contains(this.scrollParent
[0], this.offsetParent
[0])) ? this.offsetParent
: this.scrollParent
, scrollIsRootNode
= (/(html|body)/i).test(scroll
[0].tagName
);
3860 pos
.top
// The absolute mouse position
3861 + this.offset
.relative
.top
* mod
// Only for relative positioned nodes: Relative offset from element to offset parent
3862 + this.offset
.parent
.top
* mod
// The offsetParent's offset without borders (offset + border)
3863 - ($.browser
.safari
&& this.cssPosition
== 'fixed' ? 0 : ( this.cssPosition
== 'fixed' ? -this.scrollParent
.scrollTop() : ( scrollIsRootNode
? 0 : scroll
.scrollTop() ) ) * mod
)
3866 pos
.left
// The absolute mouse position
3867 + this.offset
.relative
.left
* mod
// Only for relative positioned nodes: Relative offset from element to offset parent
3868 + this.offset
.parent
.left
* mod
// The offsetParent's offset without borders (offset + border)
3869 - ($.browser
.safari
&& this.cssPosition
== 'fixed' ? 0 : ( this.cssPosition
== 'fixed' ? -this.scrollParent
.scrollLeft() : scrollIsRootNode
? 0 : scroll
.scrollLeft() ) * mod
)
3875 _generatePosition: function(event
) {
3877 var o
= this.options
, scroll
= this.cssPosition
== 'absolute' && !(this.scrollParent
[0] != document
&& $.ui
.contains(this.scrollParent
[0], this.offsetParent
[0])) ? this.offsetParent
: this.scrollParent
, scrollIsRootNode
= (/(html|body)/i).test(scroll
[0].tagName
);
3879 // This is another very weird special case that only happens for relative elements:
3880 // 1. If the css position is relative
3881 // 2. and the scroll parent is the document or similar to the offset parent
3882 // we have to refresh the relative offset during the scroll so there are no jumps
3883 if(this.cssPosition
== 'relative' && !(this.scrollParent
[0] != document
&& this.scrollParent
[0] != this.offsetParent
[0])) {
3884 this.offset
.relative
= this._getRelativeOffset();
3887 var pageX
= event
.pageX
;
3888 var pageY
= event
.pageY
;
3891 * - Position constraining -
3892 * Constrain the position to a mix of grid, containment.
3895 if(this.originalPosition
) { //If we are not dragging yet, we won't check for options
3897 if(this.containment
) {
3898 if(event
.pageX
- this.offset
.click
.left
< this.containment
[0]) pageX
= this.containment
[0] + this.offset
.click
.left
;
3899 if(event
.pageY
- this.offset
.click
.top
< this.containment
[1]) pageY
= this.containment
[1] + this.offset
.click
.top
;
3900 if(event
.pageX
- this.offset
.click
.left
> this.containment
[2]) pageX
= this.containment
[2] + this.offset
.click
.left
;
3901 if(event
.pageY
- this.offset
.click
.top
> this.containment
[3]) pageY
= this.containment
[3] + this.offset
.click
.top
;
3905 var top
= this.originalPageY
+ Math
.round((pageY
- this.originalPageY
) / o
.grid
[1]) * o
.grid
[1];
3906 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
;
3908 var left
= this.originalPageX
+ Math
.round((pageX
- this.originalPageX
) / o
.grid
[0]) * o
.grid
[0];
3909 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
;
3916 pageY
// The absolute mouse position
3917 - this.offset
.click
.top
// Click offset (relative to the element)
3918 - this.offset
.relative
.top
// Only for relative positioned nodes: Relative offset from element to offset parent
3919 - this.offset
.parent
.top
// The offsetParent's offset without borders (offset + border)
3920 + ($.browser
.safari
&& this.cssPosition
== 'fixed' ? 0 : ( this.cssPosition
== 'fixed' ? -this.scrollParent
.scrollTop() : ( scrollIsRootNode
? 0 : scroll
.scrollTop() ) ))
3923 pageX
// The absolute mouse position
3924 - this.offset
.click
.left
// Click offset (relative to the element)
3925 - this.offset
.relative
.left
// Only for relative positioned nodes: Relative offset from element to offset parent
3926 - this.offset
.parent
.left
// The offsetParent's offset without borders (offset + border)
3927 + ($.browser
.safari
&& this.cssPosition
== 'fixed' ? 0 : ( this.cssPosition
== 'fixed' ? -this.scrollParent
.scrollLeft() : scrollIsRootNode
? 0 : scroll
.scrollLeft() ))
3933 _rearrange: function(event
, i
, a
, hardRefresh
) {
3935 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
));
3937 //Various things done here to improve the performance:
3938 // 1. we create a setTimeout, that calls refreshPositions
3939 // 2. on the instance, we have a counter variable, that get's higher after every append
3940 // 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same
3941 // 4. this lets only the last addition to the timeout stack through
3942 this.counter
= this.counter
? ++this.counter
: 1;
3943 var self
= this, counter
= this.counter
;
3945 window
.setTimeout(function() {
3946 if(counter
== self
.counter
) self
.refreshPositions(!hardRefresh
); //Precompute after each DOM insertion, NOT on mousemove
3951 _clear: function(event
, noPropagation
) {
3953 this.reverting
= false;
3954 // We delay all events that have to be triggered to after the point where the placeholder has been removed and
3955 // everything else normalized again
3956 var delayedTriggers
= [], self
= this;
3958 // We first have to update the dom position of the actual currentItem
3959 // Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088)
3960 if(!this._noFinalSort
&& this.currentItem
.parent().length
) this.placeholder
.before(this.currentItem
);
3961 this._noFinalSort
= null;
3963 if(this.helper
[0] == this.currentItem
[0]) {
3964 for(var i
in this._storedCSS
) {
3965 if(this._storedCSS
[i
] == 'auto' || this._storedCSS
[i
] == 'static') this._storedCSS
[i
] = '';
3967 this.currentItem
.css(this._storedCSS
).removeClass("ui-sortable-helper");
3969 this.currentItem
.show();
3972 if(this.fromOutside
&& !noPropagation
) delayedTriggers
.push(function(event
) { this._trigger("receive", event
, this._uiHash(this.fromOutside
)); });
3973 if((this.fromOutside
|| this.domPosition
.prev
!= this.currentItem
.prev().not(".ui-sortable-helper")[0] || this.domPosition
.parent
!= this.currentItem
.parent()[0]) && !noPropagation
) delayedTriggers
.push(function(event
) { this._trigger("update", event
, this._uiHash()); }); //Trigger update callback if the DOM position has changed
3974 if(!$.ui
.contains(this.element
[0], this.currentItem
[0])) { //Node was moved out of the current element
3975 if(!noPropagation
) delayedTriggers
.push(function(event
) { this._trigger("remove", event
, this._uiHash()); });
3976 for (var i
= this.containers
.length
- 1; i
>= 0; i
--){
3977 if($.ui
.contains(this.containers
[i
].element
[0], this.currentItem
[0]) && !noPropagation
) {
3978 delayedTriggers
.push((function(c
) { return function(event
) { c
._trigger("receive", event
, this._uiHash(this)); }; }).call(this, this.containers
[i
]));
3979 delayedTriggers
.push((function(c
) { return function(event
) { c
._trigger("update", event
, this._uiHash(this)); }; }).call(this, this.containers
[i
]));
3984 //Post events to containers
3985 for (var i
= this.containers
.length
- 1; i
>= 0; i
--){
3986 if(!noPropagation
) delayedTriggers
.push((function(c
) { return function(event
) { c
._trigger("deactivate", event
, this._uiHash(this)); }; }).call(this, this.containers
[i
]));
3987 if(this.containers
[i
].containerCache
.over
) {
3988 delayedTriggers
.push((function(c
) { return function(event
) { c
._trigger("out", event
, this._uiHash(this)); }; }).call(this, this.containers
[i
]));
3989 this.containers
[i
].containerCache
.over
= 0;
3993 //Do what was originally in plugins
3994 if(this._storedCursor
) $('body').css("cursor", this._storedCursor
); //Reset cursor
3995 if(this._storedOpacity
) this.helper
.css("opacity", this._storedOpacity
); //Reset opacity
3996 if(this._storedZIndex
) this.helper
.css("zIndex", this._storedZIndex
== 'auto' ? '' : this._storedZIndex
); //Reset z-index
3998 this.dragging
= false;
3999 if(this.cancelHelperRemoval
) {
4000 if(!noPropagation
) {
4001 this._trigger("beforeStop", event
, this._uiHash());
4002 for (var i
=0; i
< delayedTriggers
.length
; i
++) { delayedTriggers
[i
].call(this, event
); }; //Trigger all delayed events
4003 this._trigger("stop", event
, this._uiHash());
4008 if(!noPropagation
) this._trigger("beforeStop", event
, this._uiHash());
4010 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
4011 this.placeholder
[0].parentNode
.removeChild(this.placeholder
[0]);
4013 if(this.helper
[0] != this.currentItem
[0]) this.helper
.remove(); this.helper
= null;
4015 if(!noPropagation
) {
4016 for (var i
=0; i
< delayedTriggers
.length
; i
++) { delayedTriggers
[i
].call(this, event
); }; //Trigger all delayed events
4017 this._trigger("stop", event
, this._uiHash());
4020 this.fromOutside
= false;
4025 _trigger: function() {
4026 if ($.Widget
.prototype._trigger
.apply(this, arguments
) === false) {
4031 _uiHash: function(inst
) {
4032 var self
= inst
|| this;
4034 helper
: self
.helper
,
4035 placeholder
: self
.placeholder
|| $([]),
4036 position
: self
.position
,
4037 originalPosition
: self
.originalPosition
,
4038 offset
: self
.positionAbs
,
4039 item
: self
.currentItem
,
4040 sender
: inst
? inst
.element
: null
4046 $.extend($.ui
.sortable
, {
4052 * jQuery UI Effects 1.8.16
4054 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
4055 * Dual licensed under the MIT or GPL Version 2 licenses.
4056 * http://jquery.org/license
4058 * http://docs.jquery.com/UI/Effects/
4060 ;jQuery
.effects
|| (function($, undefined) {
4066 /******************************************************************************/
4067 /****************************** COLOR ANIMATIONS ******************************/
4068 /******************************************************************************/
4070 // override the animation for color styles
4071 $.each(['backgroundColor', 'borderBottomColor', 'borderLeftColor',
4072 'borderRightColor', 'borderTopColor', 'borderColor', 'color', 'outlineColor'],
4074 $.fx
.step
[attr
] = function(fx
) {
4075 if (!fx
.colorInit
) {
4076 fx
.start
= getColor(fx
.elem
, attr
);
4077 fx
.end
= getRGB(fx
.end
);
4078 fx
.colorInit
= true;
4081 fx
.elem
.style
[attr
] = 'rgb(' +
4082 Math
.max(Math
.min(parseInt((fx
.pos
* (fx
.end
[0] - fx
.start
[0])) + fx
.start
[0], 10), 255), 0) + ',' +
4083 Math
.max(Math
.min(parseInt((fx
.pos
* (fx
.end
[1] - fx
.start
[1])) + fx
.start
[1], 10), 255), 0) + ',' +
4084 Math
.max(Math
.min(parseInt((fx
.pos
* (fx
.end
[2] - fx
.start
[2])) + fx
.start
[2], 10), 255), 0) + ')';
4088 // Color Conversion functions from highlightFade
4089 // By Blair Mitchelmore
4090 // http://jquery.offput.ca/highlightFade/
4092 // Parse strings looking for color tuples [255,255,255]
4093 function getRGB(color
) {
4096 // Check if we're already dealing with an array of colors
4097 if ( color
&& color
.constructor == Array
&& color
.length
== 3 )
4100 // Look for rgb(num,num,num)
4101 if (result
= /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(color
))
4102 return [parseInt(result
[1],10), parseInt(result
[2],10), parseInt(result
[3],10)];
4104 // Look for rgb(num%,num%,num%)
4105 if (result
= /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(color
))
4106 return [parseFloat(result
[1])*2.55, parseFloat(result
[2])*2.55, parseFloat(result
[3])*2.55];
4109 if (result
= /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(color
))
4110 return [parseInt(result
[1],16), parseInt(result
[2],16), parseInt(result
[3],16)];
4113 if (result
= /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(color
))
4114 return [parseInt(result
[1]+result
[1],16), parseInt(result
[2]+result
[2],16), parseInt(result
[3]+result
[3],16)];
4116 // Look for rgba(0, 0, 0, 0) == transparent in Safari 3
4117 if (result
= /rgba\(0, 0, 0, 0\)/.exec(color
))
4118 return colors
['transparent'];
4120 // Otherwise, we're most likely dealing with a named color
4121 return colors
[$.trim(color
).toLowerCase()];
4124 function getColor(elem
, attr
) {
4128 color
= $.curCSS(elem
, attr
);
4130 // Keep going until we find an element that has color, or we hit the body
4131 if ( color
!= '' && color
!= 'transparent' || $.nodeName(elem
, "body") )
4134 attr
= "backgroundColor";
4135 } while ( elem
= elem
.parentNode
);
4137 return getRGB(color
);
4140 // Some named colors to work with
4141 // From Interface by Stefan Petre
4142 // http://interface.eyecon.ro/
4146 azure
:[240,255,255],
4147 beige
:[245,245,220],
4153 darkcyan
:[0,139,139],
4154 darkgrey
:[169,169,169],
4155 darkgreen
:[0,100,0],
4156 darkkhaki
:[189,183,107],
4157 darkmagenta
:[139,0,139],
4158 darkolivegreen
:[85,107,47],
4159 darkorange
:[255,140,0],
4160 darkorchid
:[153,50,204],
4162 darksalmon
:[233,150,122],
4163 darkviolet
:[148,0,211],
4164 fuchsia
:[255,0,255],
4168 khaki
:[240,230,140],
4169 lightblue
:[173,216,230],
4170 lightcyan
:[224,255,255],
4171 lightgreen
:[144,238,144],
4172 lightgrey
:[211,211,211],
4173 lightpink
:[255,182,193],
4174 lightyellow
:[255,255,224],
4176 magenta
:[255,0,255],
4185 silver
:[192,192,192],
4186 white
:[255,255,255],
4188 transparent
: [255,255,255]
4193 /******************************************************************************/
4194 /****************************** CLASS ANIMATIONS ******************************/
4195 /******************************************************************************/
4197 var classAnimationActions
= ['add', 'remove', 'toggle'],
4210 function getElementStyles() {
4211 var style
= document
.defaultView
4212 ? document
.defaultView
.getComputedStyle(this, null)
4213 : this.currentStyle
,
4218 // webkit enumerates style porperties
4219 if (style
&& style
.length
&& style
[0] && style
[style
[0]]) {
4220 var len
= style
.length
;
4223 if (typeof style
[key
] == 'string') {
4224 camelCase
= key
.replace(/\-(\w)/g, function(all
, letter
){
4225 return letter
.toUpperCase();
4227 newStyle
[camelCase
] = style
[key
];
4231 for (key
in style
) {
4232 if (typeof style
[key
] === 'string') {
4233 newStyle
[key
] = style
[key
];
4241 function filterStyles(styles
) {
4243 for (name
in styles
) {
4244 value
= styles
[name
];
4246 // ignore null and undefined values
4248 // ignore functions (when does this occur?)
4249 $.isFunction(value
) ||
4250 // shorthand styles that need to be expanded
4251 name
in shorthandStyles
||
4252 // ignore scrollbars (break in IE)
4253 (/scrollbar/).test(name
) ||
4255 // only colors or values that can be converted to numbers
4256 (!(/color/i).test(name
) && isNaN(parseFloat(value
)))
4258 delete styles
[name
];
4265 function styleDifference(oldStyle
, newStyle
) {
4266 var diff
= { _
: 0 }, // http://dev.jquery.com/ticket/5459
4269 for (name
in newStyle
) {
4270 if (oldStyle
[name
] != newStyle
[name
]) {
4271 diff
[name
] = newStyle
[name
];
4278 $.effects
.animateClass = function(value
, duration
, easing
, callback
) {
4279 if ($.isFunction(easing
)) {
4284 return this.queue(function() {
4286 originalStyleAttr
= that
.attr('style') || ' ',
4287 originalStyle
= filterStyles(getElementStyles
.call(this)),
4289 className
= that
.attr('class');
4291 $.each(classAnimationActions
, function(i
, action
) {
4292 if (value
[action
]) {
4293 that
[action
+ 'Class'](value
[action
]);
4296 newStyle
= filterStyles(getElementStyles
.call(this));
4297 that
.attr('class', className
);
4299 that
.animate(styleDifference(originalStyle
, newStyle
), {
4303 complete: function() {
4304 $.each(classAnimationActions
, function(i
, action
) {
4305 if (value
[action
]) { that
[action
+ 'Class'](value
[action
]); }
4307 // work around bug in IE by clearing the cssText before setting it
4308 if (typeof that
.attr('style') == 'object') {
4309 that
.attr('style').cssText
= '';
4310 that
.attr('style').cssText
= originalStyleAttr
;
4312 that
.attr('style', originalStyleAttr
);
4314 if (callback
) { callback
.apply(this, arguments
); }
4322 _addClass
: $.fn
.addClass
,
4323 addClass: function(classNames
, speed
, easing
, callback
) {
4324 return speed
? $.effects
.animateClass
.apply(this, [{ add
: classNames
},speed
,easing
,callback
]) : this._addClass(classNames
);
4327 _removeClass
: $.fn
.removeClass
,
4328 removeClass: function(classNames
,speed
,easing
,callback
) {
4329 return speed
? $.effects
.animateClass
.apply(this, [{ remove
: classNames
},speed
,easing
,callback
]) : this._removeClass(classNames
);
4332 _toggleClass
: $.fn
.toggleClass
,
4333 toggleClass: function(classNames
, force
, speed
, easing
, callback
) {
4334 if ( typeof force
== "boolean" || force
=== undefined ) {
4336 // without speed parameter;
4337 return this._toggleClass(classNames
, force
);
4339 return $.effects
.animateClass
.apply(this, [(force
?{add
:classNames
}:{remove
:classNames
}),speed
,easing
,callback
]);
4342 // without switch parameter;
4343 return $.effects
.animateClass
.apply(this, [{ toggle
: classNames
},force
,speed
,easing
]);
4347 switchClass: function(remove
,add
,speed
,easing
,callback
) {
4348 return $.effects
.animateClass
.apply(this, [{ add
: add
, remove
: remove
},speed
,easing
,callback
]);
4354 /******************************************************************************/
4355 /*********************************** EFFECTS **********************************/
4356 /******************************************************************************/
4358 $.extend($.effects
, {
4361 // Saves a set of properties in a data storage
4362 save: function(element
, set) {
4363 for(var i
=0; i
< set.length
; i
++) {
4364 if(set[i
] !== null) element
.data("ec.storage."+set[i
], element
[0].style
[set[i
]]);
4368 // Restores a set of previously saved properties from a data storage
4369 restore: function(element
, set) {
4370 for(var i
=0; i
< set.length
; i
++) {
4371 if(set[i
] !== null) element
.css(set[i
], element
.data("ec.storage."+set[i
]));
4375 setMode: function(el
, mode
) {
4376 if (mode
== 'toggle') mode
= el
.is(':hidden') ? 'show' : 'hide'; // Set for toggle
4380 getBaseline: function(origin
, original
) { // Translates a [top,left] array into a baseline value
4381 // this should be a little more flexible in the future to handle a string & hash
4383 switch (origin
[0]) {
4384 case 'top': y
= 0; break;
4385 case 'middle': y
= 0.5; break;
4386 case 'bottom': y
= 1; break;
4387 default: y
= origin
[0] / original
.height
;
4389 switch (origin
[1]) {
4390 case 'left': x
= 0; break;
4391 case 'center': x
= 0.5; break;
4392 case 'right': x
= 1; break;
4393 default: x
= origin
[1] / original
.width
;
4395 return {x
: x
, y
: y
};
4398 // Wraps the element around a wrapper that copies position properties
4399 createWrapper: function(element
) {
4401 // if the element is already wrapped, return it
4402 if (element
.parent().is('.ui-effects-wrapper')) {
4403 return element
.parent();
4408 width
: element
.outerWidth(true),
4409 height
: element
.outerHeight(true),
4410 'float': element
.css('float')
4412 wrapper
= $('<div></div>')
4413 .addClass('ui-effects-wrapper')
4416 background
: 'transparent',
4421 active
= document
.activeElement
;
4423 element
.wrap(wrapper
);
4425 // Fixes #7595 - Elements lose focus when wrapped.
4426 if ( element
[ 0 ] === active
|| $.contains( element
[ 0 ], active
) ) {
4427 $( active
).focus();
4430 wrapper
= element
.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually loose the reference to the wrapped element
4432 // transfer positioning properties to the wrapper
4433 if (element
.css('position') == 'static') {
4434 wrapper
.css({ position
: 'relative' });
4435 element
.css({ position
: 'relative' });
4438 position
: element
.css('position'),
4439 zIndex
: element
.css('z-index')
4441 $.each(['top', 'left', 'bottom', 'right'], function(i
, pos
) {
4442 props
[pos
] = element
.css(pos
);
4443 if (isNaN(parseInt(props
[pos
], 10))) {
4444 props
[pos
] = 'auto';
4447 element
.css({position
: 'relative', top
: 0, left
: 0, right
: 'auto', bottom
: 'auto' });
4450 return wrapper
.css(props
).show();
4453 removeWrapper: function(element
) {
4455 active
= document
.activeElement
;
4457 if (element
.parent().is('.ui-effects-wrapper')) {
4458 parent
= element
.parent().replaceWith(element
);
4459 // Fixes #7595 - Elements lose focus when wrapped.
4460 if ( element
[ 0 ] === active
|| $.contains( element
[ 0 ], active
) ) {
4461 $( active
).focus();
4469 setTransition: function(element
, list
, factor
, value
) {
4470 value
= value
|| {};
4471 $.each(list
, function(i
, x
){
4472 unit
= element
.cssUnit(x
);
4473 if (unit
[0] > 0) value
[x
] = unit
[0] * factor
+ unit
[1];
4480 function _normalizeArguments(effect
, options
, speed
, callback
) {
4481 // shift params for method overloading
4482 if (typeof effect
== 'object') {
4486 effect
= options
.effect
;
4488 if ($.isFunction(options
)) {
4493 if (typeof options
== 'number' || $.fx
.speeds
[options
]) {
4498 if ($.isFunction(speed
)) {
4503 options
= options
|| {};
4505 speed
= speed
|| options
.duration
;
4506 speed
= $.fx
.off
? 0 : typeof speed
== 'number'
4507 ? speed
: speed
in $.fx
.speeds
? $.fx
.speeds
[speed
] : $.fx
.speeds
._default
;
4509 callback
= callback
|| options
.complete
;
4511 return [effect
, options
, speed
, callback
];
4514 function standardSpeed( speed
) {
4515 // valid standard speeds
4516 if ( !speed
|| typeof speed
=== "number" || $.fx
.speeds
[ speed
] ) {
4520 // invalid strings - treat as "normal" speed
4521 if ( typeof speed
=== "string" && !$.effects
[ speed
] ) {
4529 effect: function(effect
, options
, speed
, callback
) {
4530 var args
= _normalizeArguments
.apply(this, arguments
),
4531 // TODO: make effects take actual parameters instead of a hash
4537 mode
= args2
.options
.mode
,
4538 effectMethod
= $.effects
[effect
];
4540 if ( $.fx
.off
|| !effectMethod
) {
4541 // delegate to the original method (e.g., .show()) if possible
4543 return this[ mode
]( args2
.duration
, args2
.callback
);
4545 return this.each(function() {
4546 if ( args2
.callback
) {
4547 args2
.callback
.call( this );
4553 return effectMethod
.call(this, args2
);
4557 show: function(speed
) {
4558 if ( standardSpeed( speed
) ) {
4559 return this._show
.apply(this, arguments
);
4561 var args
= _normalizeArguments
.apply(this, arguments
);
4562 args
[1].mode
= 'show';
4563 return this.effect
.apply(this, args
);
4568 hide: function(speed
) {
4569 if ( standardSpeed( speed
) ) {
4570 return this._hide
.apply(this, arguments
);
4572 var args
= _normalizeArguments
.apply(this, arguments
);
4573 args
[1].mode
= 'hide';
4574 return this.effect
.apply(this, args
);
4578 // jQuery core overloads toggle and creates _toggle
4579 __toggle
: $.fn
.toggle
,
4580 toggle: function(speed
) {
4581 if ( standardSpeed( speed
) || typeof speed
=== "boolean" || $.isFunction( speed
) ) {
4582 return this.__toggle
.apply(this, arguments
);
4584 var args
= _normalizeArguments
.apply(this, arguments
);
4585 args
[1].mode
= 'toggle';
4586 return this.effect
.apply(this, args
);
4591 cssUnit: function(key
) {
4592 var style
= this.css(key
), val
= [];
4593 $.each( ['em','px','%','pt'], function(i
, unit
){
4594 if(style
.indexOf(unit
) > 0)
4595 val
= [parseFloat(style
), unit
];
4603 /******************************************************************************/
4604 /*********************************** EASING ***********************************/
4605 /******************************************************************************/
4608 * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
4610 * Uses the built in easing capabilities added In jQuery 1.1
4611 * to offer multiple easing options
4613 * TERMS OF USE - jQuery Easing
4615 * Open source under the BSD License.
4617 * Copyright 2008 George McGinley Smith
4618 * All rights reserved.
4620 * Redistribution and use in source and binary forms, with or without modification,
4621 * are permitted provided that the following conditions are met:
4623 * Redistributions of source code must retain the above copyright notice, this list of
4624 * conditions and the following disclaimer.
4625 * Redistributions in binary form must reproduce the above copyright notice, this list
4626 * of conditions and the following disclaimer in the documentation and/or other materials
4627 * provided with the distribution.
4629 * Neither the name of the author nor the names of contributors may be used to endorse
4630 * or promote products derived from this software without specific prior written permission.
4632 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
4633 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
4634 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
4635 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
4636 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
4637 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
4638 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
4639 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
4640 * OF THE POSSIBILITY OF SUCH DAMAGE.
4644 // t: current time, b: begInnIng value, c: change In value, d: duration
4645 $.easing
.jswing
= $.easing
.swing
;
4650 swing: function (x
, t
, b
, c
, d
) {
4651 //alert($.easing.default);
4652 return $.easing
[$.easing
.def
](x
, t
, b
, c
, d
);
4654 easeInQuad: function (x
, t
, b
, c
, d
) {
4655 return c
*(t
/=d
)*t
+ b
;
4657 easeOutQuad: function (x
, t
, b
, c
, d
) {
4658 return -c
*(t
/=d
)*(t
-2) + b
;
4660 easeInOutQuad: function (x
, t
, b
, c
, d
) {
4661 if ((t
/=d/2) < 1) return c
/2*t
*t
+ b
;
4662 return -c
/2 * ((--t
)*(t
-2) - 1) + b
;
4664 easeInCubic: function (x
, t
, b
, c
, d
) {
4665 return c
*(t
/=d
)*t
*t
+ b
;
4667 easeOutCubic: function (x
, t
, b
, c
, d
) {
4668 return c
*((t
=t
/d
-1)*t
*t
+ 1) + b
;
4670 easeInOutCubic: function (x
, t
, b
, c
, d
) {
4671 if ((t
/=d/2) < 1) return c
/2*t
*t
*t
+ b
;
4672 return c
/2*((t
-=2)*t
*t
+ 2) + b
;
4674 easeInQuart: function (x
, t
, b
, c
, d
) {
4675 return c
*(t
/=d
)*t
*t
*t
+ b
;
4677 easeOutQuart: function (x
, t
, b
, c
, d
) {
4678 return -c
* ((t
=t
/d
-1)*t
*t
*t
- 1) + b
;
4680 easeInOutQuart: function (x
, t
, b
, c
, d
) {
4681 if ((t
/=d/2) < 1) return c
/2*t
*t
*t
*t
+ b
;
4682 return -c
/2 * ((t
-=2)*t
*t
*t
- 2) + b
;
4684 easeInQuint: function (x
, t
, b
, c
, d
) {
4685 return c
*(t
/=d
)*t
*t
*t
*t
+ b
;
4687 easeOutQuint: function (x
, t
, b
, c
, d
) {
4688 return c
*((t
=t
/d
-1)*t
*t
*t
*t
+ 1) + b
;
4690 easeInOutQuint: function (x
, t
, b
, c
, d
) {
4691 if ((t
/=d/2) < 1) return c
/2*t
*t
*t
*t
*t
+ b
;
4692 return c
/2*((t
-=2)*t
*t
*t
*t
+ 2) + b
;
4694 easeInSine: function (x
, t
, b
, c
, d
) {
4695 return -c
* Math
.cos(t
/d * (Math.PI/2)) + c
+ b
;
4697 easeOutSine: function (x
, t
, b
, c
, d
) {
4698 return c
* Math
.sin(t
/d * (Math.PI/2)) + b
;
4700 easeInOutSine: function (x
, t
, b
, c
, d
) {
4701 return -c
/2 * (Math.cos(Math.PI*t/d) - 1) + b
;
4703 easeInExpo: function (x
, t
, b
, c
, d
) {
4704 return (t
==0) ? b
: c
* Math
.pow(2, 10 * (t
/d
- 1)) + b
;
4706 easeOutExpo: function (x
, t
, b
, c
, d
) {
4707 return (t
==d
) ? b
+c
: c
* (-Math
.pow(2, -10 * t
/d
) + 1) + b
;
4709 easeInOutExpo: function (x
, t
, b
, c
, d
) {
4711 if (t
==d
) return b
+c
;
4712 if ((t
/=d/2) < 1) return c
/2 * Math
.pow(2, 10 * (t
- 1)) + b
;
4713 return c
/2 * (-Math
.pow(2, -10 * --t
) + 2) + b
;
4715 easeInCirc: function (x
, t
, b
, c
, d
) {
4716 return -c
* (Math
.sqrt(1 - (t
/=d
)*t
) - 1) + b
;
4718 easeOutCirc: function (x
, t
, b
, c
, d
) {
4719 return c
* Math
.sqrt(1 - (t
=t
/d
-1)*t
) + b
;
4721 easeInOutCirc: function (x
, t
, b
, c
, d
) {
4722 if ((t
/=d/2) < 1) return -c
/2 * (Math
.sqrt(1 - t
*t
) - 1) + b
;
4723 return c
/2 * (Math
.sqrt(1 - (t
-=2)*t
) + 1) + b
;
4725 easeInElastic: function (x
, t
, b
, c
, d
) {
4726 var s
=1.70158;var p
=0;var a
=c
;
4727 if (t
==0) return b
; if ((t
/=d
)==1) return b
+c
; if (!p
) p
=d
*.3;
4728 if (a
< Math
.abs(c
)) { a
=c
; var s
=p
/4; }
4729 else var s
= p
/(2*Math.PI) * Math.asin (c/a);
4730 return -(a
*Math
.pow(2,10*(t
-=1)) * Math
.sin( (t
*d
-s
)*(2*Math
.PI
)/p
)) + b
;
4732 easeOutElastic: function (x
, t
, b
, c
, d
) {
4733 var s
=1.70158;var p
=0;var a
=c
;
4734 if (t
==0) return b
; if ((t
/=d
)==1) return b
+c
; if (!p
) p
=d
*.3;
4735 if (a
< Math
.abs(c
)) { a
=c
; var s
=p
/4; }
4736 else var s
= p
/(2*Math.PI) * Math.asin (c/a);
4737 return a
*Math
.pow(2,-10*t
) * Math
.sin( (t
*d
-s
)*(2*Math
.PI
)/p
) + c
+ b
;
4739 easeInOutElastic: function (x
, t
, b
, c
, d
) {
4740 var s
=1.70158;var p
=0;var a
=c
;
4741 if (t
==0) return b
; if ((t
/=d/2)==2) return b
+c
; if (!p
) p
=d
*(.3*1.5);
4742 if (a
< Math
.abs(c
)) { a
=c
; var s
=p
/4; }
4743 else var s
= p
/(2*Math.PI) * Math.asin (c/a);
4744 if (t
< 1) return -.5*(a
*Math
.pow(2,10*(t
-=1)) * Math
.sin( (t
*d
-s
)*(2*Math
.PI
)/p
)) + b
;
4745 return a
*Math
.pow(2,-10*(t
-=1)) * Math
.sin( (t
*d
-s
)*(2*Math
.PI
)/p
)*.5 + c
+ b
;
4747 easeInBack: function (x
, t
, b
, c
, d
, s
) {
4748 if (s
== undefined) s
= 1.70158;
4749 return c
*(t
/=d
)*t
*((s
+1)*t
- s
) + b
;
4751 easeOutBack: function (x
, t
, b
, c
, d
, s
) {
4752 if (s
== undefined) s
= 1.70158;
4753 return c
*((t
=t
/d
-1)*t
*((s
+1)*t
+ s
) + 1) + b
;
4755 easeInOutBack: function (x
, t
, b
, c
, d
, s
) {
4756 if (s
== undefined) s
= 1.70158;
4757 if ((t
/=d/2) < 1) return c
/2*(t
*t
*(((s
*=(1.525))+1)*t
- s
)) + b
;
4758 return c
/2*((t
-=2)*t
*(((s
*=(1.525))+1)*t
+ s
) + 2) + b
;
4760 easeInBounce: function (x
, t
, b
, c
, d
) {
4761 return c
- $.easing
.easeOutBounce (x
, d
-t
, 0, c
, d
) + b
;
4763 easeOutBounce: function (x
, t
, b
, c
, d
) {
4764 if ((t
/=d) < (1/2.75)) {
4765 return c
*(7.5625*t
*t
) + b
;
4766 } else if (t
< (2/2.75)) {
4767 return c
*(7.5625*(t
-=(1.5/2.75))*t
+ .75) + b
;
4768 } else if (t
< (2.5/2.75)) {
4769 return c
*(7.5625*(t
-=(2.25/2.75))*t
+ .9375) + b
;
4771 return c
*(7.5625*(t
-=(2.625/2.75))*t
+ .984375) + b
;
4774 easeInOutBounce: function (x
, t
, b
, c
, d
) {
4775 if (t
< d
/2) return $.easing
.easeInBounce (x
, t
*2, 0, c
, d
) * .5 + b
;
4776 return $.easing
.easeOutBounce (x
, t
*2-d
, 0, c
, d
) * .5 + c
*.5 + b
;
4782 * TERMS OF USE - EASING EQUATIONS
4784 * Open source under the BSD License.
4786 * Copyright 2001 Robert Penner
4787 * All rights reserved.
4789 * Redistribution and use in source and binary forms, with or without modification,
4790 * are permitted provided that the following conditions are met:
4792 * Redistributions of source code must retain the above copyright notice, this list of
4793 * conditions and the following disclaimer.
4794 * Redistributions in binary form must reproduce the above copyright notice, this list
4795 * of conditions and the following disclaimer in the documentation and/or other materials
4796 * provided with the distribution.
4798 * Neither the name of the author nor the names of contributors may be used to endorse
4799 * or promote products derived from this software without specific prior written permission.
4801 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
4802 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
4803 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
4804 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
4805 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
4806 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
4807 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
4808 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
4809 * OF THE POSSIBILITY OF SUCH DAMAGE.
4815 * jQuery UI Effects Blind 1.8.16
4817 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
4818 * Dual licensed under the MIT or GPL Version 2 licenses.
4819 * http://jquery.org/license
4821 * http://docs.jquery.com/UI/Effects/Blind
4824 * jquery.effects.core.js
4826 (function( $, undefined ) {
4828 $.effects
.blind = function(o
) {
4830 return this.queue(function() {
4833 var el
= $(this), props
= ['position','top','bottom','left','right'];
4836 var mode
= $.effects
.setMode(el
, o
.options
.mode
|| 'hide'); // Set Mode
4837 var direction
= o
.options
.direction
|| 'vertical'; // Default direction
4840 $.effects
.save(el
, props
); el
.show(); // Save & Show
4841 var wrapper
= $.effects
.createWrapper(el
).css({overflow
:'hidden'}); // Create Wrapper
4842 var ref
= (direction
== 'vertical') ? 'height' : 'width';
4843 var distance
= (direction
== 'vertical') ? wrapper
.height() : wrapper
.width();
4844 if(mode
== 'show') wrapper
.css(ref
, 0); // Shift
4848 animation
[ref
] = mode
== 'show' ? distance
: 0;
4851 wrapper
.animate(animation
, o
.duration
, o
.options
.easing
, function() {
4852 if(mode
== 'hide') el
.hide(); // Hide
4853 $.effects
.restore(el
, props
); $.effects
.removeWrapper(el
); // Restore
4854 if(o
.callback
) o
.callback
.apply(el
[0], arguments
); // Callback
4864 * jQuery UI Effects Bounce 1.8.16
4866 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
4867 * Dual licensed under the MIT or GPL Version 2 licenses.
4868 * http://jquery.org/license
4870 * http://docs.jquery.com/UI/Effects/Bounce
4873 * jquery.effects.core.js
4875 (function( $, undefined ) {
4877 $.effects
.bounce = function(o
) {
4879 return this.queue(function() {
4882 var el
= $(this), props
= ['position','top','bottom','left','right'];
4885 var mode
= $.effects
.setMode(el
, o
.options
.mode
|| 'effect'); // Set Mode
4886 var direction
= o
.options
.direction
|| 'up'; // Default direction
4887 var distance
= o
.options
.distance
|| 20; // Default distance
4888 var times
= o
.options
.times
|| 5; // Default # of times
4889 var speed
= o
.duration
|| 250; // Default speed per bounce
4890 if (/show|hide/.test(mode
)) props
.push('opacity'); // Avoid touching opacity to prevent clearType and PNG issues in IE
4893 $.effects
.save(el
, props
); el
.show(); // Save & Show
4894 $.effects
.createWrapper(el
); // Create Wrapper
4895 var ref
= (direction
== 'up' || direction
== 'down') ? 'top' : 'left';
4896 var motion
= (direction
== 'up' || direction
== 'left') ? 'pos' : 'neg';
4897 var distance
= o
.options
.distance
|| (ref
== 'top' ? el
.outerHeight({margin
:true}) / 3 : el
.outerWidth({margin
:true}) / 3);
4898 if (mode
== 'show') el
.css('opacity', 0).css(ref
, motion
== 'pos' ? -distance
: distance
); // Shift
4899 if (mode
== 'hide') distance
= distance
/ (times
* 2);
4900 if (mode
!= 'hide') times
--;
4903 if (mode
== 'show') { // Show Bounce
4904 var animation
= {opacity
: 1};
4905 animation
[ref
] = (motion
== 'pos' ? '+=' : '-=') + distance
;
4906 el
.animate(animation
, speed
/ 2, o
.options
.easing
);
4907 distance
= distance
/ 2;
4910 for (var i
= 0; i
< times
; i
++) { // Bounces
4911 var animation1
= {}, animation2
= {};
4912 animation1
[ref
] = (motion
== 'pos' ? '-=' : '+=') + distance
;
4913 animation2
[ref
] = (motion
== 'pos' ? '+=' : '-=') + distance
;
4914 el
.animate(animation1
, speed
/ 2, o
.options
.easing
).animate(animation2
, speed
/ 2, o
.options
.easing
);
4915 distance
= (mode
== 'hide') ? distance
* 2 : distance
/ 2;
4917 if (mode
== 'hide') { // Last Bounce
4918 var animation
= {opacity
: 0};
4919 animation
[ref
] = (motion
== 'pos' ? '-=' : '+=') + distance
;
4920 el
.animate(animation
, speed
/ 2, o
.options
.easing
, function(){
4922 $.effects
.restore(el
, props
); $.effects
.removeWrapper(el
); // Restore
4923 if(o
.callback
) o
.callback
.apply(this, arguments
); // Callback
4926 var animation1
= {}, animation2
= {};
4927 animation1
[ref
] = (motion
== 'pos' ? '-=' : '+=') + distance
;
4928 animation2
[ref
] = (motion
== 'pos' ? '+=' : '-=') + distance
;
4929 el
.animate(animation1
, speed
/ 2, o
.options
.easing
).animate(animation2
, speed
/ 2, o
.options
.easing
, function(){
4930 $.effects
.restore(el
, props
); $.effects
.removeWrapper(el
); // Restore
4931 if(o
.callback
) o
.callback
.apply(this, arguments
); // Callback
4934 el
.queue('fx', function() { el
.dequeue(); });
4942 * jQuery UI Effects Clip 1.8.16
4944 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
4945 * Dual licensed under the MIT or GPL Version 2 licenses.
4946 * http://jquery.org/license
4948 * http://docs.jquery.com/UI/Effects/Clip
4951 * jquery.effects.core.js
4953 (function( $, undefined ) {
4955 $.effects
.clip = function(o
) {
4957 return this.queue(function() {
4960 var el
= $(this), props
= ['position','top','bottom','left','right','height','width'];
4963 var mode
= $.effects
.setMode(el
, o
.options
.mode
|| 'hide'); // Set Mode
4964 var direction
= o
.options
.direction
|| 'vertical'; // Default direction
4967 $.effects
.save(el
, props
); el
.show(); // Save & Show
4968 var wrapper
= $.effects
.createWrapper(el
).css({overflow
:'hidden'}); // Create Wrapper
4969 var animate
= el
[0].tagName
== 'IMG' ? wrapper
: el
;
4971 size
: (direction
== 'vertical') ? 'height' : 'width',
4972 position
: (direction
== 'vertical') ? 'top' : 'left'
4974 var distance
= (direction
== 'vertical') ? animate
.height() : animate
.width();
4975 if(mode
== 'show') { animate
.css(ref
.size
, 0); animate
.css(ref
.position
, distance
/ 2); } // Shift
4979 animation
[ref
.size
] = mode
== 'show' ? distance
: 0;
4980 animation
[ref
.position
] = mode
== 'show' ? 0 : distance
/ 2;
4983 animate
.animate(animation
, { queue
: false, duration
: o
.duration
, easing
: o
.options
.easing
, complete: function() {
4984 if(mode
== 'hide') el
.hide(); // Hide
4985 $.effects
.restore(el
, props
); $.effects
.removeWrapper(el
); // Restore
4986 if(o
.callback
) o
.callback
.apply(el
[0], arguments
); // Callback
4996 * jQuery UI Effects Drop 1.8.16
4998 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
4999 * Dual licensed under the MIT or GPL Version 2 licenses.
5000 * http://jquery.org/license
5002 * http://docs.jquery.com/UI/Effects/Drop
5005 * jquery.effects.core.js
5007 (function( $, undefined ) {
5009 $.effects
.drop = function(o
) {
5011 return this.queue(function() {
5014 var el
= $(this), props
= ['position','top','bottom','left','right','opacity'];
5017 var mode
= $.effects
.setMode(el
, o
.options
.mode
|| 'hide'); // Set Mode
5018 var direction
= o
.options
.direction
|| 'left'; // Default Direction
5021 $.effects
.save(el
, props
); el
.show(); // Save & Show
5022 $.effects
.createWrapper(el
); // Create Wrapper
5023 var ref
= (direction
== 'up' || direction
== 'down') ? 'top' : 'left';
5024 var motion
= (direction
== 'up' || direction
== 'left') ? 'pos' : 'neg';
5025 var distance
= o
.options
.distance
|| (ref
== 'top' ? el
.outerHeight({margin
:true}) / 2 : el
.outerWidth({margin
:true}) / 2);
5026 if (mode
== 'show') el
.css('opacity', 0).css(ref
, motion
== 'pos' ? -distance
: distance
); // Shift
5029 var animation
= {opacity
: mode
== 'show' ? 1 : 0};
5030 animation
[ref
] = (mode
== 'show' ? (motion
== 'pos' ? '+=' : '-=') : (motion
== 'pos' ? '-=' : '+=')) + distance
;
5033 el
.animate(animation
, { queue
: false, duration
: o
.duration
, easing
: o
.options
.easing
, complete: function() {
5034 if(mode
== 'hide') el
.hide(); // Hide
5035 $.effects
.restore(el
, props
); $.effects
.removeWrapper(el
); // Restore
5036 if(o
.callback
) o
.callback
.apply(this, arguments
); // Callback
5046 * jQuery UI Effects Explode 1.8.16
5048 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
5049 * Dual licensed under the MIT or GPL Version 2 licenses.
5050 * http://jquery.org/license
5052 * http://docs.jquery.com/UI/Effects/Explode
5055 * jquery.effects.core.js
5057 (function( $, undefined ) {
5059 $.effects
.explode = function(o
) {
5061 return this.queue(function() {
5063 var rows
= o
.options
.pieces
? Math
.round(Math
.sqrt(o
.options
.pieces
)) : 3;
5064 var cells
= o
.options
.pieces
? Math
.round(Math
.sqrt(o
.options
.pieces
)) : 3;
5066 o
.options
.mode
= o
.options
.mode
== 'toggle' ? ($(this).is(':visible') ? 'hide' : 'show') : o
.options
.mode
;
5067 var el
= $(this).show().css('visibility', 'hidden');
5068 var offset
= el
.offset();
5070 //Substract the margins - not fixing the problem yet.
5071 offset
.top
-= parseInt(el
.css("marginTop"),10) || 0;
5072 offset
.left
-= parseInt(el
.css("marginLeft"),10) || 0;
5074 var width
= el
.outerWidth(true);
5075 var height
= el
.outerHeight(true);
5077 for(var i
=0;i
<rows
;i
++) { // =
5078 for(var j
=0;j
<cells
;j
++) { // ||
5082 .wrap('<div></div>')
5084 position
: 'absolute',
5085 visibility
: 'visible',
5086 left
: -j
*(width
/cells
),
5087 top
: -i
*(height
/rows
)
5090 .addClass('ui-effects-explode')
5092 position
: 'absolute',
5095 height
: height
/rows
,
5096 left
: offset
.left
+ j
*(width
/cells) + (o.options.mode == 'show' ? (j-Math.floor(cells/2))*(width
/cells
) : 0),
5097 top
: offset
.top
+ i
*(height
/rows) + (o.options.mode == 'show' ? (i-Math.floor(rows/2))*(height
/rows
) : 0),
5098 opacity
: o
.options
.mode
== 'show' ? 0 : 1
5100 left
: offset
.left
+ j
*(width
/cells) + (o.options.mode == 'show' ? 0 : (j-Math.floor(cells/2))*(width
/cells
)),
5101 top
: offset
.top
+ i
*(height
/rows) + (o.options.mode == 'show' ? 0 : (i-Math.floor(rows/2))*(height
/rows
)),
5102 opacity
: o
.options
.mode
== 'show' ? 1 : 0
5103 }, o
.duration
|| 500);
5107 // Set a timeout, to call the callback approx. when the other animations have finished
5108 setTimeout(function() {
5110 o
.options
.mode
== 'show' ? el
.css({ visibility
: 'visible' }) : el
.css({ visibility
: 'visible' }).hide();
5111 if(o
.callback
) o
.callback
.apply(el
[0]); // Callback
5114 $('div.ui-effects-explode').remove();
5116 }, o
.duration
|| 500);
5125 * jQuery UI Effects Fade 1.8.16
5127 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
5128 * Dual licensed under the MIT or GPL Version 2 licenses.
5129 * http://jquery.org/license
5131 * http://docs.jquery.com/UI/Effects/Fade
5134 * jquery.effects.core.js
5136 (function( $, undefined ) {
5138 $.effects
.fade = function(o
) {
5139 return this.queue(function() {
5141 mode
= $.effects
.setMode(elem
, o
.options
.mode
|| 'hide');
5143 elem
.animate({ opacity
: mode
}, {
5145 duration
: o
.duration
,
5146 easing
: o
.options
.easing
,
5147 complete: function() {
5148 (o
.callback
&& o
.callback
.apply(this, arguments
));
5157 * jQuery UI Effects Fold 1.8.16
5159 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
5160 * Dual licensed under the MIT or GPL Version 2 licenses.
5161 * http://jquery.org/license
5163 * http://docs.jquery.com/UI/Effects/Fold
5166 * jquery.effects.core.js
5168 (function( $, undefined ) {
5170 $.effects
.fold = function(o
) {
5172 return this.queue(function() {
5175 var el
= $(this), props
= ['position','top','bottom','left','right'];
5178 var mode
= $.effects
.setMode(el
, o
.options
.mode
|| 'hide'); // Set Mode
5179 var size
= o
.options
.size
|| 15; // Default fold size
5180 var horizFirst
= !(!o
.options
.horizFirst
); // Ensure a boolean value
5181 var duration
= o
.duration
? o
.duration
/ 2 : $.fx
.speeds
._default
/ 2;
5184 $.effects
.save(el
, props
); el
.show(); // Save & Show
5185 var wrapper
= $.effects
.createWrapper(el
).css({overflow
:'hidden'}); // Create Wrapper
5186 var widthFirst
= ((mode
== 'show') != horizFirst
);
5187 var ref
= widthFirst
? ['width', 'height'] : ['height', 'width'];
5188 var distance
= widthFirst
? [wrapper
.width(), wrapper
.height()] : [wrapper
.height(), wrapper
.width()];
5189 var percent
= /([0-9]+)%/.exec(size
);
5190 if(percent
) size
= parseInt(percent
[1],10) / 100 * distance
[mode
== 'hide' ? 0 : 1];
5191 if(mode
== 'show') wrapper
.css(horizFirst
? {height
: 0, width
: size
} : {height
: size
, width
: 0}); // Shift
5194 var animation1
= {}, animation2
= {};
5195 animation1
[ref
[0]] = mode
== 'show' ? distance
[0] : size
;
5196 animation2
[ref
[1]] = mode
== 'show' ? distance
[1] : 0;
5199 wrapper
.animate(animation1
, duration
, o
.options
.easing
)
5200 .animate(animation2
, duration
, o
.options
.easing
, function() {
5201 if(mode
== 'hide') el
.hide(); // Hide
5202 $.effects
.restore(el
, props
); $.effects
.removeWrapper(el
); // Restore
5203 if(o
.callback
) o
.callback
.apply(el
[0], arguments
); // Callback
5213 * jQuery UI Effects Highlight 1.8.16
5215 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
5216 * Dual licensed under the MIT or GPL Version 2 licenses.
5217 * http://jquery.org/license
5219 * http://docs.jquery.com/UI/Effects/Highlight
5222 * jquery.effects.core.js
5224 (function( $, undefined ) {
5226 $.effects
.highlight = function(o
) {
5227 return this.queue(function() {
5229 props
= ['backgroundImage', 'backgroundColor', 'opacity'],
5230 mode
= $.effects
.setMode(elem
, o
.options
.mode
|| 'show'),
5232 backgroundColor
: elem
.css('backgroundColor')
5235 if (mode
== 'hide') {
5236 animation
.opacity
= 0;
5239 $.effects
.save(elem
, props
);
5243 backgroundImage
: 'none',
5244 backgroundColor
: o
.options
.color
|| '#ffff99'
5246 .animate(animation
, {
5248 duration
: o
.duration
,
5249 easing
: o
.options
.easing
,
5250 complete: function() {
5251 (mode
== 'hide' && elem
.hide());
5252 $.effects
.restore(elem
, props
);
5253 (mode
== 'show' && !$.support
.opacity
&& this.style
.removeAttribute('filter'));
5254 (o
.callback
&& o
.callback
.apply(this, arguments
));
5263 * jQuery UI Effects Pulsate 1.8.16
5265 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
5266 * Dual licensed under the MIT or GPL Version 2 licenses.
5267 * http://jquery.org/license
5269 * http://docs.jquery.com/UI/Effects/Pulsate
5272 * jquery.effects.core.js
5274 (function( $, undefined ) {
5276 $.effects
.pulsate = function(o
) {
5277 return this.queue(function() {
5279 mode
= $.effects
.setMode(elem
, o
.options
.mode
|| 'show');
5280 times
= ((o
.options
.times
|| 5) * 2) - 1;
5281 duration
= o
.duration
? o
.duration
/ 2 : $.fx
.speeds
._default
/ 2,
5282 isVisible
= elem
.is(':visible'),
5286 elem
.css('opacity', 0).show();
5290 if ((mode
== 'hide' && isVisible
) || (mode
== 'show' && !isVisible
)) {
5294 for (var i
= 0; i
< times
; i
++) {
5295 elem
.animate({ opacity
: animateTo
}, duration
, o
.options
.easing
);
5296 animateTo
= (animateTo
+ 1) % 2;
5299 elem
.animate({ opacity
: animateTo
}, duration
, o
.options
.easing
, function() {
5300 if (animateTo
== 0) {
5303 (o
.callback
&& o
.callback
.apply(this, arguments
));
5307 .queue('fx', function() { elem
.dequeue(); })
5314 * jQuery UI Effects Scale 1.8.16
5316 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
5317 * Dual licensed under the MIT or GPL Version 2 licenses.
5318 * http://jquery.org/license
5320 * http://docs.jquery.com/UI/Effects/Scale
5323 * jquery.effects.core.js
5325 (function( $, undefined ) {
5327 $.effects
.puff = function(o
) {
5328 return this.queue(function() {
5330 mode
= $.effects
.setMode(elem
, o
.options
.mode
|| 'hide'),
5331 percent
= parseInt(o
.options
.percent
, 10) || 150,
5332 factor
= percent
/ 100,
5333 original
= { height
: elem
.height(), width
: elem
.width() };
5335 $.extend(o
.options
, {
5338 percent
: mode
== 'hide' ? percent
: 100,
5339 from: mode
== 'hide'
5342 height
: original
.height
* factor
,
5343 width
: original
.width
* factor
5347 elem
.effect('scale', o
.options
, o
.duration
, o
.callback
);
5352 $.effects
.scale = function(o
) {
5354 return this.queue(function() {
5360 var options
= $.extend(true, {}, o
.options
);
5361 var mode
= $.effects
.setMode(el
, o
.options
.mode
|| 'effect'); // Set Mode
5362 var percent
= parseInt(o
.options
.percent
,10) || (parseInt(o
.options
.percent
,10) == 0 ? 0 : (mode
== 'hide' ? 0 : 100)); // Set default scaling percent
5363 var direction
= o
.options
.direction
|| 'both'; // Set default axis
5364 var origin
= o
.options
.origin
; // The origin of the scaling
5365 if (mode
!= 'effect') { // Set default origin and restore for show/hide
5366 options
.origin
= origin
|| ['middle','center'];
5367 options
.restore
= true;
5369 var original
= {height
: el
.height(), width
: el
.width()}; // Save original
5370 el
.from = o
.options
.from || (mode
== 'show' ? {height
: 0, width
: 0} : original
); // Default from state
5373 var factor
= { // Set scaling factor
5374 y
: direction
!= 'horizontal' ? (percent
/ 100) : 1,
5375 x
: direction
!= 'vertical' ? (percent
/ 100) : 1
5377 el
.to
= {height
: original
.height
* factor
.y
, width
: original
.width
* factor
.x
}; // Set to state
5379 if (o
.options
.fade
) { // Fade option to support puff
5380 if (mode
== 'show') {el
.from.opacity
= 0; el
.to
.opacity
= 1;};
5381 if (mode
== 'hide') {el
.from.opacity
= 1; el
.to
.opacity
= 0;};
5385 options
.from = el
.from; options
.to
= el
.to
; options
.mode
= mode
;
5388 el
.effect('size', options
, o
.duration
, o
.callback
);
5394 $.effects
.size = function(o
) {
5396 return this.queue(function() {
5399 var el
= $(this), props
= ['position','top','bottom','left','right','width','height','overflow','opacity'];
5400 var props1
= ['position','top','bottom','left','right','overflow','opacity']; // Always restore
5401 var props2
= ['width','height','overflow']; // Copy for children
5402 var cProps
= ['fontSize'];
5403 var vProps
= ['borderTopWidth', 'borderBottomWidth', 'paddingTop', 'paddingBottom'];
5404 var hProps
= ['borderLeftWidth', 'borderRightWidth', 'paddingLeft', 'paddingRight'];
5407 var mode
= $.effects
.setMode(el
, o
.options
.mode
|| 'effect'); // Set Mode
5408 var restore
= o
.options
.restore
|| false; // Default restore
5409 var scale
= o
.options
.scale
|| 'both'; // Default scale mode
5410 var origin
= o
.options
.origin
; // The origin of the sizing
5411 var original
= {height
: el
.height(), width
: el
.width()}; // Save original
5412 el
.from = o
.options
.from || original
; // Default from state
5413 el
.to
= o
.options
.to
|| original
; // Default to state
5415 if (origin
) { // Calculate baseline shifts
5416 var baseline
= $.effects
.getBaseline(origin
, original
);
5417 el
.from.top
= (original
.height
- el
.from.height
) * baseline
.y
;
5418 el
.from.left
= (original
.width
- el
.from.width
) * baseline
.x
;
5419 el
.to
.top
= (original
.height
- el
.to
.height
) * baseline
.y
;
5420 el
.to
.left
= (original
.width
- el
.to
.width
) * baseline
.x
;
5422 var factor
= { // Set scaling factor
5423 from: {y
: el
.from.height
/ original
.height
, x
: el
.from.width
/ original
.width
},
5424 to
: {y
: el
.to
.height
/ original
.height
, x
: el
.to
.width
/ original
.width
}
5426 if (scale
== 'box' || scale
== 'both') { // Scale the css box
5427 if (factor
.from.y
!= factor
.to
.y
) { // Vertical props scaling
5428 props
= props
.concat(vProps
);
5429 el
.from = $.effects
.setTransition(el
, vProps
, factor
.from.y
, el
.from);
5430 el
.to
= $.effects
.setTransition(el
, vProps
, factor
.to
.y
, el
.to
);
5432 if (factor
.from.x
!= factor
.to
.x
) { // Horizontal props scaling
5433 props
= props
.concat(hProps
);
5434 el
.from = $.effects
.setTransition(el
, hProps
, factor
.from.x
, el
.from);
5435 el
.to
= $.effects
.setTransition(el
, hProps
, factor
.to
.x
, el
.to
);
5438 if (scale
== 'content' || scale
== 'both') { // Scale the content
5439 if (factor
.from.y
!= factor
.to
.y
) { // Vertical props scaling
5440 props
= props
.concat(cProps
);
5441 el
.from = $.effects
.setTransition(el
, cProps
, factor
.from.y
, el
.from);
5442 el
.to
= $.effects
.setTransition(el
, cProps
, factor
.to
.y
, el
.to
);
5445 $.effects
.save(el
, restore
? props
: props1
); el
.show(); // Save & Show
5446 $.effects
.createWrapper(el
); // Create Wrapper
5447 el
.css('overflow','hidden').css(el
.from); // Shift
5450 if (scale
== 'content' || scale
== 'both') { // Scale the children
5451 vProps
= vProps
.concat(['marginTop','marginBottom']).concat(cProps
); // Add margins/font-size
5452 hProps
= hProps
.concat(['marginLeft','marginRight']); // Add margins
5453 props2
= props
.concat(vProps
).concat(hProps
); // Concat
5454 el
.find("*[width]").each(function(){
5456 if (restore
) $.effects
.save(child
, props2
);
5457 var c_original
= {height
: child
.height(), width
: child
.width()}; // Save original
5458 child
.from = {height
: c_original
.height
* factor
.from.y
, width
: c_original
.width
* factor
.from.x
};
5459 child
.to
= {height
: c_original
.height
* factor
.to
.y
, width
: c_original
.width
* factor
.to
.x
};
5460 if (factor
.from.y
!= factor
.to
.y
) { // Vertical props scaling
5461 child
.from = $.effects
.setTransition(child
, vProps
, factor
.from.y
, child
.from);
5462 child
.to
= $.effects
.setTransition(child
, vProps
, factor
.to
.y
, child
.to
);
5464 if (factor
.from.x
!= factor
.to
.x
) { // Horizontal props scaling
5465 child
.from = $.effects
.setTransition(child
, hProps
, factor
.from.x
, child
.from);
5466 child
.to
= $.effects
.setTransition(child
, hProps
, factor
.to
.x
, child
.to
);
5468 child
.css(child
.from); // Shift children
5469 child
.animate(child
.to
, o
.duration
, o
.options
.easing
, function(){
5470 if (restore
) $.effects
.restore(child
, props2
); // Restore children
5471 }); // Animate children
5476 el
.animate(el
.to
, { queue
: false, duration
: o
.duration
, easing
: o
.options
.easing
, complete: function() {
5477 if (el
.to
.opacity
=== 0) {
5478 el
.css('opacity', el
.from.opacity
);
5480 if(mode
== 'hide') el
.hide(); // Hide
5481 $.effects
.restore(el
, restore
? props
: props1
); $.effects
.removeWrapper(el
); // Restore
5482 if(o
.callback
) o
.callback
.apply(this, arguments
); // Callback
5492 * jQuery UI Effects Shake 1.8.16
5494 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
5495 * Dual licensed under the MIT or GPL Version 2 licenses.
5496 * http://jquery.org/license
5498 * http://docs.jquery.com/UI/Effects/Shake
5501 * jquery.effects.core.js
5503 (function( $, undefined ) {
5505 $.effects
.shake = function(o
) {
5507 return this.queue(function() {
5510 var el
= $(this), props
= ['position','top','bottom','left','right'];
5513 var mode
= $.effects
.setMode(el
, o
.options
.mode
|| 'effect'); // Set Mode
5514 var direction
= o
.options
.direction
|| 'left'; // Default direction
5515 var distance
= o
.options
.distance
|| 20; // Default distance
5516 var times
= o
.options
.times
|| 3; // Default # of times
5517 var speed
= o
.duration
|| o
.options
.duration
|| 140; // Default speed per shake
5520 $.effects
.save(el
, props
); el
.show(); // Save & Show
5521 $.effects
.createWrapper(el
); // Create Wrapper
5522 var ref
= (direction
== 'up' || direction
== 'down') ? 'top' : 'left';
5523 var motion
= (direction
== 'up' || direction
== 'left') ? 'pos' : 'neg';
5526 var animation
= {}, animation1
= {}, animation2
= {};
5527 animation
[ref
] = (motion
== 'pos' ? '-=' : '+=') + distance
;
5528 animation1
[ref
] = (motion
== 'pos' ? '+=' : '-=') + distance
* 2;
5529 animation2
[ref
] = (motion
== 'pos' ? '-=' : '+=') + distance
* 2;
5532 el
.animate(animation
, speed
, o
.options
.easing
);
5533 for (var i
= 1; i
< times
; i
++) { // Shakes
5534 el
.animate(animation1
, speed
, o
.options
.easing
).animate(animation2
, speed
, o
.options
.easing
);
5536 el
.animate(animation1
, speed
, o
.options
.easing
).
5537 animate(animation
, speed
/ 2, o
.options
.easing
, function(){ // Last shake
5538 $.effects
.restore(el
, props
); $.effects
.removeWrapper(el
); // Restore
5539 if(o
.callback
) o
.callback
.apply(this, arguments
); // Callback
5541 el
.queue('fx', function() { el
.dequeue(); });
5549 * jQuery UI Effects Slide 1.8.16
5551 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
5552 * Dual licensed under the MIT or GPL Version 2 licenses.
5553 * http://jquery.org/license
5555 * http://docs.jquery.com/UI/Effects/Slide
5558 * jquery.effects.core.js
5560 (function( $, undefined ) {
5562 $.effects
.slide = function(o
) {
5564 return this.queue(function() {
5567 var el
= $(this), props
= ['position','top','bottom','left','right'];
5570 var mode
= $.effects
.setMode(el
, o
.options
.mode
|| 'show'); // Set Mode
5571 var direction
= o
.options
.direction
|| 'left'; // Default Direction
5574 $.effects
.save(el
, props
); el
.show(); // Save & Show
5575 $.effects
.createWrapper(el
).css({overflow
:'hidden'}); // Create Wrapper
5576 var ref
= (direction
== 'up' || direction
== 'down') ? 'top' : 'left';
5577 var motion
= (direction
== 'up' || direction
== 'left') ? 'pos' : 'neg';
5578 var distance
= o
.options
.distance
|| (ref
== 'top' ? el
.outerHeight({margin
:true}) : el
.outerWidth({margin
:true}));
5579 if (mode
== 'show') el
.css(ref
, motion
== 'pos' ? (isNaN(distance
) ? "-" + distance
: -distance
) : distance
); // Shift
5583 animation
[ref
] = (mode
== 'show' ? (motion
== 'pos' ? '+=' : '-=') : (motion
== 'pos' ? '-=' : '+=')) + distance
;
5586 el
.animate(animation
, { queue
: false, duration
: o
.duration
, easing
: o
.options
.easing
, complete: function() {
5587 if(mode
== 'hide') el
.hide(); // Hide
5588 $.effects
.restore(el
, props
); $.effects
.removeWrapper(el
); // Restore
5589 if(o
.callback
) o
.callback
.apply(this, arguments
); // Callback
5599 * jQuery UI Effects Transfer 1.8.16
5601 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
5602 * Dual licensed under the MIT or GPL Version 2 licenses.
5603 * http://jquery.org/license
5605 * http://docs.jquery.com/UI/Effects/Transfer
5608 * jquery.effects.core.js
5610 (function( $, undefined ) {
5612 $.effects
.transfer = function(o
) {
5613 return this.queue(function() {
5615 target
= $(o
.options
.to
),
5616 endPosition
= target
.offset(),
5618 top
: endPosition
.top
,
5619 left
: endPosition
.left
,
5620 height
: target
.innerHeight(),
5621 width
: target
.innerWidth()
5623 startPosition
= elem
.offset(),
5624 transfer
= $('<div class="ui-effects-transfer"></div>')
5625 .appendTo(document
.body
)
5626 .addClass(o
.options
.className
)
5628 top
: startPosition
.top
,
5629 left
: startPosition
.left
,
5630 height
: elem
.innerHeight(),
5631 width
: elem
.innerWidth(),
5632 position
: 'absolute'
5634 .animate(animation
, o
.duration
, o
.options
.easing
, function() {
5636 (o
.callback
&& o
.callback
.apply(elem
[0], arguments
));
5644 * jQuery UI Accordion 1.8.16
5646 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
5647 * Dual licensed under the MIT or GPL Version 2 licenses.
5648 * http://jquery.org/license
5650 * http://docs.jquery.com/UI/Accordion
5654 * jquery.ui.widget.js
5656 (function( $, undefined ) {
5658 $.widget( "ui.accordion", {
5667 header
: "> li > :first-child,> :not(li):even",
5669 header
: "ui-icon-triangle-1-e",
5670 headerSelected
: "ui-icon-triangle-1-s"
5673 navigationFilter: function() {
5674 return this.href
.toLowerCase() === location
.href
.toLowerCase();
5678 _create: function() {
5680 options
= self
.options
;
5685 .addClass( "ui-accordion ui-widget ui-helper-reset" )
5686 // in lack of child-selectors in CSS
5687 // we need to mark top-LIs in a UL-accordion for some IE-fix
5689 .addClass( "ui-accordion-li-fix" );
5691 self
.headers
= self
.element
.find( options
.header
)
5692 .addClass( "ui-accordion-header ui-helper-reset ui-state-default ui-corner-all" )
5693 .bind( "mouseenter.accordion", function() {
5694 if ( options
.disabled
) {
5697 $( this ).addClass( "ui-state-hover" );
5699 .bind( "mouseleave.accordion", function() {
5700 if ( options
.disabled
) {
5703 $( this ).removeClass( "ui-state-hover" );
5705 .bind( "focus.accordion", function() {
5706 if ( options
.disabled
) {
5709 $( this ).addClass( "ui-state-focus" );
5711 .bind( "blur.accordion", function() {
5712 if ( options
.disabled
) {
5715 $( this ).removeClass( "ui-state-focus" );
5719 .addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" );
5721 if ( options
.navigation
) {
5722 var current
= self
.element
.find( "a" ).filter( options
.navigationFilter
).eq( 0 );
5723 if ( current
.length
) {
5724 var header
= current
.closest( ".ui-accordion-header" );
5725 if ( header
.length
) {
5726 // anchor within header
5727 self
.active
= header
;
5729 // anchor within content
5730 self
.active
= current
.closest( ".ui-accordion-content" ).prev();
5735 self
.active
= self
._findActive( self
.active
|| options
.active
)
5736 .addClass( "ui-state-default ui-state-active" )
5737 .toggleClass( "ui-corner-all" )
5738 .toggleClass( "ui-corner-top" );
5739 self
.active
.next().addClass( "ui-accordion-content-active" );
5741 self
._createIcons();
5745 self
.element
.attr( "role", "tablist" );
5748 .attr( "role", "tab" )
5749 .bind( "keydown.accordion", function( event
) {
5750 return self
._keydown( event
);
5753 .attr( "role", "tabpanel" );
5756 .not( self
.active
|| "" )
5758 "aria-expanded": "false",
5759 "aria-selected": "false",
5765 // make sure at least one header is in the tab order
5766 if ( !self
.active
.length
) {
5767 self
.headers
.eq( 0 ).attr( "tabIndex", 0 );
5771 "aria-expanded": "true",
5772 "aria-selected": "true",
5777 // only need links in tab order for Safari
5778 if ( !$.browser
.safari
) {
5779 self
.headers
.find( "a" ).attr( "tabIndex", -1 );
5782 if ( options
.event
) {
5783 self
.headers
.bind( options
.event
.split(" ").join(".accordion ") + ".accordion", function(event
) {
5784 self
._clickHandler
.call( self
, event
, this );
5785 event
.preventDefault();
5790 _createIcons: function() {
5791 var options
= this.options
;
5792 if ( options
.icons
) {
5793 $( "<span></span>" )
5794 .addClass( "ui-icon " + options
.icons
.header
)
5795 .prependTo( this.headers
);
5796 this.active
.children( ".ui-icon" )
5797 .toggleClass(options
.icons
.header
)
5798 .toggleClass(options
.icons
.headerSelected
);
5799 this.element
.addClass( "ui-accordion-icons" );
5803 _destroyIcons: function() {
5804 this.headers
.children( ".ui-icon" ).remove();
5805 this.element
.removeClass( "ui-accordion-icons" );
5808 destroy: function() {
5809 var options
= this.options
;
5812 .removeClass( "ui-accordion ui-widget ui-helper-reset" )
5813 .removeAttr( "role" );
5816 .unbind( ".accordion" )
5817 .removeClass( "ui-accordion-header ui-accordion-disabled ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top" )
5818 .removeAttr( "role" )
5819 .removeAttr( "aria-expanded" )
5820 .removeAttr( "aria-selected" )
5821 .removeAttr( "tabIndex" );
5823 this.headers
.find( "a" ).removeAttr( "tabIndex" );
5824 this._destroyIcons();
5825 var contents
= this.headers
.next()
5826 .css( "display", "" )
5827 .removeAttr( "role" )
5828 .removeClass( "ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-accordion-disabled ui-state-disabled" );
5829 if ( options
.autoHeight
|| options
.fillHeight
) {
5830 contents
.css( "height", "" );
5833 return $.Widget
.prototype.destroy
.call( this );
5836 _setOption: function( key
, value
) {
5837 $.Widget
.prototype._setOption
.apply( this, arguments
);
5839 if ( key
== "active" ) {
5840 this.activate( value
);
5842 if ( key
== "icons" ) {
5843 this._destroyIcons();
5845 this._createIcons();
5848 // #5332 - opacity doesn't cascade to positioned elements in IE
5849 // so we need to add the disabled class to the headers and panels
5850 if ( key
== "disabled" ) {
5851 this.headers
.add(this.headers
.next())
5852 [ value
? "addClass" : "removeClass" ](
5853 "ui-accordion-disabled ui-state-disabled" );
5857 _keydown: function( event
) {
5858 if ( this.options
.disabled
|| event
.altKey
|| event
.ctrlKey
) {
5862 var keyCode
= $.ui
.keyCode
,
5863 length
= this.headers
.length
,
5864 currentIndex
= this.headers
.index( event
.target
),
5867 switch ( event
.keyCode
) {
5870 toFocus
= this.headers
[ ( currentIndex
+ 1 ) % length
];
5874 toFocus
= this.headers
[ ( currentIndex
- 1 + length
) % length
];
5878 this._clickHandler( { target
: event
.target
}, event
.target
);
5879 event
.preventDefault();
5883 $( event
.target
).attr( "tabIndex", -1 );
5884 $( toFocus
).attr( "tabIndex", 0 );
5892 resize: function() {
5893 var options
= this.options
,
5896 if ( options
.fillSpace
) {
5897 if ( $.browser
.msie
) {
5898 var defOverflow
= this.element
.parent().css( "overflow" );
5899 this.element
.parent().css( "overflow", "hidden");
5901 maxHeight
= this.element
.parent().height();
5902 if ($.browser
.msie
) {
5903 this.element
.parent().css( "overflow", defOverflow
);
5906 this.headers
.each(function() {
5907 maxHeight
-= $( this ).outerHeight( true );
5912 $( this ).height( Math
.max( 0, maxHeight
-
5913 $( this ).innerHeight() + $( this ).height() ) );
5915 .css( "overflow", "auto" );
5916 } else if ( options
.autoHeight
) {
5920 maxHeight
= Math
.max( maxHeight
, $( this ).height( "" ).height() );
5922 .height( maxHeight
);
5928 activate: function( index
) {
5929 // TODO this gets called on init, changing the option without an explicit call for that
5930 this.options
.active
= index
;
5931 // call clickHandler with custom event
5932 var active
= this._findActive( index
)[ 0 ];
5933 this._clickHandler( { target
: active
}, active
);
5938 _findActive: function( selector
) {
5940 ? typeof selector
=== "number"
5941 ? this.headers
.filter( ":eq(" + selector
+ ")" )
5942 : this.headers
.not( this.headers
.not( selector
) )
5943 : selector
=== false
5945 : this.headers
.filter( ":eq(0)" );
5948 // TODO isn't event.target enough? why the separate target argument?
5949 _clickHandler: function( event
, target
) {
5950 var options
= this.options
;
5951 if ( options
.disabled
) {
5955 // called only when using activate(false) to close all parts programmatically
5956 if ( !event
.target
) {
5957 if ( !options
.collapsible
) {
5961 .removeClass( "ui-state-active ui-corner-top" )
5962 .addClass( "ui-state-default ui-corner-all" )
5963 .children( ".ui-icon" )
5964 .removeClass( options
.icons
.headerSelected
)
5965 .addClass( options
.icons
.header
);
5966 this.active
.next().addClass( "ui-accordion-content-active" );
5967 var toHide
= this.active
.next(),
5971 oldHeader
: options
.active
,
5972 newContent
: $( [] ),
5975 toShow
= ( this.active
= $( [] ) );
5976 this._toggle( toShow
, toHide
, data
);
5980 // get the click target
5981 var clicked
= $( event
.currentTarget
|| target
),
5982 clickedIsActive
= clicked
[0] === this.active
[0];
5984 // TODO the option is changed, is that correct?
5985 // TODO if it is correct, shouldn't that happen after determining that the click is valid?
5986 options
.active
= options
.collapsible
&& clickedIsActive
?
5988 this.headers
.index( clicked
);
5990 // if animations are still active, or the active header is the target, ignore click
5991 if ( this.running
|| ( !options
.collapsible
&& clickedIsActive
) ) {
5995 // find elements to show and hide
5996 var active
= this.active
,
5997 toShow
= clicked
.next(),
5998 toHide
= this.active
.next(),
6001 newHeader
: clickedIsActive
&& options
.collapsible
? $([]) : clicked
,
6002 oldHeader
: this.active
,
6003 newContent
: clickedIsActive
&& options
.collapsible
? $([]) : toShow
,
6006 down
= this.headers
.index( this.active
[0] ) > this.headers
.index( clicked
[0] );
6008 // when the call to ._toggle() comes after the class changes
6009 // it causes a very odd bug in IE 8 (see #6720)
6010 this.active
= clickedIsActive
? $([]) : clicked
;
6011 this._toggle( toShow
, toHide
, data
, clickedIsActive
, down
);
6015 .removeClass( "ui-state-active ui-corner-top" )
6016 .addClass( "ui-state-default ui-corner-all" )
6017 .children( ".ui-icon" )
6018 .removeClass( options
.icons
.headerSelected
)
6019 .addClass( options
.icons
.header
);
6020 if ( !clickedIsActive
) {
6022 .removeClass( "ui-state-default ui-corner-all" )
6023 .addClass( "ui-state-active ui-corner-top" )
6024 .children( ".ui-icon" )
6025 .removeClass( options
.icons
.header
)
6026 .addClass( options
.icons
.headerSelected
);
6029 .addClass( "ui-accordion-content-active" );
6035 _toggle: function( toShow
, toHide
, data
, clickedIsActive
, down
) {
6037 options
= self
.options
;
6039 self
.toShow
= toShow
;
6040 self
.toHide
= toHide
;
6043 var complete = function() {
6047 return self
._completed
.apply( self
, arguments
);
6050 // trigger changestart event
6051 self
._trigger( "changestart", null, self
.data
);
6053 // count elements to animate
6054 self
.running
= toHide
.size() === 0 ? toShow
.size() : toHide
.size();
6056 if ( options
.animated
) {
6057 var animOptions
= {};
6059 if ( options
.collapsible
&& clickedIsActive
) {
6065 autoHeight
: options
.autoHeight
|| options
.fillSpace
6073 autoHeight
: options
.autoHeight
|| options
.fillSpace
6077 if ( !options
.proxied
) {
6078 options
.proxied
= options
.animated
;
6081 if ( !options
.proxiedDuration
) {
6082 options
.proxiedDuration
= options
.duration
;
6085 options
.animated
= $.isFunction( options
.proxied
) ?
6086 options
.proxied( animOptions
) :
6089 options
.duration
= $.isFunction( options
.proxiedDuration
) ?
6090 options
.proxiedDuration( animOptions
) :
6091 options
.proxiedDuration
;
6093 var animations
= $.ui
.accordion
.animations
,
6094 duration
= options
.duration
,
6095 easing
= options
.animated
;
6097 if ( easing
&& !animations
[ easing
] && !$.easing
[ easing
] ) {
6100 if ( !animations
[ easing
] ) {
6101 animations
[ easing
] = function( options
) {
6102 this.slide( options
, {
6104 duration
: duration
|| 700
6109 animations
[ easing
]( animOptions
);
6111 if ( options
.collapsible
&& clickedIsActive
) {
6121 // TODO assert that the blur and focus triggers are really necessary, remove otherwise
6124 "aria-expanded": "false",
6125 "aria-selected": "false",
6131 "aria-expanded": "true",
6132 "aria-selected": "true",
6138 _completed: function( cancel
) {
6139 this.running
= cancel
? 0 : --this.running
;
6140 if ( this.running
) {
6144 if ( this.options
.clearStyle
) {
6145 this.toShow
.add( this.toHide
).css({
6151 // other classes are removed before the animation; this one needs to stay until completed
6152 this.toHide
.removeClass( "ui-accordion-content-active" );
6153 // Work around for rendering bug in IE (#5421)
6154 if ( this.toHide
.length
) {
6155 this.toHide
.parent()[0].className
= this.toHide
.parent()[0].className
;
6158 this._trigger( "change", null, this.data
);
6162 $.extend( $.ui
.accordion
, {
6165 slide: function( options
, additions
) {
6166 options
= $.extend({
6169 }, options
, additions
);
6170 if ( !options
.toHide
.size() ) {
6171 options
.toShow
.animate({
6174 paddingBottom
: "show"
6178 if ( !options
.toShow
.size() ) {
6179 options
.toHide
.animate({
6182 paddingBottom
: "hide"
6186 var overflow
= options
.toShow
.css( "overflow" ),
6190 fxAttrs
= [ "height", "paddingTop", "paddingBottom" ],
6192 // fix width before calculating height of hidden element
6193 var s
= options
.toShow
;
6194 originalWidth
= s
[0].style
.width
;
6195 s
.width( parseInt( s
.parent().width(), 10 )
6196 - parseInt( s
.css( "paddingLeft" ), 10 )
6197 - parseInt( s
.css( "paddingRight" ), 10 )
6198 - ( parseInt( s
.css( "borderLeftWidth" ), 10 ) || 0 )
6199 - ( parseInt( s
.css( "borderRightWidth" ), 10) || 0 ) );
6201 $.each( fxAttrs
, function( i
, prop
) {
6202 hideProps
[ prop
] = "hide";
6204 var parts
= ( "" + $.css( options
.toShow
[0], prop
) ).match( /^([\d+-.]+)(.*)$/ );
6205 showProps
[ prop
] = {
6207 unit
: parts
[ 2 ] || "px"
6210 options
.toShow
.css({ height
: 0, overflow
: "hidden" }).show();
6212 .filter( ":hidden" )
6213 .each( options
.complete
)
6215 .filter( ":visible" )
6216 .animate( hideProps
, {
6217 step: function( now
, settings
) {
6218 // only calculate the percent when animating height
6219 // IE gets very inconsistent results when animating elements
6220 // with small values, which is common for padding
6221 if ( settings
.prop
== "height" ) {
6222 percentDone
= ( settings
.end
- settings
.start
=== 0 ) ? 0 :
6223 ( settings
.now
- settings
.start
) / ( settings
.end
- settings
.start
);
6226 options
.toShow
[ 0 ].style
[ settings
.prop
] =
6227 ( percentDone
* showProps
[ settings
.prop
].value
)
6228 + showProps
[ settings
.prop
].unit
;
6230 duration
: options
.duration
,
6231 easing
: options
.easing
,
6232 complete: function() {
6233 if ( !options
.autoHeight
) {
6234 options
.toShow
.css( "height", "" );
6236 options
.toShow
.css({
6237 width
: originalWidth
,
6244 bounceslide: function( options
) {
6245 this.slide( options
, {
6246 easing
: options
.down
? "easeOutBounce" : "swing",
6247 duration
: options
.down
? 1000 : 200
6255 * jQuery UI Autocomplete 1.8.16
6257 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
6258 * Dual licensed under the MIT or GPL Version 2 licenses.
6259 * http://jquery.org/license
6261 * http://docs.jquery.com/UI/Autocomplete
6265 * jquery.ui.widget.js
6266 * jquery.ui.position.js
6268 (function( $, undefined ) {
6270 // used to prevent race conditions with remote data sources
6271 var requestIndex
= 0;
6273 $.widget( "ui.autocomplete", {
6289 _create: function() {
6291 doc
= this.element
[ 0 ].ownerDocument
,
6295 .addClass( "ui-autocomplete-input" )
6296 .attr( "autocomplete", "off" )
6297 // TODO verify these actually work as intended
6300 "aria-autocomplete": "list",
6301 "aria-haspopup": "true"
6303 .bind( "keydown.autocomplete", function( event
) {
6304 if ( self
.options
.disabled
|| self
.element
.propAttr( "readOnly" ) ) {
6308 suppressKeyPress
= false;
6309 var keyCode
= $.ui
.keyCode
;
6310 switch( event
.keyCode
) {
6311 case keyCode
.PAGE_UP
:
6312 self
._move( "previousPage", event
);
6314 case keyCode
.PAGE_DOWN
:
6315 self
._move( "nextPage", event
);
6318 self
._move( "previous", event
);
6319 // prevent moving cursor to beginning of text field in some browsers
6320 event
.preventDefault();
6323 self
._move( "next", event
);
6324 // prevent moving cursor to end of text field in some browsers
6325 event
.preventDefault();
6328 case keyCode
.NUMPAD_ENTER
:
6329 // when menu is open and has focus
6330 if ( self
.menu
.active
) {
6331 // #6055 - Opera still allows the keypress to occur
6332 // which causes forms to submit
6333 suppressKeyPress
= true;
6334 event
.preventDefault();
6336 //passthrough - ENTER and TAB both select the current element
6338 if ( !self
.menu
.active
) {
6341 self
.menu
.select( event
);
6343 case keyCode
.ESCAPE
:
6344 self
.element
.val( self
.term
);
6345 self
.close( event
);
6348 // keypress is triggered before the input value is changed
6349 clearTimeout( self
.searching
);
6350 self
.searching
= setTimeout(function() {
6351 // only search if the value has changed
6352 if ( self
.term
!= self
.element
.val() ) {
6353 self
.selectedItem
= null;
6354 self
.search( null, event
);
6356 }, self
.options
.delay
);
6360 .bind( "keypress.autocomplete", function( event
) {
6361 if ( suppressKeyPress
) {
6362 suppressKeyPress
= false;
6363 event
.preventDefault();
6366 .bind( "focus.autocomplete", function() {
6367 if ( self
.options
.disabled
) {
6371 self
.selectedItem
= null;
6372 self
.previous
= self
.element
.val();
6374 .bind( "blur.autocomplete", function( event
) {
6375 if ( self
.options
.disabled
) {
6379 clearTimeout( self
.searching
);
6380 // clicks on the menu (or a button to trigger a search) will cause a blur event
6381 self
.closing
= setTimeout(function() {
6382 self
.close( event
);
6383 self
._change( event
);
6387 this.response = function() {
6388 return self
._response
.apply( self
, arguments
);
6390 this.menu
= $( "<ul></ul>" )
6391 .addClass( "ui-autocomplete" )
6392 .appendTo( $( this.options
.appendTo
|| "body", doc
)[0] )
6393 // prevent the close-on-blur in case of a "slow" click on the menu (long mousedown)
6394 .mousedown(function( event
) {
6395 // clicking on the scrollbar causes focus to shift to the body
6396 // but we can't detect a mouseup or a click immediately afterward
6397 // so we have to track the next mousedown and close the menu if
6398 // the user clicks somewhere outside of the autocomplete
6399 var menuElement
= self
.menu
.element
[ 0 ];
6400 if ( !$( event
.target
).closest( ".ui-menu-item" ).length
) {
6401 setTimeout(function() {
6402 $( document
).one( 'mousedown', function( event
) {
6403 if ( event
.target
!== self
.element
[ 0 ] &&
6404 event
.target
!== menuElement
&&
6405 !$.ui
.contains( menuElement
, event
.target
) ) {
6412 // use another timeout to make sure the blur-event-handler on the input was already triggered
6413 setTimeout(function() {
6414 clearTimeout( self
.closing
);
6418 focus: function( event
, ui
) {
6419 var item
= ui
.item
.data( "item.autocomplete" );
6420 if ( false !== self
._trigger( "focus", event
, { item
: item
} ) ) {
6421 // use value to match what will end up in the input, if it was a key event
6422 if ( /^key/.test(event
.originalEvent
.type
) ) {
6423 self
.element
.val( item
.value
);
6427 selected: function( event
, ui
) {
6428 var item
= ui
.item
.data( "item.autocomplete" ),
6429 previous
= self
.previous
;
6431 // only trigger when focus was lost (click on menu)
6432 if ( self
.element
[0] !== doc
.activeElement
) {
6433 self
.element
.focus();
6434 self
.previous
= previous
;
6435 // #6109 - IE triggers two focus events and the second
6436 // is asynchronous, so we need to reset the previous
6437 // term synchronously and asynchronously :-(
6438 setTimeout(function() {
6439 self
.previous
= previous
;
6440 self
.selectedItem
= item
;
6444 if ( false !== self
._trigger( "select", event
, { item
: item
} ) ) {
6445 self
.element
.val( item
.value
);
6447 // reset the term after the select event
6448 // this allows custom select handling to work properly
6449 self
.term
= self
.element
.val();
6451 self
.close( event
);
6452 self
.selectedItem
= item
;
6454 blur: function( event
, ui
) {
6455 // don't set the value of the text field if it's already correct
6456 // this prevents moving the cursor unnecessarily
6457 if ( self
.menu
.element
.is(":visible") &&
6458 ( self
.element
.val() !== self
.term
) ) {
6459 self
.element
.val( self
.term
);
6463 .zIndex( this.element
.zIndex() + 1 )
6464 // workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
6465 .css({ top
: 0, left
: 0 })
6468 if ( $.fn
.bgiframe
) {
6469 this.menu
.element
.bgiframe();
6473 destroy: function() {
6475 .removeClass( "ui-autocomplete-input" )
6476 .removeAttr( "autocomplete" )
6477 .removeAttr( "role" )
6478 .removeAttr( "aria-autocomplete" )
6479 .removeAttr( "aria-haspopup" );
6480 this.menu
.element
.remove();
6481 $.Widget
.prototype.destroy
.call( this );
6484 _setOption: function( key
, value
) {
6485 $.Widget
.prototype._setOption
.apply( this, arguments
);
6486 if ( key
=== "source" ) {
6489 if ( key
=== "appendTo" ) {
6490 this.menu
.element
.appendTo( $( value
|| "body", this.element
[0].ownerDocument
)[0] )
6492 if ( key
=== "disabled" && value
&& this.xhr
) {
6497 _initSource: function() {
6501 if ( $.isArray(this.options
.source
) ) {
6502 array
= this.options
.source
;
6503 this.source = function( request
, response
) {
6504 response( $.ui
.autocomplete
.filter(array
, request
.term
) );
6506 } else if ( typeof this.options
.source
=== "string" ) {
6507 url
= this.options
.source
;
6508 this.source = function( request
, response
) {
6516 autocompleteRequest
: ++requestIndex
,
6517 success: function( data
, status
) {
6518 if ( this.autocompleteRequest
=== requestIndex
) {
6523 if ( this.autocompleteRequest
=== requestIndex
) {
6530 this.source
= this.options
.source
;
6534 search: function( value
, event
) {
6535 value
= value
!= null ? value
: this.element
.val();
6537 // always save the actual value, not the one passed as an argument
6538 this.term
= this.element
.val();
6540 if ( value
.length
< this.options
.minLength
) {
6541 return this.close( event
);
6544 clearTimeout( this.closing
);
6545 if ( this._trigger( "search", event
) === false ) {
6549 return this._search( value
);
6552 _search: function( value
) {
6554 this.element
.addClass( "ui-autocomplete-loading" );
6556 this.source( { term
: value
}, this.response
);
6559 _response: function( content
) {
6560 if ( !this.options
.disabled
&& content
&& content
.length
) {
6561 content
= this._normalize( content
);
6562 this._suggest( content
);
6563 this._trigger( "open" );
6568 if ( !this.pending
) {
6569 this.element
.removeClass( "ui-autocomplete-loading" );
6573 close: function( event
) {
6574 clearTimeout( this.closing
);
6575 if ( this.menu
.element
.is(":visible") ) {
6576 this.menu
.element
.hide();
6577 this.menu
.deactivate();
6578 this._trigger( "close", event
);
6582 _change: function( event
) {
6583 if ( this.previous
!== this.element
.val() ) {
6584 this._trigger( "change", event
, { item
: this.selectedItem
} );
6588 _normalize: function( items
) {
6589 // assume all items have the right format when the first item is complete
6590 if ( items
.length
&& items
[0].label
&& items
[0].value
) {
6593 return $.map( items
, function(item
) {
6594 if ( typeof item
=== "string" ) {
6601 label
: item
.label
|| item
.value
,
6602 value
: item
.value
|| item
.label
6607 _suggest: function( items
) {
6608 var ul
= this.menu
.element
6610 .zIndex( this.element
.zIndex() + 1 );
6611 this._renderMenu( ul
, items
);
6612 // TODO refresh should check if the active item is still in the dom, removing the need for a manual deactivate
6613 this.menu
.deactivate();
6614 this.menu
.refresh();
6616 // size and position menu
6619 ul
.position( $.extend({
6621 }, this.options
.position
));
6623 if ( this.options
.autoFocus
) {
6624 this.menu
.next( new $.Event("mouseover") );
6628 _resizeMenu: function() {
6629 var ul
= this.menu
.element
;
6630 ul
.outerWidth( Math
.max(
6631 ul
.width( "" ).outerWidth(),
6632 this.element
.outerWidth()
6636 _renderMenu: function( ul
, items
) {
6638 $.each( items
, function( index
, item
) {
6639 self
._renderItem( ul
, item
);
6643 _renderItem: function( ul
, item
) {
6644 return $( "<li></li>" )
6645 .data( "item.autocomplete", item
)
6646 .append( $( "<a></a>" ).text( item
.label
) )
6650 _move: function( direction
, event
) {
6651 if ( !this.menu
.element
.is(":visible") ) {
6652 this.search( null, event
);
6655 if ( this.menu
.first() && /^previous/.test(direction
) ||
6656 this.menu
.last() && /^next/.test(direction
) ) {
6657 this.element
.val( this.term
);
6658 this.menu
.deactivate();
6661 this.menu
[ direction
]( event
);
6664 widget: function() {
6665 return this.menu
.element
;
6669 $.extend( $.ui
.autocomplete
, {
6670 escapeRegex: function( value
) {
6671 return value
.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
6673 filter: function(array
, term
) {
6674 var matcher
= new RegExp( $.ui
.autocomplete
.escapeRegex(term
), "i" );
6675 return $.grep( array
, function(value
) {
6676 return matcher
.test( value
.label
|| value
.value
|| value
);
6684 * jQuery UI Menu (not officially released)
6686 * This widget isn't yet finished and the API is subject to change. We plan to finish
6687 * it for the next release. You're welcome to give it a try anyway and give us feedback,
6688 * as long as you're okay with migrating your code later on. We can help with that, too.
6690 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
6691 * Dual licensed under the MIT or GPL Version 2 licenses.
6692 * http://jquery.org/license
6694 * http://docs.jquery.com/UI/Menu
6698 * jquery.ui.widget.js
6702 $.widget("ui.menu", {
6703 _create: function() {
6706 .addClass("ui-menu ui-widget ui-widget-content ui-corner-all")
6709 "aria-activedescendant": "ui-active-menuitem"
6711 .click(function( event
) {
6712 if ( !$( event
.target
).closest( ".ui-menu-item a" ).length
) {
6716 event
.preventDefault();
6717 self
.select( event
);
6722 refresh: function() {
6725 // don't refresh list items that are already adapted
6726 var items
= this.element
.children("li:not(.ui-menu-item):has(a)")
6727 .addClass("ui-menu-item")
6728 .attr("role", "menuitem");
6731 .addClass("ui-corner-all")
6732 .attr("tabindex", -1)
6733 // mouseenter doesn't work with event delegation
6734 .mouseenter(function( event
) {
6735 self
.activate( event
, $(this).parent() );
6737 .mouseleave(function() {
6742 activate: function( event
, item
) {
6744 if (this.hasScroll()) {
6745 var offset
= item
.offset().top
- this.element
.offset().top
,
6746 scroll
= this.element
.scrollTop(),
6747 elementHeight
= this.element
.height();
6749 this.element
.scrollTop( scroll
+ offset
);
6750 } else if (offset
>= elementHeight
) {
6751 this.element
.scrollTop( scroll
+ offset
- elementHeight
+ item
.height());
6754 this.active
= item
.eq(0)
6756 .addClass("ui-state-hover")
6757 .attr("id", "ui-active-menuitem")
6759 this._trigger("focus", event
, { item
: item
});
6762 deactivate: function() {
6763 if (!this.active
) { return; }
6765 this.active
.children("a")
6766 .removeClass("ui-state-hover")
6768 this._trigger("blur");
6772 next: function(event
) {
6773 this.move("next", ".ui-menu-item:first", event
);
6776 previous: function(event
) {
6777 this.move("prev", ".ui-menu-item:last", event
);
6781 return this.active
&& !this.active
.prevAll(".ui-menu-item").length
;
6785 return this.active
&& !this.active
.nextAll(".ui-menu-item").length
;
6788 move: function(direction
, edge
, event
) {
6790 this.activate(event
, this.element
.children(edge
));
6793 var next
= this.active
[direction
+ "All"](".ui-menu-item").eq(0);
6795 this.activate(event
, next
);
6797 this.activate(event
, this.element
.children(edge
));
6801 // TODO merge with previousPage
6802 nextPage: function(event
) {
6803 if (this.hasScroll()) {
6804 // TODO merge with no-scroll-else
6805 if (!this.active
|| this.last()) {
6806 this.activate(event
, this.element
.children(".ui-menu-item:first"));
6809 var base
= this.active
.offset().top
,
6810 height
= this.element
.height(),
6811 result
= this.element
.children(".ui-menu-item").filter(function() {
6812 var close
= $(this).offset().top
- base
- height
+ $(this).height();
6813 // TODO improve approximation
6814 return close
< 10 && close
> -10;
6817 // TODO try to catch this earlier when scrollTop indicates the last page anyway
6818 if (!result
.length
) {
6819 result
= this.element
.children(".ui-menu-item:last");
6821 this.activate(event
, result
);
6823 this.activate(event
, this.element
.children(".ui-menu-item")
6824 .filter(!this.active
|| this.last() ? ":first" : ":last"));
6828 // TODO merge with nextPage
6829 previousPage: function(event
) {
6830 if (this.hasScroll()) {
6831 // TODO merge with no-scroll-else
6832 if (!this.active
|| this.first()) {
6833 this.activate(event
, this.element
.children(".ui-menu-item:last"));
6837 var base
= this.active
.offset().top
,
6838 height
= this.element
.height();
6839 result
= this.element
.children(".ui-menu-item").filter(function() {
6840 var close
= $(this).offset().top
- base
+ height
- $(this).height();
6841 // TODO improve approximation
6842 return close
< 10 && close
> -10;
6845 // TODO try to catch this earlier when scrollTop indicates the last page anyway
6846 if (!result
.length
) {
6847 result
= this.element
.children(".ui-menu-item:first");
6849 this.activate(event
, result
);
6851 this.activate(event
, this.element
.children(".ui-menu-item")
6852 .filter(!this.active
|| this.first() ? ":last" : ":first"));
6856 hasScroll: function() {
6857 return this.element
.height() < this.element
[ $.fn
.prop
? "prop" : "attr" ]("scrollHeight");
6860 select: function( event
) {
6861 this._trigger("selected", event
, { item
: this.active
});
6867 * jQuery UI Button 1.8.16
6869 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
6870 * Dual licensed under the MIT or GPL Version 2 licenses.
6871 * http://jquery.org/license
6873 * http://docs.jquery.com/UI/Button
6877 * jquery.ui.widget.js
6879 (function( $, undefined ) {
6881 var lastActive
, startXPos
, startYPos
, clickDragged
,
6882 baseClasses
= "ui-button ui-widget ui-state-default ui-corner-all",
6883 stateClasses
= "ui-state-hover ui-state-active ",
6884 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",
6885 formResetHandler = function() {
6886 var buttons
= $( this ).find( ":ui-button" );
6887 setTimeout(function() {
6888 buttons
.button( "refresh" );
6891 radioGroup = function( radio
) {
6892 var name
= radio
.name
,
6897 radios
= $( form
).find( "[name='" + name
+ "']" );
6899 radios
= $( "[name='" + name
+ "']", radio
.ownerDocument
)
6900 .filter(function() {
6908 $.widget( "ui.button", {
6918 _create: function() {
6919 this.element
.closest( "form" )
6920 .unbind( "reset.button" )
6921 .bind( "reset.button", formResetHandler
);
6923 if ( typeof this.options
.disabled
!== "boolean" ) {
6924 this.options
.disabled
= this.element
.propAttr( "disabled" );
6927 this._determineButtonType();
6928 this.hasTitle
= !!this.buttonElement
.attr( "title" );
6931 options
= this.options
,
6932 toggleButton
= this.type
=== "checkbox" || this.type
=== "radio",
6933 hoverClass
= "ui-state-hover" + ( !toggleButton
? " ui-state-active" : "" ),
6934 focusClass
= "ui-state-focus";
6936 if ( options
.label
=== null ) {
6937 options
.label
= this.buttonElement
.html();
6940 if ( this.element
.is( ":disabled" ) ) {
6941 options
.disabled
= true;
6945 .addClass( baseClasses
)
6946 .attr( "role", "button" )
6947 .bind( "mouseenter.button", function() {
6948 if ( options
.disabled
) {
6951 $( this ).addClass( "ui-state-hover" );
6952 if ( this === lastActive
) {
6953 $( this ).addClass( "ui-state-active" );
6956 .bind( "mouseleave.button", function() {
6957 if ( options
.disabled
) {
6960 $( this ).removeClass( hoverClass
);
6962 .bind( "click.button", function( event
) {
6963 if ( options
.disabled
) {
6964 event
.preventDefault();
6965 event
.stopImmediatePropagation();
6970 .bind( "focus.button", function() {
6971 // no need to check disabled, focus won't be triggered anyway
6972 self
.buttonElement
.addClass( focusClass
);
6974 .bind( "blur.button", function() {
6975 self
.buttonElement
.removeClass( focusClass
);
6978 if ( toggleButton
) {
6979 this.element
.bind( "change.button", function() {
6980 if ( clickDragged
) {
6985 // if mouse moves between mousedown and mouseup (drag) set clickDragged flag
6986 // prevents issue where button state changes but checkbox/radio checked state
6987 // does not in Firefox (see ticket #6970)
6989 .bind( "mousedown.button", function( event
) {
6990 if ( options
.disabled
) {
6993 clickDragged
= false;
6994 startXPos
= event
.pageX
;
6995 startYPos
= event
.pageY
;
6997 .bind( "mouseup.button", function( event
) {
6998 if ( options
.disabled
) {
7001 if ( startXPos
!== event
.pageX
|| startYPos
!== event
.pageY
) {
7002 clickDragged
= true;
7007 if ( this.type
=== "checkbox" ) {
7008 this.buttonElement
.bind( "click.button", function() {
7009 if ( options
.disabled
|| clickDragged
) {
7012 $( this ).toggleClass( "ui-state-active" );
7013 self
.buttonElement
.attr( "aria-pressed", self
.element
[0].checked
);
7015 } else if ( this.type
=== "radio" ) {
7016 this.buttonElement
.bind( "click.button", function() {
7017 if ( options
.disabled
|| clickDragged
) {
7020 $( this ).addClass( "ui-state-active" );
7021 self
.buttonElement
.attr( "aria-pressed", "true" );
7023 var radio
= self
.element
[ 0 ];
7027 return $( this ).button( "widget" )[ 0 ];
7029 .removeClass( "ui-state-active" )
7030 .attr( "aria-pressed", "false" );
7034 .bind( "mousedown.button", function() {
7035 if ( options
.disabled
) {
7038 $( this ).addClass( "ui-state-active" );
7040 $( document
).one( "mouseup", function() {
7044 .bind( "mouseup.button", function() {
7045 if ( options
.disabled
) {
7048 $( this ).removeClass( "ui-state-active" );
7050 .bind( "keydown.button", function(event
) {
7051 if ( options
.disabled
) {
7054 if ( event
.keyCode
== $.ui
.keyCode
.SPACE
|| event
.keyCode
== $.ui
.keyCode
.ENTER
) {
7055 $( this ).addClass( "ui-state-active" );
7058 .bind( "keyup.button", function() {
7059 $( this ).removeClass( "ui-state-active" );
7062 if ( this.buttonElement
.is("a") ) {
7063 this.buttonElement
.keyup(function(event
) {
7064 if ( event
.keyCode
=== $.ui
.keyCode
.SPACE
) {
7065 // TODO pass through original event correctly (just as 2nd argument doesn't work)
7072 // TODO: pull out $.Widget's handling for the disabled option into
7073 // $.Widget.prototype._setOptionDisabled so it's easy to proxy and can
7074 // be overridden by individual plugins
7075 this._setOption( "disabled", options
.disabled
);
7076 this._resetButton();
7079 _determineButtonType: function() {
7081 if ( this.element
.is(":checkbox") ) {
7082 this.type
= "checkbox";
7083 } else if ( this.element
.is(":radio") ) {
7084 this.type
= "radio";
7085 } else if ( this.element
.is("input") ) {
7086 this.type
= "input";
7088 this.type
= "button";
7091 if ( this.type
=== "checkbox" || this.type
=== "radio" ) {
7092 // we don't search against the document in case the element
7093 // is disconnected from the DOM
7094 var ancestor
= this.element
.parents().filter(":last"),
7095 labelSelector
= "label[for='" + this.element
.attr("id") + "']";
7096 this.buttonElement
= ancestor
.find( labelSelector
);
7097 if ( !this.buttonElement
.length
) {
7098 ancestor
= ancestor
.length
? ancestor
.siblings() : this.element
.siblings();
7099 this.buttonElement
= ancestor
.filter( labelSelector
);
7100 if ( !this.buttonElement
.length
) {
7101 this.buttonElement
= ancestor
.find( labelSelector
);
7104 this.element
.addClass( "ui-helper-hidden-accessible" );
7106 var checked
= this.element
.is( ":checked" );
7108 this.buttonElement
.addClass( "ui-state-active" );
7110 this.buttonElement
.attr( "aria-pressed", checked
);
7112 this.buttonElement
= this.element
;
7116 widget: function() {
7117 return this.buttonElement
;
7120 destroy: function() {
7122 .removeClass( "ui-helper-hidden-accessible" );
7124 .removeClass( baseClasses
+ " " + stateClasses
+ " " + typeClasses
)
7125 .removeAttr( "role" )
7126 .removeAttr( "aria-pressed" )
7127 .html( this.buttonElement
.find(".ui-button-text").html() );
7129 if ( !this.hasTitle
) {
7130 this.buttonElement
.removeAttr( "title" );
7133 $.Widget
.prototype.destroy
.call( this );
7136 _setOption: function( key
, value
) {
7137 $.Widget
.prototype._setOption
.apply( this, arguments
);
7138 if ( key
=== "disabled" ) {
7140 this.element
.propAttr( "disabled", true );
7142 this.element
.propAttr( "disabled", false );
7146 this._resetButton();
7149 refresh: function() {
7150 var isDisabled
= this.element
.is( ":disabled" );
7151 if ( isDisabled
!== this.options
.disabled
) {
7152 this._setOption( "disabled", isDisabled
);
7154 if ( this.type
=== "radio" ) {
7155 radioGroup( this.element
[0] ).each(function() {
7156 if ( $( this ).is( ":checked" ) ) {
7157 $( this ).button( "widget" )
7158 .addClass( "ui-state-active" )
7159 .attr( "aria-pressed", "true" );
7161 $( this ).button( "widget" )
7162 .removeClass( "ui-state-active" )
7163 .attr( "aria-pressed", "false" );
7166 } else if ( this.type
=== "checkbox" ) {
7167 if ( this.element
.is( ":checked" ) ) {
7169 .addClass( "ui-state-active" )
7170 .attr( "aria-pressed", "true" );
7173 .removeClass( "ui-state-active" )
7174 .attr( "aria-pressed", "false" );
7179 _resetButton: function() {
7180 if ( this.type
=== "input" ) {
7181 if ( this.options
.label
) {
7182 this.element
.val( this.options
.label
);
7186 var buttonElement
= this.buttonElement
.removeClass( typeClasses
),
7187 buttonText
= $( "<span></span>" )
7188 .addClass( "ui-button-text" )
7189 .html( this.options
.label
)
7190 .appendTo( buttonElement
.empty() )
7192 icons
= this.options
.icons
,
7193 multipleIcons
= icons
.primary
&& icons
.secondary
,
7196 if ( icons
.primary
|| icons
.secondary
) {
7197 if ( this.options
.text
) {
7198 buttonClasses
.push( "ui-button-text-icon" + ( multipleIcons
? "s" : ( icons
.primary
? "-primary" : "-secondary" ) ) );
7201 if ( icons
.primary
) {
7202 buttonElement
.prepend( "<span class='ui-button-icon-primary ui-icon " + icons
.primary
+ "'></span>" );
7205 if ( icons
.secondary
) {
7206 buttonElement
.append( "<span class='ui-button-icon-secondary ui-icon " + icons
.secondary
+ "'></span>" );
7209 if ( !this.options
.text
) {
7210 buttonClasses
.push( multipleIcons
? "ui-button-icons-only" : "ui-button-icon-only" );
7212 if ( !this.hasTitle
) {
7213 buttonElement
.attr( "title", buttonText
);
7217 buttonClasses
.push( "ui-button-text-only" );
7219 buttonElement
.addClass( buttonClasses
.join( " " ) );
7223 $.widget( "ui.buttonset", {
7225 items
: ":button, :submit, :reset, :checkbox, :radio, a, :data(button)"
7228 _create: function() {
7229 this.element
.addClass( "ui-buttonset" );
7236 _setOption: function( key
, value
) {
7237 if ( key
=== "disabled" ) {
7238 this.buttons
.button( "option", key
, value
);
7241 $.Widget
.prototype._setOption
.apply( this, arguments
);
7244 refresh: function() {
7245 var ltr
= this.element
.css( "direction" ) === "ltr";
7247 this.buttons
= this.element
.find( this.options
.items
)
7248 .filter( ":ui-button" )
7249 .button( "refresh" )
7251 .not( ":ui-button" )
7255 return $( this ).button( "widget" )[ 0 ];
7257 .removeClass( "ui-corner-all ui-corner-left ui-corner-right" )
7259 .addClass( ltr
? "ui-corner-left" : "ui-corner-right" )
7262 .addClass( ltr
? "ui-corner-right" : "ui-corner-left" )
7267 destroy: function() {
7268 this.element
.removeClass( "ui-buttonset" );
7271 return $( this ).button( "widget" )[ 0 ];
7273 .removeClass( "ui-corner-left ui-corner-right" )
7275 .button( "destroy" );
7277 $.Widget
.prototype.destroy
.call( this );
7283 * jQuery UI Datepicker 1.8.16
7285 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
7286 * Dual licensed under the MIT or GPL Version 2 licenses.
7287 * http://jquery.org/license
7289 * http://docs.jquery.com/UI/Datepicker
7294 (function( $, undefined ) {
7296 $.extend($.ui
, { datepicker
: { version
: "1.8.16" } });
7298 var PROP_NAME
= 'datepicker';
7299 var dpuuid
= new Date().getTime();
7302 /* Date picker manager.
7303 Use the singleton instance of this class, $.datepicker, to interact with the date picker.
7304 Settings for (groups of) date pickers are maintained in an instance object,
7305 allowing multiple different settings on the same page. */
7307 function Datepicker() {
7308 this.debug
= false; // Change this to true to start debugging
7309 this._curInst
= null; // The current instance in use
7310 this._keyEvent
= false; // If the last event was a key event
7311 this._disabledInputs
= []; // List of date picker inputs that have been disabled
7312 this._datepickerShowing
= false; // True if the popup picker is showing , false if not
7313 this._inDialog
= false; // True if showing within a "dialog", false if not
7314 this._mainDivId
= 'ui-datepicker-div'; // The ID of the main datepicker division
7315 this._inlineClass
= 'ui-datepicker-inline'; // The name of the inline marker class
7316 this._appendClass
= 'ui-datepicker-append'; // The name of the append marker class
7317 this._triggerClass
= 'ui-datepicker-trigger'; // The name of the trigger marker class
7318 this._dialogClass
= 'ui-datepicker-dialog'; // The name of the dialog marker class
7319 this._disableClass
= 'ui-datepicker-disabled'; // The name of the disabled covering marker class
7320 this._unselectableClass
= 'ui-datepicker-unselectable'; // The name of the unselectable cell marker class
7321 this._currentClass
= 'ui-datepicker-current-day'; // The name of the current day marker class
7322 this._dayOverClass
= 'ui-datepicker-days-cell-over'; // The name of the day hover marker class
7323 this.regional
= []; // Available regional settings, indexed by language code
7324 this.regional
[''] = { // Default regional settings
7325 closeText
: 'Done', // Display text for close link
7326 prevText
: 'Prev', // Display text for previous month link
7327 nextText
: 'Next', // Display text for next month link
7328 currentText
: 'Today', // Display text for current month link
7329 monthNames
: ['January','February','March','April','May','June',
7330 'July','August','September','October','November','December'], // Names of months for drop-down and formatting
7331 monthNamesShort
: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], // For formatting
7332 dayNames
: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], // For formatting
7333 dayNamesShort
: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], // For formatting
7334 dayNamesMin
: ['Su','Mo','Tu','We','Th','Fr','Sa'], // Column headings for days starting at Sunday
7335 weekHeader
: 'Wk', // Column header for week of the year
7336 dateFormat
: 'mm/dd/yy', // See format options on parseDate
7337 firstDay
: 0, // The first day of the week, Sun = 0, Mon = 1, ...
7338 isRTL
: false, // True if right-to-left language, false if left-to-right
7339 showMonthAfterYear
: false, // True if the year select precedes month, false for month then year
7340 yearSuffix
: '' // Additional text to append to the year in the month headers
7342 this._defaults
= { // Global defaults for all the date picker instances
7343 showOn
: 'focus', // 'focus' for popup on focus,
7344 // 'button' for trigger button, or 'both' for either
7345 showAnim
: 'fadeIn', // Name of jQuery animation for popup
7346 showOptions
: {}, // Options for enhanced animations
7347 defaultDate
: null, // Used when field is blank: actual date,
7348 // +/-number for offset from today, null for today
7349 appendText
: '', // Display text following the input box, e.g. showing the format
7350 buttonText
: '...', // Text for trigger button
7351 buttonImage
: '', // URL for trigger button image
7352 buttonImageOnly
: false, // True if the image appears alone, false if it appears on a button
7353 hideIfNoPrevNext
: false, // True to hide next/previous month links
7354 // if not applicable, false to just disable them
7355 navigationAsDateFormat
: false, // True if date formatting applied to prev/today/next links
7356 gotoCurrent
: false, // True if today link goes back to current selection instead
7357 changeMonth
: false, // True if month can be selected directly, false if only prev/next
7358 changeYear
: false, // True if year can be selected directly, false if only prev/next
7359 yearRange
: 'c-10:c+10', // Range of years to display in drop-down,
7360 // either relative to today's year (-nn:+nn), relative to currently displayed year
7361 // (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
7362 showOtherMonths
: false, // True to show dates in other months, false to leave blank
7363 selectOtherMonths
: false, // True to allow selection of dates in other months, false for unselectable
7364 showWeek
: false, // True to show week of the year, false to not show it
7365 calculateWeek
: this.iso8601Week
, // How to calculate the week of the year,
7366 // takes a Date and returns the number of the week for it
7367 shortYearCutoff
: '+10', // Short year values < this are in the current century,
7368 // > this are in the previous century,
7369 // string value starting with '+' for current year + value
7370 minDate
: null, // The earliest selectable date, or null for no limit
7371 maxDate
: null, // The latest selectable date, or null for no limit
7372 duration
: 'fast', // Duration of display/closure
7373 beforeShowDay
: null, // Function that takes a date and returns an array with
7374 // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or '',
7375 // [2] = cell title (optional), e.g. $.datepicker.noWeekends
7376 beforeShow
: null, // Function that takes an input field and
7377 // returns a set of custom settings for the date picker
7378 onSelect
: null, // Define a callback function when a date is selected
7379 onChangeMonthYear
: null, // Define a callback function when the month or year is changed
7380 onClose
: null, // Define a callback function when the datepicker is closed
7381 numberOfMonths
: 1, // Number of months to show at a time
7382 showCurrentAtPos
: 0, // The position in multipe months at which to show the current month (starting at 0)
7383 stepMonths
: 1, // Number of months to step back/forward
7384 stepBigMonths
: 12, // Number of months to step back/forward for the big links
7385 altField
: '', // Selector for an alternate field to store selected dates into
7386 altFormat
: '', // The date format to use for the alternate field
7387 constrainInput
: true, // The input is constrained by the current date format
7388 showButtonPanel
: false, // True to show button panel, false to not show it
7389 autoSize
: false, // True to size the input for the date format, false to leave as is
7390 disabled
: false // The initial disabled state
7392 $.extend(this._defaults
, this.regional
['']);
7393 this.dpDiv
= bindHover($('<div id="' + this._mainDivId
+ '" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>'));
7396 $.extend(Datepicker
.prototype, {
7397 /* Class name added to elements to indicate already configured with a date picker. */
7398 markerClassName
: 'hasDatepicker',
7400 //Keep track of the maximum number of rows displayed (see #7043)
7403 /* Debug logging (if enabled). */
7406 console
.log
.apply('', arguments
);
7409 // TODO rename to "widget" when switching to widget factory
7410 _widgetDatepicker: function() {
7414 /* Override the default settings for all instances of the date picker.
7415 @param settings object - the new settings to use as defaults (anonymous object)
7416 @return the manager object */
7417 setDefaults: function(settings
) {
7418 extendRemove(this._defaults
, settings
|| {});
7422 /* Attach the date picker to a jQuery selection.
7423 @param target element - the target input field or division or span
7424 @param settings object - the new settings to use for this date picker instance (anonymous) */
7425 _attachDatepicker: function(target
, settings
) {
7426 // check for settings on the control itself - in namespace 'date:'
7427 var inlineSettings
= null;
7428 for (var attrName
in this._defaults
) {
7429 var attrValue
= target
.getAttribute('date:' + attrName
);
7431 inlineSettings
= inlineSettings
|| {};
7433 inlineSettings
[attrName
] = eval(attrValue
);
7435 inlineSettings
[attrName
] = attrValue
;
7439 var nodeName
= target
.nodeName
.toLowerCase();
7440 var inline
= (nodeName
== 'div' || nodeName
== 'span');
7443 target
.id
= 'dp' + this.uuid
;
7445 var inst
= this._newInst($(target
), inline
);
7446 inst
.settings
= $.extend({}, settings
|| {}, inlineSettings
|| {});
7447 if (nodeName
== 'input') {
7448 this._connectDatepicker(target
, inst
);
7449 } else if (inline
) {
7450 this._inlineDatepicker(target
, inst
);
7454 /* Create a new instance object. */
7455 _newInst: function(target
, inline
) {
7456 var id
= target
[0].id
.replace(/([^A-Za-z0-9_-])/g, '\\\\$1'); // escape jQuery meta chars
7457 return {id
: id
, input
: target
, // associated target
7458 selectedDay
: 0, selectedMonth
: 0, selectedYear
: 0, // current selection
7459 drawMonth
: 0, drawYear
: 0, // month being drawn
7460 inline
: inline
, // is datepicker inline or not
7461 dpDiv
: (!inline
? this.dpDiv
: // presentation div
7462 bindHover($('<div class="' + this._inlineClass
+ ' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>')))};
7465 /* Attach the date picker to an input field. */
7466 _connectDatepicker: function(target
, inst
) {
7467 var input
= $(target
);
7468 inst
.append
= $([]);
7469 inst
.trigger
= $([]);
7470 if (input
.hasClass(this.markerClassName
))
7472 this._attachments(input
, inst
);
7473 input
.addClass(this.markerClassName
).keydown(this._doKeyDown
).
7474 keypress(this._doKeyPress
).keyup(this._doKeyUp
).
7475 bind("setData.datepicker", function(event
, key
, value
) {
7476 inst
.settings
[key
] = value
;
7477 }).bind("getData.datepicker", function(event
, key
) {
7478 return this._get(inst
, key
);
7480 this._autoSize(inst
);
7481 $.data(target
, PROP_NAME
, inst
);
7482 //If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665)
7483 if( inst
.settings
.disabled
) {
7484 this._disableDatepicker( target
);
7488 /* Make attachments based on settings. */
7489 _attachments: function(input
, inst
) {
7490 var appendText
= this._get(inst
, 'appendText');
7491 var isRTL
= this._get(inst
, 'isRTL');
7493 inst
.append
.remove();
7495 inst
.append
= $('<span class="' + this._appendClass
+ '">' + appendText
+ '</span>');
7496 input
[isRTL
? 'before' : 'after'](inst
.append
);
7498 input
.unbind('focus', this._showDatepicker
);
7500 inst
.trigger
.remove();
7501 var showOn
= this._get(inst
, 'showOn');
7502 if (showOn
== 'focus' || showOn
== 'both') // pop-up date picker when in the marked field
7503 input
.focus(this._showDatepicker
);
7504 if (showOn
== 'button' || showOn
== 'both') { // pop-up date picker when button clicked
7505 var buttonText
= this._get(inst
, 'buttonText');
7506 var buttonImage
= this._get(inst
, 'buttonImage');
7507 inst
.trigger
= $(this._get(inst
, 'buttonImageOnly') ?
7508 $('<img/>').addClass(this._triggerClass
).
7509 attr({ src
: buttonImage
, alt
: buttonText
, title
: buttonText
}) :
7510 $('<button type="button"></button>').addClass(this._triggerClass
).
7511 html(buttonImage
== '' ? buttonText
: $('<img/>').attr(
7512 { src
:buttonImage
, alt
:buttonText
, title
:buttonText
})));
7513 input
[isRTL
? 'before' : 'after'](inst
.trigger
);
7514 inst
.trigger
.click(function() {
7515 if ($.datepicker
._datepickerShowing
&& $.datepicker
._lastInput
== input
[0])
7516 $.datepicker
._hideDatepicker();
7518 $.datepicker
._showDatepicker(input
[0]);
7524 /* Apply the maximum length for the date format. */
7525 _autoSize: function(inst
) {
7526 if (this._get(inst
, 'autoSize') && !inst
.inline
) {
7527 var date
= new Date(2009, 12 - 1, 20); // Ensure double digits
7528 var dateFormat
= this._get(inst
, 'dateFormat');
7529 if (dateFormat
.match(/[DM]/)) {
7530 var findMax = function(names
) {
7533 for (var i
= 0; i
< names
.length
; i
++) {
7534 if (names
[i
].length
> max
) {
7535 max
= names
[i
].length
;
7541 date
.setMonth(findMax(this._get(inst
, (dateFormat
.match(/MM/) ?
7542 'monthNames' : 'monthNamesShort'))));
7543 date
.setDate(findMax(this._get(inst
, (dateFormat
.match(/DD/) ?
7544 'dayNames' : 'dayNamesShort'))) + 20 - date
.getDay());
7546 inst
.input
.attr('size', this._formatDate(inst
, date
).length
);
7550 /* Attach an inline date picker to a div. */
7551 _inlineDatepicker: function(target
, inst
) {
7552 var divSpan
= $(target
);
7553 if (divSpan
.hasClass(this.markerClassName
))
7555 divSpan
.addClass(this.markerClassName
).append(inst
.dpDiv
).
7556 bind("setData.datepicker", function(event
, key
, value
){
7557 inst
.settings
[key
] = value
;
7558 }).bind("getData.datepicker", function(event
, key
){
7559 return this._get(inst
, key
);
7561 $.data(target
, PROP_NAME
, inst
);
7562 this._setDate(inst
, this._getDefaultDate(inst
), true);
7563 this._updateDatepicker(inst
);
7564 this._updateAlternate(inst
);
7565 //If disabled option is true, disable the datepicker before showing it (see ticket #5665)
7566 if( inst
.settings
.disabled
) {
7567 this._disableDatepicker( target
);
7569 // Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements
7570 // http://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height
7571 inst
.dpDiv
.css( "display", "block" );
7574 /* Pop-up the date picker in a "dialog" box.
7575 @param input element - ignored
7576 @param date string or Date - the initial date to display
7577 @param onSelect function - the function to call when a date is selected
7578 @param settings object - update the dialog date picker instance's settings (anonymous object)
7579 @param pos int[2] - coordinates for the dialog's position within the screen or
7580 event - with x/y coordinates or
7581 leave empty for default (screen centre)
7582 @return the manager object */
7583 _dialogDatepicker: function(input
, date
, onSelect
, settings
, pos
) {
7584 var inst
= this._dialogInst
; // internal instance
7587 var id
= 'dp' + this.uuid
;
7588 this._dialogInput
= $('<input type="text" id="' + id
+
7589 '" style="position: absolute; top: -100px; width: 0px; z-index: -10;"/>');
7590 this._dialogInput
.keydown(this._doKeyDown
);
7591 $('body').append(this._dialogInput
);
7592 inst
= this._dialogInst
= this._newInst(this._dialogInput
, false);
7594 $.data(this._dialogInput
[0], PROP_NAME
, inst
);
7596 extendRemove(inst
.settings
, settings
|| {});
7597 date
= (date
&& date
.constructor == Date
? this._formatDate(inst
, date
) : date
);
7598 this._dialogInput
.val(date
);
7600 this._pos
= (pos
? (pos
.length
? pos
: [pos
.pageX
, pos
.pageY
]) : null);
7602 var browserWidth
= document
.documentElement
.clientWidth
;
7603 var browserHeight
= document
.documentElement
.clientHeight
;
7604 var scrollX
= document
.documentElement
.scrollLeft
|| document
.body
.scrollLeft
;
7605 var scrollY
= document
.documentElement
.scrollTop
|| document
.body
.scrollTop
;
7606 this._pos
= // should use actual width/height below
7607 [(browserWidth
/ 2) - 100 + scrollX
, (browserHeight
/ 2) - 150 + scrollY
];
7610 // move input on screen for focus, but hidden behind dialog
7611 this._dialogInput
.css('left', (this._pos
[0] + 20) + 'px').css('top', this._pos
[1] + 'px');
7612 inst
.settings
.onSelect
= onSelect
;
7613 this._inDialog
= true;
7614 this.dpDiv
.addClass(this._dialogClass
);
7615 this._showDatepicker(this._dialogInput
[0]);
7617 $.blockUI(this.dpDiv
);
7618 $.data(this._dialogInput
[0], PROP_NAME
, inst
);
7622 /* Detach a datepicker from its control.
7623 @param target element - the target input field or division or span */
7624 _destroyDatepicker: function(target
) {
7625 var $target
= $(target
);
7626 var inst
= $.data(target
, PROP_NAME
);
7627 if (!$target
.hasClass(this.markerClassName
)) {
7630 var nodeName
= target
.nodeName
.toLowerCase();
7631 $.removeData(target
, PROP_NAME
);
7632 if (nodeName
== 'input') {
7633 inst
.append
.remove();
7634 inst
.trigger
.remove();
7635 $target
.removeClass(this.markerClassName
).
7636 unbind('focus', this._showDatepicker
).
7637 unbind('keydown', this._doKeyDown
).
7638 unbind('keypress', this._doKeyPress
).
7639 unbind('keyup', this._doKeyUp
);
7640 } else if (nodeName
== 'div' || nodeName
== 'span')
7641 $target
.removeClass(this.markerClassName
).empty();
7644 /* Enable the date picker to a jQuery selection.
7645 @param target element - the target input field or division or span */
7646 _enableDatepicker: function(target
) {
7647 var $target
= $(target
);
7648 var inst
= $.data(target
, PROP_NAME
);
7649 if (!$target
.hasClass(this.markerClassName
)) {
7652 var nodeName
= target
.nodeName
.toLowerCase();
7653 if (nodeName
== 'input') {
7654 target
.disabled
= false;
7655 inst
.trigger
.filter('button').
7656 each(function() { this.disabled
= false; }).end().
7657 filter('img').css({opacity
: '1.0', cursor
: ''});
7659 else if (nodeName
== 'div' || nodeName
== 'span') {
7660 var inline
= $target
.children('.' + this._inlineClass
);
7661 inline
.children().removeClass('ui-state-disabled');
7662 inline
.find("select.ui-datepicker-month, select.ui-datepicker-year").
7663 removeAttr("disabled");
7665 this._disabledInputs
= $.map(this._disabledInputs
,
7666 function(value
) { return (value
== target
? null : value
); }); // delete entry
7669 /* Disable the date picker to a jQuery selection.
7670 @param target element - the target input field or division or span */
7671 _disableDatepicker: function(target
) {
7672 var $target
= $(target
);
7673 var inst
= $.data(target
, PROP_NAME
);
7674 if (!$target
.hasClass(this.markerClassName
)) {
7677 var nodeName
= target
.nodeName
.toLowerCase();
7678 if (nodeName
== 'input') {
7679 target
.disabled
= true;
7680 inst
.trigger
.filter('button').
7681 each(function() { this.disabled
= true; }).end().
7682 filter('img').css({opacity
: '0.5', cursor
: 'default'});
7684 else if (nodeName
== 'div' || nodeName
== 'span') {
7685 var inline
= $target
.children('.' + this._inlineClass
);
7686 inline
.children().addClass('ui-state-disabled');
7687 inline
.find("select.ui-datepicker-month, select.ui-datepicker-year").
7688 attr("disabled", "disabled");
7690 this._disabledInputs
= $.map(this._disabledInputs
,
7691 function(value
) { return (value
== target
? null : value
); }); // delete entry
7692 this._disabledInputs
[this._disabledInputs
.length
] = target
;
7695 /* Is the first field in a jQuery collection disabled as a datepicker?
7696 @param target element - the target input field or division or span
7697 @return boolean - true if disabled, false if enabled */
7698 _isDisabledDatepicker: function(target
) {
7702 for (var i
= 0; i
< this._disabledInputs
.length
; i
++) {
7703 if (this._disabledInputs
[i
] == target
)
7709 /* Retrieve the instance data for the target control.
7710 @param target element - the target input field or division or span
7711 @return object - the associated instance data
7712 @throws error if a jQuery problem getting data */
7713 _getInst: function(target
) {
7715 return $.data(target
, PROP_NAME
);
7718 throw 'Missing instance data for this datepicker';
7722 /* Update or retrieve the settings for a date picker attached to an input field or division.
7723 @param target element - the target input field or division or span
7724 @param name object - the new settings to update or
7725 string - the name of the setting to change or retrieve,
7726 when retrieving also 'all' for all instance settings or
7727 'defaults' for all global defaults
7728 @param value any - the new value for the setting
7729 (omit if above is an object or to retrieve a value) */
7730 _optionDatepicker: function(target
, name
, value
) {
7731 var inst
= this._getInst(target
);
7732 if (arguments
.length
== 2 && typeof name
== 'string') {
7733 return (name
== 'defaults' ? $.extend({}, $.datepicker
._defaults
) :
7734 (inst
? (name
== 'all' ? $.extend({}, inst
.settings
) :
7735 this._get(inst
, name
)) : null));
7737 var settings
= name
|| {};
7738 if (typeof name
== 'string') {
7740 settings
[name
] = value
;
7743 if (this._curInst
== inst
) {
7744 this._hideDatepicker();
7746 var date
= this._getDateDatepicker(target
, true);
7747 var minDate
= this._getMinMaxDate(inst
, 'min');
7748 var maxDate
= this._getMinMaxDate(inst
, 'max');
7749 extendRemove(inst
.settings
, settings
);
7750 // reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided
7751 if (minDate
!== null && settings
['dateFormat'] !== undefined && settings
['minDate'] === undefined)
7752 inst
.settings
.minDate
= this._formatDate(inst
, minDate
);
7753 if (maxDate
!== null && settings
['dateFormat'] !== undefined && settings
['maxDate'] === undefined)
7754 inst
.settings
.maxDate
= this._formatDate(inst
, maxDate
);
7755 this._attachments($(target
), inst
);
7756 this._autoSize(inst
);
7757 this._setDate(inst
, date
);
7758 this._updateAlternate(inst
);
7759 this._updateDatepicker(inst
);
7763 // change method deprecated
7764 _changeDatepicker: function(target
, name
, value
) {
7765 this._optionDatepicker(target
, name
, value
);
7768 /* Redraw the date picker attached to an input field or division.
7769 @param target element - the target input field or division or span */
7770 _refreshDatepicker: function(target
) {
7771 var inst
= this._getInst(target
);
7773 this._updateDatepicker(inst
);
7777 /* Set the dates for a jQuery selection.
7778 @param target element - the target input field or division or span
7779 @param date Date - the new date */
7780 _setDateDatepicker: function(target
, date
) {
7781 var inst
= this._getInst(target
);
7783 this._setDate(inst
, date
);
7784 this._updateDatepicker(inst
);
7785 this._updateAlternate(inst
);
7789 /* Get the date(s) for the first entry in a jQuery selection.
7790 @param target element - the target input field or division or span
7791 @param noDefault boolean - true if no default date is to be used
7792 @return Date - the current date */
7793 _getDateDatepicker: function(target
, noDefault
) {
7794 var inst
= this._getInst(target
);
7795 if (inst
&& !inst
.inline
)
7796 this._setDateFromField(inst
, noDefault
);
7797 return (inst
? this._getDate(inst
) : null);
7800 /* Handle keystrokes. */
7801 _doKeyDown: function(event
) {
7802 var inst
= $.datepicker
._getInst(event
.target
);
7804 var isRTL
= inst
.dpDiv
.is('.ui-datepicker-rtl');
7805 inst
._keyEvent
= true;
7806 if ($.datepicker
._datepickerShowing
)
7807 switch (event
.keyCode
) {
7808 case 9: $.datepicker
._hideDatepicker();
7810 break; // hide on tab out
7811 case 13: var sel
= $('td.' + $.datepicker
._dayOverClass
+ ':not(.' +
7812 $.datepicker
._currentClass
+ ')', inst
.dpDiv
);
7814 $.datepicker
._selectDay(event
.target
, inst
.selectedMonth
, inst
.selectedYear
, sel
[0]);
7815 var onSelect
= $.datepicker
._get(inst
, 'onSelect');
7817 var dateStr
= $.datepicker
._formatDate(inst
);
7819 // trigger custom callback
7820 onSelect
.apply((inst
.input
? inst
.input
[0] : null), [dateStr
, inst
]);
7823 $.datepicker
._hideDatepicker();
7824 return false; // don't submit the form
7825 break; // select the value on enter
7826 case 27: $.datepicker
._hideDatepicker();
7827 break; // hide on escape
7828 case 33: $.datepicker
._adjustDate(event
.target
, (event
.ctrlKey
?
7829 -$.datepicker
._get(inst
, 'stepBigMonths') :
7830 -$.datepicker
._get(inst
, 'stepMonths')), 'M');
7831 break; // previous month/year on page up/+ ctrl
7832 case 34: $.datepicker
._adjustDate(event
.target
, (event
.ctrlKey
?
7833 +$.datepicker
._get(inst
, 'stepBigMonths') :
7834 +$.datepicker
._get(inst
, 'stepMonths')), 'M');
7835 break; // next month/year on page down/+ ctrl
7836 case 35: if (event
.ctrlKey
|| event
.metaKey
) $.datepicker
._clearDate(event
.target
);
7837 handled
= event
.ctrlKey
|| event
.metaKey
;
7838 break; // clear on ctrl or command +end
7839 case 36: if (event
.ctrlKey
|| event
.metaKey
) $.datepicker
._gotoToday(event
.target
);
7840 handled
= event
.ctrlKey
|| event
.metaKey
;
7841 break; // current on ctrl or command +home
7842 case 37: if (event
.ctrlKey
|| event
.metaKey
) $.datepicker
._adjustDate(event
.target
, (isRTL
? +1 : -1), 'D');
7843 handled
= event
.ctrlKey
|| event
.metaKey
;
7844 // -1 day on ctrl or command +left
7845 if (event
.originalEvent
.altKey
) $.datepicker
._adjustDate(event
.target
, (event
.ctrlKey
?
7846 -$.datepicker
._get(inst
, 'stepBigMonths') :
7847 -$.datepicker
._get(inst
, 'stepMonths')), 'M');
7848 // next month/year on alt +left on Mac
7850 case 38: if (event
.ctrlKey
|| event
.metaKey
) $.datepicker
._adjustDate(event
.target
, -7, 'D');
7851 handled
= event
.ctrlKey
|| event
.metaKey
;
7852 break; // -1 week on ctrl or command +up
7853 case 39: if (event
.ctrlKey
|| event
.metaKey
) $.datepicker
._adjustDate(event
.target
, (isRTL
? -1 : +1), 'D');
7854 handled
= event
.ctrlKey
|| event
.metaKey
;
7855 // +1 day on ctrl or command +right
7856 if (event
.originalEvent
.altKey
) $.datepicker
._adjustDate(event
.target
, (event
.ctrlKey
?
7857 +$.datepicker
._get(inst
, 'stepBigMonths') :
7858 +$.datepicker
._get(inst
, 'stepMonths')), 'M');
7859 // next month/year on alt +right
7861 case 40: if (event
.ctrlKey
|| event
.metaKey
) $.datepicker
._adjustDate(event
.target
, +7, 'D');
7862 handled
= event
.ctrlKey
|| event
.metaKey
;
7863 break; // +1 week on ctrl or command +down
7864 default: handled
= false;
7866 else if (event
.keyCode
== 36 && event
.ctrlKey
) // display the date picker on ctrl+home
7867 $.datepicker
._showDatepicker(this);
7872 event
.preventDefault();
7873 event
.stopPropagation();
7877 /* Filter entered characters - based on date format. */
7878 _doKeyPress: function(event
) {
7879 var inst
= $.datepicker
._getInst(event
.target
);
7880 if ($.datepicker
._get(inst
, 'constrainInput')) {
7881 var chars
= $.datepicker
._possibleChars($.datepicker
._get(inst
, 'dateFormat'));
7882 var chr
= String
.fromCharCode(event
.charCode
== undefined ? event
.keyCode
: event
.charCode
);
7883 return event
.ctrlKey
|| event
.metaKey
|| (chr
< ' ' || !chars
|| chars
.indexOf(chr
) > -1);
7887 /* Synchronise manual entry and field/alternate field. */
7888 _doKeyUp: function(event) {
7889 var inst = $.datepicker._getInst(event.target);
7890 if (inst.input.val() != inst.lastVal) {
7892 var date = $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
7893 (inst.input ? inst.input.val() : null),
7894 $.datepicker._getFormatConfig(inst));
7895 if (date) { // only if valid
7896 $.datepicker._setDateFromField(inst);
7897 $.datepicker._updateAlternate(inst);
7898 $.datepicker._updateDatepicker(inst);
7902 $.datepicker.log(event);
7908 /* Pop-up the date picker for a given input field.
7909 If false returned from beforeShow event handler do not show.
7910 @param input element - the input field attached to the date picker or
7911 event - if triggered by focus */
7912 _showDatepicker: function(input
) {
7913 input
= input
.target
|| input
;
7914 if (input
.nodeName
.toLowerCase() != 'input') // find from button/image trigger
7915 input
= $('input', input
.parentNode
)[0];
7916 if ($.datepicker
._isDisabledDatepicker(input
) || $.datepicker
._lastInput
== input
) // already here
7918 var inst
= $.datepicker
._getInst(input
);
7919 if ($.datepicker
._curInst
&& $.datepicker
._curInst
!= inst
) {
7920 if ( $.datepicker
._datepickerShowing
) {
7921 $.datepicker
._triggerOnClose($.datepicker
._curInst
);
7923 $.datepicker
._curInst
.dpDiv
.stop(true, true);
7925 var beforeShow
= $.datepicker
._get(inst
, 'beforeShow');
7926 var beforeShowSettings
= beforeShow
? beforeShow
.apply(input
, [input
, inst
]) : {};
7927 if(beforeShowSettings
=== false){
7931 extendRemove(inst
.settings
, beforeShowSettings
);
7932 inst
.lastVal
= null;
7933 $.datepicker
._lastInput
= input
;
7934 $.datepicker
._setDateFromField(inst
);
7935 if ($.datepicker
._inDialog
) // hide cursor
7937 if (!$.datepicker
._pos
) { // position below input
7938 $.datepicker
._pos
= $.datepicker
._findPos(input
);
7939 $.datepicker
._pos
[1] += input
.offsetHeight
; // add the height
7941 var isFixed
= false;
7942 $(input
).parents().each(function() {
7943 isFixed
|= $(this).css('position') == 'fixed';
7946 if (isFixed
&& $.browser
.opera
) { // correction for Opera when fixed and scrolled
7947 $.datepicker
._pos
[0] -= document
.documentElement
.scrollLeft
;
7948 $.datepicker
._pos
[1] -= document
.documentElement
.scrollTop
;
7950 var offset
= {left
: $.datepicker
._pos
[0], top
: $.datepicker
._pos
[1]};
7951 $.datepicker
._pos
= null;
7952 //to avoid flashes on Firefox
7954 // determine sizing offscreen
7955 inst
.dpDiv
.css({position
: 'absolute', display
: 'block', top
: '-1000px'});
7956 $.datepicker
._updateDatepicker(inst
);
7957 // fix width for dynamic number of date pickers
7958 // and adjust position before showing
7959 offset
= $.datepicker
._checkOffset(inst
, offset
, isFixed
);
7960 inst
.dpDiv
.css({position
: ($.datepicker
._inDialog
&& $.blockUI
?
7961 'static' : (isFixed
? 'fixed' : 'absolute')), display
: 'none',
7962 left
: offset
.left
+ 'px', top
: offset
.top
+ 'px'});
7964 var showAnim
= $.datepicker
._get(inst
, 'showAnim');
7965 var duration
= $.datepicker
._get(inst
, 'duration');
7966 var postProcess = function() {
7967 var cover
= inst
.dpDiv
.find('iframe.ui-datepicker-cover'); // IE6- only
7968 if( !! cover
.length
){
7969 var borders
= $.datepicker
._getBorders(inst
.dpDiv
);
7970 cover
.css({left
: -borders
[0], top
: -borders
[1],
7971 width
: inst
.dpDiv
.outerWidth(), height
: inst
.dpDiv
.outerHeight()});
7974 inst
.dpDiv
.zIndex($(input
).zIndex()+1);
7975 $.datepicker
._datepickerShowing
= true;
7976 if ($.effects
&& $.effects
[showAnim
])
7977 inst
.dpDiv
.show(showAnim
, $.datepicker
._get(inst
, 'showOptions'), duration
, postProcess
);
7979 inst
.dpDiv
[showAnim
|| 'show']((showAnim
? duration
: null), postProcess
);
7980 if (!showAnim
|| !duration
)
7982 if (inst
.input
.is(':visible') && !inst
.input
.is(':disabled'))
7984 $.datepicker
._curInst
= inst
;
7988 /* Generate the date picker content. */
7989 _updateDatepicker: function(inst
) {
7991 self
.maxRows
= 4; //Reset the max number of rows being displayed (see #7043)
7992 var borders
= $.datepicker
._getBorders(inst
.dpDiv
);
7993 instActive
= inst
; // for delegate hover events
7994 inst
.dpDiv
.empty().append(this._generateHTML(inst
));
7995 var cover
= inst
.dpDiv
.find('iframe.ui-datepicker-cover'); // IE6- only
7996 if( !!cover
.length
){ //avoid call to outerXXXX() when not in IE6
7997 cover
.css({left
: -borders
[0], top
: -borders
[1], width
: inst
.dpDiv
.outerWidth(), height
: inst
.dpDiv
.outerHeight()})
7999 inst
.dpDiv
.find('.' + this._dayOverClass
+ ' a').mouseover();
8000 var numMonths
= this._getNumberOfMonths(inst
);
8001 var cols
= numMonths
[1];
8003 inst
.dpDiv
.removeClass('ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4').width('');
8005 inst
.dpDiv
.addClass('ui-datepicker-multi-' + cols
).css('width', (width
* cols
) + 'em');
8006 inst
.dpDiv
[(numMonths
[0] != 1 || numMonths
[1] != 1 ? 'add' : 'remove') +
8007 'Class']('ui-datepicker-multi');
8008 inst
.dpDiv
[(this._get(inst
, 'isRTL') ? 'add' : 'remove') +
8009 'Class']('ui-datepicker-rtl');
8010 if (inst
== $.datepicker
._curInst
&& $.datepicker
._datepickerShowing
&& inst
.input
&&
8011 // #6694 - don't focus the input if it's already focused
8012 // this breaks the change event in IE
8013 inst
.input
.is(':visible') && !inst
.input
.is(':disabled') && inst
.input
[0] != document
.activeElement
)
8015 // deffered render of the years select (to avoid flashes on Firefox)
8016 if( inst
.yearshtml
){
8017 var origyearshtml
= inst
.yearshtml
;
8018 setTimeout(function(){
8019 //assure that inst.yearshtml didn't change.
8020 if( origyearshtml
=== inst
.yearshtml
&& inst
.yearshtml
){
8021 inst
.dpDiv
.find('select.ui-datepicker-year:first').replaceWith(inst
.yearshtml
);
8023 origyearshtml
= inst
.yearshtml
= null;
8028 /* Retrieve the size of left and top borders for an element.
8029 @param elem (jQuery object) the element of interest
8030 @return (number[2]) the left and top borders */
8031 _getBorders: function(elem
) {
8032 var convert = function(value
) {
8033 return {thin
: 1, medium
: 2, thick
: 3}[value
] || value
;
8035 return [parseFloat(convert(elem
.css('border-left-width'))),
8036 parseFloat(convert(elem
.css('border-top-width')))];
8039 /* Check positioning to remain on screen. */
8040 _checkOffset: function(inst
, offset
, isFixed
) {
8041 var dpWidth
= inst
.dpDiv
.outerWidth();
8042 var dpHeight
= inst
.dpDiv
.outerHeight();
8043 var inputWidth
= inst
.input
? inst
.input
.outerWidth() : 0;
8044 var inputHeight
= inst
.input
? inst
.input
.outerHeight() : 0;
8045 var viewWidth
= document
.documentElement
.clientWidth
+ $(document
).scrollLeft();
8046 var viewHeight
= document
.documentElement
.clientHeight
+ $(document
).scrollTop();
8048 offset
.left
-= (this._get(inst
, 'isRTL') ? (dpWidth
- inputWidth
) : 0);
8049 offset
.left
-= (isFixed
&& offset
.left
== inst
.input
.offset().left
) ? $(document
).scrollLeft() : 0;
8050 offset
.top
-= (isFixed
&& offset
.top
== (inst
.input
.offset().top
+ inputHeight
)) ? $(document
).scrollTop() : 0;
8052 // now check if datepicker is showing outside window viewport - move to a better place if so.
8053 offset
.left
-= Math
.min(offset
.left
, (offset
.left
+ dpWidth
> viewWidth
&& viewWidth
> dpWidth
) ?
8054 Math
.abs(offset
.left
+ dpWidth
- viewWidth
) : 0);
8055 offset
.top
-= Math
.min(offset
.top
, (offset
.top
+ dpHeight
> viewHeight
&& viewHeight
> dpHeight
) ?
8056 Math
.abs(dpHeight
+ inputHeight
) : 0);
8061 /* Find an object's position on the screen. */
8062 _findPos: function(obj
) {
8063 var inst
= this._getInst(obj
);
8064 var isRTL
= this._get(inst
, 'isRTL');
8065 while (obj
&& (obj
.type
== 'hidden' || obj
.nodeType
!= 1 || $.expr
.filters
.hidden(obj
))) {
8066 obj
= obj
[isRTL
? 'previousSibling' : 'nextSibling'];
8068 var position
= $(obj
).offset();
8069 return [position
.left
, position
.top
];
8072 /* Trigger custom callback of onClose. */
8073 _triggerOnClose: function(inst
) {
8074 var onClose
= this._get(inst
, 'onClose');
8076 onClose
.apply((inst
.input
? inst
.input
[0] : null),
8077 [(inst
.input
? inst
.input
.val() : ''), inst
]);
8080 /* Hide the date picker from view.
8081 @param input element - the input field attached to the date picker */
8082 _hideDatepicker: function(input
) {
8083 var inst
= this._curInst
;
8084 if (!inst
|| (input
&& inst
!= $.data(input
, PROP_NAME
)))
8086 if (this._datepickerShowing
) {
8087 var showAnim
= this._get(inst
, 'showAnim');
8088 var duration
= this._get(inst
, 'duration');
8089 var postProcess = function() {
8090 $.datepicker
._tidyDialog(inst
);
8091 this._curInst
= null;
8093 if ($.effects
&& $.effects
[showAnim
])
8094 inst
.dpDiv
.hide(showAnim
, $.datepicker
._get(inst
, 'showOptions'), duration
, postProcess
);
8096 inst
.dpDiv
[(showAnim
== 'slideDown' ? 'slideUp' :
8097 (showAnim
== 'fadeIn' ? 'fadeOut' : 'hide'))]((showAnim
? duration
: null), postProcess
);
8100 $.datepicker
._triggerOnClose(inst
);
8101 this._datepickerShowing
= false;
8102 this._lastInput
= null;
8103 if (this._inDialog
) {
8104 this._dialogInput
.css({ position
: 'absolute', left
: '0', top
: '-100px' });
8107 $('body').append(this.dpDiv
);
8110 this._inDialog
= false;
8114 /* Tidy up after a dialog display. */
8115 _tidyDialog: function(inst
) {
8116 inst
.dpDiv
.removeClass(this._dialogClass
).unbind('.ui-datepicker-calendar');
8119 /* Close date picker if clicked elsewhere. */
8120 _checkExternalClick: function(event
) {
8121 if (!$.datepicker
._curInst
)
8123 var $target
= $(event
.target
);
8124 if ($target
[0].id
!= $.datepicker
._mainDivId
&&
8125 $target
.parents('#' + $.datepicker
._mainDivId
).length
== 0 &&
8126 !$target
.hasClass($.datepicker
.markerClassName
) &&
8127 !$target
.hasClass($.datepicker
._triggerClass
) &&
8128 $.datepicker
._datepickerShowing
&& !($.datepicker
._inDialog
&& $.blockUI
))
8129 $.datepicker
._hideDatepicker();
8132 /* Adjust one of the date sub-fields. */
8133 _adjustDate: function(id
, offset
, period
) {
8135 var inst
= this._getInst(target
[0]);
8136 if (this._isDisabledDatepicker(target
[0])) {
8139 this._adjustInstDate(inst
, offset
+
8140 (period
== 'M' ? this._get(inst
, 'showCurrentAtPos') : 0), // undo positioning
8142 this._updateDatepicker(inst
);
8145 /* Action for current link. */
8146 _gotoToday: function(id
) {
8148 var inst
= this._getInst(target
[0]);
8149 if (this._get(inst
, 'gotoCurrent') && inst
.currentDay
) {
8150 inst
.selectedDay
= inst
.currentDay
;
8151 inst
.drawMonth
= inst
.selectedMonth
= inst
.currentMonth
;
8152 inst
.drawYear
= inst
.selectedYear
= inst
.currentYear
;
8155 var date
= new Date();
8156 inst
.selectedDay
= date
.getDate();
8157 inst
.drawMonth
= inst
.selectedMonth
= date
.getMonth();
8158 inst
.drawYear
= inst
.selectedYear
= date
.getFullYear();
8160 this._notifyChange(inst
);
8161 this._adjustDate(target
);
8164 /* Action for selecting a new month/year. */
8165 _selectMonthYear: function(id, select, period) {
8167 var inst = this._getInst(target[0]);
8168 inst['selected' + (period == 'M' ? 'Month' : 'Year')] =
8169 inst['draw' + (period == 'M' ? 'Month' : 'Year')] =
8170 parseInt(select.options[select.selectedIndex].value,10);
8171 this._notifyChange(inst);
8172 this._adjustDate(target);
8175 /* Action for selecting a day. */
8176 _selectDay: function(id
, month
, year
, td
) {
8178 if ($(td
).hasClass(this._unselectableClass
) || this._isDisabledDatepicker(target
[0])) {
8181 var inst
= this._getInst(target
[0]);
8182 inst
.selectedDay
= inst
.currentDay
= $('a', td
).html();
8183 inst
.selectedMonth
= inst
.currentMonth
= month
;
8184 inst
.selectedYear
= inst
.currentYear
= year
;
8185 this._selectDate(id
, this._formatDate(inst
,
8186 inst
.currentDay
, inst
.currentMonth
, inst
.currentYear
));
8189 /* Erase the input field and hide the date picker. */
8190 _clearDate: function(id
) {
8192 var inst
= this._getInst(target
[0]);
8193 this._selectDate(target
, '');
8196 /* Update the input field with the selected date. */
8197 _selectDate: function(id
, dateStr
) {
8199 var inst
= this._getInst(target
[0]);
8200 dateStr
= (dateStr
!= null ? dateStr
: this._formatDate(inst
));
8202 inst
.input
.val(dateStr
);
8203 this._updateAlternate(inst
);
8204 var onSelect
= this._get(inst
, 'onSelect');
8206 onSelect
.apply((inst
.input
? inst
.input
[0] : null), [dateStr
, inst
]); // trigger custom callback
8207 else if (inst
.input
)
8208 inst
.input
.trigger('change'); // fire the change event
8210 this._updateDatepicker(inst
);
8212 this._hideDatepicker();
8213 this._lastInput
= inst
.input
[0];
8214 if (typeof(inst
.input
[0]) != 'object')
8215 inst
.input
.focus(); // restore focus
8216 this._lastInput
= null;
8220 /* Update any alternate field to synchronise with the main field. */
8221 _updateAlternate: function(inst
) {
8222 var altField
= this._get(inst
, 'altField');
8223 if (altField
) { // update alternate field too
8224 var altFormat
= this._get(inst
, 'altFormat') || this._get(inst
, 'dateFormat');
8225 var date
= this._getDate(inst
);
8226 var dateStr
= this.formatDate(altFormat
, date
, this._getFormatConfig(inst
));
8227 $(altField
).each(function() { $(this).val(dateStr
); });
8231 /* Set as beforeShowDay function to prevent selection of weekends.
8232 @param date Date - the date to customise
8233 @return [boolean, string] - is this date selectable?, what is its CSS class? */
8234 noWeekends: function(date
) {
8235 var day
= date
.getDay();
8236 return [(day
> 0 && day
< 6), ''];
8239 /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
8240 @param date Date - the date to get the week for
8241 @return number - the number of the week within the year that contains this date */
8242 iso8601Week: function(date
) {
8243 var checkDate
= new Date(date
.getTime());
8244 // Find Thursday of this week starting on Monday
8245 checkDate
.setDate(checkDate
.getDate() + 4 - (checkDate
.getDay() || 7));
8246 var time
= checkDate
.getTime();
8247 checkDate
.setMonth(0); // Compare with Jan 1
8248 checkDate
.setDate(1);
8249 return Math
.floor(Math
.round((time
- checkDate
) / 86400000) / 7) + 1;
8252 /* Parse a string value into a date object.
8253 See formatDate below for the possible formats.
8255 @param format string - the expected format of the date
8256 @param value string - the date in the above format
8257 @param settings Object - attributes include:
8258 shortYearCutoff number - the cutoff year for determining the century (optional)
8259 dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
8260 dayNames string[7] - names of the days from Sunday (optional)
8261 monthNamesShort string[12] - abbreviated names of the months (optional)
8262 monthNames string[12] - names of the months (optional)
8263 @return Date - the extracted date value or null if value is blank */
8264 parseDate: function (format
, value
, settings
) {
8265 if (format
== null || value
== null)
8266 throw 'Invalid arguments';
8267 value
= (typeof value
== 'object' ? value
.toString() : value
+ '');
8270 var shortYearCutoff
= (settings
? settings
.shortYearCutoff
: null) || this._defaults
.shortYearCutoff
;
8271 shortYearCutoff
= (typeof shortYearCutoff
!= 'string' ? shortYearCutoff
:
8272 new Date().getFullYear() % 100 + parseInt(shortYearCutoff
, 10));
8273 var dayNamesShort
= (settings
? settings
.dayNamesShort
: null) || this._defaults
.dayNamesShort
;
8274 var dayNames
= (settings
? settings
.dayNames
: null) || this._defaults
.dayNames
;
8275 var monthNamesShort
= (settings
? settings
.monthNamesShort
: null) || this._defaults
.monthNamesShort
;
8276 var monthNames
= (settings
? settings
.monthNames
: null) || this._defaults
.monthNames
;
8281 var literal
= false;
8282 // Check whether a format character is doubled
8283 var lookAhead = function(match
) {
8284 var matches
= (iFormat
+ 1 < format
.length
&& format
.charAt(iFormat
+ 1) == match
);
8289 // Extract a number from the string value
8290 var getNumber = function(match
) {
8291 var isDoubled
= lookAhead(match
);
8292 var size
= (match
== '@' ? 14 : (match
== '!' ? 20 :
8293 (match
== 'y' && isDoubled
? 4 : (match
== 'o' ? 3 : 2))));
8294 var digits
= new RegExp('^\\d{1,' + size
+ '}');
8295 var num
= value
.substring(iValue
).match(digits
);
8297 throw 'Missing number at position ' + iValue
;
8298 iValue
+= num
[0].length
;
8299 return parseInt(num
[0], 10);
8301 // Extract a name from the string value and convert to an index
8302 var getName = function(match
, shortNames
, longNames
) {
8303 var names
= $.map(lookAhead(match
) ? longNames
: shortNames
, function (v
, k
) {
8305 }).sort(function (a
, b
) {
8306 return -(a
[1].length
- b
[1].length
);
8309 $.each(names
, function (i
, pair
) {
8311 if (value
.substr(iValue
, name
.length
).toLowerCase() == name
.toLowerCase()) {
8313 iValue
+= name
.length
;
8320 throw 'Unknown name at position ' + iValue
;
8322 // Confirm that a literal character matches the string value
8323 var checkLiteral = function() {
8324 if (value
.charAt(iValue
) != format
.charAt(iFormat
))
8325 throw 'Unexpected literal at position ' + iValue
;
8329 for (var iFormat
= 0; iFormat
< format
.length
; iFormat
++) {
8331 if (format
.charAt(iFormat
) == "'" && !lookAhead("'"))
8336 switch (format
.charAt(iFormat
)) {
8338 day
= getNumber('d');
8341 getName('D', dayNamesShort
, dayNames
);
8344 doy
= getNumber('o');
8347 month
= getNumber('m');
8350 month
= getName('M', monthNamesShort
, monthNames
);
8353 year
= getNumber('y');
8356 var date
= new Date(getNumber('@'));
8357 year
= date
.getFullYear();
8358 month
= date
.getMonth() + 1;
8359 day
= date
.getDate();
8362 var date
= new Date((getNumber('!') - this._ticksTo1970
) / 10000);
8363 year
= date
.getFullYear();
8364 month
= date
.getMonth() + 1;
8365 day
= date
.getDate();
8377 if (iValue
< value
.length
){
8378 throw "Extra/unparsed characters found in date: " + value
.substring(iValue
);
8381 year
= new Date().getFullYear();
8382 else if (year
< 100)
8383 year
+= new Date().getFullYear() - new Date().getFullYear() % 100 +
8384 (year
<= shortYearCutoff
? 0 : -100);
8389 var dim
= this._getDaysInMonth(year
, month
- 1);
8396 var date
= this._daylightSavingAdjust(new Date(year
, month
- 1, day
));
8397 if (date
.getFullYear() != year
|| date
.getMonth() + 1 != month
|| date
.getDate() != day
)
8398 throw 'Invalid date'; // E.g. 31/02/00
8402 /* Standard date formats. */
8403 ATOM
: 'yy-mm-dd', // RFC 3339 (ISO 8601)
8404 COOKIE
: 'D, dd M yy',
8405 ISO_8601
: 'yy-mm-dd',
8406 RFC_822
: 'D, d M y',
8407 RFC_850
: 'DD, dd-M-y',
8408 RFC_1036
: 'D, d M y',
8409 RFC_1123
: 'D, d M yy',
8410 RFC_2822
: 'D, d M yy',
8411 RSS
: 'D, d M y', // RFC 822
8414 W3C
: 'yy-mm-dd', // ISO 8601
8416 _ticksTo1970
: (((1970 - 1) * 365 + Math
.floor(1970 / 4) - Math
.floor(1970 / 100) +
8417 Math
.floor(1970 / 400)) * 24 * 60 * 60 * 10000000),
8419 /* Format a date object into a string value.
8420 The format can be combinations of the following:
8421 d - day of month (no leading zero)
8422 dd - day of month (two digit)
8423 o - day of year (no leading zeros)
8424 oo - day of year (three digit)
8427 m - month of year (no leading zero)
8428 mm - month of year (two digit)
8429 M - month name short
8430 MM - month name long
8431 y - year (two digit)
8432 yy - year (four digit)
8433 @ - Unix timestamp (ms since 01/01/1970)
8434 ! - Windows ticks (100ns since 01/01/0001)
8435 '...' - literal text
8438 @param format string - the desired format of the date
8439 @param date Date - the date value to format
8440 @param settings Object - attributes include:
8441 dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
8442 dayNames string[7] - names of the days from Sunday (optional)
8443 monthNamesShort string[12] - abbreviated names of the months (optional)
8444 monthNames string[12] - names of the months (optional)
8445 @return string - the date in the above format */
8446 formatDate: function (format
, date
, settings
) {
8449 var dayNamesShort
= (settings
? settings
.dayNamesShort
: null) || this._defaults
.dayNamesShort
;
8450 var dayNames
= (settings
? settings
.dayNames
: null) || this._defaults
.dayNames
;
8451 var monthNamesShort
= (settings
? settings
.monthNamesShort
: null) || this._defaults
.monthNamesShort
;
8452 var monthNames
= (settings
? settings
.monthNames
: null) || this._defaults
.monthNames
;
8453 // Check whether a format character is doubled
8454 var lookAhead = function(match
) {
8455 var matches
= (iFormat
+ 1 < format
.length
&& format
.charAt(iFormat
+ 1) == match
);
8460 // Format a number, with leading zero if necessary
8461 var formatNumber = function(match
, value
, len
) {
8462 var num
= '' + value
;
8463 if (lookAhead(match
))
8464 while (num
.length
< len
)
8468 // Format a name, short or long as requested
8469 var formatName = function(match
, value
, shortNames
, longNames
) {
8470 return (lookAhead(match
) ? longNames
[value
] : shortNames
[value
]);
8473 var literal
= false;
8475 for (var iFormat
= 0; iFormat
< format
.length
; iFormat
++) {
8477 if (format
.charAt(iFormat
) == "'" && !lookAhead("'"))
8480 output
+= format
.charAt(iFormat
);
8482 switch (format
.charAt(iFormat
)) {
8484 output
+= formatNumber('d', date
.getDate(), 2);
8487 output
+= formatName('D', date
.getDay(), dayNamesShort
, dayNames
);
8490 output
+= formatNumber('o',
8491 Math
.round((new Date(date
.getFullYear(), date
.getMonth(), date
.getDate()).getTime() - new Date(date
.getFullYear(), 0, 0).getTime()) / 86400000), 3);
8494 output
+= formatNumber('m', date
.getMonth() + 1, 2);
8497 output
+= formatName('M', date
.getMonth(), monthNamesShort
, monthNames
);
8500 output
+= (lookAhead('y') ? date
.getFullYear() :
8501 (date
.getYear() % 100 < 10 ? '0' : '') + date
.getYear() % 100);
8504 output
+= date
.getTime();
8507 output
+= date
.getTime() * 10000 + this._ticksTo1970
;
8516 output
+= format
.charAt(iFormat
);
8522 /* Extract all possible characters from the date format. */
8523 _possibleChars: function (format
) {
8525 var literal
= false;
8526 // Check whether a format character is doubled
8527 var lookAhead = function(match
) {
8528 var matches
= (iFormat
+ 1 < format
.length
&& format
.charAt(iFormat
+ 1) == match
);
8533 for (var iFormat
= 0; iFormat
< format
.length
; iFormat
++)
8535 if (format
.charAt(iFormat
) == "'" && !lookAhead("'"))
8538 chars
+= format
.charAt(iFormat
);
8540 switch (format
.charAt(iFormat
)) {
8541 case 'd': case 'm': case 'y': case '@':
8542 chars
+= '0123456789';
8545 return null; // Accept anything
8553 chars
+= format
.charAt(iFormat
);
8558 /* Get a setting value, defaulting if necessary. */
8559 _get: function(inst
, name
) {
8560 return inst
.settings
[name
] !== undefined ?
8561 inst
.settings
[name
] : this._defaults
[name
];
8564 /* Parse existing date and initialise date picker. */
8565 _setDateFromField: function(inst
, noDefault
) {
8566 if (inst
.input
.val() == inst
.lastVal
) {
8569 var dateFormat
= this._get(inst
, 'dateFormat');
8570 var dates
= inst
.lastVal
= inst
.input
? inst
.input
.val() : null;
8571 var date
, defaultDate
;
8572 date
= defaultDate
= this._getDefaultDate(inst
);
8573 var settings
= this._getFormatConfig(inst
);
8575 date
= this.parseDate(dateFormat
, dates
, settings
) || defaultDate
;
8578 dates
= (noDefault
? '' : dates
);
8580 inst
.selectedDay
= date
.getDate();
8581 inst
.drawMonth
= inst
.selectedMonth
= date
.getMonth();
8582 inst
.drawYear
= inst
.selectedYear
= date
.getFullYear();
8583 inst
.currentDay
= (dates
? date
.getDate() : 0);
8584 inst
.currentMonth
= (dates
? date
.getMonth() : 0);
8585 inst
.currentYear
= (dates
? date
.getFullYear() : 0);
8586 this._adjustInstDate(inst
);
8589 /* Retrieve the default date shown on opening. */
8590 _getDefaultDate: function(inst
) {
8591 return this._restrictMinMax(inst
,
8592 this._determineDate(inst
, this._get(inst
, 'defaultDate'), new Date()));
8595 /* A date may be specified as an exact value or a relative one. */
8596 _determineDate: function(inst
, date
, defaultDate
) {
8597 var offsetNumeric = function(offset
) {
8598 var date
= new Date();
8599 date
.setDate(date
.getDate() + offset
);
8602 var offsetString = function(offset
) {
8604 return $.datepicker
.parseDate($.datepicker
._get(inst
, 'dateFormat'),
8605 offset
, $.datepicker
._getFormatConfig(inst
));
8610 var date
= (offset
.toLowerCase().match(/^c/) ?
8611 $.datepicker
._getDate(inst
) : null) || new Date();
8612 var year
= date
.getFullYear();
8613 var month
= date
.getMonth();
8614 var day
= date
.getDate();
8615 var pattern
= /([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g;
8616 var matches
= pattern
.exec(offset
);
8618 switch (matches
[2] || 'd') {
8619 case 'd' : case 'D' :
8620 day
+= parseInt(matches
[1],10); break;
8621 case 'w' : case 'W' :
8622 day
+= parseInt(matches
[1],10) * 7; break;
8623 case 'm' : case 'M' :
8624 month
+= parseInt(matches
[1],10);
8625 day
= Math
.min(day
, $.datepicker
._getDaysInMonth(year
, month
));
8627 case 'y': case 'Y' :
8628 year
+= parseInt(matches
[1],10);
8629 day
= Math
.min(day
, $.datepicker
._getDaysInMonth(year
, month
));
8632 matches
= pattern
.exec(offset
);
8634 return new Date(year
, month
, day
);
8636 var newDate
= (date
== null || date
=== '' ? defaultDate
: (typeof date
== 'string' ? offsetString(date
) :
8637 (typeof date
== 'number' ? (isNaN(date
) ? defaultDate
: offsetNumeric(date
)) : new Date(date
.getTime()))));
8638 newDate
= (newDate
&& newDate
.toString() == 'Invalid Date' ? defaultDate
: newDate
);
8640 newDate
.setHours(0);
8641 newDate
.setMinutes(0);
8642 newDate
.setSeconds(0);
8643 newDate
.setMilliseconds(0);
8645 return this._daylightSavingAdjust(newDate
);
8648 /* Handle switch to/from daylight saving.
8649 Hours may be non-zero on daylight saving cut-over:
8650 > 12 when midnight changeover, but then cannot generate
8651 midnight datetime, so jump to 1AM, otherwise reset.
8652 @param date (Date) the date to check
8653 @return (Date) the corrected date */
8654 _daylightSavingAdjust: function(date
) {
8655 if (!date
) return null;
8656 date
.setHours(date
.getHours() > 12 ? date
.getHours() + 2 : 0);
8660 /* Set the date(s) directly. */
8661 _setDate: function(inst
, date
, noChange
) {
8663 var origMonth
= inst
.selectedMonth
;
8664 var origYear
= inst
.selectedYear
;
8665 var newDate
= this._restrictMinMax(inst
, this._determineDate(inst
, date
, new Date()));
8666 inst
.selectedDay
= inst
.currentDay
= newDate
.getDate();
8667 inst
.drawMonth
= inst
.selectedMonth
= inst
.currentMonth
= newDate
.getMonth();
8668 inst
.drawYear
= inst
.selectedYear
= inst
.currentYear
= newDate
.getFullYear();
8669 if ((origMonth
!= inst
.selectedMonth
|| origYear
!= inst
.selectedYear
) && !noChange
)
8670 this._notifyChange(inst
);
8671 this._adjustInstDate(inst
);
8673 inst
.input
.val(clear
? '' : this._formatDate(inst
));
8677 /* Retrieve the date(s) directly. */
8678 _getDate: function(inst
) {
8679 var startDate
= (!inst
.currentYear
|| (inst
.input
&& inst
.input
.val() == '') ? null :
8680 this._daylightSavingAdjust(new Date(
8681 inst
.currentYear
, inst
.currentMonth
, inst
.currentDay
)));
8685 /* Generate the HTML for the current state of the date picker. */
8686 _generateHTML: function(inst
) {
8687 var today
= new Date();
8688 today
= this._daylightSavingAdjust(
8689 new Date(today
.getFullYear(), today
.getMonth(), today
.getDate())); // clear time
8690 var isRTL
= this._get(inst
, 'isRTL');
8691 var showButtonPanel
= this._get(inst
, 'showButtonPanel');
8692 var hideIfNoPrevNext
= this._get(inst
, 'hideIfNoPrevNext');
8693 var navigationAsDateFormat
= this._get(inst
, 'navigationAsDateFormat');
8694 var numMonths
= this._getNumberOfMonths(inst
);
8695 var showCurrentAtPos
= this._get(inst
, 'showCurrentAtPos');
8696 var stepMonths
= this._get(inst
, 'stepMonths');
8697 var isMultiMonth
= (numMonths
[0] != 1 || numMonths
[1] != 1);
8698 var currentDate
= this._daylightSavingAdjust((!inst
.currentDay
? new Date(9999, 9, 9) :
8699 new Date(inst
.currentYear
, inst
.currentMonth
, inst
.currentDay
)));
8700 var minDate
= this._getMinMaxDate(inst
, 'min');
8701 var maxDate
= this._getMinMaxDate(inst
, 'max');
8702 var drawMonth
= inst
.drawMonth
- showCurrentAtPos
;
8703 var drawYear
= inst
.drawYear
;
8704 if (drawMonth
< 0) {
8709 var maxDraw
= this._daylightSavingAdjust(new Date(maxDate
.getFullYear(),
8710 maxDate
.getMonth() - (numMonths
[0] * numMonths
[1]) + 1, maxDate
.getDate()));
8711 maxDraw
= (minDate
&& maxDraw
< minDate
? minDate
: maxDraw
);
8712 while (this._daylightSavingAdjust(new Date(drawYear
, drawMonth
, 1)) > maxDraw
) {
8714 if (drawMonth
< 0) {
8720 inst
.drawMonth
= drawMonth
;
8721 inst
.drawYear
= drawYear
;
8722 var prevText
= this._get(inst
, 'prevText');
8723 prevText
= (!navigationAsDateFormat
? prevText
: this.formatDate(prevText
,
8724 this._daylightSavingAdjust(new Date(drawYear
, drawMonth
- stepMonths
, 1)),
8725 this._getFormatConfig(inst
)));
8726 var prev
= (this._canAdjustMonth(inst
, -1, drawYear
, drawMonth
) ?
8727 '<a class="ui-datepicker-prev ui-corner-all" onclick="DP_jQuery_' + dpuuid
+
8728 '.datepicker._adjustDate(\'#' + inst
.id
+ '\', -' + stepMonths
+ ', \'M\');"' +
8729 ' title="' + prevText
+ '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL
? 'e' : 'w') + '">' + prevText
+ '</span></a>' :
8730 (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>'));
8731 var nextText
= this._get(inst
, 'nextText');
8732 nextText
= (!navigationAsDateFormat
? nextText
: this.formatDate(nextText
,
8733 this._daylightSavingAdjust(new Date(drawYear
, drawMonth
+ stepMonths
, 1)),
8734 this._getFormatConfig(inst
)));
8735 var next
= (this._canAdjustMonth(inst
, +1, drawYear
, drawMonth
) ?
8736 '<a class="ui-datepicker-next ui-corner-all" onclick="DP_jQuery_' + dpuuid
+
8737 '.datepicker._adjustDate(\'#' + inst
.id
+ '\', +' + stepMonths
+ ', \'M\');"' +
8738 ' title="' + nextText
+ '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL
? 'w' : 'e') + '">' + nextText
+ '</span></a>' :
8739 (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>'));
8740 var currentText
= this._get(inst
, 'currentText');
8741 var gotoDate
= (this._get(inst
, 'gotoCurrent') && inst
.currentDay
? currentDate
: today
);
8742 currentText
= (!navigationAsDateFormat
? currentText
:
8743 this.formatDate(currentText
, gotoDate
, this._getFormatConfig(inst
)));
8744 var controls
= (!inst
.inline
? '<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" onclick="DP_jQuery_' + dpuuid
+
8745 '.datepicker._hideDatepicker();">' + this._get(inst
, 'closeText') + '</button>' : '');
8746 var buttonPanel
= (showButtonPanel
) ? '<div class="ui-datepicker-buttonpane ui-widget-content">' + (isRTL
? controls
: '') +
8747 (this._isInRange(inst
, gotoDate
) ? '<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" onclick="DP_jQuery_' + dpuuid
+
8748 '.datepicker._gotoToday(\'#' + inst
.id
+ '\');"' +
8749 '>' + currentText
+ '</button>' : '') + (isRTL
? '' : controls
) + '</div>' : '';
8750 var firstDay
= parseInt(this._get(inst
, 'firstDay'),10);
8751 firstDay
= (isNaN(firstDay
) ? 0 : firstDay
);
8752 var showWeek
= this._get(inst
, 'showWeek');
8753 var dayNames
= this._get(inst
, 'dayNames');
8754 var dayNamesShort
= this._get(inst
, 'dayNamesShort');
8755 var dayNamesMin
= this._get(inst
, 'dayNamesMin');
8756 var monthNames
= this._get(inst
, 'monthNames');
8757 var monthNamesShort
= this._get(inst
, 'monthNamesShort');
8758 var beforeShowDay
= this._get(inst
, 'beforeShowDay');
8759 var showOtherMonths
= this._get(inst
, 'showOtherMonths');
8760 var selectOtherMonths
= this._get(inst
, 'selectOtherMonths');
8761 var calculateWeek
= this._get(inst
, 'calculateWeek') || this.iso8601Week
;
8762 var defaultDate
= this._getDefaultDate(inst
);
8764 for (var row
= 0; row
< numMonths
[0]; row
++) {
8767 for (var col
= 0; col
< numMonths
[1]; col
++) {
8768 var selectedDate
= this._daylightSavingAdjust(new Date(drawYear
, drawMonth
, inst
.selectedDay
));
8769 var cornerClass
= ' ui-corner-all';
8772 calender
+= '<div class="ui-datepicker-group';
8773 if (numMonths
[1] > 1)
8775 case 0: calender
+= ' ui-datepicker-group-first';
8776 cornerClass
= ' ui-corner-' + (isRTL
? 'right' : 'left'); break;
8777 case numMonths
[1]-1: calender
+= ' ui-datepicker-group-last';
8778 cornerClass
= ' ui-corner-' + (isRTL
? 'left' : 'right'); break;
8779 default: calender
+= ' ui-datepicker-group-middle'; cornerClass
= ''; break;
8783 calender
+= '<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix' + cornerClass
+ '">' +
8784 (/all|left/.test(cornerClass
) && row
== 0 ? (isRTL
? next
: prev
) : '') +
8785 (/all|right/.test(cornerClass
) && row
== 0 ? (isRTL
? prev
: next
) : '') +
8786 this._generateMonthYearHeader(inst
, drawMonth
, drawYear
, minDate
, maxDate
,
8787 row
> 0 || col
> 0, monthNames
, monthNamesShort
) + // draw month headers
8788 '</div><table class="ui-datepicker-calendar"><thead>' +
8790 var thead
= (showWeek
? '<th class="ui-datepicker-week-col">' + this._get(inst
, 'weekHeader') + '</th>' : '');
8791 for (var dow
= 0; dow
< 7; dow
++) { // days of the week
8792 var day
= (dow
+ firstDay
) % 7;
8793 thead
+= '<th' + ((dow
+ firstDay
+ 6) % 7 >= 5 ? ' class="ui-datepicker-week-end"' : '') + '>' +
8794 '<span title="' + dayNames
[day
] + '">' + dayNamesMin
[day
] + '</span></th>';
8796 calender
+= thead
+ '</tr></thead><tbody>';
8797 var daysInMonth
= this._getDaysInMonth(drawYear
, drawMonth
);
8798 if (drawYear
== inst
.selectedYear
&& drawMonth
== inst
.selectedMonth
)
8799 inst
.selectedDay
= Math
.min(inst
.selectedDay
, daysInMonth
);
8800 var leadDays
= (this._getFirstDayOfMonth(drawYear
, drawMonth
) - firstDay
+ 7) % 7;
8801 var curRows
= Math
.ceil((leadDays
+ daysInMonth
) / 7); // calculate the number of rows to generate
8802 var numRows
= (isMultiMonth
? this.maxRows
> curRows
? this.maxRows
: curRows
: curRows
); //If multiple months, use the higher number of rows (see #7043)
8803 this.maxRows
= numRows
;
8804 var printDate
= this._daylightSavingAdjust(new Date(drawYear
, drawMonth
, 1 - leadDays
));
8805 for (var dRow
= 0; dRow
< numRows
; dRow
++) { // create date picker rows
8807 var tbody
= (!showWeek
? '' : '<td class="ui-datepicker-week-col">' +
8808 this._get(inst
, 'calculateWeek')(printDate
) + '</td>');
8809 for (var dow
= 0; dow
< 7; dow
++) { // create date picker days
8810 var daySettings
= (beforeShowDay
?
8811 beforeShowDay
.apply((inst
.input
? inst
.input
[0] : null), [printDate
]) : [true, '']);
8812 var otherMonth
= (printDate
.getMonth() != drawMonth
);
8813 var unselectable
= (otherMonth
&& !selectOtherMonths
) || !daySettings
[0] ||
8814 (minDate
&& printDate
< minDate
) || (maxDate
&& printDate
> maxDate
);
8815 tbody
+= '<td class="' +
8816 ((dow
+ firstDay
+ 6) % 7 >= 5 ? ' ui-datepicker-week-end' : '') + // highlight weekends
8817 (otherMonth
? ' ui-datepicker-other-month' : '') + // highlight days from other months
8818 ((printDate
.getTime() == selectedDate
.getTime() && drawMonth
== inst
.selectedMonth
&& inst
._keyEvent
) || // user pressed key
8819 (defaultDate
.getTime() == printDate
.getTime() && defaultDate
.getTime() == selectedDate
.getTime()) ?
8820 // or defaultDate is current printedDate and defaultDate is selectedDate
8821 ' ' + this._dayOverClass
: '') + // highlight selected day
8822 (unselectable
? ' ' + this._unselectableClass
+ ' ui-state-disabled': '') + // highlight unselectable days
8823 (otherMonth
&& !showOtherMonths
? '' : ' ' + daySettings
[1] + // highlight custom dates
8824 (printDate
.getTime() == currentDate
.getTime() ? ' ' + this._currentClass
: '') + // highlight selected day
8825 (printDate
.getTime() == today
.getTime() ? ' ui-datepicker-today' : '')) + '"' + // highlight today (if different)
8826 ((!otherMonth
|| showOtherMonths
) && daySettings
[2] ? ' title="' + daySettings
[2] + '"' : '') + // cell title
8827 (unselectable
? '' : ' onclick="DP_jQuery_' + dpuuid
+ '.datepicker._selectDay(\'#' +
8828 inst
.id
+ '\',' + printDate
.getMonth() + ',' + printDate
.getFullYear() + ', this);return false;"') + '>' + // actions
8829 (otherMonth
&& !showOtherMonths
? ' ' : // display for other months
8830 (unselectable
? '<span class="ui-state-default">' + printDate
.getDate() + '</span>' : '<a class="ui-state-default' +
8831 (printDate
.getTime() == today
.getTime() ? ' ui-state-highlight' : '') +
8832 (printDate
.getTime() == currentDate
.getTime() ? ' ui-state-active' : '') + // highlight selected day
8833 (otherMonth
? ' ui-priority-secondary' : '') + // distinguish dates from other months
8834 '" href="#">' + printDate
.getDate() + '</a>')) + '</td>'; // display selectable date
8835 printDate
.setDate(printDate
.getDate() + 1);
8836 printDate
= this._daylightSavingAdjust(printDate
);
8838 calender
+= tbody
+ '</tr>';
8841 if (drawMonth
> 11) {
8845 calender
+= '</tbody></table>' + (isMultiMonth
? '</div>' +
8846 ((numMonths
[0] > 0 && col
== numMonths
[1]-1) ? '<div class="ui-datepicker-row-break"></div>' : '') : '');
8851 html
+= buttonPanel
+ ($.browser
.msie
&& parseInt($.browser
.version
,10) < 7 && !inst
.inline
?
8852 '<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>' : '');
8853 inst
._keyEvent
= false;
8857 /* Generate the month and year header. */
8858 _generateMonthYearHeader: function(inst
, drawMonth
, drawYear
, minDate
, maxDate
,
8859 secondary
, monthNames
, monthNamesShort
) {
8860 var changeMonth
= this._get(inst
, 'changeMonth');
8861 var changeYear
= this._get(inst
, 'changeYear');
8862 var showMonthAfterYear
= this._get(inst
, 'showMonthAfterYear');
8863 var html
= '<div class="ui-datepicker-title">';
8866 if (secondary
|| !changeMonth
)
8867 monthHtml
+= '<span class="ui-datepicker-month">' + monthNames
[drawMonth
] + '</span>';
8869 var inMinYear
= (minDate
&& minDate
.getFullYear() == drawYear
);
8870 var inMaxYear
= (maxDate
&& maxDate
.getFullYear() == drawYear
);
8871 monthHtml
+= '<select class="ui-datepicker-month" ' +
8872 'onchange="DP_jQuery_' + dpuuid
+ '.datepicker._selectMonthYear(\'#' + inst
.id
+ '\', this, \'M\');" ' +
8874 for (var month
= 0; month
< 12; month
++) {
8875 if ((!inMinYear
|| month
>= minDate
.getMonth()) &&
8876 (!inMaxYear
|| month
<= maxDate
.getMonth()))
8877 monthHtml
+= '<option value="' + month
+ '"' +
8878 (month
== drawMonth
? ' selected="selected"' : '') +
8879 '>' + monthNamesShort
[month
] + '</option>';
8881 monthHtml
+= '</select>';
8883 if (!showMonthAfterYear
)
8884 html
+= monthHtml
+ (secondary
|| !(changeMonth
&& changeYear
) ? ' ' : '');
8886 if ( !inst
.yearshtml
) {
8887 inst
.yearshtml
= '';
8888 if (secondary
|| !changeYear
)
8889 html
+= '<span class="ui-datepicker-year">' + drawYear
+ '</span>';
8891 // determine range of years to display
8892 var years
= this._get(inst
, 'yearRange').split(':');
8893 var thisYear
= new Date().getFullYear();
8894 var determineYear = function(value
) {
8895 var year
= (value
.match(/c[+-].*/) ? drawYear
+ parseInt(value
.substring(1), 10) :
8896 (value
.match(/[+-].*/) ? thisYear
+ parseInt(value
, 10) :
8897 parseInt(value
, 10)));
8898 return (isNaN(year
) ? thisYear
: year
);
8900 var year
= determineYear(years
[0]);
8901 var endYear
= Math
.max(year
, determineYear(years
[1] || ''));
8902 year
= (minDate
? Math
.max(year
, minDate
.getFullYear()) : year
);
8903 endYear
= (maxDate
? Math
.min(endYear
, maxDate
.getFullYear()) : endYear
);
8904 inst
.yearshtml
+= '<select class="ui-datepicker-year" ' +
8905 'onchange="DP_jQuery_' + dpuuid
+ '.datepicker._selectMonthYear(\'#' + inst
.id
+ '\', this, \'Y\');" ' +
8907 for (; year
<= endYear
; year
++) {
8908 inst
.yearshtml
+= '<option value="' + year
+ '"' +
8909 (year
== drawYear
? ' selected="selected"' : '') +
8910 '>' + year
+ '</option>';
8912 inst
.yearshtml
+= '</select>';
8914 html
+= inst
.yearshtml
;
8915 inst
.yearshtml
= null;
8918 html
+= this._get(inst
, 'yearSuffix');
8919 if (showMonthAfterYear
)
8920 html
+= (secondary
|| !(changeMonth
&& changeYear
) ? ' ' : '') + monthHtml
;
8921 html
+= '</div>'; // Close datepicker_header
8925 /* Adjust one of the date sub-fields. */
8926 _adjustInstDate: function(inst
, offset
, period
) {
8927 var year
= inst
.drawYear
+ (period
== 'Y' ? offset
: 0);
8928 var month
= inst
.drawMonth
+ (period
== 'M' ? offset
: 0);
8929 var day
= Math
.min(inst
.selectedDay
, this._getDaysInMonth(year
, month
)) +
8930 (period
== 'D' ? offset
: 0);
8931 var date
= this._restrictMinMax(inst
,
8932 this._daylightSavingAdjust(new Date(year
, month
, day
)));
8933 inst
.selectedDay
= date
.getDate();
8934 inst
.drawMonth
= inst
.selectedMonth
= date
.getMonth();
8935 inst
.drawYear
= inst
.selectedYear
= date
.getFullYear();
8936 if (period
== 'M' || period
== 'Y')
8937 this._notifyChange(inst
);
8940 /* Ensure a date is within any min/max bounds. */
8941 _restrictMinMax: function(inst, date) {
8942 var minDate = this._getMinMaxDate(inst, 'min');
8943 var maxDate = this._getMinMaxDate(inst, 'max');
8944 var newDate = (minDate && date < minDate ? minDate : date);
8945 newDate = (maxDate && newDate > maxDate ? maxDate : newDate);
8949 /* Notify change of month/year. */
8950 _notifyChange: function(inst) {
8951 var onChange = this._get(inst, 'onChangeMonthYear');
8953 onChange.apply((inst.input ? inst.input[0] : null),
8954 [inst.selectedYear, inst.selectedMonth + 1, inst]);
8957 /* Determine the number of months to show. */
8958 _getNumberOfMonths: function(inst
) {
8959 var numMonths
= this._get(inst
, 'numberOfMonths');
8960 return (numMonths
== null ? [1, 1] : (typeof numMonths
== 'number' ? [1, numMonths
] : numMonths
));
8963 /* Determine the current maximum date - ensure no time components are set. */
8964 _getMinMaxDate: function(inst
, minMax
) {
8965 return this._determineDate(inst
, this._get(inst
, minMax
+ 'Date'), null);
8968 /* Find the number of days in a given month. */
8969 _getDaysInMonth: function(year
, month
) {
8970 return 32 - this._daylightSavingAdjust(new Date(year
, month
, 32)).getDate();
8973 /* Find the day of the week of the first of a month. */
8974 _getFirstDayOfMonth: function(year
, month
) {
8975 return new Date(year
, month
, 1).getDay();
8978 /* Determines if we should allow a "next/prev" month display change. */
8979 _canAdjustMonth: function(inst, offset, curYear, curMonth) {
8980 var numMonths = this._getNumberOfMonths(inst);
8981 var date = this._daylightSavingAdjust(new Date(curYear,
8982 curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1));
8984 date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
8985 return this._isInRange(inst, date);
8988 /* Is the given date in the accepted range? */
8989 _isInRange: function(inst
, date
) {
8990 var minDate
= this._getMinMaxDate(inst
, 'min');
8991 var maxDate
= this._getMinMaxDate(inst
, 'max');
8992 return ((!minDate
|| date
.getTime() >= minDate
.getTime()) &&
8993 (!maxDate
|| date
.getTime() <= maxDate
.getTime()));
8996 /* Provide the configuration settings for formatting/parsing. */
8997 _getFormatConfig: function(inst) {
8998 var shortYearCutoff = this._get(inst, 'shortYearCutoff');
8999 shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff :
9000 new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
9001 return {shortYearCutoff: shortYearCutoff,
9002 dayNamesShort: this._get(inst, 'dayNamesShort'), dayNames: this._get(inst, 'dayNames'),
9003 monthNamesShort: this._get(inst, 'monthNamesShort'), monthNames: this._get(inst, 'monthNames')};
9006 /* Format the given date for display. */
9007 _formatDate: function(inst
, day
, month
, year
) {
9009 inst
.currentDay
= inst
.selectedDay
;
9010 inst
.currentMonth
= inst
.selectedMonth
;
9011 inst
.currentYear
= inst
.selectedYear
;
9013 var date
= (day
? (typeof day
== 'object' ? day
:
9014 this._daylightSavingAdjust(new Date(year
, month
, day
))) :
9015 this._daylightSavingAdjust(new Date(inst
.currentYear
, inst
.currentMonth
, inst
.currentDay
)));
9016 return this.formatDate(this._get(inst
, 'dateFormat'), date
, this._getFormatConfig(inst
));
9021 * Bind hover events for datepicker elements.
9022 * Done via delegate so the binding only occurs once in the lifetime of the parent div.
9023 * Global instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker.
9025 function bindHover(dpDiv
) {
9026 var selector
= 'button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a';
9027 return dpDiv
.bind('mouseout', function(event
) {
9028 var elem
= $( event
.target
).closest( selector
);
9029 if ( !elem
.length
) {
9032 elem
.removeClass( "ui-state-hover ui-datepicker-prev-hover ui-datepicker-next-hover" );
9034 .bind('mouseover', function(event
) {
9035 var elem
= $( event
.target
).closest( selector
);
9036 if ($.datepicker
._isDisabledDatepicker( instActive
.inline
? dpDiv
.parent()[0] : instActive
.input
[0]) ||
9040 elem
.parents('.ui-datepicker-calendar').find('a').removeClass('ui-state-hover');
9041 elem
.addClass('ui-state-hover');
9042 if (elem
.hasClass('ui-datepicker-prev')) elem
.addClass('ui-datepicker-prev-hover');
9043 if (elem
.hasClass('ui-datepicker-next')) elem
.addClass('ui-datepicker-next-hover');
9047 /* jQuery extend now ignores nulls! */
9048 function extendRemove(target
, props
) {
9049 $.extend(target
, props
);
9050 for (var name
in props
)
9051 if (props
[name
] == null || props
[name
] == undefined)
9052 target
[name
] = props
[name
];
9056 /* Determine whether an object is an array. */
9057 function isArray(a
) {
9058 return (a
&& (($.browser
.safari
&& typeof a
== 'object' && a
.length
) ||
9059 (a
.constructor && a
.constructor.toString().match(/\Array\(\)/))));
9062 /* Invoke the datepicker functionality.
9063 @param options string - a command, optionally followed by additional parameters or
9064 Object - settings for attaching new datepicker functionality
9065 @return jQuery object */
9066 $.fn
.datepicker = function(options
){
9068 /* Verify an empty collection wasn't passed - Fixes #6976 */
9069 if ( !this.length
) {
9073 /* Initialise the date picker. */
9074 if (!$.datepicker
.initialized
) {
9075 $(document
).mousedown($.datepicker
._checkExternalClick
).
9076 find('body').append($.datepicker
.dpDiv
);
9077 $.datepicker
.initialized
= true;
9080 var otherArgs
= Array
.prototype.slice
.call(arguments
, 1);
9081 if (typeof options
== 'string' && (options
== 'isDisabled' || options
== 'getDate' || options
== 'widget'))
9082 return $.datepicker
['_' + options
+ 'Datepicker'].
9083 apply($.datepicker
, [this[0]].concat(otherArgs
));
9084 if (options
== 'option' && arguments
.length
== 2 && typeof arguments
[1] == 'string')
9085 return $.datepicker
['_' + options
+ 'Datepicker'].
9086 apply($.datepicker
, [this[0]].concat(otherArgs
));
9087 return this.each(function() {
9088 typeof options
== 'string' ?
9089 $.datepicker
['_' + options
+ 'Datepicker'].
9090 apply($.datepicker
, [this].concat(otherArgs
)) :
9091 $.datepicker
._attachDatepicker(this, options
);
9095 $.datepicker
= new Datepicker(); // singleton instance
9096 $.datepicker
.initialized
= false;
9097 $.datepicker
.uuid
= new Date().getTime();
9098 $.datepicker
.version
= "1.8.16";
9100 // Workaround for #4055
9101 // Add another global to avoid noConflict issues with inline event handlers
9102 window
['DP_jQuery_' + dpuuid
] = $;
9106 * jQuery UI Dialog 1.8.16
9108 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
9109 * Dual licensed under the MIT or GPL Version 2 licenses.
9110 * http://jquery.org/license
9112 * http://docs.jquery.com/UI/Dialog
9116 * jquery.ui.widget.js
9117 * jquery.ui.button.js
9118 * jquery.ui.draggable.js
9119 * jquery.ui.mouse.js
9120 * jquery.ui.position.js
9121 * jquery.ui.resizable.js
9123 (function( $, undefined ) {
9125 var uiDialogClasses
=
9128 'ui-widget-content ' +
9130 sizeRelatedOptions
= {
9139 resizableRelatedOptions
= {
9145 // support for jQuery 1.3.2 - handle common attrFn methods for dialog
9146 attrFn
= $.attrFn
|| {
9158 $.widget("ui.dialog", {
9162 closeOnEscape
: true,
9177 // ensure that the titlebar is never outside the document
9178 using: function(pos
) {
9179 var topOffset
= $(this).css(pos
).offset().top
;
9180 if (topOffset
< 0) {
9181 $(this).css('top', pos
.top
- topOffset
);
9193 _create: function() {
9194 this.originalTitle
= this.element
.attr('title');
9195 // #5742 - .attr() might return a DOMElement
9196 if ( typeof this.originalTitle
!== "string" ) {
9197 this.originalTitle
= "";
9200 this.options
.title
= this.options
.title
|| this.originalTitle
;
9202 options
= self
.options
,
9204 title
= options
.title
|| ' ',
9205 titleId
= $.ui
.dialog
.getTitleId(self
.element
),
9207 uiDialog
= (self
.uiDialog
= $('<div></div>'))
9208 .appendTo(document
.body
)
9210 .addClass(uiDialogClasses
+ options
.dialogClass
)
9212 zIndex
: options
.zIndex
9214 // setting tabIndex makes the div focusable
9215 // setting outline to 0 prevents a border on focus in Mozilla
9216 .attr('tabIndex', -1).css('outline', 0).keydown(function(event
) {
9217 if (options
.closeOnEscape
&& !event
.isDefaultPrevented() && event
.keyCode
&&
9218 event
.keyCode
=== $.ui
.keyCode
.ESCAPE
) {
9221 event
.preventDefault();
9226 'aria-labelledby': titleId
9228 .mousedown(function(event
) {
9229 self
.moveToTop(false, event
);
9232 uiDialogContent
= self
.element
9234 .removeAttr('title')
9236 'ui-dialog-content ' +
9237 'ui-widget-content')
9238 .appendTo(uiDialog
),
9240 uiDialogTitlebar
= (self
.uiDialogTitlebar
= $('<div></div>'))
9242 'ui-dialog-titlebar ' +
9243 'ui-widget-header ' +
9245 'ui-helper-clearfix'
9247 .prependTo(uiDialog
),
9249 uiDialogTitlebarClose
= $('<a href="#"></a>')
9251 'ui-dialog-titlebar-close ' +
9254 .attr('role', 'button')
9257 uiDialogTitlebarClose
.addClass('ui-state-hover');
9260 uiDialogTitlebarClose
.removeClass('ui-state-hover');
9264 uiDialogTitlebarClose
.addClass('ui-state-focus');
9267 uiDialogTitlebarClose
.removeClass('ui-state-focus');
9269 .click(function(event
) {
9273 .appendTo(uiDialogTitlebar
),
9275 uiDialogTitlebarCloseText
= (self
.uiDialogTitlebarCloseText
= $('<span></span>'))
9278 'ui-icon-closethick'
9280 .text(options
.closeText
)
9281 .appendTo(uiDialogTitlebarClose
),
9283 uiDialogTitle
= $('<span></span>')
9284 .addClass('ui-dialog-title')
9285 .attr('id', titleId
)
9287 .prependTo(uiDialogTitlebar
);
9289 //handling of deprecated beforeclose (vs beforeClose) option
9290 //Ticket #4669 http://dev.jqueryui.com/ticket/4669
9291 //TODO: remove in 1.9pre
9292 if ($.isFunction(options
.beforeclose
) && !$.isFunction(options
.beforeClose
)) {
9293 options
.beforeClose
= options
.beforeclose
;
9296 uiDialogTitlebar
.find("*").add(uiDialogTitlebar
).disableSelection();
9298 if (options
.draggable
&& $.fn
.draggable
) {
9299 self
._makeDraggable();
9301 if (options
.resizable
&& $.fn
.resizable
) {
9302 self
._makeResizable();
9305 self
._createButtons(options
.buttons
);
9306 self
._isOpen
= false;
9308 if ($.fn
.bgiframe
) {
9309 uiDialog
.bgiframe();
9314 if ( this.options
.autoOpen
) {
9319 destroy: function() {
9323 self
.overlay
.destroy();
9325 self
.uiDialog
.hide();
9328 .removeData('dialog')
9329 .removeClass('ui-dialog-content ui-widget-content')
9330 .hide().appendTo('body');
9331 self
.uiDialog
.remove();
9333 if (self
.originalTitle
) {
9334 self
.element
.attr('title', self
.originalTitle
);
9340 widget: function() {
9341 return this.uiDialog
;
9344 close: function(event
) {
9348 if (false === self
._trigger('beforeClose', event
)) {
9353 self
.overlay
.destroy();
9355 self
.uiDialog
.unbind('keypress.ui-dialog');
9357 self
._isOpen
= false;
9359 if (self
.options
.hide
) {
9360 self
.uiDialog
.hide(self
.options
.hide
, function() {
9361 self
._trigger('close', event
);
9364 self
.uiDialog
.hide();
9365 self
._trigger('close', event
);
9368 $.ui
.dialog
.overlay
.resize();
9370 // adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
9371 if (self
.options
.modal
) {
9373 $('.ui-dialog').each(function() {
9374 if (this !== self
.uiDialog
[0]) {
9375 thisZ
= $(this).css('z-index');
9377 maxZ
= Math
.max(maxZ
, thisZ
);
9381 $.ui
.dialog
.maxZ
= maxZ
;
9387 isOpen: function() {
9388 return this._isOpen
;
9391 // the force parameter allows us to move modal dialogs to their correct
9393 moveToTop: function(force
, event
) {
9395 options
= self
.options
,
9398 if ((options
.modal
&& !force
) ||
9399 (!options
.stack
&& !options
.modal
)) {
9400 return self
._trigger('focus', event
);
9403 if (options
.zIndex
> $.ui
.dialog
.maxZ
) {
9404 $.ui
.dialog
.maxZ
= options
.zIndex
;
9407 $.ui
.dialog
.maxZ
+= 1;
9408 self
.overlay
.$el
.css('z-index', $.ui
.dialog
.overlay
.maxZ
= $.ui
.dialog
.maxZ
);
9411 //Save and then restore scroll since Opera 9.5+ resets when parent z-Index is changed.
9412 // http://ui.jquery.com/bugs/ticket/3193
9413 saveScroll
= { scrollTop
: self
.element
.scrollTop(), scrollLeft
: self
.element
.scrollLeft() };
9414 $.ui
.dialog
.maxZ
+= 1;
9415 self
.uiDialog
.css('z-index', $.ui
.dialog
.maxZ
);
9416 self
.element
.attr(saveScroll
);
9417 self
._trigger('focus', event
);
9423 if (this._isOpen
) { return; }
9426 options
= self
.options
,
9427 uiDialog
= self
.uiDialog
;
9429 self
.overlay
= options
.modal
? new $.ui
.dialog
.overlay(self
) : null;
9431 self
._position(options
.position
);
9432 uiDialog
.show(options
.show
);
9433 self
.moveToTop(true);
9435 // prevent tabbing out of modal dialogs
9436 if (options
.modal
) {
9437 uiDialog
.bind('keypress.ui-dialog', function(event
) {
9438 if (event
.keyCode
!== $.ui
.keyCode
.TAB
) {
9442 var tabbables
= $(':tabbable', this),
9443 first
= tabbables
.filter(':first'),
9444 last
= tabbables
.filter(':last');
9446 if (event
.target
=== last
[0] && !event
.shiftKey
) {
9449 } else if (event
.target
=== first
[0] && event
.shiftKey
) {
9456 // set focus to the first tabbable element in the content area or the first button
9457 // if there are no tabbable elements, set focus on the dialog itself
9458 $(self
.element
.find(':tabbable').get().concat(
9459 uiDialog
.find('.ui-dialog-buttonpane :tabbable').get().concat(
9460 uiDialog
.get()))).eq(0).focus();
9462 self
._isOpen
= true;
9463 self
._trigger('open');
9468 _createButtons: function(buttons
) {
9471 uiDialogButtonPane
= $('<div></div>')
9473 'ui-dialog-buttonpane ' +
9474 'ui-widget-content ' +
9475 'ui-helper-clearfix'
9477 uiButtonSet
= $( "<div></div>" )
9478 .addClass( "ui-dialog-buttonset" )
9479 .appendTo( uiDialogButtonPane
);
9481 // if we already have a button pane, remove it
9482 self
.uiDialog
.find('.ui-dialog-buttonpane').remove();
9484 if (typeof buttons
=== 'object' && buttons
!== null) {
9485 $.each(buttons
, function() {
9486 return !(hasButtons
= true);
9490 $.each(buttons
, function(name
, props
) {
9491 props
= $.isFunction( props
) ?
9492 { click
: props
, text
: name
} :
9494 var button
= $('<button type="button"></button>')
9496 props
.click
.apply(self
.element
[0], arguments
);
9498 .appendTo(uiButtonSet
);
9499 // can't use .attr( props, true ) with jQuery 1.3.2.
9500 $.each( props
, function( key
, value
) {
9501 if ( key
=== "click" ) {
9504 if ( key
in attrFn
) {
9505 button
[ key
]( value
);
9507 button
.attr( key
, value
);
9514 uiDialogButtonPane
.appendTo(self
.uiDialog
);
9518 _makeDraggable: function() {
9520 options
= self
.options
,
9524 function filteredUi(ui
) {
9526 position
: ui
.position
,
9531 self
.uiDialog
.draggable({
9532 cancel
: '.ui-dialog-content, .ui-dialog-titlebar-close',
9533 handle
: '.ui-dialog-titlebar',
9534 containment
: 'document',
9535 start: function(event
, ui
) {
9536 heightBeforeDrag
= options
.height
=== "auto" ? "auto" : $(this).height();
9537 $(this).height($(this).height()).addClass("ui-dialog-dragging");
9538 self
._trigger('dragStart', event
, filteredUi(ui
));
9540 drag: function(event
, ui
) {
9541 self
._trigger('drag', event
, filteredUi(ui
));
9543 stop: function(event
, ui
) {
9544 options
.position
= [ui
.position
.left
- doc
.scrollLeft(),
9545 ui
.position
.top
- doc
.scrollTop()];
9546 $(this).removeClass("ui-dialog-dragging").height(heightBeforeDrag
);
9547 self
._trigger('dragStop', event
, filteredUi(ui
));
9548 $.ui
.dialog
.overlay
.resize();
9553 _makeResizable: function(handles
) {
9554 handles
= (handles
=== undefined ? this.options
.resizable
: handles
);
9556 options
= self
.options
,
9557 // .ui-resizable has position: relative defined in the stylesheet
9558 // but dialogs have to use absolute or fixed positioning
9559 position
= self
.uiDialog
.css('position'),
9560 resizeHandles
= (typeof handles
=== 'string' ?
9562 'n,e,s,w,se,sw,ne,nw'
9565 function filteredUi(ui
) {
9567 originalPosition
: ui
.originalPosition
,
9568 originalSize
: ui
.originalSize
,
9569 position
: ui
.position
,
9574 self
.uiDialog
.resizable({
9575 cancel
: '.ui-dialog-content',
9576 containment
: 'document',
9577 alsoResize
: self
.element
,
9578 maxWidth
: options
.maxWidth
,
9579 maxHeight
: options
.maxHeight
,
9580 minWidth
: options
.minWidth
,
9581 minHeight
: self
._minHeight(),
9582 handles
: resizeHandles
,
9583 start: function(event
, ui
) {
9584 $(this).addClass("ui-dialog-resizing");
9585 self
._trigger('resizeStart', event
, filteredUi(ui
));
9587 resize: function(event
, ui
) {
9588 self
._trigger('resize', event
, filteredUi(ui
));
9590 stop: function(event
, ui
) {
9591 $(this).removeClass("ui-dialog-resizing");
9592 options
.height
= $(this).height();
9593 options
.width
= $(this).width();
9594 self
._trigger('resizeStop', event
, filteredUi(ui
));
9595 $.ui
.dialog
.overlay
.resize();
9598 .css('position', position
)
9599 .find('.ui-resizable-se').addClass('ui-icon ui-icon-grip-diagonal-se');
9602 _minHeight: function() {
9603 var options
= this.options
;
9605 if (options
.height
=== 'auto') {
9606 return options
.minHeight
;
9608 return Math
.min(options
.minHeight
, options
.height
);
9612 _position: function(position
) {
9618 // deep extending converts arrays to objects in jQuery <= 1.3.2 :-(
9619 // if (typeof position == 'string' || $.isArray(position)) {
9620 // myAt = $.isArray(position) ? position : position.split(' ');
9622 if (typeof position
=== 'string' || (typeof position
=== 'object' && '0' in position
)) {
9623 myAt
= position
.split
? position
.split(' ') : [position
[0], position
[1]];
9624 if (myAt
.length
=== 1) {
9628 $.each(['left', 'top'], function(i
, offsetPosition
) {
9629 if (+myAt
[i
] === myAt
[i
]) {
9630 offset
[i
] = myAt
[i
];
9631 myAt
[i
] = offsetPosition
;
9638 offset
: offset
.join(" ")
9642 position
= $.extend({}, $.ui
.dialog
.prototype.options
.position
, position
);
9644 position
= $.ui
.dialog
.prototype.options
.position
;
9647 // need to show the dialog to get the actual offset in the position plugin
9648 isVisible
= this.uiDialog
.is(':visible');
9650 this.uiDialog
.show();
9653 // workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
9654 .css({ top
: 0, left
: 0 })
9655 .position($.extend({ of: window
}, position
));
9657 this.uiDialog
.hide();
9661 _setOptions: function( options
) {
9663 resizableOptions
= {},
9666 $.each( options
, function( key
, value
) {
9667 self
._setOption( key
, value
);
9669 if ( key
in sizeRelatedOptions
) {
9672 if ( key
in resizableRelatedOptions
) {
9673 resizableOptions
[ key
] = value
;
9680 if ( this.uiDialog
.is( ":data(resizable)" ) ) {
9681 this.uiDialog
.resizable( "option", resizableOptions
);
9685 _setOption: function(key
, value
){
9687 uiDialog
= self
.uiDialog
;
9690 //handling of deprecated beforeclose (vs beforeClose) option
9691 //Ticket #4669 http://dev.jqueryui.com/ticket/4669
9692 //TODO: remove in 1.9pre
9694 key
= "beforeClose";
9697 self
._createButtons(value
);
9700 // ensure that we always pass a string
9701 self
.uiDialogTitlebarCloseText
.text("" + value
);
9705 .removeClass(self
.options
.dialogClass
)
9706 .addClass(uiDialogClasses
+ value
);
9710 uiDialog
.addClass('ui-dialog-disabled');
9712 uiDialog
.removeClass('ui-dialog-disabled');
9716 var isDraggable
= uiDialog
.is( ":data(draggable)" );
9717 if ( isDraggable
&& !value
) {
9718 uiDialog
.draggable( "destroy" );
9721 if ( !isDraggable
&& value
) {
9722 self
._makeDraggable();
9726 self
._position(value
);
9729 // currently resizable, becoming non-resizable
9730 var isResizable
= uiDialog
.is( ":data(resizable)" );
9731 if (isResizable
&& !value
) {
9732 uiDialog
.resizable('destroy');
9735 // currently resizable, changing handles
9736 if (isResizable
&& typeof value
=== 'string') {
9737 uiDialog
.resizable('option', 'handles', value
);
9740 // currently non-resizable, becoming resizable
9741 if (!isResizable
&& value
!== false) {
9742 self
._makeResizable(value
);
9746 // convert whatever was passed in o a string, for html() to not throw up
9747 $(".ui-dialog-title", self
.uiDialogTitlebar
).html("" + (value
|| ' '));
9751 $.Widget
.prototype._setOption
.apply(self
, arguments
);
9755 /* If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
9756 * divs will both have width and height set, so we need to reset them
9758 var options
= this.options
,
9761 isVisible
= this.uiDialog
.is( ":visible" );
9763 // reset content sizing
9764 this.element
.show().css({
9770 if (options
.minWidth
> options
.width
) {
9771 options
.width
= options
.minWidth
;
9774 // reset wrapper sizing
9775 // determine the height of all the non-content elements
9776 nonContentHeight
= this.uiDialog
.css({
9778 width
: options
.width
9781 minContentHeight
= Math
.max( 0, options
.minHeight
- nonContentHeight
);
9783 if ( options
.height
=== "auto" ) {
9784 // only needed for IE6 support
9785 if ( $.support
.minHeight
) {
9787 minHeight
: minContentHeight
,
9791 this.uiDialog
.show();
9792 var autoHeight
= this.element
.css( "height", "auto" ).height();
9794 this.uiDialog
.hide();
9796 this.element
.height( Math
.max( autoHeight
, minContentHeight
) );
9799 this.element
.height( Math
.max( options
.height
- nonContentHeight
, 0 ) );
9802 if (this.uiDialog
.is(':data(resizable)')) {
9803 this.uiDialog
.resizable('option', 'minHeight', this._minHeight());
9808 $.extend($.ui
.dialog
, {
9814 getTitleId: function($el
) {
9815 var id
= $el
.attr('id');
9820 return 'ui-dialog-title-' + id
;
9823 overlay: function(dialog
) {
9824 this.$el
= $.ui
.dialog
.overlay
.create(dialog
);
9828 $.extend($.ui
.dialog
.overlay
, {
9830 // reuse old instances due to IE memory leak with alpha transparency (see #5185)
9833 events
: $.map('focus,mousedown,mouseup,keydown,keypress,click'.split(','),
9834 function(event
) { return event
+ '.dialog-overlay'; }).join(' '),
9835 create: function(dialog
) {
9836 if (this.instances
.length
=== 0) {
9837 // prevent use of anchors and inputs
9838 // we use a setTimeout in case the overlay is created from an
9839 // event that we're going to be cancelling (see #2804)
9840 setTimeout(function() {
9841 // handle $(el).dialog().dialog('close') (see #4065)
9842 if ($.ui
.dialog
.overlay
.instances
.length
) {
9843 $(document
).bind($.ui
.dialog
.overlay
.events
, function(event
) {
9844 // stop events if the z-index of the target is < the z-index of the overlay
9845 // we cannot return true when we don't want to cancel the event (#3523)
9846 if ($(event
.target
).zIndex() < $.ui
.dialog
.overlay
.maxZ
) {
9853 // allow closing by pressing the escape key
9854 $(document
).bind('keydown.dialog-overlay', function(event
) {
9855 if (dialog
.options
.closeOnEscape
&& !event
.isDefaultPrevented() && event
.keyCode
&&
9856 event
.keyCode
=== $.ui
.keyCode
.ESCAPE
) {
9858 dialog
.close(event
);
9859 event
.preventDefault();
9863 // handle window resize
9864 $(window
).bind('resize.dialog-overlay', $.ui
.dialog
.overlay
.resize
);
9867 var $el
= (this.oldInstances
.pop() || $('<div></div>').addClass('ui-widget-overlay'))
9868 .appendTo(document
.body
)
9870 width
: this.width(),
9871 height
: this.height()
9874 if ($.fn
.bgiframe
) {
9878 this.instances
.push($el
);
9882 destroy: function($el
) {
9883 var indexOf
= $.inArray($el
, this.instances
);
9885 this.oldInstances
.push(this.instances
.splice(indexOf
, 1)[0]);
9888 if (this.instances
.length
=== 0) {
9889 $([document
, window
]).unbind('.dialog-overlay');
9894 // adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
9896 $.each(this.instances
, function() {
9897 maxZ
= Math
.max(maxZ
, this.css('z-index'));
9902 height: function() {
9906 if ($.browser
.msie
&& $.browser
.version
< 7) {
9907 scrollHeight
= Math
.max(
9908 document
.documentElement
.scrollHeight
,
9909 document
.body
.scrollHeight
9911 offsetHeight
= Math
.max(
9912 document
.documentElement
.offsetHeight
,
9913 document
.body
.offsetHeight
9916 if (scrollHeight
< offsetHeight
) {
9917 return $(window
).height() + 'px';
9919 return scrollHeight
+ 'px';
9921 // handle "good" browsers
9923 return $(document
).height() + 'px';
9931 if ( $.browser
.msie
) {
9932 scrollWidth
= Math
.max(
9933 document
.documentElement
.scrollWidth
,
9934 document
.body
.scrollWidth
9936 offsetWidth
= Math
.max(
9937 document
.documentElement
.offsetWidth
,
9938 document
.body
.offsetWidth
9941 if (scrollWidth
< offsetWidth
) {
9942 return $(window
).width() + 'px';
9944 return scrollWidth
+ 'px';
9946 // handle "good" browsers
9948 return $(document
).width() + 'px';
9952 resize: function() {
9953 /* If the dialog is draggable and the user drags it past the
9954 * right edge of the window, the document becomes wider so we
9955 * need to stretch the overlay. If the user then drags the
9956 * dialog back to the left, the document will become narrower,
9957 * so we need to shrink the overlay to the appropriate size.
9958 * This is handled by shrinking the overlay before setting it
9959 * to the full document size.
9961 var $overlays
= $([]);
9962 $.each($.ui
.dialog
.overlay
.instances
, function() {
9963 $overlays
= $overlays
.add(this);
9970 width
: $.ui
.dialog
.overlay
.width(),
9971 height
: $.ui
.dialog
.overlay
.height()
9976 $.extend($.ui
.dialog
.overlay
.prototype, {
9977 destroy: function() {
9978 $.ui
.dialog
.overlay
.destroy(this.$el
);
9984 * jQuery UI Position 1.8.16
9986 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
9987 * Dual licensed under the MIT or GPL Version 2 licenses.
9988 * http://jquery.org/license
9990 * http://docs.jquery.com/UI/Position
9992 (function( $, undefined ) {
9996 var horizontalPositions
= /left|center|right/,
9997 verticalPositions
= /top|center|bottom/,
9999 _position
= $.fn
.position
,
10000 _offset
= $.fn
.offset
;
10002 $.fn
.position = function( options
) {
10003 if ( !options
|| !options
.of ) {
10004 return _position
.apply( this, arguments
);
10007 // make a copy, we don't want to modify arguments
10008 options
= $.extend( {}, options
);
10010 var target
= $( options
.of ),
10011 targetElem
= target
[0],
10012 collision
= ( options
.collision
|| "flip" ).split( " " ),
10013 offset
= options
.offset
? options
.offset
.split( " " ) : [ 0, 0 ],
10018 if ( targetElem
.nodeType
=== 9 ) {
10019 targetWidth
= target
.width();
10020 targetHeight
= target
.height();
10021 basePosition
= { top
: 0, left
: 0 };
10022 // TODO: use $.isWindow() in 1.9
10023 } else if ( targetElem
.setTimeout
) {
10024 targetWidth
= target
.width();
10025 targetHeight
= target
.height();
10026 basePosition
= { top
: target
.scrollTop(), left
: target
.scrollLeft() };
10027 } else if ( targetElem
.preventDefault
) {
10028 // force left top to allow flipping
10029 options
.at
= "left top";
10030 targetWidth
= targetHeight
= 0;
10031 basePosition
= { top
: options
.of.pageY
, left
: options
.of.pageX
};
10033 targetWidth
= target
.outerWidth();
10034 targetHeight
= target
.outerHeight();
10035 basePosition
= target
.offset();
10038 // force my and at to have valid horizontal and veritcal positions
10039 // if a value is missing or invalid, it will be converted to center
10040 $.each( [ "my", "at" ], function() {
10041 var pos
= ( options
[this] || "" ).split( " " );
10042 if ( pos
.length
=== 1) {
10043 pos
= horizontalPositions
.test( pos
[0] ) ?
10044 pos
.concat( [center
] ) :
10045 verticalPositions
.test( pos
[0] ) ?
10046 [ center
].concat( pos
) :
10047 [ center
, center
];
10049 pos
[ 0 ] = horizontalPositions
.test( pos
[0] ) ? pos
[ 0 ] : center
;
10050 pos
[ 1 ] = verticalPositions
.test( pos
[1] ) ? pos
[ 1 ] : center
;
10051 options
[ this ] = pos
;
10054 // normalize collision option
10055 if ( collision
.length
=== 1 ) {
10056 collision
[ 1 ] = collision
[ 0 ];
10059 // normalize offset option
10060 offset
[ 0 ] = parseInt( offset
[0], 10 ) || 0;
10061 if ( offset
.length
=== 1 ) {
10062 offset
[ 1 ] = offset
[ 0 ];
10064 offset
[ 1 ] = parseInt( offset
[1], 10 ) || 0;
10066 if ( options
.at
[0] === "right" ) {
10067 basePosition
.left
+= targetWidth
;
10068 } else if ( options
.at
[0] === center
) {
10069 basePosition
.left
+= targetWidth
/ 2;
10072 if ( options
.at
[1] === "bottom" ) {
10073 basePosition
.top
+= targetHeight
;
10074 } else if ( options
.at
[1] === center
) {
10075 basePosition
.top
+= targetHeight
/ 2;
10078 basePosition
.left
+= offset
[ 0 ];
10079 basePosition
.top
+= offset
[ 1 ];
10081 return this.each(function() {
10082 var elem
= $( this ),
10083 elemWidth
= elem
.outerWidth(),
10084 elemHeight
= elem
.outerHeight(),
10085 marginLeft
= parseInt( $.curCSS( this, "marginLeft", true ) ) || 0,
10086 marginTop
= parseInt( $.curCSS( this, "marginTop", true ) ) || 0,
10087 collisionWidth
= elemWidth
+ marginLeft
+
10088 ( parseInt( $.curCSS( this, "marginRight", true ) ) || 0 ),
10089 collisionHeight
= elemHeight
+ marginTop
+
10090 ( parseInt( $.curCSS( this, "marginBottom", true ) ) || 0 ),
10091 position
= $.extend( {}, basePosition
),
10094 if ( options
.my
[0] === "right" ) {
10095 position
.left
-= elemWidth
;
10096 } else if ( options
.my
[0] === center
) {
10097 position
.left
-= elemWidth
/ 2;
10100 if ( options
.my
[1] === "bottom" ) {
10101 position
.top
-= elemHeight
;
10102 } else if ( options
.my
[1] === center
) {
10103 position
.top
-= elemHeight
/ 2;
10106 // prevent fractions (see #5280)
10107 position
.left
= Math
.round( position
.left
);
10108 position
.top
= Math
.round( position
.top
);
10110 collisionPosition
= {
10111 left
: position
.left
- marginLeft
,
10112 top
: position
.top
- marginTop
10115 $.each( [ "left", "top" ], function( i
, dir
) {
10116 if ( $.ui
.position
[ collision
[i
] ] ) {
10117 $.ui
.position
[ collision
[i
] ][ dir
]( position
, {
10118 targetWidth
: targetWidth
,
10119 targetHeight
: targetHeight
,
10120 elemWidth
: elemWidth
,
10121 elemHeight
: elemHeight
,
10122 collisionPosition
: collisionPosition
,
10123 collisionWidth
: collisionWidth
,
10124 collisionHeight
: collisionHeight
,
10132 if ( $.fn
.bgiframe
) {
10135 elem
.offset( $.extend( position
, { using
: options
.using
} ) );
10141 left: function( position
, data
) {
10142 var win
= $( window
),
10143 over
= data
.collisionPosition
.left
+ data
.collisionWidth
- win
.width() - win
.scrollLeft();
10144 position
.left
= over
> 0 ? position
.left
- over
: Math
.max( position
.left
- data
.collisionPosition
.left
, position
.left
);
10146 top: function( position
, data
) {
10147 var win
= $( window
),
10148 over
= data
.collisionPosition
.top
+ data
.collisionHeight
- win
.height() - win
.scrollTop();
10149 position
.top
= over
> 0 ? position
.top
- over
: Math
.max( position
.top
- data
.collisionPosition
.top
, position
.top
);
10154 left: function( position
, data
) {
10155 if ( data
.at
[0] === center
) {
10158 var win
= $( window
),
10159 over
= data
.collisionPosition
.left
+ data
.collisionWidth
- win
.width() - win
.scrollLeft(),
10160 myOffset
= data
.my
[ 0 ] === "left" ?
10162 data
.my
[ 0 ] === "right" ?
10165 atOffset
= data
.at
[ 0 ] === "left" ?
10168 offset
= -2 * data
.offset
[ 0 ];
10169 position
.left
+= data
.collisionPosition
.left
< 0 ?
10170 myOffset
+ atOffset
+ offset
:
10172 myOffset
+ atOffset
+ offset
:
10175 top: function( position
, data
) {
10176 if ( data
.at
[1] === center
) {
10179 var win
= $( window
),
10180 over
= data
.collisionPosition
.top
+ data
.collisionHeight
- win
.height() - win
.scrollTop(),
10181 myOffset
= data
.my
[ 1 ] === "top" ?
10183 data
.my
[ 1 ] === "bottom" ?
10186 atOffset
= data
.at
[ 1 ] === "top" ?
10187 data
.targetHeight
:
10188 -data
.targetHeight
,
10189 offset
= -2 * data
.offset
[ 1 ];
10190 position
.top
+= data
.collisionPosition
.top
< 0 ?
10191 myOffset
+ atOffset
+ offset
:
10193 myOffset
+ atOffset
+ offset
:
10199 // offset setter from jQuery 1.4
10200 if ( !$.offset
.setOffset
) {
10201 $.offset
.setOffset = function( elem
, options
) {
10202 // set position first, in-case top/left are set even on static elem
10203 if ( /static/.test( $.curCSS( elem
, "position" ) ) ) {
10204 elem
.style
.position
= "relative";
10206 var curElem
= $( elem
),
10207 curOffset
= curElem
.offset(),
10208 curTop
= parseInt( $.curCSS( elem
, "top", true ), 10 ) || 0,
10209 curLeft
= parseInt( $.curCSS( elem
, "left", true ), 10) || 0,
10211 top
: (options
.top
- curOffset
.top
) + curTop
,
10212 left
: (options
.left
- curOffset
.left
) + curLeft
10215 if ( 'using' in options
) {
10216 options
.using
.call( elem
, props
);
10218 curElem
.css( props
);
10222 $.fn
.offset = function( options
) {
10223 var elem
= this[ 0 ];
10224 if ( !elem
|| !elem
.ownerDocument
) { return null; }
10226 return this.each(function() {
10227 $.offset
.setOffset( this, options
);
10230 return _offset
.call( this );
10236 * jQuery UI Progressbar 1.8.16
10238 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
10239 * Dual licensed under the MIT or GPL Version 2 licenses.
10240 * http://jquery.org/license
10242 * http://docs.jquery.com/UI/Progressbar
10245 * jquery.ui.core.js
10246 * jquery.ui.widget.js
10248 (function( $, undefined ) {
10250 $.widget( "ui.progressbar", {
10258 _create: function() {
10260 .addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
10262 role
: "progressbar",
10263 "aria-valuemin": this.min
,
10264 "aria-valuemax": this.options
.max
,
10265 "aria-valuenow": this._value()
10268 this.valueDiv
= $( "<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>" )
10269 .appendTo( this.element
);
10271 this.oldValue
= this._value();
10272 this._refreshValue();
10275 destroy: function() {
10277 .removeClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
10278 .removeAttr( "role" )
10279 .removeAttr( "aria-valuemin" )
10280 .removeAttr( "aria-valuemax" )
10281 .removeAttr( "aria-valuenow" );
10283 this.valueDiv
.remove();
10285 $.Widget
.prototype.destroy
.apply( this, arguments
);
10288 value: function( newValue
) {
10289 if ( newValue
=== undefined ) {
10290 return this._value();
10293 this._setOption( "value", newValue
);
10297 _setOption: function( key
, value
) {
10298 if ( key
=== "value" ) {
10299 this.options
.value
= value
;
10300 this._refreshValue();
10301 if ( this._value() === this.options
.max
) {
10302 this._trigger( "complete" );
10306 $.Widget
.prototype._setOption
.apply( this, arguments
);
10309 _value: function() {
10310 var val
= this.options
.value
;
10311 // normalize invalid value
10312 if ( typeof val
!== "number" ) {
10315 return Math
.min( this.options
.max
, Math
.max( this.min
, val
) );
10318 _percentage: function() {
10319 return 100 * this._value() / this.options
.max
;
10322 _refreshValue: function() {
10323 var value
= this.value();
10324 var percentage
= this._percentage();
10326 if ( this.oldValue
!== value
) {
10327 this.oldValue
= value
;
10328 this._trigger( "change" );
10332 .toggle( value
> this.min
)
10333 .toggleClass( "ui-corner-right", value
=== this.options
.max
)
10334 .width( percentage
.toFixed(0) + "%" );
10335 this.element
.attr( "aria-valuenow", value
);
10339 $.extend( $.ui
.progressbar
, {
10345 * jQuery UI Slider 1.8.16
10347 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
10348 * Dual licensed under the MIT or GPL Version 2 licenses.
10349 * http://jquery.org/license
10351 * http://docs.jquery.com/UI/Slider
10354 * jquery.ui.core.js
10355 * jquery.ui.mouse.js
10356 * jquery.ui.widget.js
10358 (function( $, undefined ) {
10360 // number of pages in a slider
10361 // (how many times can you page up/down to go through the whole range)
10364 $.widget( "ui.slider", $.ui
.mouse
, {
10366 widgetEventPrefix
: "slide",
10373 orientation
: "horizontal",
10380 _create: function() {
10383 existingHandles
= this.element
.find( ".ui-slider-handle" ).addClass( "ui-state-default ui-corner-all" ),
10384 handle
= "<a class='ui-slider-handle ui-state-default ui-corner-all' href='#'></a>",
10385 handleCount
= ( o
.values
&& o
.values
.length
) || 1,
10388 this._keySliding
= false;
10389 this._mouseSliding
= false;
10390 this._animateOff
= true;
10391 this._handleIndex
= null;
10392 this._detectOrientation();
10396 .addClass( "ui-slider" +
10397 " ui-slider-" + this.orientation
+
10399 " ui-widget-content" +
10401 ( o
.disabled
? " ui-slider-disabled ui-disabled" : "" ) );
10403 this.range
= $([]);
10406 if ( o
.range
=== true ) {
10408 o
.values
= [ this._valueMin(), this._valueMin() ];
10410 if ( o
.values
.length
&& o
.values
.length
!== 2 ) {
10411 o
.values
= [ o
.values
[0], o
.values
[0] ];
10415 this.range
= $( "<div></div>" )
10416 .appendTo( this.element
)
10417 .addClass( "ui-slider-range" +
10418 // note: this isn't the most fittingly semantic framework class for this element,
10419 // but worked best visually with a variety of themes
10420 " ui-widget-header" +
10421 ( ( o
.range
=== "min" || o
.range
=== "max" ) ? " ui-slider-range-" + o
.range
: "" ) );
10424 for ( var i
= existingHandles
.length
; i
< handleCount
; i
+= 1 ) {
10425 handles
.push( handle
);
10428 this.handles
= existingHandles
.add( $( handles
.join( "" ) ).appendTo( self
.element
) );
10430 this.handle
= this.handles
.eq( 0 );
10432 this.handles
.add( this.range
).filter( "a" )
10433 .click(function( event
) {
10434 event
.preventDefault();
10436 .hover(function() {
10437 if ( !o
.disabled
) {
10438 $( this ).addClass( "ui-state-hover" );
10441 $( this ).removeClass( "ui-state-hover" );
10443 .focus(function() {
10444 if ( !o
.disabled
) {
10445 $( ".ui-slider .ui-state-focus" ).removeClass( "ui-state-focus" );
10446 $( this ).addClass( "ui-state-focus" );
10452 $( this ).removeClass( "ui-state-focus" );
10455 this.handles
.each(function( i
) {
10456 $( this ).data( "index.ui-slider-handle", i
);
10460 .keydown(function( event
) {
10462 index
= $( this ).data( "index.ui-slider-handle" ),
10468 if ( self
.options
.disabled
) {
10472 switch ( event
.keyCode
) {
10473 case $.ui
.keyCode
.HOME
:
10474 case $.ui
.keyCode
.END
:
10475 case $.ui
.keyCode
.PAGE_UP
:
10476 case $.ui
.keyCode
.PAGE_DOWN
:
10477 case $.ui
.keyCode
.UP
:
10478 case $.ui
.keyCode
.RIGHT
:
10479 case $.ui
.keyCode
.DOWN
:
10480 case $.ui
.keyCode
.LEFT
:
10482 if ( !self
._keySliding
) {
10483 self
._keySliding
= true;
10484 $( this ).addClass( "ui-state-active" );
10485 allowed
= self
._start( event
, index
);
10486 if ( allowed
=== false ) {
10493 step
= self
.options
.step
;
10494 if ( self
.options
.values
&& self
.options
.values
.length
) {
10495 curVal
= newVal
= self
.values( index
);
10497 curVal
= newVal
= self
.value();
10500 switch ( event
.keyCode
) {
10501 case $.ui
.keyCode
.HOME
:
10502 newVal
= self
._valueMin();
10504 case $.ui
.keyCode
.END
:
10505 newVal
= self
._valueMax();
10507 case $.ui
.keyCode
.PAGE_UP
:
10508 newVal
= self
._trimAlignValue( curVal
+ ( (self
._valueMax() - self
._valueMin()) / numPages
) );
10510 case $.ui
.keyCode
.PAGE_DOWN
:
10511 newVal
= self
._trimAlignValue( curVal
- ( (self
._valueMax() - self
._valueMin()) / numPages
) );
10513 case $.ui
.keyCode
.UP
:
10514 case $.ui
.keyCode
.RIGHT
:
10515 if ( curVal
=== self
._valueMax() ) {
10518 newVal
= self
._trimAlignValue( curVal
+ step
);
10520 case $.ui
.keyCode
.DOWN
:
10521 case $.ui
.keyCode
.LEFT
:
10522 if ( curVal
=== self
._valueMin() ) {
10525 newVal
= self
._trimAlignValue( curVal
- step
);
10529 self
._slide( event
, index
, newVal
);
10534 .keyup(function( event
) {
10535 var index
= $( this ).data( "index.ui-slider-handle" );
10537 if ( self
._keySliding
) {
10538 self
._keySliding
= false;
10539 self
._stop( event
, index
);
10540 self
._change( event
, index
);
10541 $( this ).removeClass( "ui-state-active" );
10546 this._refreshValue();
10548 this._animateOff
= false;
10551 destroy: function() {
10552 this.handles
.remove();
10553 this.range
.remove();
10556 .removeClass( "ui-slider" +
10557 " ui-slider-horizontal" +
10558 " ui-slider-vertical" +
10559 " ui-slider-disabled" +
10561 " ui-widget-content" +
10563 .removeData( "slider" )
10564 .unbind( ".slider" );
10566 this._mouseDestroy();
10571 _mouseCapture: function( event
) {
10572 var o
= this.options
,
10583 if ( o
.disabled
) {
10587 this.elementSize
= {
10588 width
: this.element
.outerWidth(),
10589 height
: this.element
.outerHeight()
10591 this.elementOffset
= this.element
.offset();
10593 position
= { x
: event
.pageX
, y
: event
.pageY
};
10594 normValue
= this._normValueFromMouse( position
);
10595 distance
= this._valueMax() - this._valueMin() + 1;
10597 this.handles
.each(function( i
) {
10598 var thisDistance
= Math
.abs( normValue
- self
.values(i
) );
10599 if ( distance
> thisDistance
) {
10600 distance
= thisDistance
;
10601 closestHandle
= $( this );
10606 // workaround for bug #3736 (if both handles of a range are at 0,
10607 // the first is always used as the one with least distance,
10608 // and moving it is obviously prevented by preventing negative ranges)
10609 if( o
.range
=== true && this.values(1) === o
.min
) {
10611 closestHandle
= $( this.handles
[index
] );
10614 allowed
= this._start( event
, index
);
10615 if ( allowed
=== false ) {
10618 this._mouseSliding
= true;
10620 self
._handleIndex
= index
;
10623 .addClass( "ui-state-active" )
10626 offset
= closestHandle
.offset();
10627 mouseOverHandle
= !$( event
.target
).parents().andSelf().is( ".ui-slider-handle" );
10628 this._clickOffset
= mouseOverHandle
? { left
: 0, top
: 0 } : {
10629 left
: event
.pageX
- offset
.left
- ( closestHandle
.width() / 2 ),
10630 top
: event
.pageY
- offset
.top
-
10631 ( closestHandle
.height() / 2 ) -
10632 ( parseInt( closestHandle
.css("borderTopWidth"), 10 ) || 0 ) -
10633 ( parseInt( closestHandle
.css("borderBottomWidth"), 10 ) || 0) +
10634 ( parseInt( closestHandle
.css("marginTop"), 10 ) || 0)
10637 if ( !this.handles
.hasClass( "ui-state-hover" ) ) {
10638 this._slide( event
, index
, normValue
);
10640 this._animateOff
= true;
10644 _mouseStart: function( event
) {
10648 _mouseDrag: function( event
) {
10649 var position
= { x
: event
.pageX
, y
: event
.pageY
},
10650 normValue
= this._normValueFromMouse( position
);
10652 this._slide( event
, this._handleIndex
, normValue
);
10657 _mouseStop: function( event
) {
10658 this.handles
.removeClass( "ui-state-active" );
10659 this._mouseSliding
= false;
10661 this._stop( event
, this._handleIndex
);
10662 this._change( event
, this._handleIndex
);
10664 this._handleIndex
= null;
10665 this._clickOffset
= null;
10666 this._animateOff
= false;
10671 _detectOrientation: function() {
10672 this.orientation
= ( this.options
.orientation
=== "vertical" ) ? "vertical" : "horizontal";
10675 _normValueFromMouse: function( position
) {
10682 if ( this.orientation
=== "horizontal" ) {
10683 pixelTotal
= this.elementSize
.width
;
10684 pixelMouse
= position
.x
- this.elementOffset
.left
- ( this._clickOffset
? this._clickOffset
.left
: 0 );
10686 pixelTotal
= this.elementSize
.height
;
10687 pixelMouse
= position
.y
- this.elementOffset
.top
- ( this._clickOffset
? this._clickOffset
.top
: 0 );
10690 percentMouse
= ( pixelMouse
/ pixelTotal
);
10691 if ( percentMouse
> 1 ) {
10694 if ( percentMouse
< 0 ) {
10697 if ( this.orientation
=== "vertical" ) {
10698 percentMouse
= 1 - percentMouse
;
10701 valueTotal
= this._valueMax() - this._valueMin();
10702 valueMouse
= this._valueMin() + percentMouse
* valueTotal
;
10704 return this._trimAlignValue( valueMouse
);
10707 _start: function( event
, index
) {
10709 handle
: this.handles
[ index
],
10710 value
: this.value()
10712 if ( this.options
.values
&& this.options
.values
.length
) {
10713 uiHash
.value
= this.values( index
);
10714 uiHash
.values
= this.values();
10716 return this._trigger( "start", event
, uiHash
);
10719 _slide: function( event
, index
, newVal
) {
10724 if ( this.options
.values
&& this.options
.values
.length
) {
10725 otherVal
= this.values( index
? 0 : 1 );
10727 if ( ( this.options
.values
.length
=== 2 && this.options
.range
=== true ) &&
10728 ( ( index
=== 0 && newVal
> otherVal
) || ( index
=== 1 && newVal
< otherVal
) )
10733 if ( newVal
!== this.values( index
) ) {
10734 newValues
= this.values();
10735 newValues
[ index
] = newVal
;
10736 // A slide can be canceled by returning false from the slide callback
10737 allowed
= this._trigger( "slide", event
, {
10738 handle
: this.handles
[ index
],
10742 otherVal
= this.values( index
? 0 : 1 );
10743 if ( allowed
!== false ) {
10744 this.values( index
, newVal
, true );
10748 if ( newVal
!== this.value() ) {
10749 // A slide can be canceled by returning false from the slide callback
10750 allowed
= this._trigger( "slide", event
, {
10751 handle
: this.handles
[ index
],
10754 if ( allowed
!== false ) {
10755 this.value( newVal
);
10761 _stop: function( event
, index
) {
10763 handle
: this.handles
[ index
],
10764 value
: this.value()
10766 if ( this.options
.values
&& this.options
.values
.length
) {
10767 uiHash
.value
= this.values( index
);
10768 uiHash
.values
= this.values();
10771 this._trigger( "stop", event
, uiHash
);
10774 _change: function( event
, index
) {
10775 if ( !this._keySliding
&& !this._mouseSliding
) {
10777 handle
: this.handles
[ index
],
10778 value
: this.value()
10780 if ( this.options
.values
&& this.options
.values
.length
) {
10781 uiHash
.value
= this.values( index
);
10782 uiHash
.values
= this.values();
10785 this._trigger( "change", event
, uiHash
);
10789 value: function( newValue
) {
10790 if ( arguments
.length
) {
10791 this.options
.value
= this._trimAlignValue( newValue
);
10792 this._refreshValue();
10793 this._change( null, 0 );
10797 return this._value();
10800 values: function( index
, newValue
) {
10805 if ( arguments
.length
> 1 ) {
10806 this.options
.values
[ index
] = this._trimAlignValue( newValue
);
10807 this._refreshValue();
10808 this._change( null, index
);
10812 if ( arguments
.length
) {
10813 if ( $.isArray( arguments
[ 0 ] ) ) {
10814 vals
= this.options
.values
;
10815 newValues
= arguments
[ 0 ];
10816 for ( i
= 0; i
< vals
.length
; i
+= 1 ) {
10817 vals
[ i
] = this._trimAlignValue( newValues
[ i
] );
10818 this._change( null, i
);
10820 this._refreshValue();
10822 if ( this.options
.values
&& this.options
.values
.length
) {
10823 return this._values( index
);
10825 return this.value();
10829 return this._values();
10833 _setOption: function( key
, value
) {
10837 if ( $.isArray( this.options
.values
) ) {
10838 valsLength
= this.options
.values
.length
;
10841 $.Widget
.prototype._setOption
.apply( this, arguments
);
10846 this.handles
.filter( ".ui-state-focus" ).blur();
10847 this.handles
.removeClass( "ui-state-hover" );
10848 this.handles
.propAttr( "disabled", true );
10849 this.element
.addClass( "ui-disabled" );
10851 this.handles
.propAttr( "disabled", false );
10852 this.element
.removeClass( "ui-disabled" );
10855 case "orientation":
10856 this._detectOrientation();
10858 .removeClass( "ui-slider-horizontal ui-slider-vertical" )
10859 .addClass( "ui-slider-" + this.orientation
);
10860 this._refreshValue();
10863 this._animateOff
= true;
10864 this._refreshValue();
10865 this._change( null, 0 );
10866 this._animateOff
= false;
10869 this._animateOff
= true;
10870 this._refreshValue();
10871 for ( i
= 0; i
< valsLength
; i
+= 1 ) {
10872 this._change( null, i
);
10874 this._animateOff
= false;
10879 //internal value getter
10880 // _value() returns value trimmed by min and max, aligned by step
10881 _value: function() {
10882 var val
= this.options
.value
;
10883 val
= this._trimAlignValue( val
);
10888 //internal values getter
10889 // _values() returns array of values trimmed by min and max, aligned by step
10890 // _values( index ) returns single value trimmed by min and max, aligned by step
10891 _values: function( index
) {
10896 if ( arguments
.length
) {
10897 val
= this.options
.values
[ index
];
10898 val
= this._trimAlignValue( val
);
10902 // .slice() creates a copy of the array
10903 // this copy gets trimmed by min and max and then returned
10904 vals
= this.options
.values
.slice();
10905 for ( i
= 0; i
< vals
.length
; i
+= 1) {
10906 vals
[ i
] = this._trimAlignValue( vals
[ i
] );
10913 // returns the step-aligned value that val is closest to, between (inclusive) min and max
10914 _trimAlignValue: function( val
) {
10915 if ( val
<= this._valueMin() ) {
10916 return this._valueMin();
10918 if ( val
>= this._valueMax() ) {
10919 return this._valueMax();
10921 var step
= ( this.options
.step
> 0 ) ? this.options
.step
: 1,
10922 valModStep
= (val
- this._valueMin()) % step
,
10923 alignValue
= val
- valModStep
;
10925 if ( Math
.abs(valModStep
) * 2 >= step
) {
10926 alignValue
+= ( valModStep
> 0 ) ? step
: ( -step
);
10929 // Since JavaScript has problems with large floats, round
10930 // the final value to 5 digits after the decimal point (see #4124)
10931 return parseFloat( alignValue
.toFixed(5) );
10934 _valueMin: function() {
10935 return this.options
.min
;
10938 _valueMax: function() {
10939 return this.options
.max
;
10942 _refreshValue: function() {
10943 var oRange
= this.options
.range
,
10946 animate
= ( !this._animateOff
) ? o
.animate
: false,
10954 if ( this.options
.values
&& this.options
.values
.length
) {
10955 this.handles
.each(function( i
, j
) {
10956 valPercent
= ( self
.values(i
) - self
._valueMin() ) / ( self
._valueMax() - self
._valueMin() ) * 100;
10957 _set
[ self
.orientation
=== "horizontal" ? "left" : "bottom" ] = valPercent
+ "%";
10958 $( this ).stop( 1, 1 )[ animate
? "animate" : "css" ]( _set
, o
.animate
);
10959 if ( self
.options
.range
=== true ) {
10960 if ( self
.orientation
=== "horizontal" ) {
10962 self
.range
.stop( 1, 1 )[ animate
? "animate" : "css" ]( { left
: valPercent
+ "%" }, o
.animate
);
10965 self
.range
[ animate
? "animate" : "css" ]( { width
: ( valPercent
- lastValPercent
) + "%" }, { queue
: false, duration
: o
.animate
} );
10969 self
.range
.stop( 1, 1 )[ animate
? "animate" : "css" ]( { bottom
: ( valPercent
) + "%" }, o
.animate
);
10972 self
.range
[ animate
? "animate" : "css" ]( { height
: ( valPercent
- lastValPercent
) + "%" }, { queue
: false, duration
: o
.animate
} );
10976 lastValPercent
= valPercent
;
10979 value
= this.value();
10980 valueMin
= this._valueMin();
10981 valueMax
= this._valueMax();
10982 valPercent
= ( valueMax
!== valueMin
) ?
10983 ( value
- valueMin
) / ( valueMax
- valueMin
) * 100 :
10985 _set
[ self
.orientation
=== "horizontal" ? "left" : "bottom" ] = valPercent
+ "%";
10986 this.handle
.stop( 1, 1 )[ animate
? "animate" : "css" ]( _set
, o
.animate
);
10988 if ( oRange
=== "min" && this.orientation
=== "horizontal" ) {
10989 this.range
.stop( 1, 1 )[ animate
? "animate" : "css" ]( { width
: valPercent
+ "%" }, o
.animate
);
10991 if ( oRange
=== "max" && this.orientation
=== "horizontal" ) {
10992 this.range
[ animate
? "animate" : "css" ]( { width
: ( 100 - valPercent
) + "%" }, { queue
: false, duration
: o
.animate
} );
10994 if ( oRange
=== "min" && this.orientation
=== "vertical" ) {
10995 this.range
.stop( 1, 1 )[ animate
? "animate" : "css" ]( { height
: valPercent
+ "%" }, o
.animate
);
10997 if ( oRange
=== "max" && this.orientation
=== "vertical" ) {
10998 this.range
[ animate
? "animate" : "css" ]( { height
: ( 100 - valPercent
) + "%" }, { queue
: false, duration
: o
.animate
} );
11005 $.extend( $.ui
.slider
, {
11011 * jQuery UI Tabs 1.8.16
11013 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
11014 * Dual licensed under the MIT or GPL Version 2 licenses.
11015 * http://jquery.org/license
11017 * http://docs.jquery.com/UI/Tabs
11020 * jquery.ui.core.js
11021 * jquery.ui.widget.js
11023 (function( $, undefined ) {
11028 function getNextTabId() {
11032 function getNextListId() {
11036 $.widget( "ui.tabs", {
11041 cookie
: null, // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true }
11042 collapsible
: false,
11047 fx
: null, // e.g. { height: 'toggle', opacity: 'toggle', duration: 200 }
11048 idPrefix
: "ui-tabs-",
11050 panelTemplate
: "<div></div>",
11054 spinner
: "<em>Loading…</em>",
11055 tabTemplate
: "<li><a href='#{href}'><span>#{label}</span></a></li>"
11058 _create: function() {
11059 this._tabify( true );
11062 _setOption: function( key
, value
) {
11063 if ( key
== "selected" ) {
11064 if (this.options
.collapsible
&& value
== this.options
.selected
) {
11067 this.select( value
);
11069 this.options
[ key
] = value
;
11074 _tabId: function( a
) {
11075 return a
.title
&& a
.title
.replace( /\s/g, "_" ).replace( /[^\w\u00c0-\uFFFF-]/g, "" ) ||
11076 this.options
.idPrefix
+ getNextTabId();
11079 _sanitizeSelector: function( hash
) {
11080 // we need this because an id may contain a ":"
11081 return hash
.replace( /:/g
, "\\:" );
11084 _cookie: function() {
11085 var cookie
= this.cookie
||
11086 ( this.cookie
= this.options
.cookie
.name
|| "ui-tabs-" + getNextListId() );
11087 return $.cookie
.apply( null, [ cookie
].concat( $.makeArray( arguments
) ) );
11090 _ui: function( tab
, panel
) {
11094 index
: this.anchors
.index( tab
)
11098 _cleanup: function() {
11099 // restore all former loading tabs labels
11100 this.lis
.filter( ".ui-state-processing" )
11101 .removeClass( "ui-state-processing" )
11102 .find( "span:data(label.tabs)" )
11104 var el
= $( this );
11105 el
.html( el
.data( "label.tabs" ) ).removeData( "label.tabs" );
11109 _tabify: function( init
) {
11112 fragmentId
= /^#.+/; // Safari 2 reports '#' for an empty hash
11114 this.list
= this.element
.find( "ol,ul" ).eq( 0 );
11115 this.lis
= $( " > li:has(a[href])", this.list
);
11116 this.anchors
= this.lis
.map(function() {
11117 return $( "a", this )[ 0 ];
11119 this.panels
= $( [] );
11121 this.anchors
.each(function( i
, a
) {
11122 var href
= $( a
).attr( "href" );
11123 // For dynamically created HTML that contains a hash as href IE < 8 expands
11124 // such href to the full page url with hash and then misinterprets tab as ajax.
11125 // Same consideration applies for an added tab with a fragment identifier
11126 // since a[href=#fragment-identifier] does unexpectedly not match.
11127 // Thus normalize href attribute...
11128 var hrefBase
= href
.split( "#" )[ 0 ],
11130 if ( hrefBase
&& ( hrefBase
=== location
.toString().split( "#" )[ 0 ] ||
11131 ( baseEl
= $( "base" )[ 0 ]) && hrefBase
=== baseEl
.href
) ) {
11137 if ( fragmentId
.test( href
) ) {
11138 self
.panels
= self
.panels
.add( self
.element
.find( self
._sanitizeSelector( href
) ) );
11140 // prevent loading the page itself if href is just "#"
11141 } else if ( href
&& href
!== "#" ) {
11142 // required for restore on destroy
11143 $.data( a
, "href.tabs", href
);
11145 // TODO until #3808 is fixed strip fragment identifier from url
11146 // (IE fails to load from such url)
11147 $.data( a
, "load.tabs", href
.replace( /#.*$/, "" ) );
11149 var id
= self
._tabId( a
);
11151 var $panel
= self
.element
.find( "#" + id
);
11152 if ( !$panel
.length
) {
11153 $panel
= $( o
.panelTemplate
)
11155 .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
11156 .insertAfter( self
.panels
[ i
- 1 ] || self
.list
);
11157 $panel
.data( "destroy.tabs", true );
11159 self
.panels
= self
.panels
.add( $panel
);
11160 // invalid tab href
11162 o
.disabled
.push( i
);
11166 // initialization from scratch
11168 // attach necessary classes for styling
11169 this.element
.addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" );
11170 this.list
.addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" );
11171 this.lis
.addClass( "ui-state-default ui-corner-top" );
11172 this.panels
.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" );
11175 // use "selected" option or try to retrieve:
11176 // 1. from fragment identifier in url
11178 // 3. from selected class attribute on <li>
11179 if ( o
.selected
=== undefined ) {
11180 if ( location
.hash
) {
11181 this.anchors
.each(function( i
, a
) {
11182 if ( a
.hash
== location
.hash
) {
11188 if ( typeof o
.selected
!== "number" && o
.cookie
) {
11189 o
.selected
= parseInt( self
._cookie(), 10 );
11191 if ( typeof o
.selected
!== "number" && this.lis
.filter( ".ui-tabs-selected" ).length
) {
11192 o
.selected
= this.lis
.index( this.lis
.filter( ".ui-tabs-selected" ) );
11194 o
.selected
= o
.selected
|| ( this.lis
.length
? 0 : -1 );
11195 } else if ( o
.selected
=== null ) { // usage of null is deprecated, TODO remove in next release
11199 // sanity check - default to first tab...
11200 o
.selected
= ( ( o
.selected
>= 0 && this.anchors
[ o
.selected
] ) || o
.selected
< 0 )
11204 // Take disabling tabs via class attribute from HTML
11205 // into account and update option properly.
11206 // A selected tab cannot become disabled.
11207 o
.disabled
= $.unique( o
.disabled
.concat(
11208 $.map( this.lis
.filter( ".ui-state-disabled" ), function( n
, i
) {
11209 return self
.lis
.index( n
);
11213 if ( $.inArray( o
.selected
, o
.disabled
) != -1 ) {
11214 o
.disabled
.splice( $.inArray( o
.selected
, o
.disabled
), 1 );
11217 // highlight selected tab
11218 this.panels
.addClass( "ui-tabs-hide" );
11219 this.lis
.removeClass( "ui-tabs-selected ui-state-active" );
11220 // check for length avoids error when initializing empty list
11221 if ( o
.selected
>= 0 && this.anchors
.length
) {
11222 self
.element
.find( self
._sanitizeSelector( self
.anchors
[ o
.selected
].hash
) ).removeClass( "ui-tabs-hide" );
11223 this.lis
.eq( o
.selected
).addClass( "ui-tabs-selected ui-state-active" );
11225 // seems to be expected behavior that the show callback is fired
11226 self
.element
.queue( "tabs", function() {
11227 self
._trigger( "show", null,
11228 self
._ui( self
.anchors
[ o
.selected
], self
.element
.find( self
._sanitizeSelector( self
.anchors
[ o
.selected
].hash
) )[ 0 ] ) );
11231 this.load( o
.selected
);
11234 // clean up to avoid memory leaks in certain versions of IE 6
11235 // TODO: namespace this event
11236 $( window
).bind( "unload", function() {
11237 self
.lis
.add( self
.anchors
).unbind( ".tabs" );
11238 self
.lis
= self
.anchors
= self
.panels
= null;
11240 // update selected after add/remove
11242 o
.selected
= this.lis
.index( this.lis
.filter( ".ui-tabs-selected" ) );
11245 // update collapsible
11246 // TODO: use .toggleClass()
11247 this.element
[ o
.collapsible
? "addClass" : "removeClass" ]( "ui-tabs-collapsible" );
11249 // set or update cookie after init and add/remove respectively
11251 this._cookie( o
.selected
, o
.cookie
);
11255 for ( var i
= 0, li
; ( li
= this.lis
[ i
] ); i
++ ) {
11256 $( li
)[ $.inArray( i
, o
.disabled
) != -1 &&
11257 // TODO: use .toggleClass()
11258 !$( li
).hasClass( "ui-tabs-selected" ) ? "addClass" : "removeClass" ]( "ui-state-disabled" );
11261 // reset cache if switching from cached to not cached
11262 if ( o
.cache
=== false ) {
11263 this.anchors
.removeData( "cache.tabs" );
11266 // remove all handlers before, tabify may run on existing tabs after add or option change
11267 this.lis
.add( this.anchors
).unbind( ".tabs" );
11269 if ( o
.event
!== "mouseover" ) {
11270 var addState = function( state
, el
) {
11271 if ( el
.is( ":not(.ui-state-disabled)" ) ) {
11272 el
.addClass( "ui-state-" + state
);
11275 var removeState = function( state
, el
) {
11276 el
.removeClass( "ui-state-" + state
);
11278 this.lis
.bind( "mouseover.tabs" , function() {
11279 addState( "hover", $( this ) );
11281 this.lis
.bind( "mouseout.tabs", function() {
11282 removeState( "hover", $( this ) );
11284 this.anchors
.bind( "focus.tabs", function() {
11285 addState( "focus", $( this ).closest( "li" ) );
11287 this.anchors
.bind( "blur.tabs", function() {
11288 removeState( "focus", $( this ).closest( "li" ) );
11292 // set up animations
11293 var hideFx
, showFx
;
11295 if ( $.isArray( o
.fx
) ) {
11296 hideFx
= o
.fx
[ 0 ];
11297 showFx
= o
.fx
[ 1 ];
11299 hideFx
= showFx
= o
.fx
;
11303 // Reset certain styles left over from animation
11304 // and prevent IE's ClearType bug...
11305 function resetStyle( $el
, fx
) {
11306 $el
.css( "display", "" );
11307 if ( !$.support
.opacity
&& fx
.opacity
) {
11308 $el
[ 0 ].style
.removeAttribute( "filter" );
11313 var showTab
= showFx
11314 ? function( clicked
, $show
) {
11315 $( clicked
).closest( "li" ).addClass( "ui-tabs-selected ui-state-active" );
11316 $show
.hide().removeClass( "ui-tabs-hide" ) // avoid flicker that way
11317 .animate( showFx
, showFx
.duration
|| "normal", function() {
11318 resetStyle( $show
, showFx
);
11319 self
._trigger( "show", null, self
._ui( clicked
, $show
[ 0 ] ) );
11322 : function( clicked
, $show
) {
11323 $( clicked
).closest( "li" ).addClass( "ui-tabs-selected ui-state-active" );
11324 $show
.removeClass( "ui-tabs-hide" );
11325 self
._trigger( "show", null, self
._ui( clicked
, $show
[ 0 ] ) );
11328 // Hide a tab, $show is optional...
11329 var hideTab
= hideFx
11330 ? function( clicked
, $hide
) {
11331 $hide
.animate( hideFx
, hideFx
.duration
|| "normal", function() {
11332 self
.lis
.removeClass( "ui-tabs-selected ui-state-active" );
11333 $hide
.addClass( "ui-tabs-hide" );
11334 resetStyle( $hide
, hideFx
);
11335 self
.element
.dequeue( "tabs" );
11338 : function( clicked
, $hide
, $show
) {
11339 self
.lis
.removeClass( "ui-tabs-selected ui-state-active" );
11340 $hide
.addClass( "ui-tabs-hide" );
11341 self
.element
.dequeue( "tabs" );
11344 // attach tab event handler, unbind to avoid duplicates from former tabifying...
11345 this.anchors
.bind( o
.event
+ ".tabs", function() {
11347 $li
= $(el
).closest( "li" ),
11348 $hide
= self
.panels
.filter( ":not(.ui-tabs-hide)" ),
11349 $show
= self
.element
.find( self
._sanitizeSelector( el
.hash
) );
11351 // If tab is already selected and not collapsible or tab disabled or
11352 // or is already loading or click callback returns false stop here.
11353 // Check if click handler returns false last so that it is not executed
11354 // for a disabled or loading tab!
11355 if ( ( $li
.hasClass( "ui-tabs-selected" ) && !o
.collapsible
) ||
11356 $li
.hasClass( "ui-state-disabled" ) ||
11357 $li
.hasClass( "ui-state-processing" ) ||
11358 self
.panels
.filter( ":animated" ).length
||
11359 self
._trigger( "select", null, self
._ui( this, $show
[ 0 ] ) ) === false ) {
11364 o
.selected
= self
.anchors
.index( this );
11368 // if tab may be closed
11369 if ( o
.collapsible
) {
11370 if ( $li
.hasClass( "ui-tabs-selected" ) ) {
11374 self
._cookie( o
.selected
, o
.cookie
);
11377 self
.element
.queue( "tabs", function() {
11378 hideTab( el
, $hide
);
11379 }).dequeue( "tabs" );
11383 } else if ( !$hide
.length
) {
11385 self
._cookie( o
.selected
, o
.cookie
);
11388 self
.element
.queue( "tabs", function() {
11389 showTab( el
, $show
);
11392 // TODO make passing in node possible, see also http://dev.jqueryui.com/ticket/3171
11393 self
.load( self
.anchors
.index( this ) );
11401 self
._cookie( o
.selected
, o
.cookie
);
11405 if ( $show
.length
) {
11406 if ( $hide
.length
) {
11407 self
.element
.queue( "tabs", function() {
11408 hideTab( el
, $hide
);
11411 self
.element
.queue( "tabs", function() {
11412 showTab( el
, $show
);
11415 self
.load( self
.anchors
.index( this ) );
11417 throw "jQuery UI Tabs: Mismatching fragment identifier.";
11420 // Prevent IE from keeping other link focussed when using the back button
11421 // and remove dotted border from clicked link. This is controlled via CSS
11422 // in modern browsers; blur() removes focus from address bar in Firefox
11423 // which can become a usability and annoying problem with tabs('rotate').
11424 if ( $.browser
.msie
) {
11429 // disable click in any case
11430 this.anchors
.bind( "click.tabs", function(){
11435 _getIndex: function( index
) {
11436 // meta-function to give users option to provide a href string instead of a numerical index.
11437 // also sanitizes numerical indexes to valid values.
11438 if ( typeof index
== "string" ) {
11439 index
= this.anchors
.index( this.anchors
.filter( "[href$=" + index
+ "]" ) );
11445 destroy: function() {
11446 var o
= this.options
;
11452 .removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" )
11453 .removeData( "tabs" );
11455 this.list
.removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" );
11457 this.anchors
.each(function() {
11458 var href
= $.data( this, "href.tabs" );
11462 var $this = $( this ).unbind( ".tabs" );
11463 $.each( [ "href", "load", "cache" ], function( i
, prefix
) {
11464 $this.removeData( prefix
+ ".tabs" );
11468 this.lis
.unbind( ".tabs" ).add( this.panels
).each(function() {
11469 if ( $.data( this, "destroy.tabs" ) ) {
11470 $( this ).remove();
11472 $( this ).removeClass([
11473 "ui-state-default",
11475 "ui-tabs-selected",
11479 "ui-state-disabled",
11481 "ui-widget-content",
11482 "ui-corner-bottom",
11489 this._cookie( null, o
.cookie
);
11495 add: function( url
, label
, index
) {
11496 if ( index
=== undefined ) {
11497 index
= this.anchors
.length
;
11502 $li
= $( o
.tabTemplate
.replace( /#\{href\}/g, url
).replace( /#\{label\}/g, label
) ),
11503 id
= !url
.indexOf( "#" ) ? url
.replace( "#", "" ) : this._tabId( $( "a", $li
)[ 0 ] );
11505 $li
.addClass( "ui-state-default ui-corner-top" ).data( "destroy.tabs", true );
11507 // try to find an existing element before creating a new one
11508 var $panel
= self
.element
.find( "#" + id
);
11509 if ( !$panel
.length
) {
11510 $panel
= $( o
.panelTemplate
)
11512 .data( "destroy.tabs", true );
11514 $panel
.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide" );
11516 if ( index
>= this.lis
.length
) {
11517 $li
.appendTo( this.list
);
11518 $panel
.appendTo( this.list
[ 0 ].parentNode
);
11520 $li
.insertBefore( this.lis
[ index
] );
11521 $panel
.insertBefore( this.panels
[ index
] );
11524 o
.disabled
= $.map( o
.disabled
, function( n
, i
) {
11525 return n
>= index
? ++n
: n
;
11530 if ( this.anchors
.length
== 1 ) {
11532 $li
.addClass( "ui-tabs-selected ui-state-active" );
11533 $panel
.removeClass( "ui-tabs-hide" );
11534 this.element
.queue( "tabs", function() {
11535 self
._trigger( "show", null, self
._ui( self
.anchors
[ 0 ], self
.panels
[ 0 ] ) );
11541 this._trigger( "add", null, this._ui( this.anchors
[ index
], this.panels
[ index
] ) );
11545 remove: function( index
) {
11546 index
= this._getIndex( index
);
11547 var o
= this.options
,
11548 $li
= this.lis
.eq( index
).remove(),
11549 $panel
= this.panels
.eq( index
).remove();
11551 // If selected tab was removed focus tab to the right or
11552 // in case the last tab was removed the tab to the left.
11553 if ( $li
.hasClass( "ui-tabs-selected" ) && this.anchors
.length
> 1) {
11554 this.select( index
+ ( index
+ 1 < this.anchors
.length
? 1 : -1 ) );
11557 o
.disabled
= $.map(
11558 $.grep( o
.disabled
, function(n
, i
) {
11562 return n
>= index
? --n
: n
;
11567 this._trigger( "remove", null, this._ui( $li
.find( "a" )[ 0 ], $panel
[ 0 ] ) );
11571 enable: function( index
) {
11572 index
= this._getIndex( index
);
11573 var o
= this.options
;
11574 if ( $.inArray( index
, o
.disabled
) == -1 ) {
11578 this.lis
.eq( index
).removeClass( "ui-state-disabled" );
11579 o
.disabled
= $.grep( o
.disabled
, function( n
, i
) {
11583 this._trigger( "enable", null, this._ui( this.anchors
[ index
], this.panels
[ index
] ) );
11587 disable: function( index
) {
11588 index
= this._getIndex( index
);
11589 var self
= this, o
= this.options
;
11590 // cannot disable already selected tab
11591 if ( index
!= o
.selected
) {
11592 this.lis
.eq( index
).addClass( "ui-state-disabled" );
11594 o
.disabled
.push( index
);
11597 this._trigger( "disable", null, this._ui( this.anchors
[ index
], this.panels
[ index
] ) );
11603 select: function( index
) {
11604 index
= this._getIndex( index
);
11605 if ( index
== -1 ) {
11606 if ( this.options
.collapsible
&& this.options
.selected
!= -1 ) {
11607 index
= this.options
.selected
;
11612 this.anchors
.eq( index
).trigger( this.options
.event
+ ".tabs" );
11616 load: function( index
) {
11617 index
= this._getIndex( index
);
11620 a
= this.anchors
.eq( index
)[ 0 ],
11621 url
= $.data( a
, "load.tabs" );
11625 // not remote or from cache
11626 if ( !url
|| this.element
.queue( "tabs" ).length
!== 0 && $.data( a
, "cache.tabs" ) ) {
11627 this.element
.dequeue( "tabs" );
11631 // load remote from here on
11632 this.lis
.eq( index
).addClass( "ui-state-processing" );
11635 var span
= $( "span", a
);
11636 span
.data( "label.tabs", span
.html() ).html( o
.spinner
);
11639 this.xhr
= $.ajax( $.extend( {}, o
.ajaxOptions
, {
11641 success: function( r
, s
) {
11642 self
.element
.find( self
._sanitizeSelector( a
.hash
) ).html( r
);
11644 // take care of tab labels
11648 $.data( a
, "cache.tabs", true );
11651 self
._trigger( "load", null, self
._ui( self
.anchors
[ index
], self
.panels
[ index
] ) );
11653 o
.ajaxOptions
.success( r
, s
);
11657 error: function( xhr
, s
, e
) {
11658 // take care of tab labels
11661 self
._trigger( "load", null, self
._ui( self
.anchors
[ index
], self
.panels
[ index
] ) );
11663 // Passing index avoid a race condition when this method is
11664 // called after the user has selected another tab.
11665 // Pass the anchor that initiated this request allows
11666 // loadError to manipulate the tab content panel via $(a.hash)
11667 o
.ajaxOptions
.error( xhr
, s
, index
, a
);
11673 // last, so that load event is fired before show...
11674 self
.element
.dequeue( "tabs" );
11679 abort: function() {
11680 // stop possibly running animations
11681 this.element
.queue( [] );
11682 this.panels
.stop( false, true );
11684 // "tabs" queue must not contain more than two elements,
11685 // which are the callbacks for the latest clicked tab...
11686 this.element
.queue( "tabs", this.element
.queue( "tabs" ).splice( -2, 2 ) );
11688 // terminate pending requests from other tabs
11694 // take care of tab labels
11699 url: function( index
, url
) {
11700 this.anchors
.eq( index
).removeData( "cache.tabs" ).data( "load.tabs", url
);
11704 length: function() {
11705 return this.anchors
.length
;
11709 $.extend( $.ui
.tabs
, {
11720 $.extend( $.ui
.tabs
.prototype, {
11722 rotate: function( ms
, continuing
) {
11726 var rotate
= self
._rotate
|| ( self
._rotate = function( e
) {
11727 clearTimeout( self
.rotation
);
11728 self
.rotation
= setTimeout(function() {
11729 var t
= o
.selected
;
11730 self
.select( ++t
< self
.anchors
.length
? t
: 0 );
11734 e
.stopPropagation();
11738 var stop
= self
._unrotate
|| ( self
._unrotate
= !continuing
11740 if (e
.clientX
) { // in case of a true click
11751 this.element
.bind( "tabsshow", rotate
);
11752 this.anchors
.bind( o
.event
+ ".tabs", stop
);
11756 clearTimeout( self
.rotation
);
11757 this.element
.unbind( "tabsshow", rotate
);
11758 this.anchors
.unbind( o
.event
+ ".tabs", stop
);
11759 delete this._rotate
;
11760 delete this._unrotate
;