4 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
5 * Dual licensed under the MIT (MIT-LICENSE.txt)
6 * and GPL (GPL-LICENSE.txt) licenses.
8 * http://docs.jquery.com/UI
10 ;jQuery
.ui
|| (function($) {
12 //Helper functions and ui object
16 // $.ui.plugin is deprecated. Use the proxy pattern instead.
18 add: function(module
, option
, set) {
19 var proto
= $.ui
[module
].prototype;
21 proto
.plugins
[i
] = proto
.plugins
[i
] || [];
22 proto
.plugins
[i
].push([option
, set[i
]]);
25 call: function(instance
, name
, args
) {
26 var set = instance
.plugins
[name
];
27 if(!set || !instance
.element
[0].parentNode
) { return; }
29 for (var i
= 0; i
< set.length
; i
++) {
30 if (instance
.options
[set[i
][0]]) {
31 set[i
][1].apply(instance
.element
, args
);
37 contains: function(a
, b
) {
38 return document
.compareDocumentPosition
39 ? a
.compareDocumentPosition(b
) & 16
40 : a
!== b
&& a
.contains(b
);
43 hasScroll: function(el
, a
) {
45 //If overflow is hidden, the element might have extra content, but the user wants to hide it
46 if ($(el
).css('overflow') == 'hidden') { return false; }
48 var scroll
= (a
&& a
== 'left') ? 'scrollLeft' : 'scrollTop',
51 if (el
[scroll
] > 0) { return true; }
53 // TODO: determine which cases actually cause this to happen
54 // if the element doesn't have the scroll set, see if it's possible to
57 has
= (el
[scroll
] > 0);
62 isOverAxis: function(x
, reference
, size
) {
63 //Determines when x coordinate is over "b" element axis
64 return (x
> reference
) && (x
< (reference
+ size
));
67 isOver: function(y
, x
, top
, left
, height
, width
) {
68 //Determines when x, y coordinates is over "b" element
69 return $.ui
.isOverAxis(y
, top
, height
) && $.ui
.isOverAxis(x
, left
, width
);
105 focus: function(delay
, fn
) {
106 return typeof delay
=== 'number'
107 ? this.each(function() {
109 setTimeout(function() {
111 (fn
&& fn
.call(elem
));
114 : this._focus
.apply(this, arguments
);
117 enableSelection: function() {
119 .attr('unselectable', 'off')
120 .css('MozUserSelect', '')
121 .unbind('selectstart.ui');
124 disableSelection: function() {
126 .attr('unselectable', 'on')
127 .css('MozUserSelect', 'none')
128 .bind('selectstart.ui', function() { return false; });
131 scrollParent: function() {
133 if(($.browser
.msie
&& (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) {
134 scrollParent
= this.parents().filter(function() {
135 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));
138 scrollParent
= this.parents().filter(function() {
139 return (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
143 return (/fixed/).test(this.css('position')) || !scrollParent
.length
? $(document
) : scrollParent
;
146 zIndex: function(zIndex
) {
147 if (zIndex
!== undefined) {
148 return this.css('zIndex', zIndex
);
152 var elem
= $(this[0]), position
, value
;
153 while (elem
.length
&& elem
[0] !== document
) {
154 // Ignore z-index if position is set to a value where z-index is ignored by the browser
155 // This makes behavior of this function consistent across browsers
156 // WebKit always returns auto if the element is positioned
157 position
= elem
.css('position');
158 if (position
== 'absolute' || position
== 'relative' || position
== 'fixed')
160 // IE returns 0 when zIndex is not specified
161 // other browsers return a string
162 // we ignore the case of nested elements with an explicit value of 0
163 // <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
164 value
= parseInt(elem
.css('zIndex'));
165 if (!isNaN(value
) && value
!= 0) {
169 elem
= elem
.parent();
178 //Additional selectors
179 $.extend($.expr
[':'], {
180 data: function(elem
, i
, match
) {
181 return !!$.data(elem
, match
[3]);
184 focusable: function(element
) {
185 var nodeName
= element
.nodeName
.toLowerCase(),
186 tabIndex
= $.attr(element
, 'tabindex');
187 return (/input|select|textarea|button|object/.test(nodeName
)
189 : 'a' == nodeName
|| 'area' == nodeName
190 ? element
.href
|| !isNaN(tabIndex
)
192 // the element and all of its ancestors must be visible
193 // the browser may report that the area is hidden
194 && !$(element
)['area' == nodeName
? 'parents' : 'closest'](':hidden').length
;
197 tabbable: function(element
) {
198 var tabIndex
= $.attr(element
, 'tabindex');
199 return (isNaN(tabIndex
) || tabIndex
>= 0) && $(element
).is(':focusable');
205 * jQuery UI Widget 1.8
207 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
208 * Dual licensed under the MIT (MIT-LICENSE.txt)
209 * and GPL (GPL-LICENSE.txt) licenses.
211 * http://docs.jquery.com/UI/Widget
215 var _remove
= $.fn
.remove
;
217 $.fn
.remove = function( selector
, keepData
) {
218 return this.each(function() {
220 if ( !selector
|| $.filter( selector
, [ this ] ).length
) {
221 $( "*", this ).add( this ).each(function() {
222 $( this ).triggerHandler( "remove" );
226 return _remove
.call( $(this), selector
, keepData
);
230 $.widget = function( name
, base
, prototype ) {
231 var namespace = name
.split( "." )[ 0 ],
233 name
= name
.split( "." )[ 1 ];
234 fullName
= namespace + "-" + name
;
241 // create selector for plugin
242 $.expr
[ ":" ][ fullName
] = function( elem
) {
243 return !!$.data( elem
, name
);
246 $[ namespace ] = $[ namespace ] || {};
247 $[ namespace ][ name
] = function( options
, element
) {
248 // allow instantiation without initializing for simple inheritance
249 if ( arguments
.length
) {
250 this._createWidget( options
, element
);
254 var basePrototype
= new base();
255 // we need to make the options hash a property directly on the new instance
256 // otherwise we'll modify the options hash on the prototype that we're
258 // $.each( basePrototype, function( key, val ) {
259 // if ( $.isPlainObject(val) ) {
260 // basePrototype[ key ] = $.extend( {}, val );
263 basePrototype
.options
= $.extend( {}, basePrototype
.options
);
264 $[ namespace ][ name
].prototype = $.extend( true, basePrototype
, {
265 namespace: namespace,
267 widgetEventPrefix
: $[ namespace ][ name
].prototype.widgetEventPrefix
|| name
,
268 widgetBaseClass
: fullName
271 $.widget
.bridge( name
, $[ namespace ][ name
] );
274 $.widget
.bridge = function( name
, object
) {
275 $.fn
[ name
] = function( options
) {
276 var isMethodCall
= typeof options
=== "string",
277 args
= Array
.prototype.slice
.call( arguments
, 1 ),
280 // allow multiple hashes to be passed on init
281 options
= !isMethodCall
&& args
.length
?
282 $.extend
.apply( null, [ true, options
].concat(args
) ) :
285 // prevent calls to internal methods
286 if ( isMethodCall
&& options
.substring( 0, 1 ) === "_" ) {
290 if ( isMethodCall
) {
291 this.each(function() {
292 var instance
= $.data( this, name
),
293 methodValue
= instance
&& $.isFunction( instance
[options
] ) ?
294 instance
[ options
].apply( instance
, args
) :
296 if ( methodValue
!== instance
&& methodValue
!== undefined ) {
297 returnValue
= methodValue
;
302 this.each(function() {
303 var instance
= $.data( this, name
);
306 instance
.option( options
);
310 $.data( this, name
, new object( options
, this ) );
319 $.Widget = function( options
, element
) {
320 // allow instantiation without initializing for simple inheritance
321 if ( arguments
.length
) {
322 this._createWidget( options
, element
);
326 $.Widget
.prototype = {
327 widgetName
: "widget",
328 widgetEventPrefix
: "",
332 _createWidget: function( options
, element
) {
333 // $.widget.bridge stores the plugin instance, but we do it anyway
334 // so that it's stored even before the _create function runs
335 this.element
= $( element
).data( this.widgetName
, this );
336 this.options
= $.extend( true, {},
338 $.metadata
&& $.metadata
.get( element
)[ this.widgetName
],
342 this.element
.bind( "remove." + this.widgetName
, function() {
349 _create: function() {},
350 _init: function() {},
352 destroy: function() {
354 .unbind( "." + this.widgetName
)
355 .removeData( this.widgetName
);
357 .unbind( "." + this.widgetName
)
358 .removeAttr( "aria-disabled" )
360 this.widgetBaseClass
+ "-disabled " +
361 this.namespace + "-state-disabled" );
368 option: function( key
, value
) {
372 if ( arguments
.length
=== 0 ) {
373 // don't return a reference to the internal hash
374 return $.extend( {}, self
.options
);
377 if (typeof key
=== "string" ) {
378 if ( value
=== undefined ) {
379 return this.options
[ key
];
382 options
[ key
] = value
;
385 $.each( options
, function( key
, value
) {
386 self
._setOption( key
, value
);
391 _setOption: function( key
, value
) {
392 this.options
[ key
] = value
;
394 if ( key
=== "disabled" ) {
396 [ value
? "addClass" : "removeClass"](
397 this.widgetBaseClass
+ "-disabled" + " " +
398 this.namespace + "-state-disabled" )
399 .attr( "aria-disabled", value
);
406 return this._setOption( "disabled", false );
408 disable: function() {
409 return this._setOption( "disabled", true );
412 _trigger: function( type
, event
, data
) {
413 var callback
= this.options
[ type
];
415 event
= $.Event( event
);
416 event
.type
= ( type
=== this.widgetEventPrefix
?
418 this.widgetEventPrefix
+ type
).toLowerCase();
421 // copy original event properties over to the new event
422 // this would happen if we could call $.event.fix instead of $.Event
423 // but we don't have a way to force an event to be fixed multiple times
424 if ( event
.originalEvent
) {
425 for ( var i
= $.event
.props
.length
, prop
; i
; ) {
426 prop
= $.event
.props
[ --i
];
427 event
[ prop
] = event
.originalEvent
[ prop
];
431 this.element
.trigger( event
, data
);
433 return !( $.isFunction(callback
) &&
434 callback
.call( this.element
[0], event
, data
) === false ||
435 event
.isDefaultPrevented() );
441 * jQuery UI Mouse 1.8
443 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
444 * Dual licensed under the MIT (MIT-LICENSE.txt)
445 * and GPL (GPL-LICENSE.txt) licenses.
447 * http://docs.jquery.com/UI/Mouse
450 * jquery.ui.widget.js
454 $.widget("ui.mouse", {
456 cancel
: ':input,option',
460 _mouseInit: function() {
464 .bind('mousedown.'+this.widgetName
, function(event
) {
465 return self
._mouseDown(event
);
467 .bind('click.'+this.widgetName
, function(event
) {
468 if(self
._preventClickEvent
) {
469 self
._preventClickEvent
= false;
470 event
.stopImmediatePropagation();
475 this.started
= false;
478 // TODO: make sure destroying one instance of mouse doesn't mess with
479 // other instances of mouse
480 _mouseDestroy: function() {
481 this.element
.unbind('.'+this.widgetName
);
484 _mouseDown: function(event
) {
485 // don't let more than one widget handle mouseStart
486 // TODO: figure out why we have to use originalEvent
487 event
.originalEvent
= event
.originalEvent
|| {};
488 if (event
.originalEvent
.mouseHandled
) { return; }
490 // we may have missed mouseup (out of window)
491 (this._mouseStarted
&& this._mouseUp(event
));
493 this._mouseDownEvent
= event
;
496 btnIsLeft
= (event
.which
== 1),
497 elIsCancel
= (typeof this.options
.cancel
== "string" ? $(event
.target
).parents().add(event
.target
).filter(this.options
.cancel
).length
: false);
498 if (!btnIsLeft
|| elIsCancel
|| !this._mouseCapture(event
)) {
502 this.mouseDelayMet
= !this.options
.delay
;
503 if (!this.mouseDelayMet
) {
504 this._mouseDelayTimer
= setTimeout(function() {
505 self
.mouseDelayMet
= true;
506 }, this.options
.delay
);
509 if (this._mouseDistanceMet(event
) && this._mouseDelayMet(event
)) {
510 this._mouseStarted
= (this._mouseStart(event
) !== false);
511 if (!this._mouseStarted
) {
512 event
.preventDefault();
517 // these delegates are required to keep context
518 this._mouseMoveDelegate = function(event
) {
519 return self
._mouseMove(event
);
521 this._mouseUpDelegate = function(event
) {
522 return self
._mouseUp(event
);
525 .bind('mousemove.'+this.widgetName
, this._mouseMoveDelegate
)
526 .bind('mouseup.'+this.widgetName
, this._mouseUpDelegate
);
528 // preventDefault() is used to prevent the selection of text here -
529 // however, in Safari, this causes select boxes not to be selectable
530 // anymore, so this fix is needed
531 ($.browser
.safari
|| event
.preventDefault());
533 event
.originalEvent
.mouseHandled
= true;
537 _mouseMove: function(event
) {
538 // IE mouseup check - mouseup happened when mouse was out of window
539 if ($.browser
.msie
&& !event
.button
) {
540 return this._mouseUp(event
);
543 if (this._mouseStarted
) {
544 this._mouseDrag(event
);
545 return event
.preventDefault();
548 if (this._mouseDistanceMet(event
) && this._mouseDelayMet(event
)) {
550 (this._mouseStart(this._mouseDownEvent
, event
) !== false);
551 (this._mouseStarted
? this._mouseDrag(event
) : this._mouseUp(event
));
554 return !this._mouseStarted
;
557 _mouseUp: function(event
) {
559 .unbind('mousemove.'+this.widgetName
, this._mouseMoveDelegate
)
560 .unbind('mouseup.'+this.widgetName
, this._mouseUpDelegate
);
562 if (this._mouseStarted
) {
563 this._mouseStarted
= false;
564 this._preventClickEvent
= (event
.target
== this._mouseDownEvent
.target
);
565 this._mouseStop(event
);
571 _mouseDistanceMet: function(event
) {
573 Math
.abs(this._mouseDownEvent
.pageX
- event
.pageX
),
574 Math
.abs(this._mouseDownEvent
.pageY
- event
.pageY
)
575 ) >= this.options
.distance
579 _mouseDelayMet: function(event
) {
580 return this.mouseDelayMet
;
583 // These are placeholder methods, to be overriden by extending plugin
584 _mouseStart: function(event
) {},
585 _mouseDrag: function(event
) {},
586 _mouseStop: function(event
) {},
587 _mouseCapture: function(event
) { return true; }
592 * jQuery UI Position 1.8
594 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
595 * Dual licensed under the MIT (MIT-LICENSE.txt)
596 * and GPL (GPL-LICENSE.txt) licenses.
598 * http://docs.jquery.com/UI/Position
604 var horizontalPositions
= /left|center|right/,
605 horizontalDefault
= "center",
606 verticalPositions
= /top|center|bottom/,
607 verticalDefault
= "center",
608 _position
= $.fn
.position
,
609 _offset
= $.fn
.offset
;
611 $.fn
.position = function( options
) {
612 if ( !options
|| !options
.of ) {
613 return _position
.apply( this, arguments
);
616 // make a copy, we don't want to modify arguments
617 options
= $.extend( {}, options
);
619 var target
= $( options
.of ),
620 collision
= ( options
.collision
|| "flip" ).split( " " ),
621 offset
= options
.offset
? options
.offset
.split( " " ) : [ 0, 0 ],
626 if ( options
.of.nodeType
=== 9 ) {
627 targetWidth
= target
.width();
628 targetHeight
= target
.height();
629 basePosition
= { top
: 0, left
: 0 };
630 } else if ( options
.of.scrollTo
&& options
.of.document
) {
631 targetWidth
= target
.width();
632 targetHeight
= target
.height();
633 basePosition
= { top
: target
.scrollTop(), left
: target
.scrollLeft() };
634 } else if ( options
.of.preventDefault
) {
635 // force left top to allow flipping
636 options
.at
= "left top";
637 targetWidth
= targetHeight
= 0;
638 basePosition
= { top
: options
.of.pageY
, left
: options
.of.pageX
};
640 targetWidth
= target
.outerWidth();
641 targetHeight
= target
.outerHeight();
642 basePosition
= target
.offset();
645 // force my and at to have valid horizontal and veritcal positions
646 // if a value is missing or invalid, it will be converted to center
647 $.each( [ "my", "at" ], function() {
648 var pos
= ( options
[this] || "" ).split( " " );
649 if ( pos
.length
=== 1) {
650 pos
= horizontalPositions
.test( pos
[0] ) ?
651 pos
.concat( [verticalDefault
] ) :
652 verticalPositions
.test( pos
[0] ) ?
653 [ horizontalDefault
].concat( pos
) :
654 [ horizontalDefault
, verticalDefault
];
656 pos
[ 0 ] = horizontalPositions
.test( pos
[0] ) ? pos
[ 0 ] : horizontalDefault
;
657 pos
[ 1 ] = verticalPositions
.test( pos
[1] ) ? pos
[ 1 ] : verticalDefault
;
658 options
[ this ] = pos
;
661 // normalize collision option
662 if ( collision
.length
=== 1 ) {
663 collision
[ 1 ] = collision
[ 0 ];
666 // normalize offset option
667 offset
[ 0 ] = parseInt( offset
[0], 10 ) || 0;
668 if ( offset
.length
=== 1 ) {
669 offset
[ 1 ] = offset
[ 0 ];
671 offset
[ 1 ] = parseInt( offset
[1], 10 ) || 0;
673 if ( options
.at
[0] === "right" ) {
674 basePosition
.left
+= targetWidth
;
675 } else if (options
.at
[0] === horizontalDefault
) {
676 basePosition
.left
+= targetWidth
/ 2;
679 if ( options
.at
[1] === "bottom" ) {
680 basePosition
.top
+= targetHeight
;
681 } else if ( options
.at
[1] === verticalDefault
) {
682 basePosition
.top
+= targetHeight
/ 2;
685 basePosition
.left
+= offset
[ 0 ];
686 basePosition
.top
+= offset
[ 1 ];
688 return this.each(function() {
689 var elem
= $( this ),
690 elemWidth
= elem
.outerWidth(),
691 elemHeight
= elem
.outerHeight(),
692 position
= $.extend( {}, basePosition
);
694 if ( options
.my
[0] === "right" ) {
695 position
.left
-= elemWidth
;
696 } else if ( options
.my
[0] === horizontalDefault
) {
697 position
.left
-= elemWidth
/ 2;
700 if ( options
.my
[1] === "bottom" ) {
701 position
.top
-= elemHeight
;
702 } else if ( options
.my
[1] === verticalDefault
) {
703 position
.top
-= elemHeight
/ 2;
706 $.each( [ "left", "top" ], function( i
, dir
) {
707 if ( $.ui
.position
[ collision
[i
] ] ) {
708 $.ui
.position
[ collision
[i
] ][ dir
]( position
, {
709 targetWidth
: targetWidth
,
710 targetHeight
: targetHeight
,
711 elemWidth
: elemWidth
,
712 elemHeight
: elemHeight
,
720 if ( $.fn
.bgiframe
) {
723 elem
.offset( $.extend( position
, { using
: options
.using
} ) );
729 left: function( position
, data
) {
730 var win
= $( window
),
731 over
= position
.left
+ data
.elemWidth
- win
.width() - win
.scrollLeft();
732 position
.left
= over
> 0 ? position
.left
- over
: Math
.max( 0, position
.left
);
734 top: function( position
, data
) {
735 var win
= $( window
),
736 over
= position
.top
+ data
.elemHeight
- win
.height() - win
.scrollTop();
737 position
.top
= over
> 0 ? position
.top
- over
: Math
.max( 0, position
.top
);
742 left: function( position
, data
) {
743 if ( data
.at
[0] === "center" ) {
746 var win
= $( window
),
747 over
= position
.left
+ data
.elemWidth
- win
.width() - win
.scrollLeft(),
748 myOffset
= data
.my
[ 0 ] === "left" ?
750 data
.my
[ 0 ] === "right" ?
753 offset
= -2 * data
.offset
[ 0 ];
754 position
.left
+= position
.left
< 0 ?
755 myOffset
+ data
.targetWidth
+ offset
:
757 myOffset
- data
.targetWidth
+ offset
:
760 top: function( position
, data
) {
761 if ( data
.at
[1] === "center" ) {
764 var win
= $( window
),
765 over
= position
.top
+ data
.elemHeight
- win
.height() - win
.scrollTop(),
766 myOffset
= data
.my
[ 1 ] === "top" ?
768 data
.my
[ 1 ] === "bottom" ?
771 atOffset
= data
.at
[ 1 ] === "top" ?
774 offset
= -2 * data
.offset
[ 1 ];
775 position
.top
+= position
.top
< 0 ?
776 myOffset
+ data
.targetHeight
+ offset
:
778 myOffset
+ atOffset
+ offset
:
784 // offset setter from jQuery 1.4
785 if ( !$.offset
.setOffset
) {
786 $.offset
.setOffset = function( elem
, options
) {
787 // set position first, in-case top/left are set even on static elem
788 if ( /static/.test( $.curCSS( elem
, "position" ) ) ) {
789 elem
.style
.position
= "relative";
791 var curElem
= $( elem
),
792 curOffset
= curElem
.offset(),
793 curTop
= parseInt( $.curCSS( elem
, "top", true ), 10 ) || 0,
794 curLeft
= parseInt( $.curCSS( elem
, "left", true ), 10) || 0,
796 top
: (options
.top
- curOffset
.top
) + curTop
,
797 left
: (options
.left
- curOffset
.left
) + curLeft
800 if ( 'using' in options
) {
801 options
.using
.call( elem
, props
);
803 curElem
.css( props
);
807 $.fn
.offset = function( options
) {
808 var elem
= this[ 0 ];
809 if ( !elem
|| !elem
.ownerDocument
) { return null; }
811 return this.each(function() {
812 $.offset
.setOffset( this, options
);
815 return _offset
.call( this );
821 * jQuery UI Draggable 1.8
823 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
824 * Dual licensed under the MIT (MIT-LICENSE.txt)
825 * and GPL (GPL-LICENSE.txt) licenses.
827 * http://docs.jquery.com/UI/Draggables
832 * jquery.ui.widget.js
836 $.widget("ui.draggable", $.ui
.mouse
, {
837 widgetEventPrefix
: "drag",
842 connectToSortable
: false,
851 refreshPositions
: false,
856 scrollSensitivity
: 20,
864 _create: function() {
866 if (this.options
.helper
== 'original' && !(/^(?:r|a|f)/).test(this.element
.css("position")))
867 this.element
[0].style
.position
= 'relative';
869 (this.options
.addClasses
&& this.element
.addClass("ui-draggable"));
870 (this.options
.disabled
&& this.element
.addClass("ui-draggable-disabled"));
876 destroy: function() {
877 if(!this.element
.data('draggable')) return;
879 .removeData("draggable")
880 .unbind(".draggable")
881 .removeClass("ui-draggable"
882 + " ui-draggable-dragging"
883 + " ui-draggable-disabled");
884 this._mouseDestroy();
889 _mouseCapture: function(event
) {
891 var o
= this.options
;
893 // among others, prevent a drag on a resizable-handle
894 if (this.helper
|| o
.disabled
|| $(event
.target
).is('.ui-resizable-handle'))
897 //Quit if we're not on a valid handle
898 this.handle
= this._getHandle(event
);
906 _mouseStart: function(event
) {
908 var o
= this.options
;
910 //Create and append the visible helper
911 this.helper
= this._createHelper(event
);
913 //Cache the helper size
914 this._cacheHelperProportions();
916 //If ddmanager is used for droppables, set the global draggable
918 $.ui
.ddmanager
.current
= this;
921 * - Position generation -
922 * This block generates everything position related - it's the core of draggables.
925 //Cache the margins of the original element
926 this._cacheMargins();
928 //Store the helper's css position
929 this.cssPosition
= this.helper
.css("position");
930 this.scrollParent
= this.helper
.scrollParent();
932 //The element's absolute position on the page minus margins
933 this.offset
= this.positionAbs
= this.element
.offset();
935 top
: this.offset
.top
- this.margins
.top
,
936 left
: this.offset
.left
- this.margins
.left
939 $.extend(this.offset
, {
940 click
: { //Where the click happened, relative to the element
941 left
: event
.pageX
- this.offset
.left
,
942 top
: event
.pageY
- this.offset
.top
944 parent
: this._getParentOffset(),
945 relative
: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
948 //Generate the original position
949 this.originalPosition
= this.position
= this._generatePosition(event
);
950 this.originalPageX
= event
.pageX
;
951 this.originalPageY
= event
.pageY
;
953 //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
954 (o
.cursorAt
&& this._adjustOffsetFromHelper(o
.cursorAt
));
956 //Set a containment if given in the options
958 this._setContainment();
960 //Trigger event + callbacks
961 if(this._trigger("start", event
) === false) {
966 //Recache the helper size
967 this._cacheHelperProportions();
969 //Prepare the droppable offsets
970 if ($.ui
.ddmanager
&& !o
.dropBehaviour
)
971 $.ui
.ddmanager
.prepareOffsets(this, event
);
973 this.helper
.addClass("ui-draggable-dragging");
974 this._mouseDrag(event
, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position
978 _mouseDrag: function(event
, noPropagation
) {
980 //Compute the helpers position
981 this.position
= this._generatePosition(event
);
982 this.positionAbs
= this._convertPositionTo("absolute");
984 //Call plugins and callbacks and use the resulting position if something is returned
985 if (!noPropagation
) {
986 var ui
= this._uiHash();
987 if(this._trigger('drag', event
, ui
) === false) {
991 this.position
= ui
.position
;
994 if(!this.options
.axis
|| this.options
.axis
!= "y") this.helper
[0].style
.left
= this.position
.left
+'px';
995 if(!this.options
.axis
|| this.options
.axis
!= "x") this.helper
[0].style
.top
= this.position
.top
+'px';
996 if($.ui
.ddmanager
) $.ui
.ddmanager
.drag(this, event
);
1001 _mouseStop: function(event
) {
1003 //If we are using droppables, inform the manager about the drop
1004 var dropped
= false;
1005 if ($.ui
.ddmanager
&& !this.options
.dropBehaviour
)
1006 dropped
= $.ui
.ddmanager
.drop(this, event
);
1008 //if a drop comes from outside (a sortable)
1010 dropped
= this.dropped
;
1011 this.dropped
= false;
1014 //if the original element is removed, don't bother to continue
1015 if(!this.element
[0] || !this.element
[0].parentNode
)
1018 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
))) {
1020 $(this.helper
).animate(this.originalPosition
, parseInt(this.options
.revertDuration
, 10), function() {
1021 if(self
._trigger("stop", event
) !== false) {
1026 if(this._trigger("stop", event
) !== false) {
1034 cancel: function() {
1036 if(this.helper
.is(".ui-draggable-dragging")) {
1046 _getHandle: function(event
) {
1048 var handle
= !this.options
.handle
|| !$(this.options
.handle
, this.element
).length
? true : false;
1049 $(this.options
.handle
, this.element
)
1053 if(this == event
.target
) handle
= true;
1060 _createHelper: function(event
) {
1062 var o
= this.options
;
1063 var helper
= $.isFunction(o
.helper
) ? $(o
.helper
.apply(this.element
[0], [event
])) : (o
.helper
== 'clone' ? this.element
.clone() : this.element
);
1065 if(!helper
.parents('body').length
)
1066 helper
.appendTo((o
.appendTo
== 'parent' ? this.element
[0].parentNode
: o
.appendTo
));
1068 if(helper
[0] != this.element
[0] && !(/(fixed|absolute)/).test(helper
.css("position")))
1069 helper
.css("position", "absolute");
1075 _adjustOffsetFromHelper: function(obj
) {
1076 if (typeof obj
== 'string') {
1077 obj
= obj
.split(' ');
1079 if ($.isArray(obj
)) {
1080 obj
= {left
: +obj
[0], top
: +obj
[1] || 0};
1082 if ('left' in obj
) {
1083 this.offset
.click
.left
= obj
.left
+ this.margins
.left
;
1085 if ('right' in obj
) {
1086 this.offset
.click
.left
= this.helperProportions
.width
- obj
.right
+ this.margins
.left
;
1089 this.offset
.click
.top
= obj
.top
+ this.margins
.top
;
1091 if ('bottom' in obj
) {
1092 this.offset
.click
.top
= this.helperProportions
.height
- obj
.bottom
+ this.margins
.top
;
1096 _getParentOffset: function() {
1098 //Get the offsetParent and cache its position
1099 this.offsetParent
= this.helper
.offsetParent();
1100 var po
= this.offsetParent
.offset();
1102 // This is a special case where we need to modify a offset calculated on start, since the following happened:
1103 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
1104 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
1105 // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
1106 if(this.cssPosition
== 'absolute' && this.scrollParent
[0] != document
&& $.ui
.contains(this.scrollParent
[0], this.offsetParent
[0])) {
1107 po
.left
+= this.scrollParent
.scrollLeft();
1108 po
.top
+= this.scrollParent
.scrollTop();
1111 if((this.offsetParent
[0] == document
.body
) //This needs to be actually done for all browsers, since pageX/pageY includes this information
1112 || (this.offsetParent
[0].tagName
&& this.offsetParent
[0].tagName
.toLowerCase() == 'html' && $.browser
.msie
)) //Ugly IE fix
1113 po
= { top
: 0, left
: 0 };
1116 top
: po
.top
+ (parseInt(this.offsetParent
.css("borderTopWidth"),10) || 0),
1117 left
: po
.left
+ (parseInt(this.offsetParent
.css("borderLeftWidth"),10) || 0)
1122 _getRelativeOffset: function() {
1124 if(this.cssPosition
== "relative") {
1125 var p
= this.element
.position();
1127 top
: p
.top
- (parseInt(this.helper
.css("top"),10) || 0) + this.scrollParent
.scrollTop(),
1128 left
: p
.left
- (parseInt(this.helper
.css("left"),10) || 0) + this.scrollParent
.scrollLeft()
1131 return { top
: 0, left
: 0 };
1136 _cacheMargins: function() {
1138 left
: (parseInt(this.element
.css("marginLeft"),10) || 0),
1139 top
: (parseInt(this.element
.css("marginTop"),10) || 0)
1143 _cacheHelperProportions: function() {
1144 this.helperProportions
= {
1145 width
: this.helper
.outerWidth(),
1146 height
: this.helper
.outerHeight()
1150 _setContainment: function() {
1152 var o
= this.options
;
1153 if(o
.containment
== 'parent') o
.containment
= this.helper
[0].parentNode
;
1154 if(o
.containment
== 'document' || o
.containment
== 'window') this.containment
= [
1155 0 - this.offset
.relative
.left
- this.offset
.parent
.left
,
1156 0 - this.offset
.relative
.top
- this.offset
.parent
.top
,
1157 $(o
.containment
== 'document' ? document
: window
).width() - this.helperProportions
.width
- this.margins
.left
,
1158 ($(o
.containment
== 'document' ? document
: window
).height() || document
.body
.parentNode
.scrollHeight
) - this.helperProportions
.height
- this.margins
.top
1161 if(!(/^(document|window|parent)$/).test(o
.containment
) && o
.containment
.constructor != Array
) {
1162 var ce
= $(o
.containment
)[0]; if(!ce
) return;
1163 var co
= $(o
.containment
).offset();
1164 var over
= ($(ce
).css("overflow") != 'hidden');
1166 this.containment
= [
1167 co
.left
+ (parseInt($(ce
).css("borderLeftWidth"),10) || 0) + (parseInt($(ce
).css("paddingLeft"),10) || 0) - this.margins
.left
,
1168 co
.top
+ (parseInt($(ce
).css("borderTopWidth"),10) || 0) + (parseInt($(ce
).css("paddingTop"),10) || 0) - this.margins
.top
,
1169 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
,
1170 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
1172 } else if(o
.containment
.constructor == Array
) {
1173 this.containment
= o
.containment
;
1178 _convertPositionTo: function(d
, pos
) {
1180 if(!pos
) pos
= this.position
;
1181 var mod
= d
== "absolute" ? 1 : -1;
1182 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
);
1186 pos
.top
// The absolute mouse position
1187 + this.offset
.relative
.top
* mod
// Only for relative positioned nodes: Relative offset from element to offset parent
1188 + this.offset
.parent
.top
* mod
// The offsetParent's offset without borders (offset + border)
1189 - ($.browser
.safari
&& $.browser
.version
< 526 && this.cssPosition
== 'fixed' ? 0 : ( this.cssPosition
== 'fixed' ? -this.scrollParent
.scrollTop() : ( scrollIsRootNode
? 0 : scroll
.scrollTop() ) ) * mod
)
1192 pos
.left
// The absolute mouse position
1193 + this.offset
.relative
.left
* mod
// Only for relative positioned nodes: Relative offset from element to offset parent
1194 + this.offset
.parent
.left
* mod
// The offsetParent's offset without borders (offset + border)
1195 - ($.browser
.safari
&& $.browser
.version
< 526 && this.cssPosition
== 'fixed' ? 0 : ( this.cssPosition
== 'fixed' ? -this.scrollParent
.scrollLeft() : scrollIsRootNode
? 0 : scroll
.scrollLeft() ) * mod
)
1201 _generatePosition: function(event
) {
1203 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
);
1204 var pageX
= event
.pageX
;
1205 var pageY
= event
.pageY
;
1208 * - Position constraining -
1209 * Constrain the position to a mix of grid, containment.
1212 if(this.originalPosition
) { //If we are not dragging yet, we won't check for options
1214 if(this.containment
) {
1215 if(event
.pageX
- this.offset
.click
.left
< this.containment
[0]) pageX
= this.containment
[0] + this.offset
.click
.left
;
1216 if(event
.pageY
- this.offset
.click
.top
< this.containment
[1]) pageY
= this.containment
[1] + this.offset
.click
.top
;
1217 if(event
.pageX
- this.offset
.click
.left
> this.containment
[2]) pageX
= this.containment
[2] + this.offset
.click
.left
;
1218 if(event
.pageY
- this.offset
.click
.top
> this.containment
[3]) pageY
= this.containment
[3] + this.offset
.click
.top
;
1222 var top
= this.originalPageY
+ Math
.round((pageY
- this.originalPageY
) / o
.grid
[1]) * o
.grid
[1];
1223 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
;
1225 var left
= this.originalPageX
+ Math
.round((pageX
- this.originalPageX
) / o
.grid
[0]) * o
.grid
[0];
1226 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
;
1233 pageY
// The absolute mouse position
1234 - this.offset
.click
.top
// Click offset (relative to the element)
1235 - this.offset
.relative
.top
// Only for relative positioned nodes: Relative offset from element to offset parent
1236 - this.offset
.parent
.top
// The offsetParent's offset without borders (offset + border)
1237 + ($.browser
.safari
&& $.browser
.version
< 526 && this.cssPosition
== 'fixed' ? 0 : ( this.cssPosition
== 'fixed' ? -this.scrollParent
.scrollTop() : ( scrollIsRootNode
? 0 : scroll
.scrollTop() ) ))
1240 pageX
// The absolute mouse position
1241 - this.offset
.click
.left
// Click offset (relative to the element)
1242 - this.offset
.relative
.left
// Only for relative positioned nodes: Relative offset from element to offset parent
1243 - this.offset
.parent
.left
// The offsetParent's offset without borders (offset + border)
1244 + ($.browser
.safari
&& $.browser
.version
< 526 && this.cssPosition
== 'fixed' ? 0 : ( this.cssPosition
== 'fixed' ? -this.scrollParent
.scrollLeft() : scrollIsRootNode
? 0 : scroll
.scrollLeft() ))
1250 _clear: function() {
1251 this.helper
.removeClass("ui-draggable-dragging");
1252 if(this.helper
[0] != this.element
[0] && !this.cancelHelperRemoval
) this.helper
.remove();
1253 //if($.ui.ddmanager) $.ui.ddmanager.current = null;
1255 this.cancelHelperRemoval
= false;
1258 // From now on bulk stuff - mainly helpers
1260 _trigger: function(type
, event
, ui
) {
1261 ui
= ui
|| this._uiHash();
1262 $.ui
.plugin
.call(this, type
, [event
, ui
]);
1263 if(type
== "drag") this.positionAbs
= this._convertPositionTo("absolute"); //The absolute position has to be recalculated after plugins
1264 return $.Widget
.prototype._trigger
.call(this, type
, event
, ui
);
1269 _uiHash: function(event
) {
1271 helper
: this.helper
,
1272 position
: this.position
,
1273 originalPosition
: this.originalPosition
,
1274 offset
: this.positionAbs
1280 $.extend($.ui
.draggable
, {
1284 $.ui
.plugin
.add("draggable", "connectToSortable", {
1285 start: function(event
, ui
) {
1287 var inst
= $(this).data("draggable"), o
= inst
.options
,
1288 uiSortable
= $.extend({}, ui
, { item
: inst
.element
});
1289 inst
.sortables
= [];
1290 $(o
.connectToSortable
).each(function() {
1291 var sortable
= $.data(this, 'sortable');
1292 if (sortable
&& !sortable
.options
.disabled
) {
1293 inst
.sortables
.push({
1295 shouldRevert
: sortable
.options
.revert
1297 sortable
._refreshItems(); //Do a one-time refresh at start to refresh the containerCache
1298 sortable
._trigger("activate", event
, uiSortable
);
1303 stop: function(event
, ui
) {
1305 //If we are still over the sortable, we fake the stop event of the sortable, but also remove helper
1306 var inst
= $(this).data("draggable"),
1307 uiSortable
= $.extend({}, ui
, { item
: inst
.element
});
1309 $.each(inst
.sortables
, function() {
1310 if(this.instance
.isOver
) {
1312 this.instance
.isOver
= 0;
1314 inst
.cancelHelperRemoval
= true; //Don't remove the helper in the draggable instance
1315 this.instance
.cancelHelperRemoval
= false; //Remove it in the sortable instance (so sortable plugins like revert still work)
1317 //The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: 'valid/invalid'
1318 if(this.shouldRevert
) this.instance
.options
.revert
= true;
1320 //Trigger the stop of the sortable
1321 this.instance
._mouseStop(event
);
1323 this.instance
.options
.helper
= this.instance
.options
._helper
;
1325 //If the helper has been the original item, restore properties in the sortable
1326 if(inst
.options
.helper
== 'original')
1327 this.instance
.currentItem
.css({ top
: 'auto', left
: 'auto' });
1330 this.instance
.cancelHelperRemoval
= false; //Remove the helper in the sortable instance
1331 this.instance
._trigger("deactivate", event
, uiSortable
);
1337 drag: function(event
, ui
) {
1339 var inst
= $(this).data("draggable"), self
= this;
1341 var checkPos = function(o
) {
1342 var dyClick
= this.offset
.click
.top
, dxClick
= this.offset
.click
.left
;
1343 var helperTop
= this.positionAbs
.top
, helperLeft
= this.positionAbs
.left
;
1344 var itemHeight
= o
.height
, itemWidth
= o
.width
;
1345 var itemTop
= o
.top
, itemLeft
= o
.left
;
1347 return $.ui
.isOver(helperTop
+ dyClick
, helperLeft
+ dxClick
, itemTop
, itemLeft
, itemHeight
, itemWidth
);
1350 $.each(inst
.sortables
, function(i
) {
1352 //Copy over some variables to allow calling the sortable's native _intersectsWith
1353 this.instance
.positionAbs
= inst
.positionAbs
;
1354 this.instance
.helperProportions
= inst
.helperProportions
;
1355 this.instance
.offset
.click
= inst
.offset
.click
;
1357 if(this.instance
._intersectsWith(this.instance
.containerCache
)) {
1359 //If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once
1360 if(!this.instance
.isOver
) {
1362 this.instance
.isOver
= 1;
1363 //Now we fake the start of dragging for the sortable instance,
1364 //by cloning the list group item, appending it to the sortable and using it as inst.currentItem
1365 //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)
1366 this.instance
.currentItem
= $(self
).clone().appendTo(this.instance
.element
).data("sortable-item", true);
1367 this.instance
.options
._helper
= this.instance
.options
.helper
; //Store helper option to later restore it
1368 this.instance
.options
.helper = function() { return ui
.helper
[0]; };
1370 event
.target
= this.instance
.currentItem
[0];
1371 this.instance
._mouseCapture(event
, true);
1372 this.instance
._mouseStart(event
, true, true);
1374 //Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes
1375 this.instance
.offset
.click
.top
= inst
.offset
.click
.top
;
1376 this.instance
.offset
.click
.left
= inst
.offset
.click
.left
;
1377 this.instance
.offset
.parent
.left
-= inst
.offset
.parent
.left
- this.instance
.offset
.parent
.left
;
1378 this.instance
.offset
.parent
.top
-= inst
.offset
.parent
.top
- this.instance
.offset
.parent
.top
;
1380 inst
._trigger("toSortable", event
);
1381 inst
.dropped
= this.instance
.element
; //draggable revert needs that
1382 //hack so receive/update callbacks work (mostly)
1383 inst
.currentItem
= inst
.element
;
1384 this.instance
.fromOutside
= inst
;
1388 //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
1389 if(this.instance
.currentItem
) this.instance
._mouseDrag(event
);
1393 //If it doesn't intersect with the sortable, and it intersected before,
1394 //we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval
1395 if(this.instance
.isOver
) {
1397 this.instance
.isOver
= 0;
1398 this.instance
.cancelHelperRemoval
= true;
1400 //Prevent reverting on this forced stop
1401 this.instance
.options
.revert
= false;
1403 // The out event needs to be triggered independently
1404 this.instance
._trigger('out', event
, this.instance
._uiHash(this.instance
));
1406 this.instance
._mouseStop(event
, true);
1407 this.instance
.options
.helper
= this.instance
.options
._helper
;
1409 //Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size
1410 this.instance
.currentItem
.remove();
1411 if(this.instance
.placeholder
) this.instance
.placeholder
.remove();
1413 inst
._trigger("fromSortable", event
);
1414 inst
.dropped
= false; //draggable revert needs that
1424 $.ui
.plugin
.add("draggable", "cursor", {
1425 start: function(event
, ui
) {
1426 var t
= $('body'), o
= $(this).data('draggable').options
;
1427 if (t
.css("cursor")) o
._cursor
= t
.css("cursor");
1428 t
.css("cursor", o
.cursor
);
1430 stop: function(event
, ui
) {
1431 var o
= $(this).data('draggable').options
;
1432 if (o
._cursor
) $('body').css("cursor", o
._cursor
);
1436 $.ui
.plugin
.add("draggable", "iframeFix", {
1437 start: function(event
, ui
) {
1438 var o
= $(this).data('draggable').options
;
1439 $(o
.iframeFix
=== true ? "iframe" : o
.iframeFix
).each(function() {
1440 $('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>')
1442 width
: this.offsetWidth
+"px", height
: this.offsetHeight
+"px",
1443 position
: "absolute", opacity
: "0.001", zIndex
: 1000
1445 .css($(this).offset())
1449 stop: function(event
, ui
) {
1450 $("div.ui-draggable-iframeFix").each(function() { this.parentNode
.removeChild(this); }); //Remove frame helpers
1454 $.ui
.plugin
.add("draggable", "opacity", {
1455 start: function(event
, ui
) {
1456 var t
= $(ui
.helper
), o
= $(this).data('draggable').options
;
1457 if(t
.css("opacity")) o
._opacity
= t
.css("opacity");
1458 t
.css('opacity', o
.opacity
);
1460 stop: function(event
, ui
) {
1461 var o
= $(this).data('draggable').options
;
1462 if(o
._opacity
) $(ui
.helper
).css('opacity', o
._opacity
);
1466 $.ui
.plugin
.add("draggable", "scroll", {
1467 start: function(event
, ui
) {
1468 var i
= $(this).data("draggable");
1469 if(i
.scrollParent
[0] != document
&& i
.scrollParent
[0].tagName
!= 'HTML') i
.overflowOffset
= i
.scrollParent
.offset();
1471 drag: function(event
, ui
) {
1473 var i
= $(this).data("draggable"), o
= i
.options
, scrolled
= false;
1475 if(i
.scrollParent
[0] != document
&& i
.scrollParent
[0].tagName
!= 'HTML') {
1477 if(!o
.axis
|| o
.axis
!= 'x') {
1478 if((i
.overflowOffset
.top
+ i
.scrollParent
[0].offsetHeight
) - event
.pageY
< o
.scrollSensitivity
)
1479 i
.scrollParent
[0].scrollTop
= scrolled
= i
.scrollParent
[0].scrollTop
+ o
.scrollSpeed
;
1480 else if(event
.pageY
- i
.overflowOffset
.top
< o
.scrollSensitivity
)
1481 i
.scrollParent
[0].scrollTop
= scrolled
= i
.scrollParent
[0].scrollTop
- o
.scrollSpeed
;
1484 if(!o
.axis
|| o
.axis
!= 'y') {
1485 if((i
.overflowOffset
.left
+ i
.scrollParent
[0].offsetWidth
) - event
.pageX
< o
.scrollSensitivity
)
1486 i
.scrollParent
[0].scrollLeft
= scrolled
= i
.scrollParent
[0].scrollLeft
+ o
.scrollSpeed
;
1487 else if(event
.pageX
- i
.overflowOffset
.left
< o
.scrollSensitivity
)
1488 i
.scrollParent
[0].scrollLeft
= scrolled
= i
.scrollParent
[0].scrollLeft
- o
.scrollSpeed
;
1493 if(!o
.axis
|| o
.axis
!= 'x') {
1494 if(event
.pageY
- $(document
).scrollTop() < o
.scrollSensitivity
)
1495 scrolled
= $(document
).scrollTop($(document
).scrollTop() - o
.scrollSpeed
);
1496 else if($(window
).height() - (event
.pageY
- $(document
).scrollTop()) < o
.scrollSensitivity
)
1497 scrolled
= $(document
).scrollTop($(document
).scrollTop() + o
.scrollSpeed
);
1500 if(!o
.axis
|| o
.axis
!= 'y') {
1501 if(event
.pageX
- $(document
).scrollLeft() < o
.scrollSensitivity
)
1502 scrolled
= $(document
).scrollLeft($(document
).scrollLeft() - o
.scrollSpeed
);
1503 else if($(window
).width() - (event
.pageX
- $(document
).scrollLeft()) < o
.scrollSensitivity
)
1504 scrolled
= $(document
).scrollLeft($(document
).scrollLeft() + o
.scrollSpeed
);
1509 if(scrolled
!== false && $.ui
.ddmanager
&& !o
.dropBehaviour
)
1510 $.ui
.ddmanager
.prepareOffsets(i
, event
);
1515 $.ui
.plugin
.add("draggable", "snap", {
1516 start: function(event
, ui
) {
1518 var i
= $(this).data("draggable"), o
= i
.options
;
1519 i
.snapElements
= [];
1521 $(o
.snap
.constructor != String
? ( o
.snap
.items
|| ':data(draggable)' ) : o
.snap
).each(function() {
1522 var $t
= $(this); var $o
= $t
.offset();
1523 if(this != i
.element
[0]) i
.snapElements
.push({
1525 width
: $t
.outerWidth(), height
: $t
.outerHeight(),
1526 top
: $o
.top
, left
: $o
.left
1531 drag: function(event
, ui
) {
1533 var inst
= $(this).data("draggable"), o
= inst
.options
;
1534 var d
= o
.snapTolerance
;
1536 var x1
= ui
.offset
.left
, x2
= x1
+ inst
.helperProportions
.width
,
1537 y1
= ui
.offset
.top
, y2
= y1
+ inst
.helperProportions
.height
;
1539 for (var i
= inst
.snapElements
.length
- 1; i
>= 0; i
--){
1541 var l
= inst
.snapElements
[i
].left
, r
= l
+ inst
.snapElements
[i
].width
,
1542 t
= inst
.snapElements
[i
].top
, b
= t
+ inst
.snapElements
[i
].height
;
1544 //Yes, I know, this is insane ;)
1545 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
))) {
1546 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
})));
1547 inst
.snapElements
[i
].snapping
= false;
1551 if(o
.snapMode
!= 'inner') {
1552 var ts
= Math
.abs(t
- y2
) <= d
;
1553 var bs
= Math
.abs(b
- y1
) <= d
;
1554 var ls
= Math
.abs(l
- x2
) <= d
;
1555 var rs
= Math
.abs(r
- x1
) <= d
;
1556 if(ts
) ui
.position
.top
= inst
._convertPositionTo("relative", { top
: t
- inst
.helperProportions
.height
, left
: 0 }).top
- inst
.margins
.top
;
1557 if(bs
) ui
.position
.top
= inst
._convertPositionTo("relative", { top
: b
, left
: 0 }).top
- inst
.margins
.top
;
1558 if(ls
) ui
.position
.left
= inst
._convertPositionTo("relative", { top
: 0, left
: l
- inst
.helperProportions
.width
}).left
- inst
.margins
.left
;
1559 if(rs
) ui
.position
.left
= inst
._convertPositionTo("relative", { top
: 0, left
: r
}).left
- inst
.margins
.left
;
1562 var first
= (ts
|| bs
|| ls
|| rs
);
1564 if(o
.snapMode
!= 'outer') {
1565 var ts
= Math
.abs(t
- y1
) <= d
;
1566 var bs
= Math
.abs(b
- y2
) <= d
;
1567 var ls
= Math
.abs(l
- x1
) <= d
;
1568 var rs
= Math
.abs(r
- x2
) <= d
;
1569 if(ts
) ui
.position
.top
= inst
._convertPositionTo("relative", { top
: t
, left
: 0 }).top
- inst
.margins
.top
;
1570 if(bs
) ui
.position
.top
= inst
._convertPositionTo("relative", { top
: b
- inst
.helperProportions
.height
, left
: 0 }).top
- inst
.margins
.top
;
1571 if(ls
) ui
.position
.left
= inst
._convertPositionTo("relative", { top
: 0, left
: l
}).left
- inst
.margins
.left
;
1572 if(rs
) ui
.position
.left
= inst
._convertPositionTo("relative", { top
: 0, left
: r
- inst
.helperProportions
.width
}).left
- inst
.margins
.left
;
1575 if(!inst
.snapElements
[i
].snapping
&& (ts
|| bs
|| ls
|| rs
|| first
))
1576 (inst
.options
.snap
.snap
&& inst
.options
.snap
.snap
.call(inst
.element
, event
, $.extend(inst
._uiHash(), { snapItem
: inst
.snapElements
[i
].item
})));
1577 inst
.snapElements
[i
].snapping
= (ts
|| bs
|| ls
|| rs
|| first
);
1584 $.ui
.plugin
.add("draggable", "stack", {
1585 start: function(event
, ui
) {
1587 var o
= $(this).data("draggable").options
;
1589 var group
= $.makeArray($(o
.stack
)).sort(function(a
,b
) {
1590 return (parseInt($(a
).css("zIndex"),10) || 0) - (parseInt($(b
).css("zIndex"),10) || 0);
1592 if (!group
.length
) { return; }
1594 var min
= parseInt(group
[0].style
.zIndex
) || 0;
1595 $(group
).each(function(i
) {
1596 this.style
.zIndex
= min
+ i
;
1599 this[0].style
.zIndex
= min
+ group
.length
;
1604 $.ui
.plugin
.add("draggable", "zIndex", {
1605 start: function(event
, ui
) {
1606 var t
= $(ui
.helper
), o
= $(this).data("draggable").options
;
1607 if(t
.css("zIndex")) o
._zIndex
= t
.css("zIndex");
1608 t
.css('zIndex', o
.zIndex
);
1610 stop: function(event
, ui
) {
1611 var o
= $(this).data("draggable").options
;
1612 if(o
._zIndex
) $(ui
.helper
).css('zIndex', o
._zIndex
);
1618 * jQuery UI Droppable 1.8
1620 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
1621 * Dual licensed under the MIT (MIT-LICENSE.txt)
1622 * and GPL (GPL-LICENSE.txt) licenses.
1624 * http://docs.jquery.com/UI/Droppables
1628 * jquery.ui.widget.js
1629 * jquery.ui.mouse.js
1630 * jquery.ui.draggable.js
1634 $.widget("ui.droppable", {
1635 widgetEventPrefix
: "drop",
1643 tolerance
: 'intersect'
1645 _create: function() {
1647 var o
= this.options
, accept
= o
.accept
;
1648 this.isover
= 0; this.isout
= 1;
1650 this.accept
= $.isFunction(accept
) ? accept : function(d
) {
1651 return d
.is(accept
);
1654 //Store the droppable's proportions
1655 this.proportions
= { width
: this.element
[0].offsetWidth
, height
: this.element
[0].offsetHeight
};
1657 // Add the reference and positions to the manager
1658 $.ui
.ddmanager
.droppables
[o
.scope
] = $.ui
.ddmanager
.droppables
[o
.scope
] || [];
1659 $.ui
.ddmanager
.droppables
[o
.scope
].push(this);
1661 (o
.addClasses
&& this.element
.addClass("ui-droppable"));
1665 destroy: function() {
1666 var drop
= $.ui
.ddmanager
.droppables
[this.options
.scope
];
1667 for ( var i
= 0; i
< drop
.length
; i
++ )
1668 if ( drop
[i
] == this )
1672 .removeClass("ui-droppable ui-droppable-disabled")
1673 .removeData("droppable")
1674 .unbind(".droppable");
1679 _setOption: function(key
, value
) {
1681 if(key
== 'accept') {
1682 this.accept
= $.isFunction(value
) ? value : function(d
) {
1686 $.Widget
.prototype._setOption
.apply(this, arguments
);
1689 _activate: function(event
) {
1690 var draggable
= $.ui
.ddmanager
.current
;
1691 if(this.options
.activeClass
) this.element
.addClass(this.options
.activeClass
);
1692 (draggable
&& this._trigger('activate', event
, this.ui(draggable
)));
1695 _deactivate: function(event
) {
1696 var draggable
= $.ui
.ddmanager
.current
;
1697 if(this.options
.activeClass
) this.element
.removeClass(this.options
.activeClass
);
1698 (draggable
&& this._trigger('deactivate', event
, this.ui(draggable
)));
1701 _over: function(event
) {
1703 var draggable
= $.ui
.ddmanager
.current
;
1704 if (!draggable
|| (draggable
.currentItem
|| draggable
.element
)[0] == this.element
[0]) return; // Bail if draggable and droppable are same element
1706 if (this.accept
.call(this.element
[0],(draggable
.currentItem
|| draggable
.element
))) {
1707 if(this.options
.hoverClass
) this.element
.addClass(this.options
.hoverClass
);
1708 this._trigger('over', event
, this.ui(draggable
));
1713 _out: function(event
) {
1715 var draggable
= $.ui
.ddmanager
.current
;
1716 if (!draggable
|| (draggable
.currentItem
|| draggable
.element
)[0] == this.element
[0]) return; // Bail if draggable and droppable are same element
1718 if (this.accept
.call(this.element
[0],(draggable
.currentItem
|| draggable
.element
))) {
1719 if(this.options
.hoverClass
) this.element
.removeClass(this.options
.hoverClass
);
1720 this._trigger('out', event
, this.ui(draggable
));
1725 _drop: function(event
,custom
) {
1727 var draggable
= custom
|| $.ui
.ddmanager
.current
;
1728 if (!draggable
|| (draggable
.currentItem
|| draggable
.element
)[0] == this.element
[0]) return false; // Bail if draggable and droppable are same element
1730 var childrenIntersection
= false;
1731 this.element
.find(":data(droppable)").not(".ui-draggable-dragging").each(function() {
1732 var inst
= $.data(this, 'droppable');
1735 && !inst
.options
.disabled
1736 && inst
.options
.scope
== draggable
.options
.scope
1737 && inst
.accept
.call(inst
.element
[0], (draggable
.currentItem
|| draggable
.element
))
1738 && $.ui
.intersect(draggable
, $.extend(inst
, { offset
: inst
.element
.offset() }), inst
.options
.tolerance
)
1739 ) { childrenIntersection
= true; return false; }
1741 if(childrenIntersection
) return false;
1743 if(this.accept
.call(this.element
[0],(draggable
.currentItem
|| draggable
.element
))) {
1744 if(this.options
.activeClass
) this.element
.removeClass(this.options
.activeClass
);
1745 if(this.options
.hoverClass
) this.element
.removeClass(this.options
.hoverClass
);
1746 this._trigger('drop', event
, this.ui(draggable
));
1747 return this.element
;
1756 draggable
: (c
.currentItem
|| c
.element
),
1758 position
: c
.position
,
1759 offset
: c
.positionAbs
1765 $.extend($.ui
.droppable
, {
1769 $.ui
.intersect = function(draggable
, droppable
, toleranceMode
) {
1771 if (!droppable
.offset
) return false;
1773 var x1
= (draggable
.positionAbs
|| draggable
.position
.absolute
).left
, x2
= x1
+ draggable
.helperProportions
.width
,
1774 y1
= (draggable
.positionAbs
|| draggable
.position
.absolute
).top
, y2
= y1
+ draggable
.helperProportions
.height
;
1775 var l
= droppable
.offset
.left
, r
= l
+ droppable
.proportions
.width
,
1776 t
= droppable
.offset
.top
, b
= t
+ droppable
.proportions
.height
;
1778 switch (toleranceMode
) {
1780 return (l
< x1
&& x2
< r
1781 && t
< y1
&& y2
< b
);
1784 return (l
< x1
+ (draggable
.helperProportions
.width
/ 2) // Right Half
1785 && x2
- (draggable
.helperProportions
.width
/ 2) < r
// Left Half
1786 && t
< y1
+ (draggable
.helperProportions
.height
/ 2) // Bottom Half
1787 && y2
- (draggable
.helperProportions
.height
/ 2) < b
); // Top Half
1790 var draggableLeft
= ((draggable
.positionAbs
|| draggable
.position
.absolute
).left
+ (draggable
.clickOffset
|| draggable
.offset
.click
).left
),
1791 draggableTop
= ((draggable
.positionAbs
|| draggable
.position
.absolute
).top
+ (draggable
.clickOffset
|| draggable
.offset
.click
).top
),
1792 isOver
= $.ui
.isOver(draggableTop
, draggableLeft
, t
, l
, droppable
.proportions
.height
, droppable
.proportions
.width
);
1797 (y1
>= t
&& y1
<= b
) || // Top edge touching
1798 (y2
>= t
&& y2
<= b
) || // Bottom edge touching
1799 (y1
< t
&& y2
> b
) // Surrounded vertically
1801 (x1
>= l
&& x1
<= r
) || // Left edge touching
1802 (x2
>= l
&& x2
<= r
) || // Right edge touching
1803 (x1
< l
&& x2
> r
) // Surrounded horizontally
1814 This manager tracks offsets of draggables and droppables
1818 droppables
: { 'default': [] },
1819 prepareOffsets: function(t
, event
) {
1821 var m
= $.ui
.ddmanager
.droppables
[t
.options
.scope
] || [];
1822 var type
= event
? event
.type
: null; // workaround for #2317
1823 var list
= (t
.currentItem
|| t
.element
).find(":data(droppable)").andSelf();
1825 droppablesLoop
: for (var i
= 0; i
< m
.length
; i
++) {
1827 if(m
[i
].options
.disabled
|| (t
&& !m
[i
].accept
.call(m
[i
].element
[0],(t
.currentItem
|| t
.element
)))) continue; //No disabled and non-accepted
1828 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
1829 m
[i
].visible
= m
[i
].element
.css("display") != "none"; if(!m
[i
].visible
) continue; //If the element is not visible, continue
1831 m
[i
].offset
= m
[i
].element
.offset();
1832 m
[i
].proportions
= { width
: m
[i
].element
[0].offsetWidth
, height
: m
[i
].element
[0].offsetHeight
};
1834 if(type
== "mousedown") m
[i
]._activate
.call(m
[i
], event
); //Activate the droppable if used directly from draggables
1839 drop: function(draggable
, event
) {
1841 var dropped
= false;
1842 $.each($.ui
.ddmanager
.droppables
[draggable
.options
.scope
] || [], function() {
1844 if(!this.options
) return;
1845 if (!this.options
.disabled
&& this.visible
&& $.ui
.intersect(draggable
, this, this.options
.tolerance
))
1846 dropped
= dropped
|| this._drop
.call(this, event
);
1848 if (!this.options
.disabled
&& this.visible
&& this.accept
.call(this.element
[0],(draggable
.currentItem
|| draggable
.element
))) {
1849 this.isout
= 1; this.isover
= 0;
1850 this._deactivate
.call(this, event
);
1857 drag: function(draggable
, event
) {
1859 //If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse.
1860 if(draggable
.options
.refreshPositions
) $.ui
.ddmanager
.prepareOffsets(draggable
, event
);
1862 //Run through all droppables and check their positions based on specific tolerance options
1863 $.each($.ui
.ddmanager
.droppables
[draggable
.options
.scope
] || [], function() {
1865 if(this.options
.disabled
|| this.greedyChild
|| !this.visible
) return;
1866 var intersects
= $.ui
.intersect(draggable
, this, this.options
.tolerance
);
1868 var c
= !intersects
&& this.isover
== 1 ? 'isout' : (intersects
&& this.isover
== 0 ? 'isover' : null);
1872 if (this.options
.greedy
) {
1873 var parent
= this.element
.parents(':data(droppable):eq(0)');
1874 if (parent
.length
) {
1875 parentInstance
= $.data(parent
[0], 'droppable');
1876 parentInstance
.greedyChild
= (c
== 'isover' ? 1 : 0);
1880 // we just moved into a greedy child
1881 if (parentInstance
&& c
== 'isover') {
1882 parentInstance
['isover'] = 0;
1883 parentInstance
['isout'] = 1;
1884 parentInstance
._out
.call(parentInstance
, event
);
1887 this[c
] = 1; this[c
== 'isout' ? 'isover' : 'isout'] = 0;
1888 this[c
== "isover" ? "_over" : "_out"].call(this, event
);
1890 // we just moved out of a greedy child
1891 if (parentInstance
&& c
== 'isout') {
1892 parentInstance
['isout'] = 0;
1893 parentInstance
['isover'] = 1;
1894 parentInstance
._over
.call(parentInstance
, event
);
1903 * jQuery UI Resizable 1.8
1905 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
1906 * Dual licensed under the MIT (MIT-LICENSE.txt)
1907 * and GPL (GPL-LICENSE.txt) licenses.
1909 * http://docs.jquery.com/UI/Resizables
1913 * jquery.ui.mouse.js
1914 * jquery.ui.widget.js
1918 $.widget("ui.resizable", $.ui
.mouse
, {
1919 widgetEventPrefix
: "resize",
1923 animateDuration
: "slow",
1924 animateEasing
: "swing",
1938 _create: function() {
1940 var self
= this, o
= this.options
;
1941 this.element
.addClass("ui-resizable");
1944 _aspectRatio
: !!(o
.aspectRatio
),
1945 aspectRatio
: o
.aspectRatio
,
1946 originalElement
: this.element
,
1947 _proportionallyResizeElements
: [],
1948 _helper
: o
.helper
|| o
.ghost
|| o
.animate
? o
.helper
|| 'ui-resizable-helper' : null
1951 //Wrap the element if it cannot hold child nodes
1952 if(this.element
[0].nodeName
.match(/canvas|textarea|input|select|button|img/i)) {
1954 //Opera fix for relative positioning
1955 if (/relative/.test(this.element
.css('position')) && $.browser
.opera
)
1956 this.element
.css({ position
: 'relative', top
: 'auto', left
: 'auto' });
1958 //Create a wrapper element and set the wrapper to the new current internal element
1960 $('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({
1961 position
: this.element
.css('position'),
1962 width
: this.element
.outerWidth(),
1963 height
: this.element
.outerHeight(),
1964 top
: this.element
.css('top'),
1965 left
: this.element
.css('left')
1969 //Overwrite the original this.element
1970 this.element
= this.element
.parent().data(
1971 "resizable", this.element
.data('resizable')
1974 this.elementIsWrapper
= true;
1976 //Move margins to the wrapper
1977 this.element
.css({ marginLeft
: this.originalElement
.css("marginLeft"), marginTop
: this.originalElement
.css("marginTop"), marginRight
: this.originalElement
.css("marginRight"), marginBottom
: this.originalElement
.css("marginBottom") });
1978 this.originalElement
.css({ marginLeft
: 0, marginTop
: 0, marginRight
: 0, marginBottom
: 0});
1980 //Prevent Safari textarea resize
1981 this.originalResizeStyle
= this.originalElement
.css('resize');
1982 this.originalElement
.css('resize', 'none');
1984 //Push the actual element to our proportionallyResize internal array
1985 this._proportionallyResizeElements
.push(this.originalElement
.css({ position
: 'static', zoom
: 1, display
: 'block' }));
1987 // avoid IE jump (hard set the margin)
1988 this.originalElement
.css({ margin
: this.originalElement
.css('margin') });
1990 // fix handlers offset
1991 this._proportionallyResize();
1995 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' });
1996 if(this.handles
.constructor == String
) {
1998 if(this.handles
== 'all') this.handles
= 'n,e,s,w,se,sw,ne,nw';
1999 var n
= this.handles
.split(","); this.handles
= {};
2001 for(var i
= 0; i
< n
.length
; i
++) {
2003 var handle
= $.trim(n
[i
]), hname
= 'ui-resizable-'+handle
;
2004 var axis
= $('<div class="ui-resizable-handle ' + hname
+ '"></div>');
2006 // increase zIndex of sw, se, ne, nw axis
2007 //TODO : this modifies original option
2008 if(/sw|se|ne|nw/.test(handle
)) axis
.css({ zIndex
: ++o
.zIndex
});
2010 //TODO : What's going on here?
2011 if ('se' == handle
) {
2012 axis
.addClass('ui-icon ui-icon-gripsmall-diagonal-se');
2015 //Insert into internal handles object and append to element
2016 this.handles
[handle
] = '.ui-resizable-'+handle
;
2017 this.element
.append(axis
);
2022 this._renderAxis = function(target
) {
2024 target
= target
|| this.element
;
2026 for(var i
in this.handles
) {
2028 if(this.handles
[i
].constructor == String
)
2029 this.handles
[i
] = $(this.handles
[i
], this.element
).show();
2031 //Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls)
2032 if (this.elementIsWrapper
&& this.originalElement
[0].nodeName
.match(/textarea|input|select|button/i)) {
2034 var axis
= $(this.handles
[i
], this.element
), padWrapper
= 0;
2036 //Checking the correct pad and border
2037 padWrapper
= /sw|ne|nw|se|n|s/.test(i
) ? axis
.outerHeight() : axis
.outerWidth();
2039 //The padding type i have to apply...
2040 var padPos
= [ 'padding',
2041 /ne|nw|n/.test(i
) ? 'Top' :
2042 /se|sw|s/.test(i
) ? 'Bottom' :
2043 /^e$/.test(i
) ? 'Right' : 'Left' ].join("");
2045 target
.css(padPos
, padWrapper
);
2047 this._proportionallyResize();
2051 //TODO: What's that good for? There's not anything to be executed left
2052 if(!$(this.handles
[i
]).length
)
2058 //TODO: make renderAxis a prototype function
2059 this._renderAxis(this.element
);
2061 this._handles
= $('.ui-resizable-handle', this.element
)
2062 .disableSelection();
2064 //Matching axis name
2065 this._handles
.mouseover(function() {
2066 if (!self
.resizing
) {
2068 var axis
= this.className
.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);
2069 //Axis, default = se
2070 self
.axis
= axis
&& axis
[1] ? axis
[1] : 'se';
2074 //If we want to auto hide the elements
2076 this._handles
.hide();
2078 .addClass("ui-resizable-autohide")
2080 $(this).removeClass("ui-resizable-autohide");
2081 self
._handles
.show();
2084 if (!self
.resizing
) {
2085 $(this).addClass("ui-resizable-autohide");
2086 self
._handles
.hide();
2091 //Initialize the mouse interaction
2096 destroy: function() {
2098 this._mouseDestroy();
2100 var _destroy = function(exp
) {
2101 $(exp
).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing")
2102 .removeData("resizable").unbind(".resizable").find('.ui-resizable-handle').remove();
2105 //TODO: Unwrap at same DOM position
2106 if (this.elementIsWrapper
) {
2107 _destroy(this.element
);
2108 var wrapper
= this.element
;
2110 this.originalElement
.css({
2111 position
: wrapper
.css('position'),
2112 width
: wrapper
.outerWidth(),
2113 height
: wrapper
.outerHeight(),
2114 top
: wrapper
.css('top'),
2115 left
: wrapper
.css('left')
2120 this.originalElement
.css('resize', this.originalResizeStyle
);
2121 _destroy(this.originalElement
);
2126 _mouseCapture: function(event
) {
2128 for (var i
in this.handles
) {
2129 if ($(this.handles
[i
])[0] == event
.target
) {
2134 return !this.options
.disabled
&& handle
;
2137 _mouseStart: function(event
) {
2139 var o
= this.options
, iniPos
= this.element
.position(), el
= this.element
;
2141 this.resizing
= true;
2142 this.documentScroll
= { top
: $(document
).scrollTop(), left
: $(document
).scrollLeft() };
2144 // bugfix for http://dev.jquery.com/ticket/1749
2145 if (el
.is('.ui-draggable') || (/absolute/).test(el
.css('position'))) {
2146 el
.css({ position
: 'absolute', top
: iniPos
.top
, left
: iniPos
.left
});
2149 //Opera fixing relative position
2150 if ($.browser
.opera
&& (/relative/).test(el
.css('position')))
2151 el
.css({ position
: 'relative', top
: 'auto', left
: 'auto' });
2153 this._renderProxy();
2155 var curleft
= num(this.helper
.css('left')), curtop
= num(this.helper
.css('top'));
2157 if (o
.containment
) {
2158 curleft
+= $(o
.containment
).scrollLeft() || 0;
2159 curtop
+= $(o
.containment
).scrollTop() || 0;
2162 //Store needed variables
2163 this.offset
= this.helper
.offset();
2164 this.position
= { left
: curleft
, top
: curtop
};
2165 this.size
= this._helper
? { width
: el
.outerWidth(), height
: el
.outerHeight() } : { width
: el
.width(), height
: el
.height() };
2166 this.originalSize
= this._helper
? { width
: el
.outerWidth(), height
: el
.outerHeight() } : { width
: el
.width(), height
: el
.height() };
2167 this.originalPosition
= { left
: curleft
, top
: curtop
};
2168 this.sizeDiff
= { width
: el
.outerWidth() - el
.width(), height
: el
.outerHeight() - el
.height() };
2169 this.originalMousePosition
= { left
: event
.pageX
, top
: event
.pageY
};
2172 this.aspectRatio
= (typeof o
.aspectRatio
== 'number') ? o
.aspectRatio
: ((this.originalSize
.width
/ this.originalSize
.height
) || 1);
2174 var cursor
= $('.ui-resizable-' + this.axis
).css('cursor');
2175 $('body').css('cursor', cursor
== 'auto' ? this.axis
+ '-resize' : cursor
);
2177 el
.addClass("ui-resizable-resizing");
2178 this._propagate("start", event
);
2182 _mouseDrag: function(event
) {
2184 //Increase performance, avoid regex
2185 var el
= this.helper
, o
= this.options
, props
= {},
2186 self
= this, smp
= this.originalMousePosition
, a
= this.axis
;
2188 var dx
= (event
.pageX
-smp
.left
)||0, dy
= (event
.pageY
-smp
.top
)||0;
2189 var trigger
= this._change
[a
];
2190 if (!trigger
) return false;
2192 // Calculate the attrs that will be change
2193 var data
= trigger
.apply(this, [event
, dx
, dy
]), ie6
= $.browser
.msie
&& $.browser
.version
< 7, csdif
= this.sizeDiff
;
2195 if (this._aspectRatio
|| event
.shiftKey
)
2196 data
= this._updateRatio(data
, event
);
2198 data
= this._respectSize(data
, event
);
2200 // plugins callbacks need to be called first
2201 this._propagate("resize", event
);
2204 top
: this.position
.top
+ "px", left
: this.position
.left
+ "px",
2205 width
: this.size
.width
+ "px", height
: this.size
.height
+ "px"
2208 if (!this._helper
&& this._proportionallyResizeElements
.length
)
2209 this._proportionallyResize();
2211 this._updateCache(data
);
2213 // calling the user callback at the end
2214 this._trigger('resize', event
, this.ui());
2219 _mouseStop: function(event
) {
2221 this.resizing
= false;
2222 var o
= this.options
, self
= this;
2225 var pr
= this._proportionallyResizeElements
, ista
= pr
.length
&& (/textarea/i).test(pr
[0].nodeName
),
2226 soffseth
= ista
&& $.ui
.hasScroll(pr
[0], 'left') /* TODO - jump height */ ? 0 : self
.sizeDiff
.height
,
2227 soffsetw
= ista
? 0 : self
.sizeDiff
.width
;
2229 var s
= { width
: (self
.size
.width
- soffsetw
), height
: (self
.size
.height
- soffseth
) },
2230 left
= (parseInt(self
.element
.css('left'), 10) + (self
.position
.left
- self
.originalPosition
.left
)) || null,
2231 top
= (parseInt(self
.element
.css('top'), 10) + (self
.position
.top
- self
.originalPosition
.top
)) || null;
2234 this.element
.css($.extend(s
, { top
: top
, left
: left
}));
2236 self
.helper
.height(self
.size
.height
);
2237 self
.helper
.width(self
.size
.width
);
2239 if (this._helper
&& !o
.animate
) this._proportionallyResize();
2242 $('body').css('cursor', 'auto');
2244 this.element
.removeClass("ui-resizable-resizing");
2246 this._propagate("stop", event
);
2248 if (this._helper
) this.helper
.remove();
2253 _updateCache: function(data
) {
2254 var o
= this.options
;
2255 this.offset
= this.helper
.offset();
2256 if (isNumber(data
.left
)) this.position
.left
= data
.left
;
2257 if (isNumber(data
.top
)) this.position
.top
= data
.top
;
2258 if (isNumber(data
.height
)) this.size
.height
= data
.height
;
2259 if (isNumber(data
.width
)) this.size
.width
= data
.width
;
2262 _updateRatio: function(data
, event
) {
2264 var o
= this.options
, cpos
= this.position
, csize
= this.size
, a
= this.axis
;
2266 if (data
.height
) data
.width
= (csize
.height
* this.aspectRatio
);
2267 else if (data
.width
) data
.height
= (csize
.width
/ this.aspectRatio
);
2270 data
.left
= cpos
.left
+ (csize
.width
- data
.width
);
2274 data
.top
= cpos
.top
+ (csize
.height
- data
.height
);
2275 data
.left
= cpos
.left
+ (csize
.width
- data
.width
);
2281 _respectSize: function(data
, event
) {
2283 var el
= this.helper
, o
= this.options
, pRatio
= this._aspectRatio
|| event
.shiftKey
, a
= this.axis
,
2284 ismaxw
= isNumber(data
.width
) && o
.maxWidth
&& (o
.maxWidth
< data
.width
), ismaxh
= isNumber(data
.height
) && o
.maxHeight
&& (o
.maxHeight
< data
.height
),
2285 isminw
= isNumber(data
.width
) && o
.minWidth
&& (o
.minWidth
> data
.width
), isminh
= isNumber(data
.height
) && o
.minHeight
&& (o
.minHeight
> data
.height
);
2287 if (isminw
) data
.width
= o
.minWidth
;
2288 if (isminh
) data
.height
= o
.minHeight
;
2289 if (ismaxw
) data
.width
= o
.maxWidth
;
2290 if (ismaxh
) data
.height
= o
.maxHeight
;
2292 var dw
= this.originalPosition
.left
+ this.originalSize
.width
, dh
= this.position
.top
+ this.size
.height
;
2293 var cw
= /sw|nw|w/.test(a
), ch
= /nw|ne|n/.test(a
);
2295 if (isminw
&& cw
) data
.left
= dw
- o
.minWidth
;
2296 if (ismaxw
&& cw
) data
.left
= dw
- o
.maxWidth
;
2297 if (isminh
&& ch
) data
.top
= dh
- o
.minHeight
;
2298 if (ismaxh
&& ch
) data
.top
= dh
- o
.maxHeight
;
2300 // fixing jump error on top/left - bug #2330
2301 var isNotwh
= !data
.width
&& !data
.height
;
2302 if (isNotwh
&& !data
.left
&& data
.top
) data
.top
= null;
2303 else if (isNotwh
&& !data
.top
&& data
.left
) data
.left
= null;
2308 _proportionallyResize: function() {
2310 var o
= this.options
;
2311 if (!this._proportionallyResizeElements
.length
) return;
2312 var element
= this.helper
|| this.element
;
2314 for (var i
=0; i
< this._proportionallyResizeElements
.length
; i
++) {
2316 var prel
= this._proportionallyResizeElements
[i
];
2318 if (!this.borderDif
) {
2319 var b
= [prel
.css('borderTopWidth'), prel
.css('borderRightWidth'), prel
.css('borderBottomWidth'), prel
.css('borderLeftWidth')],
2320 p
= [prel
.css('paddingTop'), prel
.css('paddingRight'), prel
.css('paddingBottom'), prel
.css('paddingLeft')];
2322 this.borderDif
= $.map(b
, function(v
, i
) {
2323 var border
= parseInt(v
,10)||0, padding
= parseInt(p
[i
],10)||0;
2324 return border
+ padding
;
2328 if ($.browser
.msie
&& !(!($(element
).is(':hidden') || $(element
).parents(':hidden').length
)))
2332 height
: (element
.height() - this.borderDif
[0] - this.borderDif
[2]) || 0,
2333 width
: (element
.width() - this.borderDif
[1] - this.borderDif
[3]) || 0
2340 _renderProxy: function() {
2342 var el
= this.element
, o
= this.options
;
2343 this.elementOffset
= el
.offset();
2347 this.helper
= this.helper
|| $('<div style="overflow:hidden;"></div>');
2349 // fix ie6 offset TODO: This seems broken
2350 var ie6
= $.browser
.msie
&& $.browser
.version
< 7, ie6offset
= (ie6
? 1 : 0),
2351 pxyoffset
= ( ie6
? 2 : -1 );
2353 this.helper
.addClass(this._helper
).css({
2354 width
: this.element
.outerWidth() + pxyoffset
,
2355 height
: this.element
.outerHeight() + pxyoffset
,
2356 position
: 'absolute',
2357 left
: this.elementOffset
.left
- ie6offset
+'px',
2358 top
: this.elementOffset
.top
- ie6offset
+'px',
2359 zIndex
: ++o
.zIndex
//TODO: Don't modify option
2364 .disableSelection();
2367 this.helper
= this.element
;
2373 e: function(event
, dx
, dy
) {
2374 return { width
: this.originalSize
.width
+ dx
};
2376 w: function(event
, dx
, dy
) {
2377 var o
= this.options
, cs
= this.originalSize
, sp
= this.originalPosition
;
2378 return { left
: sp
.left
+ dx
, width
: cs
.width
- dx
};
2380 n: function(event
, dx
, dy
) {
2381 var o
= this.options
, cs
= this.originalSize
, sp
= this.originalPosition
;
2382 return { top
: sp
.top
+ dy
, height
: cs
.height
- dy
};
2384 s: function(event
, dx
, dy
) {
2385 return { height
: this.originalSize
.height
+ dy
};
2387 se: function(event
, dx
, dy
) {
2388 return $.extend(this._change
.s
.apply(this, arguments
), this._change
.e
.apply(this, [event
, dx
, dy
]));
2390 sw: function(event
, dx
, dy
) {
2391 return $.extend(this._change
.s
.apply(this, arguments
), this._change
.w
.apply(this, [event
, dx
, dy
]));
2393 ne: function(event
, dx
, dy
) {
2394 return $.extend(this._change
.n
.apply(this, arguments
), this._change
.e
.apply(this, [event
, dx
, dy
]));
2396 nw: function(event
, dx
, dy
) {
2397 return $.extend(this._change
.n
.apply(this, arguments
), this._change
.w
.apply(this, [event
, dx
, dy
]));
2401 _propagate: function(n
, event
) {
2402 $.ui
.plugin
.call(this, n
, [event
, this.ui()]);
2403 (n
!= "resize" && this._trigger(n
, event
, this.ui()));
2410 originalElement
: this.originalElement
,
2411 element
: this.element
,
2412 helper
: this.helper
,
2413 position
: this.position
,
2415 originalSize
: this.originalSize
,
2416 originalPosition
: this.originalPosition
2422 $.extend($.ui
.resizable
, {
2427 * Resizable Extensions
2430 $.ui
.plugin
.add("resizable", "alsoResize", {
2432 start: function(event
, ui
) {
2434 var self
= $(this).data("resizable"), o
= self
.options
;
2436 var _store = function(exp
) {
2437 $(exp
).each(function() {
2438 $(this).data("resizable-alsoresize", {
2439 width
: parseInt($(this).width(), 10), height
: parseInt($(this).height(), 10),
2440 left
: parseInt($(this).css('left'), 10), top
: parseInt($(this).css('top'), 10)
2445 if (typeof(o
.alsoResize
) == 'object' && !o
.alsoResize
.parentNode
) {
2446 if (o
.alsoResize
.length
) { o
.alsoResize
= o
.alsoResize
[0]; _store(o
.alsoResize
); }
2447 else { $.each(o
.alsoResize
, function(exp
, c
) { _store(exp
); }); }
2449 _store(o
.alsoResize
);
2453 resize: function(event
, ui
){
2454 var self
= $(this).data("resizable"), o
= self
.options
, os
= self
.originalSize
, op
= self
.originalPosition
;
2457 height
: (self
.size
.height
- os
.height
) || 0, width
: (self
.size
.width
- os
.width
) || 0,
2458 top
: (self
.position
.top
- op
.top
) || 0, left
: (self
.position
.left
- op
.left
) || 0
2461 _alsoResize = function(exp
, c
) {
2462 $(exp
).each(function() {
2463 var el
= $(this), start
= $(this).data("resizable-alsoresize"), style
= {}, css
= c
&& c
.length
? c
: ['width', 'height', 'top', 'left'];
2465 $.each(css
|| ['width', 'height', 'top', 'left'], function(i
, prop
) {
2466 var sum
= (start
[prop
]||0) + (delta
[prop
]||0);
2467 if (sum
&& sum
>= 0)
2468 style
[prop
] = sum
|| null;
2471 //Opera fixing relative position
2472 if (/relative/.test(el
.css('position')) && $.browser
.opera
) {
2473 self
._revertToRelativePosition
= true;
2474 el
.css({ position
: 'absolute', top
: 'auto', left
: 'auto' });
2481 if (typeof(o
.alsoResize
) == 'object' && !o
.alsoResize
.nodeType
) {
2482 $.each(o
.alsoResize
, function(exp
, c
) { _alsoResize(exp
, c
); });
2484 _alsoResize(o
.alsoResize
);
2488 stop: function(event
, ui
){
2489 var self
= $(this).data("resizable");
2491 //Opera fixing relative position
2492 if (self
._revertToRelativePosition
&& $.browser
.opera
) {
2493 self
._revertToRelativePosition
= false;
2494 el
.css({ position
: 'relative' });
2497 $(this).removeData("resizable-alsoresize-start");
2501 $.ui
.plugin
.add("resizable", "animate", {
2503 stop: function(event
, ui
) {
2504 var self
= $(this).data("resizable"), o
= self
.options
;
2506 var pr
= self
._proportionallyResizeElements
, ista
= pr
.length
&& (/textarea/i).test(pr
[0].nodeName
),
2507 soffseth
= ista
&& $.ui
.hasScroll(pr
[0], 'left') /* TODO - jump height */ ? 0 : self
.sizeDiff
.height
,
2508 soffsetw
= ista
? 0 : self
.sizeDiff
.width
;
2510 var style
= { width
: (self
.size
.width
- soffsetw
), height
: (self
.size
.height
- soffseth
) },
2511 left
= (parseInt(self
.element
.css('left'), 10) + (self
.position
.left
- self
.originalPosition
.left
)) || null,
2512 top
= (parseInt(self
.element
.css('top'), 10) + (self
.position
.top
- self
.originalPosition
.top
)) || null;
2514 self
.element
.animate(
2515 $.extend(style
, top
&& left
? { top
: top
, left
: left
} : {}), {
2516 duration
: o
.animateDuration
,
2517 easing
: o
.animateEasing
,
2521 width
: parseInt(self
.element
.css('width'), 10),
2522 height
: parseInt(self
.element
.css('height'), 10),
2523 top
: parseInt(self
.element
.css('top'), 10),
2524 left
: parseInt(self
.element
.css('left'), 10)
2527 if (pr
&& pr
.length
) $(pr
[0]).css({ width
: data
.width
, height
: data
.height
});
2529 // propagating resize, and updating values for each animation step
2530 self
._updateCache(data
);
2531 self
._propagate("resize", event
);
2540 $.ui
.plugin
.add("resizable", "containment", {
2542 start: function(event
, ui
) {
2543 var self
= $(this).data("resizable"), o
= self
.options
, el
= self
.element
;
2544 var oc
= o
.containment
, ce
= (oc
instanceof $) ? oc
.get(0) : (/parent/.test(oc
)) ? el
.parent().get(0) : oc
;
2547 self
.containerElement
= $(ce
);
2549 if (/document/.test(oc
) || oc
== document
) {
2550 self
.containerOffset
= { left
: 0, top
: 0 };
2551 self
.containerPosition
= { left
: 0, top
: 0 };
2554 element
: $(document
), left
: 0, top
: 0,
2555 width
: $(document
).width(), height
: $(document
).height() || document
.body
.parentNode
.scrollHeight
2559 // i'm a node, so compute top, left, right, bottom
2561 var element
= $(ce
), p
= [];
2562 $([ "Top", "Right", "Left", "Bottom" ]).each(function(i
, name
) { p
[i
] = num(element
.css("padding" + name
)); });
2564 self
.containerOffset
= element
.offset();
2565 self
.containerPosition
= element
.position();
2566 self
.containerSize
= { height
: (element
.innerHeight() - p
[3]), width
: (element
.innerWidth() - p
[1]) };
2568 var co
= self
.containerOffset
, ch
= self
.containerSize
.height
, cw
= self
.containerSize
.width
,
2569 width
= ($.ui
.hasScroll(ce
, "left") ? ce
.scrollWidth
: cw
), height
= ($.ui
.hasScroll(ce
) ? ce
.scrollHeight
: ch
);
2572 element
: ce
, left
: co
.left
, top
: co
.top
, width
: width
, height
: height
2577 resize: function(event
, ui
) {
2578 var self
= $(this).data("resizable"), o
= self
.options
,
2579 ps
= self
.containerSize
, co
= self
.containerOffset
, cs
= self
.size
, cp
= self
.position
,
2580 pRatio
= self
._aspectRatio
|| event
.shiftKey
, cop
= { top
:0, left
:0 }, ce
= self
.containerElement
;
2582 if (ce
[0] != document
&& (/static/).test(ce
.css('position'))) cop
= co
;
2584 if (cp
.left
< (self
._helper
? co
.left
: 0)) {
2585 self
.size
.width
= self
.size
.width
+ (self
._helper
? (self
.position
.left
- co
.left
) : (self
.position
.left
- cop
.left
));
2586 if (pRatio
) self
.size
.height
= self
.size
.width
/ o
.aspectRatio
;
2587 self
.position
.left
= o
.helper
? co
.left
: 0;
2590 if (cp
.top
< (self
._helper
? co
.top
: 0)) {
2591 self
.size
.height
= self
.size
.height
+ (self
._helper
? (self
.position
.top
- co
.top
) : self
.position
.top
);
2592 if (pRatio
) self
.size
.width
= self
.size
.height
* o
.aspectRatio
;
2593 self
.position
.top
= self
._helper
? co
.top
: 0;
2596 self
.offset
.left
= self
.parentData
.left
+self
.position
.left
;
2597 self
.offset
.top
= self
.parentData
.top
+self
.position
.top
;
2599 var woset
= Math
.abs( (self
._helper
? self
.offset
.left
- cop
.left
: (self
.offset
.left
- cop
.left
)) + self
.sizeDiff
.width
),
2600 hoset
= Math
.abs( (self
._helper
? self
.offset
.top
- cop
.top
: (self
.offset
.top
- co
.top
)) + self
.sizeDiff
.height
);
2602 var isParent
= self
.containerElement
.get(0) == self
.element
.parent().get(0),
2603 isOffsetRelative
= /relative|absolute/.test(self
.containerElement
.css('position'));
2605 if(isParent
&& isOffsetRelative
) woset
-= self
.parentData
.left
;
2607 if (woset
+ self
.size
.width
>= self
.parentData
.width
) {
2608 self
.size
.width
= self
.parentData
.width
- woset
;
2609 if (pRatio
) self
.size
.height
= self
.size
.width
/ self
.aspectRatio
;
2612 if (hoset
+ self
.size
.height
>= self
.parentData
.height
) {
2613 self
.size
.height
= self
.parentData
.height
- hoset
;
2614 if (pRatio
) self
.size
.width
= self
.size
.height
* self
.aspectRatio
;
2618 stop: function(event
, ui
){
2619 var self
= $(this).data("resizable"), o
= self
.options
, cp
= self
.position
,
2620 co
= self
.containerOffset
, cop
= self
.containerPosition
, ce
= self
.containerElement
;
2622 var helper
= $(self
.helper
), ho
= helper
.offset(), w
= helper
.outerWidth() - self
.sizeDiff
.width
, h
= helper
.outerHeight() - self
.sizeDiff
.height
;
2624 if (self
._helper
&& !o
.animate
&& (/relative/).test(ce
.css('position')))
2625 $(this).css({ left
: ho
.left
- cop
.left
- co
.left
, width
: w
, height
: h
});
2627 if (self
._helper
&& !o
.animate
&& (/static/).test(ce
.css('position')))
2628 $(this).css({ left
: ho
.left
- cop
.left
- co
.left
, width
: w
, height
: h
});
2633 $.ui
.plugin
.add("resizable", "ghost", {
2635 start: function(event
, ui
) {
2637 var self
= $(this).data("resizable"), o
= self
.options
, cs
= self
.size
;
2639 self
.ghost
= self
.originalElement
.clone();
2641 .css({ opacity
: .25, display
: 'block', position
: 'relative', height
: cs
.height
, width
: cs
.width
, margin
: 0, left
: 0, top
: 0 })
2642 .addClass('ui-resizable-ghost')
2643 .addClass(typeof o
.ghost
== 'string' ? o
.ghost
: '');
2645 self
.ghost
.appendTo(self
.helper
);
2649 resize: function(event
, ui
){
2650 var self
= $(this).data("resizable"), o
= self
.options
;
2651 if (self
.ghost
) self
.ghost
.css({ position
: 'relative', height
: self
.size
.height
, width
: self
.size
.width
});
2654 stop: function(event
, ui
){
2655 var self
= $(this).data("resizable"), o
= self
.options
;
2656 if (self
.ghost
&& self
.helper
) self
.helper
.get(0).removeChild(self
.ghost
.get(0));
2661 $.ui
.plugin
.add("resizable", "grid", {
2663 resize: function(event
, ui
) {
2664 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
;
2665 o
.grid
= typeof o
.grid
== "number" ? [o
.grid
, o
.grid
] : o
.grid
;
2666 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);
2668 if (/^(se|s|e)$/.test(a
)) {
2669 self
.size
.width
= os
.width
+ ox
;
2670 self
.size
.height
= os
.height
+ oy
;
2672 else if (/^(ne)$/.test(a
)) {
2673 self
.size
.width
= os
.width
+ ox
;
2674 self
.size
.height
= os
.height
+ oy
;
2675 self
.position
.top
= op
.top
- oy
;
2677 else if (/^(sw)$/.test(a
)) {
2678 self
.size
.width
= os
.width
+ ox
;
2679 self
.size
.height
= os
.height
+ oy
;
2680 self
.position
.left
= op
.left
- ox
;
2683 self
.size
.width
= os
.width
+ ox
;
2684 self
.size
.height
= os
.height
+ oy
;
2685 self
.position
.top
= op
.top
- oy
;
2686 self
.position
.left
= op
.left
- ox
;
2692 var num = function(v
) {
2693 return parseInt(v
, 10) || 0;
2696 var isNumber = function(value
) {
2697 return !isNaN(parseInt(value
, 10));
2702 * jQuery UI Selectable 1.8
2704 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
2705 * Dual licensed under the MIT (MIT-LICENSE.txt)
2706 * and GPL (GPL-LICENSE.txt) licenses.
2708 * http://docs.jquery.com/UI/Selectables
2712 * jquery.ui.mouse.js
2713 * jquery.ui.widget.js
2717 $.widget("ui.selectable", $.ui
.mouse
, {
2725 _create: function() {
2728 this.element
.addClass("ui-selectable");
2730 this.dragged
= false;
2732 // cache selectee children based on filter
2734 this.refresh = function() {
2735 selectees
= $(self
.options
.filter
, self
.element
[0]);
2736 selectees
.each(function() {
2737 var $this = $(this);
2738 var pos
= $this.offset();
2739 $.data(this, "selectable-item", {
2744 right
: pos
.left
+ $this.outerWidth(),
2745 bottom
: pos
.top
+ $this.outerHeight(),
2746 startselected
: false,
2747 selected
: $this.hasClass('ui-selected'),
2748 selecting
: $this.hasClass('ui-selecting'),
2749 unselecting
: $this.hasClass('ui-unselecting')
2755 this.selectees
= selectees
.addClass("ui-selectee");
2759 this.helper
= $(document
.createElement('div'))
2760 .css({border
:'1px dotted black'})
2761 .addClass("ui-selectable-helper");
2764 destroy: function() {
2766 .removeClass("ui-selectee")
2767 .removeData("selectable-item");
2769 .removeClass("ui-selectable ui-selectable-disabled")
2770 .removeData("selectable")
2771 .unbind(".selectable");
2772 this._mouseDestroy();
2777 _mouseStart: function(event
) {
2780 this.opos
= [event
.pageX
, event
.pageY
];
2782 if (this.options
.disabled
)
2785 var options
= this.options
;
2787 this.selectees
= $(options
.filter
, this.element
[0]);
2789 this._trigger("start", event
);
2791 $(options
.appendTo
).append(this.helper
);
2792 // position helper (lasso)
2795 "position": "absolute",
2796 "left": event
.clientX
,
2797 "top": event
.clientY
,
2802 if (options
.autoRefresh
) {
2806 this.selectees
.filter('.ui-selected').each(function() {
2807 var selectee
= $.data(this, "selectable-item");
2808 selectee
.startselected
= true;
2809 if (!event
.metaKey
) {
2810 selectee
.$element
.removeClass('ui-selected');
2811 selectee
.selected
= false;
2812 selectee
.$element
.addClass('ui-unselecting');
2813 selectee
.unselecting
= true;
2814 // selectable UNSELECTING callback
2815 self
._trigger("unselecting", event
, {
2816 unselecting
: selectee
.element
2821 $(event
.target
).parents().andSelf().each(function() {
2822 var selectee
= $.data(this, "selectable-item");
2824 selectee
.$element
.removeClass("ui-unselecting").addClass('ui-selecting');
2825 selectee
.unselecting
= false;
2826 selectee
.selecting
= true;
2827 selectee
.selected
= true;
2828 // selectable SELECTING callback
2829 self
._trigger("selecting", event
, {
2830 selecting
: selectee
.element
2838 _mouseDrag: function(event
) {
2840 this.dragged
= true;
2842 if (this.options
.disabled
)
2845 var options
= this.options
;
2847 var x1
= this.opos
[0], y1
= this.opos
[1], x2
= event
.pageX
, y2
= event
.pageY
;
2848 if (x1
> x2
) { var tmp
= x2
; x2
= x1
; x1
= tmp
; }
2849 if (y1
> y2
) { var tmp
= y2
; y2
= y1
; y1
= tmp
; }
2850 this.helper
.css({left
: x1
, top
: y1
, width
: x2
-x1
, height
: y2
-y1
});
2852 this.selectees
.each(function() {
2853 var selectee
= $.data(this, "selectable-item");
2854 //prevent helper from being selected if appendTo: selectable
2855 if (!selectee
|| selectee
.element
== self
.element
[0])
2858 if (options
.tolerance
== 'touch') {
2859 hit
= ( !(selectee
.left
> x2
|| selectee
.right
< x1
|| selectee
.top
> y2
|| selectee
.bottom
< y1
) );
2860 } else if (options
.tolerance
== 'fit') {
2861 hit
= (selectee
.left
> x1
&& selectee
.right
< x2
&& selectee
.top
> y1
&& selectee
.bottom
< y2
);
2866 if (selectee
.selected
) {
2867 selectee
.$element
.removeClass('ui-selected');
2868 selectee
.selected
= false;
2870 if (selectee
.unselecting
) {
2871 selectee
.$element
.removeClass('ui-unselecting');
2872 selectee
.unselecting
= false;
2874 if (!selectee
.selecting
) {
2875 selectee
.$element
.addClass('ui-selecting');
2876 selectee
.selecting
= true;
2877 // selectable SELECTING callback
2878 self
._trigger("selecting", event
, {
2879 selecting
: selectee
.element
2884 if (selectee
.selecting
) {
2885 if (event
.metaKey
&& selectee
.startselected
) {
2886 selectee
.$element
.removeClass('ui-selecting');
2887 selectee
.selecting
= false;
2888 selectee
.$element
.addClass('ui-selected');
2889 selectee
.selected
= true;
2891 selectee
.$element
.removeClass('ui-selecting');
2892 selectee
.selecting
= false;
2893 if (selectee
.startselected
) {
2894 selectee
.$element
.addClass('ui-unselecting');
2895 selectee
.unselecting
= true;
2897 // selectable UNSELECTING callback
2898 self
._trigger("unselecting", event
, {
2899 unselecting
: selectee
.element
2903 if (selectee
.selected
) {
2904 if (!event
.metaKey
&& !selectee
.startselected
) {
2905 selectee
.$element
.removeClass('ui-selected');
2906 selectee
.selected
= false;
2908 selectee
.$element
.addClass('ui-unselecting');
2909 selectee
.unselecting
= true;
2910 // selectable UNSELECTING callback
2911 self
._trigger("unselecting", event
, {
2912 unselecting
: selectee
.element
2922 _mouseStop: function(event
) {
2925 this.dragged
= false;
2927 var options
= this.options
;
2929 $('.ui-unselecting', this.element
[0]).each(function() {
2930 var selectee
= $.data(this, "selectable-item");
2931 selectee
.$element
.removeClass('ui-unselecting');
2932 selectee
.unselecting
= false;
2933 selectee
.startselected
= false;
2934 self
._trigger("unselected", event
, {
2935 unselected
: selectee
.element
2938 $('.ui-selecting', this.element
[0]).each(function() {
2939 var selectee
= $.data(this, "selectable-item");
2940 selectee
.$element
.removeClass('ui-selecting').addClass('ui-selected');
2941 selectee
.selecting
= false;
2942 selectee
.selected
= true;
2943 selectee
.startselected
= true;
2944 self
._trigger("selected", event
, {
2945 selected
: selectee
.element
2948 this._trigger("stop", event
);
2950 this.helper
.remove();
2957 $.extend($.ui
.selectable
, {
2963 * jQuery UI Sortable 1.8
2965 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
2966 * Dual licensed under the MIT (MIT-LICENSE.txt)
2967 * and GPL (GPL-LICENSE.txt) licenses.
2969 * http://docs.jquery.com/UI/Sortables
2973 * jquery.ui.mouse.js
2974 * jquery.ui.widget.js
2978 $.widget("ui.sortable", $.ui
.mouse
, {
2979 widgetEventPrefix
: "sort",
2988 forcePlaceholderSize
: false,
2989 forceHelperSize
: false,
2998 scrollSensitivity
: 20,
3001 tolerance
: "intersect",
3004 _create: function() {
3006 var o
= this.options
;
3007 this.containerCache
= {};
3008 this.element
.addClass("ui-sortable");
3013 //Let's determine if the items are floating
3014 this.floating
= this.items
.length
? (/left|right/).test(this.items
[0].item
.css('float')) : false;
3016 //Let's determine the parent's offset
3017 this.offset
= this.element
.offset();
3019 //Initialize mouse events for interaction
3024 destroy: function() {
3026 .removeClass("ui-sortable ui-sortable-disabled")
3027 .removeData("sortable")
3028 .unbind(".sortable");
3029 this._mouseDestroy();
3031 for ( var i
= this.items
.length
- 1; i
>= 0; i
-- )
3032 this.items
[i
].item
.removeData("sortable-item");
3037 _mouseCapture: function(event
, overrideHandle
) {
3039 if (this.reverting
) {
3043 if(this.options
.disabled
|| this.options
.type
== 'static') return false;
3045 //We have to refresh the items data once first
3046 this._refreshItems(event
);
3048 //Find out if the clicked node (or one of its parents) is a actual item in this.items
3049 var currentItem
= null, self
= this, nodes
= $(event
.target
).parents().each(function() {
3050 if($.data(this, 'sortable-item') == self
) {
3051 currentItem
= $(this);
3055 if($.data(event
.target
, 'sortable-item') == self
) currentItem
= $(event
.target
);
3057 if(!currentItem
) return false;
3058 if(this.options
.handle
&& !overrideHandle
) {
3059 var validHandle
= false;
3061 $(this.options
.handle
, currentItem
).find("*").andSelf().each(function() { if(this == event
.target
) validHandle
= true; });
3062 if(!validHandle
) return false;
3065 this.currentItem
= currentItem
;
3066 this._removeCurrentsFromItems();
3071 _mouseStart: function(event
, overrideHandle
, noActivation
) {
3073 var o
= this.options
, self
= this;
3074 this.currentContainer
= this;
3076 //We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture
3077 this.refreshPositions();
3079 //Create and append the visible helper
3080 this.helper
= this._createHelper(event
);
3082 //Cache the helper size
3083 this._cacheHelperProportions();
3086 * - Position generation -
3087 * This block generates everything position related - it's the core of draggables.
3090 //Cache the margins of the original element
3091 this._cacheMargins();
3093 //Get the next scrolling parent
3094 this.scrollParent
= this.helper
.scrollParent();
3096 //The element's absolute position on the page minus margins
3097 this.offset
= this.currentItem
.offset();
3099 top
: this.offset
.top
- this.margins
.top
,
3100 left
: this.offset
.left
- this.margins
.left
3103 // Only after we got the offset, we can change the helper's position to absolute
3104 // TODO: Still need to figure out a way to make relative sorting possible
3105 this.helper
.css("position", "absolute");
3106 this.cssPosition
= this.helper
.css("position");
3108 $.extend(this.offset
, {
3109 click
: { //Where the click happened, relative to the element
3110 left
: event
.pageX
- this.offset
.left
,
3111 top
: event
.pageY
- this.offset
.top
3113 parent
: this._getParentOffset(),
3114 relative
: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
3117 //Generate the original position
3118 this.originalPosition
= this._generatePosition(event
);
3119 this.originalPageX
= event
.pageX
;
3120 this.originalPageY
= event
.pageY
;
3122 //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
3123 (o
.cursorAt
&& this._adjustOffsetFromHelper(o
.cursorAt
));
3125 //Cache the former DOM position
3126 this.domPosition
= { prev
: this.currentItem
.prev()[0], parent
: this.currentItem
.parent()[0] };
3128 //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
3129 if(this.helper
[0] != this.currentItem
[0]) {
3130 this.currentItem
.hide();
3133 //Create the placeholder
3134 this._createPlaceholder();
3136 //Set a containment if given in the options
3138 this._setContainment();
3140 if(o
.cursor
) { // cursor option
3141 if ($('body').css("cursor")) this._storedCursor
= $('body').css("cursor");
3142 $('body').css("cursor", o
.cursor
);
3145 if(o
.opacity
) { // opacity option
3146 if (this.helper
.css("opacity")) this._storedOpacity
= this.helper
.css("opacity");
3147 this.helper
.css("opacity", o
.opacity
);
3150 if(o
.zIndex
) { // zIndex option
3151 if (this.helper
.css("zIndex")) this._storedZIndex
= this.helper
.css("zIndex");
3152 this.helper
.css("zIndex", o
.zIndex
);
3156 if(this.scrollParent
[0] != document
&& this.scrollParent
[0].tagName
!= 'HTML')
3157 this.overflowOffset
= this.scrollParent
.offset();
3160 this._trigger("start", event
, this._uiHash());
3162 //Recache the helper size
3163 if(!this._preserveHelperProportions
)
3164 this._cacheHelperProportions();
3167 //Post 'activate' events to possible containers
3169 for (var i
= this.containers
.length
- 1; i
>= 0; i
--) { this.containers
[i
]._trigger("activate", event
, self
._uiHash(this)); }
3172 //Prepare possible droppables
3174 $.ui
.ddmanager
.current
= this;
3176 if ($.ui
.ddmanager
&& !o
.dropBehaviour
)
3177 $.ui
.ddmanager
.prepareOffsets(this, event
);
3179 this.dragging
= true;
3181 this.helper
.addClass("ui-sortable-helper");
3182 this._mouseDrag(event
); //Execute the drag once - this causes the helper not to be visible before getting its correct position
3187 _mouseDrag: function(event
) {
3189 //Compute the helpers position
3190 this.position
= this._generatePosition(event
);
3191 this.positionAbs
= this._convertPositionTo("absolute");
3193 if (!this.lastPositionAbs
) {
3194 this.lastPositionAbs
= this.positionAbs
;
3198 if(this.options
.scroll
) {
3199 var o
= this.options
, scrolled
= false;
3200 if(this.scrollParent
[0] != document
&& this.scrollParent
[0].tagName
!= 'HTML') {
3202 if((this.overflowOffset
.top
+ this.scrollParent
[0].offsetHeight
) - event
.pageY
< o
.scrollSensitivity
)
3203 this.scrollParent
[0].scrollTop
= scrolled
= this.scrollParent
[0].scrollTop
+ o
.scrollSpeed
;
3204 else if(event
.pageY
- this.overflowOffset
.top
< o
.scrollSensitivity
)
3205 this.scrollParent
[0].scrollTop
= scrolled
= this.scrollParent
[0].scrollTop
- o
.scrollSpeed
;
3207 if((this.overflowOffset
.left
+ this.scrollParent
[0].offsetWidth
) - event
.pageX
< o
.scrollSensitivity
)
3208 this.scrollParent
[0].scrollLeft
= scrolled
= this.scrollParent
[0].scrollLeft
+ o
.scrollSpeed
;
3209 else if(event
.pageX
- this.overflowOffset
.left
< o
.scrollSensitivity
)
3210 this.scrollParent
[0].scrollLeft
= scrolled
= this.scrollParent
[0].scrollLeft
- o
.scrollSpeed
;
3214 if(event
.pageY
- $(document
).scrollTop() < o
.scrollSensitivity
)
3215 scrolled
= $(document
).scrollTop($(document
).scrollTop() - o
.scrollSpeed
);
3216 else if($(window
).height() - (event
.pageY
- $(document
).scrollTop()) < o
.scrollSensitivity
)
3217 scrolled
= $(document
).scrollTop($(document
).scrollTop() + o
.scrollSpeed
);
3219 if(event
.pageX
- $(document
).scrollLeft() < o
.scrollSensitivity
)
3220 scrolled
= $(document
).scrollLeft($(document
).scrollLeft() - o
.scrollSpeed
);
3221 else if($(window
).width() - (event
.pageX
- $(document
).scrollLeft()) < o
.scrollSensitivity
)
3222 scrolled
= $(document
).scrollLeft($(document
).scrollLeft() + o
.scrollSpeed
);
3226 if(scrolled
!== false && $.ui
.ddmanager
&& !o
.dropBehaviour
)
3227 $.ui
.ddmanager
.prepareOffsets(this, event
);
3230 //Regenerate the absolute position used for position checks
3231 this.positionAbs
= this._convertPositionTo("absolute");
3233 //Set the helper position
3234 if(!this.options
.axis
|| this.options
.axis
!= "y") this.helper
[0].style
.left
= this.position
.left
+'px';
3235 if(!this.options
.axis
|| this.options
.axis
!= "x") this.helper
[0].style
.top
= this.position
.top
+'px';
3238 for (var i
= this.items
.length
- 1; i
>= 0; i
--) {
3240 //Cache variables and intersection, continue if no intersection
3241 var item
= this.items
[i
], itemElement
= item
.item
[0], intersection
= this._intersectsWithPointer(item
);
3242 if (!intersection
) continue;
3244 if(itemElement
!= this.currentItem
[0] //cannot intersect with itself
3245 && this.placeholder
[intersection
== 1 ? "next" : "prev"]()[0] != itemElement
//no useless actions that have been done before
3246 && !$.ui
.contains(this.placeholder
[0], itemElement
) //no action if the item moved is the parent of the item checked
3247 && (this.options
.type
== 'semi-dynamic' ? !$.ui
.contains(this.element
[0], itemElement
) : true)
3248 //&& itemElement.parentNode == this.placeholder[0].parentNode // only rearrange items within the same container
3251 this.direction
= intersection
== 1 ? "down" : "up";
3253 if (this.options
.tolerance
== "pointer" || this._intersectsWithSides(item
)) {
3254 this._rearrange(event
, item
);
3259 this._trigger("change", event
, this._uiHash());
3264 //Post events to containers
3265 this._contactContainers(event
);
3267 //Interconnect with droppables
3268 if($.ui
.ddmanager
) $.ui
.ddmanager
.drag(this, event
);
3271 this._trigger('sort', event
, this._uiHash());
3273 this.lastPositionAbs
= this.positionAbs
;
3278 _mouseStop: function(event
, noPropagation
) {
3282 //If we are using droppables, inform the manager about the drop
3283 if ($.ui
.ddmanager
&& !this.options
.dropBehaviour
)
3284 $.ui
.ddmanager
.drop(this, event
);
3286 if(this.options
.revert
) {
3288 var cur
= self
.placeholder
.offset();
3290 self
.reverting
= true;
3292 $(this.helper
).animate({
3293 left
: cur
.left
- this.offset
.parent
.left
- self
.margins
.left
+ (this.offsetParent
[0] == document
.body
? 0 : this.offsetParent
[0].scrollLeft
),
3294 top
: cur
.top
- this.offset
.parent
.top
- self
.margins
.top
+ (this.offsetParent
[0] == document
.body
? 0 : this.offsetParent
[0].scrollTop
)
3295 }, parseInt(this.options
.revert
, 10) || 500, function() {
3299 this._clear(event
, noPropagation
);
3306 cancel: function() {
3314 if(this.options
.helper
== "original")
3315 this.currentItem
.css(this._storedCSS
).removeClass("ui-sortable-helper");
3317 this.currentItem
.show();
3319 //Post deactivating events to containers
3320 for (var i
= this.containers
.length
- 1; i
>= 0; i
--){
3321 this.containers
[i
]._trigger("deactivate", null, self
._uiHash(this));
3322 if(this.containers
[i
].containerCache
.over
) {
3323 this.containers
[i
]._trigger("out", null, self
._uiHash(this));
3324 this.containers
[i
].containerCache
.over
= 0;
3330 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
3331 if(this.placeholder
[0].parentNode
) this.placeholder
[0].parentNode
.removeChild(this.placeholder
[0]);
3332 if(this.options
.helper
!= "original" && this.helper
&& this.helper
[0].parentNode
) this.helper
.remove();
3341 if(this.domPosition
.prev
) {
3342 $(this.domPosition
.prev
).after(this.currentItem
);
3344 $(this.domPosition
.parent
).prepend(this.currentItem
);
3351 serialize: function(o
) {
3353 var items
= this._getItemsAsjQuery(o
&& o
.connected
);
3354 var str
= []; o
= o
|| {};
3356 $(items
).each(function() {
3357 var res
= ($(o
.item
|| this).attr(o
.attribute
|| 'id') || '').match(o
.expression
|| (/(.+)[-=_](.+)/));
3358 if(res
) str
.push((o
.key
|| res
[1]+'[]')+'='+(o
.key
&& o
.expression
? res
[1] : res
[2]));
3361 return str
.join('&');
3365 toArray: function(o
) {
3367 var items
= this._getItemsAsjQuery(o
&& o
.connected
);
3368 var ret
= []; o
= o
|| {};
3370 items
.each(function() { ret
.push($(o
.item
|| this).attr(o
.attribute
|| 'id') || ''); });
3375 /* Be careful with the following core functions */
3376 _intersectsWith: function(item
) {
3378 var x1
= this.positionAbs
.left
,
3379 x2
= x1
+ this.helperProportions
.width
,
3380 y1
= this.positionAbs
.top
,
3381 y2
= y1
+ this.helperProportions
.height
;
3386 b
= t
+ item
.height
;
3388 var dyClick
= this.offset
.click
.top
,
3389 dxClick
= this.offset
.click
.left
;
3391 var isOverElement
= (y1
+ dyClick
) > t
&& (y1
+ dyClick
) < b
&& (x1
+ dxClick
) > l
&& (x1
+ dxClick
) < r
;
3393 if( this.options
.tolerance
== "pointer"
3394 || this.options
.forcePointerForContainers
3395 || (this.options
.tolerance
!= "pointer" && this.helperProportions
[this.floating
? 'width' : 'height'] > item
[this.floating
? 'width' : 'height'])
3397 return isOverElement
;
3400 return (l
< x1
+ (this.helperProportions
.width
/ 2) // Right Half
3401 && x2
- (this.helperProportions
.width
/ 2) < r
// Left Half
3402 && t
< y1
+ (this.helperProportions
.height
/ 2) // Bottom Half
3403 && y2
- (this.helperProportions
.height
/ 2) < b
); // Top Half
3408 _intersectsWithPointer: function(item
) {
3410 var isOverElementHeight
= $.ui
.isOverAxis(this.positionAbs
.top
+ this.offset
.click
.top
, item
.top
, item
.height
),
3411 isOverElementWidth
= $.ui
.isOverAxis(this.positionAbs
.left
+ this.offset
.click
.left
, item
.left
, item
.width
),
3412 isOverElement
= isOverElementHeight
&& isOverElementWidth
,
3413 verticalDirection
= this._getDragVerticalDirection(),
3414 horizontalDirection
= this._getDragHorizontalDirection();
3419 return this.floating
?
3420 ( ((horizontalDirection
&& horizontalDirection
== "right") || verticalDirection
== "down") ? 2 : 1 )
3421 : ( verticalDirection
&& (verticalDirection
== "down" ? 2 : 1) );
3425 _intersectsWithSides: function(item
) {
3427 var isOverBottomHalf
= $.ui
.isOverAxis(this.positionAbs
.top
+ this.offset
.click
.top
, item
.top
+ (item
.height
/2), item
.height
),
3428 isOverRightHalf
= $.ui
.isOverAxis(this.positionAbs
.left
+ this.offset
.click
.left
, item
.left
+ (item
.width
/2), item
.width
),
3429 verticalDirection
= this._getDragVerticalDirection(),
3430 horizontalDirection
= this._getDragHorizontalDirection();
3432 if (this.floating
&& horizontalDirection
) {
3433 return ((horizontalDirection
== "right" && isOverRightHalf
) || (horizontalDirection
== "left" && !isOverRightHalf
));
3435 return verticalDirection
&& ((verticalDirection
== "down" && isOverBottomHalf
) || (verticalDirection
== "up" && !isOverBottomHalf
));
3440 _getDragVerticalDirection: function() {
3441 var delta
= this.positionAbs
.top
- this.lastPositionAbs
.top
;
3442 return delta
!= 0 && (delta
> 0 ? "down" : "up");
3445 _getDragHorizontalDirection: function() {
3446 var delta
= this.positionAbs
.left
- this.lastPositionAbs
.left
;
3447 return delta
!= 0 && (delta
> 0 ? "right" : "left");
3450 refresh: function(event
) {
3451 this._refreshItems(event
);
3452 this.refreshPositions();
3456 _connectWith: function() {
3457 var options
= this.options
;
3458 return options
.connectWith
.constructor == String
3459 ? [options
.connectWith
]
3460 : options
.connectWith
;
3463 _getItemsAsjQuery: function(connected
) {
3468 var connectWith
= this._connectWith();
3470 if(connectWith
&& connected
) {
3471 for (var i
= connectWith
.length
- 1; i
>= 0; i
--){
3472 var cur
= $(connectWith
[i
]);
3473 for (var j
= cur
.length
- 1; j
>= 0; j
--){
3474 var inst
= $.data(cur
[j
], 'sortable');
3475 if(inst
&& inst
!= this && !inst
.options
.disabled
) {
3476 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
]);
3482 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]);
3484 for (var i
= queries
.length
- 1; i
>= 0; i
--){
3485 queries
[i
][0].each(function() {
3494 _removeCurrentsFromItems: function() {
3496 var list
= this.currentItem
.find(":data(sortable-item)");
3498 for (var i
=0; i
< this.items
.length
; i
++) {
3500 for (var j
=0; j
< list
.length
; j
++) {
3501 if(list
[j
] == this.items
[i
].item
[0])
3502 this.items
.splice(i
,1);
3509 _refreshItems: function(event
) {
3512 this.containers
= [this];
3513 var items
= this.items
;
3515 var queries
= [[$.isFunction(this.options
.items
) ? this.options
.items
.call(this.element
[0], event
, { item
: this.currentItem
}) : $(this.options
.items
, this.element
), this]];
3516 var connectWith
= this._connectWith();
3519 for (var i
= connectWith
.length
- 1; i
>= 0; i
--){
3520 var cur
= $(connectWith
[i
]);
3521 for (var j
= cur
.length
- 1; j
>= 0; j
--){
3522 var inst
= $.data(cur
[j
], 'sortable');
3523 if(inst
&& inst
!= this && !inst
.options
.disabled
) {
3524 queries
.push([$.isFunction(inst
.options
.items
) ? inst
.options
.items
.call(inst
.element
[0], event
, { item
: this.currentItem
}) : $(inst
.options
.items
, inst
.element
), inst
]);
3525 this.containers
.push(inst
);
3531 for (var i
= queries
.length
- 1; i
>= 0; i
--) {
3532 var targetData
= queries
[i
][1];
3533 var _queries
= queries
[i
][0];
3535 for (var j
=0, queriesLength
= _queries
.length
; j
< queriesLength
; j
++) {
3536 var item
= $(_queries
[j
]);
3538 item
.data('sortable-item', targetData
); // Data for target checking (mouse manager)
3542 instance
: targetData
,
3543 width
: 0, height
: 0,
3551 refreshPositions: function(fast
) {
3553 //This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change
3554 if(this.offsetParent
&& this.helper
) {
3555 this.offset
.parent
= this._getParentOffset();
3558 for (var i
= this.items
.length
- 1; i
>= 0; i
--){
3559 var item
= this.items
[i
];
3561 var t
= this.options
.toleranceElement
? $(this.options
.toleranceElement
, item
.item
) : item
.item
;
3564 item
.width
= t
.outerWidth();
3565 item
.height
= t
.outerHeight();
3573 if(this.options
.custom
&& this.options
.custom
.refreshContainers
) {
3574 this.options
.custom
.refreshContainers
.call(this);
3576 for (var i
= this.containers
.length
- 1; i
>= 0; i
--){
3577 var p
= this.containers
[i
].element
.offset();
3578 this.containers
[i
].containerCache
.left
= p
.left
;
3579 this.containers
[i
].containerCache
.top
= p
.top
;
3580 this.containers
[i
].containerCache
.width
= this.containers
[i
].element
.outerWidth();
3581 this.containers
[i
].containerCache
.height
= this.containers
[i
].element
.outerHeight();
3588 _createPlaceholder: function(that
) {
3590 var self
= that
|| this, o
= self
.options
;
3592 if(!o
.placeholder
|| o
.placeholder
.constructor == String
) {
3593 var className
= o
.placeholder
;
3595 element: function() {
3597 var el
= $(document
.createElement(self
.currentItem
[0].nodeName
))
3598 .addClass(className
|| self
.currentItem
[0].className
+" ui-sortable-placeholder")
3599 .removeClass("ui-sortable-helper")[0];
3602 el
.style
.visibility
= "hidden";
3606 update: function(container
, p
) {
3608 // 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that
3609 // 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified
3610 if(className
&& !o
.forcePlaceholderSize
) return;
3612 //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
3613 if(!p
.height()) { p
.height(self
.currentItem
.innerHeight() - parseInt(self
.currentItem
.css('paddingTop')||0, 10) - parseInt(self
.currentItem
.css('paddingBottom')||0, 10)); };
3614 if(!p
.width()) { p
.width(self
.currentItem
.innerWidth() - parseInt(self
.currentItem
.css('paddingLeft')||0, 10) - parseInt(self
.currentItem
.css('paddingRight')||0, 10)); };
3619 //Create the placeholder
3620 self
.placeholder
= $(o
.placeholder
.element
.call(self
.element
, self
.currentItem
));
3622 //Append it after the actual current item
3623 self
.currentItem
.after(self
.placeholder
);
3625 //Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
3626 o
.placeholder
.update(self
, self
.placeholder
);
3630 _contactContainers: function(event
) {
3632 // get innermost container that intersects with item
3633 var innermostContainer
= null, innermostIndex
= null;
3636 for (var i
= this.containers
.length
- 1; i
>= 0; i
--){
3638 // never consider a container that's located within the item itself
3639 if($.ui
.contains(this.currentItem
[0], this.containers
[i
].element
[0]))
3642 if(this._intersectsWith(this.containers
[i
].containerCache
)) {
3644 // if we've already found a container and it's more "inner" than this, then continue
3645 if(innermostContainer
&& $.ui
.contains(this.containers
[i
].element
[0], innermostContainer
.element
[0]))
3648 innermostContainer
= this.containers
[i
];
3652 // container doesn't intersect. trigger "out" event if necessary
3653 if(this.containers
[i
].containerCache
.over
) {
3654 this.containers
[i
]._trigger("out", event
, this._uiHash(this));
3655 this.containers
[i
].containerCache
.over
= 0;
3661 // if no intersecting containers found, return
3662 if(!innermostContainer
) return;
3664 // move the item into the container if it's not there already
3665 if(this.containers
.length
=== 1) {
3666 this.containers
[innermostIndex
]._trigger("over", event
, this._uiHash(this));
3667 this.containers
[innermostIndex
].containerCache
.over
= 1;
3668 } else if(this.currentContainer
!= this.containers
[innermostIndex
]) {
3670 //When entering a new container, we will find the item with the least distance and append our item near it
3671 var dist
= 10000; var itemWithLeastDistance
= null; var base
= this.positionAbs
[this.containers
[innermostIndex
].floating
? 'left' : 'top'];
3672 for (var j
= this.items
.length
- 1; j
>= 0; j
--) {
3673 if(!$.ui
.contains(this.containers
[innermostIndex
].element
[0], this.items
[j
].item
[0])) continue;
3674 var cur
= this.items
[j
][this.containers
[innermostIndex
].floating
? 'left' : 'top'];
3675 if(Math
.abs(cur
- base
) < dist
) {
3676 dist
= Math
.abs(cur
- base
); itemWithLeastDistance
= this.items
[j
];
3680 if(!itemWithLeastDistance
&& !this.options
.dropOnEmpty
) //Check if dropOnEmpty is enabled
3683 this.currentContainer
= this.containers
[innermostIndex
];
3684 itemWithLeastDistance
? this._rearrange(event
, itemWithLeastDistance
, null, true) : this._rearrange(event
, null, this.containers
[innermostIndex
].element
, true);
3685 this._trigger("change", event
, this._uiHash());
3686 this.containers
[innermostIndex
]._trigger("change", event
, this._uiHash(this));
3688 //Update the placeholder
3689 this.options
.placeholder
.update(this.currentContainer
, this.placeholder
);
3691 this.containers
[innermostIndex
]._trigger("over", event
, this._uiHash(this));
3692 this.containers
[innermostIndex
].containerCache
.over
= 1;
3698 _createHelper: function(event
) {
3700 var o
= this.options
;
3701 var helper
= $.isFunction(o
.helper
) ? $(o
.helper
.apply(this.element
[0], [event
, this.currentItem
])) : (o
.helper
== 'clone' ? this.currentItem
.clone() : this.currentItem
);
3703 if(!helper
.parents('body').length
) //Add the helper to the DOM if that didn't happen already
3704 $(o
.appendTo
!= 'parent' ? o
.appendTo
: this.currentItem
[0].parentNode
)[0].appendChild(helper
[0]);
3706 if(helper
[0] == this.currentItem
[0])
3707 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") };
3709 if(helper
[0].style
.width
== '' || o
.forceHelperSize
) helper
.width(this.currentItem
.width());
3710 if(helper
[0].style
.height
== '' || o
.forceHelperSize
) helper
.height(this.currentItem
.height());
3716 _adjustOffsetFromHelper: function(obj
) {
3717 if (typeof obj
== 'string') {
3718 obj
= obj
.split(' ');
3720 if ($.isArray(obj
)) {
3721 obj
= {left
: +obj
[0], top
: +obj
[1] || 0};
3723 if ('left' in obj
) {
3724 this.offset
.click
.left
= obj
.left
+ this.margins
.left
;
3726 if ('right' in obj
) {
3727 this.offset
.click
.left
= this.helperProportions
.width
- obj
.right
+ this.margins
.left
;
3730 this.offset
.click
.top
= obj
.top
+ this.margins
.top
;
3732 if ('bottom' in obj
) {
3733 this.offset
.click
.top
= this.helperProportions
.height
- obj
.bottom
+ this.margins
.top
;
3737 _getParentOffset: function() {
3740 //Get the offsetParent and cache its position
3741 this.offsetParent
= this.helper
.offsetParent();
3742 var po
= this.offsetParent
.offset();
3744 // This is a special case where we need to modify a offset calculated on start, since the following happened:
3745 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
3746 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
3747 // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
3748 if(this.cssPosition
== 'absolute' && this.scrollParent
[0] != document
&& $.ui
.contains(this.scrollParent
[0], this.offsetParent
[0])) {
3749 po
.left
+= this.scrollParent
.scrollLeft();
3750 po
.top
+= this.scrollParent
.scrollTop();
3753 if((this.offsetParent
[0] == document
.body
) //This needs to be actually done for all browsers, since pageX/pageY includes this information
3754 || (this.offsetParent
[0].tagName
&& this.offsetParent
[0].tagName
.toLowerCase() == 'html' && $.browser
.msie
)) //Ugly IE fix
3755 po
= { top
: 0, left
: 0 };
3758 top
: po
.top
+ (parseInt(this.offsetParent
.css("borderTopWidth"),10) || 0),
3759 left
: po
.left
+ (parseInt(this.offsetParent
.css("borderLeftWidth"),10) || 0)
3764 _getRelativeOffset: function() {
3766 if(this.cssPosition
== "relative") {
3767 var p
= this.currentItem
.position();
3769 top
: p
.top
- (parseInt(this.helper
.css("top"),10) || 0) + this.scrollParent
.scrollTop(),
3770 left
: p
.left
- (parseInt(this.helper
.css("left"),10) || 0) + this.scrollParent
.scrollLeft()
3773 return { top
: 0, left
: 0 };
3778 _cacheMargins: function() {
3780 left
: (parseInt(this.currentItem
.css("marginLeft"),10) || 0),
3781 top
: (parseInt(this.currentItem
.css("marginTop"),10) || 0)
3785 _cacheHelperProportions: function() {
3786 this.helperProportions
= {
3787 width
: this.helper
.outerWidth(),
3788 height
: this.helper
.outerHeight()
3792 _setContainment: function() {
3794 var o
= this.options
;
3795 if(o
.containment
== 'parent') o
.containment
= this.helper
[0].parentNode
;
3796 if(o
.containment
== 'document' || o
.containment
== 'window') this.containment
= [
3797 0 - this.offset
.relative
.left
- this.offset
.parent
.left
,
3798 0 - this.offset
.relative
.top
- this.offset
.parent
.top
,
3799 $(o
.containment
== 'document' ? document
: window
).width() - this.helperProportions
.width
- this.margins
.left
,
3800 ($(o
.containment
== 'document' ? document
: window
).height() || document
.body
.parentNode
.scrollHeight
) - this.helperProportions
.height
- this.margins
.top
3803 if(!(/^(document|window|parent)$/).test(o
.containment
)) {
3804 var ce
= $(o
.containment
)[0];
3805 var co
= $(o
.containment
).offset();
3806 var over
= ($(ce
).css("overflow") != 'hidden');
3808 this.containment
= [
3809 co
.left
+ (parseInt($(ce
).css("borderLeftWidth"),10) || 0) + (parseInt($(ce
).css("paddingLeft"),10) || 0) - this.margins
.left
,
3810 co
.top
+ (parseInt($(ce
).css("borderTopWidth"),10) || 0) + (parseInt($(ce
).css("paddingTop"),10) || 0) - this.margins
.top
,
3811 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
,
3812 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
3818 _convertPositionTo: function(d
, pos
) {
3820 if(!pos
) pos
= this.position
;
3821 var mod
= d
== "absolute" ? 1 : -1;
3822 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
);
3826 pos
.top
// The absolute mouse position
3827 + this.offset
.relative
.top
* mod
// Only for relative positioned nodes: Relative offset from element to offset parent
3828 + this.offset
.parent
.top
* mod
// The offsetParent's offset without borders (offset + border)
3829 - ($.browser
.safari
&& this.cssPosition
== 'fixed' ? 0 : ( this.cssPosition
== 'fixed' ? -this.scrollParent
.scrollTop() : ( scrollIsRootNode
? 0 : scroll
.scrollTop() ) ) * mod
)
3832 pos
.left
// The absolute mouse position
3833 + this.offset
.relative
.left
* mod
// Only for relative positioned nodes: Relative offset from element to offset parent
3834 + this.offset
.parent
.left
* mod
// The offsetParent's offset without borders (offset + border)
3835 - ($.browser
.safari
&& this.cssPosition
== 'fixed' ? 0 : ( this.cssPosition
== 'fixed' ? -this.scrollParent
.scrollLeft() : scrollIsRootNode
? 0 : scroll
.scrollLeft() ) * mod
)
3841 _generatePosition: function(event
) {
3843 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
);
3845 // This is another very weird special case that only happens for relative elements:
3846 // 1. If the css position is relative
3847 // 2. and the scroll parent is the document or similar to the offset parent
3848 // we have to refresh the relative offset during the scroll so there are no jumps
3849 if(this.cssPosition
== 'relative' && !(this.scrollParent
[0] != document
&& this.scrollParent
[0] != this.offsetParent
[0])) {
3850 this.offset
.relative
= this._getRelativeOffset();
3853 var pageX
= event
.pageX
;
3854 var pageY
= event
.pageY
;
3857 * - Position constraining -
3858 * Constrain the position to a mix of grid, containment.
3861 if(this.originalPosition
) { //If we are not dragging yet, we won't check for options
3863 if(this.containment
) {
3864 if(event
.pageX
- this.offset
.click
.left
< this.containment
[0]) pageX
= this.containment
[0] + this.offset
.click
.left
;
3865 if(event
.pageY
- this.offset
.click
.top
< this.containment
[1]) pageY
= this.containment
[1] + this.offset
.click
.top
;
3866 if(event
.pageX
- this.offset
.click
.left
> this.containment
[2]) pageX
= this.containment
[2] + this.offset
.click
.left
;
3867 if(event
.pageY
- this.offset
.click
.top
> this.containment
[3]) pageY
= this.containment
[3] + this.offset
.click
.top
;
3871 var top
= this.originalPageY
+ Math
.round((pageY
- this.originalPageY
) / o
.grid
[1]) * o
.grid
[1];
3872 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
;
3874 var left
= this.originalPageX
+ Math
.round((pageX
- this.originalPageX
) / o
.grid
[0]) * o
.grid
[0];
3875 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
;
3882 pageY
// The absolute mouse position
3883 - this.offset
.click
.top
// Click offset (relative to the element)
3884 - this.offset
.relative
.top
// Only for relative positioned nodes: Relative offset from element to offset parent
3885 - this.offset
.parent
.top
// The offsetParent's offset without borders (offset + border)
3886 + ($.browser
.safari
&& this.cssPosition
== 'fixed' ? 0 : ( this.cssPosition
== 'fixed' ? -this.scrollParent
.scrollTop() : ( scrollIsRootNode
? 0 : scroll
.scrollTop() ) ))
3889 pageX
// The absolute mouse position
3890 - this.offset
.click
.left
// Click offset (relative to the element)
3891 - this.offset
.relative
.left
// Only for relative positioned nodes: Relative offset from element to offset parent
3892 - this.offset
.parent
.left
// The offsetParent's offset without borders (offset + border)
3893 + ($.browser
.safari
&& this.cssPosition
== 'fixed' ? 0 : ( this.cssPosition
== 'fixed' ? -this.scrollParent
.scrollLeft() : scrollIsRootNode
? 0 : scroll
.scrollLeft() ))
3899 _rearrange: function(event
, i
, a
, hardRefresh
) {
3901 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
));
3903 //Various things done here to improve the performance:
3904 // 1. we create a setTimeout, that calls refreshPositions
3905 // 2. on the instance, we have a counter variable, that get's higher after every append
3906 // 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same
3907 // 4. this lets only the last addition to the timeout stack through
3908 this.counter
= this.counter
? ++this.counter
: 1;
3909 var self
= this, counter
= this.counter
;
3911 window
.setTimeout(function() {
3912 if(counter
== self
.counter
) self
.refreshPositions(!hardRefresh
); //Precompute after each DOM insertion, NOT on mousemove
3917 _clear: function(event
, noPropagation
) {
3919 this.reverting
= false;
3920 // We delay all events that have to be triggered to after the point where the placeholder has been removed and
3921 // everything else normalized again
3922 var delayedTriggers
= [], self
= this;
3924 // We first have to update the dom position of the actual currentItem
3925 // Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088)
3926 if(!this._noFinalSort
&& this.currentItem
[0].parentNode
) this.placeholder
.before(this.currentItem
);
3927 this._noFinalSort
= null;
3929 if(this.helper
[0] == this.currentItem
[0]) {
3930 for(var i
in this._storedCSS
) {
3931 if(this._storedCSS
[i
] == 'auto' || this._storedCSS
[i
] == 'static') this._storedCSS
[i
] = '';
3933 this.currentItem
.css(this._storedCSS
).removeClass("ui-sortable-helper");
3935 this.currentItem
.show();
3938 if(this.fromOutside
&& !noPropagation
) delayedTriggers
.push(function(event
) { this._trigger("receive", event
, this._uiHash(this.fromOutside
)); });
3939 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
3940 if(!$.ui
.contains(this.element
[0], this.currentItem
[0])) { //Node was moved out of the current element
3941 if(!noPropagation
) delayedTriggers
.push(function(event
) { this._trigger("remove", event
, this._uiHash()); });
3942 for (var i
= this.containers
.length
- 1; i
>= 0; i
--){
3943 if($.ui
.contains(this.containers
[i
].element
[0], this.currentItem
[0]) && !noPropagation
) {
3944 delayedTriggers
.push((function(c
) { return function(event
) { c
._trigger("receive", event
, this._uiHash(this)); }; }).call(this, this.containers
[i
]));
3945 delayedTriggers
.push((function(c
) { return function(event
) { c
._trigger("update", event
, this._uiHash(this)); }; }).call(this, this.containers
[i
]));
3950 //Post events to containers
3951 for (var i
= this.containers
.length
- 1; i
>= 0; i
--){
3952 if(!noPropagation
) delayedTriggers
.push((function(c
) { return function(event
) { c
._trigger("deactivate", event
, this._uiHash(this)); }; }).call(this, this.containers
[i
]));
3953 if(this.containers
[i
].containerCache
.over
) {
3954 delayedTriggers
.push((function(c
) { return function(event
) { c
._trigger("out", event
, this._uiHash(this)); }; }).call(this, this.containers
[i
]));
3955 this.containers
[i
].containerCache
.over
= 0;
3959 //Do what was originally in plugins
3960 if(this._storedCursor
) $('body').css("cursor", this._storedCursor
); //Reset cursor
3961 if(this._storedOpacity
) this.helper
.css("opacity", this._storedOpacity
); //Reset opacity
3962 if(this._storedZIndex
) this.helper
.css("zIndex", this._storedZIndex
== 'auto' ? '' : this._storedZIndex
); //Reset z-index
3964 this.dragging
= false;
3965 if(this.cancelHelperRemoval
) {
3966 if(!noPropagation
) {
3967 this._trigger("beforeStop", event
, this._uiHash());
3968 for (var i
=0; i
< delayedTriggers
.length
; i
++) { delayedTriggers
[i
].call(this, event
); }; //Trigger all delayed events
3969 this._trigger("stop", event
, this._uiHash());
3974 if(!noPropagation
) this._trigger("beforeStop", event
, this._uiHash());
3976 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
3977 this.placeholder
[0].parentNode
.removeChild(this.placeholder
[0]);
3979 if(this.helper
[0] != this.currentItem
[0]) this.helper
.remove(); this.helper
= null;
3981 if(!noPropagation
) {
3982 for (var i
=0; i
< delayedTriggers
.length
; i
++) { delayedTriggers
[i
].call(this, event
); }; //Trigger all delayed events
3983 this._trigger("stop", event
, this._uiHash());
3986 this.fromOutside
= false;
3991 _trigger: function() {
3992 if ($.Widget
.prototype._trigger
.apply(this, arguments
) === false) {
3997 _uiHash: function(inst
) {
3998 var self
= inst
|| this;
4000 helper
: self
.helper
,
4001 placeholder
: self
.placeholder
|| $([]),
4002 position
: self
.position
,
4003 originalPosition
: self
.originalPosition
,
4004 offset
: self
.positionAbs
,
4005 item
: self
.currentItem
,
4006 sender
: inst
? inst
.element
: null
4012 $.extend($.ui
.sortable
, {
4018 * jQuery UI Accordion 1.8
4020 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
4021 * Dual licensed under the MIT (MIT-LICENSE.txt)
4022 * and GPL (GPL-LICENSE.txt) licenses.
4024 * http://docs.jquery.com/UI/Accordion
4028 * jquery.ui.widget.js
4032 $.widget("ui.accordion", {
4041 header
: "> li > :first-child,> :not(li):even",
4043 header
: "ui-icon-triangle-1-e",
4044 headerSelected
: "ui-icon-triangle-1-s"
4047 navigationFilter: function() {
4048 return this.href
.toLowerCase() == location
.href
.toLowerCase();
4051 _create: function() {
4053 var o
= this.options
, self
= this;
4056 this.element
.addClass("ui-accordion ui-widget ui-helper-reset");
4058 // in lack of child-selectors in CSS we need to mark top-LIs in a UL-accordion for some IE-fix
4059 if (this.element
[0].nodeName
== "UL") {
4060 this.element
.children("li").addClass("ui-accordion-li-fix");
4063 this.headers
= this.element
.find(o
.header
).addClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all")
4064 .bind("mouseenter.accordion", function(){ $(this).addClass('ui-state-hover'); })
4065 .bind("mouseleave.accordion", function(){ $(this).removeClass('ui-state-hover'); })
4066 .bind("focus.accordion", function(){ $(this).addClass('ui-state-focus'); })
4067 .bind("blur.accordion", function(){ $(this).removeClass('ui-state-focus'); });
4071 .addClass("ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom");
4073 if ( o
.navigation
) {
4074 var current
= this.element
.find("a").filter(o
.navigationFilter
);
4075 if ( current
.length
) {
4076 var header
= current
.closest(".ui-accordion-header");
4077 if ( header
.length
) {
4078 // anchor within header
4079 this.active
= header
;
4081 // anchor within content
4082 this.active
= current
.closest(".ui-accordion-content").prev();
4087 this.active
= this._findActive(this.active
|| o
.active
).toggleClass("ui-state-default").toggleClass("ui-state-active").toggleClass("ui-corner-all").toggleClass("ui-corner-top");
4088 this.active
.next().addClass('ui-accordion-content-active');
4090 //Append icon elements
4091 this._createIcons();
4093 // IE7-/Win - Extra vertical space in lists fixed
4094 if ($.browser
.msie
) {
4095 this.element
.find('a').css('zoom', '1');
4101 this.element
.attr('role','tablist');
4105 .bind('keydown', function(event
) { return self
._keydown(event
); })
4107 .attr('role','tabpanel');
4110 .not(this.active
|| "")
4111 .attr('aria-expanded','false')
4112 .attr("tabIndex", "-1")
4116 // make sure at least one header is in the tab order
4117 if (!this.active
.length
) {
4118 this.headers
.eq(0).attr('tabIndex','0');
4121 .attr('aria-expanded','true')
4122 .attr('tabIndex', '0');
4125 // only need links in taborder for Safari
4126 if (!$.browser
.safari
)
4127 this.headers
.find('a').attr('tabIndex','-1');
4130 this.headers
.bind((o
.event
) + ".accordion", function(event
) {
4131 self
._clickHandler
.call(self
, event
, this);
4132 event
.preventDefault();
4138 _createIcons: function() {
4139 var o
= this.options
;
4141 $("<span/>").addClass("ui-icon " + o
.icons
.header
).prependTo(this.headers
);
4142 this.active
.find(".ui-icon").toggleClass(o
.icons
.header
).toggleClass(o
.icons
.headerSelected
);
4143 this.element
.addClass("ui-accordion-icons");
4147 _destroyIcons: function() {
4148 this.headers
.children(".ui-icon").remove();
4149 this.element
.removeClass("ui-accordion-icons");
4152 destroy: function() {
4153 var o
= this.options
;
4156 .removeClass("ui-accordion ui-widget ui-helper-reset")
4158 .unbind('.accordion')
4159 .removeData('accordion');
4162 .unbind(".accordion")
4163 .removeClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-corner-top")
4164 .removeAttr("role").removeAttr("aria-expanded").removeAttr("tabindex");
4166 this.headers
.find("a").removeAttr("tabindex");
4167 this._destroyIcons();
4168 var contents
= this.headers
.next().css("display", "").removeAttr("role").removeClass("ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active");
4169 if (o
.autoHeight
|| o
.fillHeight
) {
4170 contents
.css("height", "");
4176 _setOption: function(key
, value
) {
4177 $.Widget
.prototype._setOption
.apply(this, arguments
);
4179 if (key
== "active") {
4180 this.activate(value
);
4182 if (key
== "icons") {
4183 this._destroyIcons();
4185 this._createIcons();
4191 _keydown: function(event
) {
4193 var o
= this.options
, keyCode
= $.ui
.keyCode
;
4195 if (o
.disabled
|| event
.altKey
|| event
.ctrlKey
)
4198 var length
= this.headers
.length
;
4199 var currentIndex
= this.headers
.index(event
.target
);
4200 var toFocus
= false;
4202 switch(event
.keyCode
) {
4205 toFocus
= this.headers
[(currentIndex
+ 1) % length
];
4209 toFocus
= this.headers
[(currentIndex
- 1 + length
) % length
];
4213 this._clickHandler({ target
: event
.target
}, event
.target
);
4214 event
.preventDefault();
4218 $(event
.target
).attr('tabIndex','-1');
4219 $(toFocus
).attr('tabIndex','0');
4228 resize: function() {
4230 var o
= this.options
, maxHeight
;
4234 if($.browser
.msie
) { var defOverflow
= this.element
.parent().css('overflow'); this.element
.parent().css('overflow', 'hidden'); }
4235 maxHeight
= this.element
.parent().height();
4236 if($.browser
.msie
) { this.element
.parent().css('overflow', defOverflow
); }
4238 this.headers
.each(function() {
4239 maxHeight
-= $(this).outerHeight(true);
4242 this.headers
.next().each(function() {
4243 $(this).height(Math
.max(0, maxHeight
- $(this).innerHeight() + $(this).height()));
4244 }).css('overflow', 'auto');
4246 } else if ( o
.autoHeight
) {
4248 this.headers
.next().each(function() {
4249 maxHeight
= Math
.max(maxHeight
, $(this).height());
4250 }).height(maxHeight
);
4256 activate: function(index
) {
4257 // TODO this gets called on init, changing the option without an explicit call for that
4258 this.options
.active
= index
;
4259 // call clickHandler with custom event
4260 var active
= this._findActive(index
)[0];
4261 this._clickHandler({ target
: active
}, active
);
4266 _findActive: function(selector
) {
4268 ? typeof selector
== "number"
4269 ? this.headers
.filter(":eq(" + selector
+ ")")
4270 : this.headers
.not(this.headers
.not(selector
))
4271 : selector
=== false
4273 : this.headers
.filter(":eq(0)");
4276 // TODO isn't event.target enough? why the seperate target argument?
4277 _clickHandler: function(event
, target
) {
4279 var o
= this.options
;
4283 // called only when using activate(false) to close all parts programmatically
4284 if (!event
.target
) {
4287 this.active
.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all")
4288 .find(".ui-icon").removeClass(o
.icons
.headerSelected
).addClass(o
.icons
.header
);
4289 this.active
.next().addClass('ui-accordion-content-active');
4290 var toHide
= this.active
.next(),
4294 oldHeader
: o
.active
,
4298 toShow
= (this.active
= $([]));
4299 this._toggle(toShow
, toHide
, data
);
4303 // get the click target
4304 var clicked
= $(event
.currentTarget
|| target
);
4305 var clickedIsActive
= clicked
[0] == this.active
[0];
4307 // TODO the option is changed, is that correct?
4308 // TODO if it is correct, shouldn't that happen after determining that the click is valid?
4309 o
.active
= o
.collapsible
&& clickedIsActive
? false : $('.ui-accordion-header', this.element
).index(clicked
);
4311 // if animations are still active, or the active header is the target, ignore click
4312 if (this.running
|| (!o
.collapsible
&& clickedIsActive
)) {
4317 this.active
.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all")
4318 .find(".ui-icon").removeClass(o
.icons
.headerSelected
).addClass(o
.icons
.header
);
4319 if (!clickedIsActive
) {
4320 clicked
.removeClass("ui-state-default ui-corner-all").addClass("ui-state-active ui-corner-top")
4321 .find(".ui-icon").removeClass(o
.icons
.header
).addClass(o
.icons
.headerSelected
);
4322 clicked
.next().addClass('ui-accordion-content-active');
4325 // find elements to show and hide
4326 var toShow
= clicked
.next(),
4327 toHide
= this.active
.next(),
4330 newHeader
: clickedIsActive
&& o
.collapsible
? $([]) : clicked
,
4331 oldHeader
: this.active
,
4332 newContent
: clickedIsActive
&& o
.collapsible
? $([]) : toShow
,
4335 down
= this.headers
.index( this.active
[0] ) > this.headers
.index( clicked
[0] );
4337 this.active
= clickedIsActive
? $([]) : clicked
;
4338 this._toggle(toShow
, toHide
, data
, clickedIsActive
, down
);
4344 _toggle: function(toShow
, toHide
, data
, clickedIsActive
, down
) {
4346 var o
= this.options
, self
= this;
4348 this.toShow
= toShow
;
4349 this.toHide
= toHide
;
4352 var complete = function() { if(!self
) return; return self
._completed
.apply(self
, arguments
); };
4354 // trigger changestart event
4355 this._trigger("changestart", null, this.data
);
4357 // count elements to animate
4358 this.running
= toHide
.size() === 0 ? toShow
.size() : toHide
.size();
4362 var animOptions
= {};
4364 if ( o
.collapsible
&& clickedIsActive
) {
4370 autoHeight
: o
.autoHeight
|| o
.fillSpace
4378 autoHeight
: o
.autoHeight
|| o
.fillSpace
4383 o
.proxied
= o
.animated
;
4386 if (!o
.proxiedDuration
) {
4387 o
.proxiedDuration
= o
.duration
;
4390 o
.animated
= $.isFunction(o
.proxied
) ?
4391 o
.proxied(animOptions
) : o
.proxied
;
4393 o
.duration
= $.isFunction(o
.proxiedDuration
) ?
4394 o
.proxiedDuration(animOptions
) : o
.proxiedDuration
;
4396 var animations
= $.ui
.accordion
.animations
,
4397 duration
= o
.duration
,
4398 easing
= o
.animated
;
4400 if (easing
&& !animations
[easing
] && !$.easing
[easing
]) {
4403 if (!animations
[easing
]) {
4404 animations
[easing
] = function(options
) {
4405 this.slide(options
, {
4407 duration
: duration
|| 700
4412 animations
[easing
](animOptions
);
4416 if (o
.collapsible
&& clickedIsActive
) {
4427 // TODO assert that the blur and focus triggers are really necessary, remove otherwise
4428 toHide
.prev().attr('aria-expanded','false').attr("tabIndex", "-1").blur();
4429 toShow
.prev().attr('aria-expanded','true').attr("tabIndex", "0").focus();
4433 _completed: function(cancel
) {
4435 var o
= this.options
;
4437 this.running
= cancel
? 0 : --this.running
;
4438 if (this.running
) return;
4441 this.toShow
.add(this.toHide
).css({
4447 // other classes are removed before the animation; this one needs to stay until completed
4448 this.toHide
.removeClass("ui-accordion-content-active");
4450 this._trigger('change', null, this.data
);
4456 $.extend($.ui
.accordion
, {
4459 slide: function(options
, additions
) {
4460 options
= $.extend({
4463 }, options
, additions
);
4464 if ( !options
.toHide
.size() ) {
4465 options
.toShow
.animate({height
: "show"}, options
);
4468 if ( !options
.toShow
.size() ) {
4469 options
.toHide
.animate({height
: "hide"}, options
);
4472 var overflow
= options
.toShow
.css('overflow'),
4476 fxAttrs
= [ "height", "paddingTop", "paddingBottom" ],
4478 // fix width before calculating height of hidden element
4479 var s
= options
.toShow
;
4480 originalWidth
= s
[0].style
.width
;
4481 s
.width( parseInt(s
.parent().width(),10) - parseInt(s
.css("paddingLeft"),10) - parseInt(s
.css("paddingRight"),10) - (parseInt(s
.css("borderLeftWidth"),10) || 0) - (parseInt(s
.css("borderRightWidth"),10) || 0) );
4483 $.each(fxAttrs
, function(i
, prop
) {
4484 hideProps
[prop
] = 'hide';
4486 var parts
= ('' + $.css(options
.toShow
[0], prop
)).match(/^([\d+-.]+)(.*)$/);
4489 unit
: parts
[2] || 'px'
4492 options
.toShow
.css({ height
: 0, overflow
: 'hidden' }).show();
4493 options
.toHide
.filter(":hidden").each(options
.complete
).end().filter(":visible").animate(hideProps
,{
4494 step: function(now
, settings
) {
4495 // only calculate the percent when animating height
4496 // IE gets very inconsistent results when animating elements
4497 // with small values, which is common for padding
4498 if (settings
.prop
== 'height') {
4499 percentDone
= ( settings
.end
- settings
.start
=== 0 ) ? 0 :
4500 (settings
.now
- settings
.start
) / (settings
.end
- settings
.start
);
4503 options
.toShow
[0].style
[settings
.prop
] =
4504 (percentDone
* showProps
[settings
.prop
].value
) + showProps
[settings
.prop
].unit
;
4506 duration
: options
.duration
,
4507 easing
: options
.easing
,
4508 complete: function() {
4509 if ( !options
.autoHeight
) {
4510 options
.toShow
.css("height", "");
4512 options
.toShow
.css("width", originalWidth
);
4513 options
.toShow
.css({overflow
: overflow
});
4518 bounceslide: function(options
) {
4519 this.slide(options
, {
4520 easing
: options
.down
? "easeOutBounce" : "swing",
4521 duration
: options
.down
? 1000 : 200
4529 * jQuery UI Autocomplete 1.8
4531 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
4532 * Dual licensed under the MIT (MIT-LICENSE.txt)
4533 * and GPL (GPL-LICENSE.txt) licenses.
4535 * http://docs.jquery.com/UI/Autocomplete
4539 * jquery.ui.widget.js
4540 * jquery.ui.position.js
4544 $.widget( "ui.autocomplete", {
4549 _create: function() {
4551 doc
= this.element
[ 0 ].ownerDocument
;
4553 .addClass( "ui-autocomplete-input" )
4554 .attr( "autocomplete", "off" )
4555 // TODO verify these actually work as intended
4558 "aria-autocomplete": "list",
4559 "aria-haspopup": "true"
4561 .bind( "keydown.autocomplete", function( event
) {
4562 var keyCode
= $.ui
.keyCode
;
4563 switch( event
.keyCode
) {
4564 case keyCode
.PAGE_UP
:
4565 self
._move( "previousPage", event
);
4567 case keyCode
.PAGE_DOWN
:
4568 self
._move( "nextPage", event
);
4571 self
._move( "previous", event
);
4572 // prevent moving cursor to beginning of text field in some browsers
4573 event
.preventDefault();
4576 self
._move( "next", event
);
4577 // prevent moving cursor to end of text field in some browsers
4578 event
.preventDefault();
4581 // when menu is open or has focus
4582 if ( self
.menu
.active
) {
4583 event
.preventDefault();
4585 //passthrough - ENTER and TAB both select the current element
4587 if ( !self
.menu
.active
) {
4592 case keyCode
.ESCAPE
:
4593 self
.element
.val( self
.term
);
4594 self
.close( event
);
4597 case keyCode
.CONTROL
:
4599 // ignore metakeys (shift, ctrl, alt)
4602 // keypress is triggered before the input value is changed
4603 clearTimeout( self
.searching
);
4604 self
.searching
= setTimeout(function() {
4605 self
.search( null, event
);
4606 }, self
.options
.delay
);
4610 .bind( "focus.autocomplete", function() {
4611 self
.previous
= self
.element
.val();
4613 .bind( "blur.autocomplete", function( event
) {
4614 clearTimeout( self
.searching
);
4615 // clicks on the menu (or a button to trigger a search) will cause a blur event
4616 // TODO try to implement this without a timeout, see clearTimeout in search()
4617 self
.closing
= setTimeout(function() {
4618 self
.close( event
);
4622 this.response = function() {
4623 return self
._response
.apply( self
, arguments
);
4625 this.menu
= $( "<ul></ul>" )
4626 .addClass( "ui-autocomplete" )
4627 .appendTo( "body", doc
)
4629 focus: function( event
, ui
) {
4630 var item
= ui
.item
.data( "item.autocomplete" );
4631 if ( false !== self
._trigger( "focus", null, { item
: item
} ) ) {
4632 // use value to match what will end up in the input
4633 self
.element
.val( item
.value
);
4636 selected: function( event
, ui
) {
4637 var item
= ui
.item
.data( "item.autocomplete" );
4638 if ( false !== self
._trigger( "select", event
, { item
: item
} ) ) {
4639 self
.element
.val( item
.value
);
4641 self
.close( event
);
4642 self
.previous
= self
.element
.val();
4643 // only trigger when focus was lost (click on menu)
4644 if ( self
.element
[0] !== doc
.activeElement
) {
4645 self
.element
.focus();
4648 blur: function( event
, ui
) {
4649 if ( self
.menu
.element
.is(":visible") ) {
4650 self
.element
.val( self
.term
);
4654 .zIndex( this.element
.zIndex() + 1 )
4655 // workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
4656 .css({ top
: 0, left
: 0 })
4659 if ( $.fn
.bgiframe
) {
4660 this.menu
.element
.bgiframe();
4664 destroy: function() {
4666 .removeClass( "ui-autocomplete-input ui-widget ui-widget-content" )
4667 .removeAttr( "autocomplete" )
4668 .removeAttr( "role" )
4669 .removeAttr( "aria-autocomplete" )
4670 .removeAttr( "aria-haspopup" );
4671 this.menu
.element
.remove();
4672 $.Widget
.prototype.destroy
.call( this );
4675 _setOption: function( key
) {
4676 $.Widget
.prototype._setOption
.apply( this, arguments
);
4677 if ( key
=== "source" ) {
4682 _initSource: function() {
4685 if ( $.isArray(this.options
.source
) ) {
4686 array
= this.options
.source
;
4687 this.source = function( request
, response
) {
4688 // escape regex characters
4689 var matcher
= new RegExp( $.ui
.autocomplete
.escapeRegex(request
.term
), "i" );
4690 response( $.grep( array
, function(value
) {
4691 return matcher
.test( value
.label
|| value
.value
|| value
);
4694 } else if ( typeof this.options
.source
=== "string" ) {
4695 url
= this.options
.source
;
4696 this.source = function( request
, response
) {
4697 $.getJSON( url
, request
, response
);
4700 this.source
= this.options
.source
;
4704 search: function( value
, event
) {
4705 value
= value
!= null ? value
: this.element
.val();
4706 if ( value
.length
< this.options
.minLength
) {
4707 return this.close( event
);
4710 clearTimeout( this.closing
);
4711 if ( this._trigger("search") === false ) {
4715 return this._search( value
);
4718 _search: function( value
) {
4719 this.term
= this.element
4720 .addClass( "ui-autocomplete-loading" )
4721 // always save the actual value, not the one passed as an argument
4724 this.source( { term
: value
}, this.response
);
4727 _response: function( content
) {
4728 if ( content
.length
) {
4729 content
= this._normalize( content
);
4730 this._suggest( content
);
4731 this._trigger( "open" );
4735 this.element
.removeClass( "ui-autocomplete-loading" );
4738 close: function( event
) {
4739 clearTimeout( this.closing
);
4740 if ( this.menu
.element
.is(":visible") ) {
4741 this._trigger( "close", event
);
4742 this.menu
.element
.hide();
4743 this.menu
.deactivate();
4745 if ( this.previous
!== this.element
.val() ) {
4746 this._trigger( "change", event
);
4750 _normalize: function( items
) {
4751 // assume all items have the right format when the first item is complete
4752 if ( items
.length
&& items
[0].label
&& items
[0].value
) {
4755 return $.map( items
, function(item
) {
4756 if ( typeof item
=== "string" ) {
4763 label
: item
.label
|| item
.value
,
4764 value
: item
.value
|| item
.label
4769 _suggest: function( items
) {
4770 var ul
= this.menu
.element
4772 .zIndex( this.element
.zIndex() + 1 ),
4775 this._renderMenu( ul
, items
);
4776 // TODO refresh should check if the active item is still in the dom, removing the need for a manual deactivate
4777 this.menu
.deactivate();
4778 this.menu
.refresh();
4779 this.menu
.element
.show().position({
4786 menuWidth
= ul
.width( "" ).width();
4787 textWidth
= this.element
.width();
4788 ul
.width( Math
.max( menuWidth
, textWidth
) );
4791 _renderMenu: function( ul
, items
) {
4793 $.each( items
, function( index
, item
) {
4794 self
._renderItem( ul
, item
);
4798 _renderItem: function( ul
, item
) {
4799 return $( "<li></li>" )
4800 .data( "item.autocomplete", item
)
4801 .append( "<a>" + item
.label
+ "</a>" )
4805 _move: function( direction
, event
) {
4806 if ( !this.menu
.element
.is(":visible") ) {
4807 this.search( null, event
);
4810 if ( this.menu
.first() && /^previous/.test(direction
) ||
4811 this.menu
.last() && /^next/.test(direction
) ) {
4812 this.element
.val( this.term
);
4813 this.menu
.deactivate();
4816 this.menu
[ direction
]();
4819 widget: function() {
4820 return this.menu
.element
;
4824 $.extend( $.ui
.autocomplete
, {
4825 escapeRegex: function( value
) {
4826 return value
.replace( /([\^\$\(\)\[\]\{\}\*\.\+\?\|\\])/gi, "\\$1" );
4833 * jQuery UI Menu (not officially released)
4835 * This widget isn't yet finished and the API is subject to change. We plan to finish
4836 * it for the next release. You're welcome to give it a try anyway and give us feedback,
4837 * as long as you're okay with migrating your code later on. We can help with that, too.
4839 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
4840 * Dual licensed under the MIT (MIT-LICENSE.txt)
4841 * and GPL (GPL-LICENSE.txt) licenses.
4843 * http://docs.jquery.com/UI/Menu
4847 * jquery.ui.widget.js
4851 $.widget("ui.menu", {
4852 _create: function() {
4855 .addClass("ui-menu ui-widget ui-widget-content ui-corner-all")
4858 "aria-activedescendant": "ui-active-menuitem"
4860 .click(function(e
) {
4868 refresh: function() {
4871 // don't refresh list items that are already adapted
4872 var items
= this.element
.children("li:not(.ui-menu-item):has(a)")
4873 .addClass("ui-menu-item")
4874 .attr("role", "menuitem");
4877 .addClass("ui-corner-all")
4878 .attr("tabindex", -1)
4879 // mouseenter doesn't work with event delegation
4880 .mouseenter(function() {
4881 self
.activate($(this).parent());
4883 .mouseleave(function() {
4888 activate: function(item
) {
4890 if (this.hasScroll()) {
4891 var offset
= item
.offset().top
- this.element
.offset().top
,
4892 scroll
= this.element
.attr("scrollTop"),
4893 elementHeight
= this.element
.height();
4895 this.element
.attr("scrollTop", scroll
+ offset
);
4896 } else if (offset
> elementHeight
) {
4897 this.element
.attr("scrollTop", scroll
+ offset
- elementHeight
+ item
.height());
4900 this.active
= item
.eq(0)
4902 .addClass("ui-state-hover")
4903 .attr("id", "ui-active-menuitem")
4905 this._trigger("focus", null, { item
: item
});
4908 deactivate: function() {
4909 if (!this.active
) { return; }
4911 this.active
.children("a")
4912 .removeClass("ui-state-hover")
4914 this._trigger("blur");
4919 this.move("next", "li:first");
4922 previous: function() {
4923 this.move("prev", "li:last");
4927 return this.active
&& !this.active
.prev().length
;
4931 return this.active
&& !this.active
.next().length
;
4934 move: function(direction
, edge
) {
4936 this.activate(this.element
.children(edge
));
4939 var next
= this.active
[direction
]();
4941 this.activate(next
);
4943 this.activate(this.element
.children(edge
));
4947 // TODO merge with previousPage
4948 nextPage: function() {
4949 if (this.hasScroll()) {
4950 // TODO merge with no-scroll-else
4951 if (!this.active
|| this.last()) {
4952 this.activate(this.element
.children(":first"));
4955 var base
= this.active
.offset().top
,
4956 height
= this.element
.height(),
4957 result
= this.element
.children("li").filter(function() {
4958 var close
= $(this).offset().top
- base
- height
+ $(this).height();
4959 // TODO improve approximation
4960 return close
< 10 && close
> -10;
4963 // TODO try to catch this earlier when scrollTop indicates the last page anyway
4964 if (!result
.length
) {
4965 result
= this.element
.children(":last");
4967 this.activate(result
);
4969 this.activate(this.element
.children(!this.active
|| this.last() ? ":first" : ":last"));
4973 // TODO merge with nextPage
4974 previousPage: function() {
4975 if (this.hasScroll()) {
4976 // TODO merge with no-scroll-else
4977 if (!this.active
|| this.first()) {
4978 this.activate(this.element
.children(":last"));
4982 var base
= this.active
.offset().top
,
4983 height
= this.element
.height();
4984 result
= this.element
.children("li").filter(function() {
4985 var close
= $(this).offset().top
- base
+ height
- $(this).height();
4986 // TODO improve approximation
4987 return close
< 10 && close
> -10;
4990 // TODO try to catch this earlier when scrollTop indicates the last page anyway
4991 if (!result
.length
) {
4992 result
= this.element
.children(":first");
4994 this.activate(result
);
4996 this.activate(this.element
.children(!this.active
|| this.first() ? ":last" : ":first"));
5000 hasScroll: function() {
5001 return this.element
.height() < this.element
.attr("scrollHeight");
5004 select: function() {
5005 this._trigger("selected", null, { item
: this.active
});
5011 * jQuery UI Button 1.8
5013 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
5014 * Dual licensed under the MIT (MIT-LICENSE.txt)
5015 * and GPL (GPL-LICENSE.txt) licenses.
5017 * http://docs.jquery.com/UI/Button
5021 * jquery.ui.widget.js
5026 baseClasses
= "ui-button ui-widget ui-state-default ui-corner-all",
5027 otherClasses
= "ui-state-hover ui-state-active " +
5028 "ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon ui-button-text-only",
5029 formResetHandler = function( event
) {
5030 $( ":ui-button", event
.target
.form
).each(function() {
5031 var inst
= $( this ).data( "button" );
5032 setTimeout(function() {
5037 radioGroup = function( radio
) {
5038 var name
= radio
.name
,
5043 radios
= $( form
).find( "[name='" + name
+ "']" );
5045 radios
= $( "[name='" + name
+ "']", radio
.ownerDocument
)
5046 .filter(function() {
5054 $.widget( "ui.button", {
5063 _create: function() {
5064 this.element
.closest( "form" )
5065 .unbind( "reset.button" )
5066 .bind( "reset.button", formResetHandler
);
5068 this._determineButtonType();
5069 this.hasTitle
= !!this.buttonElement
.attr( "title" );
5072 options
= this.options
,
5073 toggleButton
= this.type
=== "checkbox" || this.type
=== "radio",
5074 hoverClass
= "ui-state-hover" + ( !toggleButton
? " ui-state-active" : "" ),
5075 focusClass
= "ui-state-focus";
5077 if ( options
.label
=== null ) {
5078 options
.label
= this.buttonElement
.html();
5081 if ( this.element
.is( ":disabled" ) ) {
5082 options
.disabled
= true;
5086 .addClass( baseClasses
)
5087 .attr( "role", "button" )
5088 .bind( "mouseenter.button", function() {
5089 if ( options
.disabled
) {
5092 $( this ).addClass( "ui-state-hover" );
5093 if ( this === lastActive
) {
5094 $( this ).addClass( "ui-state-active" );
5097 .bind( "mouseleave.button", function() {
5098 if ( options
.disabled
) {
5101 $( this ).removeClass( hoverClass
);
5103 .bind( "focus.button", function() {
5104 // no need to check disabled, focus won't be triggered anyway
5105 $( this ).addClass( focusClass
);
5107 .bind( "blur.button", function() {
5108 $( this ).removeClass( focusClass
);
5111 if ( toggleButton
) {
5112 this.element
.bind( "change.button", function() {
5117 if ( this.type
=== "checkbox" ) {
5118 this.buttonElement
.bind( "click.button", function() {
5119 if ( options
.disabled
) {
5122 $( this ).toggleClass( "ui-state-active" );
5123 self
.buttonElement
.attr( "aria-pressed", self
.element
[0].checked
);
5125 } else if ( this.type
=== "radio" ) {
5126 this.buttonElement
.bind( "click.button", function() {
5127 if ( options
.disabled
) {
5130 $( this ).addClass( "ui-state-active" );
5131 self
.buttonElement
.attr( "aria-pressed", true );
5133 var radio
= self
.element
[ 0 ];
5137 return $( this ).button( "widget" )[ 0 ];
5139 .removeClass( "ui-state-active" )
5140 .attr( "aria-pressed", false );
5144 .bind( "mousedown.button", function() {
5145 if ( options
.disabled
) {
5148 $( this ).addClass( "ui-state-active" );
5150 $( document
).one( "mouseup", function() {
5154 .bind( "mouseup.button", function() {
5155 if ( options
.disabled
) {
5158 $( this ).removeClass( "ui-state-active" );
5160 .bind( "keydown.button", function(event
) {
5161 if ( options
.disabled
) {
5164 if ( event
.keyCode
== $.ui
.keyCode
.SPACE
|| event
.keyCode
== $.ui
.keyCode
.ENTER
) {
5165 $( this ).addClass( "ui-state-active" );
5168 .bind( "keyup.button", function() {
5169 $( this ).removeClass( "ui-state-active" );
5172 if ( this.buttonElement
.is("a") ) {
5173 this.buttonElement
.keyup(function(event
) {
5174 if ( event
.keyCode
=== $.ui
.keyCode
.SPACE
) {
5175 // TODO pass through original event correctly (just as 2nd argument doesn't work)
5182 // TODO: pull out $.Widget's handling for the disabled option into
5183 // $.Widget.prototype._setOptionDisabled so it's easy to proxy and can
5184 // be overridden by individual plugins
5185 this._setOption( "disabled", options
.disabled
);
5188 _determineButtonType: function() {
5190 if ( this.element
.is(":checkbox") ) {
5191 this.type
= "checkbox";
5193 if ( this.element
.is(":radio") ) {
5194 this.type
= "radio";
5196 if ( this.element
.is("input") ) {
5197 this.type
= "input";
5199 this.type
= "button";
5204 if ( this.type
=== "checkbox" || this.type
=== "radio" ) {
5205 // we don't search against the document in case the element
5206 // is disconnected from the DOM
5207 this.buttonElement
= this.element
.parents().last()
5208 .find( "[for=" + this.element
.attr("id") + "]" );
5209 this.element
.addClass( "ui-helper-hidden-accessible" );
5211 var checked
= this.element
.is( ":checked" );
5213 this.buttonElement
.addClass( "ui-state-active" );
5215 this.buttonElement
.attr( "aria-pressed", checked
);
5217 this.buttonElement
= this.element
;
5221 widget: function() {
5222 return this.buttonElement
;
5225 destroy: function() {
5227 .removeClass( "ui-helper-hidden-accessible" );
5229 .removeClass( baseClasses
+ " " + otherClasses
)
5230 .removeAttr( "role" )
5231 .removeAttr( "aria-pressed" )
5232 .html( this.buttonElement
.find(".ui-button-text").html() );
5234 if ( !this.hasTitle
) {
5235 this.buttonElement
.removeAttr( "title" );
5238 $.Widget
.prototype.destroy
.call( this );
5241 _setOption: function( key
, value
) {
5242 $.Widget
.prototype._setOption
.apply( this, arguments
);
5243 if ( key
=== "disabled" ) {
5245 this.element
.attr( "disabled", true );
5247 this.element
.removeAttr( "disabled" );
5250 this._resetButton();
5253 refresh: function() {
5254 var isDisabled
= this.element
.is( ":disabled" );
5255 if ( isDisabled
!== this.options
.disabled
) {
5256 this._setOption( "disabled", isDisabled
);
5258 if ( this.type
=== "radio" ) {
5259 radioGroup( this.element
[0] ).each(function() {
5260 if ( $( this ).is( ":checked" ) ) {
5261 $( this ).button( "widget" )
5262 .addClass( "ui-state-active" )
5263 .attr( "aria-pressed", true );
5265 $( this ).button( "widget" )
5266 .removeClass( "ui-state-active" )
5267 .attr( "aria-pressed", false );
5270 } else if ( this.type
=== "checkbox" ) {
5271 if ( this.element
.is( ":checked" ) ) {
5273 .addClass( "ui-state-active" )
5274 .attr( "aria-pressed", true );
5277 .removeClass( "ui-state-active" )
5278 .attr( "aria-pressed", false );
5283 _resetButton: function() {
5284 if ( this.type
=== "input" ) {
5285 if ( this.options
.label
) {
5286 this.element
.val( this.options
.label
);
5290 var buttonElement
= this.buttonElement
,
5291 buttonText
= $( "<span></span>" )
5292 .addClass( "ui-button-text" )
5293 .html( this.options
.label
)
5294 .appendTo( buttonElement
.empty() )
5296 icons
= this.options
.icons
,
5297 multipleIcons
= icons
.primary
&& icons
.secondary
;
5298 if ( icons
.primary
|| icons
.secondary
) {
5299 buttonElement
.addClass( "ui-button-text-icon" +
5300 ( multipleIcons
? "s" : "" ) );
5301 if ( icons
.primary
) {
5302 buttonElement
.prepend( "<span class='ui-button-icon-primary ui-icon " + icons
.primary
+ "'></span>" );
5304 if ( icons
.secondary
) {
5305 buttonElement
.append( "<span class='ui-button-icon-secondary ui-icon " + icons
.secondary
+ "'></span>" );
5307 if ( !this.options
.text
) {
5309 .addClass( multipleIcons
? "ui-button-icons-only" : "ui-button-icon-only" )
5310 .removeClass( "ui-button-text-icons ui-button-text-icon" );
5311 if ( !this.hasTitle
) {
5312 buttonElement
.attr( "title", buttonText
);
5316 buttonElement
.addClass( "ui-button-text-only" );
5321 $.widget( "ui.buttonset", {
5322 _create: function() {
5323 this.element
.addClass( "ui-buttonset" );
5331 _setOption: function( key
, value
) {
5332 if ( key
=== "disabled" ) {
5333 this.buttons
.button( "option", key
, value
);
5336 $.Widget
.prototype._setOption
.apply( this, arguments
);
5339 refresh: function() {
5340 this.buttons
= this.element
.find( ":button, :submit, :reset, :checkbox, :radio, a, :data(button)" )
5341 .filter( ":ui-button" )
5342 .button( "refresh" )
5344 .not( ":ui-button" )
5348 return $( this ).button( "widget" )[ 0 ];
5350 .removeClass( "ui-corner-all ui-corner-left ui-corner-right" )
5352 .addClass( "ui-corner-left" )
5355 .addClass( "ui-corner-right" )
5360 destroy: function() {
5361 this.element
.removeClass( "ui-buttonset" );
5364 return $( this ).button( "widget" )[ 0 ];
5366 .removeClass( "ui-corner-left ui-corner-right" )
5368 .button( "destroy" )
5370 $.Widget
.prototype.destroy
.call( this );
5376 * jQuery UI Dialog 1.8
5378 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
5379 * Dual licensed under the MIT (MIT-LICENSE.txt)
5380 * and GPL (GPL-LICENSE.txt) licenses.
5382 * http://docs.jquery.com/UI/Dialog
5386 * jquery.ui.widget.js
5387 * jquery.ui.button.js
5388 * jquery.ui.draggable.js
5389 * jquery.ui.mouse.js
5390 * jquery.ui.position.js
5391 * jquery.ui.resizable.js
5395 var uiDialogClasses
=
5398 'ui-widget-content ' +
5401 $.widget("ui.dialog", {
5405 closeOnEscape
: true,
5424 _create: function() {
5425 this.originalTitle
= this.element
.attr('title');
5428 options
= self
.options
,
5430 title
= options
.title
|| self
.originalTitle
|| ' ',
5431 titleId
= $.ui
.dialog
.getTitleId(self
.element
),
5433 uiDialog
= (self
.uiDialog
= $('<div></div>'))
5434 .appendTo(document
.body
)
5436 .addClass(uiDialogClasses
+ options
.dialogClass
)
5438 zIndex
: options
.zIndex
5440 // setting tabIndex makes the div focusable
5441 // setting outline to 0 prevents a border on focus in Mozilla
5442 .attr('tabIndex', -1).css('outline', 0).keydown(function(event
) {
5443 if (options
.closeOnEscape
&& event
.keyCode
&&
5444 event
.keyCode
=== $.ui
.keyCode
.ESCAPE
) {
5447 event
.preventDefault();
5452 'aria-labelledby': titleId
5454 .mousedown(function(event
) {
5455 self
.moveToTop(false, event
);
5458 uiDialogContent
= self
.element
5460 .removeAttr('title')
5462 'ui-dialog-content ' +
5463 'ui-widget-content')
5464 .appendTo(uiDialog
),
5466 uiDialogTitlebar
= (self
.uiDialogTitlebar
= $('<div></div>'))
5468 'ui-dialog-titlebar ' +
5469 'ui-widget-header ' +
5471 'ui-helper-clearfix'
5473 .prependTo(uiDialog
),
5475 uiDialogTitlebarClose
= $('<a href="#"></a>')
5477 'ui-dialog-titlebar-close ' +
5480 .attr('role', 'button')
5483 uiDialogTitlebarClose
.addClass('ui-state-hover');
5486 uiDialogTitlebarClose
.removeClass('ui-state-hover');
5490 uiDialogTitlebarClose
.addClass('ui-state-focus');
5493 uiDialogTitlebarClose
.removeClass('ui-state-focus');
5495 .click(function(event
) {
5499 .appendTo(uiDialogTitlebar
),
5501 uiDialogTitlebarCloseText
= (self
.uiDialogTitlebarCloseText
= $('<span></span>'))
5504 'ui-icon-closethick'
5506 .text(options
.closeText
)
5507 .appendTo(uiDialogTitlebarClose
),
5509 uiDialogTitle
= $('<span></span>')
5510 .addClass('ui-dialog-title')
5511 .attr('id', titleId
)
5513 .prependTo(uiDialogTitlebar
);
5515 //handling of deprecated beforeclose (vs beforeClose) option
5516 //Ticket #4669 http://dev.jqueryui.com/ticket/4669
5517 //TODO: remove in 1.9pre
5518 if ($.isFunction(options
.beforeclose
) && !$.isFunction(options
.beforeClose
)) {
5519 options
.beforeClose
= options
.beforeclose
;
5522 uiDialogTitlebar
.find("*").add(uiDialogTitlebar
).disableSelection();
5524 if (options
.draggable
&& $.fn
.draggable
) {
5525 self
._makeDraggable();
5527 if (options
.resizable
&& $.fn
.resizable
) {
5528 self
._makeResizable();
5531 self
._createButtons(options
.buttons
);
5532 self
._isOpen
= false;
5534 if ($.fn
.bgiframe
) {
5535 uiDialog
.bgiframe();
5539 if ( this.options
.autoOpen
) {
5544 destroy: function() {
5548 self
.overlay
.destroy();
5550 self
.uiDialog
.hide();
5553 .removeData('dialog')
5554 .removeClass('ui-dialog-content ui-widget-content')
5555 .hide().appendTo('body');
5556 self
.uiDialog
.remove();
5558 if (self
.originalTitle
) {
5559 self
.element
.attr('title', self
.originalTitle
);
5565 widget: function() {
5566 return this.uiDialog
;
5569 close: function(event
) {
5573 if (false === self
._trigger('beforeClose', event
)) {
5578 self
.overlay
.destroy();
5580 self
.uiDialog
.unbind('keypress.ui-dialog');
5582 self
._isOpen
= false;
5584 if (self
.options
.hide
) {
5585 self
.uiDialog
.hide(self
.options
.hide
, function() {
5586 self
._trigger('close', event
);
5589 self
.uiDialog
.hide();
5590 self
._trigger('close', event
);
5593 $.ui
.dialog
.overlay
.resize();
5595 // adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
5596 if (self
.options
.modal
) {
5598 $('.ui-dialog').each(function() {
5599 if (this !== self
.uiDialog
[0]) {
5600 maxZ
= Math
.max(maxZ
, $(this).css('z-index'));
5603 $.ui
.dialog
.maxZ
= maxZ
;
5609 isOpen: function() {
5610 return this._isOpen
;
5613 // the force parameter allows us to move modal dialogs to their correct
5615 moveToTop: function(force
, event
) {
5617 options
= self
.options
,
5620 if ((options
.modal
&& !force
) ||
5621 (!options
.stack
&& !options
.modal
)) {
5622 return self
._trigger('focus', event
);
5625 if (options
.zIndex
> $.ui
.dialog
.maxZ
) {
5626 $.ui
.dialog
.maxZ
= options
.zIndex
;
5629 $.ui
.dialog
.maxZ
+= 1;
5630 self
.overlay
.$el
.css('z-index', $.ui
.dialog
.overlay
.maxZ
= $.ui
.dialog
.maxZ
);
5633 //Save and then restore scroll since Opera 9.5+ resets when parent z-Index is changed.
5634 // http://ui.jquery.com/bugs/ticket/3193
5635 saveScroll
= { scrollTop
: self
.element
.attr('scrollTop'), scrollLeft
: self
.element
.attr('scrollLeft') };
5636 $.ui
.dialog
.maxZ
+= 1;
5637 self
.uiDialog
.css('z-index', $.ui
.dialog
.maxZ
);
5638 self
.element
.attr(saveScroll
);
5639 self
._trigger('focus', event
);
5645 if (this._isOpen
) { return; }
5648 options
= self
.options
,
5649 uiDialog
= self
.uiDialog
;
5651 self
.overlay
= options
.modal
? new $.ui
.dialog
.overlay(self
) : null;
5652 if (uiDialog
.next().length
) {
5653 uiDialog
.appendTo('body');
5656 self
._position(options
.position
);
5657 uiDialog
.show(options
.show
);
5658 self
.moveToTop(true);
5660 // prevent tabbing out of modal dialogs
5661 if (options
.modal
) {
5662 uiDialog
.bind('keypress.ui-dialog', function(event
) {
5663 if (event
.keyCode
!== $.ui
.keyCode
.TAB
) {
5667 var tabbables
= $(':tabbable', this),
5668 first
= tabbables
.filter(':first'),
5669 last
= tabbables
.filter(':last');
5671 if (event
.target
=== last
[0] && !event
.shiftKey
) {
5674 } else if (event
.target
=== first
[0] && event
.shiftKey
) {
5681 // set focus to the first tabbable element in the content area or the first button
5682 // if there are no tabbable elements, set focus on the dialog itself
5684 .add(uiDialog
.find('.ui-dialog-content :tabbable:first'))
5685 .add(uiDialog
.find('.ui-dialog-buttonpane :tabbable:first'))
5690 self
._trigger('open');
5691 self
._isOpen
= true;
5696 _createButtons: function(buttons
) {
5699 uiDialogButtonPane
= $('<div></div>')
5701 'ui-dialog-buttonpane ' +
5702 'ui-widget-content ' +
5703 'ui-helper-clearfix'
5706 // if we already have a button pane, remove it
5707 self
.uiDialog
.find('.ui-dialog-buttonpane').remove();
5709 if (typeof buttons
=== 'object' && buttons
!== null) {
5710 $.each(buttons
, function() {
5711 return !(hasButtons
= true);
5715 $.each(buttons
, function(name
, fn
) {
5716 var button
= $('<button type="button"></button>')
5718 .click(function() { fn
.apply(self
.element
[0], arguments
); })
5719 .appendTo(uiDialogButtonPane
);
5724 uiDialogButtonPane
.appendTo(self
.uiDialog
);
5728 _makeDraggable: function() {
5730 options
= self
.options
,
5734 function filteredUi(ui
) {
5736 position
: ui
.position
,
5741 self
.uiDialog
.draggable({
5742 cancel
: '.ui-dialog-content, .ui-dialog-titlebar-close',
5743 handle
: '.ui-dialog-titlebar',
5744 containment
: 'document',
5745 start: function(event
, ui
) {
5746 heightBeforeDrag
= options
.height
=== "auto" ? "auto" : $(this).height();
5747 $(this).height($(this).height()).addClass("ui-dialog-dragging");
5748 self
._trigger('dragStart', event
, filteredUi(ui
));
5750 drag: function(event
, ui
) {
5751 self
._trigger('drag', event
, filteredUi(ui
));
5753 stop: function(event
, ui
) {
5754 options
.position
= [ui
.position
.left
- doc
.scrollLeft(),
5755 ui
.position
.top
- doc
.scrollTop()];
5756 $(this).removeClass("ui-dialog-dragging").height(heightBeforeDrag
);
5757 self
._trigger('dragStop', event
, filteredUi(ui
));
5758 $.ui
.dialog
.overlay
.resize();
5763 _makeResizable: function(handles
) {
5764 handles
= (handles
=== undefined ? this.options
.resizable
: handles
);
5766 options
= self
.options
,
5767 // .ui-resizable has position: relative defined in the stylesheet
5768 // but dialogs have to use absolute or fixed positioning
5769 position
= self
.uiDialog
.css('position'),
5770 resizeHandles
= (typeof handles
=== 'string' ?
5772 'n,e,s,w,se,sw,ne,nw'
5775 function filteredUi(ui
) {
5777 originalPosition
: ui
.originalPosition
,
5778 originalSize
: ui
.originalSize
,
5779 position
: ui
.position
,
5784 self
.uiDialog
.resizable({
5785 cancel
: '.ui-dialog-content',
5786 containment
: 'document',
5787 alsoResize
: self
.element
,
5788 maxWidth
: options
.maxWidth
,
5789 maxHeight
: options
.maxHeight
,
5790 minWidth
: options
.minWidth
,
5791 minHeight
: self
._minHeight(),
5792 handles
: resizeHandles
,
5793 start: function(event
, ui
) {
5794 $(this).addClass("ui-dialog-resizing");
5795 self
._trigger('resizeStart', event
, filteredUi(ui
));
5797 resize: function(event
, ui
) {
5798 self
._trigger('resize', event
, filteredUi(ui
));
5800 stop: function(event
, ui
) {
5801 $(this).removeClass("ui-dialog-resizing");
5802 options
.height
= $(this).height();
5803 options
.width
= $(this).width();
5804 self
._trigger('resizeStop', event
, filteredUi(ui
));
5805 $.ui
.dialog
.overlay
.resize();
5808 .css('position', position
)
5809 .find('.ui-resizable-se').addClass('ui-icon ui-icon-grip-diagonal-se');
5812 _minHeight: function() {
5813 var options
= this.options
;
5815 if (options
.height
=== 'auto') {
5816 return options
.minHeight
;
5818 return Math
.min(options
.minHeight
, options
.height
);
5822 _position: function(position
) {
5827 position
= position
|| $.ui
.dialog
.prototype.options
.position
;
5829 // deep extending converts arrays to objects in jQuery <= 1.3.2 :-(
5830 // if (typeof position == 'string' || $.isArray(position)) {
5831 // myAt = $.isArray(position) ? position : position.split(' ');
5833 if (typeof position
=== 'string' || (typeof position
=== 'object' && '0' in position
)) {
5834 myAt
= position
.split
? position
.split(' ') : [position
[0], position
[1]];
5835 if (myAt
.length
=== 1) {
5839 $.each(['left', 'top'], function(i
, offsetPosition
) {
5840 if (+myAt
[i
] === myAt
[i
]) {
5841 offset
[i
] = myAt
[i
];
5842 myAt
[i
] = offsetPosition
;
5845 } else if (typeof position
=== 'object') {
5846 if ('left' in position
) {
5848 offset
[0] = position
.left
;
5849 } else if ('right' in position
) {
5851 offset
[0] = -position
.right
;
5854 if ('top' in position
) {
5856 offset
[1] = position
.top
;
5857 } else if ('bottom' in position
) {
5859 offset
[1] = -position
.bottom
;
5863 // need to show the dialog to get the actual offset in the position plugin
5864 isVisible
= this.uiDialog
.is(':visible');
5866 this.uiDialog
.show();
5869 // workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
5870 .css({ top
: 0, left
: 0 })
5874 offset
: offset
.join(' '),
5877 // ensure that the titlebar is never outside the document
5878 using: function(pos
) {
5879 var topOffset
= $(this).css(pos
).offset().top
;
5880 if (topOffset
< 0) {
5881 $(this).css('top', pos
.top
- topOffset
);
5886 this.uiDialog
.hide();
5890 _setOption: function(key
, value
){
5892 uiDialog
= self
.uiDialog
,
5893 isResizable
= uiDialog
.is(':data(resizable)'),
5897 //handling of deprecated beforeclose (vs beforeClose) option
5898 //Ticket #4669 http://dev.jqueryui.com/ticket/4669
5899 //TODO: remove in 1.9pre
5901 key
= "beforeClose";
5904 self
._createButtons(value
);
5907 // convert whatever was passed in to a string, for text() to not throw up
5908 self
.uiDialogTitlebarCloseText
.text("" + value
);
5912 .removeClass(self
.options
.dialogClass
)
5913 .addClass(uiDialogClasses
+ value
);
5917 uiDialog
.addClass('ui-dialog-disabled');
5919 uiDialog
.removeClass('ui-dialog-disabled');
5924 self
._makeDraggable();
5926 uiDialog
.draggable('destroy');
5934 uiDialog
.resizable('option', 'maxHeight', value
);
5940 uiDialog
.resizable('option', 'maxWidth', value
);
5946 uiDialog
.resizable('option', 'minHeight', value
);
5952 uiDialog
.resizable('option', 'minWidth', value
);
5957 self
._position(value
);
5960 // currently resizable, becoming non-resizable
5961 if (isResizable
&& !value
) {
5962 uiDialog
.resizable('destroy');
5965 // currently resizable, changing handles
5966 if (isResizable
&& typeof value
=== 'string') {
5967 uiDialog
.resizable('option', 'handles', value
);
5970 // currently non-resizable, becoming resizable
5971 if (!isResizable
&& value
!== false) {
5972 self
._makeResizable(value
);
5976 // convert whatever was passed in o a string, for html() to not throw up
5977 $(".ui-dialog-title", self
.uiDialogTitlebar
).html("" + (value
|| ' '));
5984 $.Widget
.prototype._setOption
.apply(self
, arguments
);
5991 /* If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
5992 * divs will both have width and height set, so we need to reset them
5994 var options
= this.options
,
5997 // reset content sizing
5998 // hide for non content measurement because height: 0 doesn't work in IE quirks mode (see #4350)
5999 this.element
.css('width', 'auto')
6002 // reset wrapper sizing
6003 // determine the height of all the non-content elements
6004 nonContentHeight
= this.uiDialog
.css({
6006 width
: options
.width
6011 .css(options
.height
=== 'auto' ? {
6012 minHeight
: Math
.max(options
.minHeight
- nonContentHeight
, 0),
6016 height
: Math
.max(options
.height
- nonContentHeight
, 0)
6020 if (this.uiDialog
.is(':data(resizable)')) {
6021 this.uiDialog
.resizable('option', 'minHeight', this._minHeight());
6026 $.extend($.ui
.dialog
, {
6032 getTitleId: function($el
) {
6033 var id
= $el
.attr('id');
6038 return 'ui-dialog-title-' + id
;
6041 overlay: function(dialog
) {
6042 this.$el
= $.ui
.dialog
.overlay
.create(dialog
);
6046 $.extend($.ui
.dialog
.overlay
, {
6048 // reuse old instances due to IE memory leak with alpha transparency (see #5185)
6051 events
: $.map('focus,mousedown,mouseup,keydown,keypress,click'.split(','),
6052 function(event
) { return event
+ '.dialog-overlay'; }).join(' '),
6053 create: function(dialog
) {
6054 if (this.instances
.length
=== 0) {
6055 // prevent use of anchors and inputs
6056 // we use a setTimeout in case the overlay is created from an
6057 // event that we're going to be cancelling (see #2804)
6058 setTimeout(function() {
6059 // handle $(el).dialog().dialog('close') (see #4065)
6060 if ($.ui
.dialog
.overlay
.instances
.length
) {
6061 $(document
).bind($.ui
.dialog
.overlay
.events
, function(event
) {
6062 // stop events if the z-index of the target is < the z-index of the overlay
6063 return ($(event
.target
).zIndex() >= $.ui
.dialog
.overlay
.maxZ
);
6068 // allow closing by pressing the escape key
6069 $(document
).bind('keydown.dialog-overlay', function(event
) {
6070 if (dialog
.options
.closeOnEscape
&& event
.keyCode
&&
6071 event
.keyCode
=== $.ui
.keyCode
.ESCAPE
) {
6073 dialog
.close(event
);
6074 event
.preventDefault();
6078 // handle window resize
6079 $(window
).bind('resize.dialog-overlay', $.ui
.dialog
.overlay
.resize
);
6082 var $el
= (this.oldInstances
.pop() || $('<div></div>').addClass('ui-widget-overlay'))
6083 .appendTo(document
.body
)
6085 width
: this.width(),
6086 height
: this.height()
6089 if ($.fn
.bgiframe
) {
6093 this.instances
.push($el
);
6097 destroy: function($el
) {
6098 this.oldInstances
.push(this.instances
.splice($.inArray($el
, this.instances
), 1)[0]);
6100 if (this.instances
.length
=== 0) {
6101 $([document
, window
]).unbind('.dialog-overlay');
6106 // adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
6108 $.each(this.instances
, function() {
6109 maxZ
= Math
.max(maxZ
, this.css('z-index'));
6114 height: function() {
6118 if ($.browser
.msie
&& $.browser
.version
< 7) {
6119 scrollHeight
= Math
.max(
6120 document
.documentElement
.scrollHeight
,
6121 document
.body
.scrollHeight
6123 offsetHeight
= Math
.max(
6124 document
.documentElement
.offsetHeight
,
6125 document
.body
.offsetHeight
6128 if (scrollHeight
< offsetHeight
) {
6129 return $(window
).height() + 'px';
6131 return scrollHeight
+ 'px';
6133 // handle "good" browsers
6135 return $(document
).height() + 'px';
6143 if ($.browser
.msie
&& $.browser
.version
< 7) {
6144 scrollWidth
= Math
.max(
6145 document
.documentElement
.scrollWidth
,
6146 document
.body
.scrollWidth
6148 offsetWidth
= Math
.max(
6149 document
.documentElement
.offsetWidth
,
6150 document
.body
.offsetWidth
6153 if (scrollWidth
< offsetWidth
) {
6154 return $(window
).width() + 'px';
6156 return scrollWidth
+ 'px';
6158 // handle "good" browsers
6160 return $(document
).width() + 'px';
6164 resize: function() {
6165 /* If the dialog is draggable and the user drags it past the
6166 * right edge of the window, the document becomes wider so we
6167 * need to stretch the overlay. If the user then drags the
6168 * dialog back to the left, the document will become narrower,
6169 * so we need to shrink the overlay to the appropriate size.
6170 * This is handled by shrinking the overlay before setting it
6171 * to the full document size.
6173 var $overlays
= $([]);
6174 $.each($.ui
.dialog
.overlay
.instances
, function() {
6175 $overlays
= $overlays
.add(this);
6182 width
: $.ui
.dialog
.overlay
.width(),
6183 height
: $.ui
.dialog
.overlay
.height()
6188 $.extend($.ui
.dialog
.overlay
.prototype, {
6189 destroy: function() {
6190 $.ui
.dialog
.overlay
.destroy(this.$el
);
6196 * jQuery UI Slider 1.8
6198 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
6199 * Dual licensed under the MIT (MIT-LICENSE.txt)
6200 * and GPL (GPL-LICENSE.txt) licenses.
6202 * http://docs.jquery.com/UI/Slider
6206 * jquery.ui.mouse.js
6207 * jquery.ui.widget.js
6212 // number of pages in a slider
6213 // (how many times can you page up/down to go through the whole range)
6216 $.widget("ui.slider", $.ui
.mouse
, {
6217 widgetEventPrefix
: "slide",
6223 orientation
: 'horizontal',
6229 _create: function() {
6231 var self
= this, o
= this.options
;
6232 this._keySliding
= false;
6233 this._mouseSliding
= false;
6234 this._animateOff
= true;
6235 this._handleIndex
= null;
6236 this._detectOrientation();
6240 .addClass("ui-slider"
6241 + " ui-slider-" + this.orientation
6243 + " ui-widget-content"
6244 + " ui-corner-all");
6247 this.element
.addClass('ui-slider-disabled ui-disabled');
6254 if (o
.range
=== true) {
6255 this.range
= $('<div></div>');
6256 if (!o
.values
) o
.values
= [this._valueMin(), this._valueMin()];
6257 if (o
.values
.length
&& o
.values
.length
!= 2) {
6258 o
.values
= [o
.values
[0], o
.values
[0]];
6261 this.range
= $('<div></div>');
6265 .appendTo(this.element
)
6266 .addClass("ui-slider-range");
6268 if (o
.range
== "min" || o
.range
== "max") {
6269 this.range
.addClass("ui-slider-range-" + o
.range
);
6272 // note: this isn't the most fittingly semantic framework class for this element,
6273 // but worked best visually with a variety of themes
6274 this.range
.addClass("ui-widget-header");
6278 if ($(".ui-slider-handle", this.element
).length
== 0)
6279 $('<a href="#"></a>')
6280 .appendTo(this.element
)
6281 .addClass("ui-slider-handle");
6283 if (o
.values
&& o
.values
.length
) {
6284 while ($(".ui-slider-handle", this.element
).length
< o
.values
.length
)
6285 $('<a href="#"></a>')
6286 .appendTo(this.element
)
6287 .addClass("ui-slider-handle");
6290 this.handles
= $(".ui-slider-handle", this.element
)
6291 .addClass("ui-state-default"
6292 + " ui-corner-all");
6294 this.handle
= this.handles
.eq(0);
6296 this.handles
.add(this.range
).filter("a")
6297 .click(function(event
) {
6298 event
.preventDefault();
6302 $(this).addClass('ui-state-hover');
6305 $(this).removeClass('ui-state-hover');
6309 $(".ui-slider .ui-state-focus").removeClass('ui-state-focus'); $(this).addClass('ui-state-focus');
6315 $(this).removeClass('ui-state-focus');
6318 this.handles
.each(function(i
) {
6319 $(this).data("index.ui-slider-handle", i
);
6322 this.handles
.keydown(function(event
) {
6326 var index
= $(this).data("index.ui-slider-handle");
6328 if (self
.options
.disabled
)
6331 switch (event
.keyCode
) {
6332 case $.ui
.keyCode
.HOME
:
6333 case $.ui
.keyCode
.END
:
6334 case $.ui
.keyCode
.PAGE_UP
:
6335 case $.ui
.keyCode
.PAGE_DOWN
:
6336 case $.ui
.keyCode
.UP
:
6337 case $.ui
.keyCode
.RIGHT
:
6338 case $.ui
.keyCode
.DOWN
:
6339 case $.ui
.keyCode
.LEFT
:
6341 if (!self
._keySliding
) {
6342 self
._keySliding
= true;
6343 $(this).addClass("ui-state-active");
6344 self
._start(event
, index
);
6349 var curVal
, newVal
, step
= self
._step();
6350 if (self
.options
.values
&& self
.options
.values
.length
) {
6351 curVal
= newVal
= self
.values(index
);
6353 curVal
= newVal
= self
.value();
6356 switch (event
.keyCode
) {
6357 case $.ui
.keyCode
.HOME
:
6358 newVal
= self
._valueMin();
6360 case $.ui
.keyCode
.END
:
6361 newVal
= self
._valueMax();
6363 case $.ui
.keyCode
.PAGE_UP
:
6364 newVal
= curVal
+ ((self
._valueMax() - self
._valueMin()) / numPages
);
6366 case $.ui
.keyCode
.PAGE_DOWN
:
6367 newVal
= curVal
- ((self
._valueMax() - self
._valueMin()) / numPages
);
6369 case $.ui
.keyCode
.UP
:
6370 case $.ui
.keyCode
.RIGHT
:
6371 if(curVal
== self
._valueMax()) return;
6372 newVal
= curVal
+ step
;
6374 case $.ui
.keyCode
.DOWN
:
6375 case $.ui
.keyCode
.LEFT
:
6376 if(curVal
== self
._valueMin()) return;
6377 newVal
= curVal
- step
;
6381 self
._slide(event
, index
, newVal
);
6385 }).keyup(function(event
) {
6387 var index
= $(this).data("index.ui-slider-handle");
6389 if (self
._keySliding
) {
6390 self
._keySliding
= false;
6391 self
._stop(event
, index
);
6392 self
._change(event
, index
);
6393 $(this).removeClass("ui-state-active");
6398 this._refreshValue();
6400 this._animateOff
= false;
6404 destroy: function() {
6406 this.handles
.remove();
6407 this.range
.remove();
6410 .removeClass("ui-slider"
6411 + " ui-slider-horizontal"
6412 + " ui-slider-vertical"
6413 + " ui-slider-disabled"
6415 + " ui-widget-content"
6417 .removeData("slider")
6420 this._mouseDestroy();
6425 _mouseCapture: function(event
) {
6427 var o
= this.options
;
6432 this.elementSize
= {
6433 width
: this.element
.outerWidth(),
6434 height
: this.element
.outerHeight()
6436 this.elementOffset
= this.element
.offset();
6438 var position
= { x
: event
.pageX
, y
: event
.pageY
};
6439 var normValue
= this._normValueFromMouse(position
);
6441 var distance
= this._valueMax() - this._valueMin() + 1, closestHandle
;
6442 var self
= this, index
;
6443 this.handles
.each(function(i
) {
6444 var thisDistance
= Math
.abs(normValue
- self
.values(i
));
6445 if (distance
> thisDistance
) {
6446 distance
= thisDistance
;
6447 closestHandle
= $(this);
6452 // workaround for bug #3736 (if both handles of a range are at 0,
6453 // the first is always used as the one with least distance,
6454 // and moving it is obviously prevented by preventing negative ranges)
6455 if(o
.range
== true && this.values(1) == o
.min
) {
6456 closestHandle
= $(this.handles
[++index
]);
6459 this._start(event
, index
);
6460 this._mouseSliding
= true;
6462 self
._handleIndex
= index
;
6465 .addClass("ui-state-active")
6468 var offset
= closestHandle
.offset();
6469 var mouseOverHandle
= !$(event
.target
).parents().andSelf().is('.ui-slider-handle');
6470 this._clickOffset
= mouseOverHandle
? { left
: 0, top
: 0 } : {
6471 left
: event
.pageX
- offset
.left
- (closestHandle
.width() / 2),
6472 top
: event
.pageY
- offset
.top
6473 - (closestHandle
.height() / 2)
6474 - (parseInt(closestHandle
.css('borderTopWidth'),10) || 0)
6475 - (parseInt(closestHandle
.css('borderBottomWidth'),10) || 0)
6476 + (parseInt(closestHandle
.css('marginTop'),10) || 0)
6479 normValue
= this._normValueFromMouse(position
);
6480 this._slide(event
, index
, normValue
);
6481 this._animateOff
= true;
6486 _mouseStart: function(event
) {
6490 _mouseDrag: function(event
) {
6492 var position
= { x
: event
.pageX
, y
: event
.pageY
};
6493 var normValue
= this._normValueFromMouse(position
);
6495 this._slide(event
, this._handleIndex
, normValue
);
6501 _mouseStop: function(event
) {
6503 this.handles
.removeClass("ui-state-active");
6504 this._mouseSliding
= false;
6505 this._stop(event
, this._handleIndex
);
6506 this._change(event
, this._handleIndex
);
6507 this._handleIndex
= null;
6508 this._clickOffset
= null;
6510 this._animateOff
= false;
6515 _detectOrientation: function() {
6516 this.orientation
= this.options
.orientation
== 'vertical' ? 'vertical' : 'horizontal';
6519 _normValueFromMouse: function(position
) {
6521 var pixelTotal
, pixelMouse
;
6522 if ('horizontal' == this.orientation
) {
6523 pixelTotal
= this.elementSize
.width
;
6524 pixelMouse
= position
.x
- this.elementOffset
.left
- (this._clickOffset
? this._clickOffset
.left
: 0);
6526 pixelTotal
= this.elementSize
.height
;
6527 pixelMouse
= position
.y
- this.elementOffset
.top
- (this._clickOffset
? this._clickOffset
.top
: 0);
6530 var percentMouse
= (pixelMouse
/ pixelTotal
);
6531 if (percentMouse
> 1) percentMouse
= 1;
6532 if (percentMouse
< 0) percentMouse
= 0;
6533 if ('vertical' == this.orientation
)
6534 percentMouse
= 1 - percentMouse
;
6536 var valueTotal
= this._valueMax() - this._valueMin(),
6537 valueMouse
= percentMouse
* valueTotal
,
6538 valueMouseModStep
= valueMouse
% this.options
.step
,
6539 normValue
= this._valueMin() + valueMouse
- valueMouseModStep
;
6541 if (valueMouseModStep
> (this.options
.step
/ 2))
6542 normValue
+= this.options
.step
;
6544 // Since JavaScript has problems with large floats, round
6545 // the final value to 5 digits after the decimal point (see #4124)
6546 return parseFloat(normValue
.toFixed(5));
6550 _start: function(event
, index
) {
6552 handle
: this.handles
[index
],
6555 if (this.options
.values
&& this.options
.values
.length
) {
6556 uiHash
.value
= this.values(index
);
6557 uiHash
.values
= this.values();
6559 this._trigger("start", event
, uiHash
);
6562 _slide: function(event
, index
, newVal
) {
6564 var handle
= this.handles
[index
];
6566 if (this.options
.values
&& this.options
.values
.length
) {
6568 var otherVal
= this.values(index
? 0 : 1);
6570 if ((this.options
.values
.length
== 2 && this.options
.range
=== true) &&
6571 ((index
== 0 && newVal
> otherVal
) || (index
== 1 && newVal
< otherVal
))){
6575 if (newVal
!= this.values(index
)) {
6576 var newValues
= this.values();
6577 newValues
[index
] = newVal
;
6578 // A slide can be canceled by returning false from the slide callback
6579 var allowed
= this._trigger("slide", event
, {
6580 handle
: this.handles
[index
],
6584 var otherVal
= this.values(index
? 0 : 1);
6585 if (allowed
!== false) {
6586 this.values(index
, newVal
, true);
6592 if (newVal
!= this.value()) {
6593 // A slide can be canceled by returning false from the slide callback
6594 var allowed
= this._trigger("slide", event
, {
6595 handle
: this.handles
[index
],
6598 if (allowed
!== false) {
6608 _stop: function(event
, index
) {
6610 handle
: this.handles
[index
],
6613 if (this.options
.values
&& this.options
.values
.length
) {
6614 uiHash
.value
= this.values(index
);
6615 uiHash
.values
= this.values();
6617 this._trigger("stop", event
, uiHash
);
6620 _change: function(event
, index
) {
6621 if (!this._keySliding
&& !this._mouseSliding
) {
6623 handle
: this.handles
[index
],
6626 if (this.options
.values
&& this.options
.values
.length
) {
6627 uiHash
.value
= this.values(index
);
6628 uiHash
.values
= this.values();
6630 this._trigger("change", event
, uiHash
);
6634 value: function(newValue
) {
6636 if (arguments
.length
) {
6637 this.options
.value
= this._trimValue(newValue
);
6638 this._refreshValue();
6639 this._change(null, 0);
6642 return this._value();
6646 values: function(index
, newValue
) {
6648 if (arguments
.length
> 1) {
6649 this.options
.values
[index
] = this._trimValue(newValue
);
6650 this._refreshValue();
6651 this._change(null, index
);
6654 if (arguments
.length
) {
6655 if ($.isArray(arguments
[0])) {
6656 var vals
= this.options
.values
, newValues
= arguments
[0];
6657 for (var i
= 0, l
= vals
.length
; i
< l
; i
++) {
6658 vals
[i
] = this._trimValue(newValues
[i
]);
6659 this._change(null, i
);
6661 this._refreshValue();
6663 if (this.options
.values
&& this.options
.values
.length
) {
6664 return this._values(index
);
6666 return this.value();
6670 return this._values();
6675 _setOption: function(key
, value
) {
6679 if ( jQuery
.isArray(this.options
.values
) ) {
6680 valsLength
= this.options
.values
.length
;
6683 $.Widget
.prototype._setOption
.apply(this, arguments
);
6688 this.handles
.filter(".ui-state-focus").blur();
6689 this.handles
.removeClass("ui-state-hover");
6690 this.handles
.attr("disabled", "disabled");
6691 this.element
.addClass("ui-disabled");
6693 this.handles
.removeAttr("disabled");
6694 this.element
.removeClass("ui-disabled");
6698 this._detectOrientation();
6701 .removeClass("ui-slider-horizontal ui-slider-vertical")
6702 .addClass("ui-slider-" + this.orientation
);
6703 this._refreshValue();
6706 this._animateOff
= true;
6707 this._refreshValue();
6708 this._change(null, 0);
6709 this._animateOff
= false;
6712 this._animateOff
= true;
6713 this._refreshValue();
6714 for (i
= 0; i
< valsLength
; i
++) {
6715 this._change(null, i
);
6717 this._animateOff
= false;
6724 var step
= this.options
.step
;
6728 _value: function() {
6729 //internal value getter
6730 // _value() returns value trimmed by min and max
6731 var val
= this.options
.value
;
6732 val
= this._trimValue(val
);
6737 _values: function(index
) {
6738 //internal values getter
6739 // _values() returns array of values trimmed by min and max
6740 // _values(index) returns single value trimmed by min and max
6742 if (arguments
.length
) {
6743 var val
= this.options
.values
[index
];
6744 val
= this._trimValue(val
);
6748 // .slice() creates a copy of the array
6749 // this copy gets trimmed by min and max and then returned
6750 var vals
= this.options
.values
.slice();
6751 for (var i
= 0, l
= vals
.length
; i
< l
; i
++) {
6752 vals
[i
] = this._trimValue(vals
[i
]);
6760 _trimValue: function(val
) {
6761 if (val
< this._valueMin()) val
= this._valueMin();
6762 if (val
> this._valueMax()) val
= this._valueMax();
6767 _valueMin: function() {
6768 var valueMin
= this.options
.min
;
6772 _valueMax: function() {
6773 var valueMax
= this.options
.max
;
6777 _refreshValue: function() {
6779 var oRange
= this.options
.range
, o
= this.options
, self
= this;
6780 var animate
= (!this._animateOff
) ? o
.animate
: false;
6782 if (this.options
.values
&& this.options
.values
.length
) {
6784 this.handles
.each(function(i
, j
) {
6785 var valPercent
= (self
.values(i
) - self
._valueMin()) / (self
._valueMax() - self
._valueMin()) * 100;
6786 var _set
= {}; _set
[self
.orientation
== 'horizontal' ? 'left' : 'bottom'] = valPercent
+ '%';
6787 $(this).stop(1,1)[animate
? 'animate' : 'css'](_set
, o
.animate
);
6788 if (self
.options
.range
=== true) {
6789 if (self
.orientation
== 'horizontal') {
6790 (i
== 0) && self
.range
.stop(1,1)[animate
? 'animate' : 'css']({ left
: valPercent
+ '%' }, o
.animate
);
6791 (i
== 1) && self
.range
[animate
? 'animate' : 'css']({ width
: (valPercent
- lastValPercent
) + '%' }, { queue
: false, duration
: o
.animate
});
6793 (i
== 0) && self
.range
.stop(1,1)[animate
? 'animate' : 'css']({ bottom
: (valPercent
) + '%' }, o
.animate
);
6794 (i
== 1) && self
.range
[animate
? 'animate' : 'css']({ height
: (valPercent
- lastValPercent
) + '%' }, { queue
: false, duration
: o
.animate
});
6797 lastValPercent
= valPercent
;
6800 var value
= this.value(),
6801 valueMin
= this._valueMin(),
6802 valueMax
= this._valueMax(),
6803 valPercent
= valueMax
!= valueMin
6804 ? (value
- valueMin
) / (valueMax
- valueMin
) * 100
6806 var _set
= {}; _set
[self
.orientation
== 'horizontal' ? 'left' : 'bottom'] = valPercent
+ '%';
6807 this.handle
.stop(1,1)[animate
? 'animate' : 'css'](_set
, o
.animate
);
6809 (oRange
== "min") && (this.orientation
== "horizontal") && this.range
.stop(1,1)[animate
? 'animate' : 'css']({ width
: valPercent
+ '%' }, o
.animate
);
6810 (oRange
== "max") && (this.orientation
== "horizontal") && this.range
[animate
? 'animate' : 'css']({ width
: (100 - valPercent
) + '%' }, { queue
: false, duration
: o
.animate
});
6811 (oRange
== "min") && (this.orientation
== "vertical") && this.range
.stop(1,1)[animate
? 'animate' : 'css']({ height
: valPercent
+ '%' }, o
.animate
);
6812 (oRange
== "max") && (this.orientation
== "vertical") && this.range
[animate
? 'animate' : 'css']({ height
: (100 - valPercent
) + '%' }, { queue
: false, duration
: o
.animate
});
6819 $.extend($.ui
.slider
, {
6825 * jQuery UI Tabs 1.8
6827 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
6828 * Dual licensed under the MIT (MIT-LICENSE.txt)
6829 * and GPL (GPL-LICENSE.txt) licenses.
6831 * http://docs.jquery.com/UI/Tabs
6835 * jquery.ui.widget.js
6842 $.widget("ui.tabs", {
6847 cookie
: null, // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true }
6853 fx
: null, // e.g. { height: 'toggle', opacity: 'toggle', duration: 200 }
6854 idPrefix
: 'ui-tabs-',
6856 panelTemplate
: '<div></div>',
6860 spinner
: '<em>Loading…</em>',
6861 tabTemplate
: '<li><a href="#{href}"><span>#{label}</span></a></li>'
6863 _create: function() {
6867 _setOption: function(key
, value
) {
6868 if (key
== 'selected') {
6869 if (this.options
.collapsible
&& value
== this.options
.selected
) {
6875 this.options
[key
] = value
;
6880 _tabId: function(a
) {
6881 return a
.title
&& a
.title
.replace(/\s/g, '_').replace(/[^A-Za-z0-9\-_:\.]/g, '') ||
6882 this.options
.idPrefix
+ (++tabId
);
6885 _sanitizeSelector: function(hash
) {
6886 return hash
.replace(/:/g, '\\:'); // we need
this because an id may contain a
":"
6889 _cookie: function() {
6890 var cookie
= this.cookie
|| (this.cookie
= this.options
.cookie
.name
|| 'ui-tabs-' + (++listId
));
6891 return $.cookie
.apply(null, [cookie
].concat($.makeArray(arguments
)));
6894 _ui: function(tab
, panel
) {
6898 index
: this.anchors
.index(tab
)
6902 _cleanup: function() {
6903 // restore all former loading tabs labels
6904 this.lis
.filter('.ui-state-processing').removeClass('ui-state-processing')
6905 .find('span:data(label.tabs)')
6908 el
.html(el
.data('label.tabs')).removeData('label.tabs');
6912 _tabify: function(init
) {
6914 this.list
= this.element
.find('ol,ul').eq(0);
6915 this.lis
= $('li:has(a[href])', this.list
);
6916 this.anchors
= this.lis
.map(function() { return $('a', this)[0]; });
6917 this.panels
= $([]);
6919 var self
= this, o
= this.options
;
6921 var fragmentId
= /^#.+/; // Safari 2 reports '#' for an empty hash
6922 this.anchors
.each(function(i
, a
) {
6923 var href
= $(a
).attr('href');
6925 // For dynamically created HTML that contains a hash as href IE < 8 expands
6926 // such href to the full page url with hash and then misinterprets tab as ajax.
6927 // Same consideration applies for an added tab with a fragment identifier
6928 // since a[href=#fragment-identifier] does unexpectedly not match.
6929 // Thus normalize href attribute...
6930 var hrefBase
= href
.split('#')[0], baseEl
;
6931 if (hrefBase
&& (hrefBase
=== location
.toString().split('#')[0] ||
6932 (baseEl
= $('base')[0]) && hrefBase
=== baseEl
.href
)) {
6938 if (fragmentId
.test(href
)) {
6939 self
.panels
= self
.panels
.add(self
._sanitizeSelector(href
));
6943 else if (href
!= '#') { // prevent loading the page itself if href is just "#"
6944 $.data(a
, 'href.tabs', href
); // required for restore on destroy
6946 // TODO until #3808 is fixed strip fragment identifier from url
6947 // (IE fails to load from such url)
6948 $.data(a
, 'load.tabs', href
.replace(/#.*$/, '')); // mutable data
6950 var id
= self
._tabId(a
);
6952 var $panel
= $('#' + id
);
6953 if (!$panel
.length
) {
6954 $panel
= $(o
.panelTemplate
).attr('id', id
).addClass('ui-tabs-panel ui-widget-content ui-corner-bottom')
6955 .insertAfter(self
.panels
[i
- 1] || self
.list
);
6956 $panel
.data('destroy.tabs', true);
6958 self
.panels
= self
.panels
.add($panel
);
6967 // initialization from scratch
6970 // attach necessary classes for styling
6971 this.element
.addClass('ui-tabs ui-widget ui-widget-content ui-corner-all');
6972 this.list
.addClass('ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all');
6973 this.lis
.addClass('ui-state-default ui-corner-top');
6974 this.panels
.addClass('ui-tabs-panel ui-widget-content ui-corner-bottom');
6977 // use "selected" option or try to retrieve:
6978 // 1. from fragment identifier in url
6980 // 3. from selected class attribute on <li>
6981 if (o
.selected
=== undefined) {
6982 if (location
.hash
) {
6983 this.anchors
.each(function(i
, a
) {
6984 if (a
.hash
== location
.hash
) {
6986 return false; // break
6990 if (typeof o
.selected
!= 'number' && o
.cookie
) {
6991 o
.selected
= parseInt(self
._cookie(), 10);
6993 if (typeof o
.selected
!= 'number' && this.lis
.filter('.ui-tabs-selected').length
) {
6994 o
.selected
= this.lis
.index(this.lis
.filter('.ui-tabs-selected'));
6996 o
.selected
= o
.selected
|| (this.lis
.length
? 0 : -1);
6998 else if (o
.selected
=== null) { // usage of null is deprecated, TODO remove in next release
7002 // sanity check - default to first tab...
7003 o
.selected
= ((o
.selected
>= 0 && this.anchors
[o
.selected
]) || o
.selected
< 0) ? o
.selected
: 0;
7005 // Take disabling tabs via class attribute from HTML
7006 // into account and update option properly.
7007 // A selected tab cannot become disabled.
7008 o
.disabled
= $.unique(o
.disabled
.concat(
7009 $.map(this.lis
.filter('.ui-state-disabled'),
7010 function(n
, i
) { return self
.lis
.index(n
); } )
7013 if ($.inArray(o
.selected
, o
.disabled
) != -1) {
7014 o
.disabled
.splice($.inArray(o
.selected
, o
.disabled
), 1);
7017 // highlight selected tab
7018 this.panels
.addClass('ui-tabs-hide');
7019 this.lis
.removeClass('ui-tabs-selected ui-state-active');
7020 if (o
.selected
>= 0 && this.anchors
.length
) { // check for length avoids error when initializing empty list
7021 this.panels
.eq(o
.selected
).removeClass('ui-tabs-hide');
7022 this.lis
.eq(o
.selected
).addClass('ui-tabs-selected ui-state-active');
7024 // seems to be expected behavior that the show callback is fired
7025 self
.element
.queue("tabs", function() {
7026 self
._trigger('show', null, self
._ui(self
.anchors
[o
.selected
], self
.panels
[o
.selected
]));
7029 this.load(o
.selected
);
7032 // clean up to avoid memory leaks in certain versions of IE 6
7033 $(window
).bind('unload', function() {
7034 self
.lis
.add(self
.anchors
).unbind('.tabs');
7035 self
.lis
= self
.anchors
= self
.panels
= null;
7039 // update selected after add/remove
7041 o
.selected
= this.lis
.index(this.lis
.filter('.ui-tabs-selected'));
7044 // update collapsible
7045 this.element
[o
.collapsible
? 'addClass' : 'removeClass']('ui-tabs-collapsible');
7047 // set or update cookie after init and add/remove respectively
7049 this._cookie(o
.selected
, o
.cookie
);
7053 for (var i
= 0, li
; (li
= this.lis
[i
]); i
++) {
7054 $(li
)[$.inArray(i
, o
.disabled
) != -1 &&
7055 !$(li
).hasClass('ui-tabs-selected') ? 'addClass' : 'removeClass']('ui-state-disabled');
7058 // reset cache if switching from cached to not cached
7059 if (o
.cache
=== false) {
7060 this.anchors
.removeData('cache.tabs');
7063 // remove all handlers before, tabify may run on existing tabs after add or option change
7064 this.lis
.add(this.anchors
).unbind('.tabs');
7066 if (o
.event
!= 'mouseover') {
7067 var addState = function(state
, el
) {
7068 if (el
.is(':not(.ui-state-disabled)')) {
7069 el
.addClass('ui-state-' + state
);
7072 var removeState = function(state
, el
) {
7073 el
.removeClass('ui-state-' + state
);
7075 this.lis
.bind('mouseover.tabs', function() {
7076 addState('hover', $(this));
7078 this.lis
.bind('mouseout.tabs', function() {
7079 removeState('hover', $(this));
7081 this.anchors
.bind('focus.tabs', function() {
7082 addState('focus', $(this).closest('li'));
7084 this.anchors
.bind('blur.tabs', function() {
7085 removeState('focus', $(this).closest('li'));
7089 // set up animations
7092 if ($.isArray(o
.fx
)) {
7097 hideFx
= showFx
= o
.fx
;
7101 // Reset certain styles left over from animation
7102 // and prevent IE's ClearType bug...
7103 function resetStyle($el
, fx
) {
7104 $el
.css({ display
: '' });
7105 if (!$.support
.opacity
&& fx
.opacity
) {
7106 $el
[0].style
.removeAttribute('filter');
7111 var showTab
= showFx
?
7112 function(clicked
, $show
) {
7113 $(clicked
).closest('li').addClass('ui-tabs-selected ui-state-active');
7114 $show
.hide().removeClass('ui-tabs-hide') // avoid flicker that way
7115 .animate(showFx
, showFx
.duration
|| 'normal', function() {
7116 resetStyle($show
, showFx
);
7117 self
._trigger('show', null, self
._ui(clicked
, $show
[0]));
7120 function(clicked
, $show
) {
7121 $(clicked
).closest('li').addClass('ui-tabs-selected ui-state-active');
7122 $show
.removeClass('ui-tabs-hide');
7123 self
._trigger('show', null, self
._ui(clicked
, $show
[0]));
7126 // Hide a tab, $show is optional...
7127 var hideTab
= hideFx
?
7128 function(clicked
, $hide
) {
7129 $hide
.animate(hideFx
, hideFx
.duration
|| 'normal', function() {
7130 self
.lis
.removeClass('ui-tabs-selected ui-state-active');
7131 $hide
.addClass('ui-tabs-hide');
7132 resetStyle($hide
, hideFx
);
7133 self
.element
.dequeue("tabs");
7136 function(clicked
, $hide
, $show
) {
7137 self
.lis
.removeClass('ui-tabs-selected ui-state-active');
7138 $hide
.addClass('ui-tabs-hide');
7139 self
.element
.dequeue("tabs");
7142 // attach tab event handler, unbind to avoid duplicates from former tabifying...
7143 this.anchors
.bind(o
.event
+ '.tabs', function() {
7144 var el
= this, $li
= $(this).closest('li'), $hide
= self
.panels
.filter(':not(.ui-tabs-hide)'),
7145 $show
= $(self
._sanitizeSelector(this.hash
));
7147 // If tab is already selected and not collapsible or tab disabled or
7148 // or is already loading or click callback returns false stop here.
7149 // Check if click handler returns false last so that it is not executed
7150 // for a disabled or loading tab!
7151 if (($li
.hasClass('ui-tabs-selected') && !o
.collapsible
) ||
7152 $li
.hasClass('ui-state-disabled') ||
7153 $li
.hasClass('ui-state-processing') ||
7154 self
._trigger('select', null, self
._ui(this, $show
[0])) === false) {
7159 o
.selected
= self
.anchors
.index(this);
7163 // if tab may be closed
7164 if (o
.collapsible
) {
7165 if ($li
.hasClass('ui-tabs-selected')) {
7169 self
._cookie(o
.selected
, o
.cookie
);
7172 self
.element
.queue("tabs", function() {
7179 else if (!$hide
.length
) {
7181 self
._cookie(o
.selected
, o
.cookie
);
7184 self
.element
.queue("tabs", function() {
7188 self
.load(self
.anchors
.index(this)); // TODO make passing in node possible, see also http://dev.jqueryui.com/ticket/3171
7196 self
._cookie(o
.selected
, o
.cookie
);
7202 self
.element
.queue("tabs", function() {
7206 self
.element
.queue("tabs", function() {
7210 self
.load(self
.anchors
.index(this));
7213 throw 'jQuery UI Tabs: Mismatching fragment identifier.';
7216 // Prevent IE from keeping other link focussed when using the back button
7217 // and remove dotted border from clicked link. This is controlled via CSS
7218 // in modern browsers; blur() removes focus from address bar in Firefox
7219 // which can become a usability and annoying problem with tabs('rotate').
7220 if ($.browser
.msie
) {
7226 // disable click in any case
7227 this.anchors
.bind('click.tabs', function(){return false;});
7231 destroy: function() {
7232 var o
= this.options
;
7236 this.element
.unbind('.tabs')
7237 .removeClass('ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible')
7238 .removeData('tabs');
7240 this.list
.removeClass('ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all');
7242 this.anchors
.each(function() {
7243 var href
= $.data(this, 'href.tabs');
7247 var $this = $(this).unbind('.tabs');
7248 $.each(['href', 'load', 'cache'], function(i
, prefix
) {
7249 $this.removeData(prefix
+ '.tabs');
7253 this.lis
.unbind('.tabs').add(this.panels
).each(function() {
7254 if ($.data(this, 'destroy.tabs')) {
7258 $(this).removeClass([
7265 'ui-state-disabled',
7267 'ui-widget-content',
7275 this._cookie(null, o
.cookie
);
7281 add: function(url
, label
, index
) {
7282 if (index
=== undefined) {
7283 index
= this.anchors
.length
; // append by default
7286 var self
= this, o
= this.options
,
7287 $li
= $(o
.tabTemplate
.replace(/#\{href\}/g, url
).replace(/#\{label\}/g, label
)),
7288 id
= !url
.indexOf('#') ? url
.replace('#', '') : this._tabId($('a', $li
)[0]);
7290 $li
.addClass('ui-state-default ui-corner-top').data('destroy.tabs', true);
7292 // try to find an existing element before creating a new one
7293 var $panel
= $('#' + id
);
7294 if (!$panel
.length
) {
7295 $panel
= $(o
.panelTemplate
).attr('id', id
).data('destroy.tabs', true);
7297 $panel
.addClass('ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide');
7299 if (index
>= this.lis
.length
) {
7300 $li
.appendTo(this.list
);
7301 $panel
.appendTo(this.list
[0].parentNode
);
7304 $li
.insertBefore(this.lis
[index
]);
7305 $panel
.insertBefore(this.panels
[index
]);
7308 o
.disabled
= $.map(o
.disabled
,
7309 function(n
, i
) { return n
>= index
? ++n
: n
; });
7313 if (this.anchors
.length
== 1) { // after tabify
7315 $li
.addClass('ui-tabs-selected ui-state-active');
7316 $panel
.removeClass('ui-tabs-hide');
7317 this.element
.queue("tabs", function() {
7318 self
._trigger('show', null, self
._ui(self
.anchors
[0], self
.panels
[0]));
7325 this._trigger('add', null, this._ui(this.anchors
[index
], this.panels
[index
]));
7329 remove: function(index
) {
7330 var o
= this.options
, $li
= this.lis
.eq(index
).remove(),
7331 $panel
= this.panels
.eq(index
).remove();
7333 // If selected tab was removed focus tab to the right or
7334 // in case the last tab was removed the tab to the left.
7335 if ($li
.hasClass('ui-tabs-selected') && this.anchors
.length
> 1) {
7336 this.select(index
+ (index
+ 1 < this.anchors
.length
? 1 : -1));
7339 o
.disabled
= $.map($.grep(o
.disabled
, function(n
, i
) { return n
!= index
; }),
7340 function(n
, i
) { return n
>= index
? --n
: n
; });
7345 this._trigger('remove', null, this._ui($li
.find('a')[0], $panel
[0]));
7349 enable: function(index
) {
7350 var o
= this.options
;
7351 if ($.inArray(index
, o
.disabled
) == -1) {
7355 this.lis
.eq(index
).removeClass('ui-state-disabled');
7356 o
.disabled
= $.grep(o
.disabled
, function(n
, i
) { return n
!= index
; });
7359 this._trigger('enable', null, this._ui(this.anchors
[index
], this.panels
[index
]));
7363 disable: function(index
) {
7364 var self
= this, o
= this.options
;
7365 if (index
!= o
.selected
) { // cannot disable already selected tab
7366 this.lis
.eq(index
).addClass('ui-state-disabled');
7368 o
.disabled
.push(index
);
7372 this._trigger('disable', null, this._ui(this.anchors
[index
], this.panels
[index
]));
7378 select: function(index
) {
7379 if (typeof index
== 'string') {
7380 index
= this.anchors
.index(this.anchors
.filter('[href$=' + index
+ ']'));
7382 else if (index
=== null) { // usage of null is deprecated, TODO remove in next release
7385 if (index
== -1 && this.options
.collapsible
) {
7386 index
= this.options
.selected
;
7389 this.anchors
.eq(index
).trigger(this.options
.event
+ '.tabs');
7393 load: function(index
) {
7394 var self
= this, o
= this.options
, a
= this.anchors
.eq(index
)[0], url
= $.data(a
, 'load.tabs');
7398 // not remote or from cache
7399 if (!url
|| this.element
.queue("tabs").length
!== 0 && $.data(a
, 'cache.tabs')) {
7400 this.element
.dequeue("tabs");
7404 // load remote from here on
7405 this.lis
.eq(index
).addClass('ui-state-processing');
7408 var span
= $('span', a
);
7409 span
.data('label.tabs', span
.html()).html(o
.spinner
);
7412 this.xhr
= $.ajax($.extend({}, o
.ajaxOptions
, {
7414 success: function(r
, s
) {
7415 $(self
._sanitizeSelector(a
.hash
)).html(r
);
7417 // take care of tab labels
7421 $.data(a
, 'cache.tabs', true); // if loaded once do not load them again
7425 self
._trigger('load', null, self
._ui(self
.anchors
[index
], self
.panels
[index
]));
7427 o
.ajaxOptions
.success(r
, s
);
7431 error: function(xhr
, s
, e
) {
7432 // take care of tab labels
7436 self
._trigger('load', null, self
._ui(self
.anchors
[index
], self
.panels
[index
]));
7438 // Passing index avoid a race condition when this method is
7439 // called after the user has selected another tab.
7440 // Pass the anchor that initiated this request allows
7441 // loadError to manipulate the tab content panel via $(a.hash)
7442 o
.ajaxOptions
.error(xhr
, s
, index
, a
);
7448 // last, so that load event is fired before show...
7449 self
.element
.dequeue("tabs");
7455 // stop possibly running animations
7456 this.element
.queue([]);
7457 this.panels
.stop(false, true);
7459 // "tabs" queue must not contain more than two elements,
7460 // which are the callbacks for the latest clicked tab...
7461 this.element
.queue("tabs", this.element
.queue("tabs").splice(-2, 2));
7463 // terminate pending requests from other tabs
7469 // take care of tab labels
7474 url: function(index
, url
) {
7475 this.anchors
.eq(index
).removeData('cache.tabs').data('load.tabs', url
);
7479 length: function() {
7480 return this.anchors
.length
;
7485 $.extend($.ui
.tabs
, {
7496 $.extend($.ui
.tabs
.prototype, {
7498 rotate: function(ms
, continuing
) {
7500 var self
= this, o
= this.options
;
7502 var rotate
= self
._rotate
|| (self
._rotate = function(e
) {
7503 clearTimeout(self
.rotation
);
7504 self
.rotation
= setTimeout(function() {
7506 self
.select( ++t
< self
.anchors
.length
? t
: 0 );
7510 e
.stopPropagation();
7514 var stop
= self
._unrotate
|| (self
._unrotate
= !continuing
?
7516 if (e
.clientX
) { // in case of a true click
7527 this.element
.bind('tabsshow', rotate
);
7528 this.anchors
.bind(o
.event
+ '.tabs', stop
);
7533 clearTimeout(self
.rotation
);
7534 this.element
.unbind('tabsshow', rotate
);
7535 this.anchors
.unbind(o
.event
+ '.tabs', stop
);
7536 delete this._rotate
;
7537 delete this._unrotate
;
7546 * jQuery UI Datepicker 1.8
7548 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
7549 * Dual licensed under the MIT (MIT-LICENSE.txt)
7550 * and GPL (GPL-LICENSE.txt) licenses.
7552 * http://docs.jquery.com/UI/Datepicker
7558 (function($) { // hide the namespace
7560 $.extend($.ui
, { datepicker
: { version
: "1.8" } });
7562 var PROP_NAME
= 'datepicker';
7563 var dpuuid
= new Date().getTime();
7565 /* Date picker manager.
7566 Use the singleton instance of this class, $.datepicker, to interact with the date picker.
7567 Settings for (groups of) date pickers are maintained in an instance object,
7568 allowing multiple different settings on the same page. */
7570 function Datepicker() {
7571 this.debug
= false; // Change this to true to start debugging
7572 this._curInst
= null; // The current instance in use
7573 this._keyEvent
= false; // If the last event was a key event
7574 this._disabledInputs
= []; // List of date picker inputs that have been disabled
7575 this._datepickerShowing
= false; // True if the popup picker is showing , false if not
7576 this._inDialog
= false; // True if showing within a "dialog", false if not
7577 this._mainDivId
= 'ui-datepicker-div'; // The ID of the main datepicker division
7578 this._inlineClass
= 'ui-datepicker-inline'; // The name of the inline marker class
7579 this._appendClass
= 'ui-datepicker-append'; // The name of the append marker class
7580 this._triggerClass
= 'ui-datepicker-trigger'; // The name of the trigger marker class
7581 this._dialogClass
= 'ui-datepicker-dialog'; // The name of the dialog marker class
7582 this._disableClass
= 'ui-datepicker-disabled'; // The name of the disabled covering marker class
7583 this._unselectableClass
= 'ui-datepicker-unselectable'; // The name of the unselectable cell marker class
7584 this._currentClass
= 'ui-datepicker-current-day'; // The name of the current day marker class
7585 this._dayOverClass
= 'ui-datepicker-days-cell-over'; // The name of the day hover marker class
7586 this.regional
= []; // Available regional settings, indexed by language code
7587 this.regional
[''] = { // Default regional settings
7588 closeText
: 'Done', // Display text for close link
7589 prevText
: 'Prev', // Display text for previous month link
7590 nextText
: 'Next', // Display text for next month link
7591 currentText
: 'Today', // Display text for current month link
7592 monthNames
: ['January','February','March','April','May','June',
7593 'July','August','September','October','November','December'], // Names of months for drop-down and formatting
7594 monthNamesShort
: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], // For formatting
7595 dayNames
: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], // For formatting
7596 dayNamesShort
: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], // For formatting
7597 dayNamesMin
: ['Su','Mo','Tu','We','Th','Fr','Sa'], // Column headings for days starting at Sunday
7598 weekHeader
: 'Wk', // Column header for week of the year
7599 dateFormat
: 'mm/dd/yy', // See format options on parseDate
7600 firstDay
: 0, // The first day of the week, Sun = 0, Mon = 1, ...
7601 isRTL
: false, // True if right-to-left language, false if left-to-right
7602 showMonthAfterYear
: false, // True if the year select precedes month, false for month then year
7603 yearSuffix
: '' // Additional text to append to the year in the month headers
7605 this._defaults
= { // Global defaults for all the date picker instances
7606 showOn
: 'focus', // 'focus' for popup on focus,
7607 // 'button' for trigger button, or 'both' for either
7608 showAnim
: 'show', // Name of jQuery animation for popup
7609 showOptions
: {}, // Options for enhanced animations
7610 defaultDate
: null, // Used when field is blank: actual date,
7611 // +/-number for offset from today, null for today
7612 appendText
: '', // Display text following the input box, e.g. showing the format
7613 buttonText
: '...', // Text for trigger button
7614 buttonImage
: '', // URL for trigger button image
7615 buttonImageOnly
: false, // True if the image appears alone, false if it appears on a button
7616 hideIfNoPrevNext
: false, // True to hide next/previous month links
7617 // if not applicable, false to just disable them
7618 navigationAsDateFormat
: false, // True if date formatting applied to prev/today/next links
7619 gotoCurrent
: false, // True if today link goes back to current selection instead
7620 changeMonth
: false, // True if month can be selected directly, false if only prev/next
7621 changeYear
: false, // True if year can be selected directly, false if only prev/next
7622 yearRange
: 'c-10:c+10', // Range of years to display in drop-down,
7623 // either relative to today's year (-nn:+nn), relative to currently displayed year
7624 // (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
7625 showOtherMonths
: false, // True to show dates in other months, false to leave blank
7626 selectOtherMonths
: false, // True to allow selection of dates in other months, false for unselectable
7627 showWeek
: false, // True to show week of the year, false to not show it
7628 calculateWeek
: this.iso8601Week
, // How to calculate the week of the year,
7629 // takes a Date and returns the number of the week for it
7630 shortYearCutoff
: '+10', // Short year values < this are in the current century,
7631 // > this are in the previous century,
7632 // string value starting with '+' for current year + value
7633 minDate
: null, // The earliest selectable date, or null for no limit
7634 maxDate
: null, // The latest selectable date, or null for no limit
7635 duration
: '_default', // Duration of display/closure
7636 beforeShowDay
: null, // Function that takes a date and returns an array with
7637 // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or '',
7638 // [2] = cell title (optional), e.g. $.datepicker.noWeekends
7639 beforeShow
: null, // Function that takes an input field and
7640 // returns a set of custom settings for the date picker
7641 onSelect
: null, // Define a callback function when a date is selected
7642 onChangeMonthYear
: null, // Define a callback function when the month or year is changed
7643 onClose
: null, // Define a callback function when the datepicker is closed
7644 numberOfMonths
: 1, // Number of months to show at a time
7645 showCurrentAtPos
: 0, // The position in multipe months at which to show the current month (starting at 0)
7646 stepMonths
: 1, // Number of months to step back/forward
7647 stepBigMonths
: 12, // Number of months to step back/forward for the big links
7648 altField
: '', // Selector for an alternate field to store selected dates into
7649 altFormat
: '', // The date format to use for the alternate field
7650 constrainInput
: true, // The input is constrained by the current date format
7651 showButtonPanel
: false, // True to show button panel, false to not show it
7652 autoSize
: false // True to size the input for the date format, false to leave as is
7654 $.extend(this._defaults
, this.regional
['']);
7655 this.dpDiv
= $('<div id="' + this._mainDivId
+ '" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all ui-helper-hidden-accessible"></div>');
7658 $.extend(Datepicker
.prototype, {
7659 /* Class name added to elements to indicate already configured with a date picker. */
7660 markerClassName
: 'hasDatepicker',
7662 /* Debug logging (if enabled). */
7665 console
.log
.apply('', arguments
);
7668 // TODO rename to "widget" when switching to widget factory
7669 _widgetDatepicker: function() {
7673 /* Override the default settings for all instances of the date picker.
7674 @param settings object - the new settings to use as defaults (anonymous object)
7675 @return the manager object */
7676 setDefaults: function(settings
) {
7677 extendRemove(this._defaults
, settings
|| {});
7681 /* Attach the date picker to a jQuery selection.
7682 @param target element - the target input field or division or span
7683 @param settings object - the new settings to use for this date picker instance (anonymous) */
7684 _attachDatepicker: function(target
, settings
) {
7685 // check for settings on the control itself - in namespace 'date:'
7686 var inlineSettings
= null;
7687 for (var attrName
in this._defaults
) {
7688 var attrValue
= target
.getAttribute('date:' + attrName
);
7690 inlineSettings
= inlineSettings
|| {};
7692 inlineSettings
[attrName
] = eval(attrValue
);
7694 inlineSettings
[attrName
] = attrValue
;
7698 var nodeName
= target
.nodeName
.toLowerCase();
7699 var inline
= (nodeName
== 'div' || nodeName
== 'span');
7701 target
.id
= 'dp' + (++this.uuid
);
7702 var inst
= this._newInst($(target
), inline
);
7703 inst
.settings
= $.extend({}, settings
|| {}, inlineSettings
|| {});
7704 if (nodeName
== 'input') {
7705 this._connectDatepicker(target
, inst
);
7706 } else if (inline
) {
7707 this._inlineDatepicker(target
, inst
);
7711 /* Create a new instance object. */
7712 _newInst: function(target
, inline
) {
7713 var id
= target
[0].id
.replace(/([^A-Za-z0-9_])/g, '\\\\$1'); // escape jQuery meta chars
7714 return {id
: id
, input
: target
, // associated target
7715 selectedDay
: 0, selectedMonth
: 0, selectedYear
: 0, // current selection
7716 drawMonth
: 0, drawYear
: 0, // month being drawn
7717 inline
: inline
, // is datepicker inline or not
7718 dpDiv
: (!inline
? this.dpDiv
: // presentation div
7719 $('<div class="' + this._inlineClass
+ ' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>'))};
7722 /* Attach the date picker to an input field. */
7723 _connectDatepicker: function(target
, inst
) {
7724 var input
= $(target
);
7725 inst
.append
= $([]);
7726 inst
.trigger
= $([]);
7727 if (input
.hasClass(this.markerClassName
))
7729 this._attachments(input
, inst
);
7730 input
.addClass(this.markerClassName
).keydown(this._doKeyDown
).
7731 keypress(this._doKeyPress
).keyup(this._doKeyUp
).
7732 bind("setData.datepicker", function(event
, key
, value
) {
7733 inst
.settings
[key
] = value
;
7734 }).bind("getData.datepicker", function(event
, key
) {
7735 return this._get(inst
, key
);
7737 this._autoSize(inst
);
7738 $.data(target
, PROP_NAME
, inst
);
7741 /* Make attachments based on settings. */
7742 _attachments: function(input
, inst
) {
7743 var appendText
= this._get(inst
, 'appendText');
7744 var isRTL
= this._get(inst
, 'isRTL');
7746 inst
.append
.remove();
7748 inst
.append
= $('<span class="' + this._appendClass
+ '">' + appendText
+ '</span>');
7749 input
[isRTL
? 'before' : 'after'](inst
.append
);
7751 input
.unbind('focus', this._showDatepicker
);
7753 inst
.trigger
.remove();
7754 var showOn
= this._get(inst
, 'showOn');
7755 if (showOn
== 'focus' || showOn
== 'both') // pop-up date picker when in the marked field
7756 input
.focus(this._showDatepicker
);
7757 if (showOn
== 'button' || showOn
== 'both') { // pop-up date picker when button clicked
7758 var buttonText
= this._get(inst
, 'buttonText');
7759 var buttonImage
= this._get(inst
, 'buttonImage');
7760 inst
.trigger
= $(this._get(inst
, 'buttonImageOnly') ?
7761 $('<img/>').addClass(this._triggerClass
).
7762 attr({ src
: buttonImage
, alt
: buttonText
, title
: buttonText
}) :
7763 $('<button type="button"></button>').addClass(this._triggerClass
).
7764 html(buttonImage
== '' ? buttonText
: $('<img/>').attr(
7765 { src
:buttonImage
, alt
:buttonText
, title
:buttonText
})));
7766 input
[isRTL
? 'before' : 'after'](inst
.trigger
);
7767 inst
.trigger
.click(function() {
7768 if ($.datepicker
._datepickerShowing
&& $.datepicker
._lastInput
== input
[0])
7769 $.datepicker
._hideDatepicker();
7771 $.datepicker
._showDatepicker(input
[0]);
7777 /* Apply the maximum length for the date format. */
7778 _autoSize: function(inst
) {
7779 if (this._get(inst
, 'autoSize') && !inst
.inline
) {
7780 var date
= new Date(2009, 12 - 1, 20); // Ensure double digits
7781 var dateFormat
= this._get(inst
, 'dateFormat');
7782 if (dateFormat
.match(/[DM]/)) {
7783 var findMax = function(names
) {
7786 for (var i
= 0; i
< names
.length
; i
++) {
7787 if (names
[i
].length
> max
) {
7788 max
= names
[i
].length
;
7794 date
.setMonth(findMax(this._get(inst
, (dateFormat
.match(/MM/) ?
7795 'monthNames' : 'monthNamesShort'))));
7796 date
.setDate(findMax(this._get(inst
, (dateFormat
.match(/DD/) ?
7797 'dayNames' : 'dayNamesShort'))) + 20 - date
.getDay());
7799 inst
.input
.attr('size', this._formatDate(inst
, date
).length
);
7803 /* Attach an inline date picker to a div. */
7804 _inlineDatepicker: function(target
, inst
) {
7805 var divSpan
= $(target
);
7806 if (divSpan
.hasClass(this.markerClassName
))
7808 divSpan
.addClass(this.markerClassName
).append(inst
.dpDiv
).
7809 bind("setData.datepicker", function(event
, key
, value
){
7810 inst
.settings
[key
] = value
;
7811 }).bind("getData.datepicker", function(event
, key
){
7812 return this._get(inst
, key
);
7814 $.data(target
, PROP_NAME
, inst
);
7815 this._setDate(inst
, this._getDefaultDate(inst
), true);
7816 this._updateDatepicker(inst
);
7817 this._updateAlternate(inst
);
7820 /* Pop-up the date picker in a "dialog" box.
7821 @param input element - ignored
7822 @param date string or Date - the initial date to display
7823 @param onSelect function - the function to call when a date is selected
7824 @param settings object - update the dialog date picker instance's settings (anonymous object)
7825 @param pos int[2] - coordinates for the dialog's position within the screen or
7826 event - with x/y coordinates or
7827 leave empty for default (screen centre)
7828 @return the manager object */
7829 _dialogDatepicker: function(input
, date
, onSelect
, settings
, pos
) {
7830 var inst
= this._dialogInst
; // internal instance
7832 var id
= 'dp' + (++this.uuid
);
7833 this._dialogInput
= $('<input type="text" id="' + id
+
7834 '" style="position: absolute; top: -100px; width: 0px; z-index: -10;"/>');
7835 this._dialogInput
.keydown(this._doKeyDown
);
7836 $('body').append(this._dialogInput
);
7837 inst
= this._dialogInst
= this._newInst(this._dialogInput
, false);
7839 $.data(this._dialogInput
[0], PROP_NAME
, inst
);
7841 extendRemove(inst
.settings
, settings
|| {});
7842 date
= (date
&& date
.constructor == Date
? this._formatDate(inst
, date
) : date
);
7843 this._dialogInput
.val(date
);
7845 this._pos
= (pos
? (pos
.length
? pos
: [pos
.pageX
, pos
.pageY
]) : null);
7847 var browserWidth
= document
.documentElement
.clientWidth
;
7848 var browserHeight
= document
.documentElement
.clientHeight
;
7849 var scrollX
= document
.documentElement
.scrollLeft
|| document
.body
.scrollLeft
;
7850 var scrollY
= document
.documentElement
.scrollTop
|| document
.body
.scrollTop
;
7851 this._pos
= // should use actual width/height below
7852 [(browserWidth
/ 2) - 100 + scrollX
, (browserHeight
/ 2) - 150 + scrollY
];
7855 // move input on screen for focus, but hidden behind dialog
7856 this._dialogInput
.css('left', (this._pos
[0] + 20) + 'px').css('top', this._pos
[1] + 'px');
7857 inst
.settings
.onSelect
= onSelect
;
7858 this._inDialog
= true;
7859 this.dpDiv
.addClass(this._dialogClass
);
7860 this._showDatepicker(this._dialogInput
[0]);
7862 $.blockUI(this.dpDiv
);
7863 $.data(this._dialogInput
[0], PROP_NAME
, inst
);
7867 /* Detach a datepicker from its control.
7868 @param target element - the target input field or division or span */
7869 _destroyDatepicker: function(target
) {
7870 var $target
= $(target
);
7871 var inst
= $.data(target
, PROP_NAME
);
7872 if (!$target
.hasClass(this.markerClassName
)) {
7875 var nodeName
= target
.nodeName
.toLowerCase();
7876 $.removeData(target
, PROP_NAME
);
7877 if (nodeName
== 'input') {
7878 inst
.append
.remove();
7879 inst
.trigger
.remove();
7880 $target
.removeClass(this.markerClassName
).
7881 unbind('focus', this._showDatepicker
).
7882 unbind('keydown', this._doKeyDown
).
7883 unbind('keypress', this._doKeyPress
).
7884 unbind('keyup', this._doKeyUp
);
7885 } else if (nodeName
== 'div' || nodeName
== 'span')
7886 $target
.removeClass(this.markerClassName
).empty();
7889 /* Enable the date picker to a jQuery selection.
7890 @param target element - the target input field or division or span */
7891 _enableDatepicker: function(target
) {
7892 var $target
= $(target
);
7893 var inst
= $.data(target
, PROP_NAME
);
7894 if (!$target
.hasClass(this.markerClassName
)) {
7897 var nodeName
= target
.nodeName
.toLowerCase();
7898 if (nodeName
== 'input') {
7899 target
.disabled
= false;
7900 inst
.trigger
.filter('button').
7901 each(function() { this.disabled
= false; }).end().
7902 filter('img').css({opacity
: '1.0', cursor
: ''});
7904 else if (nodeName
== 'div' || nodeName
== 'span') {
7905 var inline
= $target
.children('.' + this._inlineClass
);
7906 inline
.children().removeClass('ui-state-disabled');
7908 this._disabledInputs
= $.map(this._disabledInputs
,
7909 function(value
) { return (value
== target
? null : value
); }); // delete entry
7912 /* Disable the date picker to a jQuery selection.
7913 @param target element - the target input field or division or span */
7914 _disableDatepicker: function(target
) {
7915 var $target
= $(target
);
7916 var inst
= $.data(target
, PROP_NAME
);
7917 if (!$target
.hasClass(this.markerClassName
)) {
7920 var nodeName
= target
.nodeName
.toLowerCase();
7921 if (nodeName
== 'input') {
7922 target
.disabled
= true;
7923 inst
.trigger
.filter('button').
7924 each(function() { this.disabled
= true; }).end().
7925 filter('img').css({opacity
: '0.5', cursor
: 'default'});
7927 else if (nodeName
== 'div' || nodeName
== 'span') {
7928 var inline
= $target
.children('.' + this._inlineClass
);
7929 inline
.children().addClass('ui-state-disabled');
7931 this._disabledInputs
= $.map(this._disabledInputs
,
7932 function(value
) { return (value
== target
? null : value
); }); // delete entry
7933 this._disabledInputs
[this._disabledInputs
.length
] = target
;
7936 /* Is the first field in a jQuery collection disabled as a datepicker?
7937 @param target element - the target input field or division or span
7938 @return boolean - true if disabled, false if enabled */
7939 _isDisabledDatepicker: function(target
) {
7943 for (var i
= 0; i
< this._disabledInputs
.length
; i
++) {
7944 if (this._disabledInputs
[i
] == target
)
7950 /* Retrieve the instance data for the target control.
7951 @param target element - the target input field or division or span
7952 @return object - the associated instance data
7953 @throws error if a jQuery problem getting data */
7954 _getInst: function(target
) {
7956 return $.data(target
, PROP_NAME
);
7959 throw 'Missing instance data for this datepicker';
7963 /* Update or retrieve the settings for a date picker attached to an input field or division.
7964 @param target element - the target input field or division or span
7965 @param name object - the new settings to update or
7966 string - the name of the setting to change or retrieve,
7967 when retrieving also 'all' for all instance settings or
7968 'defaults' for all global defaults
7969 @param value any - the new value for the setting
7970 (omit if above is an object or to retrieve a value) */
7971 _optionDatepicker: function(target
, name
, value
) {
7972 var inst
= this._getInst(target
);
7973 if (arguments
.length
== 2 && typeof name
== 'string') {
7974 return (name
== 'defaults' ? $.extend({}, $.datepicker
._defaults
) :
7975 (inst
? (name
== 'all' ? $.extend({}, inst
.settings
) :
7976 this._get(inst
, name
)) : null));
7978 var settings
= name
|| {};
7979 if (typeof name
== 'string') {
7981 settings
[name
] = value
;
7984 if (this._curInst
== inst
) {
7985 this._hideDatepicker();
7987 var date
= this._getDateDatepicker(target
, true);
7988 extendRemove(inst
.settings
, settings
);
7989 this._attachments($(target
), inst
);
7990 this._autoSize(inst
);
7991 this._setDateDatepicker(target
, date
);
7992 this._updateDatepicker(inst
);
7996 // change method deprecated
7997 _changeDatepicker: function(target
, name
, value
) {
7998 this._optionDatepicker(target
, name
, value
);
8001 /* Redraw the date picker attached to an input field or division.
8002 @param target element - the target input field or division or span */
8003 _refreshDatepicker: function(target
) {
8004 var inst
= this._getInst(target
);
8006 this._updateDatepicker(inst
);
8010 /* Set the dates for a jQuery selection.
8011 @param target element - the target input field or division or span
8012 @param date Date - the new date */
8013 _setDateDatepicker: function(target
, date
) {
8014 var inst
= this._getInst(target
);
8016 this._setDate(inst
, date
);
8017 this._updateDatepicker(inst
);
8018 this._updateAlternate(inst
);
8022 /* Get the date(s) for the first entry in a jQuery selection.
8023 @param target element - the target input field or division or span
8024 @param noDefault boolean - true if no default date is to be used
8025 @return Date - the current date */
8026 _getDateDatepicker: function(target
, noDefault
) {
8027 var inst
= this._getInst(target
);
8028 if (inst
&& !inst
.inline
)
8029 this._setDateFromField(inst
, noDefault
);
8030 return (inst
? this._getDate(inst
) : null);
8033 /* Handle keystrokes. */
8034 _doKeyDown: function(event
) {
8035 var inst
= $.datepicker
._getInst(event
.target
);
8037 var isRTL
= inst
.dpDiv
.is('.ui-datepicker-rtl');
8038 inst
._keyEvent
= true;
8039 if ($.datepicker
._datepickerShowing
)
8040 switch (event
.keyCode
) {
8041 case 9: $.datepicker
._hideDatepicker();
8043 break; // hide on tab out
8044 case 13: var sel
= $('td.' + $.datepicker
._dayOverClass
, inst
.dpDiv
).
8045 add($('td.' + $.datepicker
._currentClass
, inst
.dpDiv
));
8047 $.datepicker
._selectDay(event
.target
, inst
.selectedMonth
, inst
.selectedYear
, sel
[0]);
8049 $.datepicker
._hideDatepicker();
8050 return false; // don't submit the form
8051 break; // select the value on enter
8052 case 27: $.datepicker
._hideDatepicker();
8053 break; // hide on escape
8054 case 33: $.datepicker
._adjustDate(event
.target
, (event
.ctrlKey
?
8055 -$.datepicker
._get(inst
, 'stepBigMonths') :
8056 -$.datepicker
._get(inst
, 'stepMonths')), 'M');
8057 break; // previous month/year on page up/+ ctrl
8058 case 34: $.datepicker
._adjustDate(event
.target
, (event
.ctrlKey
?
8059 +$.datepicker
._get(inst
, 'stepBigMonths') :
8060 +$.datepicker
._get(inst
, 'stepMonths')), 'M');
8061 break; // next month/year on page down/+ ctrl
8062 case 35: if (event
.ctrlKey
|| event
.metaKey
) $.datepicker
._clearDate(event
.target
);
8063 handled
= event
.ctrlKey
|| event
.metaKey
;
8064 break; // clear on ctrl or command +end
8065 case 36: if (event
.ctrlKey
|| event
.metaKey
) $.datepicker
._gotoToday(event
.target
);
8066 handled
= event
.ctrlKey
|| event
.metaKey
;
8067 break; // current on ctrl or command +home
8068 case 37: if (event
.ctrlKey
|| event
.metaKey
) $.datepicker
._adjustDate(event
.target
, (isRTL
? +1 : -1), 'D');
8069 handled
= event
.ctrlKey
|| event
.metaKey
;
8070 // -1 day on ctrl or command +left
8071 if (event
.originalEvent
.altKey
) $.datepicker
._adjustDate(event
.target
, (event
.ctrlKey
?
8072 -$.datepicker
._get(inst
, 'stepBigMonths') :
8073 -$.datepicker
._get(inst
, 'stepMonths')), 'M');
8074 // next month/year on alt +left on Mac
8076 case 38: if (event
.ctrlKey
|| event
.metaKey
) $.datepicker
._adjustDate(event
.target
, -7, 'D');
8077 handled
= event
.ctrlKey
|| event
.metaKey
;
8078 break; // -1 week on ctrl or command +up
8079 case 39: if (event
.ctrlKey
|| event
.metaKey
) $.datepicker
._adjustDate(event
.target
, (isRTL
? -1 : +1), 'D');
8080 handled
= event
.ctrlKey
|| event
.metaKey
;
8081 // +1 day on ctrl or command +right
8082 if (event
.originalEvent
.altKey
) $.datepicker
._adjustDate(event
.target
, (event
.ctrlKey
?
8083 +$.datepicker
._get(inst
, 'stepBigMonths') :
8084 +$.datepicker
._get(inst
, 'stepMonths')), 'M');
8085 // next month/year on alt +right
8087 case 40: if (event
.ctrlKey
|| event
.metaKey
) $.datepicker
._adjustDate(event
.target
, +7, 'D');
8088 handled
= event
.ctrlKey
|| event
.metaKey
;
8089 break; // +1 week on ctrl or command +down
8090 default: handled
= false;
8092 else if (event
.keyCode
== 36 && event
.ctrlKey
) // display the date picker on ctrl+home
8093 $.datepicker
._showDatepicker(this);
8098 event
.preventDefault();
8099 event
.stopPropagation();
8103 /* Filter entered characters - based on date format. */
8104 _doKeyPress: function(event
) {
8105 var inst
= $.datepicker
._getInst(event
.target
);
8106 if ($.datepicker
._get(inst
, 'constrainInput')) {
8107 var chars
= $.datepicker
._possibleChars($.datepicker
._get(inst
, 'dateFormat'));
8108 var chr
= String
.fromCharCode(event
.charCode
== undefined ? event
.keyCode
: event
.charCode
);
8109 return event
.ctrlKey
|| (chr
< ' ' || !chars
|| chars
.indexOf(chr
) > -1);
8113 /* Synchronise manual entry and field/alternate field. */
8114 _doKeyUp: function(event) {
8115 var inst = $.datepicker._getInst(event.target);
8116 if (inst.input.val() != inst.lastVal) {
8118 var date = $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
8119 (inst.input ? inst.input.val() : null),
8120 $.datepicker._getFormatConfig(inst));
8121 if (date) { // only if valid
8122 $.datepicker._setDateFromField(inst);
8123 $.datepicker._updateAlternate(inst);
8124 $.datepicker._updateDatepicker(inst);
8128 $.datepicker.log(event);
8134 /* Pop-up the date picker for a given input field.
8135 @param input element - the input field attached to the date picker or
8136 event - if triggered by focus */
8137 _showDatepicker: function(input
) {
8138 input
= input
.target
|| input
;
8139 if (input
.nodeName
.toLowerCase() != 'input') // find from button/image trigger
8140 input
= $('input', input
.parentNode
)[0];
8141 if ($.datepicker
._isDisabledDatepicker(input
) || $.datepicker
._lastInput
== input
) // already here
8143 var inst
= $.datepicker
._getInst(input
);
8144 if ($.datepicker
._curInst
&& $.datepicker
._curInst
!= inst
) {
8145 $.datepicker
._curInst
.dpDiv
.stop(true, true);
8147 var beforeShow
= $.datepicker
._get(inst
, 'beforeShow');
8148 extendRemove(inst
.settings
, (beforeShow
? beforeShow
.apply(input
, [input
, inst
]) : {}));
8149 inst
.lastVal
= null;
8150 $.datepicker
._lastInput
= input
;
8151 $.datepicker
._setDateFromField(inst
);
8152 if ($.datepicker
._inDialog
) // hide cursor
8154 if (!$.datepicker
._pos
) { // position below input
8155 $.datepicker
._pos
= $.datepicker
._findPos(input
);
8156 $.datepicker
._pos
[1] += input
.offsetHeight
; // add the height
8158 var isFixed
= false;
8159 $(input
).parents().each(function() {
8160 isFixed
|= $(this).css('position') == 'fixed';
8163 if (isFixed
&& $.browser
.opera
) { // correction for Opera when fixed and scrolled
8164 $.datepicker
._pos
[0] -= document
.documentElement
.scrollLeft
;
8165 $.datepicker
._pos
[1] -= document
.documentElement
.scrollTop
;
8167 var offset
= {left
: $.datepicker
._pos
[0], top
: $.datepicker
._pos
[1]};
8168 $.datepicker
._pos
= null;
8169 // determine sizing offscreen
8170 inst
.dpDiv
.css({position
: 'absolute', display
: 'block', top
: '-1000px'});
8171 $.datepicker
._updateDatepicker(inst
);
8172 // fix width for dynamic number of date pickers
8173 // and adjust position before showing
8174 offset
= $.datepicker
._checkOffset(inst
, offset
, isFixed
);
8175 inst
.dpDiv
.css({position
: ($.datepicker
._inDialog
&& $.blockUI
?
8176 'static' : (isFixed
? 'fixed' : 'absolute')), display
: 'none',
8177 left
: offset
.left
+ 'px', top
: offset
.top
+ 'px'});
8179 var showAnim
= $.datepicker
._get(inst
, 'showAnim');
8180 var duration
= $.datepicker
._get(inst
, 'duration');
8181 var postProcess = function() {
8182 $.datepicker
._datepickerShowing
= true;
8183 var borders
= $.datepicker
._getBorders(inst
.dpDiv
);
8184 inst
.dpDiv
.find('iframe.ui-datepicker-cover'). // IE6- only
8185 css({left
: -borders
[0], top
: -borders
[1],
8186 width
: inst
.dpDiv
.outerWidth(), height
: inst
.dpDiv
.outerHeight()});
8188 inst
.dpDiv
.zIndex($(input
).zIndex()+1);
8189 if ($.effects
&& $.effects
[showAnim
])
8190 inst
.dpDiv
.show(showAnim
, $.datepicker
._get(inst
, 'showOptions'), duration
, postProcess
);
8192 inst
.dpDiv
[showAnim
|| 'show']((showAnim
? duration
: null), postProcess
);
8193 if (!showAnim
|| !duration
)
8195 if (inst
.input
.is(':visible') && !inst
.input
.is(':disabled'))
8197 $.datepicker
._curInst
= inst
;
8201 /* Generate the date picker content. */
8202 _updateDatepicker: function(inst
) {
8204 var borders
= $.datepicker
._getBorders(inst
.dpDiv
);
8205 inst
.dpDiv
.empty().append(this._generateHTML(inst
))
8206 .find('iframe.ui-datepicker-cover') // IE6- only
8207 .css({left
: -borders
[0], top
: -borders
[1],
8208 width
: inst
.dpDiv
.outerWidth(), height
: inst
.dpDiv
.outerHeight()})
8210 .find('button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a')
8211 .bind('mouseout', function(){
8212 $(this).removeClass('ui-state-hover');
8213 if(this.className
.indexOf('ui-datepicker-prev') != -1) $(this).removeClass('ui-datepicker-prev-hover');
8214 if(this.className
.indexOf('ui-datepicker-next') != -1) $(this).removeClass('ui-datepicker-next-hover');
8216 .bind('mouseover', function(){
8217 if (!self
._isDisabledDatepicker( inst
.inline
? inst
.dpDiv
.parent()[0] : inst
.input
[0])) {
8218 $(this).parents('.ui-datepicker-calendar').find('a').removeClass('ui-state-hover');
8219 $(this).addClass('ui-state-hover');
8220 if(this.className
.indexOf('ui-datepicker-prev') != -1) $(this).addClass('ui-datepicker-prev-hover');
8221 if(this.className
.indexOf('ui-datepicker-next') != -1) $(this).addClass('ui-datepicker-next-hover');
8225 .find('.' + this._dayOverClass
+ ' a')
8226 .trigger('mouseover')
8228 var numMonths
= this._getNumberOfMonths(inst
);
8229 var cols
= numMonths
[1];
8232 inst
.dpDiv
.addClass('ui-datepicker-multi-' + cols
).css('width', (width
* cols
) + 'em');
8234 inst
.dpDiv
.removeClass('ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4').width('');
8235 inst
.dpDiv
[(numMonths
[0] != 1 || numMonths
[1] != 1 ? 'add' : 'remove') +
8236 'Class']('ui-datepicker-multi');
8237 inst
.dpDiv
[(this._get(inst
, 'isRTL') ? 'add' : 'remove') +
8238 'Class']('ui-datepicker-rtl');
8239 if (inst
== $.datepicker
._curInst
&& $.datepicker
._datepickerShowing
&& inst
.input
&&
8240 inst
.input
.is(':visible') && !inst
.input
.is(':disabled'))
8244 /* Retrieve the size of left and top borders for an element.
8245 @param elem (jQuery object) the element of interest
8246 @return (number[2]) the left and top borders */
8247 _getBorders: function(elem
) {
8248 var convert = function(value
) {
8249 return {thin
: 1, medium
: 2, thick
: 3}[value
] || value
;
8251 return [parseFloat(convert(elem
.css('border-left-width'))),
8252 parseFloat(convert(elem
.css('border-top-width')))];
8255 /* Check positioning to remain on screen. */
8256 _checkOffset: function(inst
, offset
, isFixed
) {
8257 var dpWidth
= inst
.dpDiv
.outerWidth();
8258 var dpHeight
= inst
.dpDiv
.outerHeight();
8259 var inputWidth
= inst
.input
? inst
.input
.outerWidth() : 0;
8260 var inputHeight
= inst
.input
? inst
.input
.outerHeight() : 0;
8261 var viewWidth
= document
.documentElement
.clientWidth
+ $(document
).scrollLeft();
8262 var viewHeight
= document
.documentElement
.clientHeight
+ $(document
).scrollTop();
8264 offset
.left
-= (this._get(inst
, 'isRTL') ? (dpWidth
- inputWidth
) : 0);
8265 offset
.left
-= (isFixed
&& offset
.left
== inst
.input
.offset().left
) ? $(document
).scrollLeft() : 0;
8266 offset
.top
-= (isFixed
&& offset
.top
== (inst
.input
.offset().top
+ inputHeight
)) ? $(document
).scrollTop() : 0;
8268 // now check if datepicker is showing outside window viewport - move to a better place if so.
8269 offset
.left
-= Math
.min(offset
.left
, (offset
.left
+ dpWidth
> viewWidth
&& viewWidth
> dpWidth
) ?
8270 Math
.abs(offset
.left
+ dpWidth
- viewWidth
) : 0);
8271 offset
.top
-= Math
.min(offset
.top
, (offset
.top
+ dpHeight
> viewHeight
&& viewHeight
> dpHeight
) ?
8272 Math
.abs(dpHeight
+ inputHeight
) : 0);
8277 /* Find an object's position on the screen. */
8278 _findPos: function(obj
) {
8279 var inst
= this._getInst(obj
);
8280 var isRTL
= this._get(inst
, 'isRTL');
8281 while (obj
&& (obj
.type
== 'hidden' || obj
.nodeType
!= 1)) {
8282 obj
= obj
[isRTL
? 'previousSibling' : 'nextSibling'];
8284 var position
= $(obj
).offset();
8285 return [position
.left
, position
.top
];
8288 /* Hide the date picker from view.
8289 @param input element - the input field attached to the date picker */
8290 _hideDatepicker: function(input
) {
8291 var inst
= this._curInst
;
8292 if (!inst
|| (input
&& inst
!= $.data(input
, PROP_NAME
)))
8294 if (this._datepickerShowing
) {
8295 var showAnim
= this._get(inst
, 'showAnim');
8296 var duration
= this._get(inst
, 'duration');
8297 var postProcess = function() {
8298 $.datepicker
._tidyDialog(inst
);
8299 this._curInst
= null;
8301 if ($.effects
&& $.effects
[showAnim
])
8302 inst
.dpDiv
.hide(showAnim
, $.datepicker
._get(inst
, 'showOptions'), duration
, postProcess
);
8304 inst
.dpDiv
[(showAnim
== 'slideDown' ? 'slideUp' :
8305 (showAnim
== 'fadeIn' ? 'fadeOut' : 'hide'))]((showAnim
? duration
: null), postProcess
);
8308 var onClose
= this._get(inst
, 'onClose');
8310 onClose
.apply((inst
.input
? inst
.input
[0] : null),
8311 [(inst
.input
? inst
.input
.val() : ''), inst
]); // trigger custom callback
8312 this._datepickerShowing
= false;
8313 this._lastInput
= null;
8314 if (this._inDialog
) {
8315 this._dialogInput
.css({ position
: 'absolute', left
: '0', top
: '-100px' });
8318 $('body').append(this.dpDiv
);
8321 this._inDialog
= false;
8325 /* Tidy up after a dialog display. */
8326 _tidyDialog: function(inst
) {
8327 inst
.dpDiv
.removeClass(this._dialogClass
).unbind('.ui-datepicker-calendar');
8330 /* Close date picker if clicked elsewhere. */
8331 _checkExternalClick: function(event
) {
8332 if (!$.datepicker
._curInst
)
8334 var $target
= $(event
.target
);
8335 if ($target
[0].id
!= $.datepicker
._mainDivId
&&
8336 $target
.parents('#' + $.datepicker
._mainDivId
).length
== 0 &&
8337 !$target
.hasClass($.datepicker
.markerClassName
) &&
8338 !$target
.hasClass($.datepicker
._triggerClass
) &&
8339 $.datepicker
._datepickerShowing
&& !($.datepicker
._inDialog
&& $.blockUI
))
8340 $.datepicker
._hideDatepicker();
8343 /* Adjust one of the date sub-fields. */
8344 _adjustDate: function(id
, offset
, period
) {
8346 var inst
= this._getInst(target
[0]);
8347 if (this._isDisabledDatepicker(target
[0])) {
8350 this._adjustInstDate(inst
, offset
+
8351 (period
== 'M' ? this._get(inst
, 'showCurrentAtPos') : 0), // undo positioning
8353 this._updateDatepicker(inst
);
8356 /* Action for current link. */
8357 _gotoToday: function(id
) {
8359 var inst
= this._getInst(target
[0]);
8360 if (this._get(inst
, 'gotoCurrent') && inst
.currentDay
) {
8361 inst
.selectedDay
= inst
.currentDay
;
8362 inst
.drawMonth
= inst
.selectedMonth
= inst
.currentMonth
;
8363 inst
.drawYear
= inst
.selectedYear
= inst
.currentYear
;
8366 var date
= new Date();
8367 inst
.selectedDay
= date
.getDate();
8368 inst
.drawMonth
= inst
.selectedMonth
= date
.getMonth();
8369 inst
.drawYear
= inst
.selectedYear
= date
.getFullYear();
8371 this._notifyChange(inst
);
8372 this._adjustDate(target
);
8375 /* Action for selecting a new month/year. */
8376 _selectMonthYear: function(id, select, period) {
8378 var inst = this._getInst(target[0]);
8379 inst._selectingMonthYear = false;
8380 inst['selected' + (period == 'M' ? 'Month' : 'Year')] =
8381 inst['draw' + (period == 'M' ? 'Month' : 'Year')] =
8382 parseInt(select.options[select.selectedIndex].value,10);
8383 this._notifyChange(inst);
8384 this._adjustDate(target);
8387 /* Restore input focus after not changing month/year. */
8388 _clickMonthYear: function(id) {
8390 var inst = this._getInst(target[0]);
8391 if (inst.input && inst._selectingMonthYear && !$.browser.msie)
8393 inst._selectingMonthYear = !inst._selectingMonthYear;
8396 /* Action for selecting a day. */
8397 _selectDay: function(id
, month
, year
, td
) {
8399 if ($(td
).hasClass(this._unselectableClass
) || this._isDisabledDatepicker(target
[0])) {
8402 var inst
= this._getInst(target
[0]);
8403 inst
.selectedDay
= inst
.currentDay
= $('a', td
).html();
8404 inst
.selectedMonth
= inst
.currentMonth
= month
;
8405 inst
.selectedYear
= inst
.currentYear
= year
;
8406 this._selectDate(id
, this._formatDate(inst
,
8407 inst
.currentDay
, inst
.currentMonth
, inst
.currentYear
));
8410 /* Erase the input field and hide the date picker. */
8411 _clearDate: function(id
) {
8413 var inst
= this._getInst(target
[0]);
8414 this._selectDate(target
, '');
8417 /* Update the input field with the selected date. */
8418 _selectDate: function(id
, dateStr
) {
8420 var inst
= this._getInst(target
[0]);
8421 dateStr
= (dateStr
!= null ? dateStr
: this._formatDate(inst
));
8423 inst
.input
.val(dateStr
);
8424 this._updateAlternate(inst
);
8425 var onSelect
= this._get(inst
, 'onSelect');
8427 onSelect
.apply((inst
.input
? inst
.input
[0] : null), [dateStr
, inst
]); // trigger custom callback
8428 else if (inst
.input
)
8429 inst
.input
.trigger('change'); // fire the change event
8431 this._updateDatepicker(inst
);
8433 this._hideDatepicker();
8434 this._lastInput
= inst
.input
[0];
8435 if (typeof(inst
.input
[0]) != 'object')
8436 inst
.input
.focus(); // restore focus
8437 this._lastInput
= null;
8441 /* Update any alternate field to synchronise with the main field. */
8442 _updateAlternate: function(inst
) {
8443 var altField
= this._get(inst
, 'altField');
8444 if (altField
) { // update alternate field too
8445 var altFormat
= this._get(inst
, 'altFormat') || this._get(inst
, 'dateFormat');
8446 var date
= this._getDate(inst
);
8447 var dateStr
= this.formatDate(altFormat
, date
, this._getFormatConfig(inst
));
8448 $(altField
).each(function() { $(this).val(dateStr
); });
8452 /* Set as beforeShowDay function to prevent selection of weekends.
8453 @param date Date - the date to customise
8454 @return [boolean, string] - is this date selectable?, what is its CSS class? */
8455 noWeekends: function(date
) {
8456 var day
= date
.getDay();
8457 return [(day
> 0 && day
< 6), ''];
8460 /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
8461 @param date Date - the date to get the week for
8462 @return number - the number of the week within the year that contains this date */
8463 iso8601Week: function(date
) {
8464 var checkDate
= new Date(date
.getTime());
8465 // Find Thursday of this week starting on Monday
8466 checkDate
.setDate(checkDate
.getDate() + 4 - (checkDate
.getDay() || 7));
8467 var time
= checkDate
.getTime();
8468 checkDate
.setMonth(0); // Compare with Jan 1
8469 checkDate
.setDate(1);
8470 return Math
.floor(Math
.round((time
- checkDate
) / 86400000) / 7) + 1;
8473 /* Parse a string value into a date object.
8474 See formatDate below for the possible formats.
8476 @param format string - the expected format of the date
8477 @param value string - the date in the above format
8478 @param settings Object - attributes include:
8479 shortYearCutoff number - the cutoff year for determining the century (optional)
8480 dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
8481 dayNames string[7] - names of the days from Sunday (optional)
8482 monthNamesShort string[12] - abbreviated names of the months (optional)
8483 monthNames string[12] - names of the months (optional)
8484 @return Date - the extracted date value or null if value is blank */
8485 parseDate: function (format
, value
, settings
) {
8486 if (format
== null || value
== null)
8487 throw 'Invalid arguments';
8488 value
= (typeof value
== 'object' ? value
.toString() : value
+ '');
8491 var shortYearCutoff
= (settings
? settings
.shortYearCutoff
: null) || this._defaults
.shortYearCutoff
;
8492 var dayNamesShort
= (settings
? settings
.dayNamesShort
: null) || this._defaults
.dayNamesShort
;
8493 var dayNames
= (settings
? settings
.dayNames
: null) || this._defaults
.dayNames
;
8494 var monthNamesShort
= (settings
? settings
.monthNamesShort
: null) || this._defaults
.monthNamesShort
;
8495 var monthNames
= (settings
? settings
.monthNames
: null) || this._defaults
.monthNames
;
8500 var literal
= false;
8501 // Check whether a format character is doubled
8502 var lookAhead = function(match
) {
8503 var matches
= (iFormat
+ 1 < format
.length
&& format
.charAt(iFormat
+ 1) == match
);
8508 // Extract a number from the string value
8509 var getNumber = function(match
) {
8511 var size
= (match
== '@' ? 14 : (match
== '!' ? 20 :
8512 (match
== 'y' ? 4 : (match
== 'o' ? 3 : 2))));
8513 var digits
= new RegExp('^\\d{1,' + size
+ '}');
8514 var num
= value
.substring(iValue
).match(digits
);
8516 throw 'Missing number at position ' + iValue
;
8517 iValue
+= num
[0].length
;
8518 return parseInt(num
[0], 10);
8520 // Extract a name from the string value and convert to an index
8521 var getName = function(match
, shortNames
, longNames
) {
8522 var names
= (lookAhead(match
) ? longNames
: shortNames
);
8523 for (var i
= 0; i
< names
.length
; i
++) {
8524 if (value
.substr(iValue
, names
[i
].length
) == names
[i
]) {
8525 iValue
+= names
[i
].length
;
8529 throw 'Unknown name at position ' + iValue
;
8531 // Confirm that a literal character matches the string value
8532 var checkLiteral = function() {
8533 if (value
.charAt(iValue
) != format
.charAt(iFormat
))
8534 throw 'Unexpected literal at position ' + iValue
;
8538 for (var iFormat
= 0; iFormat
< format
.length
; iFormat
++) {
8540 if (format
.charAt(iFormat
) == "'" && !lookAhead("'"))
8545 switch (format
.charAt(iFormat
)) {
8547 day
= getNumber('d');
8550 getName('D', dayNamesShort
, dayNames
);
8553 doy
= getNumber('o');
8556 month
= getNumber('m');
8559 month
= getName('M', monthNamesShort
, monthNames
);
8562 year
= getNumber('y');
8565 var date
= new Date(getNumber('@'));
8566 year
= date
.getFullYear();
8567 month
= date
.getMonth() + 1;
8568 day
= date
.getDate();
8571 var date
= new Date((getNumber('!') - this._ticksTo1970
) / 10000);
8572 year
= date
.getFullYear();
8573 month
= date
.getMonth() + 1;
8574 day
= date
.getDate();
8587 year
= new Date().getFullYear();
8588 else if (year
< 100)
8589 year
+= new Date().getFullYear() - new Date().getFullYear() % 100 +
8590 (year
<= shortYearCutoff
? 0 : -100);
8595 var dim
= this._getDaysInMonth(year
, month
- 1);
8602 var date
= this._daylightSavingAdjust(new Date(year
, month
- 1, day
));
8603 if (date
.getFullYear() != year
|| date
.getMonth() + 1 != month
|| date
.getDate() != day
)
8604 throw 'Invalid date'; // E.g. 31/02/*
8608 /* Standard date formats. */
8609 ATOM
: 'yy-mm-dd', // RFC 3339 (ISO 8601)
8610 COOKIE
: 'D, dd M yy',
8611 ISO_8601
: 'yy-mm-dd',
8612 RFC_822
: 'D, d M y',
8613 RFC_850
: 'DD, dd-M-y',
8614 RFC_1036
: 'D, d M y',
8615 RFC_1123
: 'D, d M yy',
8616 RFC_2822
: 'D, d M yy',
8617 RSS
: 'D, d M y', // RFC 822
8620 W3C
: 'yy-mm-dd', // ISO 8601
8622 _ticksTo1970
: (((1970 - 1) * 365 + Math
.floor(1970 / 4) - Math
.floor(1970 / 100) +
8623 Math
.floor(1970 / 400)) * 24 * 60 * 60 * 10000000),
8625 /* Format a date object into a string value.
8626 The format can be combinations of the following:
8627 d - day of month (no leading zero)
8628 dd - day of month (two digit)
8629 o - day of year (no leading zeros)
8630 oo - day of year (three digit)
8633 m - month of year (no leading zero)
8634 mm - month of year (two digit)
8635 M - month name short
8636 MM - month name long
8637 y - year (two digit)
8638 yy - year (four digit)
8639 @ - Unix timestamp (ms since 01/01/1970)
8640 ! - Windows ticks (100ns since 01/01/0001)
8641 '...' - literal text
8644 @param format string - the desired format of the date
8645 @param date Date - the date value to format
8646 @param settings Object - attributes include:
8647 dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
8648 dayNames string[7] - names of the days from Sunday (optional)
8649 monthNamesShort string[12] - abbreviated names of the months (optional)
8650 monthNames string[12] - names of the months (optional)
8651 @return string - the date in the above format */
8652 formatDate: function (format
, date
, settings
) {
8655 var dayNamesShort
= (settings
? settings
.dayNamesShort
: null) || this._defaults
.dayNamesShort
;
8656 var dayNames
= (settings
? settings
.dayNames
: null) || this._defaults
.dayNames
;
8657 var monthNamesShort
= (settings
? settings
.monthNamesShort
: null) || this._defaults
.monthNamesShort
;
8658 var monthNames
= (settings
? settings
.monthNames
: null) || this._defaults
.monthNames
;
8659 // Check whether a format character is doubled
8660 var lookAhead = function(match
) {
8661 var matches
= (iFormat
+ 1 < format
.length
&& format
.charAt(iFormat
+ 1) == match
);
8666 // Format a number, with leading zero if necessary
8667 var formatNumber = function(match
, value
, len
) {
8668 var num
= '' + value
;
8669 if (lookAhead(match
))
8670 while (num
.length
< len
)
8674 // Format a name, short or long as requested
8675 var formatName = function(match
, value
, shortNames
, longNames
) {
8676 return (lookAhead(match
) ? longNames
[value
] : shortNames
[value
]);
8679 var literal
= false;
8681 for (var iFormat
= 0; iFormat
< format
.length
; iFormat
++) {
8683 if (format
.charAt(iFormat
) == "'" && !lookAhead("'"))
8686 output
+= format
.charAt(iFormat
);
8688 switch (format
.charAt(iFormat
)) {
8690 output
+= formatNumber('d', date
.getDate(), 2);
8693 output
+= formatName('D', date
.getDay(), dayNamesShort
, dayNames
);
8696 output
+= formatNumber('o',
8697 (date
.getTime() - new Date(date
.getFullYear(), 0, 0).getTime()) / 86400000, 3);
8700 output
+= formatNumber('m', date
.getMonth() + 1, 2);
8703 output
+= formatName('M', date
.getMonth(), monthNamesShort
, monthNames
);
8706 output
+= (lookAhead('y') ? date
.getFullYear() :
8707 (date
.getYear() % 100 < 10 ? '0' : '') + date
.getYear() % 100);
8710 output
+= date
.getTime();
8713 output
+= date
.getTime() * 10000 + this._ticksTo1970
;
8722 output
+= format
.charAt(iFormat
);
8728 /* Extract all possible characters from the date format. */
8729 _possibleChars: function (format
) {
8731 var literal
= false;
8732 // Check whether a format character is doubled
8733 var lookAhead = function(match
) {
8734 var matches
= (iFormat
+ 1 < format
.length
&& format
.charAt(iFormat
+ 1) == match
);
8739 for (var iFormat
= 0; iFormat
< format
.length
; iFormat
++)
8741 if (format
.charAt(iFormat
) == "'" && !lookAhead("'"))
8744 chars
+= format
.charAt(iFormat
);
8746 switch (format
.charAt(iFormat
)) {
8747 case 'd': case 'm': case 'y': case '@':
8748 chars
+= '0123456789';
8751 return null; // Accept anything
8759 chars
+= format
.charAt(iFormat
);
8764 /* Get a setting value, defaulting if necessary. */
8765 _get: function(inst
, name
) {
8766 return inst
.settings
[name
] !== undefined ?
8767 inst
.settings
[name
] : this._defaults
[name
];
8770 /* Parse existing date and initialise date picker. */
8771 _setDateFromField: function(inst
, noDefault
) {
8772 if (inst
.input
.val() == inst
.lastVal
) {
8775 var dateFormat
= this._get(inst
, 'dateFormat');
8776 var dates
= inst
.lastVal
= inst
.input
? inst
.input
.val() : null;
8777 var date
, defaultDate
;
8778 date
= defaultDate
= this._getDefaultDate(inst
);
8779 var settings
= this._getFormatConfig(inst
);
8781 date
= this.parseDate(dateFormat
, dates
, settings
) || defaultDate
;
8784 dates
= (noDefault
? '' : dates
);
8786 inst
.selectedDay
= date
.getDate();
8787 inst
.drawMonth
= inst
.selectedMonth
= date
.getMonth();
8788 inst
.drawYear
= inst
.selectedYear
= date
.getFullYear();
8789 inst
.currentDay
= (dates
? date
.getDate() : 0);
8790 inst
.currentMonth
= (dates
? date
.getMonth() : 0);
8791 inst
.currentYear
= (dates
? date
.getFullYear() : 0);
8792 this._adjustInstDate(inst
);
8795 /* Retrieve the default date shown on opening. */
8796 _getDefaultDate: function(inst
) {
8797 return this._restrictMinMax(inst
,
8798 this._determineDate(inst
, this._get(inst
, 'defaultDate'), new Date()));
8801 /* A date may be specified as an exact value or a relative one. */
8802 _determineDate: function(inst
, date
, defaultDate
) {
8803 var offsetNumeric = function(offset
) {
8804 var date
= new Date();
8805 date
.setDate(date
.getDate() + offset
);
8808 var offsetString = function(offset
) {
8810 return $.datepicker
.parseDate($.datepicker
._get(inst
, 'dateFormat'),
8811 offset
, $.datepicker
._getFormatConfig(inst
));
8816 var date
= (offset
.toLowerCase().match(/^c/) ?
8817 $.datepicker
._getDate(inst
) : null) || new Date();
8818 var year
= date
.getFullYear();
8819 var month
= date
.getMonth();
8820 var day
= date
.getDate();
8821 var pattern
= /([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g;
8822 var matches
= pattern
.exec(offset
);
8824 switch (matches
[2] || 'd') {
8825 case 'd' : case 'D' :
8826 day
+= parseInt(matches
[1],10); break;
8827 case 'w' : case 'W' :
8828 day
+= parseInt(matches
[1],10) * 7; break;
8829 case 'm' : case 'M' :
8830 month
+= parseInt(matches
[1],10);
8831 day
= Math
.min(day
, $.datepicker
._getDaysInMonth(year
, month
));
8833 case 'y': case 'Y' :
8834 year
+= parseInt(matches
[1],10);
8835 day
= Math
.min(day
, $.datepicker
._getDaysInMonth(year
, month
));
8838 matches
= pattern
.exec(offset
);
8840 return new Date(year
, month
, day
);
8842 date
= (date
== null ? defaultDate
: (typeof date
== 'string' ? offsetString(date
) :
8843 (typeof date
== 'number' ? (isNaN(date
) ? defaultDate
: offsetNumeric(date
)) : date
)));
8844 date
= (date
&& date
.toString() == 'Invalid Date' ? defaultDate
: date
);
8849 date
.setMilliseconds(0);
8851 return this._daylightSavingAdjust(date
);
8854 /* Handle switch to/from daylight saving.
8855 Hours may be non-zero on daylight saving cut-over:
8856 > 12 when midnight changeover, but then cannot generate
8857 midnight datetime, so jump to 1AM, otherwise reset.
8858 @param date (Date) the date to check
8859 @return (Date) the corrected date */
8860 _daylightSavingAdjust: function(date
) {
8861 if (!date
) return null;
8862 date
.setHours(date
.getHours() > 12 ? date
.getHours() + 2 : 0);
8866 /* Set the date(s) directly. */
8867 _setDate: function(inst
, date
, noChange
) {
8868 var clear
= !(date
);
8869 var origMonth
= inst
.selectedMonth
;
8870 var origYear
= inst
.selectedYear
;
8871 date
= this._restrictMinMax(inst
, this._determineDate(inst
, date
, new Date()));
8872 inst
.selectedDay
= inst
.currentDay
= date
.getDate();
8873 inst
.drawMonth
= inst
.selectedMonth
= inst
.currentMonth
= date
.getMonth();
8874 inst
.drawYear
= inst
.selectedYear
= inst
.currentYear
= date
.getFullYear();
8875 if ((origMonth
!= inst
.selectedMonth
|| origYear
!= inst
.selectedYear
) && !noChange
)
8876 this._notifyChange(inst
);
8877 this._adjustInstDate(inst
);
8879 inst
.input
.val(clear
? '' : this._formatDate(inst
));
8883 /* Retrieve the date(s) directly. */
8884 _getDate: function(inst
) {
8885 var startDate
= (!inst
.currentYear
|| (inst
.input
&& inst
.input
.val() == '') ? null :
8886 this._daylightSavingAdjust(new Date(
8887 inst
.currentYear
, inst
.currentMonth
, inst
.currentDay
)));
8891 /* Generate the HTML for the current state of the date picker. */
8892 _generateHTML: function(inst
) {
8893 var today
= new Date();
8894 today
= this._daylightSavingAdjust(
8895 new Date(today
.getFullYear(), today
.getMonth(), today
.getDate())); // clear time
8896 var isRTL
= this._get(inst
, 'isRTL');
8897 var showButtonPanel
= this._get(inst
, 'showButtonPanel');
8898 var hideIfNoPrevNext
= this._get(inst
, 'hideIfNoPrevNext');
8899 var navigationAsDateFormat
= this._get(inst
, 'navigationAsDateFormat');
8900 var numMonths
= this._getNumberOfMonths(inst
);
8901 var showCurrentAtPos
= this._get(inst
, 'showCurrentAtPos');
8902 var stepMonths
= this._get(inst
, 'stepMonths');
8903 var isMultiMonth
= (numMonths
[0] != 1 || numMonths
[1] != 1);
8904 var currentDate
= this._daylightSavingAdjust((!inst
.currentDay
? new Date(9999, 9, 9) :
8905 new Date(inst
.currentYear
, inst
.currentMonth
, inst
.currentDay
)));
8906 var minDate
= this._getMinMaxDate(inst
, 'min');
8907 var maxDate
= this._getMinMaxDate(inst
, 'max');
8908 var drawMonth
= inst
.drawMonth
- showCurrentAtPos
;
8909 var drawYear
= inst
.drawYear
;
8910 if (drawMonth
< 0) {
8915 var maxDraw
= this._daylightSavingAdjust(new Date(maxDate
.getFullYear(),
8916 maxDate
.getMonth() - (numMonths
[0] * numMonths
[1]) + 1, maxDate
.getDate()));
8917 maxDraw
= (minDate
&& maxDraw
< minDate
? minDate
: maxDraw
);
8918 while (this._daylightSavingAdjust(new Date(drawYear
, drawMonth
, 1)) > maxDraw
) {
8920 if (drawMonth
< 0) {
8926 inst
.drawMonth
= drawMonth
;
8927 inst
.drawYear
= drawYear
;
8928 var prevText
= this._get(inst
, 'prevText');
8929 prevText
= (!navigationAsDateFormat
? prevText
: this.formatDate(prevText
,
8930 this._daylightSavingAdjust(new Date(drawYear
, drawMonth
- stepMonths
, 1)),
8931 this._getFormatConfig(inst
)));
8932 var prev
= (this._canAdjustMonth(inst
, -1, drawYear
, drawMonth
) ?
8933 '<a class="ui-datepicker-prev ui-corner-all" onclick="DP_jQuery_' + dpuuid
+
8934 '.datepicker._adjustDate(\'#' + inst
.id
+ '\', -' + stepMonths
+ ', \'M\');"' +
8935 ' title="' + prevText
+ '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL
? 'e' : 'w') + '">' + prevText
+ '</span></a>' :
8936 (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>'));
8937 var nextText
= this._get(inst
, 'nextText');
8938 nextText
= (!navigationAsDateFormat
? nextText
: this.formatDate(nextText
,
8939 this._daylightSavingAdjust(new Date(drawYear
, drawMonth
+ stepMonths
, 1)),
8940 this._getFormatConfig(inst
)));
8941 var next
= (this._canAdjustMonth(inst
, +1, drawYear
, drawMonth
) ?
8942 '<a class="ui-datepicker-next ui-corner-all" onclick="DP_jQuery_' + dpuuid
+
8943 '.datepicker._adjustDate(\'#' + inst
.id
+ '\', +' + stepMonths
+ ', \'M\');"' +
8944 ' title="' + nextText
+ '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL
? 'w' : 'e') + '">' + nextText
+ '</span></a>' :
8945 (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>'));
8946 var currentText
= this._get(inst
, 'currentText');
8947 var gotoDate
= (this._get(inst
, 'gotoCurrent') && inst
.currentDay
? currentDate
: today
);
8948 currentText
= (!navigationAsDateFormat
? currentText
:
8949 this.formatDate(currentText
, gotoDate
, this._getFormatConfig(inst
)));
8950 var controls
= (!inst
.inline
? '<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" onclick="DP_jQuery_' + dpuuid
+
8951 '.datepicker._hideDatepicker();">' + this._get(inst
, 'closeText') + '</button>' : '');
8952 var buttonPanel
= (showButtonPanel
) ? '<div class="ui-datepicker-buttonpane ui-widget-content">' + (isRTL
? controls
: '') +
8953 (this._isInRange(inst
, gotoDate
) ? '<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" onclick="DP_jQuery_' + dpuuid
+
8954 '.datepicker._gotoToday(\'#' + inst
.id
+ '\');"' +
8955 '>' + currentText
+ '</button>' : '') + (isRTL
? '' : controls
) + '</div>' : '';
8956 var firstDay
= parseInt(this._get(inst
, 'firstDay'),10);
8957 firstDay
= (isNaN(firstDay
) ? 0 : firstDay
);
8958 var showWeek
= this._get(inst
, 'showWeek');
8959 var dayNames
= this._get(inst
, 'dayNames');
8960 var dayNamesShort
= this._get(inst
, 'dayNamesShort');
8961 var dayNamesMin
= this._get(inst
, 'dayNamesMin');
8962 var monthNames
= this._get(inst
, 'monthNames');
8963 var monthNamesShort
= this._get(inst
, 'monthNamesShort');
8964 var beforeShowDay
= this._get(inst
, 'beforeShowDay');
8965 var showOtherMonths
= this._get(inst
, 'showOtherMonths');
8966 var selectOtherMonths
= this._get(inst
, 'selectOtherMonths');
8967 var calculateWeek
= this._get(inst
, 'calculateWeek') || this.iso8601Week
;
8968 var defaultDate
= this._getDefaultDate(inst
);
8970 for (var row
= 0; row
< numMonths
[0]; row
++) {
8972 for (var col
= 0; col
< numMonths
[1]; col
++) {
8973 var selectedDate
= this._daylightSavingAdjust(new Date(drawYear
, drawMonth
, inst
.selectedDay
));
8974 var cornerClass
= ' ui-corner-all';
8977 calender
+= '<div class="ui-datepicker-group';
8978 if (numMonths
[1] > 1)
8980 case 0: calender
+= ' ui-datepicker-group-first';
8981 cornerClass
= ' ui-corner-' + (isRTL
? 'right' : 'left'); break;
8982 case numMonths
[1]-1: calender
+= ' ui-datepicker-group-last';
8983 cornerClass
= ' ui-corner-' + (isRTL
? 'left' : 'right'); break;
8984 default: calender
+= ' ui-datepicker-group-middle'; cornerClass
= ''; break;
8988 calender
+= '<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix' + cornerClass
+ '">' +
8989 (/all|left/.test(cornerClass
) && row
== 0 ? (isRTL
? next
: prev
) : '') +
8990 (/all|right/.test(cornerClass
) && row
== 0 ? (isRTL
? prev
: next
) : '') +
8991 this._generateMonthYearHeader(inst
, drawMonth
, drawYear
, minDate
, maxDate
,
8992 row
> 0 || col
> 0, monthNames
, monthNamesShort
) + // draw month headers
8993 '</div><table class="ui-datepicker-calendar"><thead>' +
8995 var thead
= (showWeek
? '<th class="ui-datepicker-week-col">' + this._get(inst
, 'weekHeader') + '</th>' : '');
8996 for (var dow
= 0; dow
< 7; dow
++) { // days of the week
8997 var day
= (dow
+ firstDay
) % 7;
8998 thead
+= '<th' + ((dow
+ firstDay
+ 6) % 7 >= 5 ? ' class="ui-datepicker-week-end"' : '') + '>' +
8999 '<span title="' + dayNames
[day
] + '">' + dayNamesMin
[day
] + '</span></th>';
9001 calender
+= thead
+ '</tr></thead><tbody>';
9002 var daysInMonth
= this._getDaysInMonth(drawYear
, drawMonth
);
9003 if (drawYear
== inst
.selectedYear
&& drawMonth
== inst
.selectedMonth
)
9004 inst
.selectedDay
= Math
.min(inst
.selectedDay
, daysInMonth
);
9005 var leadDays
= (this._getFirstDayOfMonth(drawYear
, drawMonth
) - firstDay
+ 7) % 7;
9006 var numRows
= (isMultiMonth
? 6 : Math
.ceil((leadDays
+ daysInMonth
) / 7)); // calculate the number of rows to generate
9007 var printDate
= this._daylightSavingAdjust(new Date(drawYear
, drawMonth
, 1 - leadDays
));
9008 for (var dRow
= 0; dRow
< numRows
; dRow
++) { // create date picker rows
9010 var tbody
= (!showWeek
? '' : '<td class="ui-datepicker-week-col">' +
9011 this._get(inst
, 'calculateWeek')(printDate
) + '</td>');
9012 for (var dow
= 0; dow
< 7; dow
++) { // create date picker days
9013 var daySettings
= (beforeShowDay
?
9014 beforeShowDay
.apply((inst
.input
? inst
.input
[0] : null), [printDate
]) : [true, '']);
9015 var otherMonth
= (printDate
.getMonth() != drawMonth
);
9016 var unselectable
= (otherMonth
&& !selectOtherMonths
) || !daySettings
[0] ||
9017 (minDate
&& printDate
< minDate
) || (maxDate
&& printDate
> maxDate
);
9018 tbody
+= '<td class="' +
9019 ((dow
+ firstDay
+ 6) % 7 >= 5 ? ' ui-datepicker-week-end' : '') + // highlight weekends
9020 (otherMonth
? ' ui-datepicker-other-month' : '') + // highlight days from other months
9021 ((printDate
.getTime() == selectedDate
.getTime() && drawMonth
== inst
.selectedMonth
&& inst
._keyEvent
) || // user pressed key
9022 (defaultDate
.getTime() == printDate
.getTime() && defaultDate
.getTime() == selectedDate
.getTime()) ?
9023 // or defaultDate is current printedDate and defaultDate is selectedDate
9024 ' ' + this._dayOverClass
: '') + // highlight selected day
9025 (unselectable
? ' ' + this._unselectableClass
+ ' ui-state-disabled': '') + // highlight unselectable days
9026 (otherMonth
&& !showOtherMonths
? '' : ' ' + daySettings
[1] + // highlight custom dates
9027 (printDate
.getTime() == currentDate
.getTime() ? ' ' + this._currentClass
: '') + // highlight selected day
9028 (printDate
.getTime() == today
.getTime() ? ' ui-datepicker-today' : '')) + '"' + // highlight today (if different)
9029 ((!otherMonth
|| showOtherMonths
) && daySettings
[2] ? ' title="' + daySettings
[2] + '"' : '') + // cell title
9030 (unselectable
? '' : ' onclick="DP_jQuery_' + dpuuid
+ '.datepicker._selectDay(\'#' +
9031 inst
.id
+ '\',' + printDate
.getMonth() + ',' + printDate
.getFullYear() + ', this);return false;"') + '>' + // actions
9032 (otherMonth
&& !showOtherMonths
? ' ' : // display for other months
9033 (unselectable
? '<span class="ui-state-default">' + printDate
.getDate() + '</span>' : '<a class="ui-state-default' +
9034 (printDate
.getTime() == today
.getTime() ? ' ui-state-highlight' : '') +
9035 (printDate
.getTime() == currentDate
.getTime() ? ' ui-state-active' : '') + // highlight selected day
9036 (otherMonth
? ' ui-priority-secondary' : '') + // distinguish dates from other months
9037 '" href="#">' + printDate
.getDate() + '</a>')) + '</td>'; // display selectable date
9038 printDate
.setDate(printDate
.getDate() + 1);
9039 printDate
= this._daylightSavingAdjust(printDate
);
9041 calender
+= tbody
+ '</tr>';
9044 if (drawMonth
> 11) {
9048 calender
+= '</tbody></table>' + (isMultiMonth
? '</div>' +
9049 ((numMonths
[0] > 0 && col
== numMonths
[1]-1) ? '<div class="ui-datepicker-row-break"></div>' : '') : '');
9054 html
+= buttonPanel
+ ($.browser
.msie
&& parseInt($.browser
.version
,10) < 7 && !inst
.inline
?
9055 '<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>' : '');
9056 inst
._keyEvent
= false;
9060 /* Generate the month and year header. */
9061 _generateMonthYearHeader: function(inst
, drawMonth
, drawYear
, minDate
, maxDate
,
9062 secondary
, monthNames
, monthNamesShort
) {
9063 var changeMonth
= this._get(inst
, 'changeMonth');
9064 var changeYear
= this._get(inst
, 'changeYear');
9065 var showMonthAfterYear
= this._get(inst
, 'showMonthAfterYear');
9066 var html
= '<div class="ui-datepicker-title">';
9069 if (secondary
|| !changeMonth
)
9070 monthHtml
+= '<span class="ui-datepicker-month">' + monthNames
[drawMonth
] + '</span>';
9072 var inMinYear
= (minDate
&& minDate
.getFullYear() == drawYear
);
9073 var inMaxYear
= (maxDate
&& maxDate
.getFullYear() == drawYear
);
9074 monthHtml
+= '<select class="ui-datepicker-month" ' +
9075 'onchange="DP_jQuery_' + dpuuid
+ '.datepicker._selectMonthYear(\'#' + inst
.id
+ '\', this, \'M\');" ' +
9076 'onclick="DP_jQuery_' + dpuuid
+ '.datepicker._clickMonthYear(\'#' + inst
.id
+ '\');"' +
9078 for (var month
= 0; month
< 12; month
++) {
9079 if ((!inMinYear
|| month
>= minDate
.getMonth()) &&
9080 (!inMaxYear
|| month
<= maxDate
.getMonth()))
9081 monthHtml
+= '<option value="' + month
+ '"' +
9082 (month
== drawMonth
? ' selected="selected"' : '') +
9083 '>' + monthNamesShort
[month
] + '</option>';
9085 monthHtml
+= '</select>';
9087 if (!showMonthAfterYear
)
9088 html
+= monthHtml
+ (secondary
|| !(changeMonth
&& changeYear
) ? ' ' : '');
9090 if (secondary
|| !changeYear
)
9091 html
+= '<span class="ui-datepicker-year">' + drawYear
+ '</span>';
9093 // determine range of years to display
9094 var years
= this._get(inst
, 'yearRange').split(':');
9095 var thisYear
= new Date().getFullYear();
9096 var determineYear = function(value
) {
9097 var year
= (value
.match(/c[+-].*/) ? drawYear
+ parseInt(value
.substring(1), 10) :
9098 (value
.match(/[+-].*/) ? thisYear
+ parseInt(value
, 10) :
9099 parseInt(value
, 10)));
9100 return (isNaN(year
) ? thisYear
: year
);
9102 var year
= determineYear(years
[0]);
9103 var endYear
= Math
.max(year
, determineYear(years
[1] || ''));
9104 year
= (minDate
? Math
.max(year
, minDate
.getFullYear()) : year
);
9105 endYear
= (maxDate
? Math
.min(endYear
, maxDate
.getFullYear()) : endYear
);
9106 html
+= '<select class="ui-datepicker-year" ' +
9107 'onchange="DP_jQuery_' + dpuuid
+ '.datepicker._selectMonthYear(\'#' + inst
.id
+ '\', this, \'Y\');" ' +
9108 'onclick="DP_jQuery_' + dpuuid
+ '.datepicker._clickMonthYear(\'#' + inst
.id
+ '\');"' +
9110 for (; year
<= endYear
; year
++) {
9111 html
+= '<option value="' + year
+ '"' +
9112 (year
== drawYear
? ' selected="selected"' : '') +
9113 '>' + year
+ '</option>';
9115 html
+= '</select>';
9117 html
+= this._get(inst
, 'yearSuffix');
9118 if (showMonthAfterYear
)
9119 html
+= (secondary
|| !(changeMonth
&& changeYear
) ? ' ' : '') + monthHtml
;
9120 html
+= '</div>'; // Close datepicker_header
9124 /* Adjust one of the date sub-fields. */
9125 _adjustInstDate: function(inst
, offset
, period
) {
9126 var year
= inst
.drawYear
+ (period
== 'Y' ? offset
: 0);
9127 var month
= inst
.drawMonth
+ (period
== 'M' ? offset
: 0);
9128 var day
= Math
.min(inst
.selectedDay
, this._getDaysInMonth(year
, month
)) +
9129 (period
== 'D' ? offset
: 0);
9130 var date
= this._restrictMinMax(inst
,
9131 this._daylightSavingAdjust(new Date(year
, month
, day
)));
9132 inst
.selectedDay
= date
.getDate();
9133 inst
.drawMonth
= inst
.selectedMonth
= date
.getMonth();
9134 inst
.drawYear
= inst
.selectedYear
= date
.getFullYear();
9135 if (period
== 'M' || period
== 'Y')
9136 this._notifyChange(inst
);
9139 /* Ensure a date is within any min/max bounds. */
9140 _restrictMinMax: function(inst, date) {
9141 var minDate = this._getMinMaxDate(inst, 'min');
9142 var maxDate = this._getMinMaxDate(inst, 'max');
9143 date = (minDate && date < minDate ? minDate : date);
9144 date = (maxDate && date > maxDate ? maxDate : date);
9148 /* Notify change of month/year. */
9149 _notifyChange: function(inst) {
9150 var onChange = this._get(inst, 'onChangeMonthYear');
9152 onChange.apply((inst.input ? inst.input[0] : null),
9153 [inst.selectedYear, inst.selectedMonth + 1, inst]);
9156 /* Determine the number of months to show. */
9157 _getNumberOfMonths: function(inst
) {
9158 var numMonths
= this._get(inst
, 'numberOfMonths');
9159 return (numMonths
== null ? [1, 1] : (typeof numMonths
== 'number' ? [1, numMonths
] : numMonths
));
9162 /* Determine the current maximum date - ensure no time components are set. */
9163 _getMinMaxDate: function(inst
, minMax
) {
9164 return this._determineDate(inst
, this._get(inst
, minMax
+ 'Date'), null);
9167 /* Find the number of days in a given month. */
9168 _getDaysInMonth: function(year
, month
) {
9169 return 32 - new Date(year
, month
, 32).getDate();
9172 /* Find the day of the week of the first of a month. */
9173 _getFirstDayOfMonth: function(year
, month
) {
9174 return new Date(year
, month
, 1).getDay();
9177 /* Determines if we should allow a "next/prev" month display change. */
9178 _canAdjustMonth: function(inst, offset, curYear, curMonth) {
9179 var numMonths = this._getNumberOfMonths(inst);
9180 var date = this._daylightSavingAdjust(new Date(curYear,
9181 curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1));
9183 date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
9184 return this._isInRange(inst, date);
9187 /* Is the given date in the accepted range? */
9188 _isInRange: function(inst
, date
) {
9189 var minDate
= this._getMinMaxDate(inst
, 'min');
9190 var maxDate
= this._getMinMaxDate(inst
, 'max');
9191 return ((!minDate
|| date
.getTime() >= minDate
.getTime()) &&
9192 (!maxDate
|| date
.getTime() <= maxDate
.getTime()));
9195 /* Provide the configuration settings for formatting/parsing. */
9196 _getFormatConfig: function(inst) {
9197 var shortYearCutoff = this._get(inst, 'shortYearCutoff');
9198 shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff :
9199 new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
9200 return {shortYearCutoff: shortYearCutoff,
9201 dayNamesShort: this._get(inst, 'dayNamesShort'), dayNames: this._get(inst, 'dayNames'),
9202 monthNamesShort: this._get(inst, 'monthNamesShort'), monthNames: this._get(inst, 'monthNames')};
9205 /* Format the given date for display. */
9206 _formatDate: function(inst
, day
, month
, year
) {
9208 inst
.currentDay
= inst
.selectedDay
;
9209 inst
.currentMonth
= inst
.selectedMonth
;
9210 inst
.currentYear
= inst
.selectedYear
;
9212 var date
= (day
? (typeof day
== 'object' ? day
:
9213 this._daylightSavingAdjust(new Date(year
, month
, day
))) :
9214 this._daylightSavingAdjust(new Date(inst
.currentYear
, inst
.currentMonth
, inst
.currentDay
)));
9215 return this.formatDate(this._get(inst
, 'dateFormat'), date
, this._getFormatConfig(inst
));
9219 /* jQuery extend now ignores nulls! */
9220 function extendRemove(target
, props
) {
9221 $.extend(target
, props
);
9222 for (var name
in props
)
9223 if (props
[name
] == null || props
[name
] == undefined)
9224 target
[name
] = props
[name
];
9228 /* Determine whether an object is an array. */
9229 function isArray(a
) {
9230 return (a
&& (($.browser
.safari
&& typeof a
== 'object' && a
.length
) ||
9231 (a
.constructor && a
.constructor.toString().match(/\Array\(\)/))));
9234 /* Invoke the datepicker functionality.
9235 @param options string - a command, optionally followed by additional parameters or
9236 Object - settings for attaching new datepicker functionality
9237 @return jQuery object */
9238 $.fn
.datepicker = function(options
){
9240 /* Initialise the date picker. */
9241 if (!$.datepicker
.initialized
) {
9242 $(document
).mousedown($.datepicker
._checkExternalClick
).
9243 find('body').append($.datepicker
.dpDiv
);
9244 $.datepicker
.initialized
= true;
9247 var otherArgs
= Array
.prototype.slice
.call(arguments
, 1);
9248 if (typeof options
== 'string' && (options
== 'isDisabled' || options
== 'getDate' || options
== 'widget'))
9249 return $.datepicker
['_' + options
+ 'Datepicker'].
9250 apply($.datepicker
, [this[0]].concat(otherArgs
));
9251 if (options
== 'option' && arguments
.length
== 2 && typeof arguments
[1] == 'string')
9252 return $.datepicker
['_' + options
+ 'Datepicker'].
9253 apply($.datepicker
, [this[0]].concat(otherArgs
));
9254 return this.each(function() {
9255 typeof options
== 'string' ?
9256 $.datepicker
['_' + options
+ 'Datepicker'].
9257 apply($.datepicker
, [this].concat(otherArgs
)) :
9258 $.datepicker
._attachDatepicker(this, options
);
9262 $.datepicker
= new Datepicker(); // singleton instance
9263 $.datepicker
.initialized
= false;
9264 $.datepicker
.uuid
= new Date().getTime();
9265 $.datepicker
.version
= "1.8";
9267 // Workaround for #4055
9268 // Add another global to avoid noConflict issues with inline event handlers
9269 window
['DP_jQuery_' + dpuuid
] = $;
9273 * jQuery UI Progressbar 1.8
9275 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
9276 * Dual licensed under the MIT (MIT-LICENSE.txt)
9277 * and GPL (GPL-LICENSE.txt) licenses.
9279 * http://docs.jquery.com/UI/Progressbar
9283 * jquery.ui.widget.js
9287 $.widget( "ui.progressbar", {
9291 _create: function() {
9293 .addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
9295 role
: "progressbar",
9296 "aria-valuemin": this._valueMin(),
9297 "aria-valuemax": this._valueMax(),
9298 "aria-valuenow": this._value()
9301 this.valueDiv
= $( "<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>" )
9302 .appendTo( this.element
);
9304 this._refreshValue();
9307 destroy: function() {
9309 .removeClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
9310 .removeAttr( "role" )
9311 .removeAttr( "aria-valuemin" )
9312 .removeAttr( "aria-valuemax" )
9313 .removeAttr( "aria-valuenow" );
9315 this.valueDiv
.remove();
9317 $.Widget
.prototype.destroy
.apply( this, arguments
);
9320 value: function( newValue
) {
9321 if ( newValue
=== undefined ) {
9322 return this._value();
9325 this._setOption( "value", newValue
);
9329 _setOption: function( key
, value
) {
9332 this.options
.value
= value
;
9333 this._refreshValue();
9334 this._trigger( "change" );
9338 $.Widget
.prototype._setOption
.apply( this, arguments
);
9341 _value: function() {
9342 var val
= this.options
.value
;
9343 // normalize invalid value
9344 if ( typeof val
!== "number" ) {
9347 if ( val
< this._valueMin() ) {
9348 val
= this._valueMin();
9350 if ( val
> this._valueMax() ) {
9351 val
= this._valueMax();
9357 _valueMin: function() {
9361 _valueMax: function() {
9365 _refreshValue: function() {
9366 var value
= this.value();
9368 [ value
=== this._valueMax() ? "addClass" : "removeClass"]( "ui-corner-right" )
9369 .width( value
+ "%" );
9370 this.element
.attr( "aria-valuenow", value
);
9374 $.extend( $.ui
.progressbar
, {
9380 * jQuery UI Effects 1.8
9382 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
9383 * Dual licensed under the MIT (MIT-LICENSE.txt)
9384 * and GPL (GPL-LICENSE.txt) licenses.
9386 * http://docs.jquery.com/UI/Effects/
9388 ;jQuery
.effects
|| (function($) {
9394 /******************************************************************************/
9395 /****************************** COLOR ANIMATIONS ******************************/
9396 /******************************************************************************/
9398 // override the animation for color styles
9399 $.each(['backgroundColor', 'borderBottomColor', 'borderLeftColor',
9400 'borderRightColor', 'borderTopColor', 'color', 'outlineColor'],
9402 $.fx
.step
[attr
] = function(fx
) {
9403 if (!fx
.colorInit
) {
9404 fx
.start
= getColor(fx
.elem
, attr
);
9405 fx
.end
= getRGB(fx
.end
);
9406 fx
.colorInit
= true;
9409 fx
.elem
.style
[attr
] = 'rgb(' +
9410 Math
.max(Math
.min(parseInt((fx
.pos
* (fx
.end
[0] - fx
.start
[0])) + fx
.start
[0], 10), 255), 0) + ',' +
9411 Math
.max(Math
.min(parseInt((fx
.pos
* (fx
.end
[1] - fx
.start
[1])) + fx
.start
[1], 10), 255), 0) + ',' +
9412 Math
.max(Math
.min(parseInt((fx
.pos
* (fx
.end
[2] - fx
.start
[2])) + fx
.start
[2], 10), 255), 0) + ')';
9416 // Color Conversion functions from highlightFade
9417 // By Blair Mitchelmore
9418 // http://jquery.offput.ca/highlightFade/
9420 // Parse strings looking for color tuples [255,255,255]
9421 function getRGB(color
) {
9424 // Check if we're already dealing with an array of colors
9425 if ( color
&& color
.constructor == Array
&& color
.length
== 3 )
9428 // Look for rgb(num,num,num)
9429 if (result
= /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(color
))
9430 return [parseInt(result
[1],10), parseInt(result
[2],10), parseInt(result
[3],10)];
9432 // Look for rgb(num%,num%,num%)
9433 if (result
= /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(color
))
9434 return [parseFloat(result
[1])*2.55, parseFloat(result
[2])*2.55, parseFloat(result
[3])*2.55];
9437 if (result
= /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(color
))
9438 return [parseInt(result
[1],16), parseInt(result
[2],16), parseInt(result
[3],16)];
9441 if (result
= /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(color
))
9442 return [parseInt(result
[1]+result
[1],16), parseInt(result
[2]+result
[2],16), parseInt(result
[3]+result
[3],16)];
9444 // Look for rgba(0, 0, 0, 0) == transparent in Safari 3
9445 if (result
= /rgba\(0, 0, 0, 0\)/.exec(color
))
9446 return colors
['transparent'];
9448 // Otherwise, we're most likely dealing with a named color
9449 return colors
[$.trim(color
).toLowerCase()];
9452 function getColor(elem
, attr
) {
9456 color
= $.curCSS(elem
, attr
);
9458 // Keep going until we find an element that has color, or we hit the body
9459 if ( color
!= '' && color
!= 'transparent' || $.nodeName(elem
, "body") )
9462 attr
= "backgroundColor";
9463 } while ( elem
= elem
.parentNode
);
9465 return getRGB(color
);
9468 // Some named colors to work with
9469 // From Interface by Stefan Petre
9470 // http://interface.eyecon.ro/
9474 azure
:[240,255,255],
9475 beige
:[245,245,220],
9481 darkcyan
:[0,139,139],
9482 darkgrey
:[169,169,169],
9483 darkgreen
:[0,100,0],
9484 darkkhaki
:[189,183,107],
9485 darkmagenta
:[139,0,139],
9486 darkolivegreen
:[85,107,47],
9487 darkorange
:[255,140,0],
9488 darkorchid
:[153,50,204],
9490 darksalmon
:[233,150,122],
9491 darkviolet
:[148,0,211],
9492 fuchsia
:[255,0,255],
9496 khaki
:[240,230,140],
9497 lightblue
:[173,216,230],
9498 lightcyan
:[224,255,255],
9499 lightgreen
:[144,238,144],
9500 lightgrey
:[211,211,211],
9501 lightpink
:[255,182,193],
9502 lightyellow
:[255,255,224],
9504 magenta
:[255,0,255],
9513 silver
:[192,192,192],
9514 white
:[255,255,255],
9516 transparent
: [255,255,255]
9521 /******************************************************************************/
9522 /****************************** CLASS ANIMATIONS ******************************/
9523 /******************************************************************************/
9525 var classAnimationActions
= ['add', 'remove', 'toggle'],
9538 function getElementStyles() {
9539 var style
= document
.defaultView
9540 ? document
.defaultView
.getComputedStyle(this, null)
9541 : this.currentStyle
,
9546 // webkit enumerates style porperties
9547 if (style
&& style
.length
&& style
[0] && style
[style
[0]]) {
9548 var len
= style
.length
;
9551 if (typeof style
[key
] == 'string') {
9552 camelCase
= key
.replace(/\-(\w)/g, function(all
, letter
){
9553 return letter
.toUpperCase();
9555 newStyle
[camelCase
] = style
[key
];
9559 for (key
in style
) {
9560 if (typeof style
[key
] === 'string') {
9561 newStyle
[key
] = style
[key
];
9569 function filterStyles(styles
) {
9571 for (name
in styles
) {
9572 value
= styles
[name
];
9574 // ignore null and undefined values
9576 // ignore functions (when does this occur?)
9577 $.isFunction(value
) ||
9578 // shorthand styles that need to be expanded
9579 name
in shorthandStyles
||
9580 // ignore scrollbars (break in IE)
9581 (/scrollbar/).test(name
) ||
9583 // only colors or values that can be converted to numbers
9584 (!(/color/i).test(name
) && isNaN(parseFloat(value
)))
9586 delete styles
[name
];
9593 function styleDifference(oldStyle
, newStyle
) {
9594 var diff
= { _
: 0 }, // http://dev.jquery.com/ticket/5459
9597 for (name
in newStyle
) {
9598 if (oldStyle
[name
] != newStyle
[name
]) {
9599 diff
[name
] = newStyle
[name
];
9606 $.effects
.animateClass = function(value
, duration
, easing
, callback
) {
9607 if ($.isFunction(easing
)) {
9612 return this.each(function() {
9615 originalStyleAttr
= that
.attr('style') || ' ',
9616 originalStyle
= filterStyles(getElementStyles
.call(this)),
9618 className
= that
.attr('className');
9620 $.each(classAnimationActions
, function(i
, action
) {
9621 if (value
[action
]) {
9622 that
[action
+ 'Class'](value
[action
]);
9625 newStyle
= filterStyles(getElementStyles
.call(this));
9626 that
.attr('className', className
);
9628 that
.animate(styleDifference(originalStyle
, newStyle
), duration
, easing
, function() {
9629 $.each(classAnimationActions
, function(i
, action
) {
9630 if (value
[action
]) { that
[action
+ 'Class'](value
[action
]); }
9632 // work around bug in IE by clearing the cssText before setting it
9633 if (typeof that
.attr('style') == 'object') {
9634 that
.attr('style').cssText
= '';
9635 that
.attr('style').cssText
= originalStyleAttr
;
9637 that
.attr('style', originalStyleAttr
);
9639 if (callback
) { callback
.apply(this, arguments
); }
9645 _addClass
: $.fn
.addClass
,
9646 addClass: function(classNames
, speed
, easing
, callback
) {
9647 return speed
? $.effects
.animateClass
.apply(this, [{ add
: classNames
},speed
,easing
,callback
]) : this._addClass(classNames
);
9650 _removeClass
: $.fn
.removeClass
,
9651 removeClass: function(classNames
,speed
,easing
,callback
) {
9652 return speed
? $.effects
.animateClass
.apply(this, [{ remove
: classNames
},speed
,easing
,callback
]) : this._removeClass(classNames
);
9655 _toggleClass
: $.fn
.toggleClass
,
9656 toggleClass: function(classNames
, force
, speed
, easing
, callback
) {
9657 if ( typeof force
== "boolean" || force
=== undefined ) {
9659 // without speed parameter;
9660 return this._toggleClass(classNames
, force
);
9662 return $.effects
.animateClass
.apply(this, [(force
?{add
:classNames
}:{remove
:classNames
}),speed
,easing
,callback
]);
9665 // without switch parameter;
9666 return $.effects
.animateClass
.apply(this, [{ toggle
: classNames
},force
,speed
,easing
]);
9670 switchClass: function(remove
,add
,speed
,easing
,callback
) {
9671 return $.effects
.animateClass
.apply(this, [{ add
: add
, remove
: remove
},speed
,easing
,callback
]);
9677 /******************************************************************************/
9678 /*********************************** EFFECTS **********************************/
9679 /******************************************************************************/
9681 $.extend($.effects
, {
9684 // Saves a set of properties in a data storage
9685 save: function(element
, set) {
9686 for(var i
=0; i
< set.length
; i
++) {
9687 if(set[i
] !== null) element
.data("ec.storage."+set[i
], element
[0].style
[set[i
]]);
9691 // Restores a set of previously saved properties from a data storage
9692 restore: function(element
, set) {
9693 for(var i
=0; i
< set.length
; i
++) {
9694 if(set[i
] !== null) element
.css(set[i
], element
.data("ec.storage."+set[i
]));
9698 setMode: function(el
, mode
) {
9699 if (mode
== 'toggle') mode
= el
.is(':hidden') ? 'show' : 'hide'; // Set for toggle
9703 getBaseline: function(origin
, original
) { // Translates a [top,left] array into a baseline value
9704 // this should be a little more flexible in the future to handle a string & hash
9706 switch (origin
[0]) {
9707 case 'top': y
= 0; break;
9708 case 'middle': y
= 0.5; break;
9709 case 'bottom': y
= 1; break;
9710 default: y
= origin
[0] / original
.height
;
9712 switch (origin
[1]) {
9713 case 'left': x
= 0; break;
9714 case 'center': x
= 0.5; break;
9715 case 'right': x
= 1; break;
9716 default: x
= origin
[1] / original
.width
;
9718 return {x
: x
, y
: y
};
9721 // Wraps the element around a wrapper that copies position properties
9722 createWrapper: function(element
) {
9724 // if the element is already wrapped, return it
9725 if (element
.parent().is('.ui-effects-wrapper')) {
9726 return element
.parent();
9731 width
: element
.outerWidth(true),
9732 height
: element
.outerHeight(true),
9733 'float': element
.css('float')
9735 wrapper
= $('<div></div>')
9736 .addClass('ui-effects-wrapper')
9739 background
: 'transparent',
9745 element
.wrap(wrapper
);
9746 wrapper
= element
.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually loose the reference to the wrapped element
9748 // transfer positioning properties to the wrapper
9749 if (element
.css('position') == 'static') {
9750 wrapper
.css({ position
: 'relative' });
9751 element
.css({ position
: 'relative' });
9754 position
: element
.css('position'),
9755 zIndex
: element
.css('z-index')
9757 $.each(['top', 'left', 'bottom', 'right'], function(i
, pos
) {
9758 props
[pos
] = element
.css(pos
);
9759 if (isNaN(parseInt(props
[pos
], 10))) {
9760 props
[pos
] = 'auto';
9763 element
.css({position
: 'relative', top
: 0, left
: 0 });
9766 return wrapper
.css(props
).show();
9769 removeWrapper: function(element
) {
9770 if (element
.parent().is('.ui-effects-wrapper'))
9771 return element
.parent().replaceWith(element
);
9775 setTransition: function(element
, list
, factor
, value
) {
9776 value
= value
|| {};
9777 $.each(list
, function(i
, x
){
9778 unit
= element
.cssUnit(x
);
9779 if (unit
[0] > 0) value
[x
] = unit
[0] * factor
+ unit
[1];
9786 function _normalizeArguments(effect
, options
, speed
, callback
) {
9787 // shift params for method overloading
9788 if (typeof effect
== 'object') {
9792 effect
= options
.effect
;
9794 if ($.isFunction(options
)) {
9799 if ($.isFunction(speed
)) {
9803 if (typeof options
== 'number' || $.fx
.speeds
[options
]) {
9809 options
= options
|| {};
9811 speed
= speed
|| options
.duration
;
9812 speed
= $.fx
.off
? 0 : typeof speed
== 'number'
9813 ? speed
: $.fx
.speeds
[speed
] || $.fx
.speeds
._default
;
9815 callback
= callback
|| options
.complete
;
9817 return [effect
, options
, speed
, callback
];
9821 effect: function(effect
, options
, speed
, callback
) {
9822 var args
= _normalizeArguments
.apply(this, arguments
),
9823 // TODO: make effects takes actual parameters instead of a hash
9829 effectMethod
= $.effects
[effect
];
9831 return effectMethod
&& !$.fx
.off
? effectMethod
.call(this, args2
) : this;
9835 show: function(speed
) {
9836 if (!speed
|| typeof speed
== 'number' || $.fx
.speeds
[speed
]) {
9837 return this._show
.apply(this, arguments
);
9839 var args
= _normalizeArguments
.apply(this, arguments
);
9840 args
[1].mode
= 'show';
9841 return this.effect
.apply(this, args
);
9846 hide: function(speed
) {
9847 if (!speed
|| typeof speed
== 'number' || $.fx
.speeds
[speed
]) {
9848 return this._hide
.apply(this, arguments
);
9850 var args
= _normalizeArguments
.apply(this, arguments
);
9851 args
[1].mode
= 'hide';
9852 return this.effect
.apply(this, args
);
9856 // jQuery core overloads toggle and create _toggle
9857 __toggle
: $.fn
.toggle
,
9858 toggle: function(speed
) {
9859 if (!speed
|| typeof speed
== 'number' || $.fx
.speeds
[speed
] ||
9860 typeof speed
== 'boolean' || $.isFunction(speed
)) {
9861 return this.__toggle
.apply(this, arguments
);
9863 var args
= _normalizeArguments
.apply(this, arguments
);
9864 args
[1].mode
= 'toggle';
9865 return this.effect
.apply(this, args
);
9870 cssUnit: function(key
) {
9871 var style
= this.css(key
), val
= [];
9872 $.each( ['em','px','%','pt'], function(i
, unit
){
9873 if(style
.indexOf(unit
) > 0)
9874 val
= [parseFloat(style
), unit
];
9882 /******************************************************************************/
9883 /*********************************** EASING ***********************************/
9884 /******************************************************************************/
9887 * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
9889 * Uses the built in easing capabilities added In jQuery 1.1
9890 * to offer multiple easing options
9892 * TERMS OF USE - jQuery Easing
9894 * Open source under the BSD License.
9896 * Copyright 2008 George McGinley Smith
9897 * All rights reserved.
9899 * Redistribution and use in source and binary forms, with or without modification,
9900 * are permitted provided that the following conditions are met:
9902 * Redistributions of source code must retain the above copyright notice, this list of
9903 * conditions and the following disclaimer.
9904 * Redistributions in binary form must reproduce the above copyright notice, this list
9905 * of conditions and the following disclaimer in the documentation and/or other materials
9906 * provided with the distribution.
9908 * Neither the name of the author nor the names of contributors may be used to endorse
9909 * or promote products derived from this software without specific prior written permission.
9911 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
9912 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
9913 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
9914 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
9915 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
9916 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
9917 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
9918 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
9919 * OF THE POSSIBILITY OF SUCH DAMAGE.
9923 // t: current time, b: begInnIng value, c: change In value, d: duration
9924 $.easing
.jswing
= $.easing
.swing
;
9929 swing: function (x
, t
, b
, c
, d
) {
9930 //alert($.easing.default);
9931 return $.easing
[$.easing
.def
](x
, t
, b
, c
, d
);
9933 easeInQuad: function (x
, t
, b
, c
, d
) {
9934 return c
*(t
/=d
)*t
+ b
;
9936 easeOutQuad: function (x
, t
, b
, c
, d
) {
9937 return -c
*(t
/=d
)*(t
-2) + b
;
9939 easeInOutQuad: function (x
, t
, b
, c
, d
) {
9940 if ((t
/=d/2) < 1) return c
/2*t
*t
+ b
;
9941 return -c
/2 * ((--t
)*(t
-2) - 1) + b
;
9943 easeInCubic: function (x
, t
, b
, c
, d
) {
9944 return c
*(t
/=d
)*t
*t
+ b
;
9946 easeOutCubic: function (x
, t
, b
, c
, d
) {
9947 return c
*((t
=t
/d
-1)*t
*t
+ 1) + b
;
9949 easeInOutCubic: function (x
, t
, b
, c
, d
) {
9950 if ((t
/=d/2) < 1) return c
/2*t
*t
*t
+ b
;
9951 return c
/2*((t
-=2)*t
*t
+ 2) + b
;
9953 easeInQuart: function (x
, t
, b
, c
, d
) {
9954 return c
*(t
/=d
)*t
*t
*t
+ b
;
9956 easeOutQuart: function (x
, t
, b
, c
, d
) {
9957 return -c
* ((t
=t
/d
-1)*t
*t
*t
- 1) + b
;
9959 easeInOutQuart: function (x
, t
, b
, c
, d
) {
9960 if ((t
/=d/2) < 1) return c
/2*t
*t
*t
*t
+ b
;
9961 return -c
/2 * ((t
-=2)*t
*t
*t
- 2) + b
;
9963 easeInQuint: function (x
, t
, b
, c
, d
) {
9964 return c
*(t
/=d
)*t
*t
*t
*t
+ b
;
9966 easeOutQuint: function (x
, t
, b
, c
, d
) {
9967 return c
*((t
=t
/d
-1)*t
*t
*t
*t
+ 1) + b
;
9969 easeInOutQuint: function (x
, t
, b
, c
, d
) {
9970 if ((t
/=d/2) < 1) return c
/2*t
*t
*t
*t
*t
+ b
;
9971 return c
/2*((t
-=2)*t
*t
*t
*t
+ 2) + b
;
9973 easeInSine: function (x
, t
, b
, c
, d
) {
9974 return -c
* Math
.cos(t
/d * (Math.PI/2)) + c
+ b
;
9976 easeOutSine: function (x
, t
, b
, c
, d
) {
9977 return c
* Math
.sin(t
/d * (Math.PI/2)) + b
;
9979 easeInOutSine: function (x
, t
, b
, c
, d
) {
9980 return -c
/2 * (Math.cos(Math.PI*t/d) - 1) + b
;
9982 easeInExpo: function (x
, t
, b
, c
, d
) {
9983 return (t
==0) ? b
: c
* Math
.pow(2, 10 * (t
/d
- 1)) + b
;
9985 easeOutExpo: function (x
, t
, b
, c
, d
) {
9986 return (t
==d
) ? b
+c
: c
* (-Math
.pow(2, -10 * t
/d
) + 1) + b
;
9988 easeInOutExpo: function (x
, t
, b
, c
, d
) {
9990 if (t
==d
) return b
+c
;
9991 if ((t
/=d/2) < 1) return c
/2 * Math
.pow(2, 10 * (t
- 1)) + b
;
9992 return c
/2 * (-Math
.pow(2, -10 * --t
) + 2) + b
;
9994 easeInCirc: function (x
, t
, b
, c
, d
) {
9995 return -c
* (Math
.sqrt(1 - (t
/=d
)*t
) - 1) + b
;
9997 easeOutCirc: function (x
, t
, b
, c
, d
) {
9998 return c
* Math
.sqrt(1 - (t
=t
/d
-1)*t
) + b
;
10000 easeInOutCirc: function (x
, t
, b
, c
, d
) {
10001 if ((t
/=d/2) < 1) return -c
/2 * (Math
.sqrt(1 - t
*t
) - 1) + b
;
10002 return c
/2 * (Math
.sqrt(1 - (t
-=2)*t
) + 1) + b
;
10004 easeInElastic: function (x
, t
, b
, c
, d
) {
10005 var s
=1.70158;var p
=0;var a
=c
;
10006 if (t
==0) return b
; if ((t
/=d
)==1) return b
+c
; if (!p
) p
=d
*.3;
10007 if (a
< Math
.abs(c
)) { a
=c
; var s
=p
/4; }
10008 else var s
= p
/(2*Math.PI) * Math.asin (c/a);
10009 return -(a
*Math
.pow(2,10*(t
-=1)) * Math
.sin( (t
*d
-s
)*(2*Math
.PI
)/p
)) + b
;
10011 easeOutElastic: function (x
, t
, b
, c
, d
) {
10012 var s
=1.70158;var p
=0;var a
=c
;
10013 if (t
==0) return b
; if ((t
/=d
)==1) return b
+c
; if (!p
) p
=d
*.3;
10014 if (a
< Math
.abs(c
)) { a
=c
; var s
=p
/4; }
10015 else var s
= p
/(2*Math.PI) * Math.asin (c/a);
10016 return a
*Math
.pow(2,-10*t
) * Math
.sin( (t
*d
-s
)*(2*Math
.PI
)/p
) + c
+ b
;
10018 easeInOutElastic: function (x
, t
, b
, c
, d
) {
10019 var s
=1.70158;var p
=0;var a
=c
;
10020 if (t
==0) return b
; if ((t
/=d/2)==2) return b
+c
; if (!p
) p
=d
*(.3*1.5);
10021 if (a
< Math
.abs(c
)) { a
=c
; var s
=p
/4; }
10022 else var s
= p
/(2*Math.PI) * Math.asin (c/a);
10023 if (t
< 1) return -.5*(a
*Math
.pow(2,10*(t
-=1)) * Math
.sin( (t
*d
-s
)*(2*Math
.PI
)/p
)) + b
;
10024 return a
*Math
.pow(2,-10*(t
-=1)) * Math
.sin( (t
*d
-s
)*(2*Math
.PI
)/p
)*.5 + c
+ b
;
10026 easeInBack: function (x
, t
, b
, c
, d
, s
) {
10027 if (s
== undefined) s
= 1.70158;
10028 return c
*(t
/=d
)*t
*((s
+1)*t
- s
) + b
;
10030 easeOutBack: function (x
, t
, b
, c
, d
, s
) {
10031 if (s
== undefined) s
= 1.70158;
10032 return c
*((t
=t
/d
-1)*t
*((s
+1)*t
+ s
) + 1) + b
;
10034 easeInOutBack: function (x
, t
, b
, c
, d
, s
) {
10035 if (s
== undefined) s
= 1.70158;
10036 if ((t
/=d/2) < 1) return c
/2*(t
*t
*(((s
*=(1.525))+1)*t
- s
)) + b
;
10037 return c
/2*((t
-=2)*t
*(((s
*=(1.525))+1)*t
+ s
) + 2) + b
;
10039 easeInBounce: function (x
, t
, b
, c
, d
) {
10040 return c
- $.easing
.easeOutBounce (x
, d
-t
, 0, c
, d
) + b
;
10042 easeOutBounce: function (x
, t
, b
, c
, d
) {
10043 if ((t
/=d) < (1/2.75)) {
10044 return c
*(7.5625*t
*t
) + b
;
10045 } else if (t
< (2/2.75)) {
10046 return c
*(7.5625*(t
-=(1.5/2.75))*t
+ .75) + b
;
10047 } else if (t
< (2.5/2.75)) {
10048 return c
*(7.5625*(t
-=(2.25/2.75))*t
+ .9375) + b
;
10050 return c
*(7.5625*(t
-=(2.625/2.75))*t
+ .984375) + b
;
10053 easeInOutBounce: function (x
, t
, b
, c
, d
) {
10054 if (t
< d
/2) return $.easing
.easeInBounce (x
, t
*2, 0, c
, d
) * .5 + b
;
10055 return $.easing
.easeOutBounce (x
, t
*2-d
, 0, c
, d
) * .5 + c
*.5 + b
;
10061 * TERMS OF USE - EASING EQUATIONS
10063 * Open source under the BSD License.
10065 * Copyright 2001 Robert Penner
10066 * All rights reserved.
10068 * Redistribution and use in source and binary forms, with or without modification,
10069 * are permitted provided that the following conditions are met:
10071 * Redistributions of source code must retain the above copyright notice, this list of
10072 * conditions and the following disclaimer.
10073 * Redistributions in binary form must reproduce the above copyright notice, this list
10074 * of conditions and the following disclaimer in the documentation and/or other materials
10075 * provided with the distribution.
10077 * Neither the name of the author nor the names of contributors may be used to endorse
10078 * or promote products derived from this software without specific prior written permission.
10080 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
10081 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
10082 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
10083 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
10084 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
10085 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
10086 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
10087 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
10088 * OF THE POSSIBILITY OF SUCH DAMAGE.
10094 * jQuery UI Effects Blind 1.8
10096 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
10097 * Dual licensed under the MIT (MIT-LICENSE.txt)
10098 * and GPL (GPL-LICENSE.txt) licenses.
10100 * http://docs.jquery.com/UI/Effects/Blind
10103 * jquery.effects.core.js
10107 $.effects
.blind = function(o
) {
10109 return this.queue(function() {
10112 var el
= $(this), props
= ['position','top','left'];
10115 var mode
= $.effects
.setMode(el
, o
.options
.mode
|| 'hide'); // Set Mode
10116 var direction
= o
.options
.direction
|| 'vertical'; // Default direction
10119 $.effects
.save(el
, props
); el
.show(); // Save & Show
10120 var wrapper
= $.effects
.createWrapper(el
).css({overflow
:'hidden'}); // Create Wrapper
10121 var ref
= (direction
== 'vertical') ? 'height' : 'width';
10122 var distance
= (direction
== 'vertical') ? wrapper
.height() : wrapper
.width();
10123 if(mode
== 'show') wrapper
.css(ref
, 0); // Shift
10126 var animation
= {};
10127 animation
[ref
] = mode
== 'show' ? distance
: 0;
10130 wrapper
.animate(animation
, o
.duration
, o
.options
.easing
, function() {
10131 if(mode
== 'hide') el
.hide(); // Hide
10132 $.effects
.restore(el
, props
); $.effects
.removeWrapper(el
); // Restore
10133 if(o
.callback
) o
.callback
.apply(el
[0], arguments
); // Callback
10143 * jQuery UI Effects Bounce 1.8
10145 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
10146 * Dual licensed under the MIT (MIT-LICENSE.txt)
10147 * and GPL (GPL-LICENSE.txt) licenses.
10149 * http://docs.jquery.com/UI/Effects/Bounce
10152 * jquery.effects.core.js
10156 $.effects
.bounce = function(o
) {
10158 return this.queue(function() {
10161 var el
= $(this), props
= ['position','top','left'];
10164 var mode
= $.effects
.setMode(el
, o
.options
.mode
|| 'effect'); // Set Mode
10165 var direction
= o
.options
.direction
|| 'up'; // Default direction
10166 var distance
= o
.options
.distance
|| 20; // Default distance
10167 var times
= o
.options
.times
|| 5; // Default # of times
10168 var speed
= o
.duration
|| 250; // Default speed per bounce
10169 if (/show|hide/.test(mode
)) props
.push('opacity'); // Avoid touching opacity to prevent clearType and PNG issues in IE
10172 $.effects
.save(el
, props
); el
.show(); // Save & Show
10173 $.effects
.createWrapper(el
); // Create Wrapper
10174 var ref
= (direction
== 'up' || direction
== 'down') ? 'top' : 'left';
10175 var motion
= (direction
== 'up' || direction
== 'left') ? 'pos' : 'neg';
10176 var distance
= o
.options
.distance
|| (ref
== 'top' ? el
.outerHeight({margin
:true}) / 3 : el
.outerWidth({margin
:true}) / 3);
10177 if (mode
== 'show') el
.css('opacity', 0).css(ref
, motion
== 'pos' ? -distance
: distance
); // Shift
10178 if (mode
== 'hide') distance
= distance
/ (times
* 2);
10179 if (mode
!= 'hide') times
--;
10182 if (mode
== 'show') { // Show Bounce
10183 var animation
= {opacity
: 1};
10184 animation
[ref
] = (motion
== 'pos' ? '+=' : '-=') + distance
;
10185 el
.animate(animation
, speed
/ 2, o
.options
.easing
);
10186 distance
= distance
/ 2;
10189 for (var i
= 0; i
< times
; i
++) { // Bounces
10190 var animation1
= {}, animation2
= {};
10191 animation1
[ref
] = (motion
== 'pos' ? '-=' : '+=') + distance
;
10192 animation2
[ref
] = (motion
== 'pos' ? '+=' : '-=') + distance
;
10193 el
.animate(animation1
, speed
/ 2, o
.options
.easing
).animate(animation2
, speed
/ 2, o
.options
.easing
);
10194 distance
= (mode
== 'hide') ? distance
* 2 : distance
/ 2;
10196 if (mode
== 'hide') { // Last Bounce
10197 var animation
= {opacity
: 0};
10198 animation
[ref
] = (motion
== 'pos' ? '-=' : '+=') + distance
;
10199 el
.animate(animation
, speed
/ 2, o
.options
.easing
, function(){
10201 $.effects
.restore(el
, props
); $.effects
.removeWrapper(el
); // Restore
10202 if(o
.callback
) o
.callback
.apply(this, arguments
); // Callback
10205 var animation1
= {}, animation2
= {};
10206 animation1
[ref
] = (motion
== 'pos' ? '-=' : '+=') + distance
;
10207 animation2
[ref
] = (motion
== 'pos' ? '+=' : '-=') + distance
;
10208 el
.animate(animation1
, speed
/ 2, o
.options
.easing
).animate(animation2
, speed
/ 2, o
.options
.easing
, function(){
10209 $.effects
.restore(el
, props
); $.effects
.removeWrapper(el
); // Restore
10210 if(o
.callback
) o
.callback
.apply(this, arguments
); // Callback
10213 el
.queue('fx', function() { el
.dequeue(); });
10221 * jQuery UI Effects Clip 1.8
10223 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
10224 * Dual licensed under the MIT (MIT-LICENSE.txt)
10225 * and GPL (GPL-LICENSE.txt) licenses.
10227 * http://docs.jquery.com/UI/Effects/Clip
10230 * jquery.effects.core.js
10234 $.effects
.clip = function(o
) {
10236 return this.queue(function() {
10239 var el
= $(this), props
= ['position','top','left','height','width'];
10242 var mode
= $.effects
.setMode(el
, o
.options
.mode
|| 'hide'); // Set Mode
10243 var direction
= o
.options
.direction
|| 'vertical'; // Default direction
10246 $.effects
.save(el
, props
); el
.show(); // Save & Show
10247 var wrapper
= $.effects
.createWrapper(el
).css({overflow
:'hidden'}); // Create Wrapper
10248 var animate
= el
[0].tagName
== 'IMG' ? wrapper
: el
;
10250 size
: (direction
== 'vertical') ? 'height' : 'width',
10251 position
: (direction
== 'vertical') ? 'top' : 'left'
10253 var distance
= (direction
== 'vertical') ? animate
.height() : animate
.width();
10254 if(mode
== 'show') { animate
.css(ref
.size
, 0); animate
.css(ref
.position
, distance
/ 2); } // Shift
10257 var animation
= {};
10258 animation
[ref
.size
] = mode
== 'show' ? distance
: 0;
10259 animation
[ref
.position
] = mode
== 'show' ? 0 : distance
/ 2;
10262 animate
.animate(animation
, { queue
: false, duration
: o
.duration
, easing
: o
.options
.easing
, complete: function() {
10263 if(mode
== 'hide') el
.hide(); // Hide
10264 $.effects
.restore(el
, props
); $.effects
.removeWrapper(el
); // Restore
10265 if(o
.callback
) o
.callback
.apply(el
[0], arguments
); // Callback
10275 * jQuery UI Effects Drop 1.8
10277 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
10278 * Dual licensed under the MIT (MIT-LICENSE.txt)
10279 * and GPL (GPL-LICENSE.txt) licenses.
10281 * http://docs.jquery.com/UI/Effects/Drop
10284 * jquery.effects.core.js
10288 $.effects
.drop = function(o
) {
10290 return this.queue(function() {
10293 var el
= $(this), props
= ['position','top','left','opacity'];
10296 var mode
= $.effects
.setMode(el
, o
.options
.mode
|| 'hide'); // Set Mode
10297 var direction
= o
.options
.direction
|| 'left'; // Default Direction
10300 $.effects
.save(el
, props
); el
.show(); // Save & Show
10301 $.effects
.createWrapper(el
); // Create Wrapper
10302 var ref
= (direction
== 'up' || direction
== 'down') ? 'top' : 'left';
10303 var motion
= (direction
== 'up' || direction
== 'left') ? 'pos' : 'neg';
10304 var distance
= o
.options
.distance
|| (ref
== 'top' ? el
.outerHeight({margin
:true}) / 2 : el
.outerWidth({margin
:true}) / 2);
10305 if (mode
== 'show') el
.css('opacity', 0).css(ref
, motion
== 'pos' ? -distance
: distance
); // Shift
10308 var animation
= {opacity
: mode
== 'show' ? 1 : 0};
10309 animation
[ref
] = (mode
== 'show' ? (motion
== 'pos' ? '+=' : '-=') : (motion
== 'pos' ? '-=' : '+=')) + distance
;
10312 el
.animate(animation
, { queue
: false, duration
: o
.duration
, easing
: o
.options
.easing
, complete: function() {
10313 if(mode
== 'hide') el
.hide(); // Hide
10314 $.effects
.restore(el
, props
); $.effects
.removeWrapper(el
); // Restore
10315 if(o
.callback
) o
.callback
.apply(this, arguments
); // Callback
10325 * jQuery UI Effects Explode 1.8
10327 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
10328 * Dual licensed under the MIT (MIT-LICENSE.txt)
10329 * and GPL (GPL-LICENSE.txt) licenses.
10331 * http://docs.jquery.com/UI/Effects/Explode
10334 * jquery.effects.core.js
10338 $.effects
.explode = function(o
) {
10340 return this.queue(function() {
10342 var rows
= o
.options
.pieces
? Math
.round(Math
.sqrt(o
.options
.pieces
)) : 3;
10343 var cells
= o
.options
.pieces
? Math
.round(Math
.sqrt(o
.options
.pieces
)) : 3;
10345 o
.options
.mode
= o
.options
.mode
== 'toggle' ? ($(this).is(':visible') ? 'hide' : 'show') : o
.options
.mode
;
10346 var el
= $(this).show().css('visibility', 'hidden');
10347 var offset
= el
.offset();
10349 //Substract the margins - not fixing the problem yet.
10350 offset
.top
-= parseInt(el
.css("marginTop"),10) || 0;
10351 offset
.left
-= parseInt(el
.css("marginLeft"),10) || 0;
10353 var width
= el
.outerWidth(true);
10354 var height
= el
.outerHeight(true);
10356 for(var i
=0;i
<rows
;i
++) { // =
10357 for(var j
=0;j
<cells
;j
++) { // ||
10361 .wrap('<div></div>')
10363 position
: 'absolute',
10364 visibility
: 'visible',
10365 left
: -j
*(width
/cells
),
10366 top
: -i
*(height
/rows
)
10369 .addClass('ui-effects-explode')
10371 position
: 'absolute',
10372 overflow
: 'hidden',
10373 width
: width
/cells
,
10374 height
: height
/rows
,
10375 left
: offset
.left
+ j
*(width
/cells) + (o.options.mode == 'show' ? (j-Math.floor(cells/2))*(width
/cells
) : 0),
10376 top
: offset
.top
+ i
*(height
/rows) + (o.options.mode == 'show' ? (i-Math.floor(rows/2))*(height
/rows
) : 0),
10377 opacity
: o
.options
.mode
== 'show' ? 0 : 1
10379 left
: offset
.left
+ j
*(width
/cells) + (o.options.mode == 'show' ? 0 : (j-Math.floor(cells/2))*(width
/cells
)),
10380 top
: offset
.top
+ i
*(height
/rows) + (o.options.mode == 'show' ? 0 : (i-Math.floor(rows/2))*(height
/rows
)),
10381 opacity
: o
.options
.mode
== 'show' ? 1 : 0
10382 }, o
.duration
|| 500);
10386 // Set a timeout, to call the callback approx. when the other animations have finished
10387 setTimeout(function() {
10389 o
.options
.mode
== 'show' ? el
.css({ visibility
: 'visible' }) : el
.css({ visibility
: 'visible' }).hide();
10390 if(o
.callback
) o
.callback
.apply(el
[0]); // Callback
10393 $('div.ui-effects-explode').remove();
10395 }, o
.duration
|| 500);
10404 * jQuery UI Effects Fold 1.8
10406 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
10407 * Dual licensed under the MIT (MIT-LICENSE.txt)
10408 * and GPL (GPL-LICENSE.txt) licenses.
10410 * http://docs.jquery.com/UI/Effects/Fold
10413 * jquery.effects.core.js
10417 $.effects
.fold = function(o
) {
10419 return this.queue(function() {
10422 var el
= $(this), props
= ['position','top','left'];
10425 var mode
= $.effects
.setMode(el
, o
.options
.mode
|| 'hide'); // Set Mode
10426 var size
= o
.options
.size
|| 15; // Default fold size
10427 var horizFirst
= !(!o
.options
.horizFirst
); // Ensure a boolean value
10428 var duration
= o
.duration
? o
.duration
/ 2 : $.fx
.speeds
._default
/ 2;
10431 $.effects
.save(el
, props
); el
.show(); // Save & Show
10432 var wrapper
= $.effects
.createWrapper(el
).css({overflow
:'hidden'}); // Create Wrapper
10433 var widthFirst
= ((mode
== 'show') != horizFirst
);
10434 var ref
= widthFirst
? ['width', 'height'] : ['height', 'width'];
10435 var distance
= widthFirst
? [wrapper
.width(), wrapper
.height()] : [wrapper
.height(), wrapper
.width()];
10436 var percent
= /([0-9]+)%/.exec(size
);
10437 if(percent
) size
= parseInt(percent
[1],10) / 100 * distance
[mode
== 'hide' ? 0 : 1];
10438 if(mode
== 'show') wrapper
.css(horizFirst
? {height
: 0, width
: size
} : {height
: size
, width
: 0}); // Shift
10441 var animation1
= {}, animation2
= {};
10442 animation1
[ref
[0]] = mode
== 'show' ? distance
[0] : size
;
10443 animation2
[ref
[1]] = mode
== 'show' ? distance
[1] : 0;
10446 wrapper
.animate(animation1
, duration
, o
.options
.easing
)
10447 .animate(animation2
, duration
, o
.options
.easing
, function() {
10448 if(mode
== 'hide') el
.hide(); // Hide
10449 $.effects
.restore(el
, props
); $.effects
.removeWrapper(el
); // Restore
10450 if(o
.callback
) o
.callback
.apply(el
[0], arguments
); // Callback
10460 * jQuery UI Effects Highlight 1.8
10462 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
10463 * Dual licensed under the MIT (MIT-LICENSE.txt)
10464 * and GPL (GPL-LICENSE.txt) licenses.
10466 * http://docs.jquery.com/UI/Effects/Highlight
10469 * jquery.effects.core.js
10473 $.effects
.highlight = function(o
) {
10474 return this.queue(function() {
10475 var elem
= $(this),
10476 props
= ['backgroundImage', 'backgroundColor', 'opacity'],
10477 mode
= $.effects
.setMode(elem
, o
.options
.mode
|| 'show'),
10479 backgroundColor
: elem
.css('backgroundColor')
10482 if (mode
== 'hide') {
10483 animation
.opacity
= 0;
10486 $.effects
.save(elem
, props
);
10490 backgroundImage
: 'none',
10491 backgroundColor
: o
.options
.color
|| '#ffff99'
10493 .animate(animation
, {
10495 duration
: o
.duration
,
10496 easing
: o
.options
.easing
,
10497 complete: function() {
10498 (mode
== 'hide' && elem
.hide());
10499 $.effects
.restore(elem
, props
);
10500 (mode
== 'show' && !$.support
.opacity
&& this.style
.removeAttribute('filter'));
10501 (o
.callback
&& o
.callback
.apply(this, arguments
));
10510 * jQuery UI Effects Pulsate 1.8
10512 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
10513 * Dual licensed under the MIT (MIT-LICENSE.txt)
10514 * and GPL (GPL-LICENSE.txt) licenses.
10516 * http://docs.jquery.com/UI/Effects/Pulsate
10519 * jquery.effects.core.js
10523 $.effects
.pulsate = function(o
) {
10524 return this.queue(function() {
10525 var elem
= $(this),
10526 mode
= $.effects
.setMode(elem
, o
.options
.mode
|| 'show');
10527 times
= ((o
.options
.times
|| 5) * 2) - 1;
10528 duration
= o
.duration
? o
.duration
/ 2 : $.fx
.speeds
._default
/ 2,
10529 isVisible
= elem
.is(':visible'),
10533 elem
.css('opacity', 0).show();
10537 if ((mode
== 'hide' && isVisible
) || (mode
== 'show' && !isVisible
)) {
10541 for (var i
= 0; i
< times
; i
++) {
10542 elem
.animate({ opacity
: animateTo
}, duration
, o
.options
.easing
);
10543 animateTo
= (animateTo
+ 1) % 2;
10546 elem
.animate({ opacity
: animateTo
}, duration
, o
.options
.easing
, function() {
10547 if (animateTo
== 0) {
10550 (o
.callback
&& o
.callback
.apply(this, arguments
));
10554 .queue('fx', function() { elem
.dequeue(); })
10561 * jQuery UI Effects Scale 1.8
10563 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
10564 * Dual licensed under the MIT (MIT-LICENSE.txt)
10565 * and GPL (GPL-LICENSE.txt) licenses.
10567 * http://docs.jquery.com/UI/Effects/Scale
10570 * jquery.effects.core.js
10574 $.effects
.puff = function(o
) {
10575 return this.queue(function() {
10576 var elem
= $(this),
10577 mode
= $.effects
.setMode(elem
, o
.options
.mode
|| 'hide'),
10578 percent
= parseInt(o
.options
.percent
, 10) || 150,
10579 factor
= percent
/ 100,
10580 original
= { height
: elem
.height(), width
: elem
.width() };
10582 $.extend(o
.options
, {
10585 percent
: mode
== 'hide' ? percent
: 100,
10586 from: mode
== 'hide'
10589 height
: original
.height
* factor
,
10590 width
: original
.width
* factor
10594 elem
.effect('scale', o
.options
, o
.duration
, o
.callback
);
10599 $.effects
.scale = function(o
) {
10601 return this.queue(function() {
10607 var options
= $.extend(true, {}, o
.options
);
10608 var mode
= $.effects
.setMode(el
, o
.options
.mode
|| 'effect'); // Set Mode
10609 var percent
= parseInt(o
.options
.percent
,10) || (parseInt(o
.options
.percent
,10) == 0 ? 0 : (mode
== 'hide' ? 0 : 100)); // Set default scaling percent
10610 var direction
= o
.options
.direction
|| 'both'; // Set default axis
10611 var origin
= o
.options
.origin
; // The origin of the scaling
10612 if (mode
!= 'effect') { // Set default origin and restore for show/hide
10613 options
.origin
= origin
|| ['middle','center'];
10614 options
.restore
= true;
10616 var original
= {height
: el
.height(), width
: el
.width()}; // Save original
10617 el
.from = o
.options
.from || (mode
== 'show' ? {height
: 0, width
: 0} : original
); // Default from state
10620 var factor
= { // Set scaling factor
10621 y
: direction
!= 'horizontal' ? (percent
/ 100) : 1,
10622 x
: direction
!= 'vertical' ? (percent
/ 100) : 1
10624 el
.to
= {height
: original
.height
* factor
.y
, width
: original
.width
* factor
.x
}; // Set to state
10626 if (o
.options
.fade
) { // Fade option to support puff
10627 if (mode
== 'show') {el
.from.opacity
= 0; el
.to
.opacity
= 1;};
10628 if (mode
== 'hide') {el
.from.opacity
= 1; el
.to
.opacity
= 0;};
10632 options
.from = el
.from; options
.to
= el
.to
; options
.mode
= mode
;
10635 el
.effect('size', options
, o
.duration
, o
.callback
);
10641 $.effects
.size = function(o
) {
10643 return this.queue(function() {
10646 var el
= $(this), props
= ['position','top','left','width','height','overflow','opacity'];
10647 var props1
= ['position','top','left','overflow','opacity']; // Always restore
10648 var props2
= ['width','height','overflow']; // Copy for children
10649 var cProps
= ['fontSize'];
10650 var vProps
= ['borderTopWidth', 'borderBottomWidth', 'paddingTop', 'paddingBottom'];
10651 var hProps
= ['borderLeftWidth', 'borderRightWidth', 'paddingLeft', 'paddingRight'];
10654 var mode
= $.effects
.setMode(el
, o
.options
.mode
|| 'effect'); // Set Mode
10655 var restore
= o
.options
.restore
|| false; // Default restore
10656 var scale
= o
.options
.scale
|| 'both'; // Default scale mode
10657 var origin
= o
.options
.origin
; // The origin of the sizing
10658 var original
= {height
: el
.height(), width
: el
.width()}; // Save original
10659 el
.from = o
.options
.from || original
; // Default from state
10660 el
.to
= o
.options
.to
|| original
; // Default to state
10662 if (origin
) { // Calculate baseline shifts
10663 var baseline
= $.effects
.getBaseline(origin
, original
);
10664 el
.from.top
= (original
.height
- el
.from.height
) * baseline
.y
;
10665 el
.from.left
= (original
.width
- el
.from.width
) * baseline
.x
;
10666 el
.to
.top
= (original
.height
- el
.to
.height
) * baseline
.y
;
10667 el
.to
.left
= (original
.width
- el
.to
.width
) * baseline
.x
;
10669 var factor
= { // Set scaling factor
10670 from: {y
: el
.from.height
/ original
.height
, x
: el
.from.width
/ original
.width
},
10671 to
: {y
: el
.to
.height
/ original
.height
, x
: el
.to
.width
/ original
.width
}
10673 if (scale
== 'box' || scale
== 'both') { // Scale the css box
10674 if (factor
.from.y
!= factor
.to
.y
) { // Vertical props scaling
10675 props
= props
.concat(vProps
);
10676 el
.from = $.effects
.setTransition(el
, vProps
, factor
.from.y
, el
.from);
10677 el
.to
= $.effects
.setTransition(el
, vProps
, factor
.to
.y
, el
.to
);
10679 if (factor
.from.x
!= factor
.to
.x
) { // Horizontal props scaling
10680 props
= props
.concat(hProps
);
10681 el
.from = $.effects
.setTransition(el
, hProps
, factor
.from.x
, el
.from);
10682 el
.to
= $.effects
.setTransition(el
, hProps
, factor
.to
.x
, el
.to
);
10685 if (scale
== 'content' || scale
== 'both') { // Scale the content
10686 if (factor
.from.y
!= factor
.to
.y
) { // Vertical props scaling
10687 props
= props
.concat(cProps
);
10688 el
.from = $.effects
.setTransition(el
, cProps
, factor
.from.y
, el
.from);
10689 el
.to
= $.effects
.setTransition(el
, cProps
, factor
.to
.y
, el
.to
);
10692 $.effects
.save(el
, restore
? props
: props1
); el
.show(); // Save & Show
10693 $.effects
.createWrapper(el
); // Create Wrapper
10694 el
.css('overflow','hidden').css(el
.from); // Shift
10697 if (scale
== 'content' || scale
== 'both') { // Scale the children
10698 vProps
= vProps
.concat(['marginTop','marginBottom']).concat(cProps
); // Add margins/font-size
10699 hProps
= hProps
.concat(['marginLeft','marginRight']); // Add margins
10700 props2
= props
.concat(vProps
).concat(hProps
); // Concat
10701 el
.find("*[width]").each(function(){
10703 if (restore
) $.effects
.save(child
, props2
);
10704 var c_original
= {height
: child
.height(), width
: child
.width()}; // Save original
10705 child
.from = {height
: c_original
.height
* factor
.from.y
, width
: c_original
.width
* factor
.from.x
};
10706 child
.to
= {height
: c_original
.height
* factor
.to
.y
, width
: c_original
.width
* factor
.to
.x
};
10707 if (factor
.from.y
!= factor
.to
.y
) { // Vertical props scaling
10708 child
.from = $.effects
.setTransition(child
, vProps
, factor
.from.y
, child
.from);
10709 child
.to
= $.effects
.setTransition(child
, vProps
, factor
.to
.y
, child
.to
);
10711 if (factor
.from.x
!= factor
.to
.x
) { // Horizontal props scaling
10712 child
.from = $.effects
.setTransition(child
, hProps
, factor
.from.x
, child
.from);
10713 child
.to
= $.effects
.setTransition(child
, hProps
, factor
.to
.x
, child
.to
);
10715 child
.css(child
.from); // Shift children
10716 child
.animate(child
.to
, o
.duration
, o
.options
.easing
, function(){
10717 if (restore
) $.effects
.restore(child
, props2
); // Restore children
10718 }); // Animate children
10723 el
.animate(el
.to
, { queue
: false, duration
: o
.duration
, easing
: o
.options
.easing
, complete: function() {
10724 if (el
.to
.opacity
=== 0) {
10725 el
.css('opacity', el
.from.opacity
);
10727 if(mode
== 'hide') el
.hide(); // Hide
10728 $.effects
.restore(el
, restore
? props
: props1
); $.effects
.removeWrapper(el
); // Restore
10729 if(o
.callback
) o
.callback
.apply(this, arguments
); // Callback
10739 * jQuery UI Effects Shake 1.8
10741 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
10742 * Dual licensed under the MIT (MIT-LICENSE.txt)
10743 * and GPL (GPL-LICENSE.txt) licenses.
10745 * http://docs.jquery.com/UI/Effects/Shake
10748 * jquery.effects.core.js
10752 $.effects
.shake = function(o
) {
10754 return this.queue(function() {
10757 var el
= $(this), props
= ['position','top','left'];
10760 var mode
= $.effects
.setMode(el
, o
.options
.mode
|| 'effect'); // Set Mode
10761 var direction
= o
.options
.direction
|| 'left'; // Default direction
10762 var distance
= o
.options
.distance
|| 20; // Default distance
10763 var times
= o
.options
.times
|| 3; // Default # of times
10764 var speed
= o
.duration
|| o
.options
.duration
|| 140; // Default speed per shake
10767 $.effects
.save(el
, props
); el
.show(); // Save & Show
10768 $.effects
.createWrapper(el
); // Create Wrapper
10769 var ref
= (direction
== 'up' || direction
== 'down') ? 'top' : 'left';
10770 var motion
= (direction
== 'up' || direction
== 'left') ? 'pos' : 'neg';
10773 var animation
= {}, animation1
= {}, animation2
= {};
10774 animation
[ref
] = (motion
== 'pos' ? '-=' : '+=') + distance
;
10775 animation1
[ref
] = (motion
== 'pos' ? '+=' : '-=') + distance
* 2;
10776 animation2
[ref
] = (motion
== 'pos' ? '-=' : '+=') + distance
* 2;
10779 el
.animate(animation
, speed
, o
.options
.easing
);
10780 for (var i
= 1; i
< times
; i
++) { // Shakes
10781 el
.animate(animation1
, speed
, o
.options
.easing
).animate(animation2
, speed
, o
.options
.easing
);
10783 el
.animate(animation1
, speed
, o
.options
.easing
).
10784 animate(animation
, speed
/ 2, o
.options
.easing
, function(){ // Last shake
10785 $.effects
.restore(el
, props
); $.effects
.removeWrapper(el
); // Restore
10786 if(o
.callback
) o
.callback
.apply(this, arguments
); // Callback
10788 el
.queue('fx', function() { el
.dequeue(); });
10796 * jQuery UI Effects Slide 1.8
10798 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
10799 * Dual licensed under the MIT (MIT-LICENSE.txt)
10800 * and GPL (GPL-LICENSE.txt) licenses.
10802 * http://docs.jquery.com/UI/Effects/Slide
10805 * jquery.effects.core.js
10809 $.effects
.slide = function(o
) {
10811 return this.queue(function() {
10814 var el
= $(this), props
= ['position','top','left'];
10817 var mode
= $.effects
.setMode(el
, o
.options
.mode
|| 'show'); // Set Mode
10818 var direction
= o
.options
.direction
|| 'left'; // Default Direction
10821 $.effects
.save(el
, props
); el
.show(); // Save & Show
10822 $.effects
.createWrapper(el
).css({overflow
:'hidden'}); // Create Wrapper
10823 var ref
= (direction
== 'up' || direction
== 'down') ? 'top' : 'left';
10824 var motion
= (direction
== 'up' || direction
== 'left') ? 'pos' : 'neg';
10825 var distance
= o
.options
.distance
|| (ref
== 'top' ? el
.outerHeight({margin
:true}) : el
.outerWidth({margin
:true}));
10826 if (mode
== 'show') el
.css(ref
, motion
== 'pos' ? -distance
: distance
); // Shift
10829 var animation
= {};
10830 animation
[ref
] = (mode
== 'show' ? (motion
== 'pos' ? '+=' : '-=') : (motion
== 'pos' ? '-=' : '+=')) + distance
;
10833 el
.animate(animation
, { queue
: false, duration
: o
.duration
, easing
: o
.options
.easing
, complete: function() {
10834 if(mode
== 'hide') el
.hide(); // Hide
10835 $.effects
.restore(el
, props
); $.effects
.removeWrapper(el
); // Restore
10836 if(o
.callback
) o
.callback
.apply(this, arguments
); // Callback
10846 * jQuery UI Effects Transfer 1.8
10848 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
10849 * Dual licensed under the MIT (MIT-LICENSE.txt)
10850 * and GPL (GPL-LICENSE.txt) licenses.
10852 * http://docs.jquery.com/UI/Effects/Transfer
10855 * jquery.effects.core.js
10859 $.effects
.transfer = function(o
) {
10860 return this.queue(function() {
10861 var elem
= $(this),
10862 target
= $(o
.options
.to
),
10863 endPosition
= target
.offset(),
10865 top
: endPosition
.top
,
10866 left
: endPosition
.left
,
10867 height
: target
.innerHeight(),
10868 width
: target
.innerWidth()
10870 startPosition
= elem
.offset(),
10871 transfer
= $('<div class="ui-effects-transfer"></div>')
10872 .appendTo(document
.body
)
10873 .addClass(o
.options
.className
)
10875 top
: startPosition
.top
,
10876 left
: startPosition
.left
,
10877 height
: elem
.innerHeight(),
10878 width
: elem
.innerWidth(),
10879 position
: 'absolute'
10881 .animate(animation
, o
.duration
, o
.options
.easing
, function() {
10883 (o
.callback
&& o
.callback
.apply(elem
[0], arguments
));