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));