4 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
5 * Dual licensed under the MIT or GPL Version 2 licenses.
6 * http://jquery.org/license
8 * http://docs.jquery.com/UI
10 (function( $, undefined ) {
12 // prevent duplicate loading
13 // this is only a problem because we proxy existing functions
14 // and we don't want to double proxy them
20 //Helper functions and ui object
24 // $.ui.plugin is deprecated. Use the proxy pattern instead.
26 add: function( module, option, set ) {
27 var proto = $.ui[ moduleĀ ].prototype;
28 for ( var i in set ) {
29 proto.plugins[ i ] = proto.plugins[ i ] || [];
30 proto.plugins[ i ].push( [ option, set[ i ] ] );
33 call: function( instance, name, args ) {
34 var set = instance.plugins[ name ];
35 if ( !set || !instance.element[ 0 ].parentNode ) {
39 for ( var i = 0; i < set.length; i++ ) {
40 if ( instance.options[ set[ i ][ 0 ] ] ) {
41 set[ i ][ 1 ].apply( instance.element, args );
47 contains: function( a, b ) {
48 return document.compareDocumentPosition ?
49 a.compareDocumentPosition( b ) & 16 :
50 a !== b && a.contains( b );
53 hasScroll: function( el, a ) {
55 //If overflow is hidden, the element might have extra content, but the user wants to hide it
56 if ( $( el ).css( "overflow" ) === "hidden") {
60 var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
63 if ( el[ scroll ] > 0 ) {
67 // TODO: determine which cases actually cause this to happen
68 // if the element doesn't have the scroll set, see if it's possible to
71 has = ( el[ scroll ] > 0 );
76 isOverAxis: function( x, reference, size ) {
77 //Determines when x coordinate is over "b" element axis
78 return ( x > reference ) && ( x < ( reference + size ) );
81 isOver: function( y, x, top, left, height, width ) {
82 //Determines when x, y coordinates is over "b" element
83 return $.ui.isOverAxis( y, top, height ) && $.ui.isOverAxis( x, left, width );
92 COMMAND_LEFT: 91, // COMMAND
103 MENU: 93, // COMMAND_RIGHT
108 NUMPAD_MULTIPLY: 106,
109 NUMPAD_SUBTRACT: 109,
118 WINDOWS: 91 // COMMAND
125 focus: function( delay, fn ) {
126 return typeof delay === "number" ?
127 this.each(function() {
129 setTimeout(function() {
136 this._focus.apply( this, arguments );
139 enableSelection: function() {
141 .attr( "unselectable", "off" )
142 .css( "MozUserSelect", "" );
145 disableSelection: function() {
147 .attr( "unselectable", "on" )
148 .css( "MozUserSelect", "none" );
151 scrollParent: function() {
153 if (($.browser.msie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) {
154 scrollParent = this.parents().filter(function() {
155 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));
158 scrollParent = this.parents().filter(function() {
159 return (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
163 return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent;
166 zIndex: function( zIndex ) {
167 if ( zIndex !== undefined ) {
168 return this.css( "zIndex", zIndex );
172 var elem = $( this[ 0 ] ), position, value;
173 while ( elem.length && elem[ 0 ] !== document ) {
174 // Ignore z-index if position is set to a value where z-index is ignored by the browser
175 // This makes behavior of this function consistent across browsers
176 // WebKit always returns auto if the element is positioned
177 position = elem.css( "position" );
178 if ( position === "absolute" || position === "relative" || position === "fixed" ) {
179 // IE returns 0 when zIndex is not specified
180 // other browsers return a string
181 // we ignore the case of nested elements with an explicit value of 0
182 // <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
183 value = parseInt( elem.css( "zIndex" ) );
184 if ( !isNaN( value ) && value != 0 ) {
188 elem = elem.parent();
196 $.each( [ "Width", "Height" ], function( i, name ) {
197 var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
198 type = name.toLowerCase(),
200 innerWidth: $.fn.innerWidth,
201 innerHeight: $.fn.innerHeight,
202 outerWidth: $.fn.outerWidth,
203 outerHeight: $.fn.outerHeight
206 function reduce( elem, size, border, margin ) {
207 $.each( side, function() {
208 size -= parseFloat( $.curCSS( elem, "padding" + this, true) ) || 0;
210 size -= parseFloat( $.curCSS( elem, "border" + this + "Width", true) ) || 0;
213 size -= parseFloat( $.curCSS( elem, "margin" + this, true) ) || 0;
219 $.fn[ "inner" + name ] = function( size ) {
220 if ( size === undefined ) {
221 return orig[ "inner" + name ].call( this );
224 return this.each(function() {
225 $.style( this, type, reduce( this, size ) + "px" );
229 $.fn[ "outer" + name] = function( size, margin ) {
230 if ( typeof size !== "number" ) {
231 return orig[ "outer" + name ].call( this, size );
234 return this.each(function() {
235 $.style( this, type, reduce( this, size, true, margin ) + "px" );
240 //Additional selectors
241 function visible( element ) {
242 return !$( element ).parents().andSelf().filter(function() {
243 return $.curCSS( this, "visibility" ) === "hidden" ||
244 $.expr.filters.hidden( this );
248 $.extend( $.expr[ ":" ], {
249 data: function( elem, i, match ) {
250 return !!$.data( elem, match[ 3 ] );
253 focusable: function( element ) {
254 var nodeName = element.nodeName.toLowerCase(),
255 tabIndex = $.attr( element, "tabindex" );
256 if ( "area" === nodeName ) {
257 var map = element.parentNode,
260 if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
263 img = $( "img[usemap=#" + mapName + "]" )[0];
264 return !!img && visible( img );
266 return ( /input|select|textarea|button|object/.test( nodeName )
269 ? element.href || !isNaN( tabIndex )
270 : !isNaN( tabIndex ))
271 // the element and all of its ancestors must be visible
272 && visible( element );
275 tabbable: function( element ) {
276 var tabIndex = $.attr( element, "tabindex" );
277 return ( isNaN( tabIndex ) || tabIndex >= 0 ) && $( element ).is( ":focusable" );
283 * jQuery UI Widget 1.8.4
285 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
286 * Dual licensed under the MIT or GPL Version 2 licenses.
287 * http://jquery.org/license
289 * http://docs.jquery.com/UI/Widget
291 (function( $, undefined ) {
293 var _remove = $.fn.remove;
295 $.fn.remove = function( selector, keepData ) {
296 return this.each(function() {
298 if ( !selector || $.filter( selector, [ this ] ).length ) {
299 $( "*", this ).add( [ this ] ).each(function() {
300 $( this ).triggerHandler( "remove" );
304 return _remove.call( $(this), selector, keepData );
308 $.widget = function( name, base, prototype ) {
309 var namespace = name.split( "." )[ 0 ],
311 name = name.split( "." )[ 1 ];
312 fullName = namespace + "-" + name;
319 // create selector for plugin
320 $.expr[ ":" ][ fullName ] = function( elem ) {
321 return !!$.data( elem, name );
324 $[ namespace ] = $[ namespace ] || {};
325 $[ namespace ][ name ] = function( options, element ) {
326 // allow instantiation without initializing for simple inheritance
327 if ( arguments.length ) {
328 this._createWidget( options, element );
332 var basePrototype = new base();
333 // we need to make the options hash a property directly on the new instance
334 // otherwise we'll modify the options hash on the prototype that we're
336 // $.each( basePrototype, function( key, val ) {
337 // if ( $.isPlainObject(val) ) {
338 // basePrototype[ key ] = $.extend( {}, val );
341 basePrototype.options = $.extend( true, {}, basePrototype.options );
342 $[ namespace ][ name ].prototype = $.extend( true, basePrototype, {
343 namespace: namespace,
345 widgetEventPrefix: $[ namespace ][ name ].prototype.widgetEventPrefix || name,
346 widgetBaseClass: fullName
349 $.widget.bridge( name, $[ namespace ][ name ] );
352 $.widget.bridge = function( name, object ) {
353 $.fn[ name ] = function( options ) {
354 var isMethodCall = typeof options === "string",
355 args = Array.prototype.slice.call( arguments, 1 ),
358 // allow multiple hashes to be passed on init
359 options = !isMethodCall && args.length ?
360 $.extend.apply( null, [ true, options ].concat(args) ) :
363 // prevent calls to internal methods
364 if ( isMethodCall && options.substring( 0, 1 ) === "_" ) {
368 if ( isMethodCall ) {
369 this.each(function() {
370 var instance = $.data( this, name ),
371 methodValue = instance && $.isFunction( instance[options] ) ?
372 instance[ options ].apply( instance, args ) :
374 if ( methodValue !== instance && methodValue !== undefined ) {
375 returnValue = methodValue;
380 this.each(function() {
381 var instance = $.data( this, name );
384 instance.option( options );
388 $.data( this, name, new object( options, this ) );
397 $.Widget = function( options, element ) {
398 // allow instantiation without initializing for simple inheritance
399 if ( arguments.length ) {
400 this._createWidget( options, element );
404 $.Widget.prototype = {
405 widgetName: "widget",
406 widgetEventPrefix: "",
410 _createWidget: function( options, element ) {
411 // $.widget.bridge stores the plugin instance, but we do it anyway
412 // so that it's stored even before the _create function runs
413 $.data( element, this.widgetName, this );
414 this.element = $( element );
415 this.options = $.extend( true, {},
417 $.metadata && $.metadata.get( element )[ this.widgetName ],
421 this.element.bind( "remove." + this.widgetName, function() {
428 _create: function() {},
429 _init: function() {},
431 destroy: function() {
433 .unbind( "." + this.widgetName )
434 .removeData( this.widgetName );
436 .unbind( "." + this.widgetName )
437 .removeAttr( "aria-disabled" )
439 this.widgetBaseClass + "-disabled " +
440 "ui-state-disabled" );
447 option: function( key, value ) {
451 if ( arguments.length === 0 ) {
452 // don't return a reference to the internal hash
453 return $.extend( {}, self.options );
456 if (typeof key === "string" ) {
457 if ( value === undefined ) {
458 return this.options[ key ];
461 options[ key ] = value;
464 $.each( options, function( key, value ) {
465 self._setOption( key, value );
470 _setOption: function( key, value ) {
471 this.options[ key ] = value;
473 if ( key === "disabled" ) {
475 [ value ? "addClass" : "removeClass"](
476 this.widgetBaseClass + "-disabled" + " " +
477 "ui-state-disabled" )
478 .attr( "aria-disabled", value );
485 return this._setOption( "disabled", false );
487 disable: function() {
488 return this._setOption( "disabled", true );
491 _trigger: function( type, event, data ) {
492 var callback = this.options[ type ];
494 event = $.Event( event );
495 event.type = ( type === this.widgetEventPrefix ?
497 this.widgetEventPrefix + type ).toLowerCase();
500 // copy original event properties over to the new event
501 // this would happen if we could call $.event.fix instead of $.Event
502 // but we don't have a way to force an event to be fixed multiple times
503 if ( event.originalEvent ) {
504 for ( var i = $.event.props.length, prop; i; ) {
505 prop = $.event.props[ --i ];
506 event[ prop ] = event.originalEvent[ prop ];
510 this.element.trigger( event, data );
512 return !( $.isFunction(callback) &&
513 callback.call( this.element[0], event, data ) === false ||
514 event.isDefaultPrevented() );
520 * jQuery UI Mouse 1.8.4
522 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
523 * Dual licensed under the MIT or GPL Version 2 licenses.
524 * http://jquery.org/license
526 * http://docs.jquery.com/UI/Mouse
529 * jquery.ui.widget.js
531 (function( $, undefined ) {
533 $.widget("ui.mouse", {
535 cancel: ':input,option',
539 _mouseInit: function() {
543 .bind('mousedown.'+this.widgetName, function(event) {
544 return self._mouseDown(event);
546 .bind('click.'+this.widgetName, function(event) {
547 if(self._preventClickEvent) {
548 self._preventClickEvent = false;
549 event.stopImmediatePropagation();
554 this.started = false;
557 // TODO: make sure destroying one instance of mouse doesn't mess with
558 // other instances of mouse
559 _mouseDestroy: function() {
560 this.element.unbind('.'+this.widgetName);
563 _mouseDown: function(event) {
564 // don't let more than one widget handle mouseStart
565 // TODO: figure out why we have to use originalEvent
566 event.originalEvent = event.originalEvent || {};
567 if (event.originalEvent.mouseHandled) { return; }
569 // we may have missed mouseup (out of window)
570 (this._mouseStarted && this._mouseUp(event));
572 this._mouseDownEvent = event;
575 btnIsLeft = (event.which == 1),
576 elIsCancel = (typeof this.options.cancel == "string" ? $(event.target).parents().add(event.target).filter(this.options.cancel).length : false);
577 if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
581 this.mouseDelayMet = !this.options.delay;
582 if (!this.mouseDelayMet) {
583 this._mouseDelayTimer = setTimeout(function() {
584 self.mouseDelayMet = true;
585 }, this.options.delay);
588 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
589 this._mouseStarted = (this._mouseStart(event) !== false);
590 if (!this._mouseStarted) {
591 event.preventDefault();
596 // these delegates are required to keep context
597 this._mouseMoveDelegate = function(event) {
598 return self._mouseMove(event);
600 this._mouseUpDelegate = function(event) {
601 return self._mouseUp(event);
604 .bind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
605 .bind('mouseup.'+this.widgetName, this._mouseUpDelegate);
607 // preventDefault() is used to prevent the selection of text here -
608 // however, in Safari, this causes select boxes not to be selectable
609 // anymore, so this fix is needed
610 ($.browser.safari || event.preventDefault());
612 event.originalEvent.mouseHandled = true;
616 _mouseMove: function(event) {
617 // IE mouseup check - mouseup happened when mouse was out of window
618 if ($.browser.msie && !event.button) {
619 return this._mouseUp(event);
622 if (this._mouseStarted) {
623 this._mouseDrag(event);
624 return event.preventDefault();
627 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
629 (this._mouseStart(this._mouseDownEvent, event) !== false);
630 (this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
633 return !this._mouseStarted;
636 _mouseUp: function(event) {
638 .unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
639 .unbind('mouseup.'+this.widgetName, this._mouseUpDelegate);
641 if (this._mouseStarted) {
642 this._mouseStarted = false;
643 this._preventClickEvent = (event.target == this._mouseDownEvent.target);
644 this._mouseStop(event);
650 _mouseDistanceMet: function(event) {
652 Math.abs(this._mouseDownEvent.pageX - event.pageX),
653 Math.abs(this._mouseDownEvent.pageY - event.pageY)
654 ) >= this.options.distance
658 _mouseDelayMet: function(event) {
659 return this.mouseDelayMet;
662 // These are placeholder methods, to be overriden by extending plugin
663 _mouseStart: function(event) {},
664 _mouseDrag: function(event) {},
665 _mouseStop: function(event) {},
666 _mouseCapture: function(event) { return true; }
671 * jQuery UI Position 1.8.4
673 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
674 * Dual licensed under the MIT or GPL Version 2 licenses.
675 * http://jquery.org/license
677 * http://docs.jquery.com/UI/Position
679 (function( $, undefined ) {
683 var horizontalPositions = /left|center|right/,
684 horizontalDefault = "center",
685 verticalPositions = /top|center|bottom/,
686 verticalDefault = "center",
687 _position = $.fn.position,
688 _offset = $.fn.offset;
690 $.fn.position = function( options ) {
691 if ( !options || !options.of ) {
692 return _position.apply( this, arguments );
695 // make a copy, we don't want to modify arguments
696 options = $.extend( {}, options );
698 var target = $( options.of ),
699 collision = ( options.collision || "flip" ).split( " " ),
700 offset = options.offset ? options.offset.split( " " ) : [ 0, 0 ],
705 if ( options.of.nodeType === 9 ) {
706 targetWidth = target.width();
707 targetHeight = target.height();
708 basePosition = { top: 0, left: 0 };
709 } else if ( options.of.scrollTo && options.of.document ) {
710 targetWidth = target.width();
711 targetHeight = target.height();
712 basePosition = { top: target.scrollTop(), left: target.scrollLeft() };
713 } else if ( options.of.preventDefault ) {
714 // force left top to allow flipping
715 options.at = "left top";
716 targetWidth = targetHeight = 0;
717 basePosition = { top: options.of.pageY, left: options.of.pageX };
719 targetWidth = target.outerWidth();
720 targetHeight = target.outerHeight();
721 basePosition = target.offset();
724 // force my and at to have valid horizontal and veritcal positions
725 // if a value is missing or invalid, it will be converted to center
726 $.each( [ "my", "at" ], function() {
727 var pos = ( options[this] || "" ).split( " " );
728 if ( pos.length === 1) {
729 pos = horizontalPositions.test( pos[0] ) ?
730 pos.concat( [verticalDefault] ) :
731 verticalPositions.test( pos[0] ) ?
732 [ horizontalDefault ].concat( pos ) :
733 [ horizontalDefault, verticalDefault ];
735 pos[ 0 ] = horizontalPositions.test( pos[0] ) ? pos[ 0 ] : horizontalDefault;
736 pos[ 1 ] = verticalPositions.test( pos[1] ) ? pos[ 1 ] : verticalDefault;
737 options[ this ] = pos;
740 // normalize collision option
741 if ( collision.length === 1 ) {
742 collision[ 1 ] = collision[ 0 ];
745 // normalize offset option
746 offset[ 0 ] = parseInt( offset[0], 10 ) || 0;
747 if ( offset.length === 1 ) {
748 offset[ 1 ] = offset[ 0 ];
750 offset[ 1 ] = parseInt( offset[1], 10 ) || 0;
752 if ( options.at[0] === "right" ) {
753 basePosition.left += targetWidth;
754 } else if (options.at[0] === horizontalDefault ) {
755 basePosition.left += targetWidth / 2;
758 if ( options.at[1] === "bottom" ) {
759 basePosition.top += targetHeight;
760 } else if ( options.at[1] === verticalDefault ) {
761 basePosition.top += targetHeight / 2;
764 basePosition.left += offset[ 0 ];
765 basePosition.top += offset[ 1 ];
767 return this.each(function() {
768 var elem = $( this ),
769 elemWidth = elem.outerWidth(),
770 elemHeight = elem.outerHeight(),
771 position = $.extend( {}, basePosition );
773 if ( options.my[0] === "right" ) {
774 position.left -= elemWidth;
775 } else if ( options.my[0] === horizontalDefault ) {
776 position.left -= elemWidth / 2;
779 if ( options.my[1] === "bottom" ) {
780 position.top -= elemHeight;
781 } else if ( options.my[1] === verticalDefault ) {
782 position.top -= elemHeight / 2;
785 // prevent fractions (see #5280)
786 position.left = parseInt( position.left );
787 position.top = parseInt( position.top );
789 $.each( [ "left", "top" ], function( i, dir ) {
790 if ( $.ui.position[ collision[i] ] ) {
791 $.ui.position[ collision[i] ][ dir ]( position, {
792 targetWidth: targetWidth,
793 targetHeight: targetHeight,
794 elemWidth: elemWidth,
795 elemHeight: elemHeight,
803 if ( $.fn.bgiframe ) {
806 elem.offset( $.extend( position, { using: options.using } ) );
812 left: function( position, data ) {
813 var win = $( window ),
814 over = position.left + data.elemWidth - win.width() - win.scrollLeft();
815 position.left = over > 0 ? position.left - over : Math.max( 0, position.left );
817 top: function( position, data ) {
818 var win = $( window ),
819 over = position.top + data.elemHeight - win.height() - win.scrollTop();
820 position.top = over > 0 ? position.top - over : Math.max( 0, position.top );
825 left: function( position, data ) {
826 if ( data.at[0] === "center" ) {
829 var win = $( window ),
830 over = position.left + data.elemWidth - win.width() - win.scrollLeft(),
831 myOffset = data.my[ 0 ] === "left" ?
833 data.my[ 0 ] === "right" ?
836 offset = -2 * data.offset[ 0 ];
837 position.left += position.left < 0 ?
838 myOffset + data.targetWidth + offset :
840 myOffset - data.targetWidth + offset :
843 top: function( position, data ) {
844 if ( data.at[1] === "center" ) {
847 var win = $( window ),
848 over = position.top + data.elemHeight - win.height() - win.scrollTop(),
849 myOffset = data.my[ 1 ] === "top" ?
851 data.my[ 1 ] === "bottom" ?
854 atOffset = data.at[ 1 ] === "top" ?
857 offset = -2 * data.offset[ 1 ];
858 position.top += position.top < 0 ?
859 myOffset + data.targetHeight + offset :
861 myOffset + atOffset + offset :
867 // offset setter from jQuery 1.4
868 if ( !$.offset.setOffset ) {
869 $.offset.setOffset = function( elem, options ) {
870 // set position first, in-case top/left are set even on static elem
871 if ( /static/.test( $.curCSS( elem, "position" ) ) ) {
872 elem.style.position = "relative";
874 var curElem = $( elem ),
875 curOffset = curElem.offset(),
876 curTop = parseInt( $.curCSS( elem, "top", true ), 10 ) || 0,
877 curLeft = parseInt( $.curCSS( elem, "left", true ), 10) || 0,
879 top: (options.top - curOffset.top) + curTop,
880 left: (options.left - curOffset.left) + curLeft
883 if ( 'using' in options ) {
884 options.using.call( elem, props );
886 curElem.css( props );
890 $.fn.offset = function( options ) {
891 var elem = this[ 0 ];
892 if ( !elem || !elem.ownerDocument ) { return null; }
894 return this.each(function() {
895 $.offset.setOffset( this, options );
898 return _offset.call( this );
904 * jQuery UI Draggable 1.8.4
906 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
907 * Dual licensed under the MIT or GPL Version 2 licenses.
908 * http://jquery.org/license
910 * http://docs.jquery.com/UI/Draggables
915 * jquery.ui.widget.js
917 (function( $, undefined ) {
919 $.widget("ui.draggable", $.ui.mouse, {
920 widgetEventPrefix: "drag",
925 connectToSortable: false,
934 refreshPositions: false,
939 scrollSensitivity: 20,
947 _create: function() {
949 if (this.options.helper == 'original' && !(/^(?:r|a|f)/).test(this.element.css("position")))
950 this.element[0].style.position = 'relative';
952 (this.options.addClasses && this.element.addClass("ui-draggable"));
953 (this.options.disabled && this.element.addClass("ui-draggable-disabled"));
959 destroy: function() {
960 if(!this.element.data('draggable')) return;
962 .removeData("draggable")
963 .unbind(".draggable")
964 .removeClass("ui-draggable"
965 + " ui-draggable-dragging"
966 + " ui-draggable-disabled");
967 this._mouseDestroy();
972 _mouseCapture: function(event) {
974 var o = this.options;
976 // among others, prevent a drag on a resizable-handle
977 if (this.helper || o.disabled || $(event.target).is('.ui-resizable-handle'))
980 //Quit if we're not on a valid handle
981 this.handle = this._getHandle(event);
989 _mouseStart: function(event) {
991 var o = this.options;
993 //Create and append the visible helper
994 this.helper = this._createHelper(event);
996 //Cache the helper size
997 this._cacheHelperProportions();
999 //If ddmanager is used for droppables, set the global draggable
1001 $.ui.ddmanager.current = this;
1004 * - Position generation -
1005 * This block generates everything position related - it's the core of draggables.
1008 //Cache the margins of the original element
1009 this._cacheMargins();
1011 //Store the helper's css position
1012 this.cssPosition = this.helper.css("position");
1013 this.scrollParent = this.helper.scrollParent();
1015 //The element's absolute position on the page minus margins
1016 this.offset = this.positionAbs = this.element.offset();
1018 top: this.offset.top - this.margins.top,
1019 left: this.offset.left - this.margins.left
1022 $.extend(this.offset, {
1023 click: { //Where the click happened, relative to the element
1024 left: event.pageX - this.offset.left,
1025 top: event.pageY - this.offset.top
1027 parent: this._getParentOffset(),
1028 relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
1031 //Generate the original position
1032 this.originalPosition = this.position = this._generatePosition(event);
1033 this.originalPageX = event.pageX;
1034 this.originalPageY = event.pageY;
1036 //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
1037 (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
1039 //Set a containment if given in the options
1041 this._setContainment();
1043 //Trigger event + callbacks
1044 if(this._trigger("start", event) === false) {
1049 //Recache the helper size
1050 this._cacheHelperProportions();
1052 //Prepare the droppable offsets
1053 if ($.ui.ddmanager && !o.dropBehaviour)
1054 $.ui.ddmanager.prepareOffsets(this, event);
1056 this.helper.addClass("ui-draggable-dragging");
1057 this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position
1061 _mouseDrag: function(event, noPropagation) {
1063 //Compute the helpers position
1064 this.position = this._generatePosition(event);
1065 this.positionAbs = this._convertPositionTo("absolute");
1067 //Call plugins and callbacks and use the resulting position if something is returned
1068 if (!noPropagation) {
1069 var ui = this._uiHash();
1070 if(this._trigger('drag', event, ui) === false) {
1074 this.position = ui.position;
1077 if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
1078 if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
1079 if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
1084 _mouseStop: function(event) {
1086 //If we are using droppables, inform the manager about the drop
1087 var dropped = false;
1088 if ($.ui.ddmanager && !this.options.dropBehaviour)
1089 dropped = $.ui.ddmanager.drop(this, event);
1091 //if a drop comes from outside (a sortable)
1093 dropped = this.dropped;
1094 this.dropped = false;
1097 //if the original element is removed, don't bother to continue
1098 if(!this.element[0] || !this.element[0].parentNode)
1101 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))) {
1103 $(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() {
1104 if(self._trigger("stop", event) !== false) {
1109 if(this._trigger("stop", event) !== false) {
1117 cancel: function() {
1119 if(this.helper.is(".ui-draggable-dragging")) {
1129 _getHandle: function(event) {
1131 var handle = !this.options.handle || !$(this.options.handle, this.element).length ? true : false;
1132 $(this.options.handle, this.element)
1136 if(this == event.target) handle = true;
1143 _createHelper: function(event) {
1145 var o = this.options;
1146 var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper == 'clone' ? this.element.clone() : this.element);
1148 if(!helper.parents('body').length)
1149 helper.appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo));
1151 if(helper[0] != this.element[0] && !(/(fixed|absolute)/).test(helper.css("position")))
1152 helper.css("position", "absolute");
1158 _adjustOffsetFromHelper: function(obj) {
1159 if (typeof obj == 'string') {
1160 obj = obj.split(' ');
1162 if ($.isArray(obj)) {
1163 obj = {left: +obj[0], top: +obj[1] || 0};
1165 if ('left' in obj) {
1166 this.offset.click.left = obj.left + this.margins.left;
1168 if ('right' in obj) {
1169 this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
1172 this.offset.click.top = obj.top + this.margins.top;
1174 if ('bottom' in obj) {
1175 this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
1179 _getParentOffset: function() {
1181 //Get the offsetParent and cache its position
1182 this.offsetParent = this.helper.offsetParent();
1183 var po = this.offsetParent.offset();
1185 // This is a special case where we need to modify a offset calculated on start, since the following happened:
1186 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
1187 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
1188 // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
1189 if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) {
1190 po.left += this.scrollParent.scrollLeft();
1191 po.top += this.scrollParent.scrollTop();
1194 if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
1195 || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix
1196 po = { top: 0, left: 0 };
1199 top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
1200 left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
1205 _getRelativeOffset: function() {
1207 if(this.cssPosition == "relative") {
1208 var p = this.element.position();
1210 top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
1211 left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
1214 return { top: 0, left: 0 };
1219 _cacheMargins: function() {
1221 left: (parseInt(this.element.css("marginLeft"),10) || 0),
1222 top: (parseInt(this.element.css("marginTop"),10) || 0)
1226 _cacheHelperProportions: function() {
1227 this.helperProportions = {
1228 width: this.helper.outerWidth(),
1229 height: this.helper.outerHeight()
1233 _setContainment: function() {
1235 var o = this.options;
1236 if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
1237 if(o.containment == 'document' || o.containment == 'window') this.containment = [
1238 0 - this.offset.relative.left - this.offset.parent.left,
1239 0 - this.offset.relative.top - this.offset.parent.top,
1240 $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
1241 ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
1244 if(!(/^(document|window|parent)$/).test(o.containment) && o.containment.constructor != Array) {
1245 var ce = $(o.containment)[0]; if(!ce) return;
1246 var co = $(o.containment).offset();
1247 var over = ($(ce).css("overflow") != 'hidden');
1249 this.containment = [
1250 co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
1251 co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
1252 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,
1253 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
1255 } else if(o.containment.constructor == Array) {
1256 this.containment = o.containment;
1261 _convertPositionTo: function(d, pos) {
1263 if(!pos) pos = this.position;
1264 var mod = d == "absolute" ? 1 : -1;
1265 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);
1269 pos.top // The absolute mouse position
1270 + this.offset.relative.top * mod // Only for relative positioned nodes: Relative offset from element to offset parent
1271 + this.offset.parent.top * mod // The offsetParent's offset without borders (offset + border)
1272 - ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
1275 pos.left // The absolute mouse position
1276 + this.offset.relative.left * mod // Only for relative positioned nodes: Relative offset from element to offset parent
1277 + this.offset.parent.left * mod // The offsetParent's offset without borders (offset + border)
1278 - ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
1284 _generatePosition: function(event) {
1286 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);
1287 var pageX = event.pageX;
1288 var pageY = event.pageY;
1291 * - Position constraining -
1292 * Constrain the position to a mix of grid, containment.
1295 if(this.originalPosition) { //If we are not dragging yet, we won't check for options
1297 if(this.containment) {
1298 if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left;
1299 if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top;
1300 if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left;
1301 if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top;
1305 var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
1306 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;
1308 var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
1309 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;
1316 pageY // The absolute mouse position
1317 - this.offset.click.top // Click offset (relative to the element)
1318 - this.offset.relative.top // Only for relative positioned nodes: Relative offset from element to offset parent
1319 - this.offset.parent.top // The offsetParent's offset without borders (offset + border)
1320 + ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
1323 pageX // The absolute mouse position
1324 - this.offset.click.left // Click offset (relative to the element)
1325 - this.offset.relative.left // Only for relative positioned nodes: Relative offset from element to offset parent
1326 - this.offset.parent.left // The offsetParent's offset without borders (offset + border)
1327 + ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
1333 _clear: function() {
1334 this.helper.removeClass("ui-draggable-dragging");
1335 if(this.helper[0] != this.element[0] && !this.cancelHelperRemoval) this.helper.remove();
1336 //if($.ui.ddmanager) $.ui.ddmanager.current = null;
1338 this.cancelHelperRemoval = false;
1341 // From now on bulk stuff - mainly helpers
1343 _trigger: function(type, event, ui) {
1344 ui = ui || this._uiHash();
1345 $.ui.plugin.call(this, type, [event, ui]);
1346 if(type == "drag") this.positionAbs = this._convertPositionTo("absolute"); //The absolute position has to be recalculated after plugins
1347 return $.Widget.prototype._trigger.call(this, type, event, ui);
1352 _uiHash: function(event) {
1354 helper: this.helper,
1355 position: this.position,
1356 originalPosition: this.originalPosition,
1357 offset: this.positionAbs
1363 $.extend($.ui.draggable, {
1367 $.ui.plugin.add("draggable", "connectToSortable", {
1368 start: function(event, ui) {
1370 var inst = $(this).data("draggable"), o = inst.options,
1371 uiSortable = $.extend({}, ui, { item: inst.element });
1372 inst.sortables = [];
1373 $(o.connectToSortable).each(function() {
1374 var sortable = $.data(this, 'sortable');
1375 if (sortable && !sortable.options.disabled) {
1376 inst.sortables.push({
1378 shouldRevert: sortable.options.revert
1380 sortable._refreshItems(); //Do a one-time refresh at start to refresh the containerCache
1381 sortable._trigger("activate", event, uiSortable);
1386 stop: function(event, ui) {
1388 //If we are still over the sortable, we fake the stop event of the sortable, but also remove helper
1389 var inst = $(this).data("draggable"),
1390 uiSortable = $.extend({}, ui, { item: inst.element });
1392 $.each(inst.sortables, function() {
1393 if(this.instance.isOver) {
1395 this.instance.isOver = 0;
1397 inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance
1398 this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work)
1400 //The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: 'valid/invalid'
1401 if(this.shouldRevert) this.instance.options.revert = true;
1403 //Trigger the stop of the sortable
1404 this.instance._mouseStop(event);
1406 this.instance.options.helper = this.instance.options._helper;
1408 //If the helper has been the original item, restore properties in the sortable
1409 if(inst.options.helper == 'original')
1410 this.instance.currentItem.css({ top: 'auto', left: 'auto' });
1413 this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance
1414 this.instance._trigger("deactivate", event, uiSortable);
1420 drag: function(event, ui) {
1422 var inst = $(this).data("draggable"), self = this;
1424 var checkPos = function(o) {
1425 var dyClick = this.offset.click.top, dxClick = this.offset.click.left;
1426 var helperTop = this.positionAbs.top, helperLeft = this.positionAbs.left;
1427 var itemHeight = o.height, itemWidth = o.width;
1428 var itemTop = o.top, itemLeft = o.left;
1430 return $.ui.isOver(helperTop + dyClick, helperLeft + dxClick, itemTop, itemLeft, itemHeight, itemWidth);
1433 $.each(inst.sortables, function(i) {
1435 //Copy over some variables to allow calling the sortable's native _intersectsWith
1436 this.instance.positionAbs = inst.positionAbs;
1437 this.instance.helperProportions = inst.helperProportions;
1438 this.instance.offset.click = inst.offset.click;
1440 if(this.instance._intersectsWith(this.instance.containerCache)) {
1442 //If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once
1443 if(!this.instance.isOver) {
1445 this.instance.isOver = 1;
1446 //Now we fake the start of dragging for the sortable instance,
1447 //by cloning the list group item, appending it to the sortable and using it as inst.currentItem
1448 //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)
1449 this.instance.currentItem = $(self).clone().appendTo(this.instance.element).data("sortable-item", true);
1450 this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it
1451 this.instance.options.helper = function() { return ui.helper[0]; };
1453 event.target = this.instance.currentItem[0];
1454 this.instance._mouseCapture(event, true);
1455 this.instance._mouseStart(event, true, true);
1457 //Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes
1458 this.instance.offset.click.top = inst.offset.click.top;
1459 this.instance.offset.click.left = inst.offset.click.left;
1460 this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left;
1461 this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top;
1463 inst._trigger("toSortable", event);
1464 inst.dropped = this.instance.element; //draggable revert needs that
1465 //hack so receive/update callbacks work (mostly)
1466 inst.currentItem = inst.element;
1467 this.instance.fromOutside = inst;
1471 //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
1472 if(this.instance.currentItem) this.instance._mouseDrag(event);
1476 //If it doesn't intersect with the sortable, and it intersected before,
1477 //we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval
1478 if(this.instance.isOver) {
1480 this.instance.isOver = 0;
1481 this.instance.cancelHelperRemoval = true;
1483 //Prevent reverting on this forced stop
1484 this.instance.options.revert = false;
1486 // The out event needs to be triggered independently
1487 this.instance._trigger('out', event, this.instance._uiHash(this.instance));
1489 this.instance._mouseStop(event, true);
1490 this.instance.options.helper = this.instance.options._helper;
1492 //Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size
1493 this.instance.currentItem.remove();
1494 if(this.instance.placeholder) this.instance.placeholder.remove();
1496 inst._trigger("fromSortable", event);
1497 inst.dropped = false; //draggable revert needs that
1507 $.ui.plugin.add("draggable", "cursor", {
1508 start: function(event, ui) {
1509 var t = $('body'), o = $(this).data('draggable').options;
1510 if (t.css("cursor")) o._cursor = t.css("cursor");
1511 t.css("cursor", o.cursor);
1513 stop: function(event, ui) {
1514 var o = $(this).data('draggable').options;
1515 if (o._cursor) $('body').css("cursor", o._cursor);
1519 $.ui.plugin.add("draggable", "iframeFix", {
1520 start: function(event, ui) {
1521 var o = $(this).data('draggable').options;
1522 $(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() {
1523 $('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>')
1525 width: this.offsetWidth+"px", height: this.offsetHeight+"px",
1526 position: "absolute", opacity: "0.001", zIndex: 1000
1528 .css($(this).offset())
1532 stop: function(event, ui) {
1533 $("div.ui-draggable-iframeFix").each(function() { this.parentNode.removeChild(this); }); //Remove frame helpers
1537 $.ui.plugin.add("draggable", "opacity", {
1538 start: function(event, ui) {
1539 var t = $(ui.helper), o = $(this).data('draggable').options;
1540 if(t.css("opacity")) o._opacity = t.css("opacity");
1541 t.css('opacity', o.opacity);
1543 stop: function(event, ui) {
1544 var o = $(this).data('draggable').options;
1545 if(o._opacity) $(ui.helper).css('opacity', o._opacity);
1549 $.ui.plugin.add("draggable", "scroll", {
1550 start: function(event, ui) {
1551 var i = $(this).data("draggable");
1552 if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') i.overflowOffset = i.scrollParent.offset();
1554 drag: function(event, ui) {
1556 var i = $(this).data("draggable"), o = i.options, scrolled = false;
1558 if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') {
1560 if(!o.axis || o.axis != 'x') {
1561 if((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
1562 i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed;
1563 else if(event.pageY - i.overflowOffset.top < o.scrollSensitivity)
1564 i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed;
1567 if(!o.axis || o.axis != 'y') {
1568 if((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
1569 i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed;
1570 else if(event.pageX - i.overflowOffset.left < o.scrollSensitivity)
1571 i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed;
1576 if(!o.axis || o.axis != 'x') {
1577 if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
1578 scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
1579 else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
1580 scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
1583 if(!o.axis || o.axis != 'y') {
1584 if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
1585 scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
1586 else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
1587 scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
1592 if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
1593 $.ui.ddmanager.prepareOffsets(i, event);
1598 $.ui.plugin.add("draggable", "snap", {
1599 start: function(event, ui) {
1601 var i = $(this).data("draggable"), o = i.options;
1602 i.snapElements = [];
1604 $(o.snap.constructor != String ? ( o.snap.items || ':data(draggable)' ) : o.snap).each(function() {
1605 var $t = $(this); var $o = $t.offset();
1606 if(this != i.element[0]) i.snapElements.push({
1608 width: $t.outerWidth(), height: $t.outerHeight(),
1609 top: $o.top, left: $o.left
1614 drag: function(event, ui) {
1616 var inst = $(this).data("draggable"), o = inst.options;
1617 var d = o.snapTolerance;
1619 var x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
1620 y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
1622 for (var i = inst.snapElements.length - 1; i >= 0; i--){
1624 var l = inst.snapElements[i].left, r = l + inst.snapElements[i].width,
1625 t = inst.snapElements[i].top, b = t + inst.snapElements[i].height;
1627 //Yes, I know, this is insane ;)
1628 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))) {
1629 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 })));
1630 inst.snapElements[i].snapping = false;
1634 if(o.snapMode != 'inner') {
1635 var ts = Math.abs(t - y2) <= d;
1636 var bs = Math.abs(b - y1) <= d;
1637 var ls = Math.abs(l - x2) <= d;
1638 var rs = Math.abs(r - x1) <= d;
1639 if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
1640 if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top;
1641 if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left;
1642 if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left;
1645 var first = (ts || bs || ls || rs);
1647 if(o.snapMode != 'outer') {
1648 var ts = Math.abs(t - y1) <= d;
1649 var bs = Math.abs(b - y2) <= d;
1650 var ls = Math.abs(l - x1) <= d;
1651 var rs = Math.abs(r - x2) <= d;
1652 if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top;
1653 if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
1654 if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left;
1655 if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left;
1658 if(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first))
1659 (inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
1660 inst.snapElements[i].snapping = (ts || bs || ls || rs || first);
1667 $.ui.plugin.add("draggable", "stack", {
1668 start: function(event, ui) {
1670 var o = $(this).data("draggable").options;
1672 var group = $.makeArray($(o.stack)).sort(function(a,b) {
1673 return (parseInt($(a).css("zIndex"),10) || 0) - (parseInt($(b).css("zIndex"),10) || 0);
1675 if (!group.length) { return; }
1677 var min = parseInt(group[0].style.zIndex) || 0;
1678 $(group).each(function(i) {
1679 this.style.zIndex = min + i;
1682 this[0].style.zIndex = min + group.length;
1687 $.ui.plugin.add("draggable", "zIndex", {
1688 start: function(event, ui) {
1689 var t = $(ui.helper), o = $(this).data("draggable").options;
1690 if(t.css("zIndex")) o._zIndex = t.css("zIndex");
1691 t.css('zIndex', o.zIndex);
1693 stop: function(event, ui) {
1694 var o = $(this).data("draggable").options;
1695 if(o._zIndex) $(ui.helper).css('zIndex', o._zIndex);
1701 * jQuery UI Droppable 1.8.4
1703 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
1704 * Dual licensed under the MIT or GPL Version 2 licenses.
1705 * http://jquery.org/license
1707 * http://docs.jquery.com/UI/Droppables
1711 * jquery.ui.widget.js
1712 * jquery.ui.mouse.js
1713 * jquery.ui.draggable.js
1715 (function( $, undefined ) {
1717 $.widget("ui.droppable", {
1718 widgetEventPrefix: "drop",
1726 tolerance: 'intersect'
1728 _create: function() {
1730 var o = this.options, accept = o.accept;
1731 this.isover = 0; this.isout = 1;
1733 this.accept = $.isFunction(accept) ? accept : function(d) {
1734 return d.is(accept);
1737 //Store the droppable's proportions
1738 this.proportions = { width: this.element[0].offsetWidth, height: this.element[0].offsetHeight };
1740 // Add the reference and positions to the manager
1741 $.ui.ddmanager.droppables[o.scope] = $.ui.ddmanager.droppables[o.scope] || [];
1742 $.ui.ddmanager.droppables[o.scope].push(this);
1744 (o.addClasses && this.element.addClass("ui-droppable"));
1748 destroy: function() {
1749 var drop = $.ui.ddmanager.droppables[this.options.scope];
1750 for ( var i = 0; i < drop.length; i++ )
1751 if ( drop[i] == this )
1755 .removeClass("ui-droppable ui-droppable-disabled")
1756 .removeData("droppable")
1757 .unbind(".droppable");
1762 _setOption: function(key, value) {
1764 if(key == 'accept') {
1765 this.accept = $.isFunction(value) ? value : function(d) {
1769 $.Widget.prototype._setOption.apply(this, arguments);
1772 _activate: function(event) {
1773 var draggable = $.ui.ddmanager.current;
1774 if(this.options.activeClass) this.element.addClass(this.options.activeClass);
1775 (draggable && this._trigger('activate', event, this.ui(draggable)));
1778 _deactivate: function(event) {
1779 var draggable = $.ui.ddmanager.current;
1780 if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
1781 (draggable && this._trigger('deactivate', event, this.ui(draggable)));
1784 _over: function(event) {
1786 var draggable = $.ui.ddmanager.current;
1787 if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
1789 if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
1790 if(this.options.hoverClass) this.element.addClass(this.options.hoverClass);
1791 this._trigger('over', event, this.ui(draggable));
1796 _out: function(event) {
1798 var draggable = $.ui.ddmanager.current;
1799 if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
1801 if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
1802 if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
1803 this._trigger('out', event, this.ui(draggable));
1808 _drop: function(event,custom) {
1810 var draggable = custom || $.ui.ddmanager.current;
1811 if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return false; // Bail if draggable and droppable are same element
1813 var childrenIntersection = false;
1814 this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function() {
1815 var inst = $.data(this, 'droppable');
1818 && !inst.options.disabled
1819 && inst.options.scope == draggable.options.scope
1820 && inst.accept.call(inst.element[0], (draggable.currentItem || draggable.element))
1821 && $.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance)
1822 ) { childrenIntersection = true; return false; }
1824 if(childrenIntersection) return false;
1826 if(this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
1827 if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
1828 if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
1829 this._trigger('drop', event, this.ui(draggable));
1830 return this.element;
1839 draggable: (c.currentItem || c.element),
1841 position: c.position,
1842 offset: c.positionAbs
1848 $.extend($.ui.droppable, {
1852 $.ui.intersect = function(draggable, droppable, toleranceMode) {
1854 if (!droppable.offset) return false;
1856 var x1 = (draggable.positionAbs || draggable.position.absolute).left, x2 = x1 + draggable.helperProportions.width,
1857 y1 = (draggable.positionAbs || draggable.position.absolute).top, y2 = y1 + draggable.helperProportions.height;
1858 var l = droppable.offset.left, r = l + droppable.proportions.width,
1859 t = droppable.offset.top, b = t + droppable.proportions.height;
1861 switch (toleranceMode) {
1863 return (l <= x1 && x2 <= r
1864 && t <= y1 && y2 <= b);
1867 return (l < x1 + (draggable.helperProportions.width / 2) // Right Half
1868 && x2 - (draggable.helperProportions.width / 2) < r // Left Half
1869 && t < y1 + (draggable.helperProportions.height / 2) // Bottom Half
1870 && y2 - (draggable.helperProportions.height / 2) < b ); // Top Half
1873 var draggableLeft = ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left),
1874 draggableTop = ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top),
1875 isOver = $.ui.isOver(draggableTop, draggableLeft, t, l, droppable.proportions.height, droppable.proportions.width);
1880 (y1 >= t && y1 <= b) || // Top edge touching
1881 (y2 >= t && y2 <= b) || // Bottom edge touching
1882 (y1 < t && y2 > b) // Surrounded vertically
1884 (x1 >= l && x1 <= r) || // Left edge touching
1885 (x2 >= l && x2 <= r) || // Right edge touching
1886 (x1 < l && x2 > r) // Surrounded horizontally
1897 This manager tracks offsets of draggables and droppables
1901 droppables: { 'default': [] },
1902 prepareOffsets: function(t, event) {
1904 var m = $.ui.ddmanager.droppables[t.options.scope] || [];
1905 var type = event ? event.type : null; // workaround for #2317
1906 var list = (t.currentItem || t.element).find(":data(droppable)").andSelf();
1908 droppablesLoop: for (var i = 0; i < m.length; i++) {
1910 if(m[i].options.disabled || (t && !m[i].accept.call(m[i].element[0],(t.currentItem || t.element)))) continue; //No disabled and non-accepted
1911 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
1912 m[i].visible = m[i].element.css("display") != "none"; if(!m[i].visible) continue; //If the element is not visible, continue
1914 m[i].offset = m[i].element.offset();
1915 m[i].proportions = { width: m[i].element[0].offsetWidth, height: m[i].element[0].offsetHeight };
1917 if(type == "mousedown") m[i]._activate.call(m[i], event); //Activate the droppable if used directly from draggables
1922 drop: function(draggable, event) {
1924 var dropped = false;
1925 $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
1927 if(!this.options) return;
1928 if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance))
1929 dropped = dropped || this._drop.call(this, event);
1931 if (!this.options.disabled && this.visible && this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
1932 this.isout = 1; this.isover = 0;
1933 this._deactivate.call(this, event);
1940 drag: function(draggable, event) {
1942 //If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse.
1943 if(draggable.options.refreshPositions) $.ui.ddmanager.prepareOffsets(draggable, event);
1945 //Run through all droppables and check their positions based on specific tolerance options
1946 $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
1948 if(this.options.disabled || this.greedyChild || !this.visible) return;
1949 var intersects = $.ui.intersect(draggable, this, this.options.tolerance);
1951 var c = !intersects && this.isover == 1 ? 'isout' : (intersects && this.isover == 0 ? 'isover' : null);
1955 if (this.options.greedy) {
1956 var parent = this.element.parents(':data(droppable):eq(0)');
1957 if (parent.length) {
1958 parentInstance = $.data(parent[0], 'droppable');
1959 parentInstance.greedyChild = (c == 'isover' ? 1 : 0);
1963 // we just moved into a greedy child
1964 if (parentInstance && c == 'isover') {
1965 parentInstance['isover'] = 0;
1966 parentInstance['isout'] = 1;
1967 parentInstance._out.call(parentInstance, event);
1970 this[c] = 1; this[c == 'isout' ? 'isover' : 'isout'] = 0;
1971 this[c == "isover" ? "_over" : "_out"].call(this, event);
1973 // we just moved out of a greedy child
1974 if (parentInstance && c == 'isout') {
1975 parentInstance['isout'] = 0;
1976 parentInstance['isover'] = 1;
1977 parentInstance._over.call(parentInstance, event);
1986 * jQuery UI Resizable 1.8.4
1988 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
1989 * Dual licensed under the MIT or GPL Version 2 licenses.
1990 * http://jquery.org/license
1992 * http://docs.jquery.com/UI/Resizables
1996 * jquery.ui.mouse.js
1997 * jquery.ui.widget.js
1999 (function( $, undefined ) {
2001 $.widget("ui.resizable", $.ui.mouse, {
2002 widgetEventPrefix: "resize",
2006 animateDuration: "slow",
2007 animateEasing: "swing",
2021 _create: function() {
2023 var self = this, o = this.options;
2024 this.element.addClass("ui-resizable");
2027 _aspectRatio: !!(o.aspectRatio),
2028 aspectRatio: o.aspectRatio,
2029 originalElement: this.element,
2030 _proportionallyResizeElements: [],
2031 _helper: o.helper || o.ghost || o.animate ? o.helper || 'ui-resizable-helper' : null
2034 //Wrap the element if it cannot hold child nodes
2035 if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) {
2037 //Opera fix for relative positioning
2038 if (/relative/.test(this.element.css('position')) && $.browser.opera)
2039 this.element.css({ position: 'relative', top: 'auto', left: 'auto' });
2041 //Create a wrapper element and set the wrapper to the new current internal element
2043 $('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({
2044 position: this.element.css('position'),
2045 width: this.element.outerWidth(),
2046 height: this.element.outerHeight(),
2047 top: this.element.css('top'),
2048 left: this.element.css('left')
2052 //Overwrite the original this.element
2053 this.element = this.element.parent().data(
2054 "resizable", this.element.data('resizable')
2057 this.elementIsWrapper = true;
2059 //Move margins to the wrapper
2060 this.element.css({ marginLeft: this.originalElement.css("marginLeft"), marginTop: this.originalElement.css("marginTop"), marginRight: this.originalElement.css("marginRight"), marginBottom: this.originalElement.css("marginBottom") });
2061 this.originalElement.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0});
2063 //Prevent Safari textarea resize
2064 this.originalResizeStyle = this.originalElement.css('resize');
2065 this.originalElement.css('resize', 'none');
2067 //Push the actual element to our proportionallyResize internal array
2068 this._proportionallyResizeElements.push(this.originalElement.css({ position: 'static', zoom: 1, display: 'block' }));
2070 // avoid IE jump (hard set the margin)
2071 this.originalElement.css({ margin: this.originalElement.css('margin') });
2073 // fix handlers offset
2074 this._proportionallyResize();
2078 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' });
2079 if(this.handles.constructor == String) {
2081 if(this.handles == 'all') this.handles = 'n,e,s,w,se,sw,ne,nw';
2082 var n = this.handles.split(","); this.handles = {};
2084 for(var i = 0; i < n.length; i++) {
2086 var handle = $.trim(n[i]), hname = 'ui-resizable-'+handle;
2087 var axis = $('<div class="ui-resizable-handle ' + hname + '"></div>');
2089 // increase zIndex of sw, se, ne, nw axis
2090 //TODO : this modifies original option
2091 if(/sw|se|ne|nw/.test(handle)) axis.css({ zIndex: ++o.zIndex });
2093 //TODO : What's going on here?
2094 if ('se' == handle) {
2095 axis.addClass('ui-icon ui-icon-gripsmall-diagonal-se');
2098 //Insert into internal handles object and append to element
2099 this.handles[handle] = '.ui-resizable-'+handle;
2100 this.element.append(axis);
2105 this._renderAxis = function(target) {
2107 target = target || this.element;
2109 for(var i in this.handles) {
2111 if(this.handles[i].constructor == String)
2112 this.handles[i] = $(this.handles[i], this.element).show();
2114 //Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls)
2115 if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) {
2117 var axis = $(this.handles[i], this.element), padWrapper = 0;
2119 //Checking the correct pad and border
2120 padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth();
2122 //The padding type i have to apply...
2123 var padPos = [ 'padding',
2124 /ne|nw|n/.test(i) ? 'Top' :
2125 /se|sw|s/.test(i) ? 'Bottom' :
2126 /^e$/.test(i) ? 'Right' : 'Left' ].join("");
2128 target.css(padPos, padWrapper);
2130 this._proportionallyResize();
2134 //TODO: What's that good for? There's not anything to be executed left
2135 if(!$(this.handles[i]).length)
2141 //TODO: make renderAxis a prototype function
2142 this._renderAxis(this.element);
2144 this._handles = $('.ui-resizable-handle', this.element)
2145 .disableSelection();
2147 //Matching axis name
2148 this._handles.mouseover(function() {
2149 if (!self.resizing) {
2151 var axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);
2152 //Axis, default = se
2153 self.axis = axis && axis[1] ? axis[1] : 'se';
2157 //If we want to auto hide the elements
2159 this._handles.hide();
2161 .addClass("ui-resizable-autohide")
2163 $(this).removeClass("ui-resizable-autohide");
2164 self._handles.show();
2167 if (!self.resizing) {
2168 $(this).addClass("ui-resizable-autohide");
2169 self._handles.hide();
2174 //Initialize the mouse interaction
2179 destroy: function() {
2181 this._mouseDestroy();
2183 var _destroy = function(exp) {
2184 $(exp).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing")
2185 .removeData("resizable").unbind(".resizable").find('.ui-resizable-handle').remove();
2188 //TODO: Unwrap at same DOM position
2189 if (this.elementIsWrapper) {
2190 _destroy(this.element);
2191 var wrapper = this.element;
2193 this.originalElement.css({
2194 position: wrapper.css('position'),
2195 width: wrapper.outerWidth(),
2196 height: wrapper.outerHeight(),
2197 top: wrapper.css('top'),
2198 left: wrapper.css('left')
2203 this.originalElement.css('resize', this.originalResizeStyle);
2204 _destroy(this.originalElement);
2209 _mouseCapture: function(event) {
2211 for (var i in this.handles) {
2212 if ($(this.handles[i])[0] == event.target) {
2217 return !this.options.disabled && handle;
2220 _mouseStart: function(event) {
2222 var o = this.options, iniPos = this.element.position(), el = this.element;
2224 this.resizing = true;
2225 this.documentScroll = { top: $(document).scrollTop(), left: $(document).scrollLeft() };
2227 // bugfix for http://dev.jquery.com/ticket/1749
2228 if (el.is('.ui-draggable') || (/absolute/).test(el.css('position'))) {
2229 el.css({ position: 'absolute', top: iniPos.top, left: iniPos.left });
2232 //Opera fixing relative position
2233 if ($.browser.opera && (/relative/).test(el.css('position')))
2234 el.css({ position: 'relative', top: 'auto', left: 'auto' });
2236 this._renderProxy();
2238 var curleft = num(this.helper.css('left')), curtop = num(this.helper.css('top'));
2240 if (o.containment) {
2241 curleft += $(o.containment).scrollLeft() || 0;
2242 curtop += $(o.containment).scrollTop() || 0;
2245 //Store needed variables
2246 this.offset = this.helper.offset();
2247 this.position = { left: curleft, top: curtop };
2248 this.size = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
2249 this.originalSize = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
2250 this.originalPosition = { left: curleft, top: curtop };
2251 this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() };
2252 this.originalMousePosition = { left: event.pageX, top: event.pageY };
2255 this.aspectRatio = (typeof o.aspectRatio == 'number') ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1);
2257 var cursor = $('.ui-resizable-' + this.axis).css('cursor');
2258 $('body').css('cursor', cursor == 'auto' ? this.axis + '-resize' : cursor);
2260 el.addClass("ui-resizable-resizing");
2261 this._propagate("start", event);
2265 _mouseDrag: function(event) {
2267 //Increase performance, avoid regex
2268 var el = this.helper, o = this.options, props = {},
2269 self = this, smp = this.originalMousePosition, a = this.axis;
2271 var dx = (event.pageX-smp.left)||0, dy = (event.pageY-smp.top)||0;
2272 var trigger = this._change[a];
2273 if (!trigger) return false;
2275 // Calculate the attrs that will be change
2276 var data = trigger.apply(this, [event, dx, dy]), ie6 = $.browser.msie && $.browser.version < 7, csdif = this.sizeDiff;
2278 if (this._aspectRatio || event.shiftKey)
2279 data = this._updateRatio(data, event);
2281 data = this._respectSize(data, event);
2283 // plugins callbacks need to be called first
2284 this._propagate("resize", event);
2287 top: this.position.top + "px", left: this.position.left + "px",
2288 width: this.size.width + "px", height: this.size.height + "px"
2291 if (!this._helper && this._proportionallyResizeElements.length)
2292 this._proportionallyResize();
2294 this._updateCache(data);
2296 // calling the user callback at the end
2297 this._trigger('resize', event, this.ui());
2302 _mouseStop: function(event) {
2304 this.resizing = false;
2305 var o = this.options, self = this;
2308 var pr = this._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
2309 soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
2310 soffsetw = ista ? 0 : self.sizeDiff.width;
2312 var s = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },
2313 left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
2314 top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
2317 this.element.css($.extend(s, { top: top, left: left }));
2319 self.helper.height(self.size.height);
2320 self.helper.width(self.size.width);
2322 if (this._helper && !o.animate) this._proportionallyResize();
2325 $('body').css('cursor', 'auto');
2327 this.element.removeClass("ui-resizable-resizing");
2329 this._propagate("stop", event);
2331 if (this._helper) this.helper.remove();
2336 _updateCache: function(data) {
2337 var o = this.options;
2338 this.offset = this.helper.offset();
2339 if (isNumber(data.left)) this.position.left = data.left;
2340 if (isNumber(data.top)) this.position.top = data.top;
2341 if (isNumber(data.height)) this.size.height = data.height;
2342 if (isNumber(data.width)) this.size.width = data.width;
2345 _updateRatio: function(data, event) {
2347 var o = this.options, cpos = this.position, csize = this.size, a = this.axis;
2349 if (data.height) data.width = (csize.height * this.aspectRatio);
2350 else if (data.width) data.height = (csize.width / this.aspectRatio);
2353 data.left = cpos.left + (csize.width - data.width);
2357 data.top = cpos.top + (csize.height - data.height);
2358 data.left = cpos.left + (csize.width - data.width);
2364 _respectSize: function(data, event) {
2366 var el = this.helper, o = this.options, pRatio = this._aspectRatio || event.shiftKey, a = this.axis,
2367 ismaxw = isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh = isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height),
2368 isminw = isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh = isNumber(data.height) && o.minHeight && (o.minHeight > data.height);
2370 if (isminw) data.width = o.minWidth;
2371 if (isminh) data.height = o.minHeight;
2372 if (ismaxw) data.width = o.maxWidth;
2373 if (ismaxh) data.height = o.maxHeight;
2375 var dw = this.originalPosition.left + this.originalSize.width, dh = this.position.top + this.size.height;
2376 var cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a);
2378 if (isminw && cw) data.left = dw - o.minWidth;
2379 if (ismaxw && cw) data.left = dw - o.maxWidth;
2380 if (isminh && ch) data.top = dh - o.minHeight;
2381 if (ismaxh && ch) data.top = dh - o.maxHeight;
2383 // fixing jump error on top/left - bug #2330
2384 var isNotwh = !data.width && !data.height;
2385 if (isNotwh && !data.left && data.top) data.top = null;
2386 else if (isNotwh && !data.top && data.left) data.left = null;
2391 _proportionallyResize: function() {
2393 var o = this.options;
2394 if (!this._proportionallyResizeElements.length) return;
2395 var element = this.helper || this.element;
2397 for (var i=0; i < this._proportionallyResizeElements.length; i++) {
2399 var prel = this._proportionallyResizeElements[i];
2401 if (!this.borderDif) {
2402 var b = [prel.css('borderTopWidth'), prel.css('borderRightWidth'), prel.css('borderBottomWidth'), prel.css('borderLeftWidth')],
2403 p = [prel.css('paddingTop'), prel.css('paddingRight'), prel.css('paddingBottom'), prel.css('paddingLeft')];
2405 this.borderDif = $.map(b, function(v, i) {
2406 var border = parseInt(v,10)||0, padding = parseInt(p[i],10)||0;
2407 return border + padding;
2411 if ($.browser.msie && !(!($(element).is(':hidden') || $(element).parents(':hidden').length)))
2415 height: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0,
2416 width: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0
2423 _renderProxy: function() {
2425 var el = this.element, o = this.options;
2426 this.elementOffset = el.offset();
2430 this.helper = this.helper || $('<div style="overflow:hidden;"></div>');
2432 // fix ie6 offset TODO: This seems broken
2433 var ie6 = $.browser.msie && $.browser.version < 7, ie6offset = (ie6 ? 1 : 0),
2434 pxyoffset = ( ie6 ? 2 : -1 );
2436 this.helper.addClass(this._helper).css({
2437 width: this.element.outerWidth() + pxyoffset,
2438 height: this.element.outerHeight() + pxyoffset,
2439 position: 'absolute',
2440 left: this.elementOffset.left - ie6offset +'px',
2441 top: this.elementOffset.top - ie6offset +'px',
2442 zIndex: ++o.zIndex //TODO: Don't modify option
2447 .disableSelection();
2450 this.helper = this.element;
2456 e: function(event, dx, dy) {
2457 return { width: this.originalSize.width + dx };
2459 w: function(event, dx, dy) {
2460 var o = this.options, cs = this.originalSize, sp = this.originalPosition;
2461 return { left: sp.left + dx, width: cs.width - dx };
2463 n: function(event, dx, dy) {
2464 var o = this.options, cs = this.originalSize, sp = this.originalPosition;
2465 return { top: sp.top + dy, height: cs.height - dy };
2467 s: function(event, dx, dy) {
2468 return { height: this.originalSize.height + dy };
2470 se: function(event, dx, dy) {
2471 return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
2473 sw: function(event, dx, dy) {
2474 return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
2476 ne: function(event, dx, dy) {
2477 return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
2479 nw: function(event, dx, dy) {
2480 return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
2484 _propagate: function(n, event) {
2485 $.ui.plugin.call(this, n, [event, this.ui()]);
2486 (n != "resize" && this._trigger(n, event, this.ui()));
2493 originalElement: this.originalElement,
2494 element: this.element,
2495 helper: this.helper,
2496 position: this.position,
2498 originalSize: this.originalSize,
2499 originalPosition: this.originalPosition
2505 $.extend($.ui.resizable, {
2510 * Resizable Extensions
2513 $.ui.plugin.add("resizable", "alsoResize", {
2515 start: function (event, ui) {
2516 var self = $(this).data("resizable"), o = self.options;
2518 var _store = function (exp) {
2519 $(exp).each(function() {
2521 el.data("resizable-alsoresize", {
2522 width: parseInt(el.width(), 10), height: parseInt(el.height(), 10),
2523 left: parseInt(el.css('left'), 10), top: parseInt(el.css('top'), 10),
2524 position: el.css('position') // to reset Opera on stop()
2529 if (typeof(o.alsoResize) == 'object' && !o.alsoResize.parentNode) {
2530 if (o.alsoResize.length) { o.alsoResize = o.alsoResize[0]; _store(o.alsoResize); }
2531 else { $.each(o.alsoResize, function (exp) { _store(exp); }); }
2533 _store(o.alsoResize);
2537 resize: function (event, ui) {
2538 var self = $(this).data("resizable"), o = self.options, os = self.originalSize, op = self.originalPosition;
2541 height: (self.size.height - os.height) || 0, width: (self.size.width - os.width) || 0,
2542 top: (self.position.top - op.top) || 0, left: (self.position.left - op.left) || 0
2545 _alsoResize = function (exp, c) {
2546 $(exp).each(function() {
2547 var el = $(this), start = $(this).data("resizable-alsoresize"), style = {},
2548 css = c && c.length ? c : el.parents(ui.originalElement[0]).length ? ['width', 'height'] : ['width', 'height', 'top', 'left'];
2550 $.each(css, function (i, prop) {
2551 var sum = (start[prop]||0) + (delta[prop]||0);
2552 if (sum && sum >= 0)
2553 style[prop] = sum || null;
2556 // Opera fixing relative position
2557 if ($.browser.opera && /relative/.test(el.css('position'))) {
2558 self._revertToRelativePosition = true;
2559 el.css({ position: 'absolute', top: 'auto', left: 'auto' });
2566 if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) {
2567 $.each(o.alsoResize, function (exp, c) { _alsoResize(exp, c); });
2569 _alsoResize(o.alsoResize);
2573 stop: function (event, ui) {
2574 var self = $(this).data("resizable"), o = self.options;
2576 var _reset = function (exp) {
2577 $(exp).each(function() {
2579 // reset position for Opera - no need to verify it was changed
2580 el.css({ position: el.data("resizable-alsoresize").position });
2584 if (self._revertToRelativePosition) {
2585 self._revertToRelativePosition = false;
2586 if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) {
2587 $.each(o.alsoResize, function (exp) { _reset(exp); });
2589 _reset(o.alsoResize);
2593 $(this).removeData("resizable-alsoresize");
2597 $.ui.plugin.add("resizable", "animate", {
2599 stop: function(event, ui) {
2600 var self = $(this).data("resizable"), o = self.options;
2602 var pr = self._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
2603 soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
2604 soffsetw = ista ? 0 : self.sizeDiff.width;
2606 var style = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },
2607 left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
2608 top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
2610 self.element.animate(
2611 $.extend(style, top && left ? { top: top, left: left } : {}), {
2612 duration: o.animateDuration,
2613 easing: o.animateEasing,
2617 width: parseInt(self.element.css('width'), 10),
2618 height: parseInt(self.element.css('height'), 10),
2619 top: parseInt(self.element.css('top'), 10),
2620 left: parseInt(self.element.css('left'), 10)
2623 if (pr && pr.length) $(pr[0]).css({ width: data.width, height: data.height });
2625 // propagating resize, and updating values for each animation step
2626 self._updateCache(data);
2627 self._propagate("resize", event);
2636 $.ui.plugin.add("resizable", "containment", {
2638 start: function(event, ui) {
2639 var self = $(this).data("resizable"), o = self.options, el = self.element;
2640 var oc = o.containment, ce = (oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc;
2643 self.containerElement = $(ce);
2645 if (/document/.test(oc) || oc == document) {
2646 self.containerOffset = { left: 0, top: 0 };
2647 self.containerPosition = { left: 0, top: 0 };
2650 element: $(document), left: 0, top: 0,
2651 width: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight
2655 // i'm a node, so compute top, left, right, bottom
2657 var element = $(ce), p = [];
2658 $([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) { p[i] = num(element.css("padding" + name)); });
2660 self.containerOffset = element.offset();
2661 self.containerPosition = element.position();
2662 self.containerSize = { height: (element.innerHeight() - p[3]), width: (element.innerWidth() - p[1]) };
2664 var co = self.containerOffset, ch = self.containerSize.height, cw = self.containerSize.width,
2665 width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw ), height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch);
2668 element: ce, left: co.left, top: co.top, width: width, height: height
2673 resize: function(event, ui) {
2674 var self = $(this).data("resizable"), o = self.options,
2675 ps = self.containerSize, co = self.containerOffset, cs = self.size, cp = self.position,
2676 pRatio = self._aspectRatio || event.shiftKey, cop = { top:0, left:0 }, ce = self.containerElement;
2678 if (ce[0] != document && (/static/).test(ce.css('position'))) cop = co;
2680 if (cp.left < (self._helper ? co.left : 0)) {
2681 self.size.width = self.size.width + (self._helper ? (self.position.left - co.left) : (self.position.left - cop.left));
2682 if (pRatio) self.size.height = self.size.width / o.aspectRatio;
2683 self.position.left = o.helper ? co.left : 0;
2686 if (cp.top < (self._helper ? co.top : 0)) {
2687 self.size.height = self.size.height + (self._helper ? (self.position.top - co.top) : self.position.top);
2688 if (pRatio) self.size.width = self.size.height * o.aspectRatio;
2689 self.position.top = self._helper ? co.top : 0;
2692 self.offset.left = self.parentData.left+self.position.left;
2693 self.offset.top = self.parentData.top+self.position.top;
2695 var woset = Math.abs( (self._helper ? self.offset.left - cop.left : (self.offset.left - cop.left)) + self.sizeDiff.width ),
2696 hoset = Math.abs( (self._helper ? self.offset.top - cop.top : (self.offset.top - co.top)) + self.sizeDiff.height );
2698 var isParent = self.containerElement.get(0) == self.element.parent().get(0),
2699 isOffsetRelative = /relative|absolute/.test(self.containerElement.css('position'));
2701 if(isParent && isOffsetRelative) woset -= self.parentData.left;
2703 if (woset + self.size.width >= self.parentData.width) {
2704 self.size.width = self.parentData.width - woset;
2705 if (pRatio) self.size.height = self.size.width / self.aspectRatio;
2708 if (hoset + self.size.height >= self.parentData.height) {
2709 self.size.height = self.parentData.height - hoset;
2710 if (pRatio) self.size.width = self.size.height * self.aspectRatio;
2714 stop: function(event, ui){
2715 var self = $(this).data("resizable"), o = self.options, cp = self.position,
2716 co = self.containerOffset, cop = self.containerPosition, ce = self.containerElement;
2718 var helper = $(self.helper), ho = helper.offset(), w = helper.outerWidth() - self.sizeDiff.width, h = helper.outerHeight() - self.sizeDiff.height;
2720 if (self._helper && !o.animate && (/relative/).test(ce.css('position')))
2721 $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
2723 if (self._helper && !o.animate && (/static/).test(ce.css('position')))
2724 $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
2729 $.ui.plugin.add("resizable", "ghost", {
2731 start: function(event, ui) {
2733 var self = $(this).data("resizable"), o = self.options, cs = self.size;
2735 self.ghost = self.originalElement.clone();
2737 .css({ opacity: .25, display: 'block', position: 'relative', height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 })
2738 .addClass('ui-resizable-ghost')
2739 .addClass(typeof o.ghost == 'string' ? o.ghost : '');
2741 self.ghost.appendTo(self.helper);
2745 resize: function(event, ui){
2746 var self = $(this).data("resizable"), o = self.options;
2747 if (self.ghost) self.ghost.css({ position: 'relative', height: self.size.height, width: self.size.width });
2750 stop: function(event, ui){
2751 var self = $(this).data("resizable"), o = self.options;
2752 if (self.ghost && self.helper) self.helper.get(0).removeChild(self.ghost.get(0));
2757 $.ui.plugin.add("resizable", "grid", {
2759 resize: function(event, ui) {
2760 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;
2761 o.grid = typeof o.grid == "number" ? [o.grid, o.grid] : o.grid;
2762 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);
2764 if (/^(se|s|e)$/.test(a)) {
2765 self.size.width = os.width + ox;
2766 self.size.height = os.height + oy;
2768 else if (/^(ne)$/.test(a)) {
2769 self.size.width = os.width + ox;
2770 self.size.height = os.height + oy;
2771 self.position.top = op.top - oy;
2773 else if (/^(sw)$/.test(a)) {
2774 self.size.width = os.width + ox;
2775 self.size.height = os.height + oy;
2776 self.position.left = op.left - ox;
2779 self.size.width = os.width + ox;
2780 self.size.height = os.height + oy;
2781 self.position.top = op.top - oy;
2782 self.position.left = op.left - ox;
2788 var num = function(v) {
2789 return parseInt(v, 10) || 0;
2792 var isNumber = function(value) {
2793 return !isNaN(parseInt(value, 10));
2798 * jQuery UI Selectable 1.8.4
2800 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
2801 * Dual licensed under the MIT or GPL Version 2 licenses.
2802 * http://jquery.org/license
2804 * http://docs.jquery.com/UI/Selectables
2808 * jquery.ui.mouse.js
2809 * jquery.ui.widget.js
2811 (function( $, undefined ) {
2813 $.widget("ui.selectable", $.ui.mouse, {
2821 _create: function() {
2824 this.element.addClass("ui-selectable");
2826 this.dragged = false;
2828 // cache selectee children based on filter
2830 this.refresh = function() {
2831 selectees = $(self.options.filter, self.element[0]);
2832 selectees.each(function() {
2833 var $this = $(this);
2834 var pos = $this.offset();
2835 $.data(this, "selectable-item", {
2840 right: pos.left + $this.outerWidth(),
2841 bottom: pos.top + $this.outerHeight(),
2842 startselected: false,
2843 selected: $this.hasClass('ui-selected'),
2844 selecting: $this.hasClass('ui-selecting'),
2845 unselecting: $this.hasClass('ui-unselecting')
2851 this.selectees = selectees.addClass("ui-selectee");
2855 this.helper = $("<div class='ui-selectable-helper'></div>");
2858 destroy: function() {
2860 .removeClass("ui-selectee")
2861 .removeData("selectable-item");
2863 .removeClass("ui-selectable ui-selectable-disabled")
2864 .removeData("selectable")
2865 .unbind(".selectable");
2866 this._mouseDestroy();
2871 _mouseStart: function(event) {
2874 this.opos = [event.pageX, event.pageY];
2876 if (this.options.disabled)
2879 var options = this.options;
2881 this.selectees = $(options.filter, this.element[0]);
2883 this._trigger("start", event);
2885 $(options.appendTo).append(this.helper);
2886 // position helper (lasso)
2888 "left": event.clientX,
2889 "top": event.clientY,
2894 if (options.autoRefresh) {
2898 this.selectees.filter('.ui-selected').each(function() {
2899 var selectee = $.data(this, "selectable-item");
2900 selectee.startselected = true;
2901 if (!event.metaKey) {
2902 selectee.$element.removeClass('ui-selected');
2903 selectee.selected = false;
2904 selectee.$element.addClass('ui-unselecting');
2905 selectee.unselecting = true;
2906 // selectable UNSELECTING callback
2907 self._trigger("unselecting", event, {
2908 unselecting: selectee.element
2913 $(event.target).parents().andSelf().each(function() {
2914 var selectee = $.data(this, "selectable-item");
2916 var doSelect = !event.metaKey || !selectee.$element.hasClass('ui-selected');
2918 .removeClass(doSelect ? "ui-unselecting" : "ui-selected")
2919 .addClass(doSelect ? "ui-selecting" : "ui-unselecting");
2920 selectee.unselecting = !doSelect;
2921 selectee.selecting = doSelect;
2922 selectee.selected = doSelect;
2923 // selectable (UN)SELECTING callback
2925 self._trigger("selecting", event, {
2926 selecting: selectee.element
2929 self._trigger("unselecting", event, {
2930 unselecting: selectee.element
2939 _mouseDrag: function(event) {
2941 this.dragged = true;
2943 if (this.options.disabled)
2946 var options = this.options;
2948 var x1 = this.opos[0], y1 = this.opos[1], x2 = event.pageX, y2 = event.pageY;
2949 if (x1 > x2) { var tmp = x2; x2 = x1; x1 = tmp; }
2950 if (y1 > y2) { var tmp = y2; y2 = y1; y1 = tmp; }
2951 this.helper.css({left: x1, top: y1, width: x2-x1, height: y2-y1});
2953 this.selectees.each(function() {
2954 var selectee = $.data(this, "selectable-item");
2955 //prevent helper from being selected if appendTo: selectable
2956 if (!selectee || selectee.element == self.element[0])
2959 if (options.tolerance == 'touch') {
2960 hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) );
2961 } else if (options.tolerance == 'fit') {
2962 hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2);
2967 if (selectee.selected) {
2968 selectee.$element.removeClass('ui-selected');
2969 selectee.selected = false;
2971 if (selectee.unselecting) {
2972 selectee.$element.removeClass('ui-unselecting');
2973 selectee.unselecting = false;
2975 if (!selectee.selecting) {
2976 selectee.$element.addClass('ui-selecting');
2977 selectee.selecting = true;
2978 // selectable SELECTING callback
2979 self._trigger("selecting", event, {
2980 selecting: selectee.element
2985 if (selectee.selecting) {
2986 if (event.metaKey && selectee.startselected) {
2987 selectee.$element.removeClass('ui-selecting');
2988 selectee.selecting = false;
2989 selectee.$element.addClass('ui-selected');
2990 selectee.selected = true;
2992 selectee.$element.removeClass('ui-selecting');
2993 selectee.selecting = false;
2994 if (selectee.startselected) {
2995 selectee.$element.addClass('ui-unselecting');
2996 selectee.unselecting = true;
2998 // selectable UNSELECTING callback
2999 self._trigger("unselecting", event, {
3000 unselecting: selectee.element
3004 if (selectee.selected) {
3005 if (!event.metaKey && !selectee.startselected) {
3006 selectee.$element.removeClass('ui-selected');
3007 selectee.selected = false;
3009 selectee.$element.addClass('ui-unselecting');
3010 selectee.unselecting = true;
3011 // selectable UNSELECTING callback
3012 self._trigger("unselecting", event, {
3013 unselecting: selectee.element
3023 _mouseStop: function(event) {
3026 this.dragged = false;
3028 var options = this.options;
3030 $('.ui-unselecting', this.element[0]).each(function() {
3031 var selectee = $.data(this, "selectable-item");
3032 selectee.$element.removeClass('ui-unselecting');
3033 selectee.unselecting = false;
3034 selectee.startselected = false;
3035 self._trigger("unselected", event, {
3036 unselected: selectee.element
3039 $('.ui-selecting', this.element[0]).each(function() {
3040 var selectee = $.data(this, "selectable-item");
3041 selectee.$element.removeClass('ui-selecting').addClass('ui-selected');
3042 selectee.selecting = false;
3043 selectee.selected = true;
3044 selectee.startselected = true;
3045 self._trigger("selected", event, {
3046 selected: selectee.element
3049 this._trigger("stop", event);
3051 this.helper.remove();
3058 $.extend($.ui.selectable, {
3064 * jQuery UI Sortable 1.8.4
3066 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
3067 * Dual licensed under the MIT or GPL Version 2 licenses.
3068 * http://jquery.org/license
3070 * http://docs.jquery.com/UI/Sortables
3074 * jquery.ui.mouse.js
3075 * jquery.ui.widget.js
3077 (function( $, undefined ) {
3079 $.widget("ui.sortable", $.ui.mouse, {
3080 widgetEventPrefix: "sort",
3089 forcePlaceholderSize: false,
3090 forceHelperSize: false,
3099 scrollSensitivity: 20,
3102 tolerance: "intersect",
3105 _create: function() {
3107 var o = this.options;
3108 this.containerCache = {};
3109 this.element.addClass("ui-sortable");
3114 //Let's determine if the items are floating
3115 this.floating = this.items.length ? (/left|right/).test(this.items[0].item.css('float')) : false;
3117 //Let's determine the parent's offset
3118 this.offset = this.element.offset();
3120 //Initialize mouse events for interaction
3125 destroy: function() {
3127 .removeClass("ui-sortable ui-sortable-disabled")
3128 .removeData("sortable")
3129 .unbind(".sortable");
3130 this._mouseDestroy();
3132 for ( var i = this.items.length - 1; i >= 0; i-- )
3133 this.items[i].item.removeData("sortable-item");
3138 _setOption: function(key, value){
3139 if ( key === "disabled" ) {
3140 this.options[ key ] = value;
3143 [ value ? "addClass" : "removeClass"]( "ui-sortable-disabled" );
3145 // Don't call widget base _setOption for disable as it adds ui-state-disabled class
3146 $.Widget.prototype._setOption.apply(this, arguments);
3150 _mouseCapture: function(event, overrideHandle) {
3152 if (this.reverting) {
3156 if(this.options.disabled || this.options.type == 'static') return false;
3158 //We have to refresh the items data once first
3159 this._refreshItems(event);
3161 //Find out if the clicked node (or one of its parents) is a actual item in this.items
3162 var currentItem = null, self = this, nodes = $(event.target).parents().each(function() {
3163 if($.data(this, 'sortable-item') == self) {
3164 currentItem = $(this);
3168 if($.data(event.target, 'sortable-item') == self) currentItem = $(event.target);
3170 if(!currentItem) return false;
3171 if(this.options.handle && !overrideHandle) {
3172 var validHandle = false;
3174 $(this.options.handle, currentItem).find("*").andSelf().each(function() { if(this == event.target) validHandle = true; });
3175 if(!validHandle) return false;
3178 this.currentItem = currentItem;
3179 this._removeCurrentsFromItems();
3184 _mouseStart: function(event, overrideHandle, noActivation) {
3186 var o = this.options, self = this;
3187 this.currentContainer = this;
3189 //We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture
3190 this.refreshPositions();
3192 //Create and append the visible helper
3193 this.helper = this._createHelper(event);
3195 //Cache the helper size
3196 this._cacheHelperProportions();
3199 * - Position generation -
3200 * This block generates everything position related - it's the core of draggables.
3203 //Cache the margins of the original element
3204 this._cacheMargins();
3206 //Get the next scrolling parent
3207 this.scrollParent = this.helper.scrollParent();
3209 //The element's absolute position on the page minus margins
3210 this.offset = this.currentItem.offset();
3212 top: this.offset.top - this.margins.top,
3213 left: this.offset.left - this.margins.left
3216 // Only after we got the offset, we can change the helper's position to absolute
3217 // TODO: Still need to figure out a way to make relative sorting possible
3218 this.helper.css("position", "absolute");
3219 this.cssPosition = this.helper.css("position");
3221 $.extend(this.offset, {
3222 click: { //Where the click happened, relative to the element
3223 left: event.pageX - this.offset.left,
3224 top: event.pageY - this.offset.top
3226 parent: this._getParentOffset(),
3227 relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
3230 //Generate the original position
3231 this.originalPosition = this._generatePosition(event);
3232 this.originalPageX = event.pageX;
3233 this.originalPageY = event.pageY;
3235 //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
3236 (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
3238 //Cache the former DOM position
3239 this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] };
3241 //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
3242 if(this.helper[0] != this.currentItem[0]) {
3243 this.currentItem.hide();
3246 //Create the placeholder
3247 this._createPlaceholder();
3249 //Set a containment if given in the options
3251 this._setContainment();
3253 if(o.cursor) { // cursor option
3254 if ($('body').css("cursor")) this._storedCursor = $('body').css("cursor");
3255 $('body').css("cursor", o.cursor);
3258 if(o.opacity) { // opacity option
3259 if (this.helper.css("opacity")) this._storedOpacity = this.helper.css("opacity");
3260 this.helper.css("opacity", o.opacity);
3263 if(o.zIndex) { // zIndex option
3264 if (this.helper.css("zIndex")) this._storedZIndex = this.helper.css("zIndex");
3265 this.helper.css("zIndex", o.zIndex);
3269 if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML')
3270 this.overflowOffset = this.scrollParent.offset();
3273 this._trigger("start", event, this._uiHash());
3275 //Recache the helper size
3276 if(!this._preserveHelperProportions)
3277 this._cacheHelperProportions();
3280 //Post 'activate' events to possible containers
3282 for (var i = this.containers.length - 1; i >= 0; i--) { this.containers[i]._trigger("activate", event, self._uiHash(this)); }
3285 //Prepare possible droppables
3287 $.ui.ddmanager.current = this;
3289 if ($.ui.ddmanager && !o.dropBehaviour)
3290 $.ui.ddmanager.prepareOffsets(this, event);
3292 this.dragging = true;
3294 this.helper.addClass("ui-sortable-helper");
3295 this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position
3300 _mouseDrag: function(event) {
3302 //Compute the helpers position
3303 this.position = this._generatePosition(event);
3304 this.positionAbs = this._convertPositionTo("absolute");
3306 if (!this.lastPositionAbs) {
3307 this.lastPositionAbs = this.positionAbs;
3311 if(this.options.scroll) {
3312 var o = this.options, scrolled = false;
3313 if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') {
3315 if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
3316 this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed;
3317 else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity)
3318 this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed;
3320 if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
3321 this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed;
3322 else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity)
3323 this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed;
3327 if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
3328 scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
3329 else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
3330 scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
3332 if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
3333 scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
3334 else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
3335 scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
3339 if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
3340 $.ui.ddmanager.prepareOffsets(this, event);
3343 //Regenerate the absolute position used for position checks
3344 this.positionAbs = this._convertPositionTo("absolute");
3346 //Set the helper position
3347 if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
3348 if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
3351 for (var i = this.items.length - 1; i >= 0; i--) {
3353 //Cache variables and intersection, continue if no intersection
3354 var item = this.items[i], itemElement = item.item[0], intersection = this._intersectsWithPointer(item);
3355 if (!intersection) continue;
3357 if(itemElement != this.currentItem[0] //cannot intersect with itself
3358 && this.placeholder[intersection == 1 ? "next" : "prev"]()[0] != itemElement //no useless actions that have been done before
3359 && !$.ui.contains(this.placeholder[0], itemElement) //no action if the item moved is the parent of the item checked
3360 && (this.options.type == 'semi-dynamic' ? !$.ui.contains(this.element[0], itemElement) : true)
3361 //&& itemElement.parentNode == this.placeholder[0].parentNode // only rearrange items within the same container
3364 this.direction = intersection == 1 ? "down" : "up";
3366 if (this.options.tolerance == "pointer" || this._intersectsWithSides(item)) {
3367 this._rearrange(event, item);
3372 this._trigger("change", event, this._uiHash());
3377 //Post events to containers
3378 this._contactContainers(event);
3380 //Interconnect with droppables
3381 if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
3384 this._trigger('sort', event, this._uiHash());
3386 this.lastPositionAbs = this.positionAbs;
3391 _mouseStop: function(event, noPropagation) {
3395 //If we are using droppables, inform the manager about the drop
3396 if ($.ui.ddmanager && !this.options.dropBehaviour)
3397 $.ui.ddmanager.drop(this, event);
3399 if(this.options.revert) {
3401 var cur = self.placeholder.offset();
3403 self.reverting = true;
3405 $(this.helper).animate({
3406 left: cur.left - this.offset.parent.left - self.margins.left + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollLeft),
3407 top: cur.top - this.offset.parent.top - self.margins.top + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollTop)
3408 }, parseInt(this.options.revert, 10) || 500, function() {
3412 this._clear(event, noPropagation);
3419 cancel: function() {
3427 if(this.options.helper == "original")
3428 this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
3430 this.currentItem.show();
3432 //Post deactivating events to containers
3433 for (var i = this.containers.length - 1; i >= 0; i--){
3434 this.containers[i]._trigger("deactivate", null, self._uiHash(this));
3435 if(this.containers[i].containerCache.over) {
3436 this.containers[i]._trigger("out", null, self._uiHash(this));
3437 this.containers[i].containerCache.over = 0;
3443 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
3444 if(this.placeholder[0].parentNode) this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
3445 if(this.options.helper != "original" && this.helper && this.helper[0].parentNode) this.helper.remove();
3454 if(this.domPosition.prev) {
3455 $(this.domPosition.prev).after(this.currentItem);
3457 $(this.domPosition.parent).prepend(this.currentItem);
3464 serialize: function(o) {
3466 var items = this._getItemsAsjQuery(o && o.connected);
3467 var str = []; o = o || {};
3469 $(items).each(function() {
3470 var res = ($(o.item || this).attr(o.attribute || 'id') || '').match(o.expression || (/(.+)[-=_](.+)/));
3471 if(res) str.push((o.key || res[1]+'[]')+'='+(o.key && o.expression ? res[1] : res[2]));
3474 if(!str.length && o.key) {
3475 str.push(o.key + '=');
3478 return str.join('&');
3482 toArray: function(o) {
3484 var items = this._getItemsAsjQuery(o && o.connected);
3485 var ret = []; o = o || {};
3487 items.each(function() { ret.push($(o.item || this).attr(o.attribute || 'id') || ''); });
3492 /* Be careful with the following core functions */
3493 _intersectsWith: function(item) {
3495 var x1 = this.positionAbs.left,
3496 x2 = x1 + this.helperProportions.width,
3497 y1 = this.positionAbs.top,
3498 y2 = y1 + this.helperProportions.height;
3503 b = t + item.height;
3505 var dyClick = this.offset.click.top,
3506 dxClick = this.offset.click.left;
3508 var isOverElement = (y1 + dyClick) > t && (y1 + dyClick) < b && (x1 + dxClick) > l && (x1 + dxClick) < r;
3510 if( this.options.tolerance == "pointer"
3511 || this.options.forcePointerForContainers
3512 || (this.options.tolerance != "pointer" && this.helperProportions[this.floating ? 'width' : 'height'] > item[this.floating ? 'width' : 'height'])
3514 return isOverElement;
3517 return (l < x1 + (this.helperProportions.width / 2) // Right Half
3518 && x2 - (this.helperProportions.width / 2) < r // Left Half
3519 && t < y1 + (this.helperProportions.height / 2) // Bottom Half
3520 && y2 - (this.helperProportions.height / 2) < b ); // Top Half
3525 _intersectsWithPointer: function(item) {
3527 var isOverElementHeight = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height),
3528 isOverElementWidth = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width),
3529 isOverElement = isOverElementHeight && isOverElementWidth,
3530 verticalDirection = this._getDragVerticalDirection(),
3531 horizontalDirection = this._getDragHorizontalDirection();
3536 return this.floating ?
3537 ( ((horizontalDirection && horizontalDirection == "right") || verticalDirection == "down") ? 2 : 1 )
3538 : ( verticalDirection && (verticalDirection == "down" ? 2 : 1) );
3542 _intersectsWithSides: function(item) {
3544 var isOverBottomHalf = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height),
3545 isOverRightHalf = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width),
3546 verticalDirection = this._getDragVerticalDirection(),
3547 horizontalDirection = this._getDragHorizontalDirection();
3549 if (this.floating && horizontalDirection) {
3550 return ((horizontalDirection == "right" && isOverRightHalf) || (horizontalDirection == "left" && !isOverRightHalf));
3552 return verticalDirection && ((verticalDirection == "down" && isOverBottomHalf) || (verticalDirection == "up" && !isOverBottomHalf));
3557 _getDragVerticalDirection: function() {
3558 var delta = this.positionAbs.top - this.lastPositionAbs.top;
3559 return delta != 0 && (delta > 0 ? "down" : "up");
3562 _getDragHorizontalDirection: function() {
3563 var delta = this.positionAbs.left - this.lastPositionAbs.left;
3564 return delta != 0 && (delta > 0 ? "right" : "left");
3567 refresh: function(event) {
3568 this._refreshItems(event);
3569 this.refreshPositions();
3573 _connectWith: function() {
3574 var options = this.options;
3575 return options.connectWith.constructor == String
3576 ? [options.connectWith]
3577 : options.connectWith;
3580 _getItemsAsjQuery: function(connected) {
3585 var connectWith = this._connectWith();
3587 if(connectWith && connected) {
3588 for (var i = connectWith.length - 1; i >= 0; i--){
3589 var cur = $(connectWith[i]);
3590 for (var j = cur.length - 1; j >= 0; j--){
3591 var inst = $.data(cur[j], 'sortable');
3592 if(inst && inst != this && !inst.options.disabled) {
3593 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]);
3599 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]);
3601 for (var i = queries.length - 1; i >= 0; i--){
3602 queries[i][0].each(function() {
3611 _removeCurrentsFromItems: function() {
3613 var list = this.currentItem.find(":data(sortable-item)");
3615 for (var i=0; i < this.items.length; i++) {
3617 for (var j=0; j < list.length; j++) {
3618 if(list[j] == this.items[i].item[0])
3619 this.items.splice(i,1);
3626 _refreshItems: function(event) {
3629 this.containers = [this];
3630 var items = this.items;
3632 var queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]];
3633 var connectWith = this._connectWith();
3636 for (var i = connectWith.length - 1; i >= 0; i--){
3637 var cur = $(connectWith[i]);
3638 for (var j = cur.length - 1; j >= 0; j--){
3639 var inst = $.data(cur[j], 'sortable');
3640 if(inst && inst != this && !inst.options.disabled) {
3641 queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]);
3642 this.containers.push(inst);
3648 for (var i = queries.length - 1; i >= 0; i--) {
3649 var targetData = queries[i][1];
3650 var _queries = queries[i][0];
3652 for (var j=0, queriesLength = _queries.length; j < queriesLength; j++) {
3653 var item = $(_queries[j]);
3655 item.data('sortable-item', targetData); // Data for target checking (mouse manager)
3659 instance: targetData,
3660 width: 0, height: 0,
3668 refreshPositions: function(fast) {
3670 //This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change
3671 if(this.offsetParent && this.helper) {
3672 this.offset.parent = this._getParentOffset();
3675 for (var i = this.items.length - 1; i >= 0; i--){
3676 var item = this.items[i];
3678 var t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item;
3681 item.width = t.outerWidth();
3682 item.height = t.outerHeight();
3690 if(this.options.custom && this.options.custom.refreshContainers) {
3691 this.options.custom.refreshContainers.call(this);
3693 for (var i = this.containers.length - 1; i >= 0; i--){
3694 var p = this.containers[i].element.offset();
3695 this.containers[i].containerCache.left = p.left;
3696 this.containers[i].containerCache.top = p.top;
3697 this.containers[i].containerCache.width = this.containers[i].element.outerWidth();
3698 this.containers[i].containerCache.height = this.containers[i].element.outerHeight();
3705 _createPlaceholder: function(that) {
3707 var self = that || this, o = self.options;
3709 if(!o.placeholder || o.placeholder.constructor == String) {
3710 var className = o.placeholder;
3712 element: function() {
3714 var el = $(document.createElement(self.currentItem[0].nodeName))
3715 .addClass(className || self.currentItem[0].className+" ui-sortable-placeholder")
3716 .removeClass("ui-sortable-helper")[0];
3719 el.style.visibility = "hidden";
3723 update: function(container, p) {
3725 // 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that
3726 // 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified
3727 if(className && !o.forcePlaceholderSize) return;
3729 //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
3730 if(!p.height()) { p.height(self.currentItem.innerHeight() - parseInt(self.currentItem.css('paddingTop')||0, 10) - parseInt(self.currentItem.css('paddingBottom')||0, 10)); };
3731 if(!p.width()) { p.width(self.currentItem.innerWidth() - parseInt(self.currentItem.css('paddingLeft')||0, 10) - parseInt(self.currentItem.css('paddingRight')||0, 10)); };
3736 //Create the placeholder
3737 self.placeholder = $(o.placeholder.element.call(self.element, self.currentItem));
3739 //Append it after the actual current item
3740 self.currentItem.after(self.placeholder);
3742 //Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
3743 o.placeholder.update(self, self.placeholder);
3747 _contactContainers: function(event) {
3749 // get innermost container that intersects with item
3750 var innermostContainer = null, innermostIndex = null;
3753 for (var i = this.containers.length - 1; i >= 0; i--){
3755 // never consider a container that's located within the item itself
3756 if($.ui.contains(this.currentItem[0], this.containers[i].element[0]))
3759 if(this._intersectsWith(this.containers[i].containerCache)) {
3761 // if we've already found a container and it's more "inner" than this, then continue
3762 if(innermostContainer && $.ui.contains(this.containers[i].element[0], innermostContainer.element[0]))
3765 innermostContainer = this.containers[i];
3769 // container doesn't intersect. trigger "out" event if necessary
3770 if(this.containers[i].containerCache.over) {
3771 this.containers[i]._trigger("out", event, this._uiHash(this));
3772 this.containers[i].containerCache.over = 0;
3778 // if no intersecting containers found, return
3779 if(!innermostContainer) return;
3781 // move the item into the container if it's not there already
3782 if(this.containers.length === 1) {
3783 this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
3784 this.containers[innermostIndex].containerCache.over = 1;
3785 } else if(this.currentContainer != this.containers[innermostIndex]) {
3787 //When entering a new container, we will find the item with the least distance and append our item near it
3788 var dist = 10000; var itemWithLeastDistance = null; var base = this.positionAbs[this.containers[innermostIndex].floating ? 'left' : 'top'];
3789 for (var j = this.items.length - 1; j >= 0; j--) {
3790 if(!$.ui.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) continue;
3791 var cur = this.items[j][this.containers[innermostIndex].floating ? 'left' : 'top'];
3792 if(Math.abs(cur - base) < dist) {
3793 dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j];
3797 if(!itemWithLeastDistance && !this.options.dropOnEmpty) //Check if dropOnEmpty is enabled
3800 this.currentContainer = this.containers[innermostIndex];
3801 itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true);
3802 this._trigger("change", event, this._uiHash());
3803 this.containers[innermostIndex]._trigger("change", event, this._uiHash(this));
3805 //Update the placeholder
3806 this.options.placeholder.update(this.currentContainer, this.placeholder);
3808 this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
3809 this.containers[innermostIndex].containerCache.over = 1;
3815 _createHelper: function(event) {
3817 var o = this.options;
3818 var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper == 'clone' ? this.currentItem.clone() : this.currentItem);
3820 if(!helper.parents('body').length) //Add the helper to the DOM if that didn't happen already
3821 $(o.appendTo != 'parent' ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]);
3823 if(helper[0] == this.currentItem[0])
3824 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") };
3826 if(helper[0].style.width == '' || o.forceHelperSize) helper.width(this.currentItem.width());
3827 if(helper[0].style.height == '' || o.forceHelperSize) helper.height(this.currentItem.height());
3833 _adjustOffsetFromHelper: function(obj) {
3834 if (typeof obj == 'string') {
3835 obj = obj.split(' ');
3837 if ($.isArray(obj)) {
3838 obj = {left: +obj[0], top: +obj[1] || 0};
3840 if ('left' in obj) {
3841 this.offset.click.left = obj.left + this.margins.left;
3843 if ('right' in obj) {
3844 this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
3847 this.offset.click.top = obj.top + this.margins.top;
3849 if ('bottom' in obj) {
3850 this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
3854 _getParentOffset: function() {
3857 //Get the offsetParent and cache its position
3858 this.offsetParent = this.helper.offsetParent();
3859 var po = this.offsetParent.offset();
3861 // This is a special case where we need to modify a offset calculated on start, since the following happened:
3862 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
3863 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
3864 // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
3865 if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) {
3866 po.left += this.scrollParent.scrollLeft();
3867 po.top += this.scrollParent.scrollTop();
3870 if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
3871 || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix
3872 po = { top: 0, left: 0 };
3875 top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
3876 left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
3881 _getRelativeOffset: function() {
3883 if(this.cssPosition == "relative") {
3884 var p = this.currentItem.position();
3886 top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
3887 left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
3890 return { top: 0, left: 0 };
3895 _cacheMargins: function() {
3897 left: (parseInt(this.currentItem.css("marginLeft"),10) || 0),
3898 top: (parseInt(this.currentItem.css("marginTop"),10) || 0)
3902 _cacheHelperProportions: function() {
3903 this.helperProportions = {
3904 width: this.helper.outerWidth(),
3905 height: this.helper.outerHeight()
3909 _setContainment: function() {
3911 var o = this.options;
3912 if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
3913 if(o.containment == 'document' || o.containment == 'window') this.containment = [
3914 0 - this.offset.relative.left - this.offset.parent.left,
3915 0 - this.offset.relative.top - this.offset.parent.top,
3916 $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
3917 ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
3920 if(!(/^(document|window|parent)$/).test(o.containment)) {
3921 var ce = $(o.containment)[0];
3922 var co = $(o.containment).offset();
3923 var over = ($(ce).css("overflow") != 'hidden');
3925 this.containment = [
3926 co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
3927 co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
3928 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,
3929 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
3935 _convertPositionTo: function(d, pos) {
3937 if(!pos) pos = this.position;
3938 var mod = d == "absolute" ? 1 : -1;
3939 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);
3943 pos.top // The absolute mouse position
3944 + this.offset.relative.top * mod // Only for relative positioned nodes: Relative offset from element to offset parent
3945 + this.offset.parent.top * mod // The offsetParent's offset without borders (offset + border)
3946 - ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
3949 pos.left // The absolute mouse position
3950 + this.offset.relative.left * mod // Only for relative positioned nodes: Relative offset from element to offset parent
3951 + this.offset.parent.left * mod // The offsetParent's offset without borders (offset + border)
3952 - ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
3958 _generatePosition: function(event) {
3960 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);
3962 // This is another very weird special case that only happens for relative elements:
3963 // 1. If the css position is relative
3964 // 2. and the scroll parent is the document or similar to the offset parent
3965 // we have to refresh the relative offset during the scroll so there are no jumps
3966 if(this.cssPosition == 'relative' && !(this.scrollParent[0] != document && this.scrollParent[0] != this.offsetParent[0])) {
3967 this.offset.relative = this._getRelativeOffset();
3970 var pageX = event.pageX;
3971 var pageY = event.pageY;
3974 * - Position constraining -
3975 * Constrain the position to a mix of grid, containment.
3978 if(this.originalPosition) { //If we are not dragging yet, we won't check for options
3980 if(this.containment) {
3981 if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left;
3982 if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top;
3983 if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left;
3984 if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top;
3988 var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
3989 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;
3991 var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
3992 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;
3999 pageY // The absolute mouse position
4000 - this.offset.click.top // Click offset (relative to the element)
4001 - this.offset.relative.top // Only for relative positioned nodes: Relative offset from element to offset parent
4002 - this.offset.parent.top // The offsetParent's offset without borders (offset + border)
4003 + ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
4006 pageX // The absolute mouse position
4007 - this.offset.click.left // Click offset (relative to the element)
4008 - this.offset.relative.left // Only for relative positioned nodes: Relative offset from element to offset parent
4009 - this.offset.parent.left // The offsetParent's offset without borders (offset + border)
4010 + ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
4016 _rearrange: function(event, i, a, hardRefresh) {
4018 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));
4020 //Various things done here to improve the performance:
4021 // 1. we create a setTimeout, that calls refreshPositions
4022 // 2. on the instance, we have a counter variable, that get's higher after every append
4023 // 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same
4024 // 4. this lets only the last addition to the timeout stack through
4025 this.counter = this.counter ? ++this.counter : 1;
4026 var self = this, counter = this.counter;
4028 window.setTimeout(function() {
4029 if(counter == self.counter) self.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove
4034 _clear: function(event, noPropagation) {
4036 this.reverting = false;
4037 // We delay all events that have to be triggered to after the point where the placeholder has been removed and
4038 // everything else normalized again
4039 var delayedTriggers = [], self = this;
4041 // We first have to update the dom position of the actual currentItem
4042 // Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088)
4043 if(!this._noFinalSort && this.currentItem[0].parentNode) this.placeholder.before(this.currentItem);
4044 this._noFinalSort = null;
4046 if(this.helper[0] == this.currentItem[0]) {
4047 for(var i in this._storedCSS) {
4048 if(this._storedCSS[i] == 'auto' || this._storedCSS[i] == 'static') this._storedCSS[i] = '';
4050 this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
4052 this.currentItem.show();
4055 if(this.fromOutside && !noPropagation) delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); });
4056 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
4057 if(!$.ui.contains(this.element[0], this.currentItem[0])) { //Node was moved out of the current element
4058 if(!noPropagation) delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); });
4059 for (var i = this.containers.length - 1; i >= 0; i--){
4060 if($.ui.contains(this.containers[i].element[0], this.currentItem[0]) && !noPropagation) {
4061 delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); }; }).call(this, this.containers[i]));
4062 delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this)); }; }).call(this, this.containers[i]));
4067 //Post events to containers
4068 for (var i = this.containers.length - 1; i >= 0; i--){
4069 if(!noPropagation) delayedTriggers.push((function(c) { return function(event) { c._trigger("deactivate", event, this._uiHash(this)); }; }).call(this, this.containers[i]));
4070 if(this.containers[i].containerCache.over) {
4071 delayedTriggers.push((function(c) { return function(event) { c._trigger("out", event, this._uiHash(this)); }; }).call(this, this.containers[i]));
4072 this.containers[i].containerCache.over = 0;
4076 //Do what was originally in plugins
4077 if(this._storedCursor) $('body').css("cursor", this._storedCursor); //Reset cursor
4078 if(this._storedOpacity) this.helper.css("opacity", this._storedOpacity); //Reset opacity
4079 if(this._storedZIndex) this.helper.css("zIndex", this._storedZIndex == 'auto' ? '' : this._storedZIndex); //Reset z-index
4081 this.dragging = false;
4082 if(this.cancelHelperRemoval) {
4083 if(!noPropagation) {
4084 this._trigger("beforeStop", event, this._uiHash());
4085 for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events
4086 this._trigger("stop", event, this._uiHash());
4091 if(!noPropagation) this._trigger("beforeStop", event, this._uiHash());
4093 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
4094 this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
4096 if(this.helper[0] != this.currentItem[0]) this.helper.remove(); this.helper = null;
4098 if(!noPropagation) {
4099 for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events
4100 this._trigger("stop", event, this._uiHash());
4103 this.fromOutside = false;
4108 _trigger: function() {
4109 if ($.Widget.prototype._trigger.apply(this, arguments) === false) {
4114 _uiHash: function(inst) {
4115 var self = inst || this;
4117 helper: self.helper,
4118 placeholder: self.placeholder || $([]),
4119 position: self.position,
4120 originalPosition: self.originalPosition,
4121 offset: self.positionAbs,
4122 item: self.currentItem,
4123 sender: inst ? inst.element : null
4129 $.extend($.ui.sortable, {
4135 * jQuery UI Accordion 1.8.4
4137 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
4138 * Dual licensed under the MIT or GPL Version 2 licenses.
4139 * http://jquery.org/license
4141 * http://docs.jquery.com/UI/Accordion
4145 * jquery.ui.widget.js
4147 (function( $, undefined ) {
4149 $.widget( "ui.accordion", {
4158 header: "> li > :first-child,> :not(li):even",
4160 header: "ui-icon-triangle-1-e",
4161 headerSelected: "ui-icon-triangle-1-s"
4164 navigationFilter: function() {
4165 return this.href.toLowerCase() === location.href.toLowerCase();
4169 _create: function() {
4171 options = self.options;
4176 .addClass( "ui-accordion ui-widget ui-helper-reset" )
4177 // in lack of child-selectors in CSS
4178 // we need to mark top-LIs in a UL-accordion for some IE-fix
4180 .addClass( "ui-accordion-li-fix" );
4182 self.headers = self.element.find( options.header )
4183 .addClass( "ui-accordion-header ui-helper-reset ui-state-default ui-corner-all" )
4184 .bind( "mouseenter.accordion", function() {
4185 if ( options.disabled ) {
4188 $( this ).addClass( "ui-state-hover" );
4190 .bind( "mouseleave.accordion", function() {
4191 if ( options.disabled ) {
4194 $( this ).removeClass( "ui-state-hover" );
4196 .bind( "focus.accordion", function() {
4197 if ( options.disabled ) {
4200 $( this ).addClass( "ui-state-focus" );
4202 .bind( "blur.accordion", function() {
4203 if ( options.disabled ) {
4206 $( this ).removeClass( "ui-state-focus" );
4210 .addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" );
4212 if ( options.navigation ) {
4213 var current = self.element.find( "a" ).filter( options.navigationFilter ).eq( 0 );
4214 if ( current.length ) {
4215 var header = current.closest( ".ui-accordion-header" );
4216 if ( header.length ) {
4217 // anchor within header
4218 self.active = header;
4220 // anchor within content
4221 self.active = current.closest( ".ui-accordion-content" ).prev();
4226 self.active = self._findActive( self.active || options.active )
4227 .addClass( "ui-state-default ui-state-active" )
4228 .toggleClass( "ui-corner-all ui-corner-top" );
4229 self.active.next().addClass( "ui-accordion-content-active" );
4231 self._createIcons();
4235 self.element.attr( "role", "tablist" );
4238 .attr( "role", "tab" )
4239 .bind( "keydown.accordion", function( event ) {
4240 return self._keydown( event );
4243 .attr( "role", "tabpanel" );
4246 .not( self.active || "" )
4248 "aria-expanded": "false",
4254 // make sure at least one header is in the tab order
4255 if ( !self.active.length ) {
4256 self.headers.eq( 0 ).attr( "tabIndex", 0 );
4260 "aria-expanded": "true",
4265 // only need links in tab order for Safari
4266 if ( !$.browser.safari ) {
4267 self.headers.find( "a" ).attr( "tabIndex", -1 );
4270 if ( options.event ) {
4271 self.headers.bind( options.event.split(" ").join(".accordion ") + ".accordion", function(event) {
4272 self._clickHandler.call( self, event, this );
4273 event.preventDefault();
4278 _createIcons: function() {
4279 var options = this.options;
4280 if ( options.icons ) {
4281 $( "<span></span>" )
4282 .addClass( "ui-icon " + options.icons.header )
4283 .prependTo( this.headers );
4284 this.active.children( ".ui-icon" )
4285 .toggleClass(options.icons.header)
4286 .toggleClass(options.icons.headerSelected);
4287 this.element.addClass( "ui-accordion-icons" );
4291 _destroyIcons: function() {
4292 this.headers.children( ".ui-icon" ).remove();
4293 this.element.removeClass( "ui-accordion-icons" );
4296 destroy: function() {
4297 var options = this.options;
4300 .removeClass( "ui-accordion ui-widget ui-helper-reset" )
4301 .removeAttr( "role" );
4304 .unbind( ".accordion" )
4305 .removeClass( "ui-accordion-header ui-accordion-disabled ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top" )
4306 .removeAttr( "role" )
4307 .removeAttr( "aria-expanded" )
4308 .removeAttr( "tabIndex" );
4310 this.headers.find( "a" ).removeAttr( "tabIndex" );
4311 this._destroyIcons();
4312 var contents = this.headers.next()
4313 .css( "display", "" )
4314 .removeAttr( "role" )
4315 .removeClass( "ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-accordion-disabled ui-state-disabled" );
4316 if ( options.autoHeight || options.fillHeight ) {
4317 contents.css( "height", "" );
4320 return $.Widget.prototype.destroy.call( this );
4323 _setOption: function( key, value ) {
4324 $.Widget.prototype._setOption.apply( this, arguments );
4326 if ( key == "active" ) {
4327 this.activate( value );
4329 if ( key == "icons" ) {
4330 this._destroyIcons();
4332 this._createIcons();
4335 // #5332 - opacity doesn't cascade to positioned elements in IE
4336 // so we need to add the disabled class to the headers and panels
4337 if ( key == "disabled" ) {
4338 this.headers.add(this.headers.next())
4339 [ value ? "addClass" : "removeClass" ](
4340 "ui-accordion-disabled ui-state-disabled" );
4344 _keydown: function( event ) {
4345 if ( this.options.disabled || event.altKey || event.ctrlKey ) {
4349 var keyCode = $.ui.keyCode,
4350 length = this.headers.length,
4351 currentIndex = this.headers.index( event.target ),
4354 switch ( event.keyCode ) {
4357 toFocus = this.headers[ ( currentIndex + 1 ) % length ];
4361 toFocus = this.headers[ ( currentIndex - 1 + length ) % length ];
4365 this._clickHandler( { target: event.target }, event.target );
4366 event.preventDefault();
4370 $( event.target ).attr( "tabIndex", -1 );
4371 $( toFocus ).attr( "tabIndex", 0 );
4379 resize: function() {
4380 var options = this.options,
4383 if ( options.fillSpace ) {
4384 if ( $.browser.msie ) {
4385 var defOverflow = this.element.parent().css( "overflow" );
4386 this.element.parent().css( "overflow", "hidden");
4388 maxHeight = this.element.parent().height();
4389 if ($.browser.msie) {
4390 this.element.parent().css( "overflow", defOverflow );
4393 this.headers.each(function() {
4394 maxHeight -= $( this ).outerHeight( true );
4399 $( this ).height( Math.max( 0, maxHeight -
4400 $( this ).innerHeight() + $( this ).height() ) );
4402 .css( "overflow", "auto" );
4403 } else if ( options.autoHeight ) {
4407 maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() );
4409 .height( maxHeight );
4415 activate: function( index ) {
4416 // TODO this gets called on init, changing the option without an explicit call for that
4417 this.options.active = index;
4418 // call clickHandler with custom event
4419 var active = this._findActive( index )[ 0 ];
4420 this._clickHandler( { target: active }, active );
4425 _findActive: function( selector ) {
4427 ? typeof selector === "number"
4428 ? this.headers.filter( ":eq(" + selector + ")" )
4429 : this.headers.not( this.headers.not( selector ) )
4430 : selector === false
4432 : this.headers.filter( ":eq(0)" );
4435 // TODO isn't event.target enough? why the separate target argument?
4436 _clickHandler: function( event, target ) {
4437 var options = this.options;
4438 if ( options.disabled ) {
4442 // called only when using activate(false) to close all parts programmatically
4443 if ( !event.target ) {
4444 if ( !options.collapsible ) {
4448 .removeClass( "ui-state-active ui-corner-top" )
4449 .addClass( "ui-state-default ui-corner-all" )
4450 .children( ".ui-icon" )
4451 .removeClass( options.icons.headerSelected )
4452 .addClass( options.icons.header );
4453 this.active.next().addClass( "ui-accordion-content-active" );
4454 var toHide = this.active.next(),
4458 oldHeader: options.active,
4459 newContent: $( [] ),
4462 toShow = ( this.active = $( [] ) );
4463 this._toggle( toShow, toHide, data );
4467 // get the click target
4468 var clicked = $( event.currentTarget || target ),
4469 clickedIsActive = clicked[0] === this.active[0];
4471 // TODO the option is changed, is that correct?
4472 // TODO if it is correct, shouldn't that happen after determining that the click is valid?
4473 options.active = options.collapsible && clickedIsActive ?
4475 this.headers.index( clicked );
4477 // if animations are still active, or the active header is the target, ignore click
4478 if ( this.running || ( !options.collapsible && clickedIsActive ) ) {
4484 .removeClass( "ui-state-active ui-corner-top" )
4485 .addClass( "ui-state-default ui-corner-all" )
4486 .children( ".ui-icon" )
4487 .removeClass( options.icons.headerSelected )
4488 .addClass( options.icons.header );
4489 if ( !clickedIsActive ) {
4491 .removeClass( "ui-state-default ui-corner-all" )
4492 .addClass( "ui-state-active ui-corner-top" )
4493 .children( ".ui-icon" )
4494 .removeClass( options.icons.header )
4495 .addClass( options.icons.headerSelected );
4498 .addClass( "ui-accordion-content-active" );
4501 // find elements to show and hide
4502 var toShow = clicked.next(),
4503 toHide = this.active.next(),
4506 newHeader: clickedIsActive && options.collapsible ? $([]) : clicked,
4507 oldHeader: this.active,
4508 newContent: clickedIsActive && options.collapsible ? $([]) : toShow,
4511 down = this.headers.index( this.active[0] ) > this.headers.index( clicked[0] );
4513 this.active = clickedIsActive ? $([]) : clicked;
4514 this._toggle( toShow, toHide, data, clickedIsActive, down );
4519 _toggle: function( toShow, toHide, data, clickedIsActive, down ) {
4521 options = self.options;
4523 self.toShow = toShow;
4524 self.toHide = toHide;
4527 var complete = function() {
4531 return self._completed.apply( self, arguments );
4534 // trigger changestart event
4535 self._trigger( "changestart", null, self.data );
4537 // count elements to animate
4538 self.running = toHide.size() === 0 ? toShow.size() : toHide.size();
4540 if ( options.animated ) {
4541 var animOptions = {};
4543 if ( options.collapsible && clickedIsActive ) {
4549 autoHeight: options.autoHeight || options.fillSpace
4557 autoHeight: options.autoHeight || options.fillSpace
4561 if ( !options.proxied ) {
4562 options.proxied = options.animated;
4565 if ( !options.proxiedDuration ) {
4566 options.proxiedDuration = options.duration;
4569 options.animated = $.isFunction( options.proxied ) ?
4570 options.proxied( animOptions ) :
4573 options.duration = $.isFunction( options.proxiedDuration ) ?
4574 options.proxiedDuration( animOptions ) :
4575 options.proxiedDuration;
4577 var animations = $.ui.accordion.animations,
4578 duration = options.duration,
4579 easing = options.animated;
4581 if ( easing && !animations[ easing ] && !$.easing[ easing ] ) {
4584 if ( !animations[ easing ] ) {
4585 animations[ easing ] = function( options ) {
4586 this.slide( options, {
4588 duration: duration || 700
4593 animations[ easing ]( animOptions );
4595 if ( options.collapsible && clickedIsActive ) {
4605 // TODO assert that the blur and focus triggers are really necessary, remove otherwise
4608 "aria-expanded": "false",
4614 "aria-expanded": "true",
4620 _completed: function( cancel ) {
4621 this.running = cancel ? 0 : --this.running;
4622 if ( this.running ) {
4626 if ( this.options.clearStyle ) {
4627 this.toShow.add( this.toHide ).css({
4633 // other classes are removed before the animation; this one needs to stay until completed
4634 this.toHide.removeClass( "ui-accordion-content-active" );
4636 this._trigger( "change", null, this.data );
4640 $.extend( $.ui.accordion, {
4643 slide: function( options, additions ) {
4644 options = $.extend({
4647 }, options, additions );
4648 if ( !options.toHide.size() ) {
4649 options.toShow.animate({
4652 paddingBottom: "show"
4656 if ( !options.toShow.size() ) {
4657 options.toHide.animate({
4660 paddingBottom: "hide"
4664 var overflow = options.toShow.css( "overflow" ),
4668 fxAttrs = [ "height", "paddingTop", "paddingBottom" ],
4670 // fix width before calculating height of hidden element
4671 var s = options.toShow;
4672 originalWidth = s[0].style.width;
4673 s.width( parseInt( s.parent().width(), 10 )
4674 - parseInt( s.css( "paddingLeft" ), 10 )
4675 - parseInt( s.css( "paddingRight" ), 10 )
4676 - ( parseInt( s.css( "borderLeftWidth" ), 10 ) || 0 )
4677 - ( parseInt( s.css( "borderRightWidth" ), 10) || 0 ) );
4679 $.each( fxAttrs, function( i, prop ) {
4680 hideProps[ prop ] = "hide";
4682 var parts = ( "" + $.css( options.toShow[0], prop ) ).match( /^([\d+-.]+)(.*)$/ );
4683 showProps[ prop ] = {
4685 unit: parts[ 2 ] || "px"
4688 options.toShow.css({ height: 0, overflow: "hidden" }).show();
4690 .filter( ":hidden" )
4691 .each( options.complete )
4693 .filter( ":visible" )
4694 .animate( hideProps, {
4695 step: function( now, settings ) {
4696 // only calculate the percent when animating height
4697 // IE gets very inconsistent results when animating elements
4698 // with small values, which is common for padding
4699 if ( settings.prop == "height" ) {
4700 percentDone = ( settings.end - settings.start === 0 ) ? 0 :
4701 ( settings.now - settings.start ) / ( settings.end - settings.start );
4704 options.toShow[ 0 ].style[ settings.prop ] =
4705 ( percentDone * showProps[ settings.prop ].value )
4706 + showProps[ settings.prop ].unit;
4708 duration: options.duration,
4709 easing: options.easing,
4710 complete: function() {
4711 if ( !options.autoHeight ) {
4712 options.toShow.css( "height", "" );
4714 options.toShow.css({
4715 width: originalWidth,
4722 bounceslide: function( options ) {
4723 this.slide( options, {
4724 easing: options.down ? "easeOutBounce" : "swing",
4725 duration: options.down ? 1000 : 200
4733 * jQuery UI Autocomplete 1.8.4
4735 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
4736 * Dual licensed under the MIT or GPL Version 2 licenses.
4737 * http://jquery.org/license
4739 * http://docs.jquery.com/UI/Autocomplete
4743 * jquery.ui.widget.js
4744 * jquery.ui.position.js
4746 (function( $, undefined ) {
4748 $.widget( "ui.autocomplete", {
4760 _create: function() {
4762 doc = this.element[ 0 ].ownerDocument;
4764 .addClass( "ui-autocomplete-input" )
4765 .attr( "autocomplete", "off" )
4766 // TODO verify these actually work as intended
4769 "aria-autocomplete": "list",
4770 "aria-haspopup": "true"
4772 .bind( "keydown.autocomplete", function( event ) {
4773 if ( self.options.disabled ) {
4777 var keyCode = $.ui.keyCode;
4778 switch( event.keyCode ) {
4779 case keyCode.PAGE_UP:
4780 self._move( "previousPage", event );
4782 case keyCode.PAGE_DOWN:
4783 self._move( "nextPage", event );
4786 self._move( "previous", event );
4787 // prevent moving cursor to beginning of text field in some browsers
4788 event.preventDefault();
4791 self._move( "next", event );
4792 // prevent moving cursor to end of text field in some browsers
4793 event.preventDefault();
4796 case keyCode.NUMPAD_ENTER:
4797 // when menu is open or has focus
4798 if ( self.menu.element.is( ":visible" ) ) {
4799 event.preventDefault();
4801 //passthrough - ENTER and TAB both select the current element
4803 if ( !self.menu.active ) {
4806 self.menu.select( event );
4808 case keyCode.ESCAPE:
4809 self.element.val( self.term );
4810 self.close( event );
4813 // keypress is triggered before the input value is changed
4814 clearTimeout( self.searching );
4815 self.searching = setTimeout(function() {
4816 // only search if the value has changed
4817 if ( self.term != self.element.val() ) {
4818 self.selectedItem = null;
4819 self.search( null, event );
4821 }, self.options.delay );
4825 .bind( "focus.autocomplete", function() {
4826 if ( self.options.disabled ) {
4830 self.selectedItem = null;
4831 self.previous = self.element.val();
4833 .bind( "blur.autocomplete", function( event ) {
4834 if ( self.options.disabled ) {
4838 clearTimeout( self.searching );
4839 // clicks on the menu (or a button to trigger a search) will cause a blur event
4840 self.closing = setTimeout(function() {
4841 self.close( event );
4842 self._change( event );
4846 this.response = function() {
4847 return self._response.apply( self, arguments );
4849 this.menu = $( "<ul></ul>" )
4850 .addClass( "ui-autocomplete" )
4851 .appendTo( $( this.options.appendTo || "body", doc )[0] )
4852 // prevent the close-on-blur in case of a "slow" click on the menu (long mousedown)
4853 .mousedown(function( event ) {
4854 // clicking on the scrollbar causes focus to shift to the body
4855 // but we can't detect a mouseup or a click immediately afterward
4856 // so we have to track the next mousedown and close the menu if
4857 // the user clicks somewhere outside of the autocomplete
4858 var menuElement = self.menu.element[ 0 ];
4859 if ( event.target === menuElement ) {
4860 setTimeout(function() {
4861 $( document ).one( 'mousedown', function( event ) {
4862 if ( event.target !== self.element[ 0 ] &&
4863 event.target !== menuElement &&
4864 !$.ui.contains( menuElement, event.target ) ) {
4871 // use another timeout to make sure the blur-event-handler on the input was already triggered
4872 setTimeout(function() {
4873 clearTimeout( self.closing );
4877 focus: function( event, ui ) {
4878 var item = ui.item.data( "item.autocomplete" );
4879 if ( false !== self._trigger( "focus", null, { item: item } ) ) {
4880 // use value to match what will end up in the input, if it was a key event
4881 if ( /^key/.test(event.originalEvent.type) ) {
4882 self.element.val( item.value );
4886 selected: function( event, ui ) {
4887 var item = ui.item.data( "item.autocomplete" ),
4888 previous = self.previous;
4890 // only trigger when focus was lost (click on menu)
4891 if ( self.element[0] !== doc.activeElement ) {
4892 self.element.focus();
4893 self.previous = previous;
4896 if ( false !== self._trigger( "select", event, { item: item } ) ) {
4897 self.element.val( item.value );
4900 self.close( event );
4901 self.selectedItem = item;
4903 blur: function( event, ui ) {
4904 // don't set the value of the text field if it's already correct
4905 // this prevents moving the cursor unnecessarily
4906 if ( self.menu.element.is(":visible") &&
4907 ( self.element.val() !== self.term ) ) {
4908 self.element.val( self.term );
4912 .zIndex( this.element.zIndex() + 1 )
4913 // workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
4914 .css({ top: 0, left: 0 })
4917 if ( $.fn.bgiframe ) {
4918 this.menu.element.bgiframe();
4922 destroy: function() {
4924 .removeClass( "ui-autocomplete-input" )
4925 .removeAttr( "autocomplete" )
4926 .removeAttr( "role" )
4927 .removeAttr( "aria-autocomplete" )
4928 .removeAttr( "aria-haspopup" );
4929 this.menu.element.remove();
4930 $.Widget.prototype.destroy.call( this );
4933 _setOption: function( key, value ) {
4934 $.Widget.prototype._setOption.apply( this, arguments );
4935 if ( key === "source" ) {
4938 if ( key === "appendTo" ) {
4939 this.menu.element.appendTo( $( value || "body", this.element[0].ownerDocument )[0] )
4943 _initSource: function() {
4946 if ( $.isArray(this.options.source) ) {
4947 array = this.options.source;
4948 this.source = function( request, response ) {
4949 response( $.ui.autocomplete.filter(array, request.term) );
4951 } else if ( typeof this.options.source === "string" ) {
4952 url = this.options.source;
4953 this.source = function( request, response ) {
4954 $.getJSON( url, request, response );
4957 this.source = this.options.source;
4961 search: function( value, event ) {
4962 value = value != null ? value : this.element.val();
4963 if ( value.length < this.options.minLength ) {
4964 return this.close( event );
4967 clearTimeout( this.closing );
4968 if ( this._trigger("search") === false ) {
4972 return this._search( value );
4975 _search: function( value ) {
4976 this.term = this.element
4977 .addClass( "ui-autocomplete-loading" )
4978 // always save the actual value, not the one passed as an argument
4981 this.source( { term: value }, this.response );
4984 _response: function( content ) {
4985 if ( content.length ) {
4986 content = this._normalize( content );
4987 this._suggest( content );
4988 this._trigger( "open" );
4992 this.element.removeClass( "ui-autocomplete-loading" );
4995 close: function( event ) {
4996 clearTimeout( this.closing );
4997 if ( this.menu.element.is(":visible") ) {
4998 this._trigger( "close", event );
4999 this.menu.element.hide();
5000 this.menu.deactivate();
5004 _change: function( event ) {
5005 if ( this.previous !== this.element.val() ) {
5006 this._trigger( "change", event, { item: this.selectedItem } );
5010 _normalize: function( items ) {
5011 // assume all items have the right format when the first item is complete
5012 if ( items.length && items[0].label && items[0].value ) {
5015 return $.map( items, function(item) {
5016 if ( typeof item === "string" ) {
5023 label: item.label || item.value,
5024 value: item.value || item.label
5029 _suggest: function( items ) {
5030 var ul = this.menu.element
5032 .zIndex( this.element.zIndex() + 1 ),
5035 this._renderMenu( ul, items );
5036 // TODO refresh should check if the active item is still in the dom, removing the need for a manual deactivate
5037 this.menu.deactivate();
5038 this.menu.refresh();
5039 this.menu.element.show().position( $.extend({
5041 }, this.options.position ));
5043 menuWidth = ul.width( "" ).outerWidth();
5044 textWidth = this.element.outerWidth();
5045 ul.outerWidth( Math.max( menuWidth, textWidth ) );
5048 _renderMenu: function( ul, items ) {
5050 $.each( items, function( index, item ) {
5051 self._renderItem( ul, item );
5055 _renderItem: function( ul, item) {
5056 return $( "<li></li>" )
5057 .data( "item.autocomplete", item )
5058 .append( $( "<a></a>" ).text( item.label ) )
5062 _move: function( direction, event ) {
5063 if ( !this.menu.element.is(":visible") ) {
5064 this.search( null, event );
5067 if ( this.menu.first() && /^previous/.test(direction) ||
5068 this.menu.last() && /^next/.test(direction) ) {
5069 this.element.val( this.term );
5070 this.menu.deactivate();
5073 this.menu[ direction ]( event );
5076 widget: function() {
5077 return this.menu.element;
5081 $.extend( $.ui.autocomplete, {
5082 escapeRegex: function( value ) {
5083 return value.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
5085 filter: function(array, term) {
5086 var matcher = new RegExp( $.ui.autocomplete.escapeRegex(term), "i" );
5087 return $.grep( array, function(value) {
5088 return matcher.test( value.label || value.value || value );
5096 * jQuery UI Menu (not officially released)
5098 * This widget isn't yet finished and the API is subject to change. We plan to finish
5099 * it for the next release. You're welcome to give it a try anyway and give us feedback,
5100 * as long as you're okay with migrating your code later on. We can help with that, too.
5102 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
5103 * Dual licensed under the MIT or GPL Version 2 licenses.
5104 * http://jquery.org/license
5106 * http://docs.jquery.com/UI/Menu
5110 * jquery.ui.widget.js
5114 $.widget("ui.menu", {
5115 _create: function() {
5118 .addClass("ui-menu ui-widget ui-widget-content ui-corner-all")
5121 "aria-activedescendant": "ui-active-menuitem"
5123 .click(function( event ) {
5124 if ( !$( event.target ).closest( ".ui-menu-item a" ).length ) {
5128 event.preventDefault();
5129 self.select( event );
5134 refresh: function() {
5137 // don't refresh list items that are already adapted
5138 var items = this.element.children("li:not(.ui-menu-item):has(a)")
5139 .addClass("ui-menu-item")
5140 .attr("role", "menuitem");
5143 .addClass("ui-corner-all")
5144 .attr("tabindex", -1)
5145 // mouseenter doesn't work with event delegation
5146 .mouseenter(function( event ) {
5147 self.activate( event, $(this).parent() );
5149 .mouseleave(function() {
5154 activate: function( event, item ) {
5156 if (this.hasScroll()) {
5157 var offset = item.offset().top - this.element.offset().top,
5158 scroll = this.element.attr("scrollTop"),
5159 elementHeight = this.element.height();
5161 this.element.attr("scrollTop", scroll + offset);
5162 } else if (offset > elementHeight) {
5163 this.element.attr("scrollTop", scroll + offset - elementHeight + item.height());
5166 this.active = item.eq(0)
5168 .addClass("ui-state-hover")
5169 .attr("id", "ui-active-menuitem")
5171 this._trigger("focus", event, { item: item });
5174 deactivate: function() {
5175 if (!this.active) { return; }
5177 this.active.children("a")
5178 .removeClass("ui-state-hover")
5180 this._trigger("blur");
5184 next: function(event) {
5185 this.move("next", ".ui-menu-item:first", event);
5188 previous: function(event) {
5189 this.move("prev", ".ui-menu-item:last", event);
5193 return this.active && !this.active.prevAll(".ui-menu-item").length;
5197 return this.active && !this.active.nextAll(".ui-menu-item").length;
5200 move: function(direction, edge, event) {
5202 this.activate(event, this.element.children(edge));
5205 var next = this.active[direction + "All"](".ui-menu-item").eq(0);
5207 this.activate(event, next);
5209 this.activate(event, this.element.children(edge));
5213 // TODO merge with previousPage
5214 nextPage: function(event) {
5215 if (this.hasScroll()) {
5216 // TODO merge with no-scroll-else
5217 if (!this.active || this.last()) {
5218 this.activate(event, this.element.children(":first"));
5221 var base = this.active.offset().top,
5222 height = this.element.height(),
5223 result = this.element.children("li").filter(function() {
5224 var close = $(this).offset().top - base - height + $(this).height();
5225 // TODO improve approximation
5226 return close < 10 && close > -10;
5229 // TODO try to catch this earlier when scrollTop indicates the last page anyway
5230 if (!result.length) {
5231 result = this.element.children(":last");
5233 this.activate(event, result);
5235 this.activate(event, this.element.children(!this.active || this.last() ? ":first" : ":last"));
5239 // TODO merge with nextPage
5240 previousPage: function(event) {
5241 if (this.hasScroll()) {
5242 // TODO merge with no-scroll-else
5243 if (!this.active || this.first()) {
5244 this.activate(event, this.element.children(":last"));
5248 var base = this.active.offset().top,
5249 height = this.element.height();
5250 result = this.element.children("li").filter(function() {
5251 var close = $(this).offset().top - base + height - $(this).height();
5252 // TODO improve approximation
5253 return close < 10 && close > -10;
5256 // TODO try to catch this earlier when scrollTop indicates the last page anyway
5257 if (!result.length) {
5258 result = this.element.children(":first");
5260 this.activate(event, result);
5262 this.activate(event, this.element.children(!this.active || this.first() ? ":last" : ":first"));
5266 hasScroll: function() {
5267 return this.element.height() < this.element.attr("scrollHeight");
5270 select: function( event ) {
5271 this._trigger("selected", event, { item: this.active });
5277 * jQuery UI Button 1.8.4
5279 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
5280 * Dual licensed under the MIT or GPL Version 2 licenses.
5281 * http://jquery.org/license
5283 * http://docs.jquery.com/UI/Button
5287 * jquery.ui.widget.js
5289 (function( $, undefined ) {
5292 baseClasses = "ui-button ui-widget ui-state-default ui-corner-all",
5293 stateClasses = "ui-state-hover ui-state-active ",
5294 typeClasses = "ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only",
5295 formResetHandler = function( event ) {
5296 $( ":ui-button", event.target.form ).each(function() {
5297 var inst = $( this ).data( "button" );
5298 setTimeout(function() {
5303 radioGroup = function( radio ) {
5304 var name = radio.name,
5309 radios = $( form ).find( "[name='" + name + "']" );
5311 radios = $( "[name='" + name + "']", radio.ownerDocument )
5312 .filter(function() {
5320 $.widget( "ui.button", {
5329 _create: function() {
5330 this.element.closest( "form" )
5331 .unbind( "reset.button" )
5332 .bind( "reset.button", formResetHandler );
5334 this._determineButtonType();
5335 this.hasTitle = !!this.buttonElement.attr( "title" );
5338 options = this.options,
5339 toggleButton = this.type === "checkbox" || this.type === "radio",
5340 hoverClass = "ui-state-hover" + ( !toggleButton ? " ui-state-active" : "" ),
5341 focusClass = "ui-state-focus";
5343 if ( options.label === null ) {
5344 options.label = this.buttonElement.html();
5347 if ( this.element.is( ":disabled" ) ) {
5348 options.disabled = true;
5352 .addClass( baseClasses )
5353 .attr( "role", "button" )
5354 .bind( "mouseenter.button", function() {
5355 if ( options.disabled ) {
5358 $( this ).addClass( "ui-state-hover" );
5359 if ( this === lastActive ) {
5360 $( this ).addClass( "ui-state-active" );
5363 .bind( "mouseleave.button", function() {
5364 if ( options.disabled ) {
5367 $( this ).removeClass( hoverClass );
5369 .bind( "focus.button", function() {
5370 // no need to check disabled, focus won't be triggered anyway
5371 $( this ).addClass( focusClass );
5373 .bind( "blur.button", function() {
5374 $( this ).removeClass( focusClass );
5377 if ( toggleButton ) {
5378 this.element.bind( "change.button", function() {
5383 if ( this.type === "checkbox" ) {
5384 this.buttonElement.bind( "click.button", function() {
5385 if ( options.disabled ) {
5388 $( this ).toggleClass( "ui-state-active" );
5389 self.buttonElement.attr( "aria-pressed", self.element[0].checked );
5391 } else if ( this.type === "radio" ) {
5392 this.buttonElement.bind( "click.button", function() {
5393 if ( options.disabled ) {
5396 $( this ).addClass( "ui-state-active" );
5397 self.buttonElement.attr( "aria-pressed", true );
5399 var radio = self.element[ 0 ];
5403 return $( this ).button( "widget" )[ 0 ];
5405 .removeClass( "ui-state-active" )
5406 .attr( "aria-pressed", false );
5410 .bind( "mousedown.button", function() {
5411 if ( options.disabled ) {
5414 $( this ).addClass( "ui-state-active" );
5416 $( document ).one( "mouseup", function() {
5420 .bind( "mouseup.button", function() {
5421 if ( options.disabled ) {
5424 $( this ).removeClass( "ui-state-active" );
5426 .bind( "keydown.button", function(event) {
5427 if ( options.disabled ) {
5430 if ( event.keyCode == $.ui.keyCode.SPACE || event.keyCode == $.ui.keyCode.ENTER ) {
5431 $( this ).addClass( "ui-state-active" );
5434 .bind( "keyup.button", function() {
5435 $( this ).removeClass( "ui-state-active" );
5438 if ( this.buttonElement.is("a") ) {
5439 this.buttonElement.keyup(function(event) {
5440 if ( event.keyCode === $.ui.keyCode.SPACE ) {
5441 // TODO pass through original event correctly (just as 2nd argument doesn't work)
5448 // TODO: pull out $.Widget's handling for the disabled option into
5449 // $.Widget.prototype._setOptionDisabled so it's easy to proxy and can
5450 // be overridden by individual plugins
5451 this._setOption( "disabled", options.disabled );
5454 _determineButtonType: function() {
5456 if ( this.element.is(":checkbox") ) {
5457 this.type = "checkbox";
5459 if ( this.element.is(":radio") ) {
5460 this.type = "radio";
5462 if ( this.element.is("input") ) {
5463 this.type = "input";
5465 this.type = "button";
5470 if ( this.type === "checkbox" || this.type === "radio" ) {
5471 // we don't search against the document in case the element
5472 // is disconnected from the DOM
5473 this.buttonElement = this.element.parents().last()
5474 .find( "label[for=" + this.element.attr("id") + "]" );
5475 this.element.addClass( "ui-helper-hidden-accessible" );
5477 var checked = this.element.is( ":checked" );
5479 this.buttonElement.addClass( "ui-state-active" );
5481 this.buttonElement.attr( "aria-pressed", checked );
5483 this.buttonElement = this.element;
5487 widget: function() {
5488 return this.buttonElement;
5491 destroy: function() {
5493 .removeClass( "ui-helper-hidden-accessible" );
5495 .removeClass( baseClasses + " " + stateClasses + " " + typeClasses )
5496 .removeAttr( "role" )
5497 .removeAttr( "aria-pressed" )
5498 .html( this.buttonElement.find(".ui-button-text").html() );
5500 if ( !this.hasTitle ) {
5501 this.buttonElement.removeAttr( "title" );
5504 $.Widget.prototype.destroy.call( this );
5507 _setOption: function( key, value ) {
5508 $.Widget.prototype._setOption.apply( this, arguments );
5509 if ( key === "disabled" ) {
5511 this.element.attr( "disabled", true );
5513 this.element.removeAttr( "disabled" );
5516 this._resetButton();
5519 refresh: function() {
5520 var isDisabled = this.element.is( ":disabled" );
5521 if ( isDisabled !== this.options.disabled ) {
5522 this._setOption( "disabled", isDisabled );
5524 if ( this.type === "radio" ) {
5525 radioGroup( this.element[0] ).each(function() {
5526 if ( $( this ).is( ":checked" ) ) {
5527 $( this ).button( "widget" )
5528 .addClass( "ui-state-active" )
5529 .attr( "aria-pressed", true );
5531 $( this ).button( "widget" )
5532 .removeClass( "ui-state-active" )
5533 .attr( "aria-pressed", false );
5536 } else if ( this.type === "checkbox" ) {
5537 if ( this.element.is( ":checked" ) ) {
5539 .addClass( "ui-state-active" )
5540 .attr( "aria-pressed", true );
5543 .removeClass( "ui-state-active" )
5544 .attr( "aria-pressed", false );
5549 _resetButton: function() {
5550 if ( this.type === "input" ) {
5551 if ( this.options.label ) {
5552 this.element.val( this.options.label );
5556 var buttonElement = this.buttonElement.removeClass( typeClasses ),
5557 buttonText = $( "<span></span>" )
5558 .addClass( "ui-button-text" )
5559 .html( this.options.label )
5560 .appendTo( buttonElement.empty() )
5562 icons = this.options.icons,
5563 multipleIcons = icons.primary && icons.secondary;
5564 if ( icons.primary || icons.secondary ) {
5565 buttonElement.addClass( "ui-button-text-icon" +
5566 ( multipleIcons ? "s" : ( icons.primary ? "-primary" : "-secondary" ) ) );
5567 if ( icons.primary ) {
5568 buttonElement.prepend( "<span class='ui-button-icon-primary ui-icon " + icons.primary + "'></span>" );
5570 if ( icons.secondary ) {
5571 buttonElement.append( "<span class='ui-button-icon-secondary ui-icon " + icons.secondary + "'></span>" );
5573 if ( !this.options.text ) {
5575 .addClass( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" )
5576 .removeClass( "ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary" );
5577 if ( !this.hasTitle ) {
5578 buttonElement.attr( "title", buttonText );
5582 buttonElement.addClass( "ui-button-text-only" );
5587 $.widget( "ui.buttonset", {
5588 _create: function() {
5589 this.element.addClass( "ui-buttonset" );
5597 _setOption: function( key, value ) {
5598 if ( key === "disabled" ) {
5599 this.buttons.button( "option", key, value );
5602 $.Widget.prototype._setOption.apply( this, arguments );
5605 refresh: function() {
5606 this.buttons = this.element.find( ":button, :submit, :reset, :checkbox, :radio, a, :data(button)" )
5607 .filter( ":ui-button" )
5608 .button( "refresh" )
5610 .not( ":ui-button" )
5614 return $( this ).button( "widget" )[ 0 ];
5616 .removeClass( "ui-corner-all ui-corner-left ui-corner-right" )
5618 .addClass( "ui-corner-left" )
5621 .addClass( "ui-corner-right" )
5626 destroy: function() {
5627 this.element.removeClass( "ui-buttonset" );
5630 return $( this ).button( "widget" )[ 0 ];
5632 .removeClass( "ui-corner-left ui-corner-right" )
5634 .button( "destroy" );
5636 $.Widget.prototype.destroy.call( this );
5642 * jQuery UI Dialog 1.8.4
5644 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
5645 * Dual licensed under the MIT or GPL Version 2 licenses.
5646 * http://jquery.org/license
5648 * http://docs.jquery.com/UI/Dialog
5652 * jquery.ui.widget.js
5653 * jquery.ui.button.js
5654 * jquery.ui.draggable.js
5655 * jquery.ui.mouse.js
5656 * jquery.ui.position.js
5657 * jquery.ui.resizable.js
5659 (function( $, undefined ) {
5661 var uiDialogClasses =
5664 'ui-widget-content ' +
5667 $.widget("ui.dialog", {
5671 closeOnEscape: true,
5687 // ensure that the titlebar is never outside the document
5688 using: function(pos) {
5689 var topOffset = $(this).css(pos).offset().top;
5690 if (topOffset < 0) {
5691 $(this).css('top', pos.top - topOffset);
5703 _create: function() {
5704 this.originalTitle = this.element.attr('title');
5705 // #5742 - .attr() might return a DOMElement
5706 if ( typeof this.originalTitle !== "string" ) {
5707 this.originalTitle = "";
5711 options = self.options,
5713 title = options.title || self.originalTitle || ' ',
5714 titleId = $.ui.dialog.getTitleId(self.element),
5716 uiDialog = (self.uiDialog = $('<div></div>'))
5717 .appendTo(document.body)
5719 .addClass(uiDialogClasses + options.dialogClass)
5721 zIndex: options.zIndex
5723 // setting tabIndex makes the div focusable
5724 // setting outline to 0 prevents a border on focus in Mozilla
5725 .attr('tabIndex', -1).css('outline', 0).keydown(function(event) {
5726 if (options.closeOnEscape && event.keyCode &&
5727 event.keyCode === $.ui.keyCode.ESCAPE) {
5730 event.preventDefault();
5735 'aria-labelledby': titleId
5737 .mousedown(function(event) {
5738 self.moveToTop(false, event);
5741 uiDialogContent = self.element
5743 .removeAttr('title')
5745 'ui-dialog-content ' +
5746 'ui-widget-content')
5747 .appendTo(uiDialog),
5749 uiDialogTitlebar = (self.uiDialogTitlebar = $('<div></div>'))
5751 'ui-dialog-titlebar ' +
5752 'ui-widget-header ' +
5754 'ui-helper-clearfix'
5756 .prependTo(uiDialog),
5758 uiDialogTitlebarClose = $('<a href="#"></a>')
5760 'ui-dialog-titlebar-close ' +
5763 .attr('role', 'button')
5766 uiDialogTitlebarClose.addClass('ui-state-hover');
5769 uiDialogTitlebarClose.removeClass('ui-state-hover');
5773 uiDialogTitlebarClose.addClass('ui-state-focus');
5776 uiDialogTitlebarClose.removeClass('ui-state-focus');
5778 .click(function(event) {
5782 .appendTo(uiDialogTitlebar),
5784 uiDialogTitlebarCloseText = (self.uiDialogTitlebarCloseText = $('<span></span>'))
5787 'ui-icon-closethick'
5789 .text(options.closeText)
5790 .appendTo(uiDialogTitlebarClose),
5792 uiDialogTitle = $('<span></span>')
5793 .addClass('ui-dialog-title')
5794 .attr('id', titleId)
5796 .prependTo(uiDialogTitlebar);
5798 //handling of deprecated beforeclose (vs beforeClose) option
5799 //Ticket #4669 http://dev.jqueryui.com/ticket/4669
5800 //TODO: remove in 1.9pre
5801 if ($.isFunction(options.beforeclose) && !$.isFunction(options.beforeClose)) {
5802 options.beforeClose = options.beforeclose;
5805 uiDialogTitlebar.find("*").add(uiDialogTitlebar).disableSelection();
5807 if (options.draggable && $.fn.draggable) {
5808 self._makeDraggable();
5810 if (options.resizable && $.fn.resizable) {
5811 self._makeResizable();
5814 self._createButtons(options.buttons);
5815 self._isOpen = false;
5817 if ($.fn.bgiframe) {
5818 uiDialog.bgiframe();
5823 if ( this.options.autoOpen ) {
5828 destroy: function() {
5832 self.overlay.destroy();
5834 self.uiDialog.hide();
5837 .removeData('dialog')
5838 .removeClass('ui-dialog-content ui-widget-content')
5839 .hide().appendTo('body');
5840 self.uiDialog.remove();
5842 if (self.originalTitle) {
5843 self.element.attr('title', self.originalTitle);
5849 widget: function() {
5850 return this.uiDialog;
5853 close: function(event) {
5857 if (false === self._trigger('beforeClose', event)) {
5862 self.overlay.destroy();
5864 self.uiDialog.unbind('keypress.ui-dialog');
5866 self._isOpen = false;
5868 if (self.options.hide) {
5869 self.uiDialog.hide(self.options.hide, function() {
5870 self._trigger('close', event);
5873 self.uiDialog.hide();
5874 self._trigger('close', event);
5877 $.ui.dialog.overlay.resize();
5879 // adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
5880 if (self.options.modal) {
5882 $('.ui-dialog').each(function() {
5883 if (this !== self.uiDialog[0]) {
5884 maxZ = Math.max(maxZ, $(this).css('z-index'));
5887 $.ui.dialog.maxZ = maxZ;
5893 isOpen: function() {
5894 return this._isOpen;
5897 // the force parameter allows us to move modal dialogs to their correct
5899 moveToTop: function(force, event) {
5901 options = self.options,
5904 if ((options.modal && !force) ||
5905 (!options.stack && !options.modal)) {
5906 return self._trigger('focus', event);
5909 if (options.zIndex > $.ui.dialog.maxZ) {
5910 $.ui.dialog.maxZ = options.zIndex;
5913 $.ui.dialog.maxZ += 1;
5914 self.overlay.$el.css('z-index', $.ui.dialog.overlay.maxZ = $.ui.dialog.maxZ);
5917 //Save and then restore scroll since Opera 9.5+ resets when parent z-Index is changed.
5918 // http://ui.jquery.com/bugs/ticket/3193
5919 saveScroll = { scrollTop: self.element.attr('scrollTop'), scrollLeft: self.element.attr('scrollLeft') };
5920 $.ui.dialog.maxZ += 1;
5921 self.uiDialog.css('z-index', $.ui.dialog.maxZ);
5922 self.element.attr(saveScroll);
5923 self._trigger('focus', event);
5929 if (this._isOpen) { return; }
5932 options = self.options,
5933 uiDialog = self.uiDialog;
5935 self.overlay = options.modal ? new $.ui.dialog.overlay(self) : null;
5936 if (uiDialog.next().length) {
5937 uiDialog.appendTo('body');
5940 self._position(options.position);
5941 uiDialog.show(options.show);
5942 self.moveToTop(true);
5944 // prevent tabbing out of modal dialogs
5945 if (options.modal) {
5946 uiDialog.bind('keypress.ui-dialog', function(event) {
5947 if (event.keyCode !== $.ui.keyCode.TAB) {
5951 var tabbables = $(':tabbable', this),
5952 first = tabbables.filter(':first'),
5953 last = tabbables.filter(':last');
5955 if (event.target === last[0] && !event.shiftKey) {
5958 } else if (event.target === first[0] && event.shiftKey) {
5965 // set focus to the first tabbable element in the content area or the first button
5966 // if there are no tabbable elements, set focus on the dialog itself
5967 $(self.element.find(':tabbable').get().concat(
5968 uiDialog.find('.ui-dialog-buttonpane :tabbable').get().concat(
5969 uiDialog.get()))).eq(0).focus();
5971 self._trigger('open');
5972 self._isOpen = true;
5977 _createButtons: function(buttons) {
5980 uiDialogButtonPane = $('<div></div>')
5982 'ui-dialog-buttonpane ' +
5983 'ui-widget-content ' +
5984 'ui-helper-clearfix'
5986 uiButtonSet = $( "<div></div>" )
5987 .addClass( "ui-dialog-buttonset" )
5988 .appendTo( uiDialogButtonPane );
5990 // if we already have a button pane, remove it
5991 self.uiDialog.find('.ui-dialog-buttonpane').remove();
5993 if (typeof buttons === 'object' && buttons !== null) {
5994 $.each(buttons, function() {
5995 return !(hasButtons = true);
5999 $.each(buttons, function(name, fn) {
6000 var button = $('<button type="button"></button>')
6002 .click(function() { fn.apply(self.element[0], arguments); })
6003 .appendTo(uiButtonSet);
6008 uiDialogButtonPane.appendTo(self.uiDialog);
6012 _makeDraggable: function() {
6014 options = self.options,
6018 function filteredUi(ui) {
6020 position: ui.position,
6025 self.uiDialog.draggable({
6026 cancel: '.ui-dialog-content, .ui-dialog-titlebar-close',
6027 handle: '.ui-dialog-titlebar',
6028 containment: 'document',
6029 start: function(event, ui) {
6030 heightBeforeDrag = options.height === "auto" ? "auto" : $(this).height();
6031 $(this).height($(this).height()).addClass("ui-dialog-dragging");
6032 self._trigger('dragStart', event, filteredUi(ui));
6034 drag: function(event, ui) {
6035 self._trigger('drag', event, filteredUi(ui));
6037 stop: function(event, ui) {
6038 options.position = [ui.position.left - doc.scrollLeft(),
6039 ui.position.top - doc.scrollTop()];
6040 $(this).removeClass("ui-dialog-dragging").height(heightBeforeDrag);
6041 self._trigger('dragStop', event, filteredUi(ui));
6042 $.ui.dialog.overlay.resize();
6047 _makeResizable: function(handles) {
6048 handles = (handles === undefined ? this.options.resizable : handles);
6050 options = self.options,
6051 // .ui-resizable has position: relative defined in the stylesheet
6052 // but dialogs have to use absolute or fixed positioning
6053 position = self.uiDialog.css('position'),
6054 resizeHandles = (typeof handles === 'string' ?
6056 'n,e,s,w,se,sw,ne,nw'
6059 function filteredUi(ui) {
6061 originalPosition: ui.originalPosition,
6062 originalSize: ui.originalSize,
6063 position: ui.position,
6068 self.uiDialog.resizable({
6069 cancel: '.ui-dialog-content',
6070 containment: 'document',
6071 alsoResize: self.element,
6072 maxWidth: options.maxWidth,
6073 maxHeight: options.maxHeight,
6074 minWidth: options.minWidth,
6075 minHeight: self._minHeight(),
6076 handles: resizeHandles,
6077 start: function(event, ui) {
6078 $(this).addClass("ui-dialog-resizing");
6079 self._trigger('resizeStart', event, filteredUi(ui));
6081 resize: function(event, ui) {
6082 self._trigger('resize', event, filteredUi(ui));
6084 stop: function(event, ui) {
6085 $(this).removeClass("ui-dialog-resizing");
6086 options.height = $(this).height();
6087 options.width = $(this).width();
6088 self._trigger('resizeStop', event, filteredUi(ui));
6089 $.ui.dialog.overlay.resize();
6092 .css('position', position)
6093 .find('.ui-resizable-se').addClass('ui-icon ui-icon-grip-diagonal-se');
6096 _minHeight: function() {
6097 var options = this.options;
6099 if (options.height === 'auto') {
6100 return options.minHeight;
6102 return Math.min(options.minHeight, options.height);
6106 _position: function(position) {
6112 // deep extending converts arrays to objects in jQuery <= 1.3.2 :-(
6113 // if (typeof position == 'string' || $.isArray(position)) {
6114 // myAt = $.isArray(position) ? position : position.split(' ');
6116 if (typeof position === 'string' || (typeof position === 'object' && '0' in position)) {
6117 myAt = position.split ? position.split(' ') : [position[0], position[1]];
6118 if (myAt.length === 1) {
6122 $.each(['left', 'top'], function(i, offsetPosition) {
6123 if (+myAt[i] === myAt[i]) {
6124 offset[i] = myAt[i];
6125 myAt[i] = offsetPosition;
6132 offset: offset.join(" ")
6136 position = $.extend({}, $.ui.dialog.prototype.options.position, position);
6138 position = $.ui.dialog.prototype.options.position;
6141 // need to show the dialog to get the actual offset in the position plugin
6142 isVisible = this.uiDialog.is(':visible');
6144 this.uiDialog.show();
6147 // workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
6148 .css({ top: 0, left: 0 })
6149 .position(position);
6151 this.uiDialog.hide();
6155 _setOption: function(key, value){
6157 uiDialog = self.uiDialog,
6158 isResizable = uiDialog.is(':data(resizable)'),
6162 //handling of deprecated beforeclose (vs beforeClose) option
6163 //Ticket #4669 http://dev.jqueryui.com/ticket/4669
6164 //TODO: remove in 1.9pre
6166 key = "beforeClose";
6169 self._createButtons(value);
6173 // convert whatever was passed in to a string, for text() to not throw up
6174 self.uiDialogTitlebarCloseText.text("" + value);
6178 .removeClass(self.options.dialogClass)
6179 .addClass(uiDialogClasses + value);
6183 uiDialog.addClass('ui-dialog-disabled');
6185 uiDialog.removeClass('ui-dialog-disabled');
6190 self._makeDraggable();
6192 uiDialog.draggable('destroy');
6200 uiDialog.resizable('option', 'maxHeight', value);
6206 uiDialog.resizable('option', 'maxWidth', value);
6212 uiDialog.resizable('option', 'minHeight', value);
6218 uiDialog.resizable('option', 'minWidth', value);
6223 self._position(value);
6226 // currently resizable, becoming non-resizable
6227 if (isResizable && !value) {
6228 uiDialog.resizable('destroy');
6231 // currently resizable, changing handles
6232 if (isResizable && typeof value === 'string') {
6233 uiDialog.resizable('option', 'handles', value);
6236 // currently non-resizable, becoming resizable
6237 if (!isResizable && value !== false) {
6238 self._makeResizable(value);
6242 // convert whatever was passed in o a string, for html() to not throw up
6243 $(".ui-dialog-title", self.uiDialogTitlebar).html("" + (value || ' '));
6250 $.Widget.prototype._setOption.apply(self, arguments);
6257 /* If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
6258 * divs will both have width and height set, so we need to reset them
6260 var options = this.options,
6263 // reset content sizing
6264 // hide for non content measurement because height: 0 doesn't work in IE quirks mode (see #4350)
6271 if (options.minWidth > options.width) {
6272 options.width = options.minWidth;
6275 // reset wrapper sizing
6276 // determine the height of all the non-content elements
6277 nonContentHeight = this.uiDialog.css({
6279 width: options.width
6284 .css(options.height === 'auto' ? {
6285 minHeight: Math.max(options.minHeight - nonContentHeight, 0),
6289 height: Math.max(options.height - nonContentHeight, 0)
6293 if (this.uiDialog.is(':data(resizable)')) {
6294 this.uiDialog.resizable('option', 'minHeight', this._minHeight());
6299 $.extend($.ui.dialog, {
6305 getTitleId: function($el) {
6306 var id = $el.attr('id');
6311 return 'ui-dialog-title-' + id;
6314 overlay: function(dialog) {
6315 this.$el = $.ui.dialog.overlay.create(dialog);
6319 $.extend($.ui.dialog.overlay, {
6321 // reuse old instances due to IE memory leak with alpha transparency (see #5185)
6324 events: $.map('focus,mousedown,mouseup,keydown,keypress,click'.split(','),
6325 function(event) { return event + '.dialog-overlay'; }).join(' '),
6326 create: function(dialog) {
6327 if (this.instances.length === 0) {
6328 // prevent use of anchors and inputs
6329 // we use a setTimeout in case the overlay is created from an
6330 // event that we're going to be cancelling (see #2804)
6331 setTimeout(function() {
6332 // handle $(el).dialog().dialog('close') (see #4065)
6333 if ($.ui.dialog.overlay.instances.length) {
6334 $(document).bind($.ui.dialog.overlay.events, function(event) {
6335 // stop events if the z-index of the target is < the z-index of the overlay
6336 return ($(event.target).zIndex() >= $.ui.dialog.overlay.maxZ);
6341 // allow closing by pressing the escape key
6342 $(document).bind('keydown.dialog-overlay', function(event) {
6343 if (dialog.options.closeOnEscape && event.keyCode &&
6344 event.keyCode === $.ui.keyCode.ESCAPE) {
6346 dialog.close(event);
6347 event.preventDefault();
6351 // handle window resize
6352 $(window).bind('resize.dialog-overlay', $.ui.dialog.overlay.resize);
6355 var $el = (this.oldInstances.pop() || $('<div></div>').addClass('ui-widget-overlay'))
6356 .appendTo(document.body)
6358 width: this.width(),
6359 height: this.height()
6362 if ($.fn.bgiframe) {
6366 this.instances.push($el);
6370 destroy: function($el) {
6371 this.oldInstances.push(this.instances.splice($.inArray($el, this.instances), 1)[0]);
6373 if (this.instances.length === 0) {
6374 $([document, window]).unbind('.dialog-overlay');
6379 // adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
6381 $.each(this.instances, function() {
6382 maxZ = Math.max(maxZ, this.css('z-index'));
6387 height: function() {
6391 if ($.browser.msie && $.browser.version < 7) {
6392 scrollHeight = Math.max(
6393 document.documentElement.scrollHeight,
6394 document.body.scrollHeight
6396 offsetHeight = Math.max(
6397 document.documentElement.offsetHeight,
6398 document.body.offsetHeight
6401 if (scrollHeight < offsetHeight) {
6402 return $(window).height() + 'px';
6404 return scrollHeight + 'px';
6406 // handle "good" browsers
6408 return $(document).height() + 'px';
6416 if ($.browser.msie && $.browser.version < 7) {
6417 scrollWidth = Math.max(
6418 document.documentElement.scrollWidth,
6419 document.body.scrollWidth
6421 offsetWidth = Math.max(
6422 document.documentElement.offsetWidth,
6423 document.body.offsetWidth
6426 if (scrollWidth < offsetWidth) {
6427 return $(window).width() + 'px';
6429 return scrollWidth + 'px';
6431 // handle "good" browsers
6433 return $(document).width() + 'px';
6437 resize: function() {
6438 /* If the dialog is draggable and the user drags it past the
6439 * right edge of the window, the document becomes wider so we
6440 * need to stretch the overlay. If the user then drags the
6441 * dialog back to the left, the document will become narrower,
6442 * so we need to shrink the overlay to the appropriate size.
6443 * This is handled by shrinking the overlay before setting it
6444 * to the full document size.
6446 var $overlays = $([]);
6447 $.each($.ui.dialog.overlay.instances, function() {
6448 $overlays = $overlays.add(this);
6455 width: $.ui.dialog.overlay.width(),
6456 height: $.ui.dialog.overlay.height()
6461 $.extend($.ui.dialog.overlay.prototype, {
6462 destroy: function() {
6463 $.ui.dialog.overlay.destroy(this.$el);
6469 * jQuery UI Slider 1.8.4
6471 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
6472 * Dual licensed under the MIT or GPL Version 2 licenses.
6473 * http://jquery.org/license
6475 * http://docs.jquery.com/UI/Slider
6479 * jquery.ui.mouse.js
6480 * jquery.ui.widget.js
6482 (function( $, undefined ) {
6484 // number of pages in a slider
6485 // (how many times can you page up/down to go through the whole range)
6488 $.widget( "ui.slider", $.ui.mouse, {
6490 widgetEventPrefix: "slide",
6497 orientation: "horizontal",
6504 _create: function() {
6508 this._keySliding = false;
6509 this._mouseSliding = false;
6510 this._animateOff = true;
6511 this._handleIndex = null;
6512 this._detectOrientation();
6516 .addClass( "ui-slider" +
6517 " ui-slider-" + this.orientation +
6519 " ui-widget-content" +
6523 this.element.addClass( "ui-slider-disabled ui-disabled" );
6529 if ( o.range === true ) {
6530 this.range = $( "<div></div>" );
6532 o.values = [ this._valueMin(), this._valueMin() ];
6534 if ( o.values.length && o.values.length !== 2 ) {
6535 o.values = [ o.values[0], o.values[0] ];
6538 this.range = $( "<div></div>" );
6542 .appendTo( this.element )
6543 .addClass( "ui-slider-range" );
6545 if ( o.range === "min" || o.range === "max" ) {
6546 this.range.addClass( "ui-slider-range-" + o.range );
6549 // note: this isn't the most fittingly semantic framework class for this element,
6550 // but worked best visually with a variety of themes
6551 this.range.addClass( "ui-widget-header" );
6554 if ( $( ".ui-slider-handle", this.element ).length === 0 ) {
6555 $( "<a href='#'></a>" )
6556 .appendTo( this.element )
6557 .addClass( "ui-slider-handle" );
6560 if ( o.values && o.values.length ) {
6561 while ( $(".ui-slider-handle", this.element).length < o.values.length ) {
6562 $( "<a href='#'></a>" )
6563 .appendTo( this.element )
6564 .addClass( "ui-slider-handle" );
6568 this.handles = $( ".ui-slider-handle", this.element )
6569 .addClass( "ui-state-default" +
6572 this.handle = this.handles.eq( 0 );
6574 this.handles.add( this.range ).filter( "a" )
6575 .click(function( event ) {
6576 event.preventDefault();
6579 if ( !o.disabled ) {
6580 $( this ).addClass( "ui-state-hover" );
6583 $( this ).removeClass( "ui-state-hover" );
6586 if ( !o.disabled ) {
6587 $( ".ui-slider .ui-state-focus" ).removeClass( "ui-state-focus" );
6588 $( this ).addClass( "ui-state-focus" );
6594 $( this ).removeClass( "ui-state-focus" );
6597 this.handles.each(function( i ) {
6598 $( this ).data( "index.ui-slider-handle", i );
6602 .keydown(function( event ) {
6604 index = $( this ).data( "index.ui-slider-handle" ),
6610 if ( self.options.disabled ) {
6614 switch ( event.keyCode ) {
6615 case $.ui.keyCode.HOME:
6616 case $.ui.keyCode.END:
6617 case $.ui.keyCode.PAGE_UP:
6618 case $.ui.keyCode.PAGE_DOWN:
6619 case $.ui.keyCode.UP:
6620 case $.ui.keyCode.RIGHT:
6621 case $.ui.keyCode.DOWN:
6622 case $.ui.keyCode.LEFT:
6624 if ( !self._keySliding ) {
6625 self._keySliding = true;
6626 $( this ).addClass( "ui-state-active" );
6627 allowed = self._start( event, index );
6628 if ( allowed === false ) {
6635 step = self.options.step;
6636 if ( self.options.values && self.options.values.length ) {
6637 curVal = newVal = self.values( index );
6639 curVal = newVal = self.value();
6642 switch ( event.keyCode ) {
6643 case $.ui.keyCode.HOME:
6644 newVal = self._valueMin();
6646 case $.ui.keyCode.END:
6647 newVal = self._valueMax();
6649 case $.ui.keyCode.PAGE_UP:
6650 newVal = self._trimAlignValue( curVal + ( (self._valueMax() - self._valueMin()) / numPages ) );
6652 case $.ui.keyCode.PAGE_DOWN:
6653 newVal = self._trimAlignValue( curVal - ( (self._valueMax() - self._valueMin()) / numPages ) );
6655 case $.ui.keyCode.UP:
6656 case $.ui.keyCode.RIGHT:
6657 if ( curVal === self._valueMax() ) {
6660 newVal = self._trimAlignValue( curVal + step );
6662 case $.ui.keyCode.DOWN:
6663 case $.ui.keyCode.LEFT:
6664 if ( curVal === self._valueMin() ) {
6667 newVal = self._trimAlignValue( curVal - step );
6671 self._slide( event, index, newVal );
6676 .keyup(function( event ) {
6677 var index = $( this ).data( "index.ui-slider-handle" );
6679 if ( self._keySliding ) {
6680 self._keySliding = false;
6681 self._stop( event, index );
6682 self._change( event, index );
6683 $( this ).removeClass( "ui-state-active" );
6688 this._refreshValue();
6690 this._animateOff = false;
6693 destroy: function() {
6694 this.handles.remove();
6695 this.range.remove();
6698 .removeClass( "ui-slider" +
6699 " ui-slider-horizontal" +
6700 " ui-slider-vertical" +
6701 " ui-slider-disabled" +
6703 " ui-widget-content" +
6705 .removeData( "slider" )
6706 .unbind( ".slider" );
6708 this._mouseDestroy();
6713 _mouseCapture: function( event ) {
6714 var o = this.options,
6729 this.elementSize = {
6730 width: this.element.outerWidth(),
6731 height: this.element.outerHeight()
6733 this.elementOffset = this.element.offset();
6735 position = { x: event.pageX, y: event.pageY };
6736 normValue = this._normValueFromMouse( position );
6737 distance = this._valueMax() - this._valueMin() + 1;
6739 this.handles.each(function( i ) {
6740 var thisDistance = Math.abs( normValue - self.values(i) );
6741 if ( distance > thisDistance ) {
6742 distance = thisDistance;
6743 closestHandle = $( this );
6748 // workaround for bug #3736 (if both handles of a range are at 0,
6749 // the first is always used as the one with least distance,
6750 // and moving it is obviously prevented by preventing negative ranges)
6751 if( o.range === true && this.values(1) === o.min ) {
6753 closestHandle = $( this.handles[index] );
6756 allowed = this._start( event, index );
6757 if ( allowed === false ) {
6760 this._mouseSliding = true;
6762 self._handleIndex = index;
6765 .addClass( "ui-state-active" )
6768 offset = closestHandle.offset();
6769 mouseOverHandle = !$( event.target ).parents().andSelf().is( ".ui-slider-handle" );
6770 this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
6771 left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
6772 top: event.pageY - offset.top -
6773 ( closestHandle.height() / 2 ) -
6774 ( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) -
6775 ( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) +
6776 ( parseInt( closestHandle.css("marginTop"), 10 ) || 0)
6779 this._slide( event, index, normValue );
6780 this._animateOff = true;
6784 _mouseStart: function( event ) {
6788 _mouseDrag: function( event ) {
6789 var position = { x: event.pageX, y: event.pageY },
6790 normValue = this._normValueFromMouse( position );
6792 this._slide( event, this._handleIndex, normValue );
6797 _mouseStop: function( event ) {
6798 this.handles.removeClass( "ui-state-active" );
6799 this._mouseSliding = false;
6801 this._stop( event, this._handleIndex );
6802 this._change( event, this._handleIndex );
6804 this._handleIndex = null;
6805 this._clickOffset = null;
6806 this._animateOff = false;
6811 _detectOrientation: function() {
6812 this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
6815 _normValueFromMouse: function( position ) {
6822 if ( this.orientation === "horizontal" ) {
6823 pixelTotal = this.elementSize.width;
6824 pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 );
6826 pixelTotal = this.elementSize.height;
6827 pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 );
6830 percentMouse = ( pixelMouse / pixelTotal );
6831 if ( percentMouse > 1 ) {
6834 if ( percentMouse < 0 ) {
6837 if ( this.orientation === "vertical" ) {
6838 percentMouse = 1 - percentMouse;
6841 valueTotal = this._valueMax() - this._valueMin();
6842 valueMouse = this._valueMin() + percentMouse * valueTotal;
6844 return this._trimAlignValue( valueMouse );
6847 _start: function( event, index ) {
6849 handle: this.handles[ index ],
6852 if ( this.options.values && this.options.values.length ) {
6853 uiHash.value = this.values( index );
6854 uiHash.values = this.values();
6856 return this._trigger( "start", event, uiHash );
6859 _slide: function( event, index, newVal ) {
6864 if ( this.options.values && this.options.values.length ) {
6865 otherVal = this.values( index ? 0 : 1 );
6867 if ( ( this.options.values.length === 2 && this.options.range === true ) &&
6868 ( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) )
6873 if ( newVal !== this.values( index ) ) {
6874 newValues = this.values();
6875 newValues[ index ] = newVal;
6876 // A slide can be canceled by returning false from the slide callback
6877 allowed = this._trigger( "slide", event, {
6878 handle: this.handles[ index ],
6882 otherVal = this.values( index ? 0 : 1 );
6883 if ( allowed !== false ) {
6884 this.values( index, newVal, true );
6888 if ( newVal !== this.value() ) {
6889 // A slide can be canceled by returning false from the slide callback
6890 allowed = this._trigger( "slide", event, {
6891 handle: this.handles[ index ],
6894 if ( allowed !== false ) {
6895 this.value( newVal );
6901 _stop: function( event, index ) {
6903 handle: this.handles[ index ],
6906 if ( this.options.values && this.options.values.length ) {
6907 uiHash.value = this.values( index );
6908 uiHash.values = this.values();
6911 this._trigger( "stop", event, uiHash );
6914 _change: function( event, index ) {
6915 if ( !this._keySliding && !this._mouseSliding ) {
6917 handle: this.handles[ index ],
6920 if ( this.options.values && this.options.values.length ) {
6921 uiHash.value = this.values( index );
6922 uiHash.values = this.values();
6925 this._trigger( "change", event, uiHash );
6929 value: function( newValue ) {
6930 if ( arguments.length ) {
6931 this.options.value = this._trimAlignValue( newValue );
6932 this._refreshValue();
6933 this._change( null, 0 );
6936 return this._value();
6939 values: function( index, newValue ) {
6944 if ( arguments.length > 1 ) {
6945 this.options.values[ index ] = this._trimAlignValue( newValue );
6946 this._refreshValue();
6947 this._change( null, index );
6950 if ( arguments.length ) {
6951 if ( $.isArray( arguments[ 0 ] ) ) {
6952 vals = this.options.values;
6953 newValues = arguments[ 0 ];
6954 for ( i = 0; i < vals.length; i += 1 ) {
6955 vals[ i ] = this._trimAlignValue( newValues[ i ] );
6956 this._change( null, i );
6958 this._refreshValue();
6960 if ( this.options.values && this.options.values.length ) {
6961 return this._values( index );
6963 return this.value();
6967 return this._values();
6971 _setOption: function( key, value ) {
6975 if ( $.isArray( this.options.values ) ) {
6976 valsLength = this.options.values.length;
6979 $.Widget.prototype._setOption.apply( this, arguments );
6984 this.handles.filter( ".ui-state-focus" ).blur();
6985 this.handles.removeClass( "ui-state-hover" );
6986 this.handles.attr( "disabled", "disabled" );
6987 this.element.addClass( "ui-disabled" );
6989 this.handles.removeAttr( "disabled" );
6990 this.element.removeClass( "ui-disabled" );
6994 this._detectOrientation();
6996 .removeClass( "ui-slider-horizontal ui-slider-vertical" )
6997 .addClass( "ui-slider-" + this.orientation );
6998 this._refreshValue();
7001 this._animateOff = true;
7002 this._refreshValue();
7003 this._change( null, 0 );
7004 this._animateOff = false;
7007 this._animateOff = true;
7008 this._refreshValue();
7009 for ( i = 0; i < valsLength; i += 1 ) {
7010 this._change( null, i );
7012 this._animateOff = false;
7017 //internal value getter
7018 // _value() returns value trimmed by min and max, aligned by step
7019 _value: function() {
7020 var val = this.options.value;
7021 val = this._trimAlignValue( val );
7026 //internal values getter
7027 // _values() returns array of values trimmed by min and max, aligned by step
7028 // _values( index ) returns single value trimmed by min and max, aligned by step
7029 _values: function( index ) {
7034 if ( arguments.length ) {
7035 val = this.options.values[ index ];
7036 val = this._trimAlignValue( val );
7040 // .slice() creates a copy of the array
7041 // this copy gets trimmed by min and max and then returned
7042 vals = this.options.values.slice();
7043 for ( i = 0; i < vals.length; i+= 1) {
7044 vals[ i ] = this._trimAlignValue( vals[ i ] );
7051 // returns the step-aligned value that val is closest to, between (inclusive) min and max
7052 _trimAlignValue: function( val ) {
7053 if ( val < this._valueMin() ) {
7054 return this._valueMin();
7056 if ( val > this._valueMax() ) {
7057 return this._valueMax();
7059 var step = ( this.options.step > 0 ) ? this.options.step : 1,
7060 valModStep = val % step,
7061 alignValue = val - valModStep;
7063 if ( Math.abs(valModStep) * 2 >= step ) {
7064 alignValue += ( valModStep > 0 ) ? step : ( -step );
7067 // Since JavaScript has problems with large floats, round
7068 // the final value to 5 digits after the decimal point (see #4124)
7069 return parseFloat( alignValue.toFixed(5) );
7072 _valueMin: function() {
7073 return this.options.min;
7076 _valueMax: function() {
7077 return this.options.max;
7080 _refreshValue: function() {
7081 var oRange = this.options.range,
7084 animate = ( !this._animateOff ) ? o.animate : false,
7092 if ( this.options.values && this.options.values.length ) {
7093 this.handles.each(function( i, j ) {
7094 valPercent = ( self.values(i) - self._valueMin() ) / ( self._valueMax() - self._valueMin() ) * 100;
7095 _set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
7096 $( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
7097 if ( self.options.range === true ) {
7098 if ( self.orientation === "horizontal" ) {
7100 self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate );
7103 self.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
7107 self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate );
7110 self.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
7114 lastValPercent = valPercent;
7117 value = this.value();
7118 valueMin = this._valueMin();
7119 valueMax = this._valueMax();
7120 valPercent = ( valueMax !== valueMin ) ?
7121 ( value - valueMin ) / ( valueMax - valueMin ) * 100 :
7123 _set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
7124 this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
7126 if ( oRange === "min" && this.orientation === "horizontal" ) {
7127 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate );
7129 if ( oRange === "max" && this.orientation === "horizontal" ) {
7130 this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
7132 if ( oRange === "min" && this.orientation === "vertical" ) {
7133 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate );
7135 if ( oRange === "max" && this.orientation === "vertical" ) {
7136 this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
7143 $.extend( $.ui.slider, {
7149 * jQuery UI Tabs 1.8.4
7151 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
7152 * Dual licensed under the MIT or GPL Version 2 licenses.
7153 * http://jquery.org/license
7155 * http://docs.jquery.com/UI/Tabs
7159 * jquery.ui.widget.js
7161 (function( $, undefined ) {
7166 function getNextTabId() {
7170 function getNextListId() {
7174 $.widget( "ui.tabs", {
7179 cookie: null, // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true }
7185 fx: null, // e.g. { height: 'toggle', opacity: 'toggle', duration: 200 }
7186 idPrefix: "ui-tabs-",
7188 panelTemplate: "<div></div>",
7192 spinner: "<em>Loading…</em>",
7193 tabTemplate: "<li><a href='#{href}'><span>#{label}</span></a></li>"
7196 _create: function() {
7197 this._tabify( true );
7200 _setOption: function( key, value ) {
7201 if ( key == "selected" ) {
7202 if (this.options.collapsible && value == this.options.selected ) {
7205 this.select( value );
7207 this.options[ key ] = value;
7212 _tabId: function( a ) {
7213 return a.title && a.title.replace( /\s/g, "_" ).replace( /[^A-Za-z0-9\-_:\.]/g, "" ) ||
7214 this.options.idPrefix + getNextTabId();
7217 _sanitizeSelector: function( hash ) {
7218 // we need this because an id may contain a ":"
7219 return hash.replace( /:/g, "\\:" );
7222 _cookie: function() {
7223 var cookie = this.cookie ||
7224 ( this.cookie = this.options.cookie.name || "ui-tabs-" + getNextListId() );
7225 return $.cookie.apply( null, [ cookie ].concat( $.makeArray( arguments ) ) );
7228 _ui: function( tab, panel ) {
7232 index: this.anchors.index( tab )
7236 _cleanup: function() {
7237 // restore all former loading tabs labels
7238 this.lis.filter( ".ui-state-processing" )
7239 .removeClass( "ui-state-processing" )
7240 .find( "span:data(label.tabs)" )
7243 el.html( el.data( "label.tabs" ) ).removeData( "label.tabs" );
7247 _tabify: function( init ) {
7250 fragmentId = /^#.+/; // Safari 2 reports '#' for an empty hash
7252 this.list = this.element.find( "ol,ul" ).eq( 0 );
7253 this.lis = $( "li:has(a[href])", this.list );
7254 this.anchors = this.lis.map(function() {
7255 return $( "a", this )[ 0 ];
7257 this.panels = $( [] );
7259 this.anchors.each(function( i, a ) {
7260 var href = $( a ).attr( "href" );
7261 // For dynamically created HTML that contains a hash as href IE < 8 expands
7262 // such href to the full page url with hash and then misinterprets tab as ajax.
7263 // Same consideration applies for an added tab with a fragment identifier
7264 // since a[href=#fragment-identifier] does unexpectedly not match.
7265 // Thus normalize href attribute...
7266 var hrefBase = href.split( "#" )[ 0 ],
7268 if ( hrefBase && ( hrefBase === location.toString().split( "#" )[ 0 ] ||
7269 ( baseEl = $( "base" )[ 0 ]) && hrefBase === baseEl.href ) ) {
7275 if ( fragmentId.test( href ) ) {
7276 self.panels = self.panels.add( self._sanitizeSelector( href ) );
7278 // prevent loading the page itself if href is just "#"
7279 } else if ( href !== "#" ) {
7280 // required for restore on destroy
7281 $.data( a, "href.tabs", href );
7283 // TODO until #3808 is fixed strip fragment identifier from url
7284 // (IE fails to load from such url)
7285 $.data( a, "load.tabs", href.replace( /#.*$/, "" ) );
7287 var id = self._tabId( a );
7289 var $panel = $( "#" + id );
7290 if ( !$panel.length ) {
7291 $panel = $( o.panelTemplate )
7293 .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
7294 .insertAfter( self.panels[ i - 1 ] || self.list );
7295 $panel.data( "destroy.tabs", true );
7297 self.panels = self.panels.add( $panel );
7300 o.disabled.push( i );
7304 // initialization from scratch
7306 // attach necessary classes for styling
7307 this.element.addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" );
7308 this.list.addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" );
7309 this.lis.addClass( "ui-state-default ui-corner-top" );
7310 this.panels.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" );
7313 // use "selected" option or try to retrieve:
7314 // 1. from fragment identifier in url
7316 // 3. from selected class attribute on <li>
7317 if ( o.selected === undefined ) {
7318 if ( location.hash ) {
7319 this.anchors.each(function( i, a ) {
7320 if ( a.hash == location.hash ) {
7326 if ( typeof o.selected !== "number" && o.cookie ) {
7327 o.selected = parseInt( self._cookie(), 10 );
7329 if ( typeof o.selected !== "number" && this.lis.filter( ".ui-tabs-selected" ).length ) {
7330 o.selected = this.lis.index( this.lis.filter( ".ui-tabs-selected" ) );
7332 o.selected = o.selected || ( this.lis.length ? 0 : -1 );
7333 } else if ( o.selected === null ) { // usage of null is deprecated, TODO remove in next release
7337 // sanity check - default to first tab...
7338 o.selected = ( ( o.selected >= 0 && this.anchors[ o.selected ] ) || o.selected < 0 )
7342 // Take disabling tabs via class attribute from HTML
7343 // into account and update option properly.
7344 // A selected tab cannot become disabled.
7345 o.disabled = $.unique( o.disabled.concat(
7346 $.map( this.lis.filter( ".ui-state-disabled" ), function( n, i ) {
7347 return self.lis.index( n );
7351 if ( $.inArray( o.selected, o.disabled ) != -1 ) {
7352 o.disabled.splice( $.inArray( o.selected, o.disabled ), 1 );
7355 // highlight selected tab
7356 this.panels.addClass( "ui-tabs-hide" );
7357 this.lis.removeClass( "ui-tabs-selected ui-state-active" );
7358 // check for length avoids error when initializing empty list
7359 if ( o.selected >= 0 && this.anchors.length ) {
7360 this.panels.eq( o.selected ).removeClass( "ui-tabs-hide" );
7361 this.lis.eq( o.selected ).addClass( "ui-tabs-selected ui-state-active" );
7363 // seems to be expected behavior that the show callback is fired
7364 self.element.queue( "tabs", function() {
7365 self._trigger( "show", null,
7366 self._ui( self.anchors[ o.selected ], self.panels[ o.selected ] ) );
7369 this.load( o.selected );
7372 // clean up to avoid memory leaks in certain versions of IE 6
7373 // TODO: namespace this event
7374 $( window ).bind( "unload", function() {
7375 self.lis.add( self.anchors ).unbind( ".tabs" );
7376 self.lis = self.anchors = self.panels = null;
7378 // update selected after add/remove
7380 o.selected = this.lis.index( this.lis.filter( ".ui-tabs-selected" ) );
7383 // update collapsible
7384 // TODO: use .toggleClass()
7385 this.element[ o.collapsible ? "addClass" : "removeClass" ]( "ui-tabs-collapsible" );
7387 // set or update cookie after init and add/remove respectively
7389 this._cookie( o.selected, o.cookie );
7393 for ( var i = 0, li; ( li = this.lis[ i ] ); i++ ) {
7394 $( li )[ $.inArray( i, o.disabled ) != -1 &&
7395 // TODO: use .toggleClass()
7396 !$( li ).hasClass( "ui-tabs-selected" ) ? "addClass" : "removeClass" ]( "ui-state-disabled" );
7399 // reset cache if switching from cached to not cached
7400 if ( o.cache === false ) {
7401 this.anchors.removeData( "cache.tabs" );
7404 // remove all handlers before, tabify may run on existing tabs after add or option change
7405 this.lis.add( this.anchors ).unbind( ".tabs" );
7407 if ( o.event !== "mouseover" ) {
7408 var addState = function( state, el ) {
7409 if ( el.is( ":not(.ui-state-disabled)" ) ) {
7410 el.addClass( "ui-state-" + state );
7413 var removeState = function( state, el ) {
7414 el.removeClass( "ui-state-" + state );
7416 this.lis.bind( "mouseover.tabs" , function() {
7417 addState( "hover", $( this ) );
7419 this.lis.bind( "mouseout.tabs", function() {
7420 removeState( "hover", $( this ) );
7422 this.anchors.bind( "focus.tabs", function() {
7423 addState( "focus", $( this ).closest( "li" ) );
7425 this.anchors.bind( "blur.tabs", function() {
7426 removeState( "focus", $( this ).closest( "li" ) );
7430 // set up animations
7433 if ( $.isArray( o.fx ) ) {
7437 hideFx = showFx = o.fx;
7441 // Reset certain styles left over from animation
7442 // and prevent IE's ClearType bug...
7443 function resetStyle( $el, fx ) {
7444 $el.css( "display", "" );
7445 if ( !$.support.opacity && fx.opacity ) {
7446 $el[ 0 ].style.removeAttribute( "filter" );
7451 var showTab = showFx
7452 ? function( clicked, $show ) {
7453 $( clicked ).closest( "li" ).addClass( "ui-tabs-selected ui-state-active" );
7454 $show.hide().removeClass( "ui-tabs-hide" ) // avoid flicker that way
7455 .animate( showFx, showFx.duration || "normal", function() {
7456 resetStyle( $show, showFx );
7457 self._trigger( "show", null, self._ui( clicked, $show[ 0 ] ) );
7460 : function( clicked, $show ) {
7461 $( clicked ).closest( "li" ).addClass( "ui-tabs-selected ui-state-active" );
7462 $show.removeClass( "ui-tabs-hide" );
7463 self._trigger( "show", null, self._ui( clicked, $show[ 0 ] ) );
7466 // Hide a tab, $show is optional...
7467 var hideTab = hideFx
7468 ? function( clicked, $hide ) {
7469 $hide.animate( hideFx, hideFx.duration || "normal", function() {
7470 self.lis.removeClass( "ui-tabs-selected ui-state-active" );
7471 $hide.addClass( "ui-tabs-hide" );
7472 resetStyle( $hide, hideFx );
7473 self.element.dequeue( "tabs" );
7476 : function( clicked, $hide, $show ) {
7477 self.lis.removeClass( "ui-tabs-selected ui-state-active" );
7478 $hide.addClass( "ui-tabs-hide" );
7479 self.element.dequeue( "tabs" );
7482 // attach tab event handler, unbind to avoid duplicates from former tabifying...
7483 this.anchors.bind( o.event + ".tabs", function() {
7485 $li = $(el).closest( "li" ),
7486 $hide = self.panels.filter( ":not(.ui-tabs-hide)" ),
7487 $show = $( self._sanitizeSelector( el.hash ) );
7489 // If tab is already selected and not collapsible or tab disabled or
7490 // or is already loading or click callback returns false stop here.
7491 // Check if click handler returns false last so that it is not executed
7492 // for a disabled or loading tab!
7493 if ( ( $li.hasClass( "ui-tabs-selected" ) && !o.collapsible) ||
7494 $li.hasClass( "ui-state-disabled" ) ||
7495 $li.hasClass( "ui-state-processing" ) ||
7496 self._trigger( "select", null, self._ui( this, $show[ 0 ] ) ) === false ) {
7501 o.selected = self.anchors.index( this );
7505 // if tab may be closed
7506 if ( o.collapsible ) {
7507 if ( $li.hasClass( "ui-tabs-selected" ) ) {
7511 self._cookie( o.selected, o.cookie );
7514 self.element.queue( "tabs", function() {
7515 hideTab( el, $hide );
7516 }).dequeue( "tabs" );
7520 } else if ( !$hide.length ) {
7522 self._cookie( o.selected, o.cookie );
7525 self.element.queue( "tabs", function() {
7526 showTab( el, $show );
7529 // TODO make passing in node possible, see also http://dev.jqueryui.com/ticket/3171
7530 self.load( self.anchors.index( this ) );
7538 self._cookie( o.selected, o.cookie );
7542 if ( $show.length ) {
7543 if ( $hide.length ) {
7544 self.element.queue( "tabs", function() {
7545 hideTab( el, $hide );
7548 self.element.queue( "tabs", function() {
7549 showTab( el, $show );
7552 self.load( self.anchors.index( this ) );
7554 throw "jQuery UI Tabs: Mismatching fragment identifier.";
7557 // Prevent IE from keeping other link focussed when using the back button
7558 // and remove dotted border from clicked link. This is controlled via CSS
7559 // in modern browsers; blur() removes focus from address bar in Firefox
7560 // which can become a usability and annoying problem with tabs('rotate').
7561 if ( $.browser.msie ) {
7566 // disable click in any case
7567 this.anchors.bind( "click.tabs", function(){
7572 _getIndex: function( index ) {
7573 // meta-function to give users option to provide a href string instead of a numerical index.
7574 // also sanitizes numerical indexes to valid values.
7575 if ( typeof index == "string" ) {
7576 index = this.anchors.index( this.anchors.filter( "[href$=" + index + "]" ) );
7582 destroy: function() {
7583 var o = this.options;
7589 .removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" )
7590 .removeData( "tabs" );
7592 this.list.removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" );
7594 this.anchors.each(function() {
7595 var href = $.data( this, "href.tabs" );
7599 var $this = $( this ).unbind( ".tabs" );
7600 $.each( [ "href", "load", "cache" ], function( i, prefix ) {
7601 $this.removeData( prefix + ".tabs" );
7605 this.lis.unbind( ".tabs" ).add( this.panels ).each(function() {
7606 if ( $.data( this, "destroy.tabs" ) ) {
7609 $( this ).removeClass([
7616 "ui-state-disabled",
7618 "ui-widget-content",
7626 this._cookie( null, o.cookie );
7632 add: function( url, label, index ) {
7633 if ( index === undefined ) {
7634 index = this.anchors.length;
7639 $li = $( o.tabTemplate.replace( /#\{href\}/g, url ).replace( /#\{label\}/g, label ) ),
7640 id = !url.indexOf( "#" ) ? url.replace( "#", "" ) : this._tabId( $( "a", $li )[ 0 ] );
7642 $li.addClass( "ui-state-default ui-corner-top" ).data( "destroy.tabs", true );
7644 // try to find an existing element before creating a new one
7645 var $panel = $( "#" + id );
7646 if ( !$panel.length ) {
7647 $panel = $( o.panelTemplate )
7649 .data( "destroy.tabs", true );
7651 $panel.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide" );
7653 if ( index >= this.lis.length ) {
7654 $li.appendTo( this.list );
7655 $panel.appendTo( this.list[ 0 ].parentNode );
7657 $li.insertBefore( this.lis[ index ] );
7658 $panel.insertBefore( this.panels[ index ] );
7661 o.disabled = $.map( o.disabled, function( n, i ) {
7662 return n >= index ? ++n : n;
7667 if ( this.anchors.length == 1 ) {
7669 $li.addClass( "ui-tabs-selected ui-state-active" );
7670 $panel.removeClass( "ui-tabs-hide" );
7671 this.element.queue( "tabs", function() {
7672 self._trigger( "show", null, self._ui( self.anchors[ 0 ], self.panels[ 0 ] ) );
7678 this._trigger( "add", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
7682 remove: function( index ) {
7683 index = this._getIndex( index );
7684 var o = this.options,
7685 $li = this.lis.eq( index ).remove(),
7686 $panel = this.panels.eq( index ).remove();
7688 // If selected tab was removed focus tab to the right or
7689 // in case the last tab was removed the tab to the left.
7690 if ( $li.hasClass( "ui-tabs-selected" ) && this.anchors.length > 1) {
7691 this.select( index + ( index + 1 < this.anchors.length ? 1 : -1 ) );
7695 $.grep( o.disabled, function(n, i) {
7699 return n >= index ? --n : n;
7704 this._trigger( "remove", null, this._ui( $li.find( "a" )[ 0 ], $panel[ 0 ] ) );
7708 enable: function( index ) {
7709 index = this._getIndex( index );
7710 var o = this.options;
7711 if ( $.inArray( index, o.disabled ) == -1 ) {
7715 this.lis.eq( index ).removeClass( "ui-state-disabled" );
7716 o.disabled = $.grep( o.disabled, function( n, i ) {
7720 this._trigger( "enable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
7724 disable: function( index ) {
7725 index = this._getIndex( index );
7726 var self = this, o = this.options;
7727 // cannot disable already selected tab
7728 if ( index != o.selected ) {
7729 this.lis.eq( index ).addClass( "ui-state-disabled" );
7731 o.disabled.push( index );
7734 this._trigger( "disable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
7740 select: function( index ) {
7741 index = this._getIndex( index );
7742 if ( index == -1 ) {
7743 if ( this.options.collapsible && this.options.selected != -1 ) {
7744 index = this.options.selected;
7749 this.anchors.eq( index ).trigger( this.options.event + ".tabs" );
7753 load: function( indexĀ ) {
7754 index = this._getIndex( index );
7757 a = this.anchors.eq( index )[ 0 ],
7758 url = $.data( a, "load.tabs" );
7762 // not remote or from cache
7763 if ( !url || this.element.queue( "tabs" ).length !== 0 && $.data( a, "cache.tabs" ) ) {
7764 this.element.dequeue( "tabs" );
7768 // load remote from here on
7769 this.lis.eq( index ).addClass( "ui-state-processing" );
7772 var span = $( "span", a );
7773 span.data( "label.tabs", span.html() ).html( o.spinner );
7776 this.xhr = $.ajax( $.extend( {}, o.ajaxOptions, {
7778 success: function( r, s ) {
7779 $( self._sanitizeSelector( a.hash ) ).html( r );
7781 // take care of tab labels
7785 $.data( a, "cache.tabs", true );
7788 self._trigger( "load", null, self._ui( self.anchors[ index ], self.panels[ index ] ) );
7790 o.ajaxOptions.success( r, s );
7794 error: function( xhr, s, e ) {
7795 // take care of tab labels
7798 self._trigger( "load", null, self._ui( self.anchors[ index ], self.panels[ index ] ) );
7800 // Passing index avoid a race condition when this method is
7801 // called after the user has selected another tab.
7802 // Pass the anchor that initiated this request allows
7803 // loadError to manipulate the tab content panel via $(a.hash)
7804 o.ajaxOptions.error( xhr, s, index, a );
7810 // last, so that load event is fired before show...
7811 self.element.dequeue( "tabs" );
7817 // stop possibly running animations
7818 this.element.queue( [] );
7819 this.panels.stop( false, true );
7821 // "tabs" queue must not contain more than two elements,
7822 // which are the callbacks for the latest clicked tab...
7823 this.element.queue( "tabs", this.element.queue( "tabs" ).splice( -2, 2 ) );
7825 // terminate pending requests from other tabs
7831 // take care of tab labels
7836 url: function( index, url ) {
7837 this.anchors.eq( index ).removeData( "cache.tabs" ).data( "load.tabs", url );
7841 length: function() {
7842 return this.anchors.length;
7846 $.extend( $.ui.tabs, {
7857 $.extend( $.ui.tabs.prototype, {
7859 rotate: function( ms, continuing ) {
7863 var rotate = self._rotate || ( self._rotate = function( e ) {
7864 clearTimeout( self.rotation );
7865 self.rotation = setTimeout(function() {
7867 self.select( ++t < self.anchors.length ? t : 0 );
7871 e.stopPropagation();
7875 var stop = self._unrotate || ( self._unrotate = !continuing
7877 if (e.clientX) { // in case of a true click
7888 this.element.bind( "tabsshow", rotate );
7889 this.anchors.bind( o.event + ".tabs", stop );
7893 clearTimeout( self.rotation );
7894 this.element.unbind( "tabsshow", rotate );
7895 this.anchors.unbind( o.event + ".tabs", stop );
7896 delete this._rotate;
7897 delete this._unrotate;
7906 * jQuery UI Datepicker 1.8.4
7908 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
7909 * Dual licensed under the MIT or GPL Version 2 licenses.
7910 * http://jquery.org/license
7912 * http://docs.jquery.com/UI/Datepicker
7917 (function( $, undefined ) {
7919 $.extend($.ui, { datepicker: { version: "1.8.4" } });
7921 var PROP_NAME = 'datepicker';
7922 var dpuuid = new Date().getTime();
7924 /* Date picker manager.
7925 Use the singleton instance of this class, $.datepicker, to interact with the date picker.
7926 Settings for (groups of) date pickers are maintained in an instance object,
7927 allowing multiple different settings on the same page. */
7929 function Datepicker() {
7930 this.debug = false; // Change this to true to start debugging
7931 this._curInst = null; // The current instance in use
7932 this._keyEvent = false; // If the last event was a key event
7933 this._disabledInputs = []; // List of date picker inputs that have been disabled
7934 this._datepickerShowing = false; // True if the popup picker is showing , false if not
7935 this._inDialog = false; // True if showing within a "dialog", false if not
7936 this._mainDivId = 'ui-datepicker-div'; // The ID of the main datepicker division
7937 this._inlineClass = 'ui-datepicker-inline'; // The name of the inline marker class
7938 this._appendClass = 'ui-datepicker-append'; // The name of the append marker class
7939 this._triggerClass = 'ui-datepicker-trigger'; // The name of the trigger marker class
7940 this._dialogClass = 'ui-datepicker-dialog'; // The name of the dialog marker class
7941 this._disableClass = 'ui-datepicker-disabled'; // The name of the disabled covering marker class
7942 this._unselectableClass = 'ui-datepicker-unselectable'; // The name of the unselectable cell marker class
7943 this._currentClass = 'ui-datepicker-current-day'; // The name of the current day marker class
7944 this._dayOverClass = 'ui-datepicker-days-cell-over'; // The name of the day hover marker class
7945 this.regional = []; // Available regional settings, indexed by language code
7946 this.regional[''] = { // Default regional settings
7947 closeText: 'Done', // Display text for close link
7948 prevText: 'Prev', // Display text for previous month link
7949 nextText: 'Next', // Display text for next month link
7950 currentText: 'Today', // Display text for current month link
7951 monthNames: ['January','February','March','April','May','June',
7952 'July','August','September','October','November','December'], // Names of months for drop-down and formatting
7953 monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], // For formatting
7954 dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], // For formatting
7955 dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], // For formatting
7956 dayNamesMin: ['Su','Mo','Tu','We','Th','Fr','Sa'], // Column headings for days starting at Sunday
7957 weekHeader: 'Wk', // Column header for week of the year
7958 dateFormat: 'mm/dd/yy', // See format options on parseDate
7959 firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
7960 isRTL: false, // True if right-to-left language, false if left-to-right
7961 showMonthAfterYear: false, // True if the year select precedes month, false for month then year
7962 yearSuffix: '' // Additional text to append to the year in the month headers
7964 this._defaults = { // Global defaults for all the date picker instances
7965 showOn: 'focus', // 'focus' for popup on focus,
7966 // 'button' for trigger button, or 'both' for either
7967 showAnim: 'fadeIn', // Name of jQuery animation for popup
7968 showOptions: {}, // Options for enhanced animations
7969 defaultDate: null, // Used when field is blank: actual date,
7970 // +/-number for offset from today, null for today
7971 appendText: '', // Display text following the input box, e.g. showing the format
7972 buttonText: '...', // Text for trigger button
7973 buttonImage: '', // URL for trigger button image
7974 buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
7975 hideIfNoPrevNext: false, // True to hide next/previous month links
7976 // if not applicable, false to just disable them
7977 navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
7978 gotoCurrent: false, // True if today link goes back to current selection instead
7979 changeMonth: false, // True if month can be selected directly, false if only prev/next
7980 changeYear: false, // True if year can be selected directly, false if only prev/next
7981 yearRange: 'c-10:c+10', // Range of years to display in drop-down,
7982 // either relative to today's year (-nn:+nn), relative to currently displayed year
7983 // (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
7984 showOtherMonths: false, // True to show dates in other months, false to leave blank
7985 selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
7986 showWeek: false, // True to show week of the year, false to not show it
7987 calculateWeek: this.iso8601Week, // How to calculate the week of the year,
7988 // takes a Date and returns the number of the week for it
7989 shortYearCutoff: '+10', // Short year values < this are in the current century,
7990 // > this are in the previous century,
7991 // string value starting with '+' for current year + value
7992 minDate: null, // The earliest selectable date, or null for no limit
7993 maxDate: null, // The latest selectable date, or null for no limit
7994 duration: 'fast', // Duration of display/closure
7995 beforeShowDay: null, // Function that takes a date and returns an array with
7996 // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or '',
7997 // [2] = cell title (optional), e.g. $.datepicker.noWeekends
7998 beforeShow: null, // Function that takes an input field and
7999 // returns a set of custom settings for the date picker
8000 onSelect: null, // Define a callback function when a date is selected
8001 onChangeMonthYear: null, // Define a callback function when the month or year is changed
8002 onClose: null, // Define a callback function when the datepicker is closed
8003 numberOfMonths: 1, // Number of months to show at a time
8004 showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
8005 stepMonths: 1, // Number of months to step back/forward
8006 stepBigMonths: 12, // Number of months to step back/forward for the big links
8007 altField: '', // Selector for an alternate field to store selected dates into
8008 altFormat: '', // The date format to use for the alternate field
8009 constrainInput: true, // The input is constrained by the current date format
8010 showButtonPanel: false, // True to show button panel, false to not show it
8011 autoSize: false // True to size the input for the date format, false to leave as is
8013 $.extend(this._defaults, this.regional['']);
8014 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>');
8017 $.extend(Datepicker.prototype, {
8018 /* Class name added to elements to indicate already configured with a date picker. */
8019 markerClassName: 'hasDatepicker',
8021 /* Debug logging (if enabled). */
8024 console.log.apply('', arguments);
8027 // TODO rename to "widget" when switching to widget factory
8028 _widgetDatepicker: function() {
8032 /* Override the default settings for all instances of the date picker.
8033 @param settings object - the new settings to use as defaults (anonymous object)
8034 @return the manager object */
8035 setDefaults: function(settings) {
8036 extendRemove(this._defaults, settings || {});
8040 /* Attach the date picker to a jQuery selection.
8041 @param target element - the target input field or division or span
8042 @param settings object - the new settings to use for this date picker instance (anonymous) */
8043 _attachDatepicker: function(target, settings) {
8044 // check for settings on the control itself - in namespace 'date:'
8045 var inlineSettings = null;
8046 for (var attrName in this._defaults) {
8047 var attrValue = target.getAttribute('date:' + attrName);
8049 inlineSettings = inlineSettings || {};
8051 inlineSettings[attrName] = eval(attrValue);
8053 inlineSettings[attrName] = attrValue;
8057 var nodeName = target.nodeName.toLowerCase();
8058 var inline = (nodeName == 'div' || nodeName == 'span');
8061 target.id = 'dp' + this.uuid;
8063 var inst = this._newInst($(target), inline);
8064 inst.settings = $.extend({}, settings || {}, inlineSettings || {});
8065 if (nodeName == 'input') {
8066 this._connectDatepicker(target, inst);
8067 } else if (inline) {
8068 this._inlineDatepicker(target, inst);
8072 /* Create a new instance object. */
8073 _newInst: function(target, inline) {
8074 var id = target[0].id.replace(/([^A-Za-z0-9_])/g, '\\\\$1'); // escape jQuery meta chars
8075 return {id: id, input: target, // associated target
8076 selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
8077 drawMonth: 0, drawYear: 0, // month being drawn
8078 inline: inline, // is datepicker inline or not
8079 dpDiv: (!inline ? this.dpDiv : // presentation div
8080 $('<div class="' + this._inlineClass + ' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>'))};
8083 /* Attach the date picker to an input field. */
8084 _connectDatepicker: function(target, inst) {
8085 var input = $(target);
8086 inst.append = $([]);
8087 inst.trigger = $([]);
8088 if (input.hasClass(this.markerClassName))
8090 this._attachments(input, inst);
8091 input.addClass(this.markerClassName).keydown(this._doKeyDown).
8092 keypress(this._doKeyPress).keyup(this._doKeyUp).
8093 bind("setData.datepicker", function(event, key, value) {
8094 inst.settings[key] = value;
8095 }).bind("getData.datepicker", function(event, key) {
8096 return this._get(inst, key);
8098 this._autoSize(inst);
8099 $.data(target, PROP_NAME, inst);
8102 /* Make attachments based on settings. */
8103 _attachments: function(input, inst) {
8104 var appendText = this._get(inst, 'appendText');
8105 var isRTL = this._get(inst, 'isRTL');
8107 inst.append.remove();
8109 inst.append = $('<span class="' + this._appendClass + '">' + appendText + '</span>');
8110 input[isRTL ? 'before' : 'after'](inst.append);
8112 input.unbind('focus', this._showDatepicker);
8114 inst.trigger.remove();
8115 var showOn = this._get(inst, 'showOn');
8116 if (showOn == 'focus' || showOn == 'both') // pop-up date picker when in the marked field
8117 input.focus(this._showDatepicker);
8118 if (showOn == 'button' || showOn == 'both') { // pop-up date picker when button clicked
8119 var buttonText = this._get(inst, 'buttonText');
8120 var buttonImage = this._get(inst, 'buttonImage');
8121 inst.trigger = $(this._get(inst, 'buttonImageOnly') ?
8122 $('<img/>').addClass(this._triggerClass).
8123 attr({ src: buttonImage, alt: buttonText, title: buttonText }) :
8124 $('<button type="button"></button>').addClass(this._triggerClass).
8125 html(buttonImage == '' ? buttonText : $('<img/>').attr(
8126 { src:buttonImage, alt:buttonText, title:buttonText })));
8127 input[isRTL ? 'before' : 'after'](inst.trigger);
8128 inst.trigger.click(function() {
8129 if ($.datepicker._datepickerShowing && $.datepicker._lastInput == input[0])
8130 $.datepicker._hideDatepicker();
8132 $.datepicker._showDatepicker(input[0]);
8138 /* Apply the maximum length for the date format. */
8139 _autoSize: function(inst) {
8140 if (this._get(inst, 'autoSize') && !inst.inline) {
8141 var date = new Date(2009, 12 - 1, 20); // Ensure double digits
8142 var dateFormat = this._get(inst, 'dateFormat');
8143 if (dateFormat.match(/[DM]/)) {
8144 var findMax = function(names) {
8147 for (var i = 0; i < names.length; i++) {
8148 if (names[i].length > max) {
8149 max = names[i].length;
8155 date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ?
8156 'monthNames' : 'monthNamesShort'))));
8157 date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ?
8158 'dayNames' : 'dayNamesShort'))) + 20 - date.getDay());
8160 inst.input.attr('size', this._formatDate(inst, date).length);
8164 /* Attach an inline date picker to a div. */
8165 _inlineDatepicker: function(target, inst) {
8166 var divSpan = $(target);
8167 if (divSpan.hasClass(this.markerClassName))
8169 divSpan.addClass(this.markerClassName).append(inst.dpDiv).
8170 bind("setData.datepicker", function(event, key, value){
8171 inst.settings[key] = value;
8172 }).bind("getData.datepicker", function(event, key){
8173 return this._get(inst, key);
8175 $.data(target, PROP_NAME, inst);
8176 this._setDate(inst, this._getDefaultDate(inst), true);
8177 this._updateDatepicker(inst);
8178 this._updateAlternate(inst);
8181 /* Pop-up the date picker in a "dialog" box.
8182 @param input element - ignored
8183 @param date string or Date - the initial date to display
8184 @param onSelect function - the function to call when a date is selected
8185 @param settings object - update the dialog date picker instance's settings (anonymous object)
8186 @param pos int[2] - coordinates for the dialog's position within the screen or
8187 event - with x/y coordinates or
8188 leave empty for default (screen centre)
8189 @return the manager object */
8190 _dialogDatepicker: function(input, date, onSelect, settings, pos) {
8191 var inst = this._dialogInst; // internal instance
8194 var id = 'dp' + this.uuid;
8195 this._dialogInput = $('<input type="text" id="' + id +
8196 '" style="position: absolute; top: -100px; width: 0px; z-index: -10;"/>');
8197 this._dialogInput.keydown(this._doKeyDown);
8198 $('body').append(this._dialogInput);
8199 inst = this._dialogInst = this._newInst(this._dialogInput, false);
8201 $.data(this._dialogInput[0], PROP_NAME, inst);
8203 extendRemove(inst.settings, settings || {});
8204 date = (date && date.constructor == Date ? this._formatDate(inst, date) : date);
8205 this._dialogInput.val(date);
8207 this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);
8209 var browserWidth = document.documentElement.clientWidth;
8210 var browserHeight = document.documentElement.clientHeight;
8211 var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
8212 var scrollY = document.documentElement.scrollTop || document.body.scrollTop;
8213 this._pos = // should use actual width/height below
8214 [(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY];
8217 // move input on screen for focus, but hidden behind dialog
8218 this._dialogInput.css('left', (this._pos[0] + 20) + 'px').css('top', this._pos[1] + 'px');
8219 inst.settings.onSelect = onSelect;
8220 this._inDialog = true;
8221 this.dpDiv.addClass(this._dialogClass);
8222 this._showDatepicker(this._dialogInput[0]);
8224 $.blockUI(this.dpDiv);
8225 $.data(this._dialogInput[0], PROP_NAME, inst);
8229 /* Detach a datepicker from its control.
8230 @param target element - the target input field or division or span */
8231 _destroyDatepicker: function(target) {
8232 var $target = $(target);
8233 var inst = $.data(target, PROP_NAME);
8234 if (!$target.hasClass(this.markerClassName)) {
8237 var nodeName = target.nodeName.toLowerCase();
8238 $.removeData(target, PROP_NAME);
8239 if (nodeName == 'input') {
8240 inst.append.remove();
8241 inst.trigger.remove();
8242 $target.removeClass(this.markerClassName).
8243 unbind('focus', this._showDatepicker).
8244 unbind('keydown', this._doKeyDown).
8245 unbind('keypress', this._doKeyPress).
8246 unbind('keyup', this._doKeyUp);
8247 } else if (nodeName == 'div' || nodeName == 'span')
8248 $target.removeClass(this.markerClassName).empty();
8251 /* Enable the date picker to a jQuery selection.
8252 @param target element - the target input field or division or span */
8253 _enableDatepicker: function(target) {
8254 var $target = $(target);
8255 var inst = $.data(target, PROP_NAME);
8256 if (!$target.hasClass(this.markerClassName)) {
8259 var nodeName = target.nodeName.toLowerCase();
8260 if (nodeName == 'input') {
8261 target.disabled = false;
8262 inst.trigger.filter('button').
8263 each(function() { this.disabled = false; }).end().
8264 filter('img').css({opacity: '1.0', cursor: ''});
8266 else if (nodeName == 'div' || nodeName == 'span') {
8267 var inline = $target.children('.' + this._inlineClass);
8268 inline.children().removeClass('ui-state-disabled');
8270 this._disabledInputs = $.map(this._disabledInputs,
8271 function(value) { return (value == target ? null : value); }); // delete entry
8274 /* Disable the date picker to a jQuery selection.
8275 @param target element - the target input field or division or span */
8276 _disableDatepicker: function(target) {
8277 var $target = $(target);
8278 var inst = $.data(target, PROP_NAME);
8279 if (!$target.hasClass(this.markerClassName)) {
8282 var nodeName = target.nodeName.toLowerCase();
8283 if (nodeName == 'input') {
8284 target.disabled = true;
8285 inst.trigger.filter('button').
8286 each(function() { this.disabled = true; }).end().
8287 filter('img').css({opacity: '0.5', cursor: 'default'});
8289 else if (nodeName == 'div' || nodeName == 'span') {
8290 var inline = $target.children('.' + this._inlineClass);
8291 inline.children().addClass('ui-state-disabled');
8293 this._disabledInputs = $.map(this._disabledInputs,
8294 function(value) { return (value == target ? null : value); }); // delete entry
8295 this._disabledInputs[this._disabledInputs.length] = target;
8298 /* Is the first field in a jQuery collection disabled as a datepicker?
8299 @param target element - the target input field or division or span
8300 @return boolean - true if disabled, false if enabled */
8301 _isDisabledDatepicker: function(target) {
8305 for (var i = 0; i < this._disabledInputs.length; i++) {
8306 if (this._disabledInputs[i] == target)
8312 /* Retrieve the instance data for the target control.
8313 @param target element - the target input field or division or span
8314 @return object - the associated instance data
8315 @throws error if a jQuery problem getting data */
8316 _getInst: function(target) {
8318 return $.data(target, PROP_NAME);
8321 throw 'Missing instance data for this datepicker';
8325 /* Update or retrieve the settings for a date picker attached to an input field or division.
8326 @param target element - the target input field or division or span
8327 @param name object - the new settings to update or
8328 string - the name of the setting to change or retrieve,
8329 when retrieving also 'all' for all instance settings or
8330 'defaults' for all global defaults
8331 @param value any - the new value for the setting
8332 (omit if above is an object or to retrieve a value) */
8333 _optionDatepicker: function(target, name, value) {
8334 var inst = this._getInst(target);
8335 if (arguments.length == 2 && typeof name == 'string') {
8336 return (name == 'defaults' ? $.extend({}, $.datepicker._defaults) :
8337 (inst ? (name == 'all' ? $.extend({}, inst.settings) :
8338 this._get(inst, name)) : null));
8340 var settings = name || {};
8341 if (typeof name == 'string') {
8343 settings[name] = value;
8346 if (this._curInst == inst) {
8347 this._hideDatepicker();
8349 var date = this._getDateDatepicker(target, true);
8350 extendRemove(inst.settings, settings);
8351 this._attachments($(target), inst);
8352 this._autoSize(inst);
8353 this._setDateDatepicker(target, date);
8354 this._updateDatepicker(inst);
8358 // change method deprecated
8359 _changeDatepicker: function(target, name, value) {
8360 this._optionDatepicker(target, name, value);
8363 /* Redraw the date picker attached to an input field or division.
8364 @param target element - the target input field or division or span */
8365 _refreshDatepicker: function(target) {
8366 var inst = this._getInst(target);
8368 this._updateDatepicker(inst);
8372 /* Set the dates for a jQuery selection.
8373 @param target element - the target input field or division or span
8374 @param date Date - the new date */
8375 _setDateDatepicker: function(target, date) {
8376 var inst = this._getInst(target);
8378 this._setDate(inst, date);
8379 this._updateDatepicker(inst);
8380 this._updateAlternate(inst);
8384 /* Get the date(s) for the first entry in a jQuery selection.
8385 @param target element - the target input field or division or span
8386 @param noDefault boolean - true if no default date is to be used
8387 @return Date - the current date */
8388 _getDateDatepicker: function(target, noDefault) {
8389 var inst = this._getInst(target);
8390 if (inst && !inst.inline)
8391 this._setDateFromField(inst, noDefault);
8392 return (inst ? this._getDate(inst) : null);
8395 /* Handle keystrokes. */
8396 _doKeyDown: function(event) {
8397 var inst = $.datepicker._getInst(event.target);
8399 var isRTL = inst.dpDiv.is('.ui-datepicker-rtl');
8400 inst._keyEvent = true;
8401 if ($.datepicker._datepickerShowing)
8402 switch (event.keyCode) {
8403 case 9: $.datepicker._hideDatepicker();
8405 break; // hide on tab out
8406 case 13: var sel = $('td.' + $.datepicker._dayOverClass, inst.dpDiv).
8407 add($('td.' + $.datepicker._currentClass, inst.dpDiv));
8409 $.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);
8411 $.datepicker._hideDatepicker();
8412 return false; // don't submit the form
8413 break; // select the value on enter
8414 case 27: $.datepicker._hideDatepicker();
8415 break; // hide on escape
8416 case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
8417 -$.datepicker._get(inst, 'stepBigMonths') :
8418 -$.datepicker._get(inst, 'stepMonths')), 'M');
8419 break; // previous month/year on page up/+ ctrl
8420 case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
8421 +$.datepicker._get(inst, 'stepBigMonths') :
8422 +$.datepicker._get(inst, 'stepMonths')), 'M');
8423 break; // next month/year on page down/+ ctrl
8424 case 35: if (event.ctrlKey || event.metaKey) $.datepicker._clearDate(event.target);
8425 handled = event.ctrlKey || event.metaKey;
8426 break; // clear on ctrl or command +end
8427 case 36: if (event.ctrlKey || event.metaKey) $.datepicker._gotoToday(event.target);
8428 handled = event.ctrlKey || event.metaKey;
8429 break; // current on ctrl or command +home
8430 case 37: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), 'D');
8431 handled = event.ctrlKey || event.metaKey;
8432 // -1 day on ctrl or command +left
8433 if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
8434 -$.datepicker._get(inst, 'stepBigMonths') :
8435 -$.datepicker._get(inst, 'stepMonths')), 'M');
8436 // next month/year on alt +left on Mac
8438 case 38: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, -7, 'D');
8439 handled = event.ctrlKey || event.metaKey;
8440 break; // -1 week on ctrl or command +up
8441 case 39: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), 'D');
8442 handled = event.ctrlKey || event.metaKey;
8443 // +1 day on ctrl or command +right
8444 if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
8445 +$.datepicker._get(inst, 'stepBigMonths') :
8446 +$.datepicker._get(inst, 'stepMonths')), 'M');
8447 // next month/year on alt +right
8449 case 40: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, +7, 'D');
8450 handled = event.ctrlKey || event.metaKey;
8451 break; // +1 week on ctrl or command +down
8452 default: handled = false;
8454 else if (event.keyCode == 36 && event.ctrlKey) // display the date picker on ctrl+home
8455 $.datepicker._showDatepicker(this);
8460 event.preventDefault();
8461 event.stopPropagation();
8465 /* Filter entered characters - based on date format. */
8466 _doKeyPress: function(event) {
8467 var inst = $.datepicker._getInst(event.target);
8468 if ($.datepicker._get(inst, 'constrainInput')) {
8469 var chars = $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat'));
8470 var chr = String.fromCharCode(event.charCode == undefined ? event.keyCode : event.charCode);
8471 return event.ctrlKey || (chr < ' ' || !chars || chars.indexOf(chr) > -1);
8475 /* Synchronise manual entry and field/alternate field. */
8476 _doKeyUp: function(event) {
8477 var inst = $.datepicker._getInst(event.target);
8478 if (inst.input.val() != inst.lastVal) {
8480 var date = $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
8481 (inst.input ? inst.input.val() : null),
8482 $.datepicker._getFormatConfig(inst));
8483 if (date) { // only if valid
8484 $.datepicker._setDateFromField(inst);
8485 $.datepicker._updateAlternate(inst);
8486 $.datepicker._updateDatepicker(inst);
8490 $.datepicker.log(event);
8496 /* Pop-up the date picker for a given input field.
8497 @param input element - the input field attached to the date picker or
8498 event - if triggered by focus */
8499 _showDatepicker: function(input) {
8500 input = input.target || input;
8501 if (input.nodeName.toLowerCase() != 'input') // find from button/image trigger
8502 input = $('input', input.parentNode)[0];
8503 if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput == input) // already here
8505 var inst = $.datepicker._getInst(input);
8506 if ($.datepicker._curInst && $.datepicker._curInst != inst) {
8507 $.datepicker._curInst.dpDiv.stop(true, true);
8509 var beforeShow = $.datepicker._get(inst, 'beforeShow');
8510 extendRemove(inst.settings, (beforeShow ? beforeShow.apply(input, [input, inst]) : {}));
8511 inst.lastVal = null;
8512 $.datepicker._lastInput = input;
8513 $.datepicker._setDateFromField(inst);
8514 if ($.datepicker._inDialog) // hide cursor
8516 if (!$.datepicker._pos) { // position below input
8517 $.datepicker._pos = $.datepicker._findPos(input);
8518 $.datepicker._pos[1] += input.offsetHeight; // add the height
8520 var isFixed = false;
8521 $(input).parents().each(function() {
8522 isFixed |= $(this).css('position') == 'fixed';
8525 if (isFixed && $.browser.opera) { // correction for Opera when fixed and scrolled
8526 $.datepicker._pos[0] -= document.documentElement.scrollLeft;
8527 $.datepicker._pos[1] -= document.documentElement.scrollTop;
8529 var offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]};
8530 $.datepicker._pos = null;
8531 // determine sizing offscreen
8532 inst.dpDiv.css({position: 'absolute', display: 'block', top: '-1000px'});
8533 $.datepicker._updateDatepicker(inst);
8534 // fix width for dynamic number of date pickers
8535 // and adjust position before showing
8536 offset = $.datepicker._checkOffset(inst, offset, isFixed);
8537 inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ?
8538 'static' : (isFixed ? 'fixed' : 'absolute')), display: 'none',
8539 left: offset.left + 'px', top: offset.top + 'px'});
8541 var showAnim = $.datepicker._get(inst, 'showAnim');
8542 var duration = $.datepicker._get(inst, 'duration');
8543 var postProcess = function() {
8544 $.datepicker._datepickerShowing = true;
8545 var borders = $.datepicker._getBorders(inst.dpDiv);
8546 inst.dpDiv.find('iframe.ui-datepicker-cover'). // IE6- only
8547 css({left: -borders[0], top: -borders[1],
8548 width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()});
8550 inst.dpDiv.zIndex($(input).zIndex()+1);
8551 if ($.effects && $.effects[showAnim])
8552 inst.dpDiv.show(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
8554 inst.dpDiv[showAnim || 'show']((showAnim ? duration : null), postProcess);
8555 if (!showAnim || !duration)
8557 if (inst.input.is(':visible') && !inst.input.is(':disabled'))
8559 $.datepicker._curInst = inst;
8563 /* Generate the date picker content. */
8564 _updateDatepicker: function(inst) {
8566 var borders = $.datepicker._getBorders(inst.dpDiv);
8567 inst.dpDiv.empty().append(this._generateHTML(inst))
8568 .find('iframe.ui-datepicker-cover') // IE6- only
8569 .css({left: -borders[0], top: -borders[1],
8570 width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()})
8572 .find('button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a')
8573 .bind('mouseout', function(){
8574 $(this).removeClass('ui-state-hover');
8575 if(this.className.indexOf('ui-datepicker-prev') != -1) $(this).removeClass('ui-datepicker-prev-hover');
8576 if(this.className.indexOf('ui-datepicker-next') != -1) $(this).removeClass('ui-datepicker-next-hover');
8578 .bind('mouseover', function(){
8579 if (!self._isDisabledDatepicker( inst.inline ? inst.dpDiv.parent()[0] : inst.input[0])) {
8580 $(this).parents('.ui-datepicker-calendar').find('a').removeClass('ui-state-hover');
8581 $(this).addClass('ui-state-hover');
8582 if(this.className.indexOf('ui-datepicker-prev') != -1) $(this).addClass('ui-datepicker-prev-hover');
8583 if(this.className.indexOf('ui-datepicker-next') != -1) $(this).addClass('ui-datepicker-next-hover');
8587 .find('.' + this._dayOverClass + ' a')
8588 .trigger('mouseover')
8590 var numMonths = this._getNumberOfMonths(inst);
8591 var cols = numMonths[1];
8594 inst.dpDiv.addClass('ui-datepicker-multi-' + cols).css('width', (width * cols) + 'em');
8596 inst.dpDiv.removeClass('ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4').width('');
8597 inst.dpDiv[(numMonths[0] != 1 || numMonths[1] != 1 ? 'add' : 'remove') +
8598 'Class']('ui-datepicker-multi');
8599 inst.dpDiv[(this._get(inst, 'isRTL') ? 'add' : 'remove') +
8600 'Class']('ui-datepicker-rtl');
8601 if (inst == $.datepicker._curInst && $.datepicker._datepickerShowing && inst.input &&
8602 inst.input.is(':visible') && !inst.input.is(':disabled'))
8606 /* Retrieve the size of left and top borders for an element.
8607 @param elem (jQuery object) the element of interest
8608 @return (number[2]) the left and top borders */
8609 _getBorders: function(elem) {
8610 var convert = function(value) {
8611 return {thin: 1, medium: 2, thick: 3}[value] || value;
8613 return [parseFloat(convert(elem.css('border-left-width'))),
8614 parseFloat(convert(elem.css('border-top-width')))];
8617 /* Check positioning to remain on screen. */
8618 _checkOffset: function(inst, offset, isFixed) {
8619 var dpWidth = inst.dpDiv.outerWidth();
8620 var dpHeight = inst.dpDiv.outerHeight();
8621 var inputWidth = inst.input ? inst.input.outerWidth() : 0;
8622 var inputHeight = inst.input ? inst.input.outerHeight() : 0;
8623 var viewWidth = document.documentElement.clientWidth + $(document).scrollLeft();
8624 var viewHeight = document.documentElement.clientHeight + $(document).scrollTop();
8626 offset.left -= (this._get(inst, 'isRTL') ? (dpWidth - inputWidth) : 0);
8627 offset.left -= (isFixed && offset.left == inst.input.offset().left) ? $(document).scrollLeft() : 0;
8628 offset.top -= (isFixed && offset.top == (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;
8630 // now check if datepicker is showing outside window viewport - move to a better place if so.
8631 offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?
8632 Math.abs(offset.left + dpWidth - viewWidth) : 0);
8633 offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?
8634 Math.abs(dpHeight + inputHeight) : 0);
8639 /* Find an object's position on the screen. */
8640 _findPos: function(obj) {
8641 var inst = this._getInst(obj);
8642 var isRTL = this._get(inst, 'isRTL');
8643 while (obj && (obj.type == 'hidden' || obj.nodeType != 1)) {
8644 obj = obj[isRTL ? 'previousSibling' : 'nextSibling'];
8646 var position = $(obj).offset();
8647 return [position.left, position.top];
8650 /* Hide the date picker from view.
8651 @param input element - the input field attached to the date picker */
8652 _hideDatepicker: function(input) {
8653 var inst = this._curInst;
8654 if (!inst || (input && inst != $.data(input, PROP_NAME)))
8656 if (this._datepickerShowing) {
8657 var showAnim = this._get(inst, 'showAnim');
8658 var duration = this._get(inst, 'duration');
8659 var postProcess = function() {
8660 $.datepicker._tidyDialog(inst);
8661 this._curInst = null;
8663 if ($.effects && $.effects[showAnim])
8664 inst.dpDiv.hide(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
8666 inst.dpDiv[(showAnim == 'slideDown' ? 'slideUp' :
8667 (showAnim == 'fadeIn' ? 'fadeOut' : 'hide'))]((showAnim ? duration : null), postProcess);
8670 var onClose = this._get(inst, 'onClose');
8672 onClose.apply((inst.input ? inst.input[0] : null),
8673 [(inst.input ? inst.input.val() : ''), inst]); // trigger custom callback
8674 this._datepickerShowing = false;
8675 this._lastInput = null;
8676 if (this._inDialog) {
8677 this._dialogInput.css({ position: 'absolute', left: '0', top: '-100px' });
8680 $('body').append(this.dpDiv);
8683 this._inDialog = false;
8687 /* Tidy up after a dialog display. */
8688 _tidyDialog: function(inst) {
8689 inst.dpDiv.removeClass(this._dialogClass).unbind('.ui-datepicker-calendar');
8692 /* Close date picker if clicked elsewhere. */
8693 _checkExternalClick: function(event) {
8694 if (!$.datepicker._curInst)
8696 var $target = $(event.target);
8697 if ($target[0].id != $.datepicker._mainDivId &&
8698 $target.parents('#' + $.datepicker._mainDivId).length == 0 &&
8699 !$target.hasClass($.datepicker.markerClassName) &&
8700 !$target.hasClass($.datepicker._triggerClass) &&
8701 $.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI))
8702 $.datepicker._hideDatepicker();
8705 /* Adjust one of the date sub-fields. */
8706 _adjustDate: function(id, offset, period) {
8708 var inst = this._getInst(target[0]);
8709 if (this._isDisabledDatepicker(target[0])) {
8712 this._adjustInstDate(inst, offset +
8713 (period == 'M' ? this._get(inst, 'showCurrentAtPos') : 0), // undo positioning
8715 this._updateDatepicker(inst);
8718 /* Action for current link. */
8719 _gotoToday: function(id) {
8721 var inst = this._getInst(target[0]);
8722 if (this._get(inst, 'gotoCurrent') && inst.currentDay) {
8723 inst.selectedDay = inst.currentDay;
8724 inst.drawMonth = inst.selectedMonth = inst.currentMonth;
8725 inst.drawYear = inst.selectedYear = inst.currentYear;
8728 var date = new Date();
8729 inst.selectedDay = date.getDate();
8730 inst.drawMonth = inst.selectedMonth = date.getMonth();
8731 inst.drawYear = inst.selectedYear = date.getFullYear();
8733 this._notifyChange(inst);
8734 this._adjustDate(target);
8737 /* Action for selecting a new month/year. */
8738 _selectMonthYear: function(id, select, period) {
8740 var inst = this._getInst(target[0]);
8741 inst._selectingMonthYear = false;
8742 inst['selected' + (period == 'M' ? 'Month' : 'Year')] =
8743 inst['draw' + (period == 'M' ? 'Month' : 'Year')] =
8744 parseInt(select.options[select.selectedIndex].value,10);
8745 this._notifyChange(inst);
8746 this._adjustDate(target);
8749 /* Restore input focus after not changing month/year. */
8750 _clickMonthYear: function(id) {
8752 var inst = this._getInst(target[0]);
8753 if (inst.input && inst._selectingMonthYear) {
8754 setTimeout(function() {
8758 inst._selectingMonthYear = !inst._selectingMonthYear;
8761 /* Action for selecting a day. */
8762 _selectDay: function(id, month, year, td) {
8764 if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) {
8767 var inst = this._getInst(target[0]);
8768 inst.selectedDay = inst.currentDay = $('a', td).html();
8769 inst.selectedMonth = inst.currentMonth = month;
8770 inst.selectedYear = inst.currentYear = year;
8771 this._selectDate(id, this._formatDate(inst,
8772 inst.currentDay, inst.currentMonth, inst.currentYear));
8775 /* Erase the input field and hide the date picker. */
8776 _clearDate: function(id) {
8778 var inst = this._getInst(target[0]);
8779 this._selectDate(target, '');
8782 /* Update the input field with the selected date. */
8783 _selectDate: function(id, dateStr) {
8785 var inst = this._getInst(target[0]);
8786 dateStr = (dateStr != null ? dateStr : this._formatDate(inst));
8788 inst.input.val(dateStr);
8789 this._updateAlternate(inst);
8790 var onSelect = this._get(inst, 'onSelect');
8792 onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); // trigger custom callback
8793 else if (inst.input)
8794 inst.input.trigger('change'); // fire the change event
8796 this._updateDatepicker(inst);
8798 this._hideDatepicker();
8799 this._lastInput = inst.input[0];
8800 if (typeof(inst.input[0]) != 'object')
8801 inst.input.focus(); // restore focus
8802 this._lastInput = null;
8806 /* Update any alternate field to synchronise with the main field. */
8807 _updateAlternate: function(inst) {
8808 var altField = this._get(inst, 'altField');
8809 if (altField) { // update alternate field too
8810 var altFormat = this._get(inst, 'altFormat') || this._get(inst, 'dateFormat');
8811 var date = this._getDate(inst);
8812 var dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst));
8813 $(altField).each(function() { $(this).val(dateStr); });
8817 /* Set as beforeShowDay function to prevent selection of weekends.
8818 @param date Date - the date to customise
8819 @return [boolean, string] - is this date selectable?, what is its CSS class? */
8820 noWeekends: function(date) {
8821 var day = date.getDay();
8822 return [(day > 0 && day < 6), ''];
8825 /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
8826 @param date Date - the date to get the week for
8827 @return number - the number of the week within the year that contains this date */
8828 iso8601Week: function(date) {
8829 var checkDate = new Date(date.getTime());
8830 // Find Thursday of this week starting on Monday
8831 checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7));
8832 var time = checkDate.getTime();
8833 checkDate.setMonth(0); // Compare with Jan 1
8834 checkDate.setDate(1);
8835 return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
8838 /* Parse a string value into a date object.
8839 See formatDate below for the possible formats.
8841 @param format string - the expected format of the date
8842 @param value string - the date in the above format
8843 @param settings Object - attributes include:
8844 shortYearCutoff number - the cutoff year for determining the century (optional)
8845 dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
8846 dayNames string[7] - names of the days from Sunday (optional)
8847 monthNamesShort string[12] - abbreviated names of the months (optional)
8848 monthNames string[12] - names of the months (optional)
8849 @return Date - the extracted date value or null if value is blank */
8850 parseDate: function (format, value, settings) {
8851 if (format == null || value == null)
8852 throw 'Invalid arguments';
8853 value = (typeof value == 'object' ? value.toString() : value + '');
8856 var shortYearCutoff = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff;
8857 var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
8858 var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
8859 var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
8860 var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
8865 var literal = false;
8866 // Check whether a format character is doubled
8867 var lookAhead = function(match) {
8868 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
8873 // Extract a number from the string value
8874 var getNumber = function(match) {
8876 var size = (match == '@' ? 14 : (match == '!' ? 20 :
8877 (match == 'y' ? 4 : (match == 'o' ? 3 : 2))));
8878 var digits = new RegExp('^\\d{1,' + size + '}');
8879 var num = value.substring(iValue).match(digits);
8881 throw 'Missing number at position ' + iValue;
8882 iValue += num[0].length;
8883 return parseInt(num[0], 10);
8885 // Extract a name from the string value and convert to an index
8886 var getName = function(match, shortNames, longNames) {
8887 var names = (lookAhead(match) ? longNames : shortNames);
8888 for (var i = 0; i < names.length; i++) {
8889 if (value.substr(iValue, names[i].length) == names[i]) {
8890 iValue += names[i].length;
8894 throw 'Unknown name at position ' + iValue;
8896 // Confirm that a literal character matches the string value
8897 var checkLiteral = function() {
8898 if (value.charAt(iValue) != format.charAt(iFormat))
8899 throw 'Unexpected literal at position ' + iValue;
8903 for (var iFormat = 0; iFormat < format.length; iFormat++) {
8905 if (format.charAt(iFormat) == "'" && !lookAhead("'"))
8910 switch (format.charAt(iFormat)) {
8912 day = getNumber('d');
8915 getName('D', dayNamesShort, dayNames);
8918 doy = getNumber('o');
8921 month = getNumber('m');
8924 month = getName('M', monthNamesShort, monthNames);
8927 year = getNumber('y');
8930 var date = new Date(getNumber('@'));
8931 year = date.getFullYear();
8932 month = date.getMonth() + 1;
8933 day = date.getDate();
8936 var date = new Date((getNumber('!') - this._ticksTo1970) / 10000);
8937 year = date.getFullYear();
8938 month = date.getMonth() + 1;
8939 day = date.getDate();
8952 year = new Date().getFullYear();
8953 else if (year < 100)
8954 year += new Date().getFullYear() - new Date().getFullYear() % 100 +
8955 (year <= shortYearCutoff ? 0 : -100);
8960 var dim = this._getDaysInMonth(year, month - 1);
8967 var date = this._daylightSavingAdjust(new Date(year, month - 1, day));
8968 if (date.getFullYear() != year || date.getMonth() + 1 != month || date.getDate() != day)
8969 throw 'Invalid date'; // E.g. 31/02/*
8973 /* Standard date formats. */
8974 ATOM: 'yy-mm-dd', // RFC 3339 (ISO 8601)
8975 COOKIE: 'D, dd M yy',
8976 ISO_8601: 'yy-mm-dd',
8977 RFC_822: 'D, d M y',
8978 RFC_850: 'DD, dd-M-y',
8979 RFC_1036: 'D, d M y',
8980 RFC_1123: 'D, d M yy',
8981 RFC_2822: 'D, d M yy',
8982 RSS: 'D, d M y', // RFC 822
8985 W3C: 'yy-mm-dd', // ISO 8601
8987 _ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) +
8988 Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000),
8990 /* Format a date object into a string value.
8991 The format can be combinations of the following:
8992 d - day of month (no leading zero)
8993 dd - day of month (two digit)
8994 o - day of year (no leading zeros)
8995 oo - day of year (three digit)
8998 m - month of year (no leading zero)
8999 mm - month of year (two digit)
9000 M - month name short
9001 MM - month name long
9002 y - year (two digit)
9003 yy - year (four digit)
9004 @ - Unix timestamp (ms since 01/01/1970)
9005 ! - Windows ticks (100ns since 01/01/0001)
9006 '...' - literal text
9009 @param format string - the desired format of the date
9010 @param date Date - the date value to format
9011 @param settings Object - attributes include:
9012 dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
9013 dayNames string[7] - names of the days from Sunday (optional)
9014 monthNamesShort string[12] - abbreviated names of the months (optional)
9015 monthNames string[12] - names of the months (optional)
9016 @return string - the date in the above format */
9017 formatDate: function (format, date, settings) {
9020 var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
9021 var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
9022 var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
9023 var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
9024 // Check whether a format character is doubled
9025 var lookAhead = function(match) {
9026 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
9031 // Format a number, with leading zero if necessary
9032 var formatNumber = function(match, value, len) {
9033 var num = '' + value;
9034 if (lookAhead(match))
9035 while (num.length < len)
9039 // Format a name, short or long as requested
9040 var formatName = function(match, value, shortNames, longNames) {
9041 return (lookAhead(match) ? longNames[value] : shortNames[value]);
9044 var literal = false;
9046 for (var iFormat = 0; iFormat < format.length; iFormat++) {
9048 if (format.charAt(iFormat) == "'" && !lookAhead("'"))
9051 output += format.charAt(iFormat);
9053 switch (format.charAt(iFormat)) {
9055 output += formatNumber('d', date.getDate(), 2);
9058 output += formatName('D', date.getDay(), dayNamesShort, dayNames);
9061 output += formatNumber('o',
9062 (date.getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000, 3);
9065 output += formatNumber('m', date.getMonth() + 1, 2);
9068 output += formatName('M', date.getMonth(), monthNamesShort, monthNames);
9071 output += (lookAhead('y') ? date.getFullYear() :
9072 (date.getYear() % 100 < 10 ? '0' : '') + date.getYear() % 100);
9075 output += date.getTime();
9078 output += date.getTime() * 10000 + this._ticksTo1970;
9087 output += format.charAt(iFormat);
9093 /* Extract all possible characters from the date format. */
9094 _possibleChars: function (format) {
9096 var literal = false;
9097 // Check whether a format character is doubled
9098 var lookAhead = function(match) {
9099 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
9104 for (var iFormat = 0; iFormat < format.length; iFormat++)
9106 if (format.charAt(iFormat) == "'" && !lookAhead("'"))
9109 chars += format.charAt(iFormat);
9111 switch (format.charAt(iFormat)) {
9112 case 'd': case 'm': case 'y': case '@':
9113 chars += '0123456789';
9116 return null; // Accept anything
9124 chars += format.charAt(iFormat);
9129 /* Get a setting value, defaulting if necessary. */
9130 _get: function(inst, name) {
9131 return inst.settings[name] !== undefined ?
9132 inst.settings[name] : this._defaults[name];
9135 /* Parse existing date and initialise date picker. */
9136 _setDateFromField: function(inst, noDefault) {
9137 if (inst.input.val() == inst.lastVal) {
9140 var dateFormat = this._get(inst, 'dateFormat');
9141 var dates = inst.lastVal = inst.input ? inst.input.val() : null;
9142 var date, defaultDate;
9143 date = defaultDate = this._getDefaultDate(inst);
9144 var settings = this._getFormatConfig(inst);
9146 date = this.parseDate(dateFormat, dates, settings) || defaultDate;
9149 dates = (noDefault ? '' : dates);
9151 inst.selectedDay = date.getDate();
9152 inst.drawMonth = inst.selectedMonth = date.getMonth();
9153 inst.drawYear = inst.selectedYear = date.getFullYear();
9154 inst.currentDay = (dates ? date.getDate() : 0);
9155 inst.currentMonth = (dates ? date.getMonth() : 0);
9156 inst.currentYear = (dates ? date.getFullYear() : 0);
9157 this._adjustInstDate(inst);
9160 /* Retrieve the default date shown on opening. */
9161 _getDefaultDate: function(inst) {
9162 return this._restrictMinMax(inst,
9163 this._determineDate(inst, this._get(inst, 'defaultDate'), new Date()));
9166 /* A date may be specified as an exact value or a relative one. */
9167 _determineDate: function(inst, date, defaultDate) {
9168 var offsetNumeric = function(offset) {
9169 var date = new Date();
9170 date.setDate(date.getDate() + offset);
9173 var offsetString = function(offset) {
9175 return $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
9176 offset, $.datepicker._getFormatConfig(inst));
9181 var date = (offset.toLowerCase().match(/^c/) ?
9182 $.datepicker._getDate(inst) : null) || new Date();
9183 var year = date.getFullYear();
9184 var month = date.getMonth();
9185 var day = date.getDate();
9186 var pattern = /([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g;
9187 var matches = pattern.exec(offset);
9189 switch (matches[2] || 'd') {
9190 case 'd' : case 'D' :
9191 day += parseInt(matches[1],10); break;
9192 case 'w' : case 'W' :
9193 day += parseInt(matches[1],10) * 7; break;
9194 case 'm' : case 'M' :
9195 month += parseInt(matches[1],10);
9196 day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
9198 case 'y': case 'Y' :
9199 year += parseInt(matches[1],10);
9200 day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
9203 matches = pattern.exec(offset);
9205 return new Date(year, month, day);
9207 date = (date == null ? defaultDate : (typeof date == 'string' ? offsetString(date) :
9208 (typeof date == 'number' ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : date)));
9209 date = (date && date.toString() == 'Invalid Date' ? defaultDate : date);
9214 date.setMilliseconds(0);
9216 return this._daylightSavingAdjust(date);
9219 /* Handle switch to/from daylight saving.
9220 Hours may be non-zero on daylight saving cut-over:
9221 > 12 when midnight changeover, but then cannot generate
9222 midnight datetime, so jump to 1AM, otherwise reset.
9223 @param date (Date) the date to check
9224 @return (Date) the corrected date */
9225 _daylightSavingAdjust: function(date) {
9226 if (!date) return null;
9227 date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
9231 /* Set the date(s) directly. */
9232 _setDate: function(inst, date, noChange) {
9233 var clear = !(date);
9234 var origMonth = inst.selectedMonth;
9235 var origYear = inst.selectedYear;
9236 date = this._restrictMinMax(inst, this._determineDate(inst, date, new Date()));
9237 inst.selectedDay = inst.currentDay = date.getDate();
9238 inst.drawMonth = inst.selectedMonth = inst.currentMonth = date.getMonth();
9239 inst.drawYear = inst.selectedYear = inst.currentYear = date.getFullYear();
9240 if ((origMonth != inst.selectedMonth || origYear != inst.selectedYear) && !noChange)
9241 this._notifyChange(inst);
9242 this._adjustInstDate(inst);
9244 inst.input.val(clear ? '' : this._formatDate(inst));
9248 /* Retrieve the date(s) directly. */
9249 _getDate: function(inst) {
9250 var startDate = (!inst.currentYear || (inst.input && inst.input.val() == '') ? null :
9251 this._daylightSavingAdjust(new Date(
9252 inst.currentYear, inst.currentMonth, inst.currentDay)));
9256 /* Generate the HTML for the current state of the date picker. */
9257 _generateHTML: function(inst) {
9258 var today = new Date();
9259 today = this._daylightSavingAdjust(
9260 new Date(today.getFullYear(), today.getMonth(), today.getDate())); // clear time
9261 var isRTL = this._get(inst, 'isRTL');
9262 var showButtonPanel = this._get(inst, 'showButtonPanel');
9263 var hideIfNoPrevNext = this._get(inst, 'hideIfNoPrevNext');
9264 var navigationAsDateFormat = this._get(inst, 'navigationAsDateFormat');
9265 var numMonths = this._getNumberOfMonths(inst);
9266 var showCurrentAtPos = this._get(inst, 'showCurrentAtPos');
9267 var stepMonths = this._get(inst, 'stepMonths');
9268 var isMultiMonth = (numMonths[0] != 1 || numMonths[1] != 1);
9269 var currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) :
9270 new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
9271 var minDate = this._getMinMaxDate(inst, 'min');
9272 var maxDate = this._getMinMaxDate(inst, 'max');
9273 var drawMonth = inst.drawMonth - showCurrentAtPos;
9274 var drawYear = inst.drawYear;
9275 if (drawMonth < 0) {
9280 var maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),
9281 maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate()));
9282 maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);
9283 while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {
9285 if (drawMonth < 0) {
9291 inst.drawMonth = drawMonth;
9292 inst.drawYear = drawYear;
9293 var prevText = this._get(inst, 'prevText');
9294 prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText,
9295 this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),
9296 this._getFormatConfig(inst)));
9297 var prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?
9298 '<a class="ui-datepicker-prev ui-corner-all" onclick="DP_jQuery_' + dpuuid +
9299 '.datepicker._adjustDate(\'#' + inst.id + '\', -' + stepMonths + ', \'M\');"' +
9300 ' title="' + prevText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>' :
9301 (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>'));
9302 var nextText = this._get(inst, 'nextText');
9303 nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText,
9304 this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),
9305 this._getFormatConfig(inst)));
9306 var next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?
9307 '<a class="ui-datepicker-next ui-corner-all" onclick="DP_jQuery_' + dpuuid +
9308 '.datepicker._adjustDate(\'#' + inst.id + '\', +' + stepMonths + ', \'M\');"' +
9309 ' title="' + nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>' :
9310 (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>'));
9311 var currentText = this._get(inst, 'currentText');
9312 var gotoDate = (this._get(inst, 'gotoCurrent') && inst.currentDay ? currentDate : today);
9313 currentText = (!navigationAsDateFormat ? currentText :
9314 this.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));
9315 var controls = (!inst.inline ? '<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" onclick="DP_jQuery_' + dpuuid +
9316 '.datepicker._hideDatepicker();">' + this._get(inst, 'closeText') + '</button>' : '');
9317 var buttonPanel = (showButtonPanel) ? '<div class="ui-datepicker-buttonpane ui-widget-content">' + (isRTL ? controls : '') +
9318 (this._isInRange(inst, gotoDate) ? '<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" onclick="DP_jQuery_' + dpuuid +
9319 '.datepicker._gotoToday(\'#' + inst.id + '\');"' +
9320 '>' + currentText + '</button>' : '') + (isRTL ? '' : controls) + '</div>' : '';
9321 var firstDay = parseInt(this._get(inst, 'firstDay'),10);
9322 firstDay = (isNaN(firstDay) ? 0 : firstDay);
9323 var showWeek = this._get(inst, 'showWeek');
9324 var dayNames = this._get(inst, 'dayNames');
9325 var dayNamesShort = this._get(inst, 'dayNamesShort');
9326 var dayNamesMin = this._get(inst, 'dayNamesMin');
9327 var monthNames = this._get(inst, 'monthNames');
9328 var monthNamesShort = this._get(inst, 'monthNamesShort');
9329 var beforeShowDay = this._get(inst, 'beforeShowDay');
9330 var showOtherMonths = this._get(inst, 'showOtherMonths');
9331 var selectOtherMonths = this._get(inst, 'selectOtherMonths');
9332 var calculateWeek = this._get(inst, 'calculateWeek') || this.iso8601Week;
9333 var defaultDate = this._getDefaultDate(inst);
9335 for (var row = 0; row < numMonths[0]; row++) {
9337 for (var col = 0; col < numMonths[1]; col++) {
9338 var selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay));
9339 var cornerClass = ' ui-corner-all';
9342 calender += '<div class="ui-datepicker-group';
9343 if (numMonths[1] > 1)
9345 case 0: calender += ' ui-datepicker-group-first';
9346 cornerClass = ' ui-corner-' + (isRTL ? 'right' : 'left'); break;
9347 case numMonths[1]-1: calender += ' ui-datepicker-group-last';
9348 cornerClass = ' ui-corner-' + (isRTL ? 'left' : 'right'); break;
9349 default: calender += ' ui-datepicker-group-middle'; cornerClass = ''; break;
9353 calender += '<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix' + cornerClass + '">' +
9354 (/all|left/.test(cornerClass) && row == 0 ? (isRTL ? next : prev) : '') +
9355 (/all|right/.test(cornerClass) && row == 0 ? (isRTL ? prev : next) : '') +
9356 this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,
9357 row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers
9358 '</div><table class="ui-datepicker-calendar"><thead>' +
9360 var thead = (showWeek ? '<th class="ui-datepicker-week-col">' + this._get(inst, 'weekHeader') + '</th>' : '');
9361 for (var dow = 0; dow < 7; dow++) { // days of the week
9362 var day = (dow + firstDay) % 7;
9363 thead += '<th' + ((dow + firstDay + 6) % 7 >= 5 ? ' class="ui-datepicker-week-end"' : '') + '>' +
9364 '<span title="' + dayNames[day] + '">' + dayNamesMin[day] + '</span></th>';
9366 calender += thead + '</tr></thead><tbody>';
9367 var daysInMonth = this._getDaysInMonth(drawYear, drawMonth);
9368 if (drawYear == inst.selectedYear && drawMonth == inst.selectedMonth)
9369 inst.selectedDay = Math.min(inst.selectedDay, daysInMonth);
9370 var leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;
9371 var numRows = (isMultiMonth ? 6 : Math.ceil((leadDays + daysInMonth) / 7)); // calculate the number of rows to generate
9372 var printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
9373 for (var dRow = 0; dRow < numRows; dRow++) { // create date picker rows
9375 var tbody = (!showWeek ? '' : '<td class="ui-datepicker-week-col">' +
9376 this._get(inst, 'calculateWeek')(printDate) + '</td>');
9377 for (var dow = 0; dow < 7; dow++) { // create date picker days
9378 var daySettings = (beforeShowDay ?
9379 beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, '']);
9380 var otherMonth = (printDate.getMonth() != drawMonth);
9381 var unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] ||
9382 (minDate && printDate < minDate) || (maxDate && printDate > maxDate);
9383 tbody += '<td class="' +
9384 ((dow + firstDay + 6) % 7 >= 5 ? ' ui-datepicker-week-end' : '') + // highlight weekends
9385 (otherMonth ? ' ui-datepicker-other-month' : '') + // highlight days from other months
9386 ((printDate.getTime() == selectedDate.getTime() && drawMonth == inst.selectedMonth && inst._keyEvent) || // user pressed key
9387 (defaultDate.getTime() == printDate.getTime() && defaultDate.getTime() == selectedDate.getTime()) ?
9388 // or defaultDate is current printedDate and defaultDate is selectedDate
9389 ' ' + this._dayOverClass : '') + // highlight selected day
9390 (unselectable ? ' ' + this._unselectableClass + ' ui-state-disabled': '') + // highlight unselectable days
9391 (otherMonth && !showOtherMonths ? '' : ' ' + daySettings[1] + // highlight custom dates
9392 (printDate.getTime() == currentDate.getTime() ? ' ' + this._currentClass : '') + // highlight selected day
9393 (printDate.getTime() == today.getTime() ? ' ui-datepicker-today' : '')) + '"' + // highlight today (if different)
9394 ((!otherMonth || showOtherMonths) && daySettings[2] ? ' title="' + daySettings[2] + '"' : '') + // cell title
9395 (unselectable ? '' : ' onclick="DP_jQuery_' + dpuuid + '.datepicker._selectDay(\'#' +
9396 inst.id + '\',' + printDate.getMonth() + ',' + printDate.getFullYear() + ', this);return false;"') + '>' + // actions
9397 (otherMonth && !showOtherMonths ? ' ' : // display for other months
9398 (unselectable ? '<span class="ui-state-default">' + printDate.getDate() + '</span>' : '<a class="ui-state-default' +
9399 (printDate.getTime() == today.getTime() ? ' ui-state-highlight' : '') +
9400 (printDate.getTime() == selectedDate.getTime() ? ' ui-state-active' : '') + // highlight selected day
9401 (otherMonth ? ' ui-priority-secondary' : '') + // distinguish dates from other months
9402 '" href="#">' + printDate.getDate() + '</a>')) + '</td>'; // display selectable date
9403 printDate.setDate(printDate.getDate() + 1);
9404 printDate = this._daylightSavingAdjust(printDate);
9406 calender += tbody + '</tr>';
9409 if (drawMonth > 11) {
9413 calender += '</tbody></table>' + (isMultiMonth ? '</div>' +
9414 ((numMonths[0] > 0 && col == numMonths[1]-1) ? '<div class="ui-datepicker-row-break"></div>' : '') : '');
9419 html += buttonPanel + ($.browser.msie && parseInt($.browser.version,10) < 7 && !inst.inline ?
9420 '<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>' : '');
9421 inst._keyEvent = false;
9425 /* Generate the month and year header. */
9426 _generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate,
9427 secondary, monthNames, monthNamesShort) {
9428 var changeMonth = this._get(inst, 'changeMonth');
9429 var changeYear = this._get(inst, 'changeYear');
9430 var showMonthAfterYear = this._get(inst, 'showMonthAfterYear');
9431 var html = '<div class="ui-datepicker-title">';
9434 if (secondary || !changeMonth)
9435 monthHtml += '<span class="ui-datepicker-month">' + monthNames[drawMonth] + '</span>';
9437 var inMinYear = (minDate && minDate.getFullYear() == drawYear);
9438 var inMaxYear = (maxDate && maxDate.getFullYear() == drawYear);
9439 monthHtml += '<select class="ui-datepicker-month" ' +
9440 'onchange="DP_jQuery_' + dpuuid + '.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'M\');" ' +
9441 'onclick="DP_jQuery_' + dpuuid + '.datepicker._clickMonthYear(\'#' + inst.id + '\');"' +
9443 for (var month = 0; month < 12; month++) {
9444 if ((!inMinYear || month >= minDate.getMonth()) &&
9445 (!inMaxYear || month <= maxDate.getMonth()))
9446 monthHtml += '<option value="' + month + '"' +
9447 (month == drawMonth ? ' selected="selected"' : '') +
9448 '>' + monthNamesShort[month] + '</option>';
9450 monthHtml += '</select>';
9452 if (!showMonthAfterYear)
9453 html += monthHtml + (secondary || !(changeMonth && changeYear) ? ' ' : '');
9455 if (secondary || !changeYear)
9456 html += '<span class="ui-datepicker-year">' + drawYear + '</span>';
9458 // determine range of years to display
9459 var years = this._get(inst, 'yearRange').split(':');
9460 var thisYear = new Date().getFullYear();
9461 var determineYear = function(value) {
9462 var year = (value.match(/c[+-].*/) ? drawYear + parseInt(value.substring(1), 10) :
9463 (value.match(/[+-].*/) ? thisYear + parseInt(value, 10) :
9464 parseInt(value, 10)));
9465 return (isNaN(year) ? thisYear : year);
9467 var year = determineYear(years[0]);
9468 var endYear = Math.max(year, determineYear(years[1] || ''));
9469 year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
9470 endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
9471 html += '<select class="ui-datepicker-year" ' +
9472 'onchange="DP_jQuery_' + dpuuid + '.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'Y\');" ' +
9473 'onclick="DP_jQuery_' + dpuuid + '.datepicker._clickMonthYear(\'#' + inst.id + '\');"' +
9475 for (; year <= endYear; year++) {
9476 html += '<option value="' + year + '"' +
9477 (year == drawYear ? ' selected="selected"' : '') +
9478 '>' + year + '</option>';
9480 html += '</select>';
9482 html += this._get(inst, 'yearSuffix');
9483 if (showMonthAfterYear)
9484 html += (secondary || !(changeMonth && changeYear) ? ' ' : '') + monthHtml;
9485 html += '</div>'; // Close datepicker_header
9489 /* Adjust one of the date sub-fields. */
9490 _adjustInstDate: function(inst, offset, period) {
9491 var year = inst.drawYear + (period == 'Y' ? offset : 0);
9492 var month = inst.drawMonth + (period == 'M' ? offset : 0);
9493 var day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) +
9494 (period == 'D' ? offset : 0);
9495 var date = this._restrictMinMax(inst,
9496 this._daylightSavingAdjust(new Date(year, month, day)));
9497 inst.selectedDay = date.getDate();
9498 inst.drawMonth = inst.selectedMonth = date.getMonth();
9499 inst.drawYear = inst.selectedYear = date.getFullYear();
9500 if (period == 'M' || period == 'Y')
9501 this._notifyChange(inst);
9504 /* Ensure a date is within any min/max bounds. */
9505 _restrictMinMax: function(inst, date) {
9506 var minDate = this._getMinMaxDate(inst, 'min');
9507 var maxDate = this._getMinMaxDate(inst, 'max');
9508 date = (minDate && date < minDate ? minDate : date);
9509 date = (maxDate && date > maxDate ? maxDate : date);
9513 /* Notify change of month/year. */
9514 _notifyChange: function(inst) {
9515 var onChange = this._get(inst, 'onChangeMonthYear');
9517 onChange.apply((inst.input ? inst.input[0] : null),
9518 [inst.selectedYear, inst.selectedMonth + 1, inst]);
9521 /* Determine the number of months to show. */
9522 _getNumberOfMonths: function(inst) {
9523 var numMonths = this._get(inst, 'numberOfMonths');
9524 return (numMonths == null ? [1, 1] : (typeof numMonths == 'number' ? [1, numMonths] : numMonths));
9527 /* Determine the current maximum date - ensure no time components are set. */
9528 _getMinMaxDate: function(inst, minMax) {
9529 return this._determineDate(inst, this._get(inst, minMax + 'Date'), null);
9532 /* Find the number of days in a given month. */
9533 _getDaysInMonth: function(year, month) {
9534 return 32 - new Date(year, month, 32).getDate();
9537 /* Find the day of the week of the first of a month. */
9538 _getFirstDayOfMonth: function(year, month) {
9539 return new Date(year, month, 1).getDay();
9542 /* Determines if we should allow a "next/prev" month display change. */
9543 _canAdjustMonth: function(inst, offset, curYear, curMonth) {
9544 var numMonths = this._getNumberOfMonths(inst);
9545 var date = this._daylightSavingAdjust(new Date(curYear,
9546 curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1));
9548 date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
9549 return this._isInRange(inst, date);
9552 /* Is the given date in the accepted range? */
9553 _isInRange: function(inst, date) {
9554 var minDate = this._getMinMaxDate(inst, 'min');
9555 var maxDate = this._getMinMaxDate(inst, 'max');
9556 return ((!minDate || date.getTime() >= minDate.getTime()) &&
9557 (!maxDate || date.getTime() <= maxDate.getTime()));
9560 /* Provide the configuration settings for formatting/parsing. */
9561 _getFormatConfig: function(inst) {
9562 var shortYearCutoff = this._get(inst, 'shortYearCutoff');
9563 shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff :
9564 new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
9565 return {shortYearCutoff: shortYearCutoff,
9566 dayNamesShort: this._get(inst, 'dayNamesShort'), dayNames: this._get(inst, 'dayNames'),
9567 monthNamesShort: this._get(inst, 'monthNamesShort'), monthNames: this._get(inst, 'monthNames')};
9570 /* Format the given date for display. */
9571 _formatDate: function(inst, day, month, year) {
9573 inst.currentDay = inst.selectedDay;
9574 inst.currentMonth = inst.selectedMonth;
9575 inst.currentYear = inst.selectedYear;
9577 var date = (day ? (typeof day == 'object' ? day :
9578 this._daylightSavingAdjust(new Date(year, month, day))) :
9579 this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
9580 return this.formatDate(this._get(inst, 'dateFormat'), date, this._getFormatConfig(inst));
9584 /* jQuery extend now ignores nulls! */
9585 function extendRemove(target, props) {
9586 $.extend(target, props);
9587 for (var name in props)
9588 if (props[name] == null || props[name] == undefined)
9589 target[name] = props[name];
9593 /* Determine whether an object is an array. */
9594 function isArray(a) {
9595 return (a && (($.browser.safari && typeof a == 'object' && a.length) ||
9596 (a.constructor && a.constructor.toString().match(/\Array\(\)/))));
9599 /* Invoke the datepicker functionality.
9600 @param options string - a command, optionally followed by additional parameters or
9601 Object - settings for attaching new datepicker functionality
9602 @return jQuery object */
9603 $.fn.datepicker = function(options){
9605 /* Initialise the date picker. */
9606 if (!$.datepicker.initialized) {
9607 $(document).mousedown($.datepicker._checkExternalClick).
9608 find('body').append($.datepicker.dpDiv);
9609 $.datepicker.initialized = true;
9612 var otherArgs = Array.prototype.slice.call(arguments, 1);
9613 if (typeof options == 'string' && (options == 'isDisabled' || options == 'getDate' || options == 'widget'))
9614 return $.datepicker['_' + options + 'Datepicker'].
9615 apply($.datepicker, [this[0]].concat(otherArgs));
9616 if (options == 'option' && arguments.length == 2 && typeof arguments[1] == 'string')
9617 return $.datepicker['_' + options + 'Datepicker'].
9618 apply($.datepicker, [this[0]].concat(otherArgs));
9619 return this.each(function() {
9620 typeof options == 'string' ?
9621 $.datepicker['_' + options + 'Datepicker'].
9622 apply($.datepicker, [this].concat(otherArgs)) :
9623 $.datepicker._attachDatepicker(this, options);
9627 $.datepicker = new Datepicker(); // singleton instance
9628 $.datepicker.initialized = false;
9629 $.datepicker.uuid = new Date().getTime();
9630 $.datepicker.version = "1.8.4";
9632 // Workaround for #4055
9633 // Add another global to avoid noConflict issues with inline event handlers
9634 window['DP_jQuery_' + dpuuid] = $;
9638 * jQuery UI Progressbar 1.8.4
9640 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
9641 * Dual licensed under the MIT or GPL Version 2 licenses.
9642 * http://jquery.org/license
9644 * http://docs.jquery.com/UI/Progressbar
9648 * jquery.ui.widget.js
9650 (function( $, undefined ) {
9652 $.widget( "ui.progressbar", {
9660 _create: function() {
9662 .addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
9664 role: "progressbar",
9665 "aria-valuemin": this.min,
9666 "aria-valuemax": this.max,
9667 "aria-valuenow": this._value()
9670 this.valueDiv = $( "<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>" )
9671 .appendTo( this.element );
9673 this._refreshValue();
9676 destroy: function() {
9678 .removeClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
9679 .removeAttr( "role" )
9680 .removeAttr( "aria-valuemin" )
9681 .removeAttr( "aria-valuemax" )
9682 .removeAttr( "aria-valuenow" );
9684 this.valueDiv.remove();
9686 $.Widget.prototype.destroy.apply( this, arguments );
9689 value: function( newValue ) {
9690 if ( newValue === undefined ) {
9691 return this._value();
9694 this._setOption( "value", newValue );
9698 _setOption: function( key, value ) {
9699 if ( key === "value" ) {
9700 this.options.value = value;
9701 this._refreshValue();
9702 this._trigger( "change" );
9705 $.Widget.prototype._setOption.apply( this, arguments );
9708 _value: function() {
9709 var val = this.options.value;
9710 // normalize invalid value
9711 if ( typeof val !== "number" ) {
9714 return Math.min( this.max, Math.max( this.min, val ) );
9717 _refreshValue: function() {
9718 var value = this.value();
9720 .toggleClass( "ui-corner-right", value === this.max )
9721 .width( value + "%" );
9722 this.element.attr( "aria-valuenow", value );
9726 $.extend( $.ui.progressbar, {
9732 * jQuery UI Effects 1.8.4
9734 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
9735 * Dual licensed under the MIT or GPL Version 2 licenses.
9736 * http://jquery.org/license
9738 * http://docs.jquery.com/UI/Effects/
9740 ;jQuery.effects || (function($, undefined) {
9746 /******************************************************************************/
9747 /****************************** COLOR ANIMATIONS ******************************/
9748 /******************************************************************************/
9750 // override the animation for color styles
9751 $.each(['backgroundColor', 'borderBottomColor', 'borderLeftColor',
9752 'borderRightColor', 'borderTopColor', 'color', 'outlineColor'],
9754 $.fx.step[attr] = function(fx) {
9755 if (!fx.colorInit) {
9756 fx.start = getColor(fx.elem, attr);
9757 fx.end = getRGB(fx.end);
9758 fx.colorInit = true;
9761 fx.elem.style[attr] = 'rgb(' +
9762 Math.max(Math.min(parseInt((fx.pos * (fx.end[0] - fx.start[0])) + fx.start[0], 10), 255), 0) + ',' +
9763 Math.max(Math.min(parseInt((fx.pos * (fx.end[1] - fx.start[1])) + fx.start[1], 10), 255), 0) + ',' +
9764 Math.max(Math.min(parseInt((fx.pos * (fx.end[2] - fx.start[2])) + fx.start[2], 10), 255), 0) + ')';
9768 // Color Conversion functions from highlightFade
9769 // By Blair Mitchelmore
9770 // http://jquery.offput.ca/highlightFade/
9772 // Parse strings looking for color tuples [255,255,255]
9773 function getRGB(color) {
9776 // Check if we're already dealing with an array of colors
9777 if ( color && color.constructor == Array && color.length == 3 )
9780 // Look for rgb(num,num,num)
9781 if (result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(color))
9782 return [parseInt(result[1],10), parseInt(result[2],10), parseInt(result[3],10)];
9784 // Look for rgb(num%,num%,num%)
9785 if (result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(color))
9786 return [parseFloat(result[1])*2.55, parseFloat(result[2])*2.55, parseFloat(result[3])*2.55];
9789 if (result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(color))
9790 return [parseInt(result[1],16), parseInt(result[2],16), parseInt(result[3],16)];
9793 if (result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(color))
9794 return [parseInt(result[1]+result[1],16), parseInt(result[2]+result[2],16), parseInt(result[3]+result[3],16)];
9796 // Look for rgba(0, 0, 0, 0) == transparent in Safari 3
9797 if (result = /rgba\(0, 0, 0, 0\)/.exec(color))
9798 return colors['transparent'];
9800 // Otherwise, we're most likely dealing with a named color
9801 return colors[$.trim(color).toLowerCase()];
9804 function getColor(elem, attr) {
9808 color = $.curCSS(elem, attr);
9810 // Keep going until we find an element that has color, or we hit the body
9811 if ( color != '' && color != 'transparent' || $.nodeName(elem, "body") )
9814 attr = "backgroundColor";
9815 } while ( elem = elem.parentNode );
9817 return getRGB(color);
9820 // Some named colors to work with
9821 // From Interface by Stefan Petre
9822 // http://interface.eyecon.ro/
9826 azure:[240,255,255],
9827 beige:[245,245,220],
9833 darkcyan:[0,139,139],
9834 darkgrey:[169,169,169],
9835 darkgreen:[0,100,0],
9836 darkkhaki:[189,183,107],
9837 darkmagenta:[139,0,139],
9838 darkolivegreen:[85,107,47],
9839 darkorange:[255,140,0],
9840 darkorchid:[153,50,204],
9842 darksalmon:[233,150,122],
9843 darkviolet:[148,0,211],
9844 fuchsia:[255,0,255],
9848 khaki:[240,230,140],
9849 lightblue:[173,216,230],
9850 lightcyan:[224,255,255],
9851 lightgreen:[144,238,144],
9852 lightgrey:[211,211,211],
9853 lightpink:[255,182,193],
9854 lightyellow:[255,255,224],
9856 magenta:[255,0,255],
9865 silver:[192,192,192],
9866 white:[255,255,255],
9868 transparent: [255,255,255]
9873 /******************************************************************************/
9874 /****************************** CLASS ANIMATIONS ******************************/
9875 /******************************************************************************/
9877 var classAnimationActions = ['add', 'remove', 'toggle'],
9890 function getElementStyles() {
9891 var style = document.defaultView
9892 ? document.defaultView.getComputedStyle(this, null)
9893 : this.currentStyle,
9898 // webkit enumerates style porperties
9899 if (style && style.length && style[0] && style[style[0]]) {
9900 var len = style.length;
9903 if (typeof style[key] == 'string') {
9904 camelCase = key.replace(/\-(\w)/g, function(all, letter){
9905 return letter.toUpperCase();
9907 newStyle[camelCase] = style[key];
9911 for (key in style) {
9912 if (typeof style[key] === 'string') {
9913 newStyle[key] = style[key];
9921 function filterStyles(styles) {
9923 for (name in styles) {
9924 value = styles[name];
9926 // ignore null and undefined values
9928 // ignore functions (when does this occur?)
9929 $.isFunction(value) ||
9930 // shorthand styles that need to be expanded
9931 name in shorthandStyles ||
9932 // ignore scrollbars (break in IE)
9933 (/scrollbar/).test(name) ||
9935 // only colors or values that can be converted to numbers
9936 (!(/color/i).test(name) && isNaN(parseFloat(value)))
9938 delete styles[name];
9945 function styleDifference(oldStyle, newStyle) {
9946 var diff = { _: 0 }, // http://dev.jquery.com/ticket/5459
9949 for (name in newStyle) {
9950 if (oldStyle[name] != newStyle[name]) {
9951 diff[name] = newStyle[name];
9958 $.effects.animateClass = function(value, duration, easing, callback) {
9959 if ($.isFunction(easing)) {
9964 return this.each(function() {
9967 originalStyleAttr = that.attr('style') || ' ',
9968 originalStyle = filterStyles(getElementStyles.call(this)),
9970 className = that.attr('className');
9972 $.each(classAnimationActions, function(i, action) {
9973 if (value[action]) {
9974 that[action + 'Class'](value[action]);
9977 newStyle = filterStyles(getElementStyles.call(this));
9978 that.attr('className', className);
9980 that.animate(styleDifference(originalStyle, newStyle), duration, easing, function() {
9981 $.each(classAnimationActions, function(i, action) {
9982 if (value[action]) { that[action + 'Class'](value[action]); }
9984 // work around bug in IE by clearing the cssText before setting it
9985 if (typeof that.attr('style') == 'object') {
9986 that.attr('style').cssText = '';
9987 that.attr('style').cssText = originalStyleAttr;
9989 that.attr('style', originalStyleAttr);
9991 if (callback) { callback.apply(this, arguments); }
9997 _addClass: $.fn.addClass,
9998 addClass: function(classNames, speed, easing, callback) {
9999 return speed ? $.effects.animateClass.apply(this, [{ add: classNames },speed,easing,callback]) : this._addClass(classNames);
10002 _removeClass: $.fn.removeClass,
10003 removeClass: function(classNames,speed,easing,callback) {
10004 return speed ? $.effects.animateClass.apply(this, [{ remove: classNames },speed,easing,callback]) : this._removeClass(classNames);
10007 _toggleClass: $.fn.toggleClass,
10008 toggleClass: function(classNames, force, speed, easing, callback) {
10009 if ( typeof force == "boolean" || force === undefined ) {
10011 // without speed parameter;
10012 return this._toggleClass(classNames, force);
10014 return $.effects.animateClass.apply(this, [(force?{add:classNames}:{remove:classNames}),speed,easing,callback]);
10017 // without switch parameter;
10018 return $.effects.animateClass.apply(this, [{ toggle: classNames },force,speed,easing]);
10022 switchClass: function(remove,add,speed,easing,callback) {
10023 return $.effects.animateClass.apply(this, [{ add: add, remove: remove },speed,easing,callback]);
10029 /******************************************************************************/
10030 /*********************************** EFFECTS **********************************/
10031 /******************************************************************************/
10033 $.extend($.effects, {
10036 // Saves a set of properties in a data storage
10037 save: function(element, set) {
10038 for(var i=0; i < set.length; i++) {
10039 if(set[i] !== null) element.data("ec.storage."+set[i], element[0].style[set[i]]);
10043 // Restores a set of previously saved properties from a data storage
10044 restore: function(element, set) {
10045 for(var i=0; i < set.length; i++) {
10046 if(set[i] !== null) element.css(set[i], element.data("ec.storage."+set[i]));
10050 setMode: function(el, mode) {
10051 if (mode == 'toggle') mode = el.is(':hidden') ? 'show' : 'hide'; // Set for toggle
10055 getBaseline: function(origin, original) { // Translates a [top,left] array into a baseline value
10056 // this should be a little more flexible in the future to handle a string & hash
10058 switch (origin[0]) {
10059 case 'top': y = 0; break;
10060 case 'middle': y = 0.5; break;
10061 case 'bottom': y = 1; break;
10062 default: y = origin[0] / original.height;
10064 switch (origin[1]) {
10065 case 'left': x = 0; break;
10066 case 'center': x = 0.5; break;
10067 case 'right': x = 1; break;
10068 default: x = origin[1] / original.width;
10070 return {x: x, y: y};
10073 // Wraps the element around a wrapper that copies position properties
10074 createWrapper: function(element) {
10076 // if the element is already wrapped, return it
10077 if (element.parent().is('.ui-effects-wrapper')) {
10078 return element.parent();
10081 // wrap the element
10083 width: element.outerWidth(true),
10084 height: element.outerHeight(true),
10085 'float': element.css('float')
10087 wrapper = $('<div></div>')
10088 .addClass('ui-effects-wrapper')
10091 background: 'transparent',
10097 element.wrap(wrapper);
10098 wrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually loose the reference to the wrapped element
10100 // transfer positioning properties to the wrapper
10101 if (element.css('position') == 'static') {
10102 wrapper.css({ position: 'relative' });
10103 element.css({ position: 'relative' });
10106 position: element.css('position'),
10107 zIndex: element.css('z-index')
10109 $.each(['top', 'left', 'bottom', 'right'], function(i, pos) {
10110 props[pos] = element.css(pos);
10111 if (isNaN(parseInt(props[pos], 10))) {
10112 props[pos] = 'auto';
10115 element.css({position: 'relative', top: 0, left: 0 });
10118 return wrapper.css(props).show();
10121 removeWrapper: function(element) {
10122 if (element.parent().is('.ui-effects-wrapper'))
10123 return element.parent().replaceWith(element);
10127 setTransition: function(element, list, factor, value) {
10128 value = value || {};
10129 $.each(list, function(i, x){
10130 unit = element.cssUnit(x);
10131 if (unit[0] > 0) value[x] = unit[0] * factor + unit[1];
10138 function _normalizeArguments(effect, options, speed, callback) {
10139 // shift params for method overloading
10140 if (typeof effect == 'object') {
10141 callback = options;
10144 effect = options.effect;
10146 if ($.isFunction(options)) {
10147 callback = options;
10151 if (typeof options == 'number' || $.fx.speeds[options]) {
10156 if ($.isFunction(speed)) {
10161 options = options || {};
10163 speed = speed || options.duration;
10164 speed = $.fx.off ? 0 : typeof speed == 'number'
10165 ? speed : $.fx.speeds[speed] || $.fx.speeds._default;
10167 callback = callback || options.complete;
10169 return [effect, options, speed, callback];
10173 effect: function(effect, options, speed, callback) {
10174 var args = _normalizeArguments.apply(this, arguments),
10175 // TODO: make effects takes actual parameters instead of a hash
10181 effectMethod = $.effects[effect];
10183 return effectMethod && !$.fx.off ? effectMethod.call(this, args2) : this;
10187 show: function(speed) {
10188 if (!speed || typeof speed == 'number' || $.fx.speeds[speed]) {
10189 return this._show.apply(this, arguments);
10191 var args = _normalizeArguments.apply(this, arguments);
10192 args[1].mode = 'show';
10193 return this.effect.apply(this, args);
10198 hide: function(speed) {
10199 if (!speed || typeof speed == 'number' || $.fx.speeds[speed]) {
10200 return this._hide.apply(this, arguments);
10202 var args = _normalizeArguments.apply(this, arguments);
10203 args[1].mode = 'hide';
10204 return this.effect.apply(this, args);
10208 // jQuery core overloads toggle and create _toggle
10209 __toggle: $.fn.toggle,
10210 toggle: function(speed) {
10211 if (!speed || typeof speed == 'number' || $.fx.speeds[speed] ||
10212 typeof speed == 'boolean' || $.isFunction(speed)) {
10213 return this.__toggle.apply(this, arguments);
10215 var args = _normalizeArguments.apply(this, arguments);
10216 args[1].mode = 'toggle';
10217 return this.effect.apply(this, args);
10221 // helper functions
10222 cssUnit: function(key) {
10223 var style = this.css(key), val = [];
10224 $.each( ['em','px','%','pt'], function(i, unit){
10225 if(style.indexOf(unit) > 0)
10226 val = [parseFloat(style), unit];
10234 /******************************************************************************/
10235 /*********************************** EASING ***********************************/
10236 /******************************************************************************/
10239 * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
10241 * Uses the built in easing capabilities added In jQuery 1.1
10242 * to offer multiple easing options
10244 * TERMS OF USE - jQuery Easing
10246 * Open source under the BSD License.
10248 * Copyright 2008 George McGinley Smith
10249 * All rights reserved.
10251 * Redistribution and use in source and binary forms, with or without modification,
10252 * are permitted provided that the following conditions are met:
10254 * Redistributions of source code must retain the above copyright notice, this list of
10255 * conditions and the following disclaimer.
10256 * Redistributions in binary form must reproduce the above copyright notice, this list
10257 * of conditions and the following disclaimer in the documentation and/or other materials
10258 * provided with the distribution.
10260 * Neither the name of the author nor the names of contributors may be used to endorse
10261 * or promote products derived from this software without specific prior written permission.
10263 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
10264 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
10265 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
10266 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
10267 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
10268 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
10269 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
10270 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
10271 * OF THE POSSIBILITY OF SUCH DAMAGE.
10275 // t: current time, b: begInnIng value, c: change In value, d: duration
10276 $.easing.jswing = $.easing.swing;
10280 def: 'easeOutQuad',
10281 swing: function (x, t, b, c, d) {
10282 //alert($.easing.default);
10283 return $.easing[$.easing.def](x, t, b, c, d);
10285 easeInQuad: function (x, t, b, c, d) {
10286 return c*(t/=d)*t + b;
10288 easeOutQuad: function (x, t, b, c, d) {
10289 return -c *(t/=d)*(t-2) + b;
10291 easeInOutQuad: function (x, t, b, c, d) {
10292 if ((t/=d/2) < 1) return c/2*t*t + b;
10293 return -c/2 * ((--t)*(t-2) - 1) + b;
10295 easeInCubic: function (x, t, b, c, d) {
10296 return c*(t/=d)*t*t + b;
10298 easeOutCubic: function (x, t, b, c, d) {
10299 return c*((t=t/d-1)*t*t + 1) + b;
10301 easeInOutCubic: function (x, t, b, c, d) {
10302 if ((t/=d/2) < 1) return c/2*t*t*t + b;
10303 return c/2*((t-=2)*t*t + 2) + b;
10305 easeInQuart: function (x, t, b, c, d) {
10306 return c*(t/=d)*t*t*t + b;
10308 easeOutQuart: function (x, t, b, c, d) {
10309 return -c * ((t=t/d-1)*t*t*t - 1) + b;
10311 easeInOutQuart: function (x, t, b, c, d) {
10312 if ((t/=d/2) < 1) return c/2*t*t*t*t + b;
10313 return -c/2 * ((t-=2)*t*t*t - 2) + b;
10315 easeInQuint: function (x, t, b, c, d) {
10316 return c*(t/=d)*t*t*t*t + b;
10318 easeOutQuint: function (x, t, b, c, d) {
10319 return c*((t=t/d-1)*t*t*t*t + 1) + b;
10321 easeInOutQuint: function (x, t, b, c, d) {
10322 if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b;
10323 return c/2*((t-=2)*t*t*t*t + 2) + b;
10325 easeInSine: function (x, t, b, c, d) {
10326 return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
10328 easeOutSine: function (x, t, b, c, d) {
10329 return c * Math.sin(t/d * (Math.PI/2)) + b;
10331 easeInOutSine: function (x, t, b, c, d) {
10332 return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
10334 easeInExpo: function (x, t, b, c, d) {
10335 return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
10337 easeOutExpo: function (x, t, b, c, d) {
10338 return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
10340 easeInOutExpo: function (x, t, b, c, d) {
10341 if (t==0) return b;
10342 if (t==d) return b+c;
10343 if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
10344 return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
10346 easeInCirc: function (x, t, b, c, d) {
10347 return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
10349 easeOutCirc: function (x, t, b, c, d) {
10350 return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
10352 easeInOutCirc: function (x, t, b, c, d) {
10353 if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
10354 return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
10356 easeInElastic: function (x, t, b, c, d) {
10357 var s=1.70158;var p=0;var a=c;
10358 if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3;
10359 if (a < Math.abs(c)) { a=c; var s=p/4; }
10360 else var s = p/(2*Math.PI) * Math.asin (c/a);
10361 return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
10363 easeOutElastic: function (x, t, b, c, d) {
10364 var s=1.70158;var p=0;var a=c;
10365 if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3;
10366 if (a < Math.abs(c)) { a=c; var s=p/4; }
10367 else var s = p/(2*Math.PI) * Math.asin (c/a);
10368 return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
10370 easeInOutElastic: function (x, t, b, c, d) {
10371 var s=1.70158;var p=0;var a=c;
10372 if (t==0) return b; if ((t/=d/2)==2) return b+c; if (!p) p=d*(.3*1.5);
10373 if (a < Math.abs(c)) { a=c; var s=p/4; }
10374 else var s = p/(2*Math.PI) * Math.asin (c/a);
10375 if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
10376 return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
10378 easeInBack: function (x, t, b, c, d, s) {
10379 if (s == undefined) s = 1.70158;
10380 return c*(t/=d)*t*((s+1)*t - s) + b;
10382 easeOutBack: function (x, t, b, c, d, s) {
10383 if (s == undefined) s = 1.70158;
10384 return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
10386 easeInOutBack: function (x, t, b, c, d, s) {
10387 if (s == undefined) s = 1.70158;
10388 if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
10389 return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
10391 easeInBounce: function (x, t, b, c, d) {
10392 return c - $.easing.easeOutBounce (x, d-t, 0, c, d) + b;
10394 easeOutBounce: function (x, t, b, c, d) {
10395 if ((t/=d) < (1/2.75)) {
10396 return c*(7.5625*t*t) + b;
10397 } else if (t < (2/2.75)) {
10398 return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
10399 } else if (t < (2.5/2.75)) {
10400 return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
10402 return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
10405 easeInOutBounce: function (x, t, b, c, d) {
10406 if (t < d/2) return $.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b;
10407 return $.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b;
10413 * TERMS OF USE - EASING EQUATIONS
10415 * Open source under the BSD License.
10417 * Copyright 2001 Robert Penner
10418 * All rights reserved.
10420 * Redistribution and use in source and binary forms, with or without modification,
10421 * are permitted provided that the following conditions are met:
10423 * Redistributions of source code must retain the above copyright notice, this list of
10424 * conditions and the following disclaimer.
10425 * Redistributions in binary form must reproduce the above copyright notice, this list
10426 * of conditions and the following disclaimer in the documentation and/or other materials
10427 * provided with the distribution.
10429 * Neither the name of the author nor the names of contributors may be used to endorse
10430 * or promote products derived from this software without specific prior written permission.
10432 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
10433 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
10434 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
10435 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
10436 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
10437 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
10438 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
10439 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
10440 * OF THE POSSIBILITY OF SUCH DAMAGE.
10446 * jQuery UI Effects Blind 1.8.4
10448 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
10449 * Dual licensed under the MIT or GPL Version 2 licenses.
10450 * http://jquery.org/license
10452 * http://docs.jquery.com/UI/Effects/Blind
10455 * jquery.effects.core.js
10457 (function( $, undefined ) {
10459 $.effects.blind = function(o) {
10461 return this.queue(function() {
10464 var el = $(this), props = ['position','top','left'];
10467 var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
10468 var direction = o.options.direction || 'vertical'; // Default direction
10471 $.effects.save(el, props); el.show(); // Save & Show
10472 var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
10473 var ref = (direction == 'vertical') ? 'height' : 'width';
10474 var distance = (direction == 'vertical') ? wrapper.height() : wrapper.width();
10475 if(mode == 'show') wrapper.css(ref, 0); // Shift
10478 var animation = {};
10479 animation[ref] = mode == 'show' ? distance : 0;
10482 wrapper.animate(animation, o.duration, o.options.easing, function() {
10483 if(mode == 'hide') el.hide(); // Hide
10484 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
10485 if(o.callback) o.callback.apply(el[0], arguments); // Callback
10495 * jQuery UI Effects Bounce 1.8.4
10497 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
10498 * Dual licensed under the MIT or GPL Version 2 licenses.
10499 * http://jquery.org/license
10501 * http://docs.jquery.com/UI/Effects/Bounce
10504 * jquery.effects.core.js
10506 (function( $, undefined ) {
10508 $.effects.bounce = function(o) {
10510 return this.queue(function() {
10513 var el = $(this), props = ['position','top','left'];
10516 var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
10517 var direction = o.options.direction || 'up'; // Default direction
10518 var distance = o.options.distance || 20; // Default distance
10519 var times = o.options.times || 5; // Default # of times
10520 var speed = o.duration || 250; // Default speed per bounce
10521 if (/show|hide/.test(mode)) props.push('opacity'); // Avoid touching opacity to prevent clearType and PNG issues in IE
10524 $.effects.save(el, props); el.show(); // Save & Show
10525 $.effects.createWrapper(el); // Create Wrapper
10526 var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
10527 var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
10528 var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) / 3 : el.outerWidth({margin:true}) / 3);
10529 if (mode == 'show') el.css('opacity', 0).css(ref, motion == 'pos' ? -distance : distance); // Shift
10530 if (mode == 'hide') distance = distance / (times * 2);
10531 if (mode != 'hide') times--;
10534 if (mode == 'show') { // Show Bounce
10535 var animation = {opacity: 1};
10536 animation[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
10537 el.animate(animation, speed / 2, o.options.easing);
10538 distance = distance / 2;
10541 for (var i = 0; i < times; i++) { // Bounces
10542 var animation1 = {}, animation2 = {};
10543 animation1[ref] = (motion == 'pos' ? '-=' : '+=') + distance;
10544 animation2[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
10545 el.animate(animation1, speed / 2, o.options.easing).animate(animation2, speed / 2, o.options.easing);
10546 distance = (mode == 'hide') ? distance * 2 : distance / 2;
10548 if (mode == 'hide') { // Last Bounce
10549 var animation = {opacity: 0};
10550 animation[ref] = (motion == 'pos' ? '-=' : '+=') + distance;
10551 el.animate(animation, speed / 2, o.options.easing, function(){
10553 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
10554 if(o.callback) o.callback.apply(this, arguments); // Callback
10557 var animation1 = {}, animation2 = {};
10558 animation1[ref] = (motion == 'pos' ? '-=' : '+=') + distance;
10559 animation2[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
10560 el.animate(animation1, speed / 2, o.options.easing).animate(animation2, speed / 2, o.options.easing, function(){
10561 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
10562 if(o.callback) o.callback.apply(this, arguments); // Callback
10565 el.queue('fx', function() { el.dequeue(); });
10573 * jQuery UI Effects Clip 1.8.4
10575 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
10576 * Dual licensed under the MIT or GPL Version 2 licenses.
10577 * http://jquery.org/license
10579 * http://docs.jquery.com/UI/Effects/Clip
10582 * jquery.effects.core.js
10584 (function( $, undefined ) {
10586 $.effects.clip = function(o) {
10588 return this.queue(function() {
10591 var el = $(this), props = ['position','top','left','height','width'];
10594 var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
10595 var direction = o.options.direction || 'vertical'; // Default direction
10598 $.effects.save(el, props); el.show(); // Save & Show
10599 var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
10600 var animate = el[0].tagName == 'IMG' ? wrapper : el;
10602 size: (direction == 'vertical') ? 'height' : 'width',
10603 position: (direction == 'vertical') ? 'top' : 'left'
10605 var distance = (direction == 'vertical') ? animate.height() : animate.width();
10606 if(mode == 'show') { animate.css(ref.size, 0); animate.css(ref.position, distance / 2); } // Shift
10609 var animation = {};
10610 animation[ref.size] = mode == 'show' ? distance : 0;
10611 animation[ref.position] = mode == 'show' ? 0 : distance / 2;
10614 animate.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
10615 if(mode == 'hide') el.hide(); // Hide
10616 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
10617 if(o.callback) o.callback.apply(el[0], arguments); // Callback
10627 * jQuery UI Effects Drop 1.8.4
10629 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
10630 * Dual licensed under the MIT or GPL Version 2 licenses.
10631 * http://jquery.org/license
10633 * http://docs.jquery.com/UI/Effects/Drop
10636 * jquery.effects.core.js
10638 (function( $, undefined ) {
10640 $.effects.drop = function(o) {
10642 return this.queue(function() {
10645 var el = $(this), props = ['position','top','left','opacity'];
10648 var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
10649 var direction = o.options.direction || 'left'; // Default Direction
10652 $.effects.save(el, props); el.show(); // Save & Show
10653 $.effects.createWrapper(el); // Create Wrapper
10654 var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
10655 var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
10656 var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) / 2 : el.outerWidth({margin:true}) / 2);
10657 if (mode == 'show') el.css('opacity', 0).css(ref, motion == 'pos' ? -distance : distance); // Shift
10660 var animation = {opacity: mode == 'show' ? 1 : 0};
10661 animation[ref] = (mode == 'show' ? (motion == 'pos' ? '+=' : '-=') : (motion == 'pos' ? '-=' : '+=')) + distance;
10664 el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
10665 if(mode == 'hide') el.hide(); // Hide
10666 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
10667 if(o.callback) o.callback.apply(this, arguments); // Callback
10677 * jQuery UI Effects Explode 1.8.4
10679 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
10680 * Dual licensed under the MIT or GPL Version 2 licenses.
10681 * http://jquery.org/license
10683 * http://docs.jquery.com/UI/Effects/Explode
10686 * jquery.effects.core.js
10688 (function( $, undefined ) {
10690 $.effects.explode = function(o) {
10692 return this.queue(function() {
10694 var rows = o.options.pieces ? Math.round(Math.sqrt(o.options.pieces)) : 3;
10695 var cells = o.options.pieces ? Math.round(Math.sqrt(o.options.pieces)) : 3;
10697 o.options.mode = o.options.mode == 'toggle' ? ($(this).is(':visible') ? 'hide' : 'show') : o.options.mode;
10698 var el = $(this).show().css('visibility', 'hidden');
10699 var offset = el.offset();
10701 //Substract the margins - not fixing the problem yet.
10702 offset.top -= parseInt(el.css("marginTop"),10) || 0;
10703 offset.left -= parseInt(el.css("marginLeft"),10) || 0;
10705 var width = el.outerWidth(true);
10706 var height = el.outerHeight(true);
10708 for(var i=0;i<rows;i++) { // =
10709 for(var j=0;j<cells;j++) { // ||
10713 .wrap('<div></div>')
10715 position: 'absolute',
10716 visibility: 'visible',
10717 left: -j*(width/cells),
10718 top: -i*(height/rows)
10721 .addClass('ui-effects-explode')
10723 position: 'absolute',
10724 overflow: 'hidden',
10725 width: width/cells,
10726 height: height/rows,
10727 left: offset.left + j*(width/cells) + (o.options.mode == 'show' ? (j-Math.floor(cells/2))*(width/cells) : 0),
10728 top: offset.top + i*(height/rows) + (o.options.mode == 'show' ? (i-Math.floor(rows/2))*(height/rows) : 0),
10729 opacity: o.options.mode == 'show' ? 0 : 1
10731 left: offset.left + j*(width/cells) + (o.options.mode == 'show' ? 0 : (j-Math.floor(cells/2))*(width/cells)),
10732 top: offset.top + i*(height/rows) + (o.options.mode == 'show' ? 0 : (i-Math.floor(rows/2))*(height/rows)),
10733 opacity: o.options.mode == 'show' ? 1 : 0
10734 }, o.duration || 500);
10738 // Set a timeout, to call the callback approx. when the other animations have finished
10739 setTimeout(function() {
10741 o.options.mode == 'show' ? el.css({ visibility: 'visible' }) : el.css({ visibility: 'visible' }).hide();
10742 if(o.callback) o.callback.apply(el[0]); // Callback
10745 $('div.ui-effects-explode').remove();
10747 }, o.duration || 500);
10756 * jQuery UI Effects Fold 1.8.4
10758 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
10759 * Dual licensed under the MIT or GPL Version 2 licenses.
10760 * http://jquery.org/license
10762 * http://docs.jquery.com/UI/Effects/Fold
10765 * jquery.effects.core.js
10767 (function( $, undefined ) {
10769 $.effects.fold = function(o) {
10771 return this.queue(function() {
10774 var el = $(this), props = ['position','top','left'];
10777 var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
10778 var size = o.options.size || 15; // Default fold size
10779 var horizFirst = !(!o.options.horizFirst); // Ensure a boolean value
10780 var duration = o.duration ? o.duration / 2 : $.fx.speeds._default / 2;
10783 $.effects.save(el, props); el.show(); // Save & Show
10784 var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
10785 var widthFirst = ((mode == 'show') != horizFirst);
10786 var ref = widthFirst ? ['width', 'height'] : ['height', 'width'];
10787 var distance = widthFirst ? [wrapper.width(), wrapper.height()] : [wrapper.height(), wrapper.width()];
10788 var percent = /([0-9]+)%/.exec(size);
10789 if(percent) size = parseInt(percent[1],10) / 100 * distance[mode == 'hide' ? 0 : 1];
10790 if(mode == 'show') wrapper.css(horizFirst ? {height: 0, width: size} : {height: size, width: 0}); // Shift
10793 var animation1 = {}, animation2 = {};
10794 animation1[ref[0]] = mode == 'show' ? distance[0] : size;
10795 animation2[ref[1]] = mode == 'show' ? distance[1] : 0;
10798 wrapper.animate(animation1, duration, o.options.easing)
10799 .animate(animation2, duration, o.options.easing, function() {
10800 if(mode == 'hide') el.hide(); // Hide
10801 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
10802 if(o.callback) o.callback.apply(el[0], arguments); // Callback
10812 * jQuery UI Effects Highlight 1.8.4
10814 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
10815 * Dual licensed under the MIT or GPL Version 2 licenses.
10816 * http://jquery.org/license
10818 * http://docs.jquery.com/UI/Effects/Highlight
10821 * jquery.effects.core.js
10823 (function( $, undefined ) {
10825 $.effects.highlight = function(o) {
10826 return this.queue(function() {
10827 var elem = $(this),
10828 props = ['backgroundImage', 'backgroundColor', 'opacity'],
10829 mode = $.effects.setMode(elem, o.options.mode || 'show'),
10831 backgroundColor: elem.css('backgroundColor')
10834 if (mode == 'hide') {
10835 animation.opacity = 0;
10838 $.effects.save(elem, props);
10842 backgroundImage: 'none',
10843 backgroundColor: o.options.color || '#ffff99'
10845 .animate(animation, {
10847 duration: o.duration,
10848 easing: o.options.easing,
10849 complete: function() {
10850 (mode == 'hide' && elem.hide());
10851 $.effects.restore(elem, props);
10852 (mode == 'show' && !$.support.opacity && this.style.removeAttribute('filter'));
10853 (o.callback && o.callback.apply(this, arguments));
10862 * jQuery UI Effects Pulsate 1.8.4
10864 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
10865 * Dual licensed under the MIT or GPL Version 2 licenses.
10866 * http://jquery.org/license
10868 * http://docs.jquery.com/UI/Effects/Pulsate
10871 * jquery.effects.core.js
10873 (function( $, undefined ) {
10875 $.effects.pulsate = function(o) {
10876 return this.queue(function() {
10877 var elem = $(this),
10878 mode = $.effects.setMode(elem, o.options.mode || 'show');
10879 times = ((o.options.times || 5) * 2) - 1;
10880 duration = o.duration ? o.duration / 2 : $.fx.speeds._default / 2,
10881 isVisible = elem.is(':visible'),
10885 elem.css('opacity', 0).show();
10889 if ((mode == 'hide' && isVisible) || (mode == 'show' && !isVisible)) {
10893 for (var i = 0; i < times; i++) {
10894 elem.animate({ opacity: animateTo }, duration, o.options.easing);
10895 animateTo = (animateTo + 1) % 2;
10898 elem.animate({ opacity: animateTo }, duration, o.options.easing, function() {
10899 if (animateTo == 0) {
10902 (o.callback && o.callback.apply(this, arguments));
10906 .queue('fx', function() { elem.dequeue(); })
10913 * jQuery UI Effects Scale 1.8.4
10915 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
10916 * Dual licensed under the MIT or GPL Version 2 licenses.
10917 * http://jquery.org/license
10919 * http://docs.jquery.com/UI/Effects/Scale
10922 * jquery.effects.core.js
10924 (function( $, undefined ) {
10926 $.effects.puff = function(o) {
10927 return this.queue(function() {
10928 var elem = $(this),
10929 mode = $.effects.setMode(elem, o.options.mode || 'hide'),
10930 percent = parseInt(o.options.percent, 10) || 150,
10931 factor = percent / 100,
10932 original = { height: elem.height(), width: elem.width() };
10934 $.extend(o.options, {
10937 percent: mode == 'hide' ? percent : 100,
10938 from: mode == 'hide'
10941 height: original.height * factor,
10942 width: original.width * factor
10946 elem.effect('scale', o.options, o.duration, o.callback);
10951 $.effects.scale = function(o) {
10953 return this.queue(function() {
10959 var options = $.extend(true, {}, o.options);
10960 var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
10961 var percent = parseInt(o.options.percent,10) || (parseInt(o.options.percent,10) == 0 ? 0 : (mode == 'hide' ? 0 : 100)); // Set default scaling percent
10962 var direction = o.options.direction || 'both'; // Set default axis
10963 var origin = o.options.origin; // The origin of the scaling
10964 if (mode != 'effect') { // Set default origin and restore for show/hide
10965 options.origin = origin || ['middle','center'];
10966 options.restore = true;
10968 var original = {height: el.height(), width: el.width()}; // Save original
10969 el.from = o.options.from || (mode == 'show' ? {height: 0, width: 0} : original); // Default from state
10972 var factor = { // Set scaling factor
10973 y: direction != 'horizontal' ? (percent / 100) : 1,
10974 x: direction != 'vertical' ? (percent / 100) : 1
10976 el.to = {height: original.height * factor.y, width: original.width * factor.x}; // Set to state
10978 if (o.options.fade) { // Fade option to support puff
10979 if (mode == 'show') {el.from.opacity = 0; el.to.opacity = 1;};
10980 if (mode == 'hide') {el.from.opacity = 1; el.to.opacity = 0;};
10984 options.from = el.from; options.to = el.to; options.mode = mode;
10987 el.effect('size', options, o.duration, o.callback);
10993 $.effects.size = function(o) {
10995 return this.queue(function() {
10998 var el = $(this), props = ['position','top','left','width','height','overflow','opacity'];
10999 var props1 = ['position','top','left','overflow','opacity']; // Always restore
11000 var props2 = ['width','height','overflow']; // Copy for children
11001 var cProps = ['fontSize'];
11002 var vProps = ['borderTopWidth', 'borderBottomWidth', 'paddingTop', 'paddingBottom'];
11003 var hProps = ['borderLeftWidth', 'borderRightWidth', 'paddingLeft', 'paddingRight'];
11006 var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
11007 var restore = o.options.restore || false; // Default restore
11008 var scale = o.options.scale || 'both'; // Default scale mode
11009 var origin = o.options.origin; // The origin of the sizing
11010 var original = {height: el.height(), width: el.width()}; // Save original
11011 el.from = o.options.from || original; // Default from state
11012 el.to = o.options.to || original; // Default to state
11014 if (origin) { // Calculate baseline shifts
11015 var baseline = $.effects.getBaseline(origin, original);
11016 el.from.top = (original.height - el.from.height) * baseline.y;
11017 el.from.left = (original.width - el.from.width) * baseline.x;
11018 el.to.top = (original.height - el.to.height) * baseline.y;
11019 el.to.left = (original.width - el.to.width) * baseline.x;
11021 var factor = { // Set scaling factor
11022 from: {y: el.from.height / original.height, x: el.from.width / original.width},
11023 to: {y: el.to.height / original.height, x: el.to.width / original.width}
11025 if (scale == 'box' || scale == 'both') { // Scale the css box
11026 if (factor.from.y != factor.to.y) { // Vertical props scaling
11027 props = props.concat(vProps);
11028 el.from = $.effects.setTransition(el, vProps, factor.from.y, el.from);
11029 el.to = $.effects.setTransition(el, vProps, factor.to.y, el.to);
11031 if (factor.from.x != factor.to.x) { // Horizontal props scaling
11032 props = props.concat(hProps);
11033 el.from = $.effects.setTransition(el, hProps, factor.from.x, el.from);
11034 el.to = $.effects.setTransition(el, hProps, factor.to.x, el.to);
11037 if (scale == 'content' || scale == 'both') { // Scale the content
11038 if (factor.from.y != factor.to.y) { // Vertical props scaling
11039 props = props.concat(cProps);
11040 el.from = $.effects.setTransition(el, cProps, factor.from.y, el.from);
11041 el.to = $.effects.setTransition(el, cProps, factor.to.y, el.to);
11044 $.effects.save(el, restore ? props : props1); el.show(); // Save & Show
11045 $.effects.createWrapper(el); // Create Wrapper
11046 el.css('overflow','hidden').css(el.from); // Shift
11049 if (scale == 'content' || scale == 'both') { // Scale the children
11050 vProps = vProps.concat(['marginTop','marginBottom']).concat(cProps); // Add margins/font-size
11051 hProps = hProps.concat(['marginLeft','marginRight']); // Add margins
11052 props2 = props.concat(vProps).concat(hProps); // Concat
11053 el.find("*[width]").each(function(){
11055 if (restore) $.effects.save(child, props2);
11056 var c_original = {height: child.height(), width: child.width()}; // Save original
11057 child.from = {height: c_original.height * factor.from.y, width: c_original.width * factor.from.x};
11058 child.to = {height: c_original.height * factor.to.y, width: c_original.width * factor.to.x};
11059 if (factor.from.y != factor.to.y) { // Vertical props scaling
11060 child.from = $.effects.setTransition(child, vProps, factor.from.y, child.from);
11061 child.to = $.effects.setTransition(child, vProps, factor.to.y, child.to);
11063 if (factor.from.x != factor.to.x) { // Horizontal props scaling
11064 child.from = $.effects.setTransition(child, hProps, factor.from.x, child.from);
11065 child.to = $.effects.setTransition(child, hProps, factor.to.x, child.to);
11067 child.css(child.from); // Shift children
11068 child.animate(child.to, o.duration, o.options.easing, function(){
11069 if (restore) $.effects.restore(child, props2); // Restore children
11070 }); // Animate children
11075 el.animate(el.to, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
11076 if (el.to.opacity === 0) {
11077 el.css('opacity', el.from.opacity);
11079 if(mode == 'hide') el.hide(); // Hide
11080 $.effects.restore(el, restore ? props : props1); $.effects.removeWrapper(el); // Restore
11081 if(o.callback) o.callback.apply(this, arguments); // Callback
11091 * jQuery UI Effects Shake 1.8.4
11093 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
11094 * Dual licensed under the MIT or GPL Version 2 licenses.
11095 * http://jquery.org/license
11097 * http://docs.jquery.com/UI/Effects/Shake
11100 * jquery.effects.core.js
11102 (function( $, undefined ) {
11104 $.effects.shake = function(o) {
11106 return this.queue(function() {
11109 var el = $(this), props = ['position','top','left'];
11112 var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
11113 var direction = o.options.direction || 'left'; // Default direction
11114 var distance = o.options.distance || 20; // Default distance
11115 var times = o.options.times || 3; // Default # of times
11116 var speed = o.duration || o.options.duration || 140; // Default speed per shake
11119 $.effects.save(el, props); el.show(); // Save & Show
11120 $.effects.createWrapper(el); // Create Wrapper
11121 var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
11122 var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
11125 var animation = {}, animation1 = {}, animation2 = {};
11126 animation[ref] = (motion == 'pos' ? '-=' : '+=') + distance;
11127 animation1[ref] = (motion == 'pos' ? '+=' : '-=') + distance * 2;
11128 animation2[ref] = (motion == 'pos' ? '-=' : '+=') + distance * 2;
11131 el.animate(animation, speed, o.options.easing);
11132 for (var i = 1; i < times; i++) { // Shakes
11133 el.animate(animation1, speed, o.options.easing).animate(animation2, speed, o.options.easing);
11135 el.animate(animation1, speed, o.options.easing).
11136 animate(animation, speed / 2, o.options.easing, function(){ // Last shake
11137 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
11138 if(o.callback) o.callback.apply(this, arguments); // Callback
11140 el.queue('fx', function() { el.dequeue(); });
11148 * jQuery UI Effects Slide 1.8.4
11150 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
11151 * Dual licensed under the MIT or GPL Version 2 licenses.
11152 * http://jquery.org/license
11154 * http://docs.jquery.com/UI/Effects/Slide
11157 * jquery.effects.core.js
11159 (function( $, undefined ) {
11161 $.effects.slide = function(o) {
11163 return this.queue(function() {
11166 var el = $(this), props = ['position','top','left'];
11169 var mode = $.effects.setMode(el, o.options.mode || 'show'); // Set Mode
11170 var direction = o.options.direction || 'left'; // Default Direction
11173 $.effects.save(el, props); el.show(); // Save & Show
11174 $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
11175 var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
11176 var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
11177 var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) : el.outerWidth({margin:true}));
11178 if (mode == 'show') el.css(ref, motion == 'pos' ? -distance : distance); // Shift
11181 var animation = {};
11182 animation[ref] = (mode == 'show' ? (motion == 'pos' ? '+=' : '-=') : (motion == 'pos' ? '-=' : '+=')) + distance;
11185 el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
11186 if(mode == 'hide') el.hide(); // Hide
11187 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
11188 if(o.callback) o.callback.apply(this, arguments); // Callback
11198 * jQuery UI Effects Transfer 1.8.4
11200 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
11201 * Dual licensed under the MIT or GPL Version 2 licenses.
11202 * http://jquery.org/license
11204 * http://docs.jquery.com/UI/Effects/Transfer
11207 * jquery.effects.core.js
11209 (function( $, undefined ) {
11211 $.effects.transfer = function(o) {
11212 return this.queue(function() {
11213 var elem = $(this),
11214 target = $(o.options.to),
11215 endPosition = target.offset(),
11217 top: endPosition.top,
11218 left: endPosition.left,
11219 height: target.innerHeight(),
11220 width: target.innerWidth()
11222 startPosition = elem.offset(),
11223 transfer = $('<div class="ui-effects-transfer"></div>')
11224 .appendTo(document.body)
11225 .addClass(o.options.className)
11227 top: startPosition.top,
11228 left: startPosition.left,
11229 height: elem.innerHeight(),
11230 width: elem.innerWidth(),
11231 position: 'absolute'
11233 .animate(animation, o.duration, o.options.easing, function() {
11235 (o.callback && o.callback.apply(elem[0], arguments));