4 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
5 * Dual licensed under the MIT or GPL Version 2 licenses.
6 * http://jquery.org/license
8 * http://docs.jquery.com/UI
10 (function( $, undefined ) {
12 // prevent duplicate loading
13 // this is only a problem because we proxy existing functions
14 // and we don't want to double proxy them
29 COMMAND_LEFT: 91, // COMMAND
40 MENU: 93, // COMMAND_RIGHT
55 WINDOWS: 91 // COMMAND
62 focus: function( delay, fn ) {
63 return typeof delay === "number" ?
64 this.each(function() {
66 setTimeout(function() {
73 this._focus.apply( this, arguments );
76 scrollParent: function() {
78 if (($.browser.msie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) {
79 scrollParent = this.parents().filter(function() {
80 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));
83 scrollParent = this.parents().filter(function() {
84 return (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
88 return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent;
91 zIndex: function( zIndex ) {
92 if ( zIndex !== undefined ) {
93 return this.css( "zIndex", zIndex );
97 var elem = $( this[ 0 ] ), position, value;
98 while ( elem.length && elem[ 0 ] !== document ) {
99 // Ignore z-index if position is set to a value where z-index is ignored by the browser
100 // This makes behavior of this function consistent across browsers
101 // WebKit always returns auto if the element is positioned
102 position = elem.css( "position" );
103 if ( position === "absolute" || position === "relative" || position === "fixed" ) {
104 // IE returns 0 when zIndex is not specified
105 // other browsers return a string
106 // we ignore the case of nested elements with an explicit value of 0
107 // <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
108 value = parseInt( elem.css( "zIndex" ), 10 );
109 if ( !isNaN( value ) && value !== 0 ) {
113 elem = elem.parent();
120 disableSelection: function() {
121 return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) +
122 ".ui-disableSelection", function( event ) {
123 event.preventDefault();
127 enableSelection: function() {
128 return this.unbind( ".ui-disableSelection" );
132 $.each( [ "Width", "Height" ], function( i, name ) {
133 var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
134 type = name.toLowerCase(),
136 innerWidth: $.fn.innerWidth,
137 innerHeight: $.fn.innerHeight,
138 outerWidth: $.fn.outerWidth,
139 outerHeight: $.fn.outerHeight
142 function reduce( elem, size, border, margin ) {
143 $.each( side, function() {
144 size -= parseFloat( $.curCSS( elem, "padding" + this, true) ) || 0;
146 size -= parseFloat( $.curCSS( elem, "border" + this + "Width", true) ) || 0;
149 size -= parseFloat( $.curCSS( elem, "margin" + this, true) ) || 0;
155 $.fn[ "inner" + name ] = function( size ) {
156 if ( size === undefined ) {
157 return orig[ "inner" + name ].call( this );
160 return this.each(function() {
161 $( this ).css( type, reduce( this, size ) + "px" );
165 $.fn[ "outer" + name] = function( size, margin ) {
166 if ( typeof size !== "number" ) {
167 return orig[ "outer" + name ].call( this, size );
170 return this.each(function() {
171 $( this).css( type, reduce( this, size, true, margin ) + "px" );
177 function focusable( element, isTabIndexNotNaN ) {
178 var nodeName = element.nodeName.toLowerCase();
179 if ( "area" === nodeName ) {
180 var map = element.parentNode,
183 if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
186 img = $( "img[usemap=#" + mapName + "]" )[0];
187 return !!img && visible( img );
189 return ( /input|select|textarea|button|object/.test( nodeName )
192 ? element.href || isTabIndexNotNaN
194 // the element and all of its ancestors must be visible
195 && visible( element );
198 function visible( element ) {
199 return !$( element ).parents().andSelf().filter(function() {
200 return $.curCSS( this, "visibility" ) === "hidden" ||
201 $.expr.filters.hidden( this );
205 $.extend( $.expr[ ":" ], {
206 data: function( elem, i, match ) {
207 return !!$.data( elem, match[ 3 ] );
210 focusable: function( element ) {
211 return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) );
214 tabbable: function( element ) {
215 var tabIndex = $.attr( element, "tabindex" ),
216 isTabIndexNaN = isNaN( tabIndex );
217 return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN );
223 var body = document.body,
224 div = body.appendChild( div = document.createElement( "div" ) );
226 $.extend( div.style, {
233 $.support.minHeight = div.offsetHeight === 100;
234 $.support.selectstart = "onselectstart" in div;
236 // set display to none to avoid a layout bug in IE
237 // http://dev.jquery.com/ticket/4014
238 body.removeChild( div ).style.display = "none";
247 // $.ui.plugin is deprecated. Use the proxy pattern instead.
249 add: function( module, option, set ) {
250 var proto = $.ui[ module ].prototype;
251 for ( var i in set ) {
252 proto.plugins[ i ] = proto.plugins[ i ] || [];
253 proto.plugins[ i ].push( [ option, set[ i ] ] );
256 call: function( instance, name, args ) {
257 var set = instance.plugins[ name ];
258 if ( !set || !instance.element[ 0 ].parentNode ) {
262 for ( var i = 0; i < set.length; i++ ) {
263 if ( instance.options[ set[ i ][ 0 ] ] ) {
264 set[ i ][ 1 ].apply( instance.element, args );
270 // will be deprecated when we switch to jQuery 1.4 - use jQuery.contains()
271 contains: function( a, b ) {
272 return document.compareDocumentPosition ?
273 a.compareDocumentPosition( b ) & 16 :
274 a !== b && a.contains( b );
277 // only used by resizable
278 hasScroll: function( el, a ) {
280 //If overflow is hidden, the element might have extra content, but the user wants to hide it
281 if ( $( el ).css( "overflow" ) === "hidden") {
285 var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
288 if ( el[ scroll ] > 0 ) {
292 // TODO: determine which cases actually cause this to happen
293 // if the element doesn't have the scroll set, see if it's possible to
296 has = ( el[ scroll ] > 0 );
301 // these are odd functions, fix the API or move into individual plugins
302 isOverAxis: function( x, reference, size ) {
303 //Determines when x coordinate is over "b" element axis
304 return ( x > reference ) && ( x < ( reference + size ) );
306 isOver: function( y, x, top, left, height, width ) {
307 //Determines when x, y coordinates is over "b" element
308 return $.ui.isOverAxis( y, top, height ) && $.ui.isOverAxis( x, left, width );
314 * jQuery UI Widget 1.8.14
316 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
317 * Dual licensed under the MIT or GPL Version 2 licenses.
318 * http://jquery.org/license
320 * http://docs.jquery.com/UI/Widget
322 (function( $, undefined ) {
326 var _cleanData = $.cleanData;
327 $.cleanData = function( elems ) {
328 for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
329 $( elem ).triggerHandler( "remove" );
334 var _remove = $.fn.remove;
335 $.fn.remove = function( selector, keepData ) {
336 return this.each(function() {
338 if ( !selector || $.filter( selector, [ this ] ).length ) {
339 $( "*", this ).add( [ this ] ).each(function() {
340 $( this ).triggerHandler( "remove" );
344 return _remove.call( $(this), selector, keepData );
349 $.widget = function( name, base, prototype ) {
350 var namespace = name.split( "." )[ 0 ],
352 name = name.split( "." )[ 1 ];
353 fullName = namespace + "-" + name;
360 // create selector for plugin
361 $.expr[ ":" ][ fullName ] = function( elem ) {
362 return !!$.data( elem, name );
365 $[ namespace ] = $[ namespace ] || {};
366 $[ namespace ][ name ] = function( options, element ) {
367 // allow instantiation without initializing for simple inheritance
368 if ( arguments.length ) {
369 this._createWidget( options, element );
373 var basePrototype = new base();
374 // we need to make the options hash a property directly on the new instance
375 // otherwise we'll modify the options hash on the prototype that we're
377 // $.each( basePrototype, function( key, val ) {
378 // if ( $.isPlainObject(val) ) {
379 // basePrototype[ key ] = $.extend( {}, val );
382 basePrototype.options = $.extend( true, {}, basePrototype.options );
383 $[ namespace ][ name ].prototype = $.extend( true, basePrototype, {
384 namespace: namespace,
386 widgetEventPrefix: $[ namespace ][ name ].prototype.widgetEventPrefix || name,
387 widgetBaseClass: fullName
390 $.widget.bridge( name, $[ namespace ][ name ] );
393 $.widget.bridge = function( name, object ) {
394 $.fn[ name ] = function( options ) {
395 var isMethodCall = typeof options === "string",
396 args = Array.prototype.slice.call( arguments, 1 ),
399 // allow multiple hashes to be passed on init
400 options = !isMethodCall && args.length ?
401 $.extend.apply( null, [ true, options ].concat(args) ) :
404 // prevent calls to internal methods
405 if ( isMethodCall && options.charAt( 0 ) === "_" ) {
409 if ( isMethodCall ) {
410 this.each(function() {
411 var instance = $.data( this, name ),
412 methodValue = instance && $.isFunction( instance[options] ) ?
413 instance[ options ].apply( instance, args ) :
415 // TODO: add this back in 1.9 and use $.error() (see #5972)
416 // if ( !instance ) {
417 // throw "cannot call methods on " + name + " prior to initialization; " +
418 // "attempted to call method '" + options + "'";
420 // if ( !$.isFunction( instance[options] ) ) {
421 // throw "no such method '" + options + "' for " + name + " widget instance";
423 // var methodValue = instance[ options ].apply( instance, args );
424 if ( methodValue !== instance && methodValue !== undefined ) {
425 returnValue = methodValue;
430 this.each(function() {
431 var instance = $.data( this, name );
433 instance.option( options || {} )._init();
435 $.data( this, name, new object( options, this ) );
444 $.Widget = function( options, element ) {
445 // allow instantiation without initializing for simple inheritance
446 if ( arguments.length ) {
447 this._createWidget( options, element );
451 $.Widget.prototype = {
452 widgetName: "widget",
453 widgetEventPrefix: "",
457 _createWidget: function( options, element ) {
458 // $.widget.bridge stores the plugin instance, but we do it anyway
459 // so that it's stored even before the _create function runs
460 $.data( element, this.widgetName, this );
461 this.element = $( element );
462 this.options = $.extend( true, {},
464 this._getCreateOptions(),
468 this.element.bind( "remove." + this.widgetName, function() {
473 this._trigger( "create" );
476 _getCreateOptions: function() {
477 return $.metadata && $.metadata.get( this.element[0] )[ this.widgetName ];
479 _create: function() {},
480 _init: function() {},
482 destroy: function() {
484 .unbind( "." + this.widgetName )
485 .removeData( this.widgetName );
487 .unbind( "." + this.widgetName )
488 .removeAttr( "aria-disabled" )
490 this.widgetBaseClass + "-disabled " +
491 "ui-state-disabled" );
498 option: function( key, value ) {
501 if ( arguments.length === 0 ) {
502 // don't return a reference to the internal hash
503 return $.extend( {}, this.options );
506 if (typeof key === "string" ) {
507 if ( value === undefined ) {
508 return this.options[ key ];
511 options[ key ] = value;
514 this._setOptions( options );
518 _setOptions: function( options ) {
520 $.each( options, function( key, value ) {
521 self._setOption( key, value );
526 _setOption: function( key, value ) {
527 this.options[ key ] = value;
529 if ( key === "disabled" ) {
531 [ value ? "addClass" : "removeClass"](
532 this.widgetBaseClass + "-disabled" + " " +
533 "ui-state-disabled" )
534 .attr( "aria-disabled", value );
541 return this._setOption( "disabled", false );
543 disable: function() {
544 return this._setOption( "disabled", true );
547 _trigger: function( type, event, data ) {
548 var callback = this.options[ type ];
550 event = $.Event( event );
551 event.type = ( type === this.widgetEventPrefix ?
553 this.widgetEventPrefix + type ).toLowerCase();
556 // copy original event properties over to the new event
557 // this would happen if we could call $.event.fix instead of $.Event
558 // but we don't have a way to force an event to be fixed multiple times
559 if ( event.originalEvent ) {
560 for ( var i = $.event.props.length, prop; i; ) {
561 prop = $.event.props[ --i ];
562 event[ prop ] = event.originalEvent[ prop ];
566 this.element.trigger( event, data );
568 return !( $.isFunction(callback) &&
569 callback.call( this.element[0], event, data ) === false ||
570 event.isDefaultPrevented() );
576 * jQuery UI Mouse 1.8.14
578 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
579 * Dual licensed under the MIT or GPL Version 2 licenses.
580 * http://jquery.org/license
582 * http://docs.jquery.com/UI/Mouse
585 * jquery.ui.widget.js
587 (function( $, undefined ) {
589 var mouseHandled = false;
590 $(document).mousedown(function(e) {
591 mouseHandled = false;
594 $.widget("ui.mouse", {
596 cancel: ':input,option',
600 _mouseInit: function() {
604 .bind('mousedown.'+this.widgetName, function(event) {
605 return self._mouseDown(event);
607 .bind('click.'+this.widgetName, function(event) {
608 if (true === $.data(event.target, self.widgetName + '.preventClickEvent')) {
609 $.removeData(event.target, self.widgetName + '.preventClickEvent');
610 event.stopImmediatePropagation();
615 this.started = false;
618 // TODO: make sure destroying one instance of mouse doesn't mess with
619 // other instances of mouse
620 _mouseDestroy: function() {
621 this.element.unbind('.'+this.widgetName);
624 _mouseDown: function(event) {
625 // don't let more than one widget handle mouseStart
626 if(mouseHandled) {return};
628 // we may have missed mouseup (out of window)
629 (this._mouseStarted && this._mouseUp(event));
631 this._mouseDownEvent = event;
634 btnIsLeft = (event.which == 1),
635 elIsCancel = (typeof this.options.cancel == "string" ? $(event.target).closest(this.options.cancel).length : false);
636 if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
640 this.mouseDelayMet = !this.options.delay;
641 if (!this.mouseDelayMet) {
642 this._mouseDelayTimer = setTimeout(function() {
643 self.mouseDelayMet = true;
644 }, this.options.delay);
647 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
648 this._mouseStarted = (this._mouseStart(event) !== false);
649 if (!this._mouseStarted) {
650 event.preventDefault();
655 // Click event may never have fired (Gecko & Opera)
656 if (true === $.data(event.target, this.widgetName + '.preventClickEvent')) {
657 $.removeData(event.target, this.widgetName + '.preventClickEvent');
660 // these delegates are required to keep context
661 this._mouseMoveDelegate = function(event) {
662 return self._mouseMove(event);
664 this._mouseUpDelegate = function(event) {
665 return self._mouseUp(event);
668 .bind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
669 .bind('mouseup.'+this.widgetName, this._mouseUpDelegate);
671 event.preventDefault();
677 _mouseMove: function(event) {
678 // IE mouseup check - mouseup happened when mouse was out of window
679 if ($.browser.msie && !(document.documentMode >= 9) && !event.button) {
680 return this._mouseUp(event);
683 if (this._mouseStarted) {
684 this._mouseDrag(event);
685 return event.preventDefault();
688 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
690 (this._mouseStart(this._mouseDownEvent, event) !== false);
691 (this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
694 return !this._mouseStarted;
697 _mouseUp: function(event) {
699 .unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
700 .unbind('mouseup.'+this.widgetName, this._mouseUpDelegate);
702 if (this._mouseStarted) {
703 this._mouseStarted = false;
705 if (event.target == this._mouseDownEvent.target) {
706 $.data(event.target, this.widgetName + '.preventClickEvent', true);
709 this._mouseStop(event);
715 _mouseDistanceMet: function(event) {
717 Math.abs(this._mouseDownEvent.pageX - event.pageX),
718 Math.abs(this._mouseDownEvent.pageY - event.pageY)
719 ) >= this.options.distance
723 _mouseDelayMet: function(event) {
724 return this.mouseDelayMet;
727 // These are placeholder methods, to be overriden by extending plugin
728 _mouseStart: function(event) {},
729 _mouseDrag: function(event) {},
730 _mouseStop: function(event) {},
731 _mouseCapture: function(event) { return true; }
736 * jQuery UI Position 1.8.14
738 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
739 * Dual licensed under the MIT or GPL Version 2 licenses.
740 * http://jquery.org/license
742 * http://docs.jquery.com/UI/Position
744 (function( $, undefined ) {
748 var horizontalPositions = /left|center|right/,
749 verticalPositions = /top|center|bottom/,
751 _position = $.fn.position,
752 _offset = $.fn.offset;
754 $.fn.position = function( options ) {
755 if ( !options || !options.of ) {
756 return _position.apply( this, arguments );
759 // make a copy, we don't want to modify arguments
760 options = $.extend( {}, options );
762 var target = $( options.of ),
763 targetElem = target[0],
764 collision = ( options.collision || "flip" ).split( " " ),
765 offset = options.offset ? options.offset.split( " " ) : [ 0, 0 ],
770 if ( targetElem.nodeType === 9 ) {
771 targetWidth = target.width();
772 targetHeight = target.height();
773 basePosition = { top: 0, left: 0 };
774 // TODO: use $.isWindow() in 1.9
775 } else if ( targetElem.setTimeout ) {
776 targetWidth = target.width();
777 targetHeight = target.height();
778 basePosition = { top: target.scrollTop(), left: target.scrollLeft() };
779 } else if ( targetElem.preventDefault ) {
780 // force left top to allow flipping
781 options.at = "left top";
782 targetWidth = targetHeight = 0;
783 basePosition = { top: options.of.pageY, left: options.of.pageX };
785 targetWidth = target.outerWidth();
786 targetHeight = target.outerHeight();
787 basePosition = target.offset();
790 // force my and at to have valid horizontal and veritcal positions
791 // if a value is missing or invalid, it will be converted to center
792 $.each( [ "my", "at" ], function() {
793 var pos = ( options[this] || "" ).split( " " );
794 if ( pos.length === 1) {
795 pos = horizontalPositions.test( pos[0] ) ?
796 pos.concat( [center] ) :
797 verticalPositions.test( pos[0] ) ?
798 [ center ].concat( pos ) :
801 pos[ 0 ] = horizontalPositions.test( pos[0] ) ? pos[ 0 ] : center;
802 pos[ 1 ] = verticalPositions.test( pos[1] ) ? pos[ 1 ] : center;
803 options[ this ] = pos;
806 // normalize collision option
807 if ( collision.length === 1 ) {
808 collision[ 1 ] = collision[ 0 ];
811 // normalize offset option
812 offset[ 0 ] = parseInt( offset[0], 10 ) || 0;
813 if ( offset.length === 1 ) {
814 offset[ 1 ] = offset[ 0 ];
816 offset[ 1 ] = parseInt( offset[1], 10 ) || 0;
818 if ( options.at[0] === "right" ) {
819 basePosition.left += targetWidth;
820 } else if ( options.at[0] === center ) {
821 basePosition.left += targetWidth / 2;
824 if ( options.at[1] === "bottom" ) {
825 basePosition.top += targetHeight;
826 } else if ( options.at[1] === center ) {
827 basePosition.top += targetHeight / 2;
830 basePosition.left += offset[ 0 ];
831 basePosition.top += offset[ 1 ];
833 return this.each(function() {
834 var elem = $( this ),
835 elemWidth = elem.outerWidth(),
836 elemHeight = elem.outerHeight(),
837 marginLeft = parseInt( $.curCSS( this, "marginLeft", true ) ) || 0,
838 marginTop = parseInt( $.curCSS( this, "marginTop", true ) ) || 0,
839 collisionWidth = elemWidth + marginLeft +
840 ( parseInt( $.curCSS( this, "marginRight", true ) ) || 0 ),
841 collisionHeight = elemHeight + marginTop +
842 ( parseInt( $.curCSS( this, "marginBottom", true ) ) || 0 ),
843 position = $.extend( {}, basePosition ),
846 if ( options.my[0] === "right" ) {
847 position.left -= elemWidth;
848 } else if ( options.my[0] === center ) {
849 position.left -= elemWidth / 2;
852 if ( options.my[1] === "bottom" ) {
853 position.top -= elemHeight;
854 } else if ( options.my[1] === center ) {
855 position.top -= elemHeight / 2;
858 // prevent fractions (see #5280)
859 position.left = Math.round( position.left );
860 position.top = Math.round( position.top );
862 collisionPosition = {
863 left: position.left - marginLeft,
864 top: position.top - marginTop
867 $.each( [ "left", "top" ], function( i, dir ) {
868 if ( $.ui.position[ collision[i] ] ) {
869 $.ui.position[ collision[i] ][ dir ]( position, {
870 targetWidth: targetWidth,
871 targetHeight: targetHeight,
872 elemWidth: elemWidth,
873 elemHeight: elemHeight,
874 collisionPosition: collisionPosition,
875 collisionWidth: collisionWidth,
876 collisionHeight: collisionHeight,
884 if ( $.fn.bgiframe ) {
887 elem.offset( $.extend( position, { using: options.using } ) );
893 left: function( position, data ) {
894 var win = $( window ),
895 over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft();
896 position.left = over > 0 ? position.left - over : Math.max( position.left - data.collisionPosition.left, position.left );
898 top: function( position, data ) {
899 var win = $( window ),
900 over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop();
901 position.top = over > 0 ? position.top - over : Math.max( position.top - data.collisionPosition.top, position.top );
906 left: function( position, data ) {
907 if ( data.at[0] === center ) {
910 var win = $( window ),
911 over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft(),
912 myOffset = data.my[ 0 ] === "left" ?
914 data.my[ 0 ] === "right" ?
917 atOffset = data.at[ 0 ] === "left" ?
920 offset = -2 * data.offset[ 0 ];
921 position.left += data.collisionPosition.left < 0 ?
922 myOffset + atOffset + offset :
924 myOffset + atOffset + offset :
927 top: function( position, data ) {
928 if ( data.at[1] === center ) {
931 var win = $( window ),
932 over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop(),
933 myOffset = data.my[ 1 ] === "top" ?
935 data.my[ 1 ] === "bottom" ?
938 atOffset = data.at[ 1 ] === "top" ?
941 offset = -2 * data.offset[ 1 ];
942 position.top += data.collisionPosition.top < 0 ?
943 myOffset + atOffset + offset :
945 myOffset + atOffset + offset :
951 // offset setter from jQuery 1.4
952 if ( !$.offset.setOffset ) {
953 $.offset.setOffset = function( elem, options ) {
954 // set position first, in-case top/left are set even on static elem
955 if ( /static/.test( $.curCSS( elem, "position" ) ) ) {
956 elem.style.position = "relative";
958 var curElem = $( elem ),
959 curOffset = curElem.offset(),
960 curTop = parseInt( $.curCSS( elem, "top", true ), 10 ) || 0,
961 curLeft = parseInt( $.curCSS( elem, "left", true ), 10) || 0,
963 top: (options.top - curOffset.top) + curTop,
964 left: (options.left - curOffset.left) + curLeft
967 if ( 'using' in options ) {
968 options.using.call( elem, props );
970 curElem.css( props );
974 $.fn.offset = function( options ) {
975 var elem = this[ 0 ];
976 if ( !elem || !elem.ownerDocument ) { return null; }
978 return this.each(function() {
979 $.offset.setOffset( this, options );
982 return _offset.call( this );
988 * jQuery UI Draggable 1.8.14
990 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
991 * Dual licensed under the MIT or GPL Version 2 licenses.
992 * http://jquery.org/license
994 * http://docs.jquery.com/UI/Draggables
999 * jquery.ui.widget.js
1001 (function( $, undefined ) {
1003 $.widget("ui.draggable", $.ui.mouse, {
1004 widgetEventPrefix: "drag",
1009 connectToSortable: false,
1018 refreshPositions: false,
1020 revertDuration: 500,
1023 scrollSensitivity: 20,
1031 _create: function() {
1033 if (this.options.helper == 'original' && !(/^(?:r|a|f)/).test(this.element.css("position")))
1034 this.element[0].style.position = 'relative';
1036 (this.options.addClasses && this.element.addClass("ui-draggable"));
1037 (this.options.disabled && this.element.addClass("ui-draggable-disabled"));
1043 destroy: function() {
1044 if(!this.element.data('draggable')) return;
1046 .removeData("draggable")
1047 .unbind(".draggable")
1048 .removeClass("ui-draggable"
1049 + " ui-draggable-dragging"
1050 + " ui-draggable-disabled");
1051 this._mouseDestroy();
1056 _mouseCapture: function(event) {
1058 var o = this.options;
1060 // among others, prevent a drag on a resizable-handle
1061 if (this.helper || o.disabled || $(event.target).is('.ui-resizable-handle'))
1064 //Quit if we're not on a valid handle
1065 this.handle = this._getHandle(event);
1069 $(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() {
1070 $('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>')
1072 width: this.offsetWidth+"px", height: this.offsetHeight+"px",
1073 position: "absolute", opacity: "0.001", zIndex: 1000
1075 .css($(this).offset())
1083 _mouseStart: function(event) {
1085 var o = this.options;
1087 //Create and append the visible helper
1088 this.helper = this._createHelper(event);
1090 //Cache the helper size
1091 this._cacheHelperProportions();
1093 //If ddmanager is used for droppables, set the global draggable
1095 $.ui.ddmanager.current = this;
1098 * - Position generation -
1099 * This block generates everything position related - it's the core of draggables.
1102 //Cache the margins of the original element
1103 this._cacheMargins();
1105 //Store the helper's css position
1106 this.cssPosition = this.helper.css("position");
1107 this.scrollParent = this.helper.scrollParent();
1109 //The element's absolute position on the page minus margins
1110 this.offset = this.positionAbs = this.element.offset();
1112 top: this.offset.top - this.margins.top,
1113 left: this.offset.left - this.margins.left
1116 $.extend(this.offset, {
1117 click: { //Where the click happened, relative to the element
1118 left: event.pageX - this.offset.left,
1119 top: event.pageY - this.offset.top
1121 parent: this._getParentOffset(),
1122 relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
1125 //Generate the original position
1126 this.originalPosition = this.position = this._generatePosition(event);
1127 this.originalPageX = event.pageX;
1128 this.originalPageY = event.pageY;
1130 //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
1131 (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
1133 //Set a containment if given in the options
1135 this._setContainment();
1137 //Trigger event + callbacks
1138 if(this._trigger("start", event) === false) {
1143 //Recache the helper size
1144 this._cacheHelperProportions();
1146 //Prepare the droppable offsets
1147 if ($.ui.ddmanager && !o.dropBehaviour)
1148 $.ui.ddmanager.prepareOffsets(this, event);
1150 this.helper.addClass("ui-draggable-dragging");
1151 this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position
1153 //If the ddmanager is used for droppables, inform the manager that dragging has started (see #5003)
1154 if ( $.ui.ddmanager ) $.ui.ddmanager.dragStart(this, event);
1159 _mouseDrag: function(event, noPropagation) {
1161 //Compute the helpers position
1162 this.position = this._generatePosition(event);
1163 this.positionAbs = this._convertPositionTo("absolute");
1165 //Call plugins and callbacks and use the resulting position if something is returned
1166 if (!noPropagation) {
1167 var ui = this._uiHash();
1168 if(this._trigger('drag', event, ui) === false) {
1172 this.position = ui.position;
1175 if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
1176 if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
1177 if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
1182 _mouseStop: function(event) {
1184 //If we are using droppables, inform the manager about the drop
1185 var dropped = false;
1186 if ($.ui.ddmanager && !this.options.dropBehaviour)
1187 dropped = $.ui.ddmanager.drop(this, event);
1189 //if a drop comes from outside (a sortable)
1191 dropped = this.dropped;
1192 this.dropped = false;
1195 //if the original element is removed, don't bother to continue if helper is set to "original"
1196 if((!this.element[0] || !this.element[0].parentNode) && this.options.helper == "original")
1199 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))) {
1201 $(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() {
1202 if(self._trigger("stop", event) !== false) {
1207 if(this._trigger("stop", event) !== false) {
1215 _mouseUp: function(event) {
1216 if (this.options.iframeFix === true) {
1217 $("div.ui-draggable-iframeFix").each(function() {
1218 this.parentNode.removeChild(this);
1219 }); //Remove frame helpers
1222 //If the ddmanager is used for droppables, inform the manager that dragging has stopped (see #5003)
1223 if( $.ui.ddmanager ) $.ui.ddmanager.dragStop(this, event);
1225 return $.ui.mouse.prototype._mouseUp.call(this, event);
1228 cancel: function() {
1230 if(this.helper.is(".ui-draggable-dragging")) {
1240 _getHandle: function(event) {
1242 var handle = !this.options.handle || !$(this.options.handle, this.element).length ? true : false;
1243 $(this.options.handle, this.element)
1247 if(this == event.target) handle = true;
1254 _createHelper: function(event) {
1256 var o = this.options;
1257 var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper == 'clone' ? this.element.clone().removeAttr('id') : this.element);
1259 if(!helper.parents('body').length)
1260 helper.appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo));
1262 if(helper[0] != this.element[0] && !(/(fixed|absolute)/).test(helper.css("position")))
1263 helper.css("position", "absolute");
1269 _adjustOffsetFromHelper: function(obj) {
1270 if (typeof obj == 'string') {
1271 obj = obj.split(' ');
1273 if ($.isArray(obj)) {
1274 obj = {left: +obj[0], top: +obj[1] || 0};
1276 if ('left' in obj) {
1277 this.offset.click.left = obj.left + this.margins.left;
1279 if ('right' in obj) {
1280 this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
1283 this.offset.click.top = obj.top + this.margins.top;
1285 if ('bottom' in obj) {
1286 this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
1290 _getParentOffset: function() {
1292 //Get the offsetParent and cache its position
1293 this.offsetParent = this.helper.offsetParent();
1294 var po = this.offsetParent.offset();
1296 // This is a special case where we need to modify a offset calculated on start, since the following happened:
1297 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
1298 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
1299 // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
1300 if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) {
1301 po.left += this.scrollParent.scrollLeft();
1302 po.top += this.scrollParent.scrollTop();
1305 if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
1306 || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix
1307 po = { top: 0, left: 0 };
1310 top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
1311 left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
1316 _getRelativeOffset: function() {
1318 if(this.cssPosition == "relative") {
1319 var p = this.element.position();
1321 top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
1322 left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
1325 return { top: 0, left: 0 };
1330 _cacheMargins: function() {
1332 left: (parseInt(this.element.css("marginLeft"),10) || 0),
1333 top: (parseInt(this.element.css("marginTop"),10) || 0),
1334 right: (parseInt(this.element.css("marginRight"),10) || 0),
1335 bottom: (parseInt(this.element.css("marginBottom"),10) || 0)
1339 _cacheHelperProportions: function() {
1340 this.helperProportions = {
1341 width: this.helper.outerWidth(),
1342 height: this.helper.outerHeight()
1346 _setContainment: function() {
1348 var o = this.options;
1349 if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
1350 if(o.containment == 'document' || o.containment == 'window') this.containment = [
1351 o.containment == 'document' ? 0 : $(window).scrollLeft() - this.offset.relative.left - this.offset.parent.left,
1352 o.containment == 'document' ? 0 : $(window).scrollTop() - this.offset.relative.top - this.offset.parent.top,
1353 (o.containment == 'document' ? 0 : $(window).scrollLeft()) + $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
1354 (o.containment == 'document' ? 0 : $(window).scrollTop()) + ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
1357 if(!(/^(document|window|parent)$/).test(o.containment) && o.containment.constructor != Array) {
1358 var c = $(o.containment);
1359 var ce = c[0]; if(!ce) return;
1360 var co = c.offset();
1361 var over = ($(ce).css("overflow") != 'hidden');
1363 this.containment = [
1364 (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0),
1365 (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0),
1366 (over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left - this.margins.right,
1367 (over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top - this.margins.bottom
1369 this.relative_container = c;
1371 } else if(o.containment.constructor == Array) {
1372 this.containment = o.containment;
1377 _convertPositionTo: function(d, pos) {
1379 if(!pos) pos = this.position;
1380 var mod = d == "absolute" ? 1 : -1;
1381 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);
1385 pos.top // The absolute mouse position
1386 + this.offset.relative.top * mod // Only for relative positioned nodes: Relative offset from element to offset parent
1387 + this.offset.parent.top * mod // The offsetParent's offset without borders (offset + border)
1388 - ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
1391 pos.left // The absolute mouse position
1392 + this.offset.relative.left * mod // Only for relative positioned nodes: Relative offset from element to offset parent
1393 + this.offset.parent.left * mod // The offsetParent's offset without borders (offset + border)
1394 - ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
1400 _generatePosition: function(event) {
1402 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);
1403 var pageX = event.pageX;
1404 var pageY = event.pageY;
1407 * - Position constraining -
1408 * Constrain the position to a mix of grid, containment.
1411 if(this.originalPosition) { //If we are not dragging yet, we won't check for options
1413 if(this.containment) {
1414 if (this.relative_container){
1415 var co = this.relative_container.offset();
1416 containment = [ this.containment[0] + co.left,
1417 this.containment[1] + co.top,
1418 this.containment[2] + co.left,
1419 this.containment[3] + co.top ];
1422 containment = this.containment;
1425 if(event.pageX - this.offset.click.left < containment[0]) pageX = containment[0] + this.offset.click.left;
1426 if(event.pageY - this.offset.click.top < containment[1]) pageY = containment[1] + this.offset.click.top;
1427 if(event.pageX - this.offset.click.left > containment[2]) pageX = containment[2] + this.offset.click.left;
1428 if(event.pageY - this.offset.click.top > containment[3]) pageY = containment[3] + this.offset.click.top;
1432 //Check for grid elements set to 0 to prevent divide by 0 error causing invalid argument errors in IE (see ticket #6950)
1433 var top = o.grid[1] ? this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1] : this.originalPageY;
1434 pageY = containment ? (!(top - this.offset.click.top < containment[1] || top - this.offset.click.top > containment[3]) ? top : (!(top - this.offset.click.top < containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;
1436 var left = o.grid[0] ? this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0] : this.originalPageX;
1437 pageX = containment ? (!(left - this.offset.click.left < containment[0] || left - this.offset.click.left > containment[2]) ? left : (!(left - this.offset.click.left < containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
1444 pageY // The absolute mouse position
1445 - this.offset.click.top // Click offset (relative to the element)
1446 - this.offset.relative.top // Only for relative positioned nodes: Relative offset from element to offset parent
1447 - this.offset.parent.top // The offsetParent's offset without borders (offset + border)
1448 + ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
1451 pageX // The absolute mouse position
1452 - this.offset.click.left // Click offset (relative to the element)
1453 - this.offset.relative.left // Only for relative positioned nodes: Relative offset from element to offset parent
1454 - this.offset.parent.left // The offsetParent's offset without borders (offset + border)
1455 + ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
1461 _clear: function() {
1462 this.helper.removeClass("ui-draggable-dragging");
1463 if(this.helper[0] != this.element[0] && !this.cancelHelperRemoval) this.helper.remove();
1464 //if($.ui.ddmanager) $.ui.ddmanager.current = null;
1466 this.cancelHelperRemoval = false;
1469 // From now on bulk stuff - mainly helpers
1471 _trigger: function(type, event, ui) {
1472 ui = ui || this._uiHash();
1473 $.ui.plugin.call(this, type, [event, ui]);
1474 if(type == "drag") this.positionAbs = this._convertPositionTo("absolute"); //The absolute position has to be recalculated after plugins
1475 return $.Widget.prototype._trigger.call(this, type, event, ui);
1480 _uiHash: function(event) {
1482 helper: this.helper,
1483 position: this.position,
1484 originalPosition: this.originalPosition,
1485 offset: this.positionAbs
1491 $.extend($.ui.draggable, {
1495 $.ui.plugin.add("draggable", "connectToSortable", {
1496 start: function(event, ui) {
1498 var inst = $(this).data("draggable"), o = inst.options,
1499 uiSortable = $.extend({}, ui, { item: inst.element });
1500 inst.sortables = [];
1501 $(o.connectToSortable).each(function() {
1502 var sortable = $.data(this, 'sortable');
1503 if (sortable && !sortable.options.disabled) {
1504 inst.sortables.push({
1506 shouldRevert: sortable.options.revert
1508 sortable.refreshPositions(); // Call the sortable's refreshPositions at drag start to refresh the containerCache since the sortable container cache is used in drag and needs to be up to date (this will ensure it's initialised as well as being kept in step with any changes that might have happened on the page).
1509 sortable._trigger("activate", event, uiSortable);
1514 stop: function(event, ui) {
1516 //If we are still over the sortable, we fake the stop event of the sortable, but also remove helper
1517 var inst = $(this).data("draggable"),
1518 uiSortable = $.extend({}, ui, { item: inst.element });
1520 $.each(inst.sortables, function() {
1521 if(this.instance.isOver) {
1523 this.instance.isOver = 0;
1525 inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance
1526 this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work)
1528 //The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: 'valid/invalid'
1529 if(this.shouldRevert) this.instance.options.revert = true;
1531 //Trigger the stop of the sortable
1532 this.instance._mouseStop(event);
1534 this.instance.options.helper = this.instance.options._helper;
1536 //If the helper has been the original item, restore properties in the sortable
1537 if(inst.options.helper == 'original')
1538 this.instance.currentItem.css({ top: 'auto', left: 'auto' });
1541 this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance
1542 this.instance._trigger("deactivate", event, uiSortable);
1548 drag: function(event, ui) {
1550 var inst = $(this).data("draggable"), self = this;
1552 var checkPos = function(o) {
1553 var dyClick = this.offset.click.top, dxClick = this.offset.click.left;
1554 var helperTop = this.positionAbs.top, helperLeft = this.positionAbs.left;
1555 var itemHeight = o.height, itemWidth = o.width;
1556 var itemTop = o.top, itemLeft = o.left;
1558 return $.ui.isOver(helperTop + dyClick, helperLeft + dxClick, itemTop, itemLeft, itemHeight, itemWidth);
1561 $.each(inst.sortables, function(i) {
1563 //Copy over some variables to allow calling the sortable's native _intersectsWith
1564 this.instance.positionAbs = inst.positionAbs;
1565 this.instance.helperProportions = inst.helperProportions;
1566 this.instance.offset.click = inst.offset.click;
1568 if(this.instance._intersectsWith(this.instance.containerCache)) {
1570 //If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once
1571 if(!this.instance.isOver) {
1573 this.instance.isOver = 1;
1574 //Now we fake the start of dragging for the sortable instance,
1575 //by cloning the list group item, appending it to the sortable and using it as inst.currentItem
1576 //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)
1577 this.instance.currentItem = $(self).clone().removeAttr('id').appendTo(this.instance.element).data("sortable-item", true);
1578 this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it
1579 this.instance.options.helper = function() { return ui.helper[0]; };
1581 event.target = this.instance.currentItem[0];
1582 this.instance._mouseCapture(event, true);
1583 this.instance._mouseStart(event, true, true);
1585 //Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes
1586 this.instance.offset.click.top = inst.offset.click.top;
1587 this.instance.offset.click.left = inst.offset.click.left;
1588 this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left;
1589 this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top;
1591 inst._trigger("toSortable", event);
1592 inst.dropped = this.instance.element; //draggable revert needs that
1593 //hack so receive/update callbacks work (mostly)
1594 inst.currentItem = inst.element;
1595 this.instance.fromOutside = inst;
1599 //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
1600 if(this.instance.currentItem) this.instance._mouseDrag(event);
1604 //If it doesn't intersect with the sortable, and it intersected before,
1605 //we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval
1606 if(this.instance.isOver) {
1608 this.instance.isOver = 0;
1609 this.instance.cancelHelperRemoval = true;
1611 //Prevent reverting on this forced stop
1612 this.instance.options.revert = false;
1614 // The out event needs to be triggered independently
1615 this.instance._trigger('out', event, this.instance._uiHash(this.instance));
1617 this.instance._mouseStop(event, true);
1618 this.instance.options.helper = this.instance.options._helper;
1620 //Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size
1621 this.instance.currentItem.remove();
1622 if(this.instance.placeholder) this.instance.placeholder.remove();
1624 inst._trigger("fromSortable", event);
1625 inst.dropped = false; //draggable revert needs that
1635 $.ui.plugin.add("draggable", "cursor", {
1636 start: function(event, ui) {
1637 var t = $('body'), o = $(this).data('draggable').options;
1638 if (t.css("cursor")) o._cursor = t.css("cursor");
1639 t.css("cursor", o.cursor);
1641 stop: function(event, ui) {
1642 var o = $(this).data('draggable').options;
1643 if (o._cursor) $('body').css("cursor", o._cursor);
1647 $.ui.plugin.add("draggable", "opacity", {
1648 start: function(event, ui) {
1649 var t = $(ui.helper), o = $(this).data('draggable').options;
1650 if(t.css("opacity")) o._opacity = t.css("opacity");
1651 t.css('opacity', o.opacity);
1653 stop: function(event, ui) {
1654 var o = $(this).data('draggable').options;
1655 if(o._opacity) $(ui.helper).css('opacity', o._opacity);
1659 $.ui.plugin.add("draggable", "scroll", {
1660 start: function(event, ui) {
1661 var i = $(this).data("draggable");
1662 if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') i.overflowOffset = i.scrollParent.offset();
1664 drag: function(event, ui) {
1666 var i = $(this).data("draggable"), o = i.options, scrolled = false;
1668 if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') {
1670 if(!o.axis || o.axis != 'x') {
1671 if((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
1672 i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed;
1673 else if(event.pageY - i.overflowOffset.top < o.scrollSensitivity)
1674 i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed;
1677 if(!o.axis || o.axis != 'y') {
1678 if((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
1679 i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed;
1680 else if(event.pageX - i.overflowOffset.left < o.scrollSensitivity)
1681 i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed;
1686 if(!o.axis || o.axis != 'x') {
1687 if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
1688 scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
1689 else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
1690 scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
1693 if(!o.axis || o.axis != 'y') {
1694 if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
1695 scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
1696 else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
1697 scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
1702 if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
1703 $.ui.ddmanager.prepareOffsets(i, event);
1708 $.ui.plugin.add("draggable", "snap", {
1709 start: function(event, ui) {
1711 var i = $(this).data("draggable"), o = i.options;
1712 i.snapElements = [];
1714 $(o.snap.constructor != String ? ( o.snap.items || ':data(draggable)' ) : o.snap).each(function() {
1715 var $t = $(this); var $o = $t.offset();
1716 if(this != i.element[0]) i.snapElements.push({
1718 width: $t.outerWidth(), height: $t.outerHeight(),
1719 top: $o.top, left: $o.left
1724 drag: function(event, ui) {
1726 var inst = $(this).data("draggable"), o = inst.options;
1727 var d = o.snapTolerance;
1729 var x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
1730 y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
1732 for (var i = inst.snapElements.length - 1; i >= 0; i--){
1734 var l = inst.snapElements[i].left, r = l + inst.snapElements[i].width,
1735 t = inst.snapElements[i].top, b = t + inst.snapElements[i].height;
1737 //Yes, I know, this is insane ;)
1738 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))) {
1739 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 })));
1740 inst.snapElements[i].snapping = false;
1744 if(o.snapMode != 'inner') {
1745 var ts = Math.abs(t - y2) <= d;
1746 var bs = Math.abs(b - y1) <= d;
1747 var ls = Math.abs(l - x2) <= d;
1748 var rs = Math.abs(r - x1) <= d;
1749 if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
1750 if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top;
1751 if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left;
1752 if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left;
1755 var first = (ts || bs || ls || rs);
1757 if(o.snapMode != 'outer') {
1758 var ts = Math.abs(t - y1) <= d;
1759 var bs = Math.abs(b - y2) <= d;
1760 var ls = Math.abs(l - x1) <= d;
1761 var rs = Math.abs(r - x2) <= d;
1762 if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top;
1763 if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
1764 if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left;
1765 if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left;
1768 if(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first))
1769 (inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
1770 inst.snapElements[i].snapping = (ts || bs || ls || rs || first);
1777 $.ui.plugin.add("draggable", "stack", {
1778 start: function(event, ui) {
1780 var o = $(this).data("draggable").options;
1782 var group = $.makeArray($(o.stack)).sort(function(a,b) {
1783 return (parseInt($(a).css("zIndex"),10) || 0) - (parseInt($(b).css("zIndex"),10) || 0);
1785 if (!group.length) { return; }
1787 var min = parseInt(group[0].style.zIndex) || 0;
1788 $(group).each(function(i) {
1789 this.style.zIndex = min + i;
1792 this[0].style.zIndex = min + group.length;
1797 $.ui.plugin.add("draggable", "zIndex", {
1798 start: function(event, ui) {
1799 var t = $(ui.helper), o = $(this).data("draggable").options;
1800 if(t.css("zIndex")) o._zIndex = t.css("zIndex");
1801 t.css('zIndex', o.zIndex);
1803 stop: function(event, ui) {
1804 var o = $(this).data("draggable").options;
1805 if(o._zIndex) $(ui.helper).css('zIndex', o._zIndex);
1811 * jQuery UI Droppable 1.8.14
1813 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
1814 * Dual licensed under the MIT or GPL Version 2 licenses.
1815 * http://jquery.org/license
1817 * http://docs.jquery.com/UI/Droppables
1821 * jquery.ui.widget.js
1822 * jquery.ui.mouse.js
1823 * jquery.ui.draggable.js
1825 (function( $, undefined ) {
1827 $.widget("ui.droppable", {
1828 widgetEventPrefix: "drop",
1836 tolerance: 'intersect'
1838 _create: function() {
1840 var o = this.options, accept = o.accept;
1841 this.isover = 0; this.isout = 1;
1843 this.accept = $.isFunction(accept) ? accept : function(d) {
1844 return d.is(accept);
1847 //Store the droppable's proportions
1848 this.proportions = { width: this.element[0].offsetWidth, height: this.element[0].offsetHeight };
1850 // Add the reference and positions to the manager
1851 $.ui.ddmanager.droppables[o.scope] = $.ui.ddmanager.droppables[o.scope] || [];
1852 $.ui.ddmanager.droppables[o.scope].push(this);
1854 (o.addClasses && this.element.addClass("ui-droppable"));
1858 destroy: function() {
1859 var drop = $.ui.ddmanager.droppables[this.options.scope];
1860 for ( var i = 0; i < drop.length; i++ )
1861 if ( drop[i] == this )
1865 .removeClass("ui-droppable ui-droppable-disabled")
1866 .removeData("droppable")
1867 .unbind(".droppable");
1872 _setOption: function(key, value) {
1874 if(key == 'accept') {
1875 this.accept = $.isFunction(value) ? value : function(d) {
1879 $.Widget.prototype._setOption.apply(this, arguments);
1882 _activate: function(event) {
1883 var draggable = $.ui.ddmanager.current;
1884 if(this.options.activeClass) this.element.addClass(this.options.activeClass);
1885 (draggable && this._trigger('activate', event, this.ui(draggable)));
1888 _deactivate: function(event) {
1889 var draggable = $.ui.ddmanager.current;
1890 if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
1891 (draggable && this._trigger('deactivate', event, this.ui(draggable)));
1894 _over: function(event) {
1896 var draggable = $.ui.ddmanager.current;
1897 if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
1899 if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
1900 if(this.options.hoverClass) this.element.addClass(this.options.hoverClass);
1901 this._trigger('over', event, this.ui(draggable));
1906 _out: function(event) {
1908 var draggable = $.ui.ddmanager.current;
1909 if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
1911 if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
1912 if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
1913 this._trigger('out', event, this.ui(draggable));
1918 _drop: function(event,custom) {
1920 var draggable = custom || $.ui.ddmanager.current;
1921 if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return false; // Bail if draggable and droppable are same element
1923 var childrenIntersection = false;
1924 this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function() {
1925 var inst = $.data(this, 'droppable');
1928 && !inst.options.disabled
1929 && inst.options.scope == draggable.options.scope
1930 && inst.accept.call(inst.element[0], (draggable.currentItem || draggable.element))
1931 && $.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance)
1932 ) { childrenIntersection = true; return false; }
1934 if(childrenIntersection) return false;
1936 if(this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
1937 if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
1938 if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
1939 this._trigger('drop', event, this.ui(draggable));
1940 return this.element;
1949 draggable: (c.currentItem || c.element),
1951 position: c.position,
1952 offset: c.positionAbs
1958 $.extend($.ui.droppable, {
1962 $.ui.intersect = function(draggable, droppable, toleranceMode) {
1964 if (!droppable.offset) return false;
1966 var x1 = (draggable.positionAbs || draggable.position.absolute).left, x2 = x1 + draggable.helperProportions.width,
1967 y1 = (draggable.positionAbs || draggable.position.absolute).top, y2 = y1 + draggable.helperProportions.height;
1968 var l = droppable.offset.left, r = l + droppable.proportions.width,
1969 t = droppable.offset.top, b = t + droppable.proportions.height;
1971 switch (toleranceMode) {
1973 return (l <= x1 && x2 <= r
1974 && t <= y1 && y2 <= b);
1977 return (l < x1 + (draggable.helperProportions.width / 2) // Right Half
1978 && x2 - (draggable.helperProportions.width / 2) < r // Left Half
1979 && t < y1 + (draggable.helperProportions.height / 2) // Bottom Half
1980 && y2 - (draggable.helperProportions.height / 2) < b ); // Top Half
1983 var draggableLeft = ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left),
1984 draggableTop = ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top),
1985 isOver = $.ui.isOver(draggableTop, draggableLeft, t, l, droppable.proportions.height, droppable.proportions.width);
1990 (y1 >= t && y1 <= b) || // Top edge touching
1991 (y2 >= t && y2 <= b) || // Bottom edge touching
1992 (y1 < t && y2 > b) // Surrounded vertically
1994 (x1 >= l && x1 <= r) || // Left edge touching
1995 (x2 >= l && x2 <= r) || // Right edge touching
1996 (x1 < l && x2 > r) // Surrounded horizontally
2007 This manager tracks offsets of draggables and droppables
2011 droppables: { 'default': [] },
2012 prepareOffsets: function(t, event) {
2014 var m = $.ui.ddmanager.droppables[t.options.scope] || [];
2015 var type = event ? event.type : null; // workaround for #2317
2016 var list = (t.currentItem || t.element).find(":data(droppable)").andSelf();
2018 droppablesLoop: for (var i = 0; i < m.length; i++) {
2020 if(m[i].options.disabled || (t && !m[i].accept.call(m[i].element[0],(t.currentItem || t.element)))) continue; //No disabled and non-accepted
2021 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
2022 m[i].visible = m[i].element.css("display") != "none"; if(!m[i].visible) continue; //If the element is not visible, continue
2024 if(type == "mousedown") m[i]._activate.call(m[i], event); //Activate the droppable if used directly from draggables
2026 m[i].offset = m[i].element.offset();
2027 m[i].proportions = { width: m[i].element[0].offsetWidth, height: m[i].element[0].offsetHeight };
2032 drop: function(draggable, event) {
2034 var dropped = false;
2035 $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
2037 if(!this.options) return;
2038 if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance))
2039 dropped = dropped || this._drop.call(this, event);
2041 if (!this.options.disabled && this.visible && this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
2042 this.isout = 1; this.isover = 0;
2043 this._deactivate.call(this, event);
2050 dragStart: function( draggable, event ) {
2051 //Listen for scrolling so that if the dragging causes scrolling the position of the droppables can be recalculated (see #5003)
2052 draggable.element.parentsUntil( "body" ).bind( "scroll.droppable", function() {
2053 if( !draggable.options.refreshPositions ) $.ui.ddmanager.prepareOffsets( draggable, event );
2056 drag: function(draggable, event) {
2058 //If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse.
2059 if(draggable.options.refreshPositions) $.ui.ddmanager.prepareOffsets(draggable, event);
2061 //Run through all droppables and check their positions based on specific tolerance options
2062 $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
2064 if(this.options.disabled || this.greedyChild || !this.visible) return;
2065 var intersects = $.ui.intersect(draggable, this, this.options.tolerance);
2067 var c = !intersects && this.isover == 1 ? 'isout' : (intersects && this.isover == 0 ? 'isover' : null);
2071 if (this.options.greedy) {
2072 var parent = this.element.parents(':data(droppable):eq(0)');
2073 if (parent.length) {
2074 parentInstance = $.data(parent[0], 'droppable');
2075 parentInstance.greedyChild = (c == 'isover' ? 1 : 0);
2079 // we just moved into a greedy child
2080 if (parentInstance && c == 'isover') {
2081 parentInstance['isover'] = 0;
2082 parentInstance['isout'] = 1;
2083 parentInstance._out.call(parentInstance, event);
2086 this[c] = 1; this[c == 'isout' ? 'isover' : 'isout'] = 0;
2087 this[c == "isover" ? "_over" : "_out"].call(this, event);
2089 // we just moved out of a greedy child
2090 if (parentInstance && c == 'isout') {
2091 parentInstance['isout'] = 0;
2092 parentInstance['isover'] = 1;
2093 parentInstance._over.call(parentInstance, event);
2098 dragStop: function( draggable, event ) {
2099 draggable.element.parentsUntil( "body" ).unbind( "scroll.droppable" );
2100 //Call prepareOffsets one final time since IE does not fire return scroll events when overflow was caused by drag (see #5003)
2101 if( !draggable.options.refreshPositions ) $.ui.ddmanager.prepareOffsets( draggable, event );
2107 * jQuery UI Resizable 1.8.14
2109 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
2110 * Dual licensed under the MIT or GPL Version 2 licenses.
2111 * http://jquery.org/license
2113 * http://docs.jquery.com/UI/Resizables
2117 * jquery.ui.mouse.js
2118 * jquery.ui.widget.js
2120 (function( $, undefined ) {
2122 $.widget("ui.resizable", $.ui.mouse, {
2123 widgetEventPrefix: "resize",
2127 animateDuration: "slow",
2128 animateEasing: "swing",
2142 _create: function() {
2144 var self = this, o = this.options;
2145 this.element.addClass("ui-resizable");
2148 _aspectRatio: !!(o.aspectRatio),
2149 aspectRatio: o.aspectRatio,
2150 originalElement: this.element,
2151 _proportionallyResizeElements: [],
2152 _helper: o.helper || o.ghost || o.animate ? o.helper || 'ui-resizable-helper' : null
2155 //Wrap the element if it cannot hold child nodes
2156 if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) {
2158 //Opera fix for relative positioning
2159 if (/relative/.test(this.element.css('position')) && $.browser.opera)
2160 this.element.css({ position: 'relative', top: 'auto', left: 'auto' });
2162 //Create a wrapper element and set the wrapper to the new current internal element
2164 $('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({
2165 position: this.element.css('position'),
2166 width: this.element.outerWidth(),
2167 height: this.element.outerHeight(),
2168 top: this.element.css('top'),
2169 left: this.element.css('left')
2173 //Overwrite the original this.element
2174 this.element = this.element.parent().data(
2175 "resizable", this.element.data('resizable')
2178 this.elementIsWrapper = true;
2180 //Move margins to the wrapper
2181 this.element.css({ marginLeft: this.originalElement.css("marginLeft"), marginTop: this.originalElement.css("marginTop"), marginRight: this.originalElement.css("marginRight"), marginBottom: this.originalElement.css("marginBottom") });
2182 this.originalElement.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0});
2184 //Prevent Safari textarea resize
2185 this.originalResizeStyle = this.originalElement.css('resize');
2186 this.originalElement.css('resize', 'none');
2188 //Push the actual element to our proportionallyResize internal array
2189 this._proportionallyResizeElements.push(this.originalElement.css({ position: 'static', zoom: 1, display: 'block' }));
2191 // avoid IE jump (hard set the margin)
2192 this.originalElement.css({ margin: this.originalElement.css('margin') });
2194 // fix handlers offset
2195 this._proportionallyResize();
2199 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' });
2200 if(this.handles.constructor == String) {
2202 if(this.handles == 'all') this.handles = 'n,e,s,w,se,sw,ne,nw';
2203 var n = this.handles.split(","); this.handles = {};
2205 for(var i = 0; i < n.length; i++) {
2207 var handle = $.trim(n[i]), hname = 'ui-resizable-'+handle;
2208 var axis = $('<div class="ui-resizable-handle ' + hname + '"></div>');
2210 // increase zIndex of sw, se, ne, nw axis
2211 //TODO : this modifies original option
2212 if(/sw|se|ne|nw/.test(handle)) axis.css({ zIndex: ++o.zIndex });
2214 //TODO : What's going on here?
2215 if ('se' == handle) {
2216 axis.addClass('ui-icon ui-icon-gripsmall-diagonal-se');
2219 //Insert into internal handles object and append to element
2220 this.handles[handle] = '.ui-resizable-'+handle;
2221 this.element.append(axis);
2226 this._renderAxis = function(target) {
2228 target = target || this.element;
2230 for(var i in this.handles) {
2232 if(this.handles[i].constructor == String)
2233 this.handles[i] = $(this.handles[i], this.element).show();
2235 //Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls)
2236 if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) {
2238 var axis = $(this.handles[i], this.element), padWrapper = 0;
2240 //Checking the correct pad and border
2241 padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth();
2243 //The padding type i have to apply...
2244 var padPos = [ 'padding',
2245 /ne|nw|n/.test(i) ? 'Top' :
2246 /se|sw|s/.test(i) ? 'Bottom' :
2247 /^e$/.test(i) ? 'Right' : 'Left' ].join("");
2249 target.css(padPos, padWrapper);
2251 this._proportionallyResize();
2255 //TODO: What's that good for? There's not anything to be executed left
2256 if(!$(this.handles[i]).length)
2262 //TODO: make renderAxis a prototype function
2263 this._renderAxis(this.element);
2265 this._handles = $('.ui-resizable-handle', this.element)
2266 .disableSelection();
2268 //Matching axis name
2269 this._handles.mouseover(function() {
2270 if (!self.resizing) {
2272 var axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);
2273 //Axis, default = se
2274 self.axis = axis && axis[1] ? axis[1] : 'se';
2278 //If we want to auto hide the elements
2280 this._handles.hide();
2282 .addClass("ui-resizable-autohide")
2284 if (o.disabled) return;
2285 $(this).removeClass("ui-resizable-autohide");
2286 self._handles.show();
2289 if (o.disabled) return;
2290 if (!self.resizing) {
2291 $(this).addClass("ui-resizable-autohide");
2292 self._handles.hide();
2297 //Initialize the mouse interaction
2302 destroy: function() {
2304 this._mouseDestroy();
2306 var _destroy = function(exp) {
2307 $(exp).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing")
2308 .removeData("resizable").unbind(".resizable").find('.ui-resizable-handle').remove();
2311 //TODO: Unwrap at same DOM position
2312 if (this.elementIsWrapper) {
2313 _destroy(this.element);
2314 var wrapper = this.element;
2316 this.originalElement.css({
2317 position: wrapper.css('position'),
2318 width: wrapper.outerWidth(),
2319 height: wrapper.outerHeight(),
2320 top: wrapper.css('top'),
2321 left: wrapper.css('left')
2326 this.originalElement.css('resize', this.originalResizeStyle);
2327 _destroy(this.originalElement);
2332 _mouseCapture: function(event) {
2334 for (var i in this.handles) {
2335 if ($(this.handles[i])[0] == event.target) {
2340 return !this.options.disabled && handle;
2343 _mouseStart: function(event) {
2345 var o = this.options, iniPos = this.element.position(), el = this.element;
2347 this.resizing = true;
2348 this.documentScroll = { top: $(document).scrollTop(), left: $(document).scrollLeft() };
2350 // bugfix for http://dev.jquery.com/ticket/1749
2351 if (el.is('.ui-draggable') || (/absolute/).test(el.css('position'))) {
2352 el.css({ position: 'absolute', top: iniPos.top, left: iniPos.left });
2355 //Opera fixing relative position
2356 if ($.browser.opera && (/relative/).test(el.css('position')))
2357 el.css({ position: 'relative', top: 'auto', left: 'auto' });
2359 this._renderProxy();
2361 var curleft = num(this.helper.css('left')), curtop = num(this.helper.css('top'));
2363 if (o.containment) {
2364 curleft += $(o.containment).scrollLeft() || 0;
2365 curtop += $(o.containment).scrollTop() || 0;
2368 //Store needed variables
2369 this.offset = this.helper.offset();
2370 this.position = { left: curleft, top: curtop };
2371 this.size = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
2372 this.originalSize = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
2373 this.originalPosition = { left: curleft, top: curtop };
2374 this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() };
2375 this.originalMousePosition = { left: event.pageX, top: event.pageY };
2378 this.aspectRatio = (typeof o.aspectRatio == 'number') ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1);
2380 var cursor = $('.ui-resizable-' + this.axis).css('cursor');
2381 $('body').css('cursor', cursor == 'auto' ? this.axis + '-resize' : cursor);
2383 el.addClass("ui-resizable-resizing");
2384 this._propagate("start", event);
2388 _mouseDrag: function(event) {
2390 //Increase performance, avoid regex
2391 var el = this.helper, o = this.options, props = {},
2392 self = this, smp = this.originalMousePosition, a = this.axis;
2394 var dx = (event.pageX-smp.left)||0, dy = (event.pageY-smp.top)||0;
2395 var trigger = this._change[a];
2396 if (!trigger) return false;
2398 // Calculate the attrs that will be change
2399 var data = trigger.apply(this, [event, dx, dy]), ie6 = $.browser.msie && $.browser.version < 7, csdif = this.sizeDiff;
2401 // Put this in the mouseDrag handler since the user can start pressing shift while resizing
2402 this._updateVirtualBoundaries(event.shiftKey);
2403 if (this._aspectRatio || event.shiftKey)
2404 data = this._updateRatio(data, event);
2406 data = this._respectSize(data, event);
2408 // plugins callbacks need to be called first
2409 this._propagate("resize", event);
2412 top: this.position.top + "px", left: this.position.left + "px",
2413 width: this.size.width + "px", height: this.size.height + "px"
2416 if (!this._helper && this._proportionallyResizeElements.length)
2417 this._proportionallyResize();
2419 this._updateCache(data);
2421 // calling the user callback at the end
2422 this._trigger('resize', event, this.ui());
2427 _mouseStop: function(event) {
2429 this.resizing = false;
2430 var o = this.options, self = this;
2433 var pr = this._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
2434 soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
2435 soffsetw = ista ? 0 : self.sizeDiff.width;
2437 var s = { width: (self.helper.width() - soffsetw), height: (self.helper.height() - soffseth) },
2438 left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
2439 top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
2442 this.element.css($.extend(s, { top: top, left: left }));
2444 self.helper.height(self.size.height);
2445 self.helper.width(self.size.width);
2447 if (this._helper && !o.animate) this._proportionallyResize();
2450 $('body').css('cursor', 'auto');
2452 this.element.removeClass("ui-resizable-resizing");
2454 this._propagate("stop", event);
2456 if (this._helper) this.helper.remove();
2461 _updateVirtualBoundaries: function(forceAspectRatio) {
2462 var o = this.options, pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b;
2465 minWidth: isNumber(o.minWidth) ? o.minWidth : 0,
2466 maxWidth: isNumber(o.maxWidth) ? o.maxWidth : Infinity,
2467 minHeight: isNumber(o.minHeight) ? o.minHeight : 0,
2468 maxHeight: isNumber(o.maxHeight) ? o.maxHeight : Infinity
2471 if(this._aspectRatio || forceAspectRatio) {
2472 // We want to create an enclosing box whose aspect ration is the requested one
2473 // First, compute the "projected" size for each dimension based on the aspect ratio and other dimension
2474 pMinWidth = b.minHeight * this.aspectRatio;
2475 pMinHeight = b.minWidth / this.aspectRatio;
2476 pMaxWidth = b.maxHeight * this.aspectRatio;
2477 pMaxHeight = b.maxWidth / this.aspectRatio;
2479 if(pMinWidth > b.minWidth) b.minWidth = pMinWidth;
2480 if(pMinHeight > b.minHeight) b.minHeight = pMinHeight;
2481 if(pMaxWidth < b.maxWidth) b.maxWidth = pMaxWidth;
2482 if(pMaxHeight < b.maxHeight) b.maxHeight = pMaxHeight;
2484 this._vBoundaries = b;
2487 _updateCache: function(data) {
2488 var o = this.options;
2489 this.offset = this.helper.offset();
2490 if (isNumber(data.left)) this.position.left = data.left;
2491 if (isNumber(data.top)) this.position.top = data.top;
2492 if (isNumber(data.height)) this.size.height = data.height;
2493 if (isNumber(data.width)) this.size.width = data.width;
2496 _updateRatio: function(data, event) {
2498 var o = this.options, cpos = this.position, csize = this.size, a = this.axis;
2500 if (isNumber(data.height)) data.width = (data.height * this.aspectRatio);
2501 else if (isNumber(data.width)) data.height = (data.width / this.aspectRatio);
2504 data.left = cpos.left + (csize.width - data.width);
2508 data.top = cpos.top + (csize.height - data.height);
2509 data.left = cpos.left + (csize.width - data.width);
2515 _respectSize: function(data, event) {
2517 var el = this.helper, o = this._vBoundaries, pRatio = this._aspectRatio || event.shiftKey, a = this.axis,
2518 ismaxw = isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh = isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height),
2519 isminw = isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh = isNumber(data.height) && o.minHeight && (o.minHeight > data.height);
2521 if (isminw) data.width = o.minWidth;
2522 if (isminh) data.height = o.minHeight;
2523 if (ismaxw) data.width = o.maxWidth;
2524 if (ismaxh) data.height = o.maxHeight;
2526 var dw = this.originalPosition.left + this.originalSize.width, dh = this.position.top + this.size.height;
2527 var cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a);
2529 if (isminw && cw) data.left = dw - o.minWidth;
2530 if (ismaxw && cw) data.left = dw - o.maxWidth;
2531 if (isminh && ch) data.top = dh - o.minHeight;
2532 if (ismaxh && ch) data.top = dh - o.maxHeight;
2534 // fixing jump error on top/left - bug #2330
2535 var isNotwh = !data.width && !data.height;
2536 if (isNotwh && !data.left && data.top) data.top = null;
2537 else if (isNotwh && !data.top && data.left) data.left = null;
2542 _proportionallyResize: function() {
2544 var o = this.options;
2545 if (!this._proportionallyResizeElements.length) return;
2546 var element = this.helper || this.element;
2548 for (var i=0; i < this._proportionallyResizeElements.length; i++) {
2550 var prel = this._proportionallyResizeElements[i];
2552 if (!this.borderDif) {
2553 var b = [prel.css('borderTopWidth'), prel.css('borderRightWidth'), prel.css('borderBottomWidth'), prel.css('borderLeftWidth')],
2554 p = [prel.css('paddingTop'), prel.css('paddingRight'), prel.css('paddingBottom'), prel.css('paddingLeft')];
2556 this.borderDif = $.map(b, function(v, i) {
2557 var border = parseInt(v,10)||0, padding = parseInt(p[i],10)||0;
2558 return border + padding;
2562 if ($.browser.msie && !(!($(element).is(':hidden') || $(element).parents(':hidden').length)))
2566 height: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0,
2567 width: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0
2574 _renderProxy: function() {
2576 var el = this.element, o = this.options;
2577 this.elementOffset = el.offset();
2581 this.helper = this.helper || $('<div style="overflow:hidden;"></div>');
2583 // fix ie6 offset TODO: This seems broken
2584 var ie6 = $.browser.msie && $.browser.version < 7, ie6offset = (ie6 ? 1 : 0),
2585 pxyoffset = ( ie6 ? 2 : -1 );
2587 this.helper.addClass(this._helper).css({
2588 width: this.element.outerWidth() + pxyoffset,
2589 height: this.element.outerHeight() + pxyoffset,
2590 position: 'absolute',
2591 left: this.elementOffset.left - ie6offset +'px',
2592 top: this.elementOffset.top - ie6offset +'px',
2593 zIndex: ++o.zIndex //TODO: Don't modify option
2598 .disableSelection();
2601 this.helper = this.element;
2607 e: function(event, dx, dy) {
2608 return { width: this.originalSize.width + dx };
2610 w: function(event, dx, dy) {
2611 var o = this.options, cs = this.originalSize, sp = this.originalPosition;
2612 return { left: sp.left + dx, width: cs.width - dx };
2614 n: function(event, dx, dy) {
2615 var o = this.options, cs = this.originalSize, sp = this.originalPosition;
2616 return { top: sp.top + dy, height: cs.height - dy };
2618 s: function(event, dx, dy) {
2619 return { height: this.originalSize.height + dy };
2621 se: function(event, dx, dy) {
2622 return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
2624 sw: function(event, dx, dy) {
2625 return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
2627 ne: function(event, dx, dy) {
2628 return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
2630 nw: function(event, dx, dy) {
2631 return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
2635 _propagate: function(n, event) {
2636 $.ui.plugin.call(this, n, [event, this.ui()]);
2637 (n != "resize" && this._trigger(n, event, this.ui()));
2644 originalElement: this.originalElement,
2645 element: this.element,
2646 helper: this.helper,
2647 position: this.position,
2649 originalSize: this.originalSize,
2650 originalPosition: this.originalPosition
2656 $.extend($.ui.resizable, {
2661 * Resizable Extensions
2664 $.ui.plugin.add("resizable", "alsoResize", {
2666 start: function (event, ui) {
2667 var self = $(this).data("resizable"), o = self.options;
2669 var _store = function (exp) {
2670 $(exp).each(function() {
2672 el.data("resizable-alsoresize", {
2673 width: parseInt(el.width(), 10), height: parseInt(el.height(), 10),
2674 left: parseInt(el.css('left'), 10), top: parseInt(el.css('top'), 10),
2675 position: el.css('position') // to reset Opera on stop()
2680 if (typeof(o.alsoResize) == 'object' && !o.alsoResize.parentNode) {
2681 if (o.alsoResize.length) { o.alsoResize = o.alsoResize[0]; _store(o.alsoResize); }
2682 else { $.each(o.alsoResize, function (exp) { _store(exp); }); }
2684 _store(o.alsoResize);
2688 resize: function (event, ui) {
2689 var self = $(this).data("resizable"), o = self.options, os = self.originalSize, op = self.originalPosition;
2692 height: (self.size.height - os.height) || 0, width: (self.size.width - os.width) || 0,
2693 top: (self.position.top - op.top) || 0, left: (self.position.left - op.left) || 0
2696 _alsoResize = function (exp, c) {
2697 $(exp).each(function() {
2698 var el = $(this), start = $(this).data("resizable-alsoresize"), style = {},
2699 css = c && c.length ? c : el.parents(ui.originalElement[0]).length ? ['width', 'height'] : ['width', 'height', 'top', 'left'];
2701 $.each(css, function (i, prop) {
2702 var sum = (start[prop]||0) + (delta[prop]||0);
2703 if (sum && sum >= 0)
2704 style[prop] = sum || null;
2707 // Opera fixing relative position
2708 if ($.browser.opera && /relative/.test(el.css('position'))) {
2709 self._revertToRelativePosition = true;
2710 el.css({ position: 'absolute', top: 'auto', left: 'auto' });
2717 if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) {
2718 $.each(o.alsoResize, function (exp, c) { _alsoResize(exp, c); });
2720 _alsoResize(o.alsoResize);
2724 stop: function (event, ui) {
2725 var self = $(this).data("resizable"), o = self.options;
2727 var _reset = function (exp) {
2728 $(exp).each(function() {
2730 // reset position for Opera - no need to verify it was changed
2731 el.css({ position: el.data("resizable-alsoresize").position });
2735 if (self._revertToRelativePosition) {
2736 self._revertToRelativePosition = false;
2737 if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) {
2738 $.each(o.alsoResize, function (exp) { _reset(exp); });
2740 _reset(o.alsoResize);
2744 $(this).removeData("resizable-alsoresize");
2748 $.ui.plugin.add("resizable", "animate", {
2750 stop: function(event, ui) {
2751 var self = $(this).data("resizable"), o = self.options;
2753 var pr = self._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
2754 soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
2755 soffsetw = ista ? 0 : self.sizeDiff.width;
2757 var style = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },
2758 left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
2759 top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
2761 self.element.animate(
2762 $.extend(style, top && left ? { top: top, left: left } : {}), {
2763 duration: o.animateDuration,
2764 easing: o.animateEasing,
2768 width: parseInt(self.element.css('width'), 10),
2769 height: parseInt(self.element.css('height'), 10),
2770 top: parseInt(self.element.css('top'), 10),
2771 left: parseInt(self.element.css('left'), 10)
2774 if (pr && pr.length) $(pr[0]).css({ width: data.width, height: data.height });
2776 // propagating resize, and updating values for each animation step
2777 self._updateCache(data);
2778 self._propagate("resize", event);
2787 $.ui.plugin.add("resizable", "containment", {
2789 start: function(event, ui) {
2790 var self = $(this).data("resizable"), o = self.options, el = self.element;
2791 var oc = o.containment, ce = (oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc;
2794 self.containerElement = $(ce);
2796 if (/document/.test(oc) || oc == document) {
2797 self.containerOffset = { left: 0, top: 0 };
2798 self.containerPosition = { left: 0, top: 0 };
2801 element: $(document), left: 0, top: 0,
2802 width: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight
2806 // i'm a node, so compute top, left, right, bottom
2808 var element = $(ce), p = [];
2809 $([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) { p[i] = num(element.css("padding" + name)); });
2811 self.containerOffset = element.offset();
2812 self.containerPosition = element.position();
2813 self.containerSize = { height: (element.innerHeight() - p[3]), width: (element.innerWidth() - p[1]) };
2815 var co = self.containerOffset, ch = self.containerSize.height, cw = self.containerSize.width,
2816 width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw ), height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch);
2819 element: ce, left: co.left, top: co.top, width: width, height: height
2824 resize: function(event, ui) {
2825 var self = $(this).data("resizable"), o = self.options,
2826 ps = self.containerSize, co = self.containerOffset, cs = self.size, cp = self.position,
2827 pRatio = self._aspectRatio || event.shiftKey, cop = { top:0, left:0 }, ce = self.containerElement;
2829 if (ce[0] != document && (/static/).test(ce.css('position'))) cop = co;
2831 if (cp.left < (self._helper ? co.left : 0)) {
2832 self.size.width = self.size.width + (self._helper ? (self.position.left - co.left) : (self.position.left - cop.left));
2833 if (pRatio) self.size.height = self.size.width / o.aspectRatio;
2834 self.position.left = o.helper ? co.left : 0;
2837 if (cp.top < (self._helper ? co.top : 0)) {
2838 self.size.height = self.size.height + (self._helper ? (self.position.top - co.top) : self.position.top);
2839 if (pRatio) self.size.width = self.size.height * o.aspectRatio;
2840 self.position.top = self._helper ? co.top : 0;
2843 self.offset.left = self.parentData.left+self.position.left;
2844 self.offset.top = self.parentData.top+self.position.top;
2846 var woset = Math.abs( (self._helper ? self.offset.left - cop.left : (self.offset.left - cop.left)) + self.sizeDiff.width ),
2847 hoset = Math.abs( (self._helper ? self.offset.top - cop.top : (self.offset.top - co.top)) + self.sizeDiff.height );
2849 var isParent = self.containerElement.get(0) == self.element.parent().get(0),
2850 isOffsetRelative = /relative|absolute/.test(self.containerElement.css('position'));
2852 if(isParent && isOffsetRelative) woset -= self.parentData.left;
2854 if (woset + self.size.width >= self.parentData.width) {
2855 self.size.width = self.parentData.width - woset;
2856 if (pRatio) self.size.height = self.size.width / self.aspectRatio;
2859 if (hoset + self.size.height >= self.parentData.height) {
2860 self.size.height = self.parentData.height - hoset;
2861 if (pRatio) self.size.width = self.size.height * self.aspectRatio;
2865 stop: function(event, ui){
2866 var self = $(this).data("resizable"), o = self.options, cp = self.position,
2867 co = self.containerOffset, cop = self.containerPosition, ce = self.containerElement;
2869 var helper = $(self.helper), ho = helper.offset(), w = helper.outerWidth() - self.sizeDiff.width, h = helper.outerHeight() - self.sizeDiff.height;
2871 if (self._helper && !o.animate && (/relative/).test(ce.css('position')))
2872 $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
2874 if (self._helper && !o.animate && (/static/).test(ce.css('position')))
2875 $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
2880 $.ui.plugin.add("resizable", "ghost", {
2882 start: function(event, ui) {
2884 var self = $(this).data("resizable"), o = self.options, cs = self.size;
2886 self.ghost = self.originalElement.clone();
2888 .css({ opacity: .25, display: 'block', position: 'relative', height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 })
2889 .addClass('ui-resizable-ghost')
2890 .addClass(typeof o.ghost == 'string' ? o.ghost : '');
2892 self.ghost.appendTo(self.helper);
2896 resize: function(event, ui){
2897 var self = $(this).data("resizable"), o = self.options;
2898 if (self.ghost) self.ghost.css({ position: 'relative', height: self.size.height, width: self.size.width });
2901 stop: function(event, ui){
2902 var self = $(this).data("resizable"), o = self.options;
2903 if (self.ghost && self.helper) self.helper.get(0).removeChild(self.ghost.get(0));
2908 $.ui.plugin.add("resizable", "grid", {
2910 resize: function(event, ui) {
2911 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;
2912 o.grid = typeof o.grid == "number" ? [o.grid, o.grid] : o.grid;
2913 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);
2915 if (/^(se|s|e)$/.test(a)) {
2916 self.size.width = os.width + ox;
2917 self.size.height = os.height + oy;
2919 else if (/^(ne)$/.test(a)) {
2920 self.size.width = os.width + ox;
2921 self.size.height = os.height + oy;
2922 self.position.top = op.top - oy;
2924 else if (/^(sw)$/.test(a)) {
2925 self.size.width = os.width + ox;
2926 self.size.height = os.height + oy;
2927 self.position.left = op.left - ox;
2930 self.size.width = os.width + ox;
2931 self.size.height = os.height + oy;
2932 self.position.top = op.top - oy;
2933 self.position.left = op.left - ox;
2939 var num = function(v) {
2940 return parseInt(v, 10) || 0;
2943 var isNumber = function(value) {
2944 return !isNaN(parseInt(value, 10));
2949 * jQuery UI Selectable 1.8.14
2951 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
2952 * Dual licensed under the MIT or GPL Version 2 licenses.
2953 * http://jquery.org/license
2955 * http://docs.jquery.com/UI/Selectables
2959 * jquery.ui.mouse.js
2960 * jquery.ui.widget.js
2962 (function( $, undefined ) {
2964 $.widget("ui.selectable", $.ui.mouse, {
2972 _create: function() {
2975 this.element.addClass("ui-selectable");
2977 this.dragged = false;
2979 // cache selectee children based on filter
2981 this.refresh = function() {
2982 selectees = $(self.options.filter, self.element[0]);
2983 selectees.each(function() {
2984 var $this = $(this);
2985 var pos = $this.offset();
2986 $.data(this, "selectable-item", {
2991 right: pos.left + $this.outerWidth(),
2992 bottom: pos.top + $this.outerHeight(),
2993 startselected: false,
2994 selected: $this.hasClass('ui-selected'),
2995 selecting: $this.hasClass('ui-selecting'),
2996 unselecting: $this.hasClass('ui-unselecting')
3002 this.selectees = selectees.addClass("ui-selectee");
3006 this.helper = $("<div class='ui-selectable-helper'></div>");
3009 destroy: function() {
3011 .removeClass("ui-selectee")
3012 .removeData("selectable-item");
3014 .removeClass("ui-selectable ui-selectable-disabled")
3015 .removeData("selectable")
3016 .unbind(".selectable");
3017 this._mouseDestroy();
3022 _mouseStart: function(event) {
3025 this.opos = [event.pageX, event.pageY];
3027 if (this.options.disabled)
3030 var options = this.options;
3032 this.selectees = $(options.filter, this.element[0]);
3034 this._trigger("start", event);
3036 $(options.appendTo).append(this.helper);
3037 // position helper (lasso)
3039 "left": event.clientX,
3040 "top": event.clientY,
3045 if (options.autoRefresh) {
3049 this.selectees.filter('.ui-selected').each(function() {
3050 var selectee = $.data(this, "selectable-item");
3051 selectee.startselected = true;
3052 if (!event.metaKey) {
3053 selectee.$element.removeClass('ui-selected');
3054 selectee.selected = false;
3055 selectee.$element.addClass('ui-unselecting');
3056 selectee.unselecting = true;
3057 // selectable UNSELECTING callback
3058 self._trigger("unselecting", event, {
3059 unselecting: selectee.element
3064 $(event.target).parents().andSelf().each(function() {
3065 var selectee = $.data(this, "selectable-item");
3067 var doSelect = !event.metaKey || !selectee.$element.hasClass('ui-selected');
3069 .removeClass(doSelect ? "ui-unselecting" : "ui-selected")
3070 .addClass(doSelect ? "ui-selecting" : "ui-unselecting");
3071 selectee.unselecting = !doSelect;
3072 selectee.selecting = doSelect;
3073 selectee.selected = doSelect;
3074 // selectable (UN)SELECTING callback
3076 self._trigger("selecting", event, {
3077 selecting: selectee.element
3080 self._trigger("unselecting", event, {
3081 unselecting: selectee.element
3090 _mouseDrag: function(event) {
3092 this.dragged = true;
3094 if (this.options.disabled)
3097 var options = this.options;
3099 var x1 = this.opos[0], y1 = this.opos[1], x2 = event.pageX, y2 = event.pageY;
3100 if (x1 > x2) { var tmp = x2; x2 = x1; x1 = tmp; }
3101 if (y1 > y2) { var tmp = y2; y2 = y1; y1 = tmp; }
3102 this.helper.css({left: x1, top: y1, width: x2-x1, height: y2-y1});
3104 this.selectees.each(function() {
3105 var selectee = $.data(this, "selectable-item");
3106 //prevent helper from being selected if appendTo: selectable
3107 if (!selectee || selectee.element == self.element[0])
3110 if (options.tolerance == 'touch') {
3111 hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) );
3112 } else if (options.tolerance == 'fit') {
3113 hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2);
3118 if (selectee.selected) {
3119 selectee.$element.removeClass('ui-selected');
3120 selectee.selected = false;
3122 if (selectee.unselecting) {
3123 selectee.$element.removeClass('ui-unselecting');
3124 selectee.unselecting = false;
3126 if (!selectee.selecting) {
3127 selectee.$element.addClass('ui-selecting');
3128 selectee.selecting = true;
3129 // selectable SELECTING callback
3130 self._trigger("selecting", event, {
3131 selecting: selectee.element
3136 if (selectee.selecting) {
3137 if (event.metaKey && selectee.startselected) {
3138 selectee.$element.removeClass('ui-selecting');
3139 selectee.selecting = false;
3140 selectee.$element.addClass('ui-selected');
3141 selectee.selected = true;
3143 selectee.$element.removeClass('ui-selecting');
3144 selectee.selecting = false;
3145 if (selectee.startselected) {
3146 selectee.$element.addClass('ui-unselecting');
3147 selectee.unselecting = true;
3149 // selectable UNSELECTING callback
3150 self._trigger("unselecting", event, {
3151 unselecting: selectee.element
3155 if (selectee.selected) {
3156 if (!event.metaKey && !selectee.startselected) {
3157 selectee.$element.removeClass('ui-selected');
3158 selectee.selected = false;
3160 selectee.$element.addClass('ui-unselecting');
3161 selectee.unselecting = true;
3162 // selectable UNSELECTING callback
3163 self._trigger("unselecting", event, {
3164 unselecting: selectee.element
3174 _mouseStop: function(event) {
3177 this.dragged = false;
3179 var options = this.options;
3181 $('.ui-unselecting', this.element[0]).each(function() {
3182 var selectee = $.data(this, "selectable-item");
3183 selectee.$element.removeClass('ui-unselecting');
3184 selectee.unselecting = false;
3185 selectee.startselected = false;
3186 self._trigger("unselected", event, {
3187 unselected: selectee.element
3190 $('.ui-selecting', this.element[0]).each(function() {
3191 var selectee = $.data(this, "selectable-item");
3192 selectee.$element.removeClass('ui-selecting').addClass('ui-selected');
3193 selectee.selecting = false;
3194 selectee.selected = true;
3195 selectee.startselected = true;
3196 self._trigger("selected", event, {
3197 selected: selectee.element
3200 this._trigger("stop", event);
3202 this.helper.remove();
3209 $.extend($.ui.selectable, {
3215 * jQuery UI Sortable 1.8.14
3217 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
3218 * Dual licensed under the MIT or GPL Version 2 licenses.
3219 * http://jquery.org/license
3221 * http://docs.jquery.com/UI/Sortables
3225 * jquery.ui.mouse.js
3226 * jquery.ui.widget.js
3228 (function( $, undefined ) {
3230 $.widget("ui.sortable", $.ui.mouse, {
3231 widgetEventPrefix: "sort",
3240 forcePlaceholderSize: false,
3241 forceHelperSize: false,
3250 scrollSensitivity: 20,
3253 tolerance: "intersect",
3256 _create: function() {
3258 var o = this.options;
3259 this.containerCache = {};
3260 this.element.addClass("ui-sortable");
3265 //Let's determine if the items are being displayed horizontally
3266 this.floating = this.items.length ? o.axis === 'x' || (/left|right/).test(this.items[0].item.css('float')) || (/inline|table-cell/).test(this.items[0].item.css('display')) : false;
3268 //Let's determine the parent's offset
3269 this.offset = this.element.offset();
3271 //Initialize mouse events for interaction
3276 destroy: function() {
3278 .removeClass("ui-sortable ui-sortable-disabled")
3279 .removeData("sortable")
3280 .unbind(".sortable");
3281 this._mouseDestroy();
3283 for ( var i = this.items.length - 1; i >= 0; i-- )
3284 this.items[i].item.removeData("sortable-item");
3289 _setOption: function(key, value){
3290 if ( key === "disabled" ) {
3291 this.options[ key ] = value;
3294 [ value ? "addClass" : "removeClass"]( "ui-sortable-disabled" );
3296 // Don't call widget base _setOption for disable as it adds ui-state-disabled class
3297 $.Widget.prototype._setOption.apply(this, arguments);
3301 _mouseCapture: function(event, overrideHandle) {
3303 if (this.reverting) {
3307 if(this.options.disabled || this.options.type == 'static') return false;
3309 //We have to refresh the items data once first
3310 this._refreshItems(event);
3312 //Find out if the clicked node (or one of its parents) is a actual item in this.items
3313 var currentItem = null, self = this, nodes = $(event.target).parents().each(function() {
3314 if($.data(this, 'sortable-item') == self) {
3315 currentItem = $(this);
3319 if($.data(event.target, 'sortable-item') == self) currentItem = $(event.target);
3321 if(!currentItem) return false;
3322 if(this.options.handle && !overrideHandle) {
3323 var validHandle = false;
3325 $(this.options.handle, currentItem).find("*").andSelf().each(function() { if(this == event.target) validHandle = true; });
3326 if(!validHandle) return false;
3329 this.currentItem = currentItem;
3330 this._removeCurrentsFromItems();
3335 _mouseStart: function(event, overrideHandle, noActivation) {
3337 var o = this.options, self = this;
3338 this.currentContainer = this;
3340 //We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture
3341 this.refreshPositions();
3343 //Create and append the visible helper
3344 this.helper = this._createHelper(event);
3346 //Cache the helper size
3347 this._cacheHelperProportions();
3350 * - Position generation -
3351 * This block generates everything position related - it's the core of draggables.
3354 //Cache the margins of the original element
3355 this._cacheMargins();
3357 //Get the next scrolling parent
3358 this.scrollParent = this.helper.scrollParent();
3360 //The element's absolute position on the page minus margins
3361 this.offset = this.currentItem.offset();
3363 top: this.offset.top - this.margins.top,
3364 left: this.offset.left - this.margins.left
3367 // Only after we got the offset, we can change the helper's position to absolute
3368 // TODO: Still need to figure out a way to make relative sorting possible
3369 this.helper.css("position", "absolute");
3370 this.cssPosition = this.helper.css("position");
3372 $.extend(this.offset, {
3373 click: { //Where the click happened, relative to the element
3374 left: event.pageX - this.offset.left,
3375 top: event.pageY - this.offset.top
3377 parent: this._getParentOffset(),
3378 relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
3381 //Generate the original position
3382 this.originalPosition = this._generatePosition(event);
3383 this.originalPageX = event.pageX;
3384 this.originalPageY = event.pageY;
3386 //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
3387 (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
3389 //Cache the former DOM position
3390 this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] };
3392 //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
3393 if(this.helper[0] != this.currentItem[0]) {
3394 this.currentItem.hide();
3397 //Create the placeholder
3398 this._createPlaceholder();
3400 //Set a containment if given in the options
3402 this._setContainment();
3404 if(o.cursor) { // cursor option
3405 if ($('body').css("cursor")) this._storedCursor = $('body').css("cursor");
3406 $('body').css("cursor", o.cursor);
3409 if(o.opacity) { // opacity option
3410 if (this.helper.css("opacity")) this._storedOpacity = this.helper.css("opacity");
3411 this.helper.css("opacity", o.opacity);
3414 if(o.zIndex) { // zIndex option
3415 if (this.helper.css("zIndex")) this._storedZIndex = this.helper.css("zIndex");
3416 this.helper.css("zIndex", o.zIndex);
3420 if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML')
3421 this.overflowOffset = this.scrollParent.offset();
3424 this._trigger("start", event, this._uiHash());
3426 //Recache the helper size
3427 if(!this._preserveHelperProportions)
3428 this._cacheHelperProportions();
3431 //Post 'activate' events to possible containers
3433 for (var i = this.containers.length - 1; i >= 0; i--) { this.containers[i]._trigger("activate", event, self._uiHash(this)); }
3436 //Prepare possible droppables
3438 $.ui.ddmanager.current = this;
3440 if ($.ui.ddmanager && !o.dropBehaviour)
3441 $.ui.ddmanager.prepareOffsets(this, event);
3443 this.dragging = true;
3445 this.helper.addClass("ui-sortable-helper");
3446 this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position
3451 _mouseDrag: function(event) {
3453 //Compute the helpers position
3454 this.position = this._generatePosition(event);
3455 this.positionAbs = this._convertPositionTo("absolute");
3457 if (!this.lastPositionAbs) {
3458 this.lastPositionAbs = this.positionAbs;
3462 if(this.options.scroll) {
3463 var o = this.options, scrolled = false;
3464 if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') {
3466 if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
3467 this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed;
3468 else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity)
3469 this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed;
3471 if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
3472 this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed;
3473 else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity)
3474 this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed;
3478 if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
3479 scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
3480 else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
3481 scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
3483 if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
3484 scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
3485 else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
3486 scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
3490 if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
3491 $.ui.ddmanager.prepareOffsets(this, event);
3494 //Regenerate the absolute position used for position checks
3495 this.positionAbs = this._convertPositionTo("absolute");
3497 //Set the helper position
3498 if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
3499 if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
3502 for (var i = this.items.length - 1; i >= 0; i--) {
3504 //Cache variables and intersection, continue if no intersection
3505 var item = this.items[i], itemElement = item.item[0], intersection = this._intersectsWithPointer(item);
3506 if (!intersection) continue;
3508 if(itemElement != this.currentItem[0] //cannot intersect with itself
3509 && this.placeholder[intersection == 1 ? "next" : "prev"]()[0] != itemElement //no useless actions that have been done before
3510 && !$.ui.contains(this.placeholder[0], itemElement) //no action if the item moved is the parent of the item checked
3511 && (this.options.type == 'semi-dynamic' ? !$.ui.contains(this.element[0], itemElement) : true)
3512 //&& itemElement.parentNode == this.placeholder[0].parentNode // only rearrange items within the same container
3515 this.direction = intersection == 1 ? "down" : "up";
3517 if (this.options.tolerance == "pointer" || this._intersectsWithSides(item)) {
3518 this._rearrange(event, item);
3523 this._trigger("change", event, this._uiHash());
3528 //Post events to containers
3529 this._contactContainers(event);
3531 //Interconnect with droppables
3532 if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
3535 this._trigger('sort', event, this._uiHash());
3537 this.lastPositionAbs = this.positionAbs;
3542 _mouseStop: function(event, noPropagation) {
3546 //If we are using droppables, inform the manager about the drop
3547 if ($.ui.ddmanager && !this.options.dropBehaviour)
3548 $.ui.ddmanager.drop(this, event);
3550 if(this.options.revert) {
3552 var cur = self.placeholder.offset();
3554 self.reverting = true;
3556 $(this.helper).animate({
3557 left: cur.left - this.offset.parent.left - self.margins.left + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollLeft),
3558 top: cur.top - this.offset.parent.top - self.margins.top + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollTop)
3559 }, parseInt(this.options.revert, 10) || 500, function() {
3563 this._clear(event, noPropagation);
3570 cancel: function() {
3576 this._mouseUp({ target: null });
3578 if(this.options.helper == "original")
3579 this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
3581 this.currentItem.show();
3583 //Post deactivating events to containers
3584 for (var i = this.containers.length - 1; i >= 0; i--){
3585 this.containers[i]._trigger("deactivate", null, self._uiHash(this));
3586 if(this.containers[i].containerCache.over) {
3587 this.containers[i]._trigger("out", null, self._uiHash(this));
3588 this.containers[i].containerCache.over = 0;
3594 if (this.placeholder) {
3595 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
3596 if(this.placeholder[0].parentNode) this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
3597 if(this.options.helper != "original" && this.helper && this.helper[0].parentNode) this.helper.remove();
3606 if(this.domPosition.prev) {
3607 $(this.domPosition.prev).after(this.currentItem);
3609 $(this.domPosition.parent).prepend(this.currentItem);
3617 serialize: function(o) {
3619 var items = this._getItemsAsjQuery(o && o.connected);
3620 var str = []; o = o || {};
3622 $(items).each(function() {
3623 var res = ($(o.item || this).attr(o.attribute || 'id') || '').match(o.expression || (/(.+)[-=_](.+)/));
3624 if(res) str.push((o.key || res[1]+'[]')+'='+(o.key && o.expression ? res[1] : res[2]));
3627 if(!str.length && o.key) {
3628 str.push(o.key + '=');
3631 return str.join('&');
3635 toArray: function(o) {
3637 var items = this._getItemsAsjQuery(o && o.connected);
3638 var ret = []; o = o || {};
3640 items.each(function() { ret.push($(o.item || this).attr(o.attribute || 'id') || ''); });
3645 /* Be careful with the following core functions */
3646 _intersectsWith: function(item) {
3648 var x1 = this.positionAbs.left,
3649 x2 = x1 + this.helperProportions.width,
3650 y1 = this.positionAbs.top,
3651 y2 = y1 + this.helperProportions.height;
3656 b = t + item.height;
3658 var dyClick = this.offset.click.top,
3659 dxClick = this.offset.click.left;
3661 var isOverElement = (y1 + dyClick) > t && (y1 + dyClick) < b && (x1 + dxClick) > l && (x1 + dxClick) < r;
3663 if( this.options.tolerance == "pointer"
3664 || this.options.forcePointerForContainers
3665 || (this.options.tolerance != "pointer" && this.helperProportions[this.floating ? 'width' : 'height'] > item[this.floating ? 'width' : 'height'])
3667 return isOverElement;
3670 return (l < x1 + (this.helperProportions.width / 2) // Right Half
3671 && x2 - (this.helperProportions.width / 2) < r // Left Half
3672 && t < y1 + (this.helperProportions.height / 2) // Bottom Half
3673 && y2 - (this.helperProportions.height / 2) < b ); // Top Half
3678 _intersectsWithPointer: function(item) {
3680 var isOverElementHeight = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height),
3681 isOverElementWidth = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width),
3682 isOverElement = isOverElementHeight && isOverElementWidth,
3683 verticalDirection = this._getDragVerticalDirection(),
3684 horizontalDirection = this._getDragHorizontalDirection();
3689 return this.floating ?
3690 ( ((horizontalDirection && horizontalDirection == "right") || verticalDirection == "down") ? 2 : 1 )
3691 : ( verticalDirection && (verticalDirection == "down" ? 2 : 1) );
3695 _intersectsWithSides: function(item) {
3697 var isOverBottomHalf = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height),
3698 isOverRightHalf = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width),
3699 verticalDirection = this._getDragVerticalDirection(),
3700 horizontalDirection = this._getDragHorizontalDirection();
3702 if (this.floating && horizontalDirection) {
3703 return ((horizontalDirection == "right" && isOverRightHalf) || (horizontalDirection == "left" && !isOverRightHalf));
3705 return verticalDirection && ((verticalDirection == "down" && isOverBottomHalf) || (verticalDirection == "up" && !isOverBottomHalf));
3710 _getDragVerticalDirection: function() {
3711 var delta = this.positionAbs.top - this.lastPositionAbs.top;
3712 return delta != 0 && (delta > 0 ? "down" : "up");
3715 _getDragHorizontalDirection: function() {
3716 var delta = this.positionAbs.left - this.lastPositionAbs.left;
3717 return delta != 0 && (delta > 0 ? "right" : "left");
3720 refresh: function(event) {
3721 this._refreshItems(event);
3722 this.refreshPositions();
3726 _connectWith: function() {
3727 var options = this.options;
3728 return options.connectWith.constructor == String
3729 ? [options.connectWith]
3730 : options.connectWith;
3733 _getItemsAsjQuery: function(connected) {
3738 var connectWith = this._connectWith();
3740 if(connectWith && connected) {
3741 for (var i = connectWith.length - 1; i >= 0; i--){
3742 var cur = $(connectWith[i]);
3743 for (var j = cur.length - 1; j >= 0; j--){
3744 var inst = $.data(cur[j], 'sortable');
3745 if(inst && inst != this && !inst.options.disabled) {
3746 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]);
3752 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]);
3754 for (var i = queries.length - 1; i >= 0; i--){
3755 queries[i][0].each(function() {
3764 _removeCurrentsFromItems: function() {
3766 var list = this.currentItem.find(":data(sortable-item)");
3768 for (var i=0; i < this.items.length; i++) {
3770 for (var j=0; j < list.length; j++) {
3771 if(list[j] == this.items[i].item[0])
3772 this.items.splice(i,1);
3779 _refreshItems: function(event) {
3782 this.containers = [this];
3783 var items = this.items;
3785 var queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]];
3786 var connectWith = this._connectWith();
3789 for (var i = connectWith.length - 1; i >= 0; i--){
3790 var cur = $(connectWith[i]);
3791 for (var j = cur.length - 1; j >= 0; j--){
3792 var inst = $.data(cur[j], 'sortable');
3793 if(inst && inst != this && !inst.options.disabled) {
3794 queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]);
3795 this.containers.push(inst);
3801 for (var i = queries.length - 1; i >= 0; i--) {
3802 var targetData = queries[i][1];
3803 var _queries = queries[i][0];
3805 for (var j=0, queriesLength = _queries.length; j < queriesLength; j++) {
3806 var item = $(_queries[j]);
3808 item.data('sortable-item', targetData); // Data for target checking (mouse manager)
3812 instance: targetData,
3813 width: 0, height: 0,
3821 refreshPositions: function(fast) {
3823 //This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change
3824 if(this.offsetParent && this.helper) {
3825 this.offset.parent = this._getParentOffset();
3828 for (var i = this.items.length - 1; i >= 0; i--){
3829 var item = this.items[i];
3831 //We ignore calculating positions of all connected containers when we're not over them
3832 if(item.instance != this.currentContainer && this.currentContainer && item.item[0] != this.currentItem[0])
3835 var t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item;
3838 item.width = t.outerWidth();
3839 item.height = t.outerHeight();
3847 if(this.options.custom && this.options.custom.refreshContainers) {
3848 this.options.custom.refreshContainers.call(this);
3850 for (var i = this.containers.length - 1; i >= 0; i--){
3851 var p = this.containers[i].element.offset();
3852 this.containers[i].containerCache.left = p.left;
3853 this.containers[i].containerCache.top = p.top;
3854 this.containers[i].containerCache.width = this.containers[i].element.outerWidth();
3855 this.containers[i].containerCache.height = this.containers[i].element.outerHeight();
3862 _createPlaceholder: function(that) {
3864 var self = that || this, o = self.options;
3866 if(!o.placeholder || o.placeholder.constructor == String) {
3867 var className = o.placeholder;
3869 element: function() {
3871 var el = $(document.createElement(self.currentItem[0].nodeName))
3872 .addClass(className || self.currentItem[0].className+" ui-sortable-placeholder")
3873 .removeClass("ui-sortable-helper")[0];
3876 el.style.visibility = "hidden";
3880 update: function(container, p) {
3882 // 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that
3883 // 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified
3884 if(className && !o.forcePlaceholderSize) return;
3886 //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
3887 if(!p.height()) { p.height(self.currentItem.innerHeight() - parseInt(self.currentItem.css('paddingTop')||0, 10) - parseInt(self.currentItem.css('paddingBottom')||0, 10)); };
3888 if(!p.width()) { p.width(self.currentItem.innerWidth() - parseInt(self.currentItem.css('paddingLeft')||0, 10) - parseInt(self.currentItem.css('paddingRight')||0, 10)); };
3893 //Create the placeholder
3894 self.placeholder = $(o.placeholder.element.call(self.element, self.currentItem));
3896 //Append it after the actual current item
3897 self.currentItem.after(self.placeholder);
3899 //Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
3900 o.placeholder.update(self, self.placeholder);
3904 _contactContainers: function(event) {
3906 // get innermost container that intersects with item
3907 var innermostContainer = null, innermostIndex = null;
3910 for (var i = this.containers.length - 1; i >= 0; i--){
3912 // never consider a container that's located within the item itself
3913 if($.ui.contains(this.currentItem[0], this.containers[i].element[0]))
3916 if(this._intersectsWith(this.containers[i].containerCache)) {
3918 // if we've already found a container and it's more "inner" than this, then continue
3919 if(innermostContainer && $.ui.contains(this.containers[i].element[0], innermostContainer.element[0]))
3922 innermostContainer = this.containers[i];
3926 // container doesn't intersect. trigger "out" event if necessary
3927 if(this.containers[i].containerCache.over) {
3928 this.containers[i]._trigger("out", event, this._uiHash(this));
3929 this.containers[i].containerCache.over = 0;
3935 // if no intersecting containers found, return
3936 if(!innermostContainer) return;
3938 // move the item into the container if it's not there already
3939 if(this.containers.length === 1) {
3940 this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
3941 this.containers[innermostIndex].containerCache.over = 1;
3942 } else if(this.currentContainer != this.containers[innermostIndex]) {
3944 //When entering a new container, we will find the item with the least distance and append our item near it
3945 var dist = 10000; var itemWithLeastDistance = null; var base = this.positionAbs[this.containers[innermostIndex].floating ? 'left' : 'top'];
3946 for (var j = this.items.length - 1; j >= 0; j--) {
3947 if(!$.ui.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) continue;
3948 var cur = this.items[j][this.containers[innermostIndex].floating ? 'left' : 'top'];
3949 if(Math.abs(cur - base) < dist) {
3950 dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j];
3954 if(!itemWithLeastDistance && !this.options.dropOnEmpty) //Check if dropOnEmpty is enabled
3957 this.currentContainer = this.containers[innermostIndex];
3958 itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true);
3959 this._trigger("change", event, this._uiHash());
3960 this.containers[innermostIndex]._trigger("change", event, this._uiHash(this));
3962 //Update the placeholder
3963 this.options.placeholder.update(this.currentContainer, this.placeholder);
3965 this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
3966 this.containers[innermostIndex].containerCache.over = 1;
3972 _createHelper: function(event) {
3974 var o = this.options;
3975 var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper == 'clone' ? this.currentItem.clone() : this.currentItem);
3977 if(!helper.parents('body').length) //Add the helper to the DOM if that didn't happen already
3978 $(o.appendTo != 'parent' ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]);
3980 if(helper[0] == this.currentItem[0])
3981 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") };
3983 if(helper[0].style.width == '' || o.forceHelperSize) helper.width(this.currentItem.width());
3984 if(helper[0].style.height == '' || o.forceHelperSize) helper.height(this.currentItem.height());
3990 _adjustOffsetFromHelper: function(obj) {
3991 if (typeof obj == 'string') {
3992 obj = obj.split(' ');
3994 if ($.isArray(obj)) {
3995 obj = {left: +obj[0], top: +obj[1] || 0};
3997 if ('left' in obj) {
3998 this.offset.click.left = obj.left + this.margins.left;
4000 if ('right' in obj) {
4001 this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
4004 this.offset.click.top = obj.top + this.margins.top;
4006 if ('bottom' in obj) {
4007 this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
4011 _getParentOffset: function() {
4014 //Get the offsetParent and cache its position
4015 this.offsetParent = this.helper.offsetParent();
4016 var po = this.offsetParent.offset();
4018 // This is a special case where we need to modify a offset calculated on start, since the following happened:
4019 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
4020 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
4021 // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
4022 if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) {
4023 po.left += this.scrollParent.scrollLeft();
4024 po.top += this.scrollParent.scrollTop();
4027 if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
4028 || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix
4029 po = { top: 0, left: 0 };
4032 top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
4033 left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
4038 _getRelativeOffset: function() {
4040 if(this.cssPosition == "relative") {
4041 var p = this.currentItem.position();
4043 top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
4044 left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
4047 return { top: 0, left: 0 };
4052 _cacheMargins: function() {
4054 left: (parseInt(this.currentItem.css("marginLeft"),10) || 0),
4055 top: (parseInt(this.currentItem.css("marginTop"),10) || 0)
4059 _cacheHelperProportions: function() {
4060 this.helperProportions = {
4061 width: this.helper.outerWidth(),
4062 height: this.helper.outerHeight()
4066 _setContainment: function() {
4068 var o = this.options;
4069 if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
4070 if(o.containment == 'document' || o.containment == 'window') this.containment = [
4071 0 - this.offset.relative.left - this.offset.parent.left,
4072 0 - this.offset.relative.top - this.offset.parent.top,
4073 $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
4074 ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
4077 if(!(/^(document|window|parent)$/).test(o.containment)) {
4078 var ce = $(o.containment)[0];
4079 var co = $(o.containment).offset();
4080 var over = ($(ce).css("overflow") != 'hidden');
4082 this.containment = [
4083 co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
4084 co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
4085 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,
4086 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
4092 _convertPositionTo: function(d, pos) {
4094 if(!pos) pos = this.position;
4095 var mod = d == "absolute" ? 1 : -1;
4096 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);
4100 pos.top // The absolute mouse position
4101 + this.offset.relative.top * mod // Only for relative positioned nodes: Relative offset from element to offset parent
4102 + this.offset.parent.top * mod // The offsetParent's offset without borders (offset + border)
4103 - ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
4106 pos.left // The absolute mouse position
4107 + this.offset.relative.left * mod // Only for relative positioned nodes: Relative offset from element to offset parent
4108 + this.offset.parent.left * mod // The offsetParent's offset without borders (offset + border)
4109 - ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
4115 _generatePosition: function(event) {
4117 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);
4119 // This is another very weird special case that only happens for relative elements:
4120 // 1. If the css position is relative
4121 // 2. and the scroll parent is the document or similar to the offset parent
4122 // we have to refresh the relative offset during the scroll so there are no jumps
4123 if(this.cssPosition == 'relative' && !(this.scrollParent[0] != document && this.scrollParent[0] != this.offsetParent[0])) {
4124 this.offset.relative = this._getRelativeOffset();
4127 var pageX = event.pageX;
4128 var pageY = event.pageY;
4131 * - Position constraining -
4132 * Constrain the position to a mix of grid, containment.
4135 if(this.originalPosition) { //If we are not dragging yet, we won't check for options
4137 if(this.containment) {
4138 if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left;
4139 if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top;
4140 if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left;
4141 if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top;
4145 var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
4146 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;
4148 var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
4149 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;
4156 pageY // The absolute mouse position
4157 - this.offset.click.top // Click offset (relative to the element)
4158 - this.offset.relative.top // Only for relative positioned nodes: Relative offset from element to offset parent
4159 - this.offset.parent.top // The offsetParent's offset without borders (offset + border)
4160 + ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
4163 pageX // The absolute mouse position
4164 - this.offset.click.left // Click offset (relative to the element)
4165 - this.offset.relative.left // Only for relative positioned nodes: Relative offset from element to offset parent
4166 - this.offset.parent.left // The offsetParent's offset without borders (offset + border)
4167 + ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
4173 _rearrange: function(event, i, a, hardRefresh) {
4175 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));
4177 //Various things done here to improve the performance:
4178 // 1. we create a setTimeout, that calls refreshPositions
4179 // 2. on the instance, we have a counter variable, that get's higher after every append
4180 // 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same
4181 // 4. this lets only the last addition to the timeout stack through
4182 this.counter = this.counter ? ++this.counter : 1;
4183 var self = this, counter = this.counter;
4185 window.setTimeout(function() {
4186 if(counter == self.counter) self.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove
4191 _clear: function(event, noPropagation) {
4193 this.reverting = false;
4194 // We delay all events that have to be triggered to after the point where the placeholder has been removed and
4195 // everything else normalized again
4196 var delayedTriggers = [], self = this;
4198 // We first have to update the dom position of the actual currentItem
4199 // Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088)
4200 if(!this._noFinalSort && this.currentItem.parent().length) this.placeholder.before(this.currentItem);
4201 this._noFinalSort = null;
4203 if(this.helper[0] == this.currentItem[0]) {
4204 for(var i in this._storedCSS) {
4205 if(this._storedCSS[i] == 'auto' || this._storedCSS[i] == 'static') this._storedCSS[i] = '';
4207 this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
4209 this.currentItem.show();
4212 if(this.fromOutside && !noPropagation) delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); });
4213 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
4214 if(!$.ui.contains(this.element[0], this.currentItem[0])) { //Node was moved out of the current element
4215 if(!noPropagation) delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); });
4216 for (var i = this.containers.length - 1; i >= 0; i--){
4217 if($.ui.contains(this.containers[i].element[0], this.currentItem[0]) && !noPropagation) {
4218 delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); }; }).call(this, this.containers[i]));
4219 delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this)); }; }).call(this, this.containers[i]));
4224 //Post events to containers
4225 for (var i = this.containers.length - 1; i >= 0; i--){
4226 if(!noPropagation) delayedTriggers.push((function(c) { return function(event) { c._trigger("deactivate", event, this._uiHash(this)); }; }).call(this, this.containers[i]));
4227 if(this.containers[i].containerCache.over) {
4228 delayedTriggers.push((function(c) { return function(event) { c._trigger("out", event, this._uiHash(this)); }; }).call(this, this.containers[i]));
4229 this.containers[i].containerCache.over = 0;
4233 //Do what was originally in plugins
4234 if(this._storedCursor) $('body').css("cursor", this._storedCursor); //Reset cursor
4235 if(this._storedOpacity) this.helper.css("opacity", this._storedOpacity); //Reset opacity
4236 if(this._storedZIndex) this.helper.css("zIndex", this._storedZIndex == 'auto' ? '' : this._storedZIndex); //Reset z-index
4238 this.dragging = false;
4239 if(this.cancelHelperRemoval) {
4240 if(!noPropagation) {
4241 this._trigger("beforeStop", event, this._uiHash());
4242 for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events
4243 this._trigger("stop", event, this._uiHash());
4248 if(!noPropagation) this._trigger("beforeStop", event, this._uiHash());
4250 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
4251 this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
4253 if(this.helper[0] != this.currentItem[0]) this.helper.remove(); this.helper = null;
4255 if(!noPropagation) {
4256 for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events
4257 this._trigger("stop", event, this._uiHash());
4260 this.fromOutside = false;
4265 _trigger: function() {
4266 if ($.Widget.prototype._trigger.apply(this, arguments) === false) {
4271 _uiHash: function(inst) {
4272 var self = inst || this;
4274 helper: self.helper,
4275 placeholder: self.placeholder || $([]),
4276 position: self.position,
4277 originalPosition: self.originalPosition,
4278 offset: self.positionAbs,
4279 item: self.currentItem,
4280 sender: inst ? inst.element : null
4286 $.extend($.ui.sortable, {
4292 * jQuery UI Accordion 1.8.14
4294 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
4295 * Dual licensed under the MIT or GPL Version 2 licenses.
4296 * http://jquery.org/license
4298 * http://docs.jquery.com/UI/Accordion
4302 * jquery.ui.widget.js
4304 (function( $, undefined ) {
4306 $.widget( "ui.accordion", {
4315 header: "> li > :first-child,> :not(li):even",
4317 header: "ui-icon-triangle-1-e",
4318 headerSelected: "ui-icon-triangle-1-s"
4321 navigationFilter: function() {
4322 return this.href.toLowerCase() === location.href.toLowerCase();
4326 _create: function() {
4328 options = self.options;
4333 .addClass( "ui-accordion ui-widget ui-helper-reset" )
4334 // in lack of child-selectors in CSS
4335 // we need to mark top-LIs in a UL-accordion for some IE-fix
4337 .addClass( "ui-accordion-li-fix" );
4339 self.headers = self.element.find( options.header )
4340 .addClass( "ui-accordion-header ui-helper-reset ui-state-default ui-corner-all" )
4341 .bind( "mouseenter.accordion", function() {
4342 if ( options.disabled ) {
4345 $( this ).addClass( "ui-state-hover" );
4347 .bind( "mouseleave.accordion", function() {
4348 if ( options.disabled ) {
4351 $( this ).removeClass( "ui-state-hover" );
4353 .bind( "focus.accordion", function() {
4354 if ( options.disabled ) {
4357 $( this ).addClass( "ui-state-focus" );
4359 .bind( "blur.accordion", function() {
4360 if ( options.disabled ) {
4363 $( this ).removeClass( "ui-state-focus" );
4367 .addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" );
4369 if ( options.navigation ) {
4370 var current = self.element.find( "a" ).filter( options.navigationFilter ).eq( 0 );
4371 if ( current.length ) {
4372 var header = current.closest( ".ui-accordion-header" );
4373 if ( header.length ) {
4374 // anchor within header
4375 self.active = header;
4377 // anchor within content
4378 self.active = current.closest( ".ui-accordion-content" ).prev();
4383 self.active = self._findActive( self.active || options.active )
4384 .addClass( "ui-state-default ui-state-active" )
4385 .toggleClass( "ui-corner-all" )
4386 .toggleClass( "ui-corner-top" );
4387 self.active.next().addClass( "ui-accordion-content-active" );
4389 self._createIcons();
4393 self.element.attr( "role", "tablist" );
4396 .attr( "role", "tab" )
4397 .bind( "keydown.accordion", function( event ) {
4398 return self._keydown( event );
4401 .attr( "role", "tabpanel" );
4404 .not( self.active || "" )
4406 "aria-expanded": "false",
4407 "aria-selected": "false",
4413 // make sure at least one header is in the tab order
4414 if ( !self.active.length ) {
4415 self.headers.eq( 0 ).attr( "tabIndex", 0 );
4419 "aria-expanded": "true",
4420 "aria-selected": "true",
4425 // only need links in tab order for Safari
4426 if ( !$.browser.safari ) {
4427 self.headers.find( "a" ).attr( "tabIndex", -1 );
4430 if ( options.event ) {
4431 self.headers.bind( options.event.split(" ").join(".accordion ") + ".accordion", function(event) {
4432 self._clickHandler.call( self, event, this );
4433 event.preventDefault();
4438 _createIcons: function() {
4439 var options = this.options;
4440 if ( options.icons ) {
4441 $( "<span></span>" )
4442 .addClass( "ui-icon " + options.icons.header )
4443 .prependTo( this.headers );
4444 this.active.children( ".ui-icon" )
4445 .toggleClass(options.icons.header)
4446 .toggleClass(options.icons.headerSelected);
4447 this.element.addClass( "ui-accordion-icons" );
4451 _destroyIcons: function() {
4452 this.headers.children( ".ui-icon" ).remove();
4453 this.element.removeClass( "ui-accordion-icons" );
4456 destroy: function() {
4457 var options = this.options;
4460 .removeClass( "ui-accordion ui-widget ui-helper-reset" )
4461 .removeAttr( "role" );
4464 .unbind( ".accordion" )
4465 .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" )
4466 .removeAttr( "role" )
4467 .removeAttr( "aria-expanded" )
4468 .removeAttr( "aria-selected" )
4469 .removeAttr( "tabIndex" );
4471 this.headers.find( "a" ).removeAttr( "tabIndex" );
4472 this._destroyIcons();
4473 var contents = this.headers.next()
4474 .css( "display", "" )
4475 .removeAttr( "role" )
4476 .removeClass( "ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-accordion-disabled ui-state-disabled" );
4477 if ( options.autoHeight || options.fillHeight ) {
4478 contents.css( "height", "" );
4481 return $.Widget.prototype.destroy.call( this );
4484 _setOption: function( key, value ) {
4485 $.Widget.prototype._setOption.apply( this, arguments );
4487 if ( key == "active" ) {
4488 this.activate( value );
4490 if ( key == "icons" ) {
4491 this._destroyIcons();
4493 this._createIcons();
4496 // #5332 - opacity doesn't cascade to positioned elements in IE
4497 // so we need to add the disabled class to the headers and panels
4498 if ( key == "disabled" ) {
4499 this.headers.add(this.headers.next())
4500 [ value ? "addClass" : "removeClass" ](
4501 "ui-accordion-disabled ui-state-disabled" );
4505 _keydown: function( event ) {
4506 if ( this.options.disabled || event.altKey || event.ctrlKey ) {
4510 var keyCode = $.ui.keyCode,
4511 length = this.headers.length,
4512 currentIndex = this.headers.index( event.target ),
4515 switch ( event.keyCode ) {
4518 toFocus = this.headers[ ( currentIndex + 1 ) % length ];
4522 toFocus = this.headers[ ( currentIndex - 1 + length ) % length ];
4526 this._clickHandler( { target: event.target }, event.target );
4527 event.preventDefault();
4531 $( event.target ).attr( "tabIndex", -1 );
4532 $( toFocus ).attr( "tabIndex", 0 );
4540 resize: function() {
4541 var options = this.options,
4544 if ( options.fillSpace ) {
4545 if ( $.browser.msie ) {
4546 var defOverflow = this.element.parent().css( "overflow" );
4547 this.element.parent().css( "overflow", "hidden");
4549 maxHeight = this.element.parent().height();
4550 if ($.browser.msie) {
4551 this.element.parent().css( "overflow", defOverflow );
4554 this.headers.each(function() {
4555 maxHeight -= $( this ).outerHeight( true );
4560 $( this ).height( Math.max( 0, maxHeight -
4561 $( this ).innerHeight() + $( this ).height() ) );
4563 .css( "overflow", "auto" );
4564 } else if ( options.autoHeight ) {
4568 maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() );
4570 .height( maxHeight );
4576 activate: function( index ) {
4577 // TODO this gets called on init, changing the option without an explicit call for that
4578 this.options.active = index;
4579 // call clickHandler with custom event
4580 var active = this._findActive( index )[ 0 ];
4581 this._clickHandler( { target: active }, active );
4586 _findActive: function( selector ) {
4588 ? typeof selector === "number"
4589 ? this.headers.filter( ":eq(" + selector + ")" )
4590 : this.headers.not( this.headers.not( selector ) )
4591 : selector === false
4593 : this.headers.filter( ":eq(0)" );
4596 // TODO isn't event.target enough? why the separate target argument?
4597 _clickHandler: function( event, target ) {
4598 var options = this.options;
4599 if ( options.disabled ) {
4603 // called only when using activate(false) to close all parts programmatically
4604 if ( !event.target ) {
4605 if ( !options.collapsible ) {
4609 .removeClass( "ui-state-active ui-corner-top" )
4610 .addClass( "ui-state-default ui-corner-all" )
4611 .children( ".ui-icon" )
4612 .removeClass( options.icons.headerSelected )
4613 .addClass( options.icons.header );
4614 this.active.next().addClass( "ui-accordion-content-active" );
4615 var toHide = this.active.next(),
4619 oldHeader: options.active,
4620 newContent: $( [] ),
4623 toShow = ( this.active = $( [] ) );
4624 this._toggle( toShow, toHide, data );
4628 // get the click target
4629 var clicked = $( event.currentTarget || target ),
4630 clickedIsActive = clicked[0] === this.active[0];
4632 // TODO the option is changed, is that correct?
4633 // TODO if it is correct, shouldn't that happen after determining that the click is valid?
4634 options.active = options.collapsible && clickedIsActive ?
4636 this.headers.index( clicked );
4638 // if animations are still active, or the active header is the target, ignore click
4639 if ( this.running || ( !options.collapsible && clickedIsActive ) ) {
4643 // find elements to show and hide
4644 var active = this.active,
4645 toShow = clicked.next(),
4646 toHide = this.active.next(),
4649 newHeader: clickedIsActive && options.collapsible ? $([]) : clicked,
4650 oldHeader: this.active,
4651 newContent: clickedIsActive && options.collapsible ? $([]) : toShow,
4654 down = this.headers.index( this.active[0] ) > this.headers.index( clicked[0] );
4656 // when the call to ._toggle() comes after the class changes
4657 // it causes a very odd bug in IE 8 (see #6720)
4658 this.active = clickedIsActive ? $([]) : clicked;
4659 this._toggle( toShow, toHide, data, clickedIsActive, down );
4663 .removeClass( "ui-state-active ui-corner-top" )
4664 .addClass( "ui-state-default ui-corner-all" )
4665 .children( ".ui-icon" )
4666 .removeClass( options.icons.headerSelected )
4667 .addClass( options.icons.header );
4668 if ( !clickedIsActive ) {
4670 .removeClass( "ui-state-default ui-corner-all" )
4671 .addClass( "ui-state-active ui-corner-top" )
4672 .children( ".ui-icon" )
4673 .removeClass( options.icons.header )
4674 .addClass( options.icons.headerSelected );
4677 .addClass( "ui-accordion-content-active" );
4683 _toggle: function( toShow, toHide, data, clickedIsActive, down ) {
4685 options = self.options;
4687 self.toShow = toShow;
4688 self.toHide = toHide;
4691 var complete = function() {
4695 return self._completed.apply( self, arguments );
4698 // trigger changestart event
4699 self._trigger( "changestart", null, self.data );
4701 // count elements to animate
4702 self.running = toHide.size() === 0 ? toShow.size() : toHide.size();
4704 if ( options.animated ) {
4705 var animOptions = {};
4707 if ( options.collapsible && clickedIsActive ) {
4713 autoHeight: options.autoHeight || options.fillSpace
4721 autoHeight: options.autoHeight || options.fillSpace
4725 if ( !options.proxied ) {
4726 options.proxied = options.animated;
4729 if ( !options.proxiedDuration ) {
4730 options.proxiedDuration = options.duration;
4733 options.animated = $.isFunction( options.proxied ) ?
4734 options.proxied( animOptions ) :
4737 options.duration = $.isFunction( options.proxiedDuration ) ?
4738 options.proxiedDuration( animOptions ) :
4739 options.proxiedDuration;
4741 var animations = $.ui.accordion.animations,
4742 duration = options.duration,
4743 easing = options.animated;
4745 if ( easing && !animations[ easing ] && !$.easing[ easing ] ) {
4748 if ( !animations[ easing ] ) {
4749 animations[ easing ] = function( options ) {
4750 this.slide( options, {
4752 duration: duration || 700
4757 animations[ easing ]( animOptions );
4759 if ( options.collapsible && clickedIsActive ) {
4769 // TODO assert that the blur and focus triggers are really necessary, remove otherwise
4772 "aria-expanded": "false",
4773 "aria-selected": "false",
4779 "aria-expanded": "true",
4780 "aria-selected": "true",
4786 _completed: function( cancel ) {
4787 this.running = cancel ? 0 : --this.running;
4788 if ( this.running ) {
4792 if ( this.options.clearStyle ) {
4793 this.toShow.add( this.toHide ).css({
4799 // other classes are removed before the animation; this one needs to stay until completed
4800 this.toHide.removeClass( "ui-accordion-content-active" );
4801 // Work around for rendering bug in IE (#5421)
4802 if ( this.toHide.length ) {
4803 this.toHide.parent()[0].className = this.toHide.parent()[0].className;
4806 this._trigger( "change", null, this.data );
4810 $.extend( $.ui.accordion, {
4813 slide: function( options, additions ) {
4814 options = $.extend({
4817 }, options, additions );
4818 if ( !options.toHide.size() ) {
4819 options.toShow.animate({
4822 paddingBottom: "show"
4826 if ( !options.toShow.size() ) {
4827 options.toHide.animate({
4830 paddingBottom: "hide"
4834 var overflow = options.toShow.css( "overflow" ),
4838 fxAttrs = [ "height", "paddingTop", "paddingBottom" ],
4840 // fix width before calculating height of hidden element
4841 var s = options.toShow;
4842 originalWidth = s[0].style.width;
4843 s.width( parseInt( s.parent().width(), 10 )
4844 - parseInt( s.css( "paddingLeft" ), 10 )
4845 - parseInt( s.css( "paddingRight" ), 10 )
4846 - ( parseInt( s.css( "borderLeftWidth" ), 10 ) || 0 )
4847 - ( parseInt( s.css( "borderRightWidth" ), 10) || 0 ) );
4849 $.each( fxAttrs, function( i, prop ) {
4850 hideProps[ prop ] = "hide";
4852 var parts = ( "" + $.css( options.toShow[0], prop ) ).match( /^([\d+-.]+)(.*)$/ );
4853 showProps[ prop ] = {
4855 unit: parts[ 2 ] || "px"
4858 options.toShow.css({ height: 0, overflow: "hidden" }).show();
4860 .filter( ":hidden" )
4861 .each( options.complete )
4863 .filter( ":visible" )
4864 .animate( hideProps, {
4865 step: function( now, settings ) {
4866 // only calculate the percent when animating height
4867 // IE gets very inconsistent results when animating elements
4868 // with small values, which is common for padding
4869 if ( settings.prop == "height" ) {
4870 percentDone = ( settings.end - settings.start === 0 ) ? 0 :
4871 ( settings.now - settings.start ) / ( settings.end - settings.start );
4874 options.toShow[ 0 ].style[ settings.prop ] =
4875 ( percentDone * showProps[ settings.prop ].value )
4876 + showProps[ settings.prop ].unit;
4878 duration: options.duration,
4879 easing: options.easing,
4880 complete: function() {
4881 if ( !options.autoHeight ) {
4882 options.toShow.css( "height", "" );
4884 options.toShow.css({
4885 width: originalWidth,
4892 bounceslide: function( options ) {
4893 this.slide( options, {
4894 easing: options.down ? "easeOutBounce" : "swing",
4895 duration: options.down ? 1000 : 200
4903 * jQuery UI Autocomplete 1.8.14
4905 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
4906 * Dual licensed under the MIT or GPL Version 2 licenses.
4907 * http://jquery.org/license
4909 * http://docs.jquery.com/UI/Autocomplete
4913 * jquery.ui.widget.js
4914 * jquery.ui.position.js
4916 (function( $, undefined ) {
4918 // used to prevent race conditions with remote data sources
4919 var requestIndex = 0;
4921 $.widget( "ui.autocomplete", {
4937 _create: function() {
4939 doc = this.element[ 0 ].ownerDocument,
4943 .addClass( "ui-autocomplete-input" )
4944 .attr( "autocomplete", "off" )
4945 // TODO verify these actually work as intended
4948 "aria-autocomplete": "list",
4949 "aria-haspopup": "true"
4951 .bind( "keydown.autocomplete", function( event ) {
4952 if ( self.options.disabled || self.element.attr( "readonly" ) ) {
4956 suppressKeyPress = false;
4957 var keyCode = $.ui.keyCode;
4958 switch( event.keyCode ) {
4959 case keyCode.PAGE_UP:
4960 self._move( "previousPage", event );
4962 case keyCode.PAGE_DOWN:
4963 self._move( "nextPage", event );
4966 self._move( "previous", event );
4967 // prevent moving cursor to beginning of text field in some browsers
4968 event.preventDefault();
4971 self._move( "next", event );
4972 // prevent moving cursor to end of text field in some browsers
4973 event.preventDefault();
4976 case keyCode.NUMPAD_ENTER:
4977 // when menu is open and has focus
4978 if ( self.menu.active ) {
4979 // #6055 - Opera still allows the keypress to occur
4980 // which causes forms to submit
4981 suppressKeyPress = true;
4982 event.preventDefault();
4984 //passthrough - ENTER and TAB both select the current element
4986 if ( !self.menu.active ) {
4989 self.menu.select( event );
4991 case keyCode.ESCAPE:
4992 self.element.val( self.term );
4993 self.close( event );
4996 // keypress is triggered before the input value is changed
4997 clearTimeout( self.searching );
4998 self.searching = setTimeout(function() {
4999 // only search if the value has changed
5000 if ( self.term != self.element.val() ) {
5001 self.selectedItem = null;
5002 self.search( null, event );
5004 }, self.options.delay );
5008 .bind( "keypress.autocomplete", function( event ) {
5009 if ( suppressKeyPress ) {
5010 suppressKeyPress = false;
5011 event.preventDefault();
5014 .bind( "focus.autocomplete", function() {
5015 if ( self.options.disabled ) {
5019 self.selectedItem = null;
5020 self.previous = self.element.val();
5022 .bind( "blur.autocomplete", function( event ) {
5023 if ( self.options.disabled ) {
5027 clearTimeout( self.searching );
5028 // clicks on the menu (or a button to trigger a search) will cause a blur event
5029 self.closing = setTimeout(function() {
5030 self.close( event );
5031 self._change( event );
5035 this.response = function() {
5036 return self._response.apply( self, arguments );
5038 this.menu = $( "<ul></ul>" )
5039 .addClass( "ui-autocomplete" )
5040 .appendTo( $( this.options.appendTo || "body", doc )[0] )
5041 // prevent the close-on-blur in case of a "slow" click on the menu (long mousedown)
5042 .mousedown(function( event ) {
5043 // clicking on the scrollbar causes focus to shift to the body
5044 // but we can't detect a mouseup or a click immediately afterward
5045 // so we have to track the next mousedown and close the menu if
5046 // the user clicks somewhere outside of the autocomplete
5047 var menuElement = self.menu.element[ 0 ];
5048 if ( !$( event.target ).closest( ".ui-menu-item" ).length ) {
5049 setTimeout(function() {
5050 $( document ).one( 'mousedown', function( event ) {
5051 if ( event.target !== self.element[ 0 ] &&
5052 event.target !== menuElement &&
5053 !$.ui.contains( menuElement, event.target ) ) {
5060 // use another timeout to make sure the blur-event-handler on the input was already triggered
5061 setTimeout(function() {
5062 clearTimeout( self.closing );
5066 focus: function( event, ui ) {
5067 var item = ui.item.data( "item.autocomplete" );
5068 if ( false !== self._trigger( "focus", event, { item: item } ) ) {
5069 // use value to match what will end up in the input, if it was a key event
5070 if ( /^key/.test(event.originalEvent.type) ) {
5071 self.element.val( item.value );
5075 selected: function( event, ui ) {
5076 var item = ui.item.data( "item.autocomplete" ),
5077 previous = self.previous;
5079 // only trigger when focus was lost (click on menu)
5080 if ( self.element[0] !== doc.activeElement ) {
5081 self.element.focus();
5082 self.previous = previous;
5083 // #6109 - IE triggers two focus events and the second
5084 // is asynchronous, so we need to reset the previous
5085 // term synchronously and asynchronously :-(
5086 setTimeout(function() {
5087 self.previous = previous;
5088 self.selectedItem = item;
5092 if ( false !== self._trigger( "select", event, { item: item } ) ) {
5093 self.element.val( item.value );
5095 // reset the term after the select event
5096 // this allows custom select handling to work properly
5097 self.term = self.element.val();
5099 self.close( event );
5100 self.selectedItem = item;
5102 blur: function( event, ui ) {
5103 // don't set the value of the text field if it's already correct
5104 // this prevents moving the cursor unnecessarily
5105 if ( self.menu.element.is(":visible") &&
5106 ( self.element.val() !== self.term ) ) {
5107 self.element.val( self.term );
5111 .zIndex( this.element.zIndex() + 1 )
5112 // workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
5113 .css({ top: 0, left: 0 })
5116 if ( $.fn.bgiframe ) {
5117 this.menu.element.bgiframe();
5121 destroy: function() {
5123 .removeClass( "ui-autocomplete-input" )
5124 .removeAttr( "autocomplete" )
5125 .removeAttr( "role" )
5126 .removeAttr( "aria-autocomplete" )
5127 .removeAttr( "aria-haspopup" );
5128 this.menu.element.remove();
5129 $.Widget.prototype.destroy.call( this );
5132 _setOption: function( key, value ) {
5133 $.Widget.prototype._setOption.apply( this, arguments );
5134 if ( key === "source" ) {
5137 if ( key === "appendTo" ) {
5138 this.menu.element.appendTo( $( value || "body", this.element[0].ownerDocument )[0] )
5140 if ( key === "disabled" && value && this.xhr ) {
5145 _initSource: function() {
5149 if ( $.isArray(this.options.source) ) {
5150 array = this.options.source;
5151 this.source = function( request, response ) {
5152 response( $.ui.autocomplete.filter(array, request.term) );
5154 } else if ( typeof this.options.source === "string" ) {
5155 url = this.options.source;
5156 this.source = function( request, response ) {
5164 autocompleteRequest: ++requestIndex,
5165 success: function( data, status ) {
5166 if ( this.autocompleteRequest === requestIndex ) {
5171 if ( this.autocompleteRequest === requestIndex ) {
5178 this.source = this.options.source;
5182 search: function( value, event ) {
5183 value = value != null ? value : this.element.val();
5185 // always save the actual value, not the one passed as an argument
5186 this.term = this.element.val();
5188 if ( value.length < this.options.minLength ) {
5189 return this.close( event );
5192 clearTimeout( this.closing );
5193 if ( this._trigger( "search", event ) === false ) {
5197 return this._search( value );
5200 _search: function( value ) {
5202 this.element.addClass( "ui-autocomplete-loading" );
5204 this.source( { term: value }, this.response );
5207 _response: function( content ) {
5208 if ( !this.options.disabled && content && content.length ) {
5209 content = this._normalize( content );
5210 this._suggest( content );
5211 this._trigger( "open" );
5216 if ( !this.pending ) {
5217 this.element.removeClass( "ui-autocomplete-loading" );
5221 close: function( event ) {
5222 clearTimeout( this.closing );
5223 if ( this.menu.element.is(":visible") ) {
5224 this.menu.element.hide();
5225 this.menu.deactivate();
5226 this._trigger( "close", event );
5230 _change: function( event ) {
5231 if ( this.previous !== this.element.val() ) {
5232 this._trigger( "change", event, { item: this.selectedItem } );
5236 _normalize: function( items ) {
5237 // assume all items have the right format when the first item is complete
5238 if ( items.length && items[0].label && items[0].value ) {
5241 return $.map( items, function(item) {
5242 if ( typeof item === "string" ) {
5249 label: item.label || item.value,
5250 value: item.value || item.label
5255 _suggest: function( items ) {
5256 var ul = this.menu.element
5258 .zIndex( this.element.zIndex() + 1 );
5259 this._renderMenu( ul, items );
5260 // TODO refresh should check if the active item is still in the dom, removing the need for a manual deactivate
5261 this.menu.deactivate();
5262 this.menu.refresh();
5264 // size and position menu
5267 ul.position( $.extend({
5269 }, this.options.position ));
5271 if ( this.options.autoFocus ) {
5272 this.menu.next( new $.Event("mouseover") );
5276 _resizeMenu: function() {
5277 var ul = this.menu.element;
5278 ul.outerWidth( Math.max(
5279 ul.width( "" ).outerWidth(),
5280 this.element.outerWidth()
5284 _renderMenu: function( ul, items ) {
5286 $.each( items, function( index, item ) {
5287 self._renderItem( ul, item );
5291 _renderItem: function( ul, item) {
5292 return $( "<li></li>" )
5293 .data( "item.autocomplete", item )
5294 .append( $( "<a></a>" ).text( item.label ) )
5298 _move: function( direction, event ) {
5299 if ( !this.menu.element.is(":visible") ) {
5300 this.search( null, event );
5303 if ( this.menu.first() && /^previous/.test(direction) ||
5304 this.menu.last() && /^next/.test(direction) ) {
5305 this.element.val( this.term );
5306 this.menu.deactivate();
5309 this.menu[ direction ]( event );
5312 widget: function() {
5313 return this.menu.element;
5317 $.extend( $.ui.autocomplete, {
5318 escapeRegex: function( value ) {
5319 return value.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
5321 filter: function(array, term) {
5322 var matcher = new RegExp( $.ui.autocomplete.escapeRegex(term), "i" );
5323 return $.grep( array, function(value) {
5324 return matcher.test( value.label || value.value || value );
5332 * jQuery UI Menu (not officially released)
5334 * This widget isn't yet finished and the API is subject to change. We plan to finish
5335 * it for the next release. You're welcome to give it a try anyway and give us feedback,
5336 * as long as you're okay with migrating your code later on. We can help with that, too.
5338 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
5339 * Dual licensed under the MIT or GPL Version 2 licenses.
5340 * http://jquery.org/license
5342 * http://docs.jquery.com/UI/Menu
5346 * jquery.ui.widget.js
5350 $.widget("ui.menu", {
5351 _create: function() {
5354 .addClass("ui-menu ui-widget ui-widget-content ui-corner-all")
5357 "aria-activedescendant": "ui-active-menuitem"
5359 .click(function( event ) {
5360 if ( !$( event.target ).closest( ".ui-menu-item a" ).length ) {
5364 event.preventDefault();
5365 self.select( event );
5370 refresh: function() {
5373 // don't refresh list items that are already adapted
5374 var items = this.element.children("li:not(.ui-menu-item):has(a)")
5375 .addClass("ui-menu-item")
5376 .attr("role", "menuitem");
5379 .addClass("ui-corner-all")
5380 .attr("tabindex", -1)
5381 // mouseenter doesn't work with event delegation
5382 .mouseenter(function( event ) {
5383 self.activate( event, $(this).parent() );
5385 .mouseleave(function() {
5390 activate: function( event, item ) {
5392 if (this.hasScroll()) {
5393 var offset = item.offset().top - this.element.offset().top,
5394 scroll = this.element.scrollTop(),
5395 elementHeight = this.element.height();
5397 this.element.scrollTop( scroll + offset);
5398 } else if (offset >= elementHeight) {
5399 this.element.scrollTop( scroll + offset - elementHeight + item.height());
5402 this.active = item.eq(0)
5404 .addClass("ui-state-hover")
5405 .attr("id", "ui-active-menuitem")
5407 this._trigger("focus", event, { item: item });
5410 deactivate: function() {
5411 if (!this.active) { return; }
5413 this.active.children("a")
5414 .removeClass("ui-state-hover")
5416 this._trigger("blur");
5420 next: function(event) {
5421 this.move("next", ".ui-menu-item:first", event);
5424 previous: function(event) {
5425 this.move("prev", ".ui-menu-item:last", event);
5429 return this.active && !this.active.prevAll(".ui-menu-item").length;
5433 return this.active && !this.active.nextAll(".ui-menu-item").length;
5436 move: function(direction, edge, event) {
5438 this.activate(event, this.element.children(edge));
5441 var next = this.active[direction + "All"](".ui-menu-item").eq(0);
5443 this.activate(event, next);
5445 this.activate(event, this.element.children(edge));
5449 // TODO merge with previousPage
5450 nextPage: function(event) {
5451 if (this.hasScroll()) {
5452 // TODO merge with no-scroll-else
5453 if (!this.active || this.last()) {
5454 this.activate(event, this.element.children(".ui-menu-item:first"));
5457 var base = this.active.offset().top,
5458 height = this.element.height(),
5459 result = this.element.children(".ui-menu-item").filter(function() {
5460 var close = $(this).offset().top - base - height + $(this).height();
5461 // TODO improve approximation
5462 return close < 10 && close > -10;
5465 // TODO try to catch this earlier when scrollTop indicates the last page anyway
5466 if (!result.length) {
5467 result = this.element.children(".ui-menu-item:last");
5469 this.activate(event, result);
5471 this.activate(event, this.element.children(".ui-menu-item")
5472 .filter(!this.active || this.last() ? ":first" : ":last"));
5476 // TODO merge with nextPage
5477 previousPage: function(event) {
5478 if (this.hasScroll()) {
5479 // TODO merge with no-scroll-else
5480 if (!this.active || this.first()) {
5481 this.activate(event, this.element.children(".ui-menu-item:last"));
5485 var base = this.active.offset().top,
5486 height = this.element.height();
5487 result = this.element.children(".ui-menu-item").filter(function() {
5488 var close = $(this).offset().top - base + height - $(this).height();
5489 // TODO improve approximation
5490 return close < 10 && close > -10;
5493 // TODO try to catch this earlier when scrollTop indicates the last page anyway
5494 if (!result.length) {
5495 result = this.element.children(".ui-menu-item:first");
5497 this.activate(event, result);
5499 this.activate(event, this.element.children(".ui-menu-item")
5500 .filter(!this.active || this.first() ? ":last" : ":first"));
5504 hasScroll: function() {
5505 return this.element.height() < this.element[ $.fn.prop ? "prop" : "attr" ]("scrollHeight");
5508 select: function( event ) {
5509 this._trigger("selected", event, { item: this.active });
5515 * jQuery UI Button 1.8.14
5517 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
5518 * Dual licensed under the MIT or GPL Version 2 licenses.
5519 * http://jquery.org/license
5521 * http://docs.jquery.com/UI/Button
5525 * jquery.ui.widget.js
5527 (function( $, undefined ) {
5529 var lastActive, startXPos, startYPos, clickDragged,
5530 baseClasses = "ui-button ui-widget ui-state-default ui-corner-all",
5531 stateClasses = "ui-state-hover ui-state-active ",
5532 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",
5533 formResetHandler = function() {
5534 var buttons = $( this ).find( ":ui-button" );
5535 setTimeout(function() {
5536 buttons.button( "refresh" );
5539 radioGroup = function( radio ) {
5540 var name = radio.name,
5545 radios = $( form ).find( "[name='" + name + "']" );
5547 radios = $( "[name='" + name + "']", radio.ownerDocument )
5548 .filter(function() {
5556 $.widget( "ui.button", {
5566 _create: function() {
5567 this.element.closest( "form" )
5568 .unbind( "reset.button" )
5569 .bind( "reset.button", formResetHandler );
5571 if ( typeof this.options.disabled !== "boolean" ) {
5572 this.options.disabled = this.element.attr( "disabled" );
5575 this._determineButtonType();
5576 this.hasTitle = !!this.buttonElement.attr( "title" );
5579 options = this.options,
5580 toggleButton = this.type === "checkbox" || this.type === "radio",
5581 hoverClass = "ui-state-hover" + ( !toggleButton ? " ui-state-active" : "" ),
5582 focusClass = "ui-state-focus";
5584 if ( options.label === null ) {
5585 options.label = this.buttonElement.html();
5588 if ( this.element.is( ":disabled" ) ) {
5589 options.disabled = true;
5593 .addClass( baseClasses )
5594 .attr( "role", "button" )
5595 .bind( "mouseenter.button", function() {
5596 if ( options.disabled ) {
5599 $( this ).addClass( "ui-state-hover" );
5600 if ( this === lastActive ) {
5601 $( this ).addClass( "ui-state-active" );
5604 .bind( "mouseleave.button", function() {
5605 if ( options.disabled ) {
5608 $( this ).removeClass( hoverClass );
5610 .bind( "click.button", function( event ) {
5611 if ( options.disabled ) {
5612 event.preventDefault();
5613 event.stopImmediatePropagation();
5618 .bind( "focus.button", function() {
5619 // no need to check disabled, focus won't be triggered anyway
5620 self.buttonElement.addClass( focusClass );
5622 .bind( "blur.button", function() {
5623 self.buttonElement.removeClass( focusClass );
5626 if ( toggleButton ) {
5627 this.element.bind( "change.button", function() {
5628 if ( clickDragged ) {
5633 // if mouse moves between mousedown and mouseup (drag) set clickDragged flag
5634 // prevents issue where button state changes but checkbox/radio checked state
5635 // does not in Firefox (see ticket #6970)
5637 .bind( "mousedown.button", function( event ) {
5638 if ( options.disabled ) {
5641 clickDragged = false;
5642 startXPos = event.pageX;
5643 startYPos = event.pageY;
5645 .bind( "mouseup.button", function( event ) {
5646 if ( options.disabled ) {
5649 if ( startXPos !== event.pageX || startYPos !== event.pageY ) {
5650 clickDragged = true;
5655 if ( this.type === "checkbox" ) {
5656 this.buttonElement.bind( "click.button", function() {
5657 if ( options.disabled || clickDragged ) {
5660 $( this ).toggleClass( "ui-state-active" );
5661 self.buttonElement.attr( "aria-pressed", self.element[0].checked );
5663 } else if ( this.type === "radio" ) {
5664 this.buttonElement.bind( "click.button", function() {
5665 if ( options.disabled || clickDragged ) {
5668 $( this ).addClass( "ui-state-active" );
5669 self.buttonElement.attr( "aria-pressed", true );
5671 var radio = self.element[ 0 ];
5675 return $( this ).button( "widget" )[ 0 ];
5677 .removeClass( "ui-state-active" )
5678 .attr( "aria-pressed", false );
5682 .bind( "mousedown.button", function() {
5683 if ( options.disabled ) {
5686 $( this ).addClass( "ui-state-active" );
5688 $( document ).one( "mouseup", function() {
5692 .bind( "mouseup.button", function() {
5693 if ( options.disabled ) {
5696 $( this ).removeClass( "ui-state-active" );
5698 .bind( "keydown.button", function(event) {
5699 if ( options.disabled ) {
5702 if ( event.keyCode == $.ui.keyCode.SPACE || event.keyCode == $.ui.keyCode.ENTER ) {
5703 $( this ).addClass( "ui-state-active" );
5706 .bind( "keyup.button", function() {
5707 $( this ).removeClass( "ui-state-active" );
5710 if ( this.buttonElement.is("a") ) {
5711 this.buttonElement.keyup(function(event) {
5712 if ( event.keyCode === $.ui.keyCode.SPACE ) {
5713 // TODO pass through original event correctly (just as 2nd argument doesn't work)
5720 // TODO: pull out $.Widget's handling for the disabled option into
5721 // $.Widget.prototype._setOptionDisabled so it's easy to proxy and can
5722 // be overridden by individual plugins
5723 this._setOption( "disabled", options.disabled );
5724 this._resetButton();
5727 _determineButtonType: function() {
5729 if ( this.element.is(":checkbox") ) {
5730 this.type = "checkbox";
5731 } else if ( this.element.is(":radio") ) {
5732 this.type = "radio";
5733 } else if ( this.element.is("input") ) {
5734 this.type = "input";
5736 this.type = "button";
5739 if ( this.type === "checkbox" || this.type === "radio" ) {
5740 // we don't search against the document in case the element
5741 // is disconnected from the DOM
5742 var ancestor = this.element.parents().filter(":last"),
5743 labelSelector = "label[for=" + this.element.attr("id") + "]";
5744 this.buttonElement = ancestor.find( labelSelector );
5745 if ( !this.buttonElement.length ) {
5746 ancestor = ancestor.length ? ancestor.siblings() : this.element.siblings();
5747 this.buttonElement = ancestor.filter( labelSelector );
5748 if ( !this.buttonElement.length ) {
5749 this.buttonElement = ancestor.find( labelSelector );
5752 this.element.addClass( "ui-helper-hidden-accessible" );
5754 var checked = this.element.is( ":checked" );
5756 this.buttonElement.addClass( "ui-state-active" );
5758 this.buttonElement.attr( "aria-pressed", checked );
5760 this.buttonElement = this.element;
5764 widget: function() {
5765 return this.buttonElement;
5768 destroy: function() {
5770 .removeClass( "ui-helper-hidden-accessible" );
5772 .removeClass( baseClasses + " " + stateClasses + " " + typeClasses )
5773 .removeAttr( "role" )
5774 .removeAttr( "aria-pressed" )
5775 .html( this.buttonElement.find(".ui-button-text").html() );
5777 if ( !this.hasTitle ) {
5778 this.buttonElement.removeAttr( "title" );
5781 $.Widget.prototype.destroy.call( this );
5784 _setOption: function( key, value ) {
5785 $.Widget.prototype._setOption.apply( this, arguments );
5786 if ( key === "disabled" ) {
5788 this.element.attr( "disabled", true );
5790 this.element.removeAttr( "disabled" );
5794 this._resetButton();
5797 refresh: function() {
5798 var isDisabled = this.element.is( ":disabled" );
5799 if ( isDisabled !== this.options.disabled ) {
5800 this._setOption( "disabled", isDisabled );
5802 if ( this.type === "radio" ) {
5803 radioGroup( this.element[0] ).each(function() {
5804 if ( $( this ).is( ":checked" ) ) {
5805 $( this ).button( "widget" )
5806 .addClass( "ui-state-active" )
5807 .attr( "aria-pressed", true );
5809 $( this ).button( "widget" )
5810 .removeClass( "ui-state-active" )
5811 .attr( "aria-pressed", false );
5814 } else if ( this.type === "checkbox" ) {
5815 if ( this.element.is( ":checked" ) ) {
5817 .addClass( "ui-state-active" )
5818 .attr( "aria-pressed", true );
5821 .removeClass( "ui-state-active" )
5822 .attr( "aria-pressed", false );
5827 _resetButton: function() {
5828 if ( this.type === "input" ) {
5829 if ( this.options.label ) {
5830 this.element.val( this.options.label );
5834 var buttonElement = this.buttonElement.removeClass( typeClasses ),
5835 buttonText = $( "<span></span>" )
5836 .addClass( "ui-button-text" )
5837 .html( this.options.label )
5838 .appendTo( buttonElement.empty() )
5840 icons = this.options.icons,
5841 multipleIcons = icons.primary && icons.secondary,
5844 if ( icons.primary || icons.secondary ) {
5845 if ( this.options.text ) {
5846 buttonClasses.push( "ui-button-text-icon" + ( multipleIcons ? "s" : ( icons.primary ? "-primary" : "-secondary" ) ) );
5849 if ( icons.primary ) {
5850 buttonElement.prepend( "<span class='ui-button-icon-primary ui-icon " + icons.primary + "'></span>" );
5853 if ( icons.secondary ) {
5854 buttonElement.append( "<span class='ui-button-icon-secondary ui-icon " + icons.secondary + "'></span>" );
5857 if ( !this.options.text ) {
5858 buttonClasses.push( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" );
5860 if ( !this.hasTitle ) {
5861 buttonElement.attr( "title", buttonText );
5865 buttonClasses.push( "ui-button-text-only" );
5867 buttonElement.addClass( buttonClasses.join( " " ) );
5871 $.widget( "ui.buttonset", {
5873 items: ":button, :submit, :reset, :checkbox, :radio, a, :data(button)"
5876 _create: function() {
5877 this.element.addClass( "ui-buttonset" );
5884 _setOption: function( key, value ) {
5885 if ( key === "disabled" ) {
5886 this.buttons.button( "option", key, value );
5889 $.Widget.prototype._setOption.apply( this, arguments );
5892 refresh: function() {
5893 var ltr = this.element.css( "direction" ) === "ltr";
5895 this.buttons = this.element.find( this.options.items )
5896 .filter( ":ui-button" )
5897 .button( "refresh" )
5899 .not( ":ui-button" )
5903 return $( this ).button( "widget" )[ 0 ];
5905 .removeClass( "ui-corner-all ui-corner-left ui-corner-right" )
5907 .addClass( ltr ? "ui-corner-left" : "ui-corner-right" )
5910 .addClass( ltr ? "ui-corner-right" : "ui-corner-left" )
5915 destroy: function() {
5916 this.element.removeClass( "ui-buttonset" );
5919 return $( this ).button( "widget" )[ 0 ];
5921 .removeClass( "ui-corner-left ui-corner-right" )
5923 .button( "destroy" );
5925 $.Widget.prototype.destroy.call( this );
5931 * jQuery UI Dialog 1.8.14
5933 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
5934 * Dual licensed under the MIT or GPL Version 2 licenses.
5935 * http://jquery.org/license
5937 * http://docs.jquery.com/UI/Dialog
5941 * jquery.ui.widget.js
5942 * jquery.ui.button.js
5943 * jquery.ui.draggable.js
5944 * jquery.ui.mouse.js
5945 * jquery.ui.position.js
5946 * jquery.ui.resizable.js
5948 (function( $, undefined ) {
5950 var uiDialogClasses =
5953 'ui-widget-content ' +
5955 sizeRelatedOptions = {
5964 resizableRelatedOptions = {
5970 // support for jQuery 1.3.2 - handle common attrFn methods for dialog
5971 attrFn = $.attrFn || {
5983 $.widget("ui.dialog", {
5987 closeOnEscape: true,
6002 // ensure that the titlebar is never outside the document
6003 using: function(pos) {
6004 var topOffset = $(this).css(pos).offset().top;
6005 if (topOffset < 0) {
6006 $(this).css('top', pos.top - topOffset);
6018 _create: function() {
6019 this.originalTitle = this.element.attr('title');
6020 // #5742 - .attr() might return a DOMElement
6021 if ( typeof this.originalTitle !== "string" ) {
6022 this.originalTitle = "";
6025 this.options.title = this.options.title || this.originalTitle;
6027 options = self.options,
6029 title = options.title || ' ',
6030 titleId = $.ui.dialog.getTitleId(self.element),
6032 uiDialog = (self.uiDialog = $('<div></div>'))
6033 .appendTo(document.body)
6035 .addClass(uiDialogClasses + options.dialogClass)
6037 zIndex: options.zIndex
6039 // setting tabIndex makes the div focusable
6040 // setting outline to 0 prevents a border on focus in Mozilla
6041 .attr('tabIndex', -1).css('outline', 0).keydown(function(event) {
6042 if (options.closeOnEscape && event.keyCode &&
6043 event.keyCode === $.ui.keyCode.ESCAPE) {
6046 event.preventDefault();
6051 'aria-labelledby': titleId
6053 .mousedown(function(event) {
6054 self.moveToTop(false, event);
6057 uiDialogContent = self.element
6059 .removeAttr('title')
6061 'ui-dialog-content ' +
6062 'ui-widget-content')
6063 .appendTo(uiDialog),
6065 uiDialogTitlebar = (self.uiDialogTitlebar = $('<div></div>'))
6067 'ui-dialog-titlebar ' +
6068 'ui-widget-header ' +
6070 'ui-helper-clearfix'
6072 .prependTo(uiDialog),
6074 uiDialogTitlebarClose = $('<a href="#"></a>')
6076 'ui-dialog-titlebar-close ' +
6079 .attr('role', 'button')
6082 uiDialogTitlebarClose.addClass('ui-state-hover');
6085 uiDialogTitlebarClose.removeClass('ui-state-hover');
6089 uiDialogTitlebarClose.addClass('ui-state-focus');
6092 uiDialogTitlebarClose.removeClass('ui-state-focus');
6094 .click(function(event) {
6098 .appendTo(uiDialogTitlebar),
6100 uiDialogTitlebarCloseText = (self.uiDialogTitlebarCloseText = $('<span></span>'))
6103 'ui-icon-closethick'
6105 .text(options.closeText)
6106 .appendTo(uiDialogTitlebarClose),
6108 uiDialogTitle = $('<span></span>')
6109 .addClass('ui-dialog-title')
6110 .attr('id', titleId)
6112 .prependTo(uiDialogTitlebar);
6114 //handling of deprecated beforeclose (vs beforeClose) option
6115 //Ticket #4669 http://dev.jqueryui.com/ticket/4669
6116 //TODO: remove in 1.9pre
6117 if ($.isFunction(options.beforeclose) && !$.isFunction(options.beforeClose)) {
6118 options.beforeClose = options.beforeclose;
6121 uiDialogTitlebar.find("*").add(uiDialogTitlebar).disableSelection();
6123 if (options.draggable && $.fn.draggable) {
6124 self._makeDraggable();
6126 if (options.resizable && $.fn.resizable) {
6127 self._makeResizable();
6130 self._createButtons(options.buttons);
6131 self._isOpen = false;
6133 if ($.fn.bgiframe) {
6134 uiDialog.bgiframe();
6139 if ( this.options.autoOpen ) {
6144 destroy: function() {
6148 self.overlay.destroy();
6150 self.uiDialog.hide();
6153 .removeData('dialog')
6154 .removeClass('ui-dialog-content ui-widget-content')
6155 .hide().appendTo('body');
6156 self.uiDialog.remove();
6158 if (self.originalTitle) {
6159 self.element.attr('title', self.originalTitle);
6165 widget: function() {
6166 return this.uiDialog;
6169 close: function(event) {
6173 if (false === self._trigger('beforeClose', event)) {
6178 self.overlay.destroy();
6180 self.uiDialog.unbind('keypress.ui-dialog');
6182 self._isOpen = false;
6184 if (self.options.hide) {
6185 self.uiDialog.hide(self.options.hide, function() {
6186 self._trigger('close', event);
6189 self.uiDialog.hide();
6190 self._trigger('close', event);
6193 $.ui.dialog.overlay.resize();
6195 // adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
6196 if (self.options.modal) {
6198 $('.ui-dialog').each(function() {
6199 if (this !== self.uiDialog[0]) {
6200 thisZ = $(this).css('z-index');
6202 maxZ = Math.max(maxZ, thisZ);
6206 $.ui.dialog.maxZ = maxZ;
6212 isOpen: function() {
6213 return this._isOpen;
6216 // the force parameter allows us to move modal dialogs to their correct
6218 moveToTop: function(force, event) {
6220 options = self.options,
6223 if ((options.modal && !force) ||
6224 (!options.stack && !options.modal)) {
6225 return self._trigger('focus', event);
6228 if (options.zIndex > $.ui.dialog.maxZ) {
6229 $.ui.dialog.maxZ = options.zIndex;
6232 $.ui.dialog.maxZ += 1;
6233 self.overlay.$el.css('z-index', $.ui.dialog.overlay.maxZ = $.ui.dialog.maxZ);
6236 //Save and then restore scroll since Opera 9.5+ resets when parent z-Index is changed.
6237 // http://ui.jquery.com/bugs/ticket/3193
6238 saveScroll = { scrollTop: self.element.attr('scrollTop'), scrollLeft: self.element.attr('scrollLeft') };
6239 $.ui.dialog.maxZ += 1;
6240 self.uiDialog.css('z-index', $.ui.dialog.maxZ);
6241 self.element.attr(saveScroll);
6242 self._trigger('focus', event);
6248 if (this._isOpen) { return; }
6251 options = self.options,
6252 uiDialog = self.uiDialog;
6254 self.overlay = options.modal ? new $.ui.dialog.overlay(self) : null;
6256 self._position(options.position);
6257 uiDialog.show(options.show);
6258 self.moveToTop(true);
6260 // prevent tabbing out of modal dialogs
6261 if (options.modal) {
6262 uiDialog.bind('keypress.ui-dialog', function(event) {
6263 if (event.keyCode !== $.ui.keyCode.TAB) {
6267 var tabbables = $(':tabbable', this),
6268 first = tabbables.filter(':first'),
6269 last = tabbables.filter(':last');
6271 if (event.target === last[0] && !event.shiftKey) {
6274 } else if (event.target === first[0] && event.shiftKey) {
6281 // set focus to the first tabbable element in the content area or the first button
6282 // if there are no tabbable elements, set focus on the dialog itself
6283 $(self.element.find(':tabbable').get().concat(
6284 uiDialog.find('.ui-dialog-buttonpane :tabbable').get().concat(
6285 uiDialog.get()))).eq(0).focus();
6287 self._isOpen = true;
6288 self._trigger('open');
6293 _createButtons: function(buttons) {
6296 uiDialogButtonPane = $('<div></div>')
6298 'ui-dialog-buttonpane ' +
6299 'ui-widget-content ' +
6300 'ui-helper-clearfix'
6302 uiButtonSet = $( "<div></div>" )
6303 .addClass( "ui-dialog-buttonset" )
6304 .appendTo( uiDialogButtonPane );
6306 // if we already have a button pane, remove it
6307 self.uiDialog.find('.ui-dialog-buttonpane').remove();
6309 if (typeof buttons === 'object' && buttons !== null) {
6310 $.each(buttons, function() {
6311 return !(hasButtons = true);
6315 $.each(buttons, function(name, props) {
6316 props = $.isFunction( props ) ?
6317 { click: props, text: name } :
6319 var button = $('<button type="button"></button>')
6321 props.click.apply(self.element[0], arguments);
6323 .appendTo(uiButtonSet);
6324 // can't use .attr( props, true ) with jQuery 1.3.2.
6325 $.each( props, function( key, value ) {
6326 if ( key === "click" ) {
6329 if ( key in attrFn ) {
6330 button[ key ]( value );
6332 button.attr( key, value );
6339 uiDialogButtonPane.appendTo(self.uiDialog);
6343 _makeDraggable: function() {
6345 options = self.options,
6349 function filteredUi(ui) {
6351 position: ui.position,
6356 self.uiDialog.draggable({
6357 cancel: '.ui-dialog-content, .ui-dialog-titlebar-close',
6358 handle: '.ui-dialog-titlebar',
6359 containment: 'document',
6360 start: function(event, ui) {
6361 heightBeforeDrag = options.height === "auto" ? "auto" : $(this).height();
6362 $(this).height($(this).height()).addClass("ui-dialog-dragging");
6363 self._trigger('dragStart', event, filteredUi(ui));
6365 drag: function(event, ui) {
6366 self._trigger('drag', event, filteredUi(ui));
6368 stop: function(event, ui) {
6369 options.position = [ui.position.left - doc.scrollLeft(),
6370 ui.position.top - doc.scrollTop()];
6371 $(this).removeClass("ui-dialog-dragging").height(heightBeforeDrag);
6372 self._trigger('dragStop', event, filteredUi(ui));
6373 $.ui.dialog.overlay.resize();
6378 _makeResizable: function(handles) {
6379 handles = (handles === undefined ? this.options.resizable : handles);
6381 options = self.options,
6382 // .ui-resizable has position: relative defined in the stylesheet
6383 // but dialogs have to use absolute or fixed positioning
6384 position = self.uiDialog.css('position'),
6385 resizeHandles = (typeof handles === 'string' ?
6387 'n,e,s,w,se,sw,ne,nw'
6390 function filteredUi(ui) {
6392 originalPosition: ui.originalPosition,
6393 originalSize: ui.originalSize,
6394 position: ui.position,
6399 self.uiDialog.resizable({
6400 cancel: '.ui-dialog-content',
6401 containment: 'document',
6402 alsoResize: self.element,
6403 maxWidth: options.maxWidth,
6404 maxHeight: options.maxHeight,
6405 minWidth: options.minWidth,
6406 minHeight: self._minHeight(),
6407 handles: resizeHandles,
6408 start: function(event, ui) {
6409 $(this).addClass("ui-dialog-resizing");
6410 self._trigger('resizeStart', event, filteredUi(ui));
6412 resize: function(event, ui) {
6413 self._trigger('resize', event, filteredUi(ui));
6415 stop: function(event, ui) {
6416 $(this).removeClass("ui-dialog-resizing");
6417 options.height = $(this).height();
6418 options.width = $(this).width();
6419 self._trigger('resizeStop', event, filteredUi(ui));
6420 $.ui.dialog.overlay.resize();
6423 .css('position', position)
6424 .find('.ui-resizable-se').addClass('ui-icon ui-icon-grip-diagonal-se');
6427 _minHeight: function() {
6428 var options = this.options;
6430 if (options.height === 'auto') {
6431 return options.minHeight;
6433 return Math.min(options.minHeight, options.height);
6437 _position: function(position) {
6443 // deep extending converts arrays to objects in jQuery <= 1.3.2 :-(
6444 // if (typeof position == 'string' || $.isArray(position)) {
6445 // myAt = $.isArray(position) ? position : position.split(' ');
6447 if (typeof position === 'string' || (typeof position === 'object' && '0' in position)) {
6448 myAt = position.split ? position.split(' ') : [position[0], position[1]];
6449 if (myAt.length === 1) {
6453 $.each(['left', 'top'], function(i, offsetPosition) {
6454 if (+myAt[i] === myAt[i]) {
6455 offset[i] = myAt[i];
6456 myAt[i] = offsetPosition;
6463 offset: offset.join(" ")
6467 position = $.extend({}, $.ui.dialog.prototype.options.position, position);
6469 position = $.ui.dialog.prototype.options.position;
6472 // need to show the dialog to get the actual offset in the position plugin
6473 isVisible = this.uiDialog.is(':visible');
6475 this.uiDialog.show();
6478 // workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
6479 .css({ top: 0, left: 0 })
6480 .position($.extend({ of: window }, position));
6482 this.uiDialog.hide();
6486 _setOptions: function( options ) {
6488 resizableOptions = {},
6491 $.each( options, function( key, value ) {
6492 self._setOption( key, value );
6494 if ( key in sizeRelatedOptions ) {
6497 if ( key in resizableRelatedOptions ) {
6498 resizableOptions[ key ] = value;
6505 if ( this.uiDialog.is( ":data(resizable)" ) ) {
6506 this.uiDialog.resizable( "option", resizableOptions );
6510 _setOption: function(key, value){
6512 uiDialog = self.uiDialog;
6515 //handling of deprecated beforeclose (vs beforeClose) option
6516 //Ticket #4669 http://dev.jqueryui.com/ticket/4669
6517 //TODO: remove in 1.9pre
6519 key = "beforeClose";
6522 self._createButtons(value);
6525 // ensure that we always pass a string
6526 self.uiDialogTitlebarCloseText.text("" + value);
6530 .removeClass(self.options.dialogClass)
6531 .addClass(uiDialogClasses + value);
6535 uiDialog.addClass('ui-dialog-disabled');
6537 uiDialog.removeClass('ui-dialog-disabled');
6541 var isDraggable = uiDialog.is( ":data(draggable)" );
6542 if ( isDraggable && !value ) {
6543 uiDialog.draggable( "destroy" );
6546 if ( !isDraggable && value ) {
6547 self._makeDraggable();
6551 self._position(value);
6554 // currently resizable, becoming non-resizable
6555 var isResizable = uiDialog.is( ":data(resizable)" );
6556 if (isResizable && !value) {
6557 uiDialog.resizable('destroy');
6560 // currently resizable, changing handles
6561 if (isResizable && typeof value === 'string') {
6562 uiDialog.resizable('option', 'handles', value);
6565 // currently non-resizable, becoming resizable
6566 if (!isResizable && value !== false) {
6567 self._makeResizable(value);
6571 // convert whatever was passed in o a string, for html() to not throw up
6572 $(".ui-dialog-title", self.uiDialogTitlebar).html("" + (value || ' '));
6576 $.Widget.prototype._setOption.apply(self, arguments);
6580 /* If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
6581 * divs will both have width and height set, so we need to reset them
6583 var options = this.options,
6586 isVisible = this.uiDialog.is( ":visible" );
6588 // reset content sizing
6589 this.element.show().css({
6595 if (options.minWidth > options.width) {
6596 options.width = options.minWidth;
6599 // reset wrapper sizing
6600 // determine the height of all the non-content elements
6601 nonContentHeight = this.uiDialog.css({
6603 width: options.width
6606 minContentHeight = Math.max( 0, options.minHeight - nonContentHeight );
6608 if ( options.height === "auto" ) {
6609 // only needed for IE6 support
6610 if ( $.support.minHeight ) {
6612 minHeight: minContentHeight,
6616 this.uiDialog.show();
6617 var autoHeight = this.element.css( "height", "auto" ).height();
6619 this.uiDialog.hide();
6621 this.element.height( Math.max( autoHeight, minContentHeight ) );
6624 this.element.height( Math.max( options.height - nonContentHeight, 0 ) );
6627 if (this.uiDialog.is(':data(resizable)')) {
6628 this.uiDialog.resizable('option', 'minHeight', this._minHeight());
6633 $.extend($.ui.dialog, {
6639 getTitleId: function($el) {
6640 var id = $el.attr('id');
6645 return 'ui-dialog-title-' + id;
6648 overlay: function(dialog) {
6649 this.$el = $.ui.dialog.overlay.create(dialog);
6653 $.extend($.ui.dialog.overlay, {
6655 // reuse old instances due to IE memory leak with alpha transparency (see #5185)
6658 events: $.map('focus,mousedown,mouseup,keydown,keypress,click'.split(','),
6659 function(event) { return event + '.dialog-overlay'; }).join(' '),
6660 create: function(dialog) {
6661 if (this.instances.length === 0) {
6662 // prevent use of anchors and inputs
6663 // we use a setTimeout in case the overlay is created from an
6664 // event that we're going to be cancelling (see #2804)
6665 setTimeout(function() {
6666 // handle $(el).dialog().dialog('close') (see #4065)
6667 if ($.ui.dialog.overlay.instances.length) {
6668 $(document).bind($.ui.dialog.overlay.events, function(event) {
6669 // stop events if the z-index of the target is < the z-index of the overlay
6670 // we cannot return true when we don't want to cancel the event (#3523)
6671 if ($(event.target).zIndex() < $.ui.dialog.overlay.maxZ) {
6678 // allow closing by pressing the escape key
6679 $(document).bind('keydown.dialog-overlay', function(event) {
6680 if (dialog.options.closeOnEscape && event.keyCode &&
6681 event.keyCode === $.ui.keyCode.ESCAPE) {
6683 dialog.close(event);
6684 event.preventDefault();
6688 // handle window resize
6689 $(window).bind('resize.dialog-overlay', $.ui.dialog.overlay.resize);
6692 var $el = (this.oldInstances.pop() || $('<div></div>').addClass('ui-widget-overlay'))
6693 .appendTo(document.body)
6695 width: this.width(),
6696 height: this.height()
6699 if ($.fn.bgiframe) {
6703 this.instances.push($el);
6707 destroy: function($el) {
6708 var indexOf = $.inArray($el, this.instances);
6710 this.oldInstances.push(this.instances.splice(indexOf, 1)[0]);
6713 if (this.instances.length === 0) {
6714 $([document, window]).unbind('.dialog-overlay');
6719 // adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
6721 $.each(this.instances, function() {
6722 maxZ = Math.max(maxZ, this.css('z-index'));
6727 height: function() {
6731 if ($.browser.msie && $.browser.version < 7) {
6732 scrollHeight = Math.max(
6733 document.documentElement.scrollHeight,
6734 document.body.scrollHeight
6736 offsetHeight = Math.max(
6737 document.documentElement.offsetHeight,
6738 document.body.offsetHeight
6741 if (scrollHeight < offsetHeight) {
6742 return $(window).height() + 'px';
6744 return scrollHeight + 'px';
6746 // handle "good" browsers
6748 return $(document).height() + 'px';
6756 if ( $.browser.msie ) {
6757 scrollWidth = Math.max(
6758 document.documentElement.scrollWidth,
6759 document.body.scrollWidth
6761 offsetWidth = Math.max(
6762 document.documentElement.offsetWidth,
6763 document.body.offsetWidth
6766 if (scrollWidth < offsetWidth) {
6767 return $(window).width() + 'px';
6769 return scrollWidth + 'px';
6771 // handle "good" browsers
6773 return $(document).width() + 'px';
6777 resize: function() {
6778 /* If the dialog is draggable and the user drags it past the
6779 * right edge of the window, the document becomes wider so we
6780 * need to stretch the overlay. If the user then drags the
6781 * dialog back to the left, the document will become narrower,
6782 * so we need to shrink the overlay to the appropriate size.
6783 * This is handled by shrinking the overlay before setting it
6784 * to the full document size.
6786 var $overlays = $([]);
6787 $.each($.ui.dialog.overlay.instances, function() {
6788 $overlays = $overlays.add(this);
6795 width: $.ui.dialog.overlay.width(),
6796 height: $.ui.dialog.overlay.height()
6801 $.extend($.ui.dialog.overlay.prototype, {
6802 destroy: function() {
6803 $.ui.dialog.overlay.destroy(this.$el);
6809 * jQuery UI Slider 1.8.14
6811 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
6812 * Dual licensed under the MIT or GPL Version 2 licenses.
6813 * http://jquery.org/license
6815 * http://docs.jquery.com/UI/Slider
6819 * jquery.ui.mouse.js
6820 * jquery.ui.widget.js
6822 (function( $, undefined ) {
6824 // number of pages in a slider
6825 // (how many times can you page up/down to go through the whole range)
6828 $.widget( "ui.slider", $.ui.mouse, {
6830 widgetEventPrefix: "slide",
6837 orientation: "horizontal",
6844 _create: function() {
6847 existingHandles = this.element.find( ".ui-slider-handle" ).addClass( "ui-state-default ui-corner-all" ),
6848 handle = "<a class='ui-slider-handle ui-state-default ui-corner-all' href='#'></a>",
6849 handleCount = ( o.values && o.values.length ) || 1,
6852 this._keySliding = false;
6853 this._mouseSliding = false;
6854 this._animateOff = true;
6855 this._handleIndex = null;
6856 this._detectOrientation();
6860 .addClass( "ui-slider" +
6861 " ui-slider-" + this.orientation +
6863 " ui-widget-content" +
6865 ( o.disabled ? " ui-slider-disabled ui-disabled" : "" ) );
6870 if ( o.range === true ) {
6872 o.values = [ this._valueMin(), this._valueMin() ];
6874 if ( o.values.length && o.values.length !== 2 ) {
6875 o.values = [ o.values[0], o.values[0] ];
6879 this.range = $( "<div></div>" )
6880 .appendTo( this.element )
6881 .addClass( "ui-slider-range" +
6882 // note: this isn't the most fittingly semantic framework class for this element,
6883 // but worked best visually with a variety of themes
6884 " ui-widget-header" +
6885 ( ( o.range === "min" || o.range === "max" ) ? " ui-slider-range-" + o.range : "" ) );
6888 for ( var i = existingHandles.length; i < handleCount; i += 1 ) {
6889 handles.push( handle );
6892 this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( self.element ) );
6894 this.handle = this.handles.eq( 0 );
6896 this.handles.add( this.range ).filter( "a" )
6897 .click(function( event ) {
6898 event.preventDefault();
6901 if ( !o.disabled ) {
6902 $( this ).addClass( "ui-state-hover" );
6905 $( this ).removeClass( "ui-state-hover" );
6908 if ( !o.disabled ) {
6909 $( ".ui-slider .ui-state-focus" ).removeClass( "ui-state-focus" );
6910 $( this ).addClass( "ui-state-focus" );
6916 $( this ).removeClass( "ui-state-focus" );
6919 this.handles.each(function( i ) {
6920 $( this ).data( "index.ui-slider-handle", i );
6924 .keydown(function( event ) {
6926 index = $( this ).data( "index.ui-slider-handle" ),
6932 if ( self.options.disabled ) {
6936 switch ( event.keyCode ) {
6937 case $.ui.keyCode.HOME:
6938 case $.ui.keyCode.END:
6939 case $.ui.keyCode.PAGE_UP:
6940 case $.ui.keyCode.PAGE_DOWN:
6941 case $.ui.keyCode.UP:
6942 case $.ui.keyCode.RIGHT:
6943 case $.ui.keyCode.DOWN:
6944 case $.ui.keyCode.LEFT:
6946 if ( !self._keySliding ) {
6947 self._keySliding = true;
6948 $( this ).addClass( "ui-state-active" );
6949 allowed = self._start( event, index );
6950 if ( allowed === false ) {
6957 step = self.options.step;
6958 if ( self.options.values && self.options.values.length ) {
6959 curVal = newVal = self.values( index );
6961 curVal = newVal = self.value();
6964 switch ( event.keyCode ) {
6965 case $.ui.keyCode.HOME:
6966 newVal = self._valueMin();
6968 case $.ui.keyCode.END:
6969 newVal = self._valueMax();
6971 case $.ui.keyCode.PAGE_UP:
6972 newVal = self._trimAlignValue( curVal + ( (self._valueMax() - self._valueMin()) / numPages ) );
6974 case $.ui.keyCode.PAGE_DOWN:
6975 newVal = self._trimAlignValue( curVal - ( (self._valueMax() - self._valueMin()) / numPages ) );
6977 case $.ui.keyCode.UP:
6978 case $.ui.keyCode.RIGHT:
6979 if ( curVal === self._valueMax() ) {
6982 newVal = self._trimAlignValue( curVal + step );
6984 case $.ui.keyCode.DOWN:
6985 case $.ui.keyCode.LEFT:
6986 if ( curVal === self._valueMin() ) {
6989 newVal = self._trimAlignValue( curVal - step );
6993 self._slide( event, index, newVal );
6998 .keyup(function( event ) {
6999 var index = $( this ).data( "index.ui-slider-handle" );
7001 if ( self._keySliding ) {
7002 self._keySliding = false;
7003 self._stop( event, index );
7004 self._change( event, index );
7005 $( this ).removeClass( "ui-state-active" );
7010 this._refreshValue();
7012 this._animateOff = false;
7015 destroy: function() {
7016 this.handles.remove();
7017 this.range.remove();
7020 .removeClass( "ui-slider" +
7021 " ui-slider-horizontal" +
7022 " ui-slider-vertical" +
7023 " ui-slider-disabled" +
7025 " ui-widget-content" +
7027 .removeData( "slider" )
7028 .unbind( ".slider" );
7030 this._mouseDestroy();
7035 _mouseCapture: function( event ) {
7036 var o = this.options,
7051 this.elementSize = {
7052 width: this.element.outerWidth(),
7053 height: this.element.outerHeight()
7055 this.elementOffset = this.element.offset();
7057 position = { x: event.pageX, y: event.pageY };
7058 normValue = this._normValueFromMouse( position );
7059 distance = this._valueMax() - this._valueMin() + 1;
7061 this.handles.each(function( i ) {
7062 var thisDistance = Math.abs( normValue - self.values(i) );
7063 if ( distance > thisDistance ) {
7064 distance = thisDistance;
7065 closestHandle = $( this );
7070 // workaround for bug #3736 (if both handles of a range are at 0,
7071 // the first is always used as the one with least distance,
7072 // and moving it is obviously prevented by preventing negative ranges)
7073 if( o.range === true && this.values(1) === o.min ) {
7075 closestHandle = $( this.handles[index] );
7078 allowed = this._start( event, index );
7079 if ( allowed === false ) {
7082 this._mouseSliding = true;
7084 self._handleIndex = index;
7087 .addClass( "ui-state-active" )
7090 offset = closestHandle.offset();
7091 mouseOverHandle = !$( event.target ).parents().andSelf().is( ".ui-slider-handle" );
7092 this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
7093 left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
7094 top: event.pageY - offset.top -
7095 ( closestHandle.height() / 2 ) -
7096 ( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) -
7097 ( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) +
7098 ( parseInt( closestHandle.css("marginTop"), 10 ) || 0)
7101 if ( !this.handles.hasClass( "ui-state-hover" ) ) {
7102 this._slide( event, index, normValue );
7104 this._animateOff = true;
7108 _mouseStart: function( event ) {
7112 _mouseDrag: function( event ) {
7113 var position = { x: event.pageX, y: event.pageY },
7114 normValue = this._normValueFromMouse( position );
7116 this._slide( event, this._handleIndex, normValue );
7121 _mouseStop: function( event ) {
7122 this.handles.removeClass( "ui-state-active" );
7123 this._mouseSliding = false;
7125 this._stop( event, this._handleIndex );
7126 this._change( event, this._handleIndex );
7128 this._handleIndex = null;
7129 this._clickOffset = null;
7130 this._animateOff = false;
7135 _detectOrientation: function() {
7136 this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
7139 _normValueFromMouse: function( position ) {
7146 if ( this.orientation === "horizontal" ) {
7147 pixelTotal = this.elementSize.width;
7148 pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 );
7150 pixelTotal = this.elementSize.height;
7151 pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 );
7154 percentMouse = ( pixelMouse / pixelTotal );
7155 if ( percentMouse > 1 ) {
7158 if ( percentMouse < 0 ) {
7161 if ( this.orientation === "vertical" ) {
7162 percentMouse = 1 - percentMouse;
7165 valueTotal = this._valueMax() - this._valueMin();
7166 valueMouse = this._valueMin() + percentMouse * valueTotal;
7168 return this._trimAlignValue( valueMouse );
7171 _start: function( event, index ) {
7173 handle: this.handles[ index ],
7176 if ( this.options.values && this.options.values.length ) {
7177 uiHash.value = this.values( index );
7178 uiHash.values = this.values();
7180 return this._trigger( "start", event, uiHash );
7183 _slide: function( event, index, newVal ) {
7188 if ( this.options.values && this.options.values.length ) {
7189 otherVal = this.values( index ? 0 : 1 );
7191 if ( ( this.options.values.length === 2 && this.options.range === true ) &&
7192 ( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) )
7197 if ( newVal !== this.values( index ) ) {
7198 newValues = this.values();
7199 newValues[ index ] = newVal;
7200 // A slide can be canceled by returning false from the slide callback
7201 allowed = this._trigger( "slide", event, {
7202 handle: this.handles[ index ],
7206 otherVal = this.values( index ? 0 : 1 );
7207 if ( allowed !== false ) {
7208 this.values( index, newVal, true );
7212 if ( newVal !== this.value() ) {
7213 // A slide can be canceled by returning false from the slide callback
7214 allowed = this._trigger( "slide", event, {
7215 handle: this.handles[ index ],
7218 if ( allowed !== false ) {
7219 this.value( newVal );
7225 _stop: function( event, index ) {
7227 handle: this.handles[ index ],
7230 if ( this.options.values && this.options.values.length ) {
7231 uiHash.value = this.values( index );
7232 uiHash.values = this.values();
7235 this._trigger( "stop", event, uiHash );
7238 _change: function( event, index ) {
7239 if ( !this._keySliding && !this._mouseSliding ) {
7241 handle: this.handles[ index ],
7244 if ( this.options.values && this.options.values.length ) {
7245 uiHash.value = this.values( index );
7246 uiHash.values = this.values();
7249 this._trigger( "change", event, uiHash );
7253 value: function( newValue ) {
7254 if ( arguments.length ) {
7255 this.options.value = this._trimAlignValue( newValue );
7256 this._refreshValue();
7257 this._change( null, 0 );
7261 return this._value();
7264 values: function( index, newValue ) {
7269 if ( arguments.length > 1 ) {
7270 this.options.values[ index ] = this._trimAlignValue( newValue );
7271 this._refreshValue();
7272 this._change( null, index );
7276 if ( arguments.length ) {
7277 if ( $.isArray( arguments[ 0 ] ) ) {
7278 vals = this.options.values;
7279 newValues = arguments[ 0 ];
7280 for ( i = 0; i < vals.length; i += 1 ) {
7281 vals[ i ] = this._trimAlignValue( newValues[ i ] );
7282 this._change( null, i );
7284 this._refreshValue();
7286 if ( this.options.values && this.options.values.length ) {
7287 return this._values( index );
7289 return this.value();
7293 return this._values();
7297 _setOption: function( key, value ) {
7301 if ( $.isArray( this.options.values ) ) {
7302 valsLength = this.options.values.length;
7305 $.Widget.prototype._setOption.apply( this, arguments );
7310 this.handles.filter( ".ui-state-focus" ).blur();
7311 this.handles.removeClass( "ui-state-hover" );
7312 this.handles.attr( "disabled", "disabled" );
7313 this.element.addClass( "ui-disabled" );
7315 this.handles.removeAttr( "disabled" );
7316 this.element.removeClass( "ui-disabled" );
7320 this._detectOrientation();
7322 .removeClass( "ui-slider-horizontal ui-slider-vertical" )
7323 .addClass( "ui-slider-" + this.orientation );
7324 this._refreshValue();
7327 this._animateOff = true;
7328 this._refreshValue();
7329 this._change( null, 0 );
7330 this._animateOff = false;
7333 this._animateOff = true;
7334 this._refreshValue();
7335 for ( i = 0; i < valsLength; i += 1 ) {
7336 this._change( null, i );
7338 this._animateOff = false;
7343 //internal value getter
7344 // _value() returns value trimmed by min and max, aligned by step
7345 _value: function() {
7346 var val = this.options.value;
7347 val = this._trimAlignValue( val );
7352 //internal values getter
7353 // _values() returns array of values trimmed by min and max, aligned by step
7354 // _values( index ) returns single value trimmed by min and max, aligned by step
7355 _values: function( index ) {
7360 if ( arguments.length ) {
7361 val = this.options.values[ index ];
7362 val = this._trimAlignValue( val );
7366 // .slice() creates a copy of the array
7367 // this copy gets trimmed by min and max and then returned
7368 vals = this.options.values.slice();
7369 for ( i = 0; i < vals.length; i+= 1) {
7370 vals[ i ] = this._trimAlignValue( vals[ i ] );
7377 // returns the step-aligned value that val is closest to, between (inclusive) min and max
7378 _trimAlignValue: function( val ) {
7379 if ( val <= this._valueMin() ) {
7380 return this._valueMin();
7382 if ( val >= this._valueMax() ) {
7383 return this._valueMax();
7385 var step = ( this.options.step > 0 ) ? this.options.step : 1,
7386 valModStep = (val - this._valueMin()) % step;
7387 alignValue = val - valModStep;
7389 if ( Math.abs(valModStep) * 2 >= step ) {
7390 alignValue += ( valModStep > 0 ) ? step : ( -step );
7393 // Since JavaScript has problems with large floats, round
7394 // the final value to 5 digits after the decimal point (see #4124)
7395 return parseFloat( alignValue.toFixed(5) );
7398 _valueMin: function() {
7399 return this.options.min;
7402 _valueMax: function() {
7403 return this.options.max;
7406 _refreshValue: function() {
7407 var oRange = this.options.range,
7410 animate = ( !this._animateOff ) ? o.animate : false,
7418 if ( this.options.values && this.options.values.length ) {
7419 this.handles.each(function( i, j ) {
7420 valPercent = ( self.values(i) - self._valueMin() ) / ( self._valueMax() - self._valueMin() ) * 100;
7421 _set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
7422 $( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
7423 if ( self.options.range === true ) {
7424 if ( self.orientation === "horizontal" ) {
7426 self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate );
7429 self.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
7433 self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate );
7436 self.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
7440 lastValPercent = valPercent;
7443 value = this.value();
7444 valueMin = this._valueMin();
7445 valueMax = this._valueMax();
7446 valPercent = ( valueMax !== valueMin ) ?
7447 ( value - valueMin ) / ( valueMax - valueMin ) * 100 :
7449 _set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
7450 this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
7452 if ( oRange === "min" && this.orientation === "horizontal" ) {
7453 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate );
7455 if ( oRange === "max" && this.orientation === "horizontal" ) {
7456 this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
7458 if ( oRange === "min" && this.orientation === "vertical" ) {
7459 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate );
7461 if ( oRange === "max" && this.orientation === "vertical" ) {
7462 this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
7469 $.extend( $.ui.slider, {
7475 * jQuery UI Tabs 1.8.14
7477 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
7478 * Dual licensed under the MIT or GPL Version 2 licenses.
7479 * http://jquery.org/license
7481 * http://docs.jquery.com/UI/Tabs
7485 * jquery.ui.widget.js
7487 (function( $, undefined ) {
7492 function getNextTabId() {
7496 function getNextListId() {
7500 $.widget( "ui.tabs", {
7505 cookie: null, // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true }
7511 fx: null, // e.g. { height: 'toggle', opacity: 'toggle', duration: 200 }
7512 idPrefix: "ui-tabs-",
7514 panelTemplate: "<div></div>",
7518 spinner: "<em>Loading…</em>",
7519 tabTemplate: "<li><a href='#{href}'><span>#{label}</span></a></li>"
7522 _create: function() {
7523 this._tabify( true );
7526 _setOption: function( key, value ) {
7527 if ( key == "selected" ) {
7528 if (this.options.collapsible && value == this.options.selected ) {
7531 this.select( value );
7533 this.options[ key ] = value;
7538 _tabId: function( a ) {
7539 return a.title && a.title.replace( /\s/g, "_" ).replace( /[^\w\u00c0-\uFFFF-]/g, "" ) ||
7540 this.options.idPrefix + getNextTabId();
7543 _sanitizeSelector: function( hash ) {
7544 // we need this because an id may contain a ":"
7545 return hash.replace( /:/g, "\\:" );
7548 _cookie: function() {
7549 var cookie = this.cookie ||
7550 ( this.cookie = this.options.cookie.name || "ui-tabs-" + getNextListId() );
7551 return $.cookie.apply( null, [ cookie ].concat( $.makeArray( arguments ) ) );
7554 _ui: function( tab, panel ) {
7558 index: this.anchors.index( tab )
7562 _cleanup: function() {
7563 // restore all former loading tabs labels
7564 this.lis.filter( ".ui-state-processing" )
7565 .removeClass( "ui-state-processing" )
7566 .find( "span:data(label.tabs)" )
7569 el.html( el.data( "label.tabs" ) ).removeData( "label.tabs" );
7573 _tabify: function( init ) {
7576 fragmentId = /^#.+/; // Safari 2 reports '#' for an empty hash
7578 this.list = this.element.find( "ol,ul" ).eq( 0 );
7579 this.lis = $( " > li:has(a[href])", this.list );
7580 this.anchors = this.lis.map(function() {
7581 return $( "a", this )[ 0 ];
7583 this.panels = $( [] );
7585 this.anchors.each(function( i, a ) {
7586 var href = $( a ).attr( "href" );
7587 // For dynamically created HTML that contains a hash as href IE < 8 expands
7588 // such href to the full page url with hash and then misinterprets tab as ajax.
7589 // Same consideration applies for an added tab with a fragment identifier
7590 // since a[href=#fragment-identifier] does unexpectedly not match.
7591 // Thus normalize href attribute...
7592 var hrefBase = href.split( "#" )[ 0 ],
7594 if ( hrefBase && ( hrefBase === location.toString().split( "#" )[ 0 ] ||
7595 ( baseEl = $( "base" )[ 0 ]) && hrefBase === baseEl.href ) ) {
7601 if ( fragmentId.test( href ) ) {
7602 self.panels = self.panels.add( self.element.find( self._sanitizeSelector( href ) ) );
7604 // prevent loading the page itself if href is just "#"
7605 } else if ( href && href !== "#" ) {
7606 // required for restore on destroy
7607 $.data( a, "href.tabs", href );
7609 // TODO until #3808 is fixed strip fragment identifier from url
7610 // (IE fails to load from such url)
7611 $.data( a, "load.tabs", href.replace( /#.*$/, "" ) );
7613 var id = self._tabId( a );
7615 var $panel = self.element.find( "#" + id );
7616 if ( !$panel.length ) {
7617 $panel = $( o.panelTemplate )
7619 .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
7620 .insertAfter( self.panels[ i - 1 ] || self.list );
7621 $panel.data( "destroy.tabs", true );
7623 self.panels = self.panels.add( $panel );
7626 o.disabled.push( i );
7630 // initialization from scratch
7632 // attach necessary classes for styling
7633 this.element.addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" );
7634 this.list.addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" );
7635 this.lis.addClass( "ui-state-default ui-corner-top" );
7636 this.panels.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" );
7639 // use "selected" option or try to retrieve:
7640 // 1. from fragment identifier in url
7642 // 3. from selected class attribute on <li>
7643 if ( o.selected === undefined ) {
7644 if ( location.hash ) {
7645 this.anchors.each(function( i, a ) {
7646 if ( a.hash == location.hash ) {
7652 if ( typeof o.selected !== "number" && o.cookie ) {
7653 o.selected = parseInt( self._cookie(), 10 );
7655 if ( typeof o.selected !== "number" && this.lis.filter( ".ui-tabs-selected" ).length ) {
7656 o.selected = this.lis.index( this.lis.filter( ".ui-tabs-selected" ) );
7658 o.selected = o.selected || ( this.lis.length ? 0 : -1 );
7659 } else if ( o.selected === null ) { // usage of null is deprecated, TODO remove in next release
7663 // sanity check - default to first tab...
7664 o.selected = ( ( o.selected >= 0 && this.anchors[ o.selected ] ) || o.selected < 0 )
7668 // Take disabling tabs via class attribute from HTML
7669 // into account and update option properly.
7670 // A selected tab cannot become disabled.
7671 o.disabled = $.unique( o.disabled.concat(
7672 $.map( this.lis.filter( ".ui-state-disabled" ), function( n, i ) {
7673 return self.lis.index( n );
7677 if ( $.inArray( o.selected, o.disabled ) != -1 ) {
7678 o.disabled.splice( $.inArray( o.selected, o.disabled ), 1 );
7681 // highlight selected tab
7682 this.panels.addClass( "ui-tabs-hide" );
7683 this.lis.removeClass( "ui-tabs-selected ui-state-active" );
7684 // check for length avoids error when initializing empty list
7685 if ( o.selected >= 0 && this.anchors.length ) {
7686 self.element.find( self._sanitizeSelector( self.anchors[ o.selected ].hash ) ).removeClass( "ui-tabs-hide" );
7687 this.lis.eq( o.selected ).addClass( "ui-tabs-selected ui-state-active" );
7689 // seems to be expected behavior that the show callback is fired
7690 self.element.queue( "tabs", function() {
7691 self._trigger( "show", null,
7692 self._ui( self.anchors[ o.selected ], self.element.find( self._sanitizeSelector( self.anchors[ o.selected ].hash ) )[ 0 ] ) );
7695 this.load( o.selected );
7698 // clean up to avoid memory leaks in certain versions of IE 6
7699 // TODO: namespace this event
7700 $( window ).bind( "unload", function() {
7701 self.lis.add( self.anchors ).unbind( ".tabs" );
7702 self.lis = self.anchors = self.panels = null;
7704 // update selected after add/remove
7706 o.selected = this.lis.index( this.lis.filter( ".ui-tabs-selected" ) );
7709 // update collapsible
7710 // TODO: use .toggleClass()
7711 this.element[ o.collapsible ? "addClass" : "removeClass" ]( "ui-tabs-collapsible" );
7713 // set or update cookie after init and add/remove respectively
7715 this._cookie( o.selected, o.cookie );
7719 for ( var i = 0, li; ( li = this.lis[ i ] ); i++ ) {
7720 $( li )[ $.inArray( i, o.disabled ) != -1 &&
7721 // TODO: use .toggleClass()
7722 !$( li ).hasClass( "ui-tabs-selected" ) ? "addClass" : "removeClass" ]( "ui-state-disabled" );
7725 // reset cache if switching from cached to not cached
7726 if ( o.cache === false ) {
7727 this.anchors.removeData( "cache.tabs" );
7730 // remove all handlers before, tabify may run on existing tabs after add or option change
7731 this.lis.add( this.anchors ).unbind( ".tabs" );
7733 if ( o.event !== "mouseover" ) {
7734 var addState = function( state, el ) {
7735 if ( el.is( ":not(.ui-state-disabled)" ) ) {
7736 el.addClass( "ui-state-" + state );
7739 var removeState = function( state, el ) {
7740 el.removeClass( "ui-state-" + state );
7742 this.lis.bind( "mouseover.tabs" , function() {
7743 addState( "hover", $( this ) );
7745 this.lis.bind( "mouseout.tabs", function() {
7746 removeState( "hover", $( this ) );
7748 this.anchors.bind( "focus.tabs", function() {
7749 addState( "focus", $( this ).closest( "li" ) );
7751 this.anchors.bind( "blur.tabs", function() {
7752 removeState( "focus", $( this ).closest( "li" ) );
7756 // set up animations
7759 if ( $.isArray( o.fx ) ) {
7763 hideFx = showFx = o.fx;
7767 // Reset certain styles left over from animation
7768 // and prevent IE's ClearType bug...
7769 function resetStyle( $el, fx ) {
7770 $el.css( "display", "" );
7771 if ( !$.support.opacity && fx.opacity ) {
7772 $el[ 0 ].style.removeAttribute( "filter" );
7777 var showTab = showFx
7778 ? function( clicked, $show ) {
7779 $( clicked ).closest( "li" ).addClass( "ui-tabs-selected ui-state-active" );
7780 $show.hide().removeClass( "ui-tabs-hide" ) // avoid flicker that way
7781 .animate( showFx, showFx.duration || "normal", function() {
7782 resetStyle( $show, showFx );
7783 self._trigger( "show", null, self._ui( clicked, $show[ 0 ] ) );
7786 : function( clicked, $show ) {
7787 $( clicked ).closest( "li" ).addClass( "ui-tabs-selected ui-state-active" );
7788 $show.removeClass( "ui-tabs-hide" );
7789 self._trigger( "show", null, self._ui( clicked, $show[ 0 ] ) );
7792 // Hide a tab, $show is optional...
7793 var hideTab = hideFx
7794 ? function( clicked, $hide ) {
7795 $hide.animate( hideFx, hideFx.duration || "normal", function() {
7796 self.lis.removeClass( "ui-tabs-selected ui-state-active" );
7797 $hide.addClass( "ui-tabs-hide" );
7798 resetStyle( $hide, hideFx );
7799 self.element.dequeue( "tabs" );
7802 : function( clicked, $hide, $show ) {
7803 self.lis.removeClass( "ui-tabs-selected ui-state-active" );
7804 $hide.addClass( "ui-tabs-hide" );
7805 self.element.dequeue( "tabs" );
7808 // attach tab event handler, unbind to avoid duplicates from former tabifying...
7809 this.anchors.bind( o.event + ".tabs", function() {
7811 $li = $(el).closest( "li" ),
7812 $hide = self.panels.filter( ":not(.ui-tabs-hide)" ),
7813 $show = self.element.find( self._sanitizeSelector( el.hash ) );
7815 // If tab is already selected and not collapsible or tab disabled or
7816 // or is already loading or click callback returns false stop here.
7817 // Check if click handler returns false last so that it is not executed
7818 // for a disabled or loading tab!
7819 if ( ( $li.hasClass( "ui-tabs-selected" ) && !o.collapsible) ||
7820 $li.hasClass( "ui-state-disabled" ) ||
7821 $li.hasClass( "ui-state-processing" ) ||
7822 self.panels.filter( ":animated" ).length ||
7823 self._trigger( "select", null, self._ui( this, $show[ 0 ] ) ) === false ) {
7828 o.selected = self.anchors.index( this );
7832 // if tab may be closed
7833 if ( o.collapsible ) {
7834 if ( $li.hasClass( "ui-tabs-selected" ) ) {
7838 self._cookie( o.selected, o.cookie );
7841 self.element.queue( "tabs", function() {
7842 hideTab( el, $hide );
7843 }).dequeue( "tabs" );
7847 } else if ( !$hide.length ) {
7849 self._cookie( o.selected, o.cookie );
7852 self.element.queue( "tabs", function() {
7853 showTab( el, $show );
7856 // TODO make passing in node possible, see also http://dev.jqueryui.com/ticket/3171
7857 self.load( self.anchors.index( this ) );
7865 self._cookie( o.selected, o.cookie );
7869 if ( $show.length ) {
7870 if ( $hide.length ) {
7871 self.element.queue( "tabs", function() {
7872 hideTab( el, $hide );
7875 self.element.queue( "tabs", function() {
7876 showTab( el, $show );
7879 self.load( self.anchors.index( this ) );
7881 throw "jQuery UI Tabs: Mismatching fragment identifier.";
7884 // Prevent IE from keeping other link focussed when using the back button
7885 // and remove dotted border from clicked link. This is controlled via CSS
7886 // in modern browsers; blur() removes focus from address bar in Firefox
7887 // which can become a usability and annoying problem with tabs('rotate').
7888 if ( $.browser.msie ) {
7893 // disable click in any case
7894 this.anchors.bind( "click.tabs", function(){
7899 _getIndex: function( index ) {
7900 // meta-function to give users option to provide a href string instead of a numerical index.
7901 // also sanitizes numerical indexes to valid values.
7902 if ( typeof index == "string" ) {
7903 index = this.anchors.index( this.anchors.filter( "[href$=" + index + "]" ) );
7909 destroy: function() {
7910 var o = this.options;
7916 .removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" )
7917 .removeData( "tabs" );
7919 this.list.removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" );
7921 this.anchors.each(function() {
7922 var href = $.data( this, "href.tabs" );
7926 var $this = $( this ).unbind( ".tabs" );
7927 $.each( [ "href", "load", "cache" ], function( i, prefix ) {
7928 $this.removeData( prefix + ".tabs" );
7932 this.lis.unbind( ".tabs" ).add( this.panels ).each(function() {
7933 if ( $.data( this, "destroy.tabs" ) ) {
7936 $( this ).removeClass([
7943 "ui-state-disabled",
7945 "ui-widget-content",
7953 this._cookie( null, o.cookie );
7959 add: function( url, label, index ) {
7960 if ( index === undefined ) {
7961 index = this.anchors.length;
7966 $li = $( o.tabTemplate.replace( /#\{href\}/g, url ).replace( /#\{label\}/g, label ) ),
7967 id = !url.indexOf( "#" ) ? url.replace( "#", "" ) : this._tabId( $( "a", $li )[ 0 ] );
7969 $li.addClass( "ui-state-default ui-corner-top" ).data( "destroy.tabs", true );
7971 // try to find an existing element before creating a new one
7972 var $panel = self.element.find( "#" + id );
7973 if ( !$panel.length ) {
7974 $panel = $( o.panelTemplate )
7976 .data( "destroy.tabs", true );
7978 $panel.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide" );
7980 if ( index >= this.lis.length ) {
7981 $li.appendTo( this.list );
7982 $panel.appendTo( this.list[ 0 ].parentNode );
7984 $li.insertBefore( this.lis[ index ] );
7985 $panel.insertBefore( this.panels[ index ] );
7988 o.disabled = $.map( o.disabled, function( n, i ) {
7989 return n >= index ? ++n : n;
7994 if ( this.anchors.length == 1 ) {
7996 $li.addClass( "ui-tabs-selected ui-state-active" );
7997 $panel.removeClass( "ui-tabs-hide" );
7998 this.element.queue( "tabs", function() {
7999 self._trigger( "show", null, self._ui( self.anchors[ 0 ], self.panels[ 0 ] ) );
8005 this._trigger( "add", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
8009 remove: function( index ) {
8010 index = this._getIndex( index );
8011 var o = this.options,
8012 $li = this.lis.eq( index ).remove(),
8013 $panel = this.panels.eq( index ).remove();
8015 // If selected tab was removed focus tab to the right or
8016 // in case the last tab was removed the tab to the left.
8017 if ( $li.hasClass( "ui-tabs-selected" ) && this.anchors.length > 1) {
8018 this.select( index + ( index + 1 < this.anchors.length ? 1 : -1 ) );
8022 $.grep( o.disabled, function(n, i) {
8026 return n >= index ? --n : n;
8031 this._trigger( "remove", null, this._ui( $li.find( "a" )[ 0 ], $panel[ 0 ] ) );
8035 enable: function( index ) {
8036 index = this._getIndex( index );
8037 var o = this.options;
8038 if ( $.inArray( index, o.disabled ) == -1 ) {
8042 this.lis.eq( index ).removeClass( "ui-state-disabled" );
8043 o.disabled = $.grep( o.disabled, function( n, i ) {
8047 this._trigger( "enable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
8051 disable: function( index ) {
8052 index = this._getIndex( index );
8053 var self = this, o = this.options;
8054 // cannot disable already selected tab
8055 if ( index != o.selected ) {
8056 this.lis.eq( index ).addClass( "ui-state-disabled" );
8058 o.disabled.push( index );
8061 this._trigger( "disable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
8067 select: function( index ) {
8068 index = this._getIndex( index );
8069 if ( index == -1 ) {
8070 if ( this.options.collapsible && this.options.selected != -1 ) {
8071 index = this.options.selected;
8076 this.anchors.eq( index ).trigger( this.options.event + ".tabs" );
8080 load: function( index ) {
8081 index = this._getIndex( index );
8084 a = this.anchors.eq( index )[ 0 ],
8085 url = $.data( a, "load.tabs" );
8089 // not remote or from cache
8090 if ( !url || this.element.queue( "tabs" ).length !== 0 && $.data( a, "cache.tabs" ) ) {
8091 this.element.dequeue( "tabs" );
8095 // load remote from here on
8096 this.lis.eq( index ).addClass( "ui-state-processing" );
8099 var span = $( "span", a );
8100 span.data( "label.tabs", span.html() ).html( o.spinner );
8103 this.xhr = $.ajax( $.extend( {}, o.ajaxOptions, {
8105 success: function( r, s ) {
8106 self.element.find( self._sanitizeSelector( a.hash ) ).html( r );
8108 // take care of tab labels
8112 $.data( a, "cache.tabs", true );
8115 self._trigger( "load", null, self._ui( self.anchors[ index ], self.panels[ index ] ) );
8117 o.ajaxOptions.success( r, s );
8121 error: function( xhr, s, e ) {
8122 // take care of tab labels
8125 self._trigger( "load", null, self._ui( self.anchors[ index ], self.panels[ index ] ) );
8127 // Passing index avoid a race condition when this method is
8128 // called after the user has selected another tab.
8129 // Pass the anchor that initiated this request allows
8130 // loadError to manipulate the tab content panel via $(a.hash)
8131 o.ajaxOptions.error( xhr, s, index, a );
8137 // last, so that load event is fired before show...
8138 self.element.dequeue( "tabs" );
8144 // stop possibly running animations
8145 this.element.queue( [] );
8146 this.panels.stop( false, true );
8148 // "tabs" queue must not contain more than two elements,
8149 // which are the callbacks for the latest clicked tab...
8150 this.element.queue( "tabs", this.element.queue( "tabs" ).splice( -2, 2 ) );
8152 // terminate pending requests from other tabs
8158 // take care of tab labels
8163 url: function( index, url ) {
8164 this.anchors.eq( index ).removeData( "cache.tabs" ).data( "load.tabs", url );
8168 length: function() {
8169 return this.anchors.length;
8173 $.extend( $.ui.tabs, {
8184 $.extend( $.ui.tabs.prototype, {
8186 rotate: function( ms, continuing ) {
8190 var rotate = self._rotate || ( self._rotate = function( e ) {
8191 clearTimeout( self.rotation );
8192 self.rotation = setTimeout(function() {
8194 self.select( ++t < self.anchors.length ? t : 0 );
8198 e.stopPropagation();
8202 var stop = self._unrotate || ( self._unrotate = !continuing
8204 if (e.clientX) { // in case of a true click
8215 this.element.bind( "tabsshow", rotate );
8216 this.anchors.bind( o.event + ".tabs", stop );
8220 clearTimeout( self.rotation );
8221 this.element.unbind( "tabsshow", rotate );
8222 this.anchors.unbind( o.event + ".tabs", stop );
8223 delete this._rotate;
8224 delete this._unrotate;
8233 * jQuery UI Datepicker 1.8.14
8235 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
8236 * Dual licensed under the MIT or GPL Version 2 licenses.
8237 * http://jquery.org/license
8239 * http://docs.jquery.com/UI/Datepicker
8244 (function( $, undefined ) {
8246 $.extend($.ui, { datepicker: { version: "1.8.14" } });
8248 var PROP_NAME = 'datepicker';
8249 var dpuuid = new Date().getTime();
8252 /* Date picker manager.
8253 Use the singleton instance of this class, $.datepicker, to interact with the date picker.
8254 Settings for (groups of) date pickers are maintained in an instance object,
8255 allowing multiple different settings on the same page. */
8257 function Datepicker() {
8258 this.debug = false; // Change this to true to start debugging
8259 this._curInst = null; // The current instance in use
8260 this._keyEvent = false; // If the last event was a key event
8261 this._disabledInputs = []; // List of date picker inputs that have been disabled
8262 this._datepickerShowing = false; // True if the popup picker is showing , false if not
8263 this._inDialog = false; // True if showing within a "dialog", false if not
8264 this._mainDivId = 'ui-datepicker-div'; // The ID of the main datepicker division
8265 this._inlineClass = 'ui-datepicker-inline'; // The name of the inline marker class
8266 this._appendClass = 'ui-datepicker-append'; // The name of the append marker class
8267 this._triggerClass = 'ui-datepicker-trigger'; // The name of the trigger marker class
8268 this._dialogClass = 'ui-datepicker-dialog'; // The name of the dialog marker class
8269 this._disableClass = 'ui-datepicker-disabled'; // The name of the disabled covering marker class
8270 this._unselectableClass = 'ui-datepicker-unselectable'; // The name of the unselectable cell marker class
8271 this._currentClass = 'ui-datepicker-current-day'; // The name of the current day marker class
8272 this._dayOverClass = 'ui-datepicker-days-cell-over'; // The name of the day hover marker class
8273 this.regional = []; // Available regional settings, indexed by language code
8274 this.regional[''] = { // Default regional settings
8275 closeText: 'Done', // Display text for close link
8276 prevText: 'Prev', // Display text for previous month link
8277 nextText: 'Next', // Display text for next month link
8278 currentText: 'Today', // Display text for current month link
8279 monthNames: ['January','February','March','April','May','June',
8280 'July','August','September','October','November','December'], // Names of months for drop-down and formatting
8281 monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], // For formatting
8282 dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], // For formatting
8283 dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], // For formatting
8284 dayNamesMin: ['Su','Mo','Tu','We','Th','Fr','Sa'], // Column headings for days starting at Sunday
8285 weekHeader: 'Wk', // Column header for week of the year
8286 dateFormat: 'mm/dd/yy', // See format options on parseDate
8287 firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
8288 isRTL: false, // True if right-to-left language, false if left-to-right
8289 showMonthAfterYear: false, // True if the year select precedes month, false for month then year
8290 yearSuffix: '' // Additional text to append to the year in the month headers
8292 this._defaults = { // Global defaults for all the date picker instances
8293 showOn: 'focus', // 'focus' for popup on focus,
8294 // 'button' for trigger button, or 'both' for either
8295 showAnim: 'fadeIn', // Name of jQuery animation for popup
8296 showOptions: {}, // Options for enhanced animations
8297 defaultDate: null, // Used when field is blank: actual date,
8298 // +/-number for offset from today, null for today
8299 appendText: '', // Display text following the input box, e.g. showing the format
8300 buttonText: '...', // Text for trigger button
8301 buttonImage: '', // URL for trigger button image
8302 buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
8303 hideIfNoPrevNext: false, // True to hide next/previous month links
8304 // if not applicable, false to just disable them
8305 navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
8306 gotoCurrent: false, // True if today link goes back to current selection instead
8307 changeMonth: false, // True if month can be selected directly, false if only prev/next
8308 changeYear: false, // True if year can be selected directly, false if only prev/next
8309 yearRange: 'c-10:c+10', // Range of years to display in drop-down,
8310 // either relative to today's year (-nn:+nn), relative to currently displayed year
8311 // (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
8312 showOtherMonths: false, // True to show dates in other months, false to leave blank
8313 selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
8314 showWeek: false, // True to show week of the year, false to not show it
8315 calculateWeek: this.iso8601Week, // How to calculate the week of the year,
8316 // takes a Date and returns the number of the week for it
8317 shortYearCutoff: '+10', // Short year values < this are in the current century,
8318 // > this are in the previous century,
8319 // string value starting with '+' for current year + value
8320 minDate: null, // The earliest selectable date, or null for no limit
8321 maxDate: null, // The latest selectable date, or null for no limit
8322 duration: 'fast', // Duration of display/closure
8323 beforeShowDay: null, // Function that takes a date and returns an array with
8324 // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or '',
8325 // [2] = cell title (optional), e.g. $.datepicker.noWeekends
8326 beforeShow: null, // Function that takes an input field and
8327 // returns a set of custom settings for the date picker
8328 onSelect: null, // Define a callback function when a date is selected
8329 onChangeMonthYear: null, // Define a callback function when the month or year is changed
8330 onClose: null, // Define a callback function when the datepicker is closed
8331 numberOfMonths: 1, // Number of months to show at a time
8332 showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
8333 stepMonths: 1, // Number of months to step back/forward
8334 stepBigMonths: 12, // Number of months to step back/forward for the big links
8335 altField: '', // Selector for an alternate field to store selected dates into
8336 altFormat: '', // The date format to use for the alternate field
8337 constrainInput: true, // The input is constrained by the current date format
8338 showButtonPanel: false, // True to show button panel, false to not show it
8339 autoSize: false // True to size the input for the date format, false to leave as is
8341 $.extend(this._defaults, this.regional['']);
8342 this.dpDiv = bindHover($('<div id="' + this._mainDivId + '" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>'));
8345 $.extend(Datepicker.prototype, {
8346 /* Class name added to elements to indicate already configured with a date picker. */
8347 markerClassName: 'hasDatepicker',
8349 //Keep track of the maximum number of rows displayed (see #7043)
8352 /* Debug logging (if enabled). */
8355 console.log.apply('', arguments);
8358 // TODO rename to "widget" when switching to widget factory
8359 _widgetDatepicker: function() {
8363 /* Override the default settings for all instances of the date picker.
8364 @param settings object - the new settings to use as defaults (anonymous object)
8365 @return the manager object */
8366 setDefaults: function(settings) {
8367 extendRemove(this._defaults, settings || {});
8371 /* Attach the date picker to a jQuery selection.
8372 @param target element - the target input field or division or span
8373 @param settings object - the new settings to use for this date picker instance (anonymous) */
8374 _attachDatepicker: function(target, settings) {
8375 // check for settings on the control itself - in namespace 'date:'
8376 var inlineSettings = null;
8377 for (var attrName in this._defaults) {
8378 var attrValue = target.getAttribute('date:' + attrName);
8380 inlineSettings = inlineSettings || {};
8382 inlineSettings[attrName] = eval(attrValue);
8384 inlineSettings[attrName] = attrValue;
8388 var nodeName = target.nodeName.toLowerCase();
8389 var inline = (nodeName == 'div' || nodeName == 'span');
8392 target.id = 'dp' + this.uuid;
8394 var inst = this._newInst($(target), inline);
8395 inst.settings = $.extend({}, settings || {}, inlineSettings || {});
8396 if (nodeName == 'input') {
8397 this._connectDatepicker(target, inst);
8398 } else if (inline) {
8399 this._inlineDatepicker(target, inst);
8403 /* Create a new instance object. */
8404 _newInst: function(target, inline) {
8405 var id = target[0].id.replace(/([^A-Za-z0-9_-])/g, '\\\\$1'); // escape jQuery meta chars
8406 return {id: id, input: target, // associated target
8407 selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
8408 drawMonth: 0, drawYear: 0, // month being drawn
8409 inline: inline, // is datepicker inline or not
8410 dpDiv: (!inline ? this.dpDiv : // presentation div
8411 bindHover($('<div class="' + this._inlineClass + ' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>')))};
8414 /* Attach the date picker to an input field. */
8415 _connectDatepicker: function(target, inst) {
8416 var input = $(target);
8417 inst.append = $([]);
8418 inst.trigger = $([]);
8419 if (input.hasClass(this.markerClassName))
8421 this._attachments(input, inst);
8422 input.addClass(this.markerClassName).keydown(this._doKeyDown).
8423 keypress(this._doKeyPress).keyup(this._doKeyUp).
8424 bind("setData.datepicker", function(event, key, value) {
8425 inst.settings[key] = value;
8426 }).bind("getData.datepicker", function(event, key) {
8427 return this._get(inst, key);
8429 this._autoSize(inst);
8430 $.data(target, PROP_NAME, inst);
8433 /* Make attachments based on settings. */
8434 _attachments: function(input, inst) {
8435 var appendText = this._get(inst, 'appendText');
8436 var isRTL = this._get(inst, 'isRTL');
8438 inst.append.remove();
8440 inst.append = $('<span class="' + this._appendClass + '">' + appendText + '</span>');
8441 input[isRTL ? 'before' : 'after'](inst.append);
8443 input.unbind('focus', this._showDatepicker);
8445 inst.trigger.remove();
8446 var showOn = this._get(inst, 'showOn');
8447 if (showOn == 'focus' || showOn == 'both') // pop-up date picker when in the marked field
8448 input.focus(this._showDatepicker);
8449 if (showOn == 'button' || showOn == 'both') { // pop-up date picker when button clicked
8450 var buttonText = this._get(inst, 'buttonText');
8451 var buttonImage = this._get(inst, 'buttonImage');
8452 inst.trigger = $(this._get(inst, 'buttonImageOnly') ?
8453 $('<img/>').addClass(this._triggerClass).
8454 attr({ src: buttonImage, alt: buttonText, title: buttonText }) :
8455 $('<button type="button"></button>').addClass(this._triggerClass).
8456 html(buttonImage == '' ? buttonText : $('<img/>').attr(
8457 { src:buttonImage, alt:buttonText, title:buttonText })));
8458 input[isRTL ? 'before' : 'after'](inst.trigger);
8459 inst.trigger.click(function() {
8460 if ($.datepicker._datepickerShowing && $.datepicker._lastInput == input[0])
8461 $.datepicker._hideDatepicker();
8463 $.datepicker._showDatepicker(input[0]);
8469 /* Apply the maximum length for the date format. */
8470 _autoSize: function(inst) {
8471 if (this._get(inst, 'autoSize') && !inst.inline) {
8472 var date = new Date(2009, 12 - 1, 20); // Ensure double digits
8473 var dateFormat = this._get(inst, 'dateFormat');
8474 if (dateFormat.match(/[DM]/)) {
8475 var findMax = function(names) {
8478 for (var i = 0; i < names.length; i++) {
8479 if (names[i].length > max) {
8480 max = names[i].length;
8486 date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ?
8487 'monthNames' : 'monthNamesShort'))));
8488 date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ?
8489 'dayNames' : 'dayNamesShort'))) + 20 - date.getDay());
8491 inst.input.attr('size', this._formatDate(inst, date).length);
8495 /* Attach an inline date picker to a div. */
8496 _inlineDatepicker: function(target, inst) {
8497 var divSpan = $(target);
8498 if (divSpan.hasClass(this.markerClassName))
8500 divSpan.addClass(this.markerClassName).append(inst.dpDiv).
8501 bind("setData.datepicker", function(event, key, value){
8502 inst.settings[key] = value;
8503 }).bind("getData.datepicker", function(event, key){
8504 return this._get(inst, key);
8506 $.data(target, PROP_NAME, inst);
8507 this._setDate(inst, this._getDefaultDate(inst), true);
8508 this._updateDatepicker(inst);
8509 this._updateAlternate(inst);
8513 /* Pop-up the date picker in a "dialog" box.
8514 @param input element - ignored
8515 @param date string or Date - the initial date to display
8516 @param onSelect function - the function to call when a date is selected
8517 @param settings object - update the dialog date picker instance's settings (anonymous object)
8518 @param pos int[2] - coordinates for the dialog's position within the screen or
8519 event - with x/y coordinates or
8520 leave empty for default (screen centre)
8521 @return the manager object */
8522 _dialogDatepicker: function(input, date, onSelect, settings, pos) {
8523 var inst = this._dialogInst; // internal instance
8526 var id = 'dp' + this.uuid;
8527 this._dialogInput = $('<input type="text" id="' + id +
8528 '" style="position: absolute; top: -100px; width: 0px; z-index: -10;"/>');
8529 this._dialogInput.keydown(this._doKeyDown);
8530 $('body').append(this._dialogInput);
8531 inst = this._dialogInst = this._newInst(this._dialogInput, false);
8533 $.data(this._dialogInput[0], PROP_NAME, inst);
8535 extendRemove(inst.settings, settings || {});
8536 date = (date && date.constructor == Date ? this._formatDate(inst, date) : date);
8537 this._dialogInput.val(date);
8539 this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);
8541 var browserWidth = document.documentElement.clientWidth;
8542 var browserHeight = document.documentElement.clientHeight;
8543 var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
8544 var scrollY = document.documentElement.scrollTop || document.body.scrollTop;
8545 this._pos = // should use actual width/height below
8546 [(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY];
8549 // move input on screen for focus, but hidden behind dialog
8550 this._dialogInput.css('left', (this._pos[0] + 20) + 'px').css('top', this._pos[1] + 'px');
8551 inst.settings.onSelect = onSelect;
8552 this._inDialog = true;
8553 this.dpDiv.addClass(this._dialogClass);
8554 this._showDatepicker(this._dialogInput[0]);
8556 $.blockUI(this.dpDiv);
8557 $.data(this._dialogInput[0], PROP_NAME, inst);
8561 /* Detach a datepicker from its control.
8562 @param target element - the target input field or division or span */
8563 _destroyDatepicker: function(target) {
8564 var $target = $(target);
8565 var inst = $.data(target, PROP_NAME);
8566 if (!$target.hasClass(this.markerClassName)) {
8569 var nodeName = target.nodeName.toLowerCase();
8570 $.removeData(target, PROP_NAME);
8571 if (nodeName == 'input') {
8572 inst.append.remove();
8573 inst.trigger.remove();
8574 $target.removeClass(this.markerClassName).
8575 unbind('focus', this._showDatepicker).
8576 unbind('keydown', this._doKeyDown).
8577 unbind('keypress', this._doKeyPress).
8578 unbind('keyup', this._doKeyUp);
8579 } else if (nodeName == 'div' || nodeName == 'span')
8580 $target.removeClass(this.markerClassName).empty();
8583 /* Enable the date picker to a jQuery selection.
8584 @param target element - the target input field or division or span */
8585 _enableDatepicker: function(target) {
8586 var $target = $(target);
8587 var inst = $.data(target, PROP_NAME);
8588 if (!$target.hasClass(this.markerClassName)) {
8591 var nodeName = target.nodeName.toLowerCase();
8592 if (nodeName == 'input') {
8593 target.disabled = false;
8594 inst.trigger.filter('button').
8595 each(function() { this.disabled = false; }).end().
8596 filter('img').css({opacity: '1.0', cursor: ''});
8598 else if (nodeName == 'div' || nodeName == 'span') {
8599 var inline = $target.children('.' + this._inlineClass);
8600 inline.children().removeClass('ui-state-disabled');
8601 inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
8602 removeAttr("disabled");
8604 this._disabledInputs = $.map(this._disabledInputs,
8605 function(value) { return (value == target ? null : value); }); // delete entry
8608 /* Disable the date picker to a jQuery selection.
8609 @param target element - the target input field or division or span */
8610 _disableDatepicker: function(target) {
8611 var $target = $(target);
8612 var inst = $.data(target, PROP_NAME);
8613 if (!$target.hasClass(this.markerClassName)) {
8616 var nodeName = target.nodeName.toLowerCase();
8617 if (nodeName == 'input') {
8618 target.disabled = true;
8619 inst.trigger.filter('button').
8620 each(function() { this.disabled = true; }).end().
8621 filter('img').css({opacity: '0.5', cursor: 'default'});
8623 else if (nodeName == 'div' || nodeName == 'span') {
8624 var inline = $target.children('.' + this._inlineClass);
8625 inline.children().addClass('ui-state-disabled');
8626 inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
8627 attr("disabled", "disabled");
8629 this._disabledInputs = $.map(this._disabledInputs,
8630 function(value) { return (value == target ? null : value); }); // delete entry
8631 this._disabledInputs[this._disabledInputs.length] = target;
8634 /* Is the first field in a jQuery collection disabled as a datepicker?
8635 @param target element - the target input field or division or span
8636 @return boolean - true if disabled, false if enabled */
8637 _isDisabledDatepicker: function(target) {
8641 for (var i = 0; i < this._disabledInputs.length; i++) {
8642 if (this._disabledInputs[i] == target)
8648 /* Retrieve the instance data for the target control.
8649 @param target element - the target input field or division or span
8650 @return object - the associated instance data
8651 @throws error if a jQuery problem getting data */
8652 _getInst: function(target) {
8654 return $.data(target, PROP_NAME);
8657 throw 'Missing instance data for this datepicker';
8661 /* Update or retrieve the settings for a date picker attached to an input field or division.
8662 @param target element - the target input field or division or span
8663 @param name object - the new settings to update or
8664 string - the name of the setting to change or retrieve,
8665 when retrieving also 'all' for all instance settings or
8666 'defaults' for all global defaults
8667 @param value any - the new value for the setting
8668 (omit if above is an object or to retrieve a value) */
8669 _optionDatepicker: function(target, name, value) {
8670 var inst = this._getInst(target);
8671 if (arguments.length == 2 && typeof name == 'string') {
8672 return (name == 'defaults' ? $.extend({}, $.datepicker._defaults) :
8673 (inst ? (name == 'all' ? $.extend({}, inst.settings) :
8674 this._get(inst, name)) : null));
8676 var settings = name || {};
8677 if (typeof name == 'string') {
8679 settings[name] = value;
8682 if (this._curInst == inst) {
8683 this._hideDatepicker();
8685 var date = this._getDateDatepicker(target, true);
8686 var minDate = this._getMinMaxDate(inst, 'min');
8687 var maxDate = this._getMinMaxDate(inst, 'max');
8688 extendRemove(inst.settings, settings);
8689 // reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided
8690 if (minDate !== null && settings['dateFormat'] !== undefined && settings['minDate'] === undefined)
8691 inst.settings.minDate = this._formatDate(inst, minDate);
8692 if (maxDate !== null && settings['dateFormat'] !== undefined && settings['maxDate'] === undefined)
8693 inst.settings.maxDate = this._formatDate(inst, maxDate);
8694 this._attachments($(target), inst);
8695 this._autoSize(inst);
8696 this._setDate(inst, date);
8697 this._updateAlternate(inst);
8698 this._updateDatepicker(inst);
8702 // change method deprecated
8703 _changeDatepicker: function(target, name, value) {
8704 this._optionDatepicker(target, name, value);
8707 /* Redraw the date picker attached to an input field or division.
8708 @param target element - the target input field or division or span */
8709 _refreshDatepicker: function(target) {
8710 var inst = this._getInst(target);
8712 this._updateDatepicker(inst);
8716 /* Set the dates for a jQuery selection.
8717 @param target element - the target input field or division or span
8718 @param date Date - the new date */
8719 _setDateDatepicker: function(target, date) {
8720 var inst = this._getInst(target);
8722 this._setDate(inst, date);
8723 this._updateDatepicker(inst);
8724 this._updateAlternate(inst);
8728 /* Get the date(s) for the first entry in a jQuery selection.
8729 @param target element - the target input field or division or span
8730 @param noDefault boolean - true if no default date is to be used
8731 @return Date - the current date */
8732 _getDateDatepicker: function(target, noDefault) {
8733 var inst = this._getInst(target);
8734 if (inst && !inst.inline)
8735 this._setDateFromField(inst, noDefault);
8736 return (inst ? this._getDate(inst) : null);
8739 /* Handle keystrokes. */
8740 _doKeyDown: function(event) {
8741 var inst = $.datepicker._getInst(event.target);
8743 var isRTL = inst.dpDiv.is('.ui-datepicker-rtl');
8744 inst._keyEvent = true;
8745 if ($.datepicker._datepickerShowing)
8746 switch (event.keyCode) {
8747 case 9: $.datepicker._hideDatepicker();
8749 break; // hide on tab out
8750 case 13: var sel = $('td.' + $.datepicker._dayOverClass + ':not(.' +
8751 $.datepicker._currentClass + ')', inst.dpDiv);
8753 $.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);
8755 $.datepicker._hideDatepicker();
8756 return false; // don't submit the form
8757 break; // select the value on enter
8758 case 27: $.datepicker._hideDatepicker();
8759 break; // hide on escape
8760 case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
8761 -$.datepicker._get(inst, 'stepBigMonths') :
8762 -$.datepicker._get(inst, 'stepMonths')), 'M');
8763 break; // previous month/year on page up/+ ctrl
8764 case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
8765 +$.datepicker._get(inst, 'stepBigMonths') :
8766 +$.datepicker._get(inst, 'stepMonths')), 'M');
8767 break; // next month/year on page down/+ ctrl
8768 case 35: if (event.ctrlKey || event.metaKey) $.datepicker._clearDate(event.target);
8769 handled = event.ctrlKey || event.metaKey;
8770 break; // clear on ctrl or command +end
8771 case 36: if (event.ctrlKey || event.metaKey) $.datepicker._gotoToday(event.target);
8772 handled = event.ctrlKey || event.metaKey;
8773 break; // current on ctrl or command +home
8774 case 37: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), 'D');
8775 handled = event.ctrlKey || event.metaKey;
8776 // -1 day on ctrl or command +left
8777 if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
8778 -$.datepicker._get(inst, 'stepBigMonths') :
8779 -$.datepicker._get(inst, 'stepMonths')), 'M');
8780 // next month/year on alt +left on Mac
8782 case 38: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, -7, 'D');
8783 handled = event.ctrlKey || event.metaKey;
8784 break; // -1 week on ctrl or command +up
8785 case 39: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), 'D');
8786 handled = event.ctrlKey || event.metaKey;
8787 // +1 day on ctrl or command +right
8788 if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
8789 +$.datepicker._get(inst, 'stepBigMonths') :
8790 +$.datepicker._get(inst, 'stepMonths')), 'M');
8791 // next month/year on alt +right
8793 case 40: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, +7, 'D');
8794 handled = event.ctrlKey || event.metaKey;
8795 break; // +1 week on ctrl or command +down
8796 default: handled = false;
8798 else if (event.keyCode == 36 && event.ctrlKey) // display the date picker on ctrl+home
8799 $.datepicker._showDatepicker(this);
8804 event.preventDefault();
8805 event.stopPropagation();
8809 /* Filter entered characters - based on date format. */
8810 _doKeyPress: function(event) {
8811 var inst = $.datepicker._getInst(event.target);
8812 if ($.datepicker._get(inst, 'constrainInput')) {
8813 var chars = $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat'));
8814 var chr = String.fromCharCode(event.charCode == undefined ? event.keyCode : event.charCode);
8815 return event.ctrlKey || event.metaKey || (chr < ' ' || !chars || chars.indexOf(chr) > -1);
8819 /* Synchronise manual entry and field/alternate field. */
8820 _doKeyUp: function(event) {
8821 var inst = $.datepicker._getInst(event.target);
8822 if (inst.input.val() != inst.lastVal) {
8824 var date = $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
8825 (inst.input ? inst.input.val() : null),
8826 $.datepicker._getFormatConfig(inst));
8827 if (date) { // only if valid
8828 $.datepicker._setDateFromField(inst);
8829 $.datepicker._updateAlternate(inst);
8830 $.datepicker._updateDatepicker(inst);
8834 $.datepicker.log(event);
8840 /* Pop-up the date picker for a given input field.
8841 @param input element - the input field attached to the date picker or
8842 event - if triggered by focus */
8843 _showDatepicker: function(input) {
8844 input = input.target || input;
8845 if (input.nodeName.toLowerCase() != 'input') // find from button/image trigger
8846 input = $('input', input.parentNode)[0];
8847 if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput == input) // already here
8849 var inst = $.datepicker._getInst(input);
8850 if ($.datepicker._curInst && $.datepicker._curInst != inst) {
8851 if ( $.datepicker._datepickerShowing ) {
8852 $.datepicker._triggerOnClose($.datepicker._curInst);
8854 $.datepicker._curInst.dpDiv.stop(true, true);
8856 var beforeShow = $.datepicker._get(inst, 'beforeShow');
8857 extendRemove(inst.settings, (beforeShow ? beforeShow.apply(input, [input, inst]) : {}));
8858 inst.lastVal = null;
8859 $.datepicker._lastInput = input;
8860 $.datepicker._setDateFromField(inst);
8861 if ($.datepicker._inDialog) // hide cursor
8863 if (!$.datepicker._pos) { // position below input
8864 $.datepicker._pos = $.datepicker._findPos(input);
8865 $.datepicker._pos[1] += input.offsetHeight; // add the height
8867 var isFixed = false;
8868 $(input).parents().each(function() {
8869 isFixed |= $(this).css('position') == 'fixed';
8872 if (isFixed && $.browser.opera) { // correction for Opera when fixed and scrolled
8873 $.datepicker._pos[0] -= document.documentElement.scrollLeft;
8874 $.datepicker._pos[1] -= document.documentElement.scrollTop;
8876 var offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]};
8877 $.datepicker._pos = null;
8878 //to avoid flashes on Firefox
8880 // determine sizing offscreen
8881 inst.dpDiv.css({position: 'absolute', display: 'block', top: '-1000px'});
8882 $.datepicker._updateDatepicker(inst);
8883 // fix width for dynamic number of date pickers
8884 // and adjust position before showing
8885 offset = $.datepicker._checkOffset(inst, offset, isFixed);
8886 inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ?
8887 'static' : (isFixed ? 'fixed' : 'absolute')), display: 'none',
8888 left: offset.left + 'px', top: offset.top + 'px'});
8890 var showAnim = $.datepicker._get(inst, 'showAnim');
8891 var duration = $.datepicker._get(inst, 'duration');
8892 var postProcess = function() {
8893 var cover = inst.dpDiv.find('iframe.ui-datepicker-cover'); // IE6- only
8894 if( !! cover.length ){
8895 var borders = $.datepicker._getBorders(inst.dpDiv);
8896 cover.css({left: -borders[0], top: -borders[1],
8897 width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()});
8900 inst.dpDiv.zIndex($(input).zIndex()+1);
8901 $.datepicker._datepickerShowing = true;
8902 if ($.effects && $.effects[showAnim])
8903 inst.dpDiv.show(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
8905 inst.dpDiv[showAnim || 'show']((showAnim ? duration : null), postProcess);
8906 if (!showAnim || !duration)
8908 if (inst.input.is(':visible') && !inst.input.is(':disabled'))
8910 $.datepicker._curInst = inst;
8914 /* Generate the date picker content. */
8915 _updateDatepicker: function(inst) {
8917 self.maxRows = 4; //Reset the max number of rows being displayed (see #7043)
8918 var borders = $.datepicker._getBorders(inst.dpDiv);
8919 instActive = inst; // for delegate hover events
8920 inst.dpDiv.empty().append(this._generateHTML(inst));
8921 var cover = inst.dpDiv.find('iframe.ui-datepicker-cover'); // IE6- only
8922 if( !!cover.length ){ //avoid call to outerXXXX() when not in IE6
8923 cover.css({left: -borders[0], top: -borders[1], width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()})
8925 inst.dpDiv.find('.' + this._dayOverClass + ' a').mouseover();
8926 var numMonths = this._getNumberOfMonths(inst);
8927 var cols = numMonths[1];
8929 inst.dpDiv.removeClass('ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4').width('');
8931 inst.dpDiv.addClass('ui-datepicker-multi-' + cols).css('width', (width * cols) + 'em');
8932 inst.dpDiv[(numMonths[0] != 1 || numMonths[1] != 1 ? 'add' : 'remove') +
8933 'Class']('ui-datepicker-multi');
8934 inst.dpDiv[(this._get(inst, 'isRTL') ? 'add' : 'remove') +
8935 'Class']('ui-datepicker-rtl');
8936 if (inst == $.datepicker._curInst && $.datepicker._datepickerShowing && inst.input &&
8937 // #6694 - don't focus the input if it's already focused
8938 // this breaks the change event in IE
8939 inst.input.is(':visible') && !inst.input.is(':disabled') && inst.input[0] != document.activeElement)
8941 // deffered render of the years select (to avoid flashes on Firefox)
8942 if( inst.yearshtml ){
8943 var origyearshtml = inst.yearshtml;
8944 setTimeout(function(){
8945 //assure that inst.yearshtml didn't change.
8946 if( origyearshtml === inst.yearshtml && inst.yearshtml ){
8947 inst.dpDiv.find('select.ui-datepicker-year:first').replaceWith(inst.yearshtml);
8949 origyearshtml = inst.yearshtml = null;
8954 /* Retrieve the size of left and top borders for an element.
8955 @param elem (jQuery object) the element of interest
8956 @return (number[2]) the left and top borders */
8957 _getBorders: function(elem) {
8958 var convert = function(value) {
8959 return {thin: 1, medium: 2, thick: 3}[value] || value;
8961 return [parseFloat(convert(elem.css('border-left-width'))),
8962 parseFloat(convert(elem.css('border-top-width')))];
8965 /* Check positioning to remain on screen. */
8966 _checkOffset: function(inst, offset, isFixed) {
8967 var dpWidth = inst.dpDiv.outerWidth();
8968 var dpHeight = inst.dpDiv.outerHeight();
8969 var inputWidth = inst.input ? inst.input.outerWidth() : 0;
8970 var inputHeight = inst.input ? inst.input.outerHeight() : 0;
8971 var viewWidth = document.documentElement.clientWidth + $(document).scrollLeft();
8972 var viewHeight = document.documentElement.clientHeight + $(document).scrollTop();
8974 offset.left -= (this._get(inst, 'isRTL') ? (dpWidth - inputWidth) : 0);
8975 offset.left -= (isFixed && offset.left == inst.input.offset().left) ? $(document).scrollLeft() : 0;
8976 offset.top -= (isFixed && offset.top == (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;
8978 // now check if datepicker is showing outside window viewport - move to a better place if so.
8979 offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?
8980 Math.abs(offset.left + dpWidth - viewWidth) : 0);
8981 offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?
8982 Math.abs(dpHeight + inputHeight) : 0);
8987 /* Find an object's position on the screen. */
8988 _findPos: function(obj) {
8989 var inst = this._getInst(obj);
8990 var isRTL = this._get(inst, 'isRTL');
8991 while (obj && (obj.type == 'hidden' || obj.nodeType != 1 || $.expr.filters.hidden(obj))) {
8992 obj = obj[isRTL ? 'previousSibling' : 'nextSibling'];
8994 var position = $(obj).offset();
8995 return [position.left, position.top];
8998 /* Trigger custom callback of onClose. */
8999 _triggerOnClose: function(inst) {
9000 var onClose = this._get(inst, 'onClose');
9002 onClose.apply((inst.input ? inst.input[0] : null),
9003 [(inst.input ? inst.input.val() : ''), inst]);
9006 /* Hide the date picker from view.
9007 @param input element - the input field attached to the date picker */
9008 _hideDatepicker: function(input) {
9009 var inst = this._curInst;
9010 if (!inst || (input && inst != $.data(input, PROP_NAME)))
9012 if (this._datepickerShowing) {
9013 var showAnim = this._get(inst, 'showAnim');
9014 var duration = this._get(inst, 'duration');
9015 var postProcess = function() {
9016 $.datepicker._tidyDialog(inst);
9017 this._curInst = null;
9019 if ($.effects && $.effects[showAnim])
9020 inst.dpDiv.hide(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
9022 inst.dpDiv[(showAnim == 'slideDown' ? 'slideUp' :
9023 (showAnim == 'fadeIn' ? 'fadeOut' : 'hide'))]((showAnim ? duration : null), postProcess);
9026 $.datepicker._triggerOnClose(inst);
9027 this._datepickerShowing = false;
9028 this._lastInput = null;
9029 if (this._inDialog) {
9030 this._dialogInput.css({ position: 'absolute', left: '0', top: '-100px' });
9033 $('body').append(this.dpDiv);
9036 this._inDialog = false;
9040 /* Tidy up after a dialog display. */
9041 _tidyDialog: function(inst) {
9042 inst.dpDiv.removeClass(this._dialogClass).unbind('.ui-datepicker-calendar');
9045 /* Close date picker if clicked elsewhere. */
9046 _checkExternalClick: function(event) {
9047 if (!$.datepicker._curInst)
9049 var $target = $(event.target);
9050 if ($target[0].id != $.datepicker._mainDivId &&
9051 $target.parents('#' + $.datepicker._mainDivId).length == 0 &&
9052 !$target.hasClass($.datepicker.markerClassName) &&
9053 !$target.hasClass($.datepicker._triggerClass) &&
9054 $.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI))
9055 $.datepicker._hideDatepicker();
9058 /* Adjust one of the date sub-fields. */
9059 _adjustDate: function(id, offset, period) {
9061 var inst = this._getInst(target[0]);
9062 if (this._isDisabledDatepicker(target[0])) {
9065 this._adjustInstDate(inst, offset +
9066 (period == 'M' ? this._get(inst, 'showCurrentAtPos') : 0), // undo positioning
9068 this._updateDatepicker(inst);
9071 /* Action for current link. */
9072 _gotoToday: function(id) {
9074 var inst = this._getInst(target[0]);
9075 if (this._get(inst, 'gotoCurrent') && inst.currentDay) {
9076 inst.selectedDay = inst.currentDay;
9077 inst.drawMonth = inst.selectedMonth = inst.currentMonth;
9078 inst.drawYear = inst.selectedYear = inst.currentYear;
9081 var date = new Date();
9082 inst.selectedDay = date.getDate();
9083 inst.drawMonth = inst.selectedMonth = date.getMonth();
9084 inst.drawYear = inst.selectedYear = date.getFullYear();
9086 this._notifyChange(inst);
9087 this._adjustDate(target);
9090 /* Action for selecting a new month/year. */
9091 _selectMonthYear: function(id, select, period) {
9093 var inst = this._getInst(target[0]);
9094 inst._selectingMonthYear = false;
9095 inst['selected' + (period == 'M' ? 'Month' : 'Year')] =
9096 inst['draw' + (period == 'M' ? 'Month' : 'Year')] =
9097 parseInt(select.options[select.selectedIndex].value,10);
9098 this._notifyChange(inst);
9099 this._adjustDate(target);
9102 /* Restore input focus after not changing month/year. */
9103 _clickMonthYear: function(id) {
9105 var inst = this._getInst(target[0]);
9106 if (inst.input && inst._selectingMonthYear) {
9107 setTimeout(function() {
9111 inst._selectingMonthYear = !inst._selectingMonthYear;
9114 /* Action for selecting a day. */
9115 _selectDay: function(id, month, year, td) {
9117 if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) {
9120 var inst = this._getInst(target[0]);
9121 inst.selectedDay = inst.currentDay = $('a', td).html();
9122 inst.selectedMonth = inst.currentMonth = month;
9123 inst.selectedYear = inst.currentYear = year;
9124 this._selectDate(id, this._formatDate(inst,
9125 inst.currentDay, inst.currentMonth, inst.currentYear));
9128 /* Erase the input field and hide the date picker. */
9129 _clearDate: function(id) {
9131 var inst = this._getInst(target[0]);
9132 this._selectDate(target, '');
9135 /* Update the input field with the selected date. */
9136 _selectDate: function(id, dateStr) {
9138 var inst = this._getInst(target[0]);
9139 dateStr = (dateStr != null ? dateStr : this._formatDate(inst));
9141 inst.input.val(dateStr);
9142 this._updateAlternate(inst);
9143 var onSelect = this._get(inst, 'onSelect');
9145 onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); // trigger custom callback
9146 else if (inst.input)
9147 inst.input.trigger('change'); // fire the change event
9149 this._updateDatepicker(inst);
9151 this._hideDatepicker();
9152 this._lastInput = inst.input[0];
9153 if (typeof(inst.input[0]) != 'object')
9154 inst.input.focus(); // restore focus
9155 this._lastInput = null;
9159 /* Update any alternate field to synchronise with the main field. */
9160 _updateAlternate: function(inst) {
9161 var altField = this._get(inst, 'altField');
9162 if (altField) { // update alternate field too
9163 var altFormat = this._get(inst, 'altFormat') || this._get(inst, 'dateFormat');
9164 var date = this._getDate(inst);
9165 var dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst));
9166 $(altField).each(function() { $(this).val(dateStr); });
9170 /* Set as beforeShowDay function to prevent selection of weekends.
9171 @param date Date - the date to customise
9172 @return [boolean, string] - is this date selectable?, what is its CSS class? */
9173 noWeekends: function(date) {
9174 var day = date.getDay();
9175 return [(day > 0 && day < 6), ''];
9178 /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
9179 @param date Date - the date to get the week for
9180 @return number - the number of the week within the year that contains this date */
9181 iso8601Week: function(date) {
9182 var checkDate = new Date(date.getTime());
9183 // Find Thursday of this week starting on Monday
9184 checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7));
9185 var time = checkDate.getTime();
9186 checkDate.setMonth(0); // Compare with Jan 1
9187 checkDate.setDate(1);
9188 return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
9191 /* Parse a string value into a date object.
9192 See formatDate below for the possible formats.
9194 @param format string - the expected format of the date
9195 @param value string - the date in the above format
9196 @param settings Object - attributes include:
9197 shortYearCutoff number - the cutoff year for determining the century (optional)
9198 dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
9199 dayNames string[7] - names of the days from Sunday (optional)
9200 monthNamesShort string[12] - abbreviated names of the months (optional)
9201 monthNames string[12] - names of the months (optional)
9202 @return Date - the extracted date value or null if value is blank */
9203 parseDate: function (format, value, settings) {
9204 if (format == null || value == null)
9205 throw 'Invalid arguments';
9206 value = (typeof value == 'object' ? value.toString() : value + '');
9209 var shortYearCutoff = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff;
9210 shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff :
9211 new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
9212 var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
9213 var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
9214 var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
9215 var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
9220 var literal = false;
9221 // Check whether a format character is doubled
9222 var lookAhead = function(match) {
9223 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
9228 // Extract a number from the string value
9229 var getNumber = function(match) {
9230 var isDoubled = lookAhead(match);
9231 var size = (match == '@' ? 14 : (match == '!' ? 20 :
9232 (match == 'y' && isDoubled ? 4 : (match == 'o' ? 3 : 2))));
9233 var digits = new RegExp('^\\d{1,' + size + '}');
9234 var num = value.substring(iValue).match(digits);
9236 throw 'Missing number at position ' + iValue;
9237 iValue += num[0].length;
9238 return parseInt(num[0], 10);
9240 // Extract a name from the string value and convert to an index
9241 var getName = function(match, shortNames, longNames) {
9242 var names = $.map(lookAhead(match) ? longNames : shortNames, function (v, k) {
9244 }).sort(function (a, b) {
9245 return -(a[1].length - b[1].length);
9248 $.each(names, function (i, pair) {
9250 if (value.substr(iValue, name.length).toLowerCase() == name.toLowerCase()) {
9252 iValue += name.length;
9259 throw 'Unknown name at position ' + iValue;
9261 // Confirm that a literal character matches the string value
9262 var checkLiteral = function() {
9263 if (value.charAt(iValue) != format.charAt(iFormat))
9264 throw 'Unexpected literal at position ' + iValue;
9268 for (var iFormat = 0; iFormat < format.length; iFormat++) {
9270 if (format.charAt(iFormat) == "'" && !lookAhead("'"))
9275 switch (format.charAt(iFormat)) {
9277 day = getNumber('d');
9280 getName('D', dayNamesShort, dayNames);
9283 doy = getNumber('o');
9286 month = getNumber('m');
9289 month = getName('M', monthNamesShort, monthNames);
9292 year = getNumber('y');
9295 var date = new Date(getNumber('@'));
9296 year = date.getFullYear();
9297 month = date.getMonth() + 1;
9298 day = date.getDate();
9301 var date = new Date((getNumber('!') - this._ticksTo1970) / 10000);
9302 year = date.getFullYear();
9303 month = date.getMonth() + 1;
9304 day = date.getDate();
9316 if (iValue < value.length){
9317 throw "Extra/unparsed characters found in date: " + value.substring(iValue);
9320 year = new Date().getFullYear();
9321 else if (year < 100)
9322 year += new Date().getFullYear() - new Date().getFullYear() % 100 +
9323 (year <= shortYearCutoff ? 0 : -100);
9328 var dim = this._getDaysInMonth(year, month - 1);
9335 var date = this._daylightSavingAdjust(new Date(year, month - 1, day));
9336 if (date.getFullYear() != year || date.getMonth() + 1 != month || date.getDate() != day)
9337 throw 'Invalid date'; // E.g. 31/02/00
9341 /* Standard date formats. */
9342 ATOM: 'yy-mm-dd', // RFC 3339 (ISO 8601)
9343 COOKIE: 'D, dd M yy',
9344 ISO_8601: 'yy-mm-dd',
9345 RFC_822: 'D, d M y',
9346 RFC_850: 'DD, dd-M-y',
9347 RFC_1036: 'D, d M y',
9348 RFC_1123: 'D, d M yy',
9349 RFC_2822: 'D, d M yy',
9350 RSS: 'D, d M y', // RFC 822
9353 W3C: 'yy-mm-dd', // ISO 8601
9355 _ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) +
9356 Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000),
9358 /* Format a date object into a string value.
9359 The format can be combinations of the following:
9360 d - day of month (no leading zero)
9361 dd - day of month (two digit)
9362 o - day of year (no leading zeros)
9363 oo - day of year (three digit)
9366 m - month of year (no leading zero)
9367 mm - month of year (two digit)
9368 M - month name short
9369 MM - month name long
9370 y - year (two digit)
9371 yy - year (four digit)
9372 @ - Unix timestamp (ms since 01/01/1970)
9373 ! - Windows ticks (100ns since 01/01/0001)
9374 '...' - literal text
9377 @param format string - the desired format of the date
9378 @param date Date - the date value to format
9379 @param settings Object - attributes include:
9380 dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
9381 dayNames string[7] - names of the days from Sunday (optional)
9382 monthNamesShort string[12] - abbreviated names of the months (optional)
9383 monthNames string[12] - names of the months (optional)
9384 @return string - the date in the above format */
9385 formatDate: function (format, date, settings) {
9388 var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
9389 var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
9390 var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
9391 var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
9392 // Check whether a format character is doubled
9393 var lookAhead = function(match) {
9394 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
9399 // Format a number, with leading zero if necessary
9400 var formatNumber = function(match, value, len) {
9401 var num = '' + value;
9402 if (lookAhead(match))
9403 while (num.length < len)
9407 // Format a name, short or long as requested
9408 var formatName = function(match, value, shortNames, longNames) {
9409 return (lookAhead(match) ? longNames[value] : shortNames[value]);
9412 var literal = false;
9414 for (var iFormat = 0; iFormat < format.length; iFormat++) {
9416 if (format.charAt(iFormat) == "'" && !lookAhead("'"))
9419 output += format.charAt(iFormat);
9421 switch (format.charAt(iFormat)) {
9423 output += formatNumber('d', date.getDate(), 2);
9426 output += formatName('D', date.getDay(), dayNamesShort, dayNames);
9429 output += formatNumber('o',
9430 Math.round((new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000), 3);
9433 output += formatNumber('m', date.getMonth() + 1, 2);
9436 output += formatName('M', date.getMonth(), monthNamesShort, monthNames);
9439 output += (lookAhead('y') ? date.getFullYear() :
9440 (date.getYear() % 100 < 10 ? '0' : '') + date.getYear() % 100);
9443 output += date.getTime();
9446 output += date.getTime() * 10000 + this._ticksTo1970;
9455 output += format.charAt(iFormat);
9461 /* Extract all possible characters from the date format. */
9462 _possibleChars: function (format) {
9464 var literal = false;
9465 // Check whether a format character is doubled
9466 var lookAhead = function(match) {
9467 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
9472 for (var iFormat = 0; iFormat < format.length; iFormat++)
9474 if (format.charAt(iFormat) == "'" && !lookAhead("'"))
9477 chars += format.charAt(iFormat);
9479 switch (format.charAt(iFormat)) {
9480 case 'd': case 'm': case 'y': case '@':
9481 chars += '0123456789';
9484 return null; // Accept anything
9492 chars += format.charAt(iFormat);
9497 /* Get a setting value, defaulting if necessary. */
9498 _get: function(inst, name) {
9499 return inst.settings[name] !== undefined ?
9500 inst.settings[name] : this._defaults[name];
9503 /* Parse existing date and initialise date picker. */
9504 _setDateFromField: function(inst, noDefault) {
9505 if (inst.input.val() == inst.lastVal) {
9508 var dateFormat = this._get(inst, 'dateFormat');
9509 var dates = inst.lastVal = inst.input ? inst.input.val() : null;
9510 var date, defaultDate;
9511 date = defaultDate = this._getDefaultDate(inst);
9512 var settings = this._getFormatConfig(inst);
9514 date = this.parseDate(dateFormat, dates, settings) || defaultDate;
9517 dates = (noDefault ? '' : dates);
9519 inst.selectedDay = date.getDate();
9520 inst.drawMonth = inst.selectedMonth = date.getMonth();
9521 inst.drawYear = inst.selectedYear = date.getFullYear();
9522 inst.currentDay = (dates ? date.getDate() : 0);
9523 inst.currentMonth = (dates ? date.getMonth() : 0);
9524 inst.currentYear = (dates ? date.getFullYear() : 0);
9525 this._adjustInstDate(inst);
9528 /* Retrieve the default date shown on opening. */
9529 _getDefaultDate: function(inst) {
9530 return this._restrictMinMax(inst,
9531 this._determineDate(inst, this._get(inst, 'defaultDate'), new Date()));
9534 /* A date may be specified as an exact value or a relative one. */
9535 _determineDate: function(inst, date, defaultDate) {
9536 var offsetNumeric = function(offset) {
9537 var date = new Date();
9538 date.setDate(date.getDate() + offset);
9541 var offsetString = function(offset) {
9543 return $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
9544 offset, $.datepicker._getFormatConfig(inst));
9549 var date = (offset.toLowerCase().match(/^c/) ?
9550 $.datepicker._getDate(inst) : null) || new Date();
9551 var year = date.getFullYear();
9552 var month = date.getMonth();
9553 var day = date.getDate();
9554 var pattern = /([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g;
9555 var matches = pattern.exec(offset);
9557 switch (matches[2] || 'd') {
9558 case 'd' : case 'D' :
9559 day += parseInt(matches[1],10); break;
9560 case 'w' : case 'W' :
9561 day += parseInt(matches[1],10) * 7; break;
9562 case 'm' : case 'M' :
9563 month += parseInt(matches[1],10);
9564 day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
9566 case 'y': case 'Y' :
9567 year += parseInt(matches[1],10);
9568 day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
9571 matches = pattern.exec(offset);
9573 return new Date(year, month, day);
9575 var newDate = (date == null || date === '' ? defaultDate : (typeof date == 'string' ? offsetString(date) :
9576 (typeof date == 'number' ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : new Date(date.getTime()))));
9577 newDate = (newDate && newDate.toString() == 'Invalid Date' ? defaultDate : newDate);
9579 newDate.setHours(0);
9580 newDate.setMinutes(0);
9581 newDate.setSeconds(0);
9582 newDate.setMilliseconds(0);
9584 return this._daylightSavingAdjust(newDate);
9587 /* Handle switch to/from daylight saving.
9588 Hours may be non-zero on daylight saving cut-over:
9589 > 12 when midnight changeover, but then cannot generate
9590 midnight datetime, so jump to 1AM, otherwise reset.
9591 @param date (Date) the date to check
9592 @return (Date) the corrected date */
9593 _daylightSavingAdjust: function(date) {
9594 if (!date) return null;
9595 date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
9599 /* Set the date(s) directly. */
9600 _setDate: function(inst, date, noChange) {
9602 var origMonth = inst.selectedMonth;
9603 var origYear = inst.selectedYear;
9604 var newDate = this._restrictMinMax(inst, this._determineDate(inst, date, new Date()));
9605 inst.selectedDay = inst.currentDay = newDate.getDate();
9606 inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth();
9607 inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear();
9608 if ((origMonth != inst.selectedMonth || origYear != inst.selectedYear) && !noChange)
9609 this._notifyChange(inst);
9610 this._adjustInstDate(inst);
9612 inst.input.val(clear ? '' : this._formatDate(inst));
9616 /* Retrieve the date(s) directly. */
9617 _getDate: function(inst) {
9618 var startDate = (!inst.currentYear || (inst.input && inst.input.val() == '') ? null :
9619 this._daylightSavingAdjust(new Date(
9620 inst.currentYear, inst.currentMonth, inst.currentDay)));
9624 /* Generate the HTML for the current state of the date picker. */
9625 _generateHTML: function(inst) {
9626 var today = new Date();
9627 today = this._daylightSavingAdjust(
9628 new Date(today.getFullYear(), today.getMonth(), today.getDate())); // clear time
9629 var isRTL = this._get(inst, 'isRTL');
9630 var showButtonPanel = this._get(inst, 'showButtonPanel');
9631 var hideIfNoPrevNext = this._get(inst, 'hideIfNoPrevNext');
9632 var navigationAsDateFormat = this._get(inst, 'navigationAsDateFormat');
9633 var numMonths = this._getNumberOfMonths(inst);
9634 var showCurrentAtPos = this._get(inst, 'showCurrentAtPos');
9635 var stepMonths = this._get(inst, 'stepMonths');
9636 var isMultiMonth = (numMonths[0] != 1 || numMonths[1] != 1);
9637 var currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) :
9638 new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
9639 var minDate = this._getMinMaxDate(inst, 'min');
9640 var maxDate = this._getMinMaxDate(inst, 'max');
9641 var drawMonth = inst.drawMonth - showCurrentAtPos;
9642 var drawYear = inst.drawYear;
9643 if (drawMonth < 0) {
9648 var maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),
9649 maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate()));
9650 maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);
9651 while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {
9653 if (drawMonth < 0) {
9659 inst.drawMonth = drawMonth;
9660 inst.drawYear = drawYear;
9661 var prevText = this._get(inst, 'prevText');
9662 prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText,
9663 this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),
9664 this._getFormatConfig(inst)));
9665 var prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?
9666 '<a class="ui-datepicker-prev ui-corner-all" onclick="DP_jQuery_' + dpuuid +
9667 '.datepicker._adjustDate(\'#' + inst.id + '\', -' + stepMonths + ', \'M\');"' +
9668 ' title="' + prevText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>' :
9669 (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>'));
9670 var nextText = this._get(inst, 'nextText');
9671 nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText,
9672 this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),
9673 this._getFormatConfig(inst)));
9674 var next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?
9675 '<a class="ui-datepicker-next ui-corner-all" onclick="DP_jQuery_' + dpuuid +
9676 '.datepicker._adjustDate(\'#' + inst.id + '\', +' + stepMonths + ', \'M\');"' +
9677 ' title="' + nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>' :
9678 (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>'));
9679 var currentText = this._get(inst, 'currentText');
9680 var gotoDate = (this._get(inst, 'gotoCurrent') && inst.currentDay ? currentDate : today);
9681 currentText = (!navigationAsDateFormat ? currentText :
9682 this.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));
9683 var controls = (!inst.inline ? '<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" onclick="DP_jQuery_' + dpuuid +
9684 '.datepicker._hideDatepicker();">' + this._get(inst, 'closeText') + '</button>' : '');
9685 var buttonPanel = (showButtonPanel) ? '<div class="ui-datepicker-buttonpane ui-widget-content">' + (isRTL ? controls : '') +
9686 (this._isInRange(inst, gotoDate) ? '<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" onclick="DP_jQuery_' + dpuuid +
9687 '.datepicker._gotoToday(\'#' + inst.id + '\');"' +
9688 '>' + currentText + '</button>' : '') + (isRTL ? '' : controls) + '</div>' : '';
9689 var firstDay = parseInt(this._get(inst, 'firstDay'),10);
9690 firstDay = (isNaN(firstDay) ? 0 : firstDay);
9691 var showWeek = this._get(inst, 'showWeek');
9692 var dayNames = this._get(inst, 'dayNames');
9693 var dayNamesShort = this._get(inst, 'dayNamesShort');
9694 var dayNamesMin = this._get(inst, 'dayNamesMin');
9695 var monthNames = this._get(inst, 'monthNames');
9696 var monthNamesShort = this._get(inst, 'monthNamesShort');
9697 var beforeShowDay = this._get(inst, 'beforeShowDay');
9698 var showOtherMonths = this._get(inst, 'showOtherMonths');
9699 var selectOtherMonths = this._get(inst, 'selectOtherMonths');
9700 var calculateWeek = this._get(inst, 'calculateWeek') || this.iso8601Week;
9701 var defaultDate = this._getDefaultDate(inst);
9703 for (var row = 0; row < numMonths[0]; row++) {
9706 for (var col = 0; col < numMonths[1]; col++) {
9707 var selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay));
9708 var cornerClass = ' ui-corner-all';
9711 calender += '<div class="ui-datepicker-group';
9712 if (numMonths[1] > 1)
9714 case 0: calender += ' ui-datepicker-group-first';
9715 cornerClass = ' ui-corner-' + (isRTL ? 'right' : 'left'); break;
9716 case numMonths[1]-1: calender += ' ui-datepicker-group-last';
9717 cornerClass = ' ui-corner-' + (isRTL ? 'left' : 'right'); break;
9718 default: calender += ' ui-datepicker-group-middle'; cornerClass = ''; break;
9722 calender += '<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix' + cornerClass + '">' +
9723 (/all|left/.test(cornerClass) && row == 0 ? (isRTL ? next : prev) : '') +
9724 (/all|right/.test(cornerClass) && row == 0 ? (isRTL ? prev : next) : '') +
9725 this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,
9726 row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers
9727 '</div><table class="ui-datepicker-calendar"><thead>' +
9729 var thead = (showWeek ? '<th class="ui-datepicker-week-col">' + this._get(inst, 'weekHeader') + '</th>' : '');
9730 for (var dow = 0; dow < 7; dow++) { // days of the week
9731 var day = (dow + firstDay) % 7;
9732 thead += '<th' + ((dow + firstDay + 6) % 7 >= 5 ? ' class="ui-datepicker-week-end"' : '') + '>' +
9733 '<span title="' + dayNames[day] + '">' + dayNamesMin[day] + '</span></th>';
9735 calender += thead + '</tr></thead><tbody>';
9736 var daysInMonth = this._getDaysInMonth(drawYear, drawMonth);
9737 if (drawYear == inst.selectedYear && drawMonth == inst.selectedMonth)
9738 inst.selectedDay = Math.min(inst.selectedDay, daysInMonth);
9739 var leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;
9740 var curRows = Math.ceil((leadDays + daysInMonth) / 7); // calculate the number of rows to generate
9741 var numRows = (isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows); //If multiple months, use the higher number of rows (see #7043)
9742 this.maxRows = numRows;
9743 var printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
9744 for (var dRow = 0; dRow < numRows; dRow++) { // create date picker rows
9746 var tbody = (!showWeek ? '' : '<td class="ui-datepicker-week-col">' +
9747 this._get(inst, 'calculateWeek')(printDate) + '</td>');
9748 for (var dow = 0; dow < 7; dow++) { // create date picker days
9749 var daySettings = (beforeShowDay ?
9750 beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, '']);
9751 var otherMonth = (printDate.getMonth() != drawMonth);
9752 var unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] ||
9753 (minDate && printDate < minDate) || (maxDate && printDate > maxDate);
9754 tbody += '<td class="' +
9755 ((dow + firstDay + 6) % 7 >= 5 ? ' ui-datepicker-week-end' : '') + // highlight weekends
9756 (otherMonth ? ' ui-datepicker-other-month' : '') + // highlight days from other months
9757 ((printDate.getTime() == selectedDate.getTime() && drawMonth == inst.selectedMonth && inst._keyEvent) || // user pressed key
9758 (defaultDate.getTime() == printDate.getTime() && defaultDate.getTime() == selectedDate.getTime()) ?
9759 // or defaultDate is current printedDate and defaultDate is selectedDate
9760 ' ' + this._dayOverClass : '') + // highlight selected day
9761 (unselectable ? ' ' + this._unselectableClass + ' ui-state-disabled': '') + // highlight unselectable days
9762 (otherMonth && !showOtherMonths ? '' : ' ' + daySettings[1] + // highlight custom dates
9763 (printDate.getTime() == currentDate.getTime() ? ' ' + this._currentClass : '') + // highlight selected day
9764 (printDate.getTime() == today.getTime() ? ' ui-datepicker-today' : '')) + '"' + // highlight today (if different)
9765 ((!otherMonth || showOtherMonths) && daySettings[2] ? ' title="' + daySettings[2] + '"' : '') + // cell title
9766 (unselectable ? '' : ' onclick="DP_jQuery_' + dpuuid + '.datepicker._selectDay(\'#' +
9767 inst.id + '\',' + printDate.getMonth() + ',' + printDate.getFullYear() + ', this);return false;"') + '>' + // actions
9768 (otherMonth && !showOtherMonths ? ' ' : // display for other months
9769 (unselectable ? '<span class="ui-state-default">' + printDate.getDate() + '</span>' : '<a class="ui-state-default' +
9770 (printDate.getTime() == today.getTime() ? ' ui-state-highlight' : '') +
9771 (printDate.getTime() == currentDate.getTime() ? ' ui-state-active' : '') + // highlight selected day
9772 (otherMonth ? ' ui-priority-secondary' : '') + // distinguish dates from other months
9773 '" href="#">' + printDate.getDate() + '</a>')) + '</td>'; // display selectable date
9774 printDate.setDate(printDate.getDate() + 1);
9775 printDate = this._daylightSavingAdjust(printDate);
9777 calender += tbody + '</tr>';
9780 if (drawMonth > 11) {
9784 calender += '</tbody></table>' + (isMultiMonth ? '</div>' +
9785 ((numMonths[0] > 0 && col == numMonths[1]-1) ? '<div class="ui-datepicker-row-break"></div>' : '') : '');
9790 html += buttonPanel + ($.browser.msie && parseInt($.browser.version,10) < 7 && !inst.inline ?
9791 '<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>' : '');
9792 inst._keyEvent = false;
9796 /* Generate the month and year header. */
9797 _generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate,
9798 secondary, monthNames, monthNamesShort) {
9799 var changeMonth = this._get(inst, 'changeMonth');
9800 var changeYear = this._get(inst, 'changeYear');
9801 var showMonthAfterYear = this._get(inst, 'showMonthAfterYear');
9802 var html = '<div class="ui-datepicker-title">';
9805 if (secondary || !changeMonth)
9806 monthHtml += '<span class="ui-datepicker-month">' + monthNames[drawMonth] + '</span>';
9808 var inMinYear = (minDate && minDate.getFullYear() == drawYear);
9809 var inMaxYear = (maxDate && maxDate.getFullYear() == drawYear);
9810 monthHtml += '<select class="ui-datepicker-month" ' +
9811 'onchange="DP_jQuery_' + dpuuid + '.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'M\');" ' +
9812 'onclick="DP_jQuery_' + dpuuid + '.datepicker._clickMonthYear(\'#' + inst.id + '\');"' +
9814 for (var month = 0; month < 12; month++) {
9815 if ((!inMinYear || month >= minDate.getMonth()) &&
9816 (!inMaxYear || month <= maxDate.getMonth()))
9817 monthHtml += '<option value="' + month + '"' +
9818 (month == drawMonth ? ' selected="selected"' : '') +
9819 '>' + monthNamesShort[month] + '</option>';
9821 monthHtml += '</select>';
9823 if (!showMonthAfterYear)
9824 html += monthHtml + (secondary || !(changeMonth && changeYear) ? ' ' : '');
9826 if ( !inst.yearshtml ) {
9827 inst.yearshtml = '';
9828 if (secondary || !changeYear)
9829 html += '<span class="ui-datepicker-year">' + drawYear + '</span>';
9831 // determine range of years to display
9832 var years = this._get(inst, 'yearRange').split(':');
9833 var thisYear = new Date().getFullYear();
9834 var determineYear = function(value) {
9835 var year = (value.match(/c[+-].*/) ? drawYear + parseInt(value.substring(1), 10) :
9836 (value.match(/[+-].*/) ? thisYear + parseInt(value, 10) :
9837 parseInt(value, 10)));
9838 return (isNaN(year) ? thisYear : year);
9840 var year = determineYear(years[0]);
9841 var endYear = Math.max(year, determineYear(years[1] || ''));
9842 year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
9843 endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
9844 inst.yearshtml += '<select class="ui-datepicker-year" ' +
9845 'onchange="DP_jQuery_' + dpuuid + '.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'Y\');" ' +
9846 'onclick="DP_jQuery_' + dpuuid + '.datepicker._clickMonthYear(\'#' + inst.id + '\');"' +
9848 for (; year <= endYear; year++) {
9849 inst.yearshtml += '<option value="' + year + '"' +
9850 (year == drawYear ? ' selected="selected"' : '') +
9851 '>' + year + '</option>';
9853 inst.yearshtml += '</select>';
9855 html += inst.yearshtml;
9856 inst.yearshtml = null;
9859 html += this._get(inst, 'yearSuffix');
9860 if (showMonthAfterYear)
9861 html += (secondary || !(changeMonth && changeYear) ? ' ' : '') + monthHtml;
9862 html += '</div>'; // Close datepicker_header
9866 /* Adjust one of the date sub-fields. */
9867 _adjustInstDate: function(inst, offset, period) {
9868 var year = inst.drawYear + (period == 'Y' ? offset : 0);
9869 var month = inst.drawMonth + (period == 'M' ? offset : 0);
9870 var day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) +
9871 (period == 'D' ? offset : 0);
9872 var date = this._restrictMinMax(inst,
9873 this._daylightSavingAdjust(new Date(year, month, day)));
9874 inst.selectedDay = date.getDate();
9875 inst.drawMonth = inst.selectedMonth = date.getMonth();
9876 inst.drawYear = inst.selectedYear = date.getFullYear();
9877 if (period == 'M' || period == 'Y')
9878 this._notifyChange(inst);
9881 /* Ensure a date is within any min/max bounds. */
9882 _restrictMinMax: function(inst, date) {
9883 var minDate = this._getMinMaxDate(inst, 'min');
9884 var maxDate = this._getMinMaxDate(inst, 'max');
9885 var newDate = (minDate && date < minDate ? minDate : date);
9886 newDate = (maxDate && newDate > maxDate ? maxDate : newDate);
9890 /* Notify change of month/year. */
9891 _notifyChange: function(inst) {
9892 var onChange = this._get(inst, 'onChangeMonthYear');
9894 onChange.apply((inst.input ? inst.input[0] : null),
9895 [inst.selectedYear, inst.selectedMonth + 1, inst]);
9898 /* Determine the number of months to show. */
9899 _getNumberOfMonths: function(inst) {
9900 var numMonths = this._get(inst, 'numberOfMonths');
9901 return (numMonths == null ? [1, 1] : (typeof numMonths == 'number' ? [1, numMonths] : numMonths));
9904 /* Determine the current maximum date - ensure no time components are set. */
9905 _getMinMaxDate: function(inst, minMax) {
9906 return this._determineDate(inst, this._get(inst, minMax + 'Date'), null);
9909 /* Find the number of days in a given month. */
9910 _getDaysInMonth: function(year, month) {
9911 return 32 - this._daylightSavingAdjust(new Date(year, month, 32)).getDate();
9914 /* Find the day of the week of the first of a month. */
9915 _getFirstDayOfMonth: function(year, month) {
9916 return new Date(year, month, 1).getDay();
9919 /* Determines if we should allow a "next/prev" month display change. */
9920 _canAdjustMonth: function(inst, offset, curYear, curMonth) {
9921 var numMonths = this._getNumberOfMonths(inst);
9922 var date = this._daylightSavingAdjust(new Date(curYear,
9923 curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1));
9925 date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
9926 return this._isInRange(inst, date);
9929 /* Is the given date in the accepted range? */
9930 _isInRange: function(inst, date) {
9931 var minDate = this._getMinMaxDate(inst, 'min');
9932 var maxDate = this._getMinMaxDate(inst, 'max');
9933 return ((!minDate || date.getTime() >= minDate.getTime()) &&
9934 (!maxDate || date.getTime() <= maxDate.getTime()));
9937 /* Provide the configuration settings for formatting/parsing. */
9938 _getFormatConfig: function(inst) {
9939 var shortYearCutoff = this._get(inst, 'shortYearCutoff');
9940 shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff :
9941 new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
9942 return {shortYearCutoff: shortYearCutoff,
9943 dayNamesShort: this._get(inst, 'dayNamesShort'), dayNames: this._get(inst, 'dayNames'),
9944 monthNamesShort: this._get(inst, 'monthNamesShort'), monthNames: this._get(inst, 'monthNames')};
9947 /* Format the given date for display. */
9948 _formatDate: function(inst, day, month, year) {
9950 inst.currentDay = inst.selectedDay;
9951 inst.currentMonth = inst.selectedMonth;
9952 inst.currentYear = inst.selectedYear;
9954 var date = (day ? (typeof day == 'object' ? day :
9955 this._daylightSavingAdjust(new Date(year, month, day))) :
9956 this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
9957 return this.formatDate(this._get(inst, 'dateFormat'), date, this._getFormatConfig(inst));
9962 * Bind hover events for datepicker elements.
9963 * Done via delegate so the binding only occurs once in the lifetime of the parent div.
9964 * Global instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker.
9966 function bindHover(dpDiv) {
9967 var selector = 'button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a';
9968 return dpDiv.bind('mouseout', function(event) {
9969 var elem = $( event.target ).closest( selector );
9970 if ( !elem.length ) {
9973 elem.removeClass( "ui-state-hover ui-datepicker-prev-hover ui-datepicker-next-hover" );
9975 .bind('mouseover', function(event) {
9976 var elem = $( event.target ).closest( selector );
9977 if ($.datepicker._isDisabledDatepicker( instActive.inline ? dpDiv.parent()[0] : instActive.input[0]) ||
9981 elem.parents('.ui-datepicker-calendar').find('a').removeClass('ui-state-hover');
9982 elem.addClass('ui-state-hover');
9983 if (elem.hasClass('ui-datepicker-prev')) elem.addClass('ui-datepicker-prev-hover');
9984 if (elem.hasClass('ui-datepicker-next')) elem.addClass('ui-datepicker-next-hover');
9988 /* jQuery extend now ignores nulls! */
9989 function extendRemove(target, props) {
9990 $.extend(target, props);
9991 for (var name in props)
9992 if (props[name] == null || props[name] == undefined)
9993 target[name] = props[name];
9997 /* Determine whether an object is an array. */
9998 function isArray(a) {
9999 return (a && (($.browser.safari && typeof a == 'object' && a.length) ||
10000 (a.constructor && a.constructor.toString().match(/\Array\(\)/))));
10003 /* Invoke the datepicker functionality.
10004 @param options string - a command, optionally followed by additional parameters or
10005 Object - settings for attaching new datepicker functionality
10006 @return jQuery object */
10007 $.fn.datepicker = function(options){
10009 /* Verify an empty collection wasn't passed - Fixes #6976 */
10010 if ( !this.length ) {
10014 /* Initialise the date picker. */
10015 if (!$.datepicker.initialized) {
10016 $(document).mousedown($.datepicker._checkExternalClick).
10017 find('body').append($.datepicker.dpDiv);
10018 $.datepicker.initialized = true;
10021 var otherArgs = Array.prototype.slice.call(arguments, 1);
10022 if (typeof options == 'string' && (options == 'isDisabled' || options == 'getDate' || options == 'widget'))
10023 return $.datepicker['_' + options + 'Datepicker'].
10024 apply($.datepicker, [this[0]].concat(otherArgs));
10025 if (options == 'option' && arguments.length == 2 && typeof arguments[1] == 'string')
10026 return $.datepicker['_' + options + 'Datepicker'].
10027 apply($.datepicker, [this[0]].concat(otherArgs));
10028 return this.each(function() {
10029 typeof options == 'string' ?
10030 $.datepicker['_' + options + 'Datepicker'].
10031 apply($.datepicker, [this].concat(otherArgs)) :
10032 $.datepicker._attachDatepicker(this, options);
10036 $.datepicker = new Datepicker(); // singleton instance
10037 $.datepicker.initialized = false;
10038 $.datepicker.uuid = new Date().getTime();
10039 $.datepicker.version = "1.8.14";
10041 // Workaround for #4055
10042 // Add another global to avoid noConflict issues with inline event handlers
10043 window['DP_jQuery_' + dpuuid] = $;
10047 * jQuery UI Progressbar 1.8.14
10049 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
10050 * Dual licensed under the MIT or GPL Version 2 licenses.
10051 * http://jquery.org/license
10053 * http://docs.jquery.com/UI/Progressbar
10056 * jquery.ui.core.js
10057 * jquery.ui.widget.js
10059 (function( $, undefined ) {
10061 $.widget( "ui.progressbar", {
10069 _create: function() {
10071 .addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
10073 role: "progressbar",
10074 "aria-valuemin": this.min,
10075 "aria-valuemax": this.options.max,
10076 "aria-valuenow": this._value()
10079 this.valueDiv = $( "<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>" )
10080 .appendTo( this.element );
10082 this.oldValue = this._value();
10083 this._refreshValue();
10086 destroy: function() {
10088 .removeClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
10089 .removeAttr( "role" )
10090 .removeAttr( "aria-valuemin" )
10091 .removeAttr( "aria-valuemax" )
10092 .removeAttr( "aria-valuenow" );
10094 this.valueDiv.remove();
10096 $.Widget.prototype.destroy.apply( this, arguments );
10099 value: function( newValue ) {
10100 if ( newValue === undefined ) {
10101 return this._value();
10104 this._setOption( "value", newValue );
10108 _setOption: function( key, value ) {
10109 if ( key === "value" ) {
10110 this.options.value = value;
10111 this._refreshValue();
10112 if ( this._value() === this.options.max ) {
10113 this._trigger( "complete" );
10117 $.Widget.prototype._setOption.apply( this, arguments );
10120 _value: function() {
10121 var val = this.options.value;
10122 // normalize invalid value
10123 if ( typeof val !== "number" ) {
10126 return Math.min( this.options.max, Math.max( this.min, val ) );
10129 _percentage: function() {
10130 return 100 * this._value() / this.options.max;
10133 _refreshValue: function() {
10134 var value = this.value();
10135 var percentage = this._percentage();
10137 if ( this.oldValue !== value ) {
10138 this.oldValue = value;
10139 this._trigger( "change" );
10143 .toggle( value > this.min )
10144 .toggleClass( "ui-corner-right", value === this.options.max )
10145 .width( percentage.toFixed(0) + "%" );
10146 this.element.attr( "aria-valuenow", value );
10150 $.extend( $.ui.progressbar, {
10156 * jQuery UI Effects 1.8.14
10158 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
10159 * Dual licensed under the MIT or GPL Version 2 licenses.
10160 * http://jquery.org/license
10162 * http://docs.jquery.com/UI/Effects/
10164 ;jQuery.effects || (function($, undefined) {
10170 /******************************************************************************/
10171 /****************************** COLOR ANIMATIONS ******************************/
10172 /******************************************************************************/
10174 // override the animation for color styles
10175 $.each(['backgroundColor', 'borderBottomColor', 'borderLeftColor',
10176 'borderRightColor', 'borderTopColor', 'borderColor', 'color', 'outlineColor'],
10177 function(i, attr) {
10178 $.fx.step[attr] = function(fx) {
10179 if (!fx.colorInit) {
10180 fx.start = getColor(fx.elem, attr);
10181 fx.end = getRGB(fx.end);
10182 fx.colorInit = true;
10185 fx.elem.style[attr] = 'rgb(' +
10186 Math.max(Math.min(parseInt((fx.pos * (fx.end[0] - fx.start[0])) + fx.start[0], 10), 255), 0) + ',' +
10187 Math.max(Math.min(parseInt((fx.pos * (fx.end[1] - fx.start[1])) + fx.start[1], 10), 255), 0) + ',' +
10188 Math.max(Math.min(parseInt((fx.pos * (fx.end[2] - fx.start[2])) + fx.start[2], 10), 255), 0) + ')';
10192 // Color Conversion functions from highlightFade
10193 // By Blair Mitchelmore
10194 // http://jquery.offput.ca/highlightFade/
10196 // Parse strings looking for color tuples [255,255,255]
10197 function getRGB(color) {
10200 // Check if we're already dealing with an array of colors
10201 if ( color && color.constructor == Array && color.length == 3 )
10204 // Look for rgb(num,num,num)
10205 if (result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(color))
10206 return [parseInt(result[1],10), parseInt(result[2],10), parseInt(result[3],10)];
10208 // Look for rgb(num%,num%,num%)
10209 if (result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(color))
10210 return [parseFloat(result[1])*2.55, parseFloat(result[2])*2.55, parseFloat(result[3])*2.55];
10212 // Look for #a0b1c2
10213 if (result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(color))
10214 return [parseInt(result[1],16), parseInt(result[2],16), parseInt(result[3],16)];
10217 if (result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(color))
10218 return [parseInt(result[1]+result[1],16), parseInt(result[2]+result[2],16), parseInt(result[3]+result[3],16)];
10220 // Look for rgba(0, 0, 0, 0) == transparent in Safari 3
10221 if (result = /rgba\(0, 0, 0, 0\)/.exec(color))
10222 return colors['transparent'];
10224 // Otherwise, we're most likely dealing with a named color
10225 return colors[$.trim(color).toLowerCase()];
10228 function getColor(elem, attr) {
10232 color = $.curCSS(elem, attr);
10234 // Keep going until we find an element that has color, or we hit the body
10235 if ( color != '' && color != 'transparent' || $.nodeName(elem, "body") )
10238 attr = "backgroundColor";
10239 } while ( elem = elem.parentNode );
10241 return getRGB(color);
10244 // Some named colors to work with
10245 // From Interface by Stefan Petre
10246 // http://interface.eyecon.ro/
10250 azure:[240,255,255],
10251 beige:[245,245,220],
10256 darkblue:[0,0,139],
10257 darkcyan:[0,139,139],
10258 darkgrey:[169,169,169],
10259 darkgreen:[0,100,0],
10260 darkkhaki:[189,183,107],
10261 darkmagenta:[139,0,139],
10262 darkolivegreen:[85,107,47],
10263 darkorange:[255,140,0],
10264 darkorchid:[153,50,204],
10266 darksalmon:[233,150,122],
10267 darkviolet:[148,0,211],
10268 fuchsia:[255,0,255],
10272 khaki:[240,230,140],
10273 lightblue:[173,216,230],
10274 lightcyan:[224,255,255],
10275 lightgreen:[144,238,144],
10276 lightgrey:[211,211,211],
10277 lightpink:[255,182,193],
10278 lightyellow:[255,255,224],
10280 magenta:[255,0,255],
10284 orange:[255,165,0],
10285 pink:[255,192,203],
10286 purple:[128,0,128],
10287 violet:[128,0,128],
10289 silver:[192,192,192],
10290 white:[255,255,255],
10291 yellow:[255,255,0],
10292 transparent: [255,255,255]
10297 /******************************************************************************/
10298 /****************************** CLASS ANIMATIONS ******************************/
10299 /******************************************************************************/
10301 var classAnimationActions = ['add', 'remove', 'toggle'],
10302 shorthandStyles = {
10314 function getElementStyles() {
10315 var style = document.defaultView
10316 ? document.defaultView.getComputedStyle(this, null)
10317 : this.currentStyle,
10322 // webkit enumerates style porperties
10323 if (style && style.length && style[0] && style[style[0]]) {
10324 var len = style.length;
10327 if (typeof style[key] == 'string') {
10328 camelCase = key.replace(/\-(\w)/g, function(all, letter){
10329 return letter.toUpperCase();
10331 newStyle[camelCase] = style[key];
10335 for (key in style) {
10336 if (typeof style[key] === 'string') {
10337 newStyle[key] = style[key];
10345 function filterStyles(styles) {
10347 for (name in styles) {
10348 value = styles[name];
10350 // ignore null and undefined values
10352 // ignore functions (when does this occur?)
10353 $.isFunction(value) ||
10354 // shorthand styles that need to be expanded
10355 name in shorthandStyles ||
10356 // ignore scrollbars (break in IE)
10357 (/scrollbar/).test(name) ||
10359 // only colors or values that can be converted to numbers
10360 (!(/color/i).test(name) && isNaN(parseFloat(value)))
10362 delete styles[name];
10369 function styleDifference(oldStyle, newStyle) {
10370 var diff = { _: 0 }, // http://dev.jquery.com/ticket/5459
10373 for (name in newStyle) {
10374 if (oldStyle[name] != newStyle[name]) {
10375 diff[name] = newStyle[name];
10382 $.effects.animateClass = function(value, duration, easing, callback) {
10383 if ($.isFunction(easing)) {
10388 return this.queue(function() {
10389 var that = $(this),
10390 originalStyleAttr = that.attr('style') || ' ',
10391 originalStyle = filterStyles(getElementStyles.call(this)),
10393 className = that.attr('class');
10395 $.each(classAnimationActions, function(i, action) {
10396 if (value[action]) {
10397 that[action + 'Class'](value[action]);
10400 newStyle = filterStyles(getElementStyles.call(this));
10401 that.attr('class', className);
10403 that.animate(styleDifference(originalStyle, newStyle), {
10405 duration: duration,
10407 complete: function() {
10408 $.each(classAnimationActions, function(i, action) {
10409 if (value[action]) { that[action + 'Class'](value[action]); }
10411 // work around bug in IE by clearing the cssText before setting it
10412 if (typeof that.attr('style') == 'object') {
10413 that.attr('style').cssText = '';
10414 that.attr('style').cssText = originalStyleAttr;
10416 that.attr('style', originalStyleAttr);
10418 if (callback) { callback.apply(this, arguments); }
10426 _addClass: $.fn.addClass,
10427 addClass: function(classNames, speed, easing, callback) {
10428 return speed ? $.effects.animateClass.apply(this, [{ add: classNames },speed,easing,callback]) : this._addClass(classNames);
10431 _removeClass: $.fn.removeClass,
10432 removeClass: function(classNames,speed,easing,callback) {
10433 return speed ? $.effects.animateClass.apply(this, [{ remove: classNames },speed,easing,callback]) : this._removeClass(classNames);
10436 _toggleClass: $.fn.toggleClass,
10437 toggleClass: function(classNames, force, speed, easing, callback) {
10438 if ( typeof force == "boolean" || force === undefined ) {
10440 // without speed parameter;
10441 return this._toggleClass(classNames, force);
10443 return $.effects.animateClass.apply(this, [(force?{add:classNames}:{remove:classNames}),speed,easing,callback]);
10446 // without switch parameter;
10447 return $.effects.animateClass.apply(this, [{ toggle: classNames },force,speed,easing]);
10451 switchClass: function(remove,add,speed,easing,callback) {
10452 return $.effects.animateClass.apply(this, [{ add: add, remove: remove },speed,easing,callback]);
10458 /******************************************************************************/
10459 /*********************************** EFFECTS **********************************/
10460 /******************************************************************************/
10462 $.extend($.effects, {
10465 // Saves a set of properties in a data storage
10466 save: function(element, set) {
10467 for(var i=0; i < set.length; i++) {
10468 if(set[i] !== null) element.data("ec.storage."+set[i], element[0].style[set[i]]);
10472 // Restores a set of previously saved properties from a data storage
10473 restore: function(element, set) {
10474 for(var i=0; i < set.length; i++) {
10475 if(set[i] !== null) element.css(set[i], element.data("ec.storage."+set[i]));
10479 setMode: function(el, mode) {
10480 if (mode == 'toggle') mode = el.is(':hidden') ? 'show' : 'hide'; // Set for toggle
10484 getBaseline: function(origin, original) { // Translates a [top,left] array into a baseline value
10485 // this should be a little more flexible in the future to handle a string & hash
10487 switch (origin[0]) {
10488 case 'top': y = 0; break;
10489 case 'middle': y = 0.5; break;
10490 case 'bottom': y = 1; break;
10491 default: y = origin[0] / original.height;
10493 switch (origin[1]) {
10494 case 'left': x = 0; break;
10495 case 'center': x = 0.5; break;
10496 case 'right': x = 1; break;
10497 default: x = origin[1] / original.width;
10499 return {x: x, y: y};
10502 // Wraps the element around a wrapper that copies position properties
10503 createWrapper: function(element) {
10505 // if the element is already wrapped, return it
10506 if (element.parent().is('.ui-effects-wrapper')) {
10507 return element.parent();
10510 // wrap the element
10512 width: element.outerWidth(true),
10513 height: element.outerHeight(true),
10514 'float': element.css('float')
10516 wrapper = $('<div></div>')
10517 .addClass('ui-effects-wrapper')
10520 background: 'transparent',
10526 element.wrap(wrapper);
10527 wrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually loose the reference to the wrapped element
10529 // transfer positioning properties to the wrapper
10530 if (element.css('position') == 'static') {
10531 wrapper.css({ position: 'relative' });
10532 element.css({ position: 'relative' });
10535 position: element.css('position'),
10536 zIndex: element.css('z-index')
10538 $.each(['top', 'left', 'bottom', 'right'], function(i, pos) {
10539 props[pos] = element.css(pos);
10540 if (isNaN(parseInt(props[pos], 10))) {
10541 props[pos] = 'auto';
10544 element.css({position: 'relative', top: 0, left: 0, right: 'auto', bottom: 'auto' });
10547 return wrapper.css(props).show();
10550 removeWrapper: function(element) {
10551 if (element.parent().is('.ui-effects-wrapper'))
10552 return element.parent().replaceWith(element);
10556 setTransition: function(element, list, factor, value) {
10557 value = value || {};
10558 $.each(list, function(i, x){
10559 unit = element.cssUnit(x);
10560 if (unit[0] > 0) value[x] = unit[0] * factor + unit[1];
10567 function _normalizeArguments(effect, options, speed, callback) {
10568 // shift params for method overloading
10569 if (typeof effect == 'object') {
10570 callback = options;
10573 effect = options.effect;
10575 if ($.isFunction(options)) {
10576 callback = options;
10580 if (typeof options == 'number' || $.fx.speeds[options]) {
10585 if ($.isFunction(speed)) {
10590 options = options || {};
10592 speed = speed || options.duration;
10593 speed = $.fx.off ? 0 : typeof speed == 'number'
10594 ? speed : speed in $.fx.speeds ? $.fx.speeds[speed] : $.fx.speeds._default;
10596 callback = callback || options.complete;
10598 return [effect, options, speed, callback];
10601 function standardSpeed( speed ) {
10602 // valid standard speeds
10603 if ( !speed || typeof speed === "number" || $.fx.speeds[ speed ] ) {
10607 // invalid strings - treat as "normal" speed
10608 if ( typeof speed === "string" && !$.effects[ speed ] ) {
10616 effect: function(effect, options, speed, callback) {
10617 var args = _normalizeArguments.apply(this, arguments),
10618 // TODO: make effects take actual parameters instead of a hash
10624 mode = args2.options.mode,
10625 effectMethod = $.effects[effect];
10627 if ( $.fx.off || !effectMethod ) {
10628 // delegate to the original method (e.g., .show()) if possible
10630 return this[ mode ]( args2.duration, args2.callback );
10632 return this.each(function() {
10633 if ( args2.callback ) {
10634 args2.callback.call( this );
10640 return effectMethod.call(this, args2);
10644 show: function(speed) {
10645 if ( standardSpeed( speed ) ) {
10646 return this._show.apply(this, arguments);
10648 var args = _normalizeArguments.apply(this, arguments);
10649 args[1].mode = 'show';
10650 return this.effect.apply(this, args);
10655 hide: function(speed) {
10656 if ( standardSpeed( speed ) ) {
10657 return this._hide.apply(this, arguments);
10659 var args = _normalizeArguments.apply(this, arguments);
10660 args[1].mode = 'hide';
10661 return this.effect.apply(this, args);
10665 // jQuery core overloads toggle and creates _toggle
10666 __toggle: $.fn.toggle,
10667 toggle: function(speed) {
10668 if ( standardSpeed( speed ) || typeof speed === "boolean" || $.isFunction( speed ) ) {
10669 return this.__toggle.apply(this, arguments);
10671 var args = _normalizeArguments.apply(this, arguments);
10672 args[1].mode = 'toggle';
10673 return this.effect.apply(this, args);
10677 // helper functions
10678 cssUnit: function(key) {
10679 var style = this.css(key), val = [];
10680 $.each( ['em','px','%','pt'], function(i, unit){
10681 if(style.indexOf(unit) > 0)
10682 val = [parseFloat(style), unit];
10690 /******************************************************************************/
10691 /*********************************** EASING ***********************************/
10692 /******************************************************************************/
10695 * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
10697 * Uses the built in easing capabilities added In jQuery 1.1
10698 * to offer multiple easing options
10700 * TERMS OF USE - jQuery Easing
10702 * Open source under the BSD License.
10704 * Copyright 2008 George McGinley Smith
10705 * All rights reserved.
10707 * Redistribution and use in source and binary forms, with or without modification,
10708 * are permitted provided that the following conditions are met:
10710 * Redistributions of source code must retain the above copyright notice, this list of
10711 * conditions and the following disclaimer.
10712 * Redistributions in binary form must reproduce the above copyright notice, this list
10713 * of conditions and the following disclaimer in the documentation and/or other materials
10714 * provided with the distribution.
10716 * Neither the name of the author nor the names of contributors may be used to endorse
10717 * or promote products derived from this software without specific prior written permission.
10719 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
10720 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
10721 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
10722 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
10723 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
10724 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
10725 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
10726 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
10727 * OF THE POSSIBILITY OF SUCH DAMAGE.
10731 // t: current time, b: begInnIng value, c: change In value, d: duration
10732 $.easing.jswing = $.easing.swing;
10736 def: 'easeOutQuad',
10737 swing: function (x, t, b, c, d) {
10738 //alert($.easing.default);
10739 return $.easing[$.easing.def](x, t, b, c, d);
10741 easeInQuad: function (x, t, b, c, d) {
10742 return c*(t/=d)*t + b;
10744 easeOutQuad: function (x, t, b, c, d) {
10745 return -c *(t/=d)*(t-2) + b;
10747 easeInOutQuad: function (x, t, b, c, d) {
10748 if ((t/=d/2) < 1) return c/2*t*t + b;
10749 return -c/2 * ((--t)*(t-2) - 1) + b;
10751 easeInCubic: function (x, t, b, c, d) {
10752 return c*(t/=d)*t*t + b;
10754 easeOutCubic: function (x, t, b, c, d) {
10755 return c*((t=t/d-1)*t*t + 1) + b;
10757 easeInOutCubic: function (x, t, b, c, d) {
10758 if ((t/=d/2) < 1) return c/2*t*t*t + b;
10759 return c/2*((t-=2)*t*t + 2) + b;
10761 easeInQuart: function (x, t, b, c, d) {
10762 return c*(t/=d)*t*t*t + b;
10764 easeOutQuart: function (x, t, b, c, d) {
10765 return -c * ((t=t/d-1)*t*t*t - 1) + b;
10767 easeInOutQuart: function (x, t, b, c, d) {
10768 if ((t/=d/2) < 1) return c/2*t*t*t*t + b;
10769 return -c/2 * ((t-=2)*t*t*t - 2) + b;
10771 easeInQuint: function (x, t, b, c, d) {
10772 return c*(t/=d)*t*t*t*t + b;
10774 easeOutQuint: function (x, t, b, c, d) {
10775 return c*((t=t/d-1)*t*t*t*t + 1) + b;
10777 easeInOutQuint: function (x, t, b, c, d) {
10778 if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b;
10779 return c/2*((t-=2)*t*t*t*t + 2) + b;
10781 easeInSine: function (x, t, b, c, d) {
10782 return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
10784 easeOutSine: function (x, t, b, c, d) {
10785 return c * Math.sin(t/d * (Math.PI/2)) + b;
10787 easeInOutSine: function (x, t, b, c, d) {
10788 return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
10790 easeInExpo: function (x, t, b, c, d) {
10791 return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
10793 easeOutExpo: function (x, t, b, c, d) {
10794 return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
10796 easeInOutExpo: function (x, t, b, c, d) {
10797 if (t==0) return b;
10798 if (t==d) return b+c;
10799 if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
10800 return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
10802 easeInCirc: function (x, t, b, c, d) {
10803 return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
10805 easeOutCirc: function (x, t, b, c, d) {
10806 return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
10808 easeInOutCirc: function (x, t, b, c, d) {
10809 if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
10810 return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
10812 easeInElastic: function (x, t, b, c, d) {
10813 var s=1.70158;var p=0;var a=c;
10814 if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3;
10815 if (a < Math.abs(c)) { a=c; var s=p/4; }
10816 else var s = p/(2*Math.PI) * Math.asin (c/a);
10817 return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
10819 easeOutElastic: function (x, t, b, c, d) {
10820 var s=1.70158;var p=0;var a=c;
10821 if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3;
10822 if (a < Math.abs(c)) { a=c; var s=p/4; }
10823 else var s = p/(2*Math.PI) * Math.asin (c/a);
10824 return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
10826 easeInOutElastic: function (x, t, b, c, d) {
10827 var s=1.70158;var p=0;var a=c;
10828 if (t==0) return b; if ((t/=d/2)==2) return b+c; if (!p) p=d*(.3*1.5);
10829 if (a < Math.abs(c)) { a=c; var s=p/4; }
10830 else var s = p/(2*Math.PI) * Math.asin (c/a);
10831 if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
10832 return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
10834 easeInBack: function (x, t, b, c, d, s) {
10835 if (s == undefined) s = 1.70158;
10836 return c*(t/=d)*t*((s+1)*t - s) + b;
10838 easeOutBack: function (x, t, b, c, d, s) {
10839 if (s == undefined) s = 1.70158;
10840 return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
10842 easeInOutBack: function (x, t, b, c, d, s) {
10843 if (s == undefined) s = 1.70158;
10844 if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
10845 return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
10847 easeInBounce: function (x, t, b, c, d) {
10848 return c - $.easing.easeOutBounce (x, d-t, 0, c, d) + b;
10850 easeOutBounce: function (x, t, b, c, d) {
10851 if ((t/=d) < (1/2.75)) {
10852 return c*(7.5625*t*t) + b;
10853 } else if (t < (2/2.75)) {
10854 return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
10855 } else if (t < (2.5/2.75)) {
10856 return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
10858 return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
10861 easeInOutBounce: function (x, t, b, c, d) {
10862 if (t < d/2) return $.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b;
10863 return $.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b;
10869 * TERMS OF USE - EASING EQUATIONS
10871 * Open source under the BSD License.
10873 * Copyright 2001 Robert Penner
10874 * All rights reserved.
10876 * Redistribution and use in source and binary forms, with or without modification,
10877 * are permitted provided that the following conditions are met:
10879 * Redistributions of source code must retain the above copyright notice, this list of
10880 * conditions and the following disclaimer.
10881 * Redistributions in binary form must reproduce the above copyright notice, this list
10882 * of conditions and the following disclaimer in the documentation and/or other materials
10883 * provided with the distribution.
10885 * Neither the name of the author nor the names of contributors may be used to endorse
10886 * or promote products derived from this software without specific prior written permission.
10888 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
10889 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
10890 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
10891 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
10892 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
10893 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
10894 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
10895 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
10896 * OF THE POSSIBILITY OF SUCH DAMAGE.
10902 * jQuery UI Effects Blind 1.8.14
10904 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
10905 * Dual licensed under the MIT or GPL Version 2 licenses.
10906 * http://jquery.org/license
10908 * http://docs.jquery.com/UI/Effects/Blind
10911 * jquery.effects.core.js
10913 (function( $, undefined ) {
10915 $.effects.blind = function(o) {
10917 return this.queue(function() {
10920 var el = $(this), props = ['position','top','bottom','left','right'];
10923 var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
10924 var direction = o.options.direction || 'vertical'; // Default direction
10927 $.effects.save(el, props); el.show(); // Save & Show
10928 var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
10929 var ref = (direction == 'vertical') ? 'height' : 'width';
10930 var distance = (direction == 'vertical') ? wrapper.height() : wrapper.width();
10931 if(mode == 'show') wrapper.css(ref, 0); // Shift
10934 var animation = {};
10935 animation[ref] = mode == 'show' ? distance : 0;
10938 wrapper.animate(animation, o.duration, o.options.easing, function() {
10939 if(mode == 'hide') el.hide(); // Hide
10940 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
10941 if(o.callback) o.callback.apply(el[0], arguments); // Callback
10951 * jQuery UI Effects Bounce 1.8.14
10953 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
10954 * Dual licensed under the MIT or GPL Version 2 licenses.
10955 * http://jquery.org/license
10957 * http://docs.jquery.com/UI/Effects/Bounce
10960 * jquery.effects.core.js
10962 (function( $, undefined ) {
10964 $.effects.bounce = function(o) {
10966 return this.queue(function() {
10969 var el = $(this), props = ['position','top','bottom','left','right'];
10972 var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
10973 var direction = o.options.direction || 'up'; // Default direction
10974 var distance = o.options.distance || 20; // Default distance
10975 var times = o.options.times || 5; // Default # of times
10976 var speed = o.duration || 250; // Default speed per bounce
10977 if (/show|hide/.test(mode)) props.push('opacity'); // Avoid touching opacity to prevent clearType and PNG issues in IE
10980 $.effects.save(el, props); el.show(); // Save & Show
10981 $.effects.createWrapper(el); // Create Wrapper
10982 var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
10983 var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
10984 var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) / 3 : el.outerWidth({margin:true}) / 3);
10985 if (mode == 'show') el.css('opacity', 0).css(ref, motion == 'pos' ? -distance : distance); // Shift
10986 if (mode == 'hide') distance = distance / (times * 2);
10987 if (mode != 'hide') times--;
10990 if (mode == 'show') { // Show Bounce
10991 var animation = {opacity: 1};
10992 animation[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
10993 el.animate(animation, speed / 2, o.options.easing);
10994 distance = distance / 2;
10997 for (var i = 0; i < times; i++) { // Bounces
10998 var animation1 = {}, animation2 = {};
10999 animation1[ref] = (motion == 'pos' ? '-=' : '+=') + distance;
11000 animation2[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
11001 el.animate(animation1, speed / 2, o.options.easing).animate(animation2, speed / 2, o.options.easing);
11002 distance = (mode == 'hide') ? distance * 2 : distance / 2;
11004 if (mode == 'hide') { // Last Bounce
11005 var animation = {opacity: 0};
11006 animation[ref] = (motion == 'pos' ? '-=' : '+=') + distance;
11007 el.animate(animation, speed / 2, o.options.easing, function(){
11009 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
11010 if(o.callback) o.callback.apply(this, arguments); // Callback
11013 var animation1 = {}, animation2 = {};
11014 animation1[ref] = (motion == 'pos' ? '-=' : '+=') + distance;
11015 animation2[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
11016 el.animate(animation1, speed / 2, o.options.easing).animate(animation2, speed / 2, o.options.easing, function(){
11017 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
11018 if(o.callback) o.callback.apply(this, arguments); // Callback
11021 el.queue('fx', function() { el.dequeue(); });
11029 * jQuery UI Effects Clip 1.8.14
11031 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
11032 * Dual licensed under the MIT or GPL Version 2 licenses.
11033 * http://jquery.org/license
11035 * http://docs.jquery.com/UI/Effects/Clip
11038 * jquery.effects.core.js
11040 (function( $, undefined ) {
11042 $.effects.clip = function(o) {
11044 return this.queue(function() {
11047 var el = $(this), props = ['position','top','bottom','left','right','height','width'];
11050 var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
11051 var direction = o.options.direction || 'vertical'; // Default direction
11054 $.effects.save(el, props); el.show(); // Save & Show
11055 var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
11056 var animate = el[0].tagName == 'IMG' ? wrapper : el;
11058 size: (direction == 'vertical') ? 'height' : 'width',
11059 position: (direction == 'vertical') ? 'top' : 'left'
11061 var distance = (direction == 'vertical') ? animate.height() : animate.width();
11062 if(mode == 'show') { animate.css(ref.size, 0); animate.css(ref.position, distance / 2); } // Shift
11065 var animation = {};
11066 animation[ref.size] = mode == 'show' ? distance : 0;
11067 animation[ref.position] = mode == 'show' ? 0 : distance / 2;
11070 animate.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
11071 if(mode == 'hide') el.hide(); // Hide
11072 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
11073 if(o.callback) o.callback.apply(el[0], arguments); // Callback
11083 * jQuery UI Effects Drop 1.8.14
11085 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
11086 * Dual licensed under the MIT or GPL Version 2 licenses.
11087 * http://jquery.org/license
11089 * http://docs.jquery.com/UI/Effects/Drop
11092 * jquery.effects.core.js
11094 (function( $, undefined ) {
11096 $.effects.drop = function(o) {
11098 return this.queue(function() {
11101 var el = $(this), props = ['position','top','bottom','left','right','opacity'];
11104 var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
11105 var direction = o.options.direction || 'left'; // Default Direction
11108 $.effects.save(el, props); el.show(); // Save & Show
11109 $.effects.createWrapper(el); // Create Wrapper
11110 var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
11111 var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
11112 var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) / 2 : el.outerWidth({margin:true}) / 2);
11113 if (mode == 'show') el.css('opacity', 0).css(ref, motion == 'pos' ? -distance : distance); // Shift
11116 var animation = {opacity: mode == 'show' ? 1 : 0};
11117 animation[ref] = (mode == 'show' ? (motion == 'pos' ? '+=' : '-=') : (motion == 'pos' ? '-=' : '+=')) + distance;
11120 el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
11121 if(mode == 'hide') el.hide(); // Hide
11122 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
11123 if(o.callback) o.callback.apply(this, arguments); // Callback
11133 * jQuery UI Effects Explode 1.8.14
11135 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
11136 * Dual licensed under the MIT or GPL Version 2 licenses.
11137 * http://jquery.org/license
11139 * http://docs.jquery.com/UI/Effects/Explode
11142 * jquery.effects.core.js
11144 (function( $, undefined ) {
11146 $.effects.explode = function(o) {
11148 return this.queue(function() {
11150 var rows = o.options.pieces ? Math.round(Math.sqrt(o.options.pieces)) : 3;
11151 var cells = o.options.pieces ? Math.round(Math.sqrt(o.options.pieces)) : 3;
11153 o.options.mode = o.options.mode == 'toggle' ? ($(this).is(':visible') ? 'hide' : 'show') : o.options.mode;
11154 var el = $(this).show().css('visibility', 'hidden');
11155 var offset = el.offset();
11157 //Substract the margins - not fixing the problem yet.
11158 offset.top -= parseInt(el.css("marginTop"),10) || 0;
11159 offset.left -= parseInt(el.css("marginLeft"),10) || 0;
11161 var width = el.outerWidth(true);
11162 var height = el.outerHeight(true);
11164 for(var i=0;i<rows;i++) { // =
11165 for(var j=0;j<cells;j++) { // ||
11169 .wrap('<div></div>')
11171 position: 'absolute',
11172 visibility: 'visible',
11173 left: -j*(width/cells),
11174 top: -i*(height/rows)
11177 .addClass('ui-effects-explode')
11179 position: 'absolute',
11180 overflow: 'hidden',
11181 width: width/cells,
11182 height: height/rows,
11183 left: offset.left + j*(width/cells) + (o.options.mode == 'show' ? (j-Math.floor(cells/2))*(width/cells) : 0),
11184 top: offset.top + i*(height/rows) + (o.options.mode == 'show' ? (i-Math.floor(rows/2))*(height/rows) : 0),
11185 opacity: o.options.mode == 'show' ? 0 : 1
11187 left: offset.left + j*(width/cells) + (o.options.mode == 'show' ? 0 : (j-Math.floor(cells/2))*(width/cells)),
11188 top: offset.top + i*(height/rows) + (o.options.mode == 'show' ? 0 : (i-Math.floor(rows/2))*(height/rows)),
11189 opacity: o.options.mode == 'show' ? 1 : 0
11190 }, o.duration || 500);
11194 // Set a timeout, to call the callback approx. when the other animations have finished
11195 setTimeout(function() {
11197 o.options.mode == 'show' ? el.css({ visibility: 'visible' }) : el.css({ visibility: 'visible' }).hide();
11198 if(o.callback) o.callback.apply(el[0]); // Callback
11201 $('div.ui-effects-explode').remove();
11203 }, o.duration || 500);
11212 * jQuery UI Effects Fade 1.8.14
11214 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
11215 * Dual licensed under the MIT or GPL Version 2 licenses.
11216 * http://jquery.org/license
11218 * http://docs.jquery.com/UI/Effects/Fade
11221 * jquery.effects.core.js
11223 (function( $, undefined ) {
11225 $.effects.fade = function(o) {
11226 return this.queue(function() {
11227 var elem = $(this),
11228 mode = $.effects.setMode(elem, o.options.mode || 'hide');
11230 elem.animate({ opacity: mode }, {
11232 duration: o.duration,
11233 easing: o.options.easing,
11234 complete: function() {
11235 (o.callback && o.callback.apply(this, arguments));
11244 * jQuery UI Effects Fold 1.8.14
11246 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
11247 * Dual licensed under the MIT or GPL Version 2 licenses.
11248 * http://jquery.org/license
11250 * http://docs.jquery.com/UI/Effects/Fold
11253 * jquery.effects.core.js
11255 (function( $, undefined ) {
11257 $.effects.fold = function(o) {
11259 return this.queue(function() {
11262 var el = $(this), props = ['position','top','bottom','left','right'];
11265 var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
11266 var size = o.options.size || 15; // Default fold size
11267 var horizFirst = !(!o.options.horizFirst); // Ensure a boolean value
11268 var duration = o.duration ? o.duration / 2 : $.fx.speeds._default / 2;
11271 $.effects.save(el, props); el.show(); // Save & Show
11272 var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
11273 var widthFirst = ((mode == 'show') != horizFirst);
11274 var ref = widthFirst ? ['width', 'height'] : ['height', 'width'];
11275 var distance = widthFirst ? [wrapper.width(), wrapper.height()] : [wrapper.height(), wrapper.width()];
11276 var percent = /([0-9]+)%/.exec(size);
11277 if(percent) size = parseInt(percent[1],10) / 100 * distance[mode == 'hide' ? 0 : 1];
11278 if(mode == 'show') wrapper.css(horizFirst ? {height: 0, width: size} : {height: size, width: 0}); // Shift
11281 var animation1 = {}, animation2 = {};
11282 animation1[ref[0]] = mode == 'show' ? distance[0] : size;
11283 animation2[ref[1]] = mode == 'show' ? distance[1] : 0;
11286 wrapper.animate(animation1, duration, o.options.easing)
11287 .animate(animation2, duration, o.options.easing, function() {
11288 if(mode == 'hide') el.hide(); // Hide
11289 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
11290 if(o.callback) o.callback.apply(el[0], arguments); // Callback
11300 * jQuery UI Effects Highlight 1.8.14
11302 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
11303 * Dual licensed under the MIT or GPL Version 2 licenses.
11304 * http://jquery.org/license
11306 * http://docs.jquery.com/UI/Effects/Highlight
11309 * jquery.effects.core.js
11311 (function( $, undefined ) {
11313 $.effects.highlight = function(o) {
11314 return this.queue(function() {
11315 var elem = $(this),
11316 props = ['backgroundImage', 'backgroundColor', 'opacity'],
11317 mode = $.effects.setMode(elem, o.options.mode || 'show'),
11319 backgroundColor: elem.css('backgroundColor')
11322 if (mode == 'hide') {
11323 animation.opacity = 0;
11326 $.effects.save(elem, props);
11330 backgroundImage: 'none',
11331 backgroundColor: o.options.color || '#ffff99'
11333 .animate(animation, {
11335 duration: o.duration,
11336 easing: o.options.easing,
11337 complete: function() {
11338 (mode == 'hide' && elem.hide());
11339 $.effects.restore(elem, props);
11340 (mode == 'show' && !$.support.opacity && this.style.removeAttribute('filter'));
11341 (o.callback && o.callback.apply(this, arguments));
11350 * jQuery UI Effects Pulsate 1.8.14
11352 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
11353 * Dual licensed under the MIT or GPL Version 2 licenses.
11354 * http://jquery.org/license
11356 * http://docs.jquery.com/UI/Effects/Pulsate
11359 * jquery.effects.core.js
11361 (function( $, undefined ) {
11363 $.effects.pulsate = function(o) {
11364 return this.queue(function() {
11365 var elem = $(this),
11366 mode = $.effects.setMode(elem, o.options.mode || 'show');
11367 times = ((o.options.times || 5) * 2) - 1;
11368 duration = o.duration ? o.duration / 2 : $.fx.speeds._default / 2,
11369 isVisible = elem.is(':visible'),
11373 elem.css('opacity', 0).show();
11377 if ((mode == 'hide' && isVisible) || (mode == 'show' && !isVisible)) {
11381 for (var i = 0; i < times; i++) {
11382 elem.animate({ opacity: animateTo }, duration, o.options.easing);
11383 animateTo = (animateTo + 1) % 2;
11386 elem.animate({ opacity: animateTo }, duration, o.options.easing, function() {
11387 if (animateTo == 0) {
11390 (o.callback && o.callback.apply(this, arguments));
11394 .queue('fx', function() { elem.dequeue(); })
11401 * jQuery UI Effects Scale 1.8.14
11403 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
11404 * Dual licensed under the MIT or GPL Version 2 licenses.
11405 * http://jquery.org/license
11407 * http://docs.jquery.com/UI/Effects/Scale
11410 * jquery.effects.core.js
11412 (function( $, undefined ) {
11414 $.effects.puff = function(o) {
11415 return this.queue(function() {
11416 var elem = $(this),
11417 mode = $.effects.setMode(elem, o.options.mode || 'hide'),
11418 percent = parseInt(o.options.percent, 10) || 150,
11419 factor = percent / 100,
11420 original = { height: elem.height(), width: elem.width() };
11422 $.extend(o.options, {
11425 percent: mode == 'hide' ? percent : 100,
11426 from: mode == 'hide'
11429 height: original.height * factor,
11430 width: original.width * factor
11434 elem.effect('scale', o.options, o.duration, o.callback);
11439 $.effects.scale = function(o) {
11441 return this.queue(function() {
11447 var options = $.extend(true, {}, o.options);
11448 var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
11449 var percent = parseInt(o.options.percent,10) || (parseInt(o.options.percent,10) == 0 ? 0 : (mode == 'hide' ? 0 : 100)); // Set default scaling percent
11450 var direction = o.options.direction || 'both'; // Set default axis
11451 var origin = o.options.origin; // The origin of the scaling
11452 if (mode != 'effect') { // Set default origin and restore for show/hide
11453 options.origin = origin || ['middle','center'];
11454 options.restore = true;
11456 var original = {height: el.height(), width: el.width()}; // Save original
11457 el.from = o.options.from || (mode == 'show' ? {height: 0, width: 0} : original); // Default from state
11460 var factor = { // Set scaling factor
11461 y: direction != 'horizontal' ? (percent / 100) : 1,
11462 x: direction != 'vertical' ? (percent / 100) : 1
11464 el.to = {height: original.height * factor.y, width: original.width * factor.x}; // Set to state
11466 if (o.options.fade) { // Fade option to support puff
11467 if (mode == 'show') {el.from.opacity = 0; el.to.opacity = 1;};
11468 if (mode == 'hide') {el.from.opacity = 1; el.to.opacity = 0;};
11472 options.from = el.from; options.to = el.to; options.mode = mode;
11475 el.effect('size', options, o.duration, o.callback);
11481 $.effects.size = function(o) {
11483 return this.queue(function() {
11486 var el = $(this), props = ['position','top','bottom','left','right','width','height','overflow','opacity'];
11487 var props1 = ['position','top','bottom','left','right','overflow','opacity']; // Always restore
11488 var props2 = ['width','height','overflow']; // Copy for children
11489 var cProps = ['fontSize'];
11490 var vProps = ['borderTopWidth', 'borderBottomWidth', 'paddingTop', 'paddingBottom'];
11491 var hProps = ['borderLeftWidth', 'borderRightWidth', 'paddingLeft', 'paddingRight'];
11494 var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
11495 var restore = o.options.restore || false; // Default restore
11496 var scale = o.options.scale || 'both'; // Default scale mode
11497 var origin = o.options.origin; // The origin of the sizing
11498 var original = {height: el.height(), width: el.width()}; // Save original
11499 el.from = o.options.from || original; // Default from state
11500 el.to = o.options.to || original; // Default to state
11502 if (origin) { // Calculate baseline shifts
11503 var baseline = $.effects.getBaseline(origin, original);
11504 el.from.top = (original.height - el.from.height) * baseline.y;
11505 el.from.left = (original.width - el.from.width) * baseline.x;
11506 el.to.top = (original.height - el.to.height) * baseline.y;
11507 el.to.left = (original.width - el.to.width) * baseline.x;
11509 var factor = { // Set scaling factor
11510 from: {y: el.from.height / original.height, x: el.from.width / original.width},
11511 to: {y: el.to.height / original.height, x: el.to.width / original.width}
11513 if (scale == 'box' || scale == 'both') { // Scale the css box
11514 if (factor.from.y != factor.to.y) { // Vertical props scaling
11515 props = props.concat(vProps);
11516 el.from = $.effects.setTransition(el, vProps, factor.from.y, el.from);
11517 el.to = $.effects.setTransition(el, vProps, factor.to.y, el.to);
11519 if (factor.from.x != factor.to.x) { // Horizontal props scaling
11520 props = props.concat(hProps);
11521 el.from = $.effects.setTransition(el, hProps, factor.from.x, el.from);
11522 el.to = $.effects.setTransition(el, hProps, factor.to.x, el.to);
11525 if (scale == 'content' || scale == 'both') { // Scale the content
11526 if (factor.from.y != factor.to.y) { // Vertical props scaling
11527 props = props.concat(cProps);
11528 el.from = $.effects.setTransition(el, cProps, factor.from.y, el.from);
11529 el.to = $.effects.setTransition(el, cProps, factor.to.y, el.to);
11532 $.effects.save(el, restore ? props : props1); el.show(); // Save & Show
11533 $.effects.createWrapper(el); // Create Wrapper
11534 el.css('overflow','hidden').css(el.from); // Shift
11537 if (scale == 'content' || scale == 'both') { // Scale the children
11538 vProps = vProps.concat(['marginTop','marginBottom']).concat(cProps); // Add margins/font-size
11539 hProps = hProps.concat(['marginLeft','marginRight']); // Add margins
11540 props2 = props.concat(vProps).concat(hProps); // Concat
11541 el.find("*[width]").each(function(){
11543 if (restore) $.effects.save(child, props2);
11544 var c_original = {height: child.height(), width: child.width()}; // Save original
11545 child.from = {height: c_original.height * factor.from.y, width: c_original.width * factor.from.x};
11546 child.to = {height: c_original.height * factor.to.y, width: c_original.width * factor.to.x};
11547 if (factor.from.y != factor.to.y) { // Vertical props scaling
11548 child.from = $.effects.setTransition(child, vProps, factor.from.y, child.from);
11549 child.to = $.effects.setTransition(child, vProps, factor.to.y, child.to);
11551 if (factor.from.x != factor.to.x) { // Horizontal props scaling
11552 child.from = $.effects.setTransition(child, hProps, factor.from.x, child.from);
11553 child.to = $.effects.setTransition(child, hProps, factor.to.x, child.to);
11555 child.css(child.from); // Shift children
11556 child.animate(child.to, o.duration, o.options.easing, function(){
11557 if (restore) $.effects.restore(child, props2); // Restore children
11558 }); // Animate children
11563 el.animate(el.to, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
11564 if (el.to.opacity === 0) {
11565 el.css('opacity', el.from.opacity);
11567 if(mode == 'hide') el.hide(); // Hide
11568 $.effects.restore(el, restore ? props : props1); $.effects.removeWrapper(el); // Restore
11569 if(o.callback) o.callback.apply(this, arguments); // Callback
11579 * jQuery UI Effects Shake 1.8.14
11581 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
11582 * Dual licensed under the MIT or GPL Version 2 licenses.
11583 * http://jquery.org/license
11585 * http://docs.jquery.com/UI/Effects/Shake
11588 * jquery.effects.core.js
11590 (function( $, undefined ) {
11592 $.effects.shake = function(o) {
11594 return this.queue(function() {
11597 var el = $(this), props = ['position','top','bottom','left','right'];
11600 var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
11601 var direction = o.options.direction || 'left'; // Default direction
11602 var distance = o.options.distance || 20; // Default distance
11603 var times = o.options.times || 3; // Default # of times
11604 var speed = o.duration || o.options.duration || 140; // Default speed per shake
11607 $.effects.save(el, props); el.show(); // Save & Show
11608 $.effects.createWrapper(el); // Create Wrapper
11609 var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
11610 var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
11613 var animation = {}, animation1 = {}, animation2 = {};
11614 animation[ref] = (motion == 'pos' ? '-=' : '+=') + distance;
11615 animation1[ref] = (motion == 'pos' ? '+=' : '-=') + distance * 2;
11616 animation2[ref] = (motion == 'pos' ? '-=' : '+=') + distance * 2;
11619 el.animate(animation, speed, o.options.easing);
11620 for (var i = 1; i < times; i++) { // Shakes
11621 el.animate(animation1, speed, o.options.easing).animate(animation2, speed, o.options.easing);
11623 el.animate(animation1, speed, o.options.easing).
11624 animate(animation, speed / 2, o.options.easing, function(){ // Last shake
11625 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
11626 if(o.callback) o.callback.apply(this, arguments); // Callback
11628 el.queue('fx', function() { el.dequeue(); });
11636 * jQuery UI Effects Slide 1.8.14
11638 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
11639 * Dual licensed under the MIT or GPL Version 2 licenses.
11640 * http://jquery.org/license
11642 * http://docs.jquery.com/UI/Effects/Slide
11645 * jquery.effects.core.js
11647 (function( $, undefined ) {
11649 $.effects.slide = function(o) {
11651 return this.queue(function() {
11654 var el = $(this), props = ['position','top','bottom','left','right'];
11657 var mode = $.effects.setMode(el, o.options.mode || 'show'); // Set Mode
11658 var direction = o.options.direction || 'left'; // Default Direction
11661 $.effects.save(el, props); el.show(); // Save & Show
11662 $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
11663 var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
11664 var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
11665 var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) : el.outerWidth({margin:true}));
11666 if (mode == 'show') el.css(ref, motion == 'pos' ? (isNaN(distance) ? "-" + distance : -distance) : distance); // Shift
11669 var animation = {};
11670 animation[ref] = (mode == 'show' ? (motion == 'pos' ? '+=' : '-=') : (motion == 'pos' ? '-=' : '+=')) + distance;
11673 el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
11674 if(mode == 'hide') el.hide(); // Hide
11675 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
11676 if(o.callback) o.callback.apply(this, arguments); // Callback
11686 * jQuery UI Effects Transfer 1.8.14
11688 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
11689 * Dual licensed under the MIT or GPL Version 2 licenses.
11690 * http://jquery.org/license
11692 * http://docs.jquery.com/UI/Effects/Transfer
11695 * jquery.effects.core.js
11697 (function( $, undefined ) {
11699 $.effects.transfer = function(o) {
11700 return this.queue(function() {
11701 var elem = $(this),
11702 target = $(o.options.to),
11703 endPosition = target.offset(),
11705 top: endPosition.top,
11706 left: endPosition.left,
11707 height: target.innerHeight(),
11708 width: target.innerWidth()
11710 startPosition = elem.offset(),
11711 transfer = $('<div class="ui-effects-transfer"></div>')
11712 .appendTo(document.body)
11713 .addClass(o.options.className)
11715 top: startPosition.top,
11716 left: startPosition.left,
11717 height: elem.innerHeight(),
11718 width: elem.innerWidth(),
11719 position: 'absolute'
11721 .animate(animation, o.duration, o.options.easing, function() {
11723 (o.callback && o.callback.apply(elem[0], arguments));