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 visible( element ) {
178 return !$( element ).parents().andSelf().filter(function() {
179 return $.curCSS( this, "visibility" ) === "hidden" ||
180 $.expr.filters.hidden( this );
184 $.extend( $.expr[ ":" ], {
185 data: function( elem, i, match ) {
186 return !!$.data( elem, match[ 3 ] );
189 focusable: function( element ) {
190 var nodeName = element.nodeName.toLowerCase(),
191 tabIndex = $.attr( element, "tabindex" );
192 if ( "area" === nodeName ) {
193 var map = element.parentNode,
196 if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
199 img = $( "img[usemap=#" + mapName + "]" )[0];
200 return !!img && visible( img );
202 return ( /input|select|textarea|button|object/.test( nodeName )
205 ? element.href || !isNaN( tabIndex )
206 : !isNaN( tabIndex ))
207 // the element and all of its ancestors must be visible
208 && visible( element );
211 tabbable: function( element ) {
212 var tabIndex = $.attr( element, "tabindex" );
213 return ( isNaN( tabIndex ) || tabIndex >= 0 ) && $( element ).is( ":focusable" );
219 var body = document.body,
220 div = body.appendChild( div = document.createElement( "div" ) );
222 $.extend( div.style, {
229 $.support.minHeight = div.offsetHeight === 100;
230 $.support.selectstart = "onselectstart" in div;
232 // set display to none to avoid a layout bug in IE
233 // http://dev.jquery.com/ticket/4014
234 body.removeChild( div ).style.display = "none";
243 // $.ui.plugin is deprecated. Use the proxy pattern instead.
245 add: function( module, option, set ) {
246 var proto = $.ui[ module ].prototype;
247 for ( var i in set ) {
248 proto.plugins[ i ] = proto.plugins[ i ] || [];
249 proto.plugins[ i ].push( [ option, set[ i ] ] );
252 call: function( instance, name, args ) {
253 var set = instance.plugins[ name ];
254 if ( !set || !instance.element[ 0 ].parentNode ) {
258 for ( var i = 0; i < set.length; i++ ) {
259 if ( instance.options[ set[ i ][ 0 ] ] ) {
260 set[ i ][ 1 ].apply( instance.element, args );
266 // will be deprecated when we switch to jQuery 1.4 - use jQuery.contains()
267 contains: function( a, b ) {
268 return document.compareDocumentPosition ?
269 a.compareDocumentPosition( b ) & 16 :
270 a !== b && a.contains( b );
273 // only used by resizable
274 hasScroll: function( el, a ) {
276 //If overflow is hidden, the element might have extra content, but the user wants to hide it
277 if ( $( el ).css( "overflow" ) === "hidden") {
281 var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
284 if ( el[ scroll ] > 0 ) {
288 // TODO: determine which cases actually cause this to happen
289 // if the element doesn't have the scroll set, see if it's possible to
292 has = ( el[ scroll ] > 0 );
297 // these are odd functions, fix the API or move into individual plugins
298 isOverAxis: function( x, reference, size ) {
299 //Determines when x coordinate is over "b" element axis
300 return ( x > reference ) && ( x < ( reference + size ) );
302 isOver: function( y, x, top, left, height, width ) {
303 //Determines when x, y coordinates is over "b" element
304 return $.ui.isOverAxis( y, top, height ) && $.ui.isOverAxis( x, left, width );
310 * jQuery UI Widget 1.8.10
312 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
313 * Dual licensed under the MIT or GPL Version 2 licenses.
314 * http://jquery.org/license
316 * http://docs.jquery.com/UI/Widget
318 (function( $, undefined ) {
322 var _cleanData = $.cleanData;
323 $.cleanData = function( elems ) {
324 for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
325 $( elem ).triggerHandler( "remove" );
330 var _remove = $.fn.remove;
331 $.fn.remove = function( selector, keepData ) {
332 return this.each(function() {
334 if ( !selector || $.filter( selector, [ this ] ).length ) {
335 $( "*", this ).add( [ this ] ).each(function() {
336 $( this ).triggerHandler( "remove" );
340 return _remove.call( $(this), selector, keepData );
345 $.widget = function( name, base, prototype ) {
346 var namespace = name.split( "." )[ 0 ],
348 name = name.split( "." )[ 1 ];
349 fullName = namespace + "-" + name;
356 // create selector for plugin
357 $.expr[ ":" ][ fullName ] = function( elem ) {
358 return !!$.data( elem, name );
361 $[ namespace ] = $[ namespace ] || {};
362 $[ namespace ][ name ] = function( options, element ) {
363 // allow instantiation without initializing for simple inheritance
364 if ( arguments.length ) {
365 this._createWidget( options, element );
369 var basePrototype = new base();
370 // we need to make the options hash a property directly on the new instance
371 // otherwise we'll modify the options hash on the prototype that we're
373 // $.each( basePrototype, function( key, val ) {
374 // if ( $.isPlainObject(val) ) {
375 // basePrototype[ key ] = $.extend( {}, val );
378 basePrototype.options = $.extend( true, {}, basePrototype.options );
379 $[ namespace ][ name ].prototype = $.extend( true, basePrototype, {
380 namespace: namespace,
382 widgetEventPrefix: $[ namespace ][ name ].prototype.widgetEventPrefix || name,
383 widgetBaseClass: fullName
386 $.widget.bridge( name, $[ namespace ][ name ] );
389 $.widget.bridge = function( name, object ) {
390 $.fn[ name ] = function( options ) {
391 var isMethodCall = typeof options === "string",
392 args = Array.prototype.slice.call( arguments, 1 ),
395 // allow multiple hashes to be passed on init
396 options = !isMethodCall && args.length ?
397 $.extend.apply( null, [ true, options ].concat(args) ) :
400 // prevent calls to internal methods
401 if ( isMethodCall && options.charAt( 0 ) === "_" ) {
405 if ( isMethodCall ) {
406 this.each(function() {
407 var instance = $.data( this, name ),
408 methodValue = instance && $.isFunction( instance[options] ) ?
409 instance[ options ].apply( instance, args ) :
411 // TODO: add this back in 1.9 and use $.error() (see #5972)
412 // if ( !instance ) {
413 // throw "cannot call methods on " + name + " prior to initialization; " +
414 // "attempted to call method '" + options + "'";
416 // if ( !$.isFunction( instance[options] ) ) {
417 // throw "no such method '" + options + "' for " + name + " widget instance";
419 // var methodValue = instance[ options ].apply( instance, args );
420 if ( methodValue !== instance && methodValue !== undefined ) {
421 returnValue = methodValue;
426 this.each(function() {
427 var instance = $.data( this, name );
429 instance.option( options || {} )._init();
431 $.data( this, name, new object( options, this ) );
440 $.Widget = function( options, element ) {
441 // allow instantiation without initializing for simple inheritance
442 if ( arguments.length ) {
443 this._createWidget( options, element );
447 $.Widget.prototype = {
448 widgetName: "widget",
449 widgetEventPrefix: "",
453 _createWidget: function( options, element ) {
454 // $.widget.bridge stores the plugin instance, but we do it anyway
455 // so that it's stored even before the _create function runs
456 $.data( element, this.widgetName, this );
457 this.element = $( element );
458 this.options = $.extend( true, {},
460 this._getCreateOptions(),
464 this.element.bind( "remove." + this.widgetName, function() {
469 this._trigger( "create" );
472 _getCreateOptions: function() {
473 return $.metadata && $.metadata.get( this.element[0] )[ this.widgetName ];
475 _create: function() {},
476 _init: function() {},
478 destroy: function() {
480 .unbind( "." + this.widgetName )
481 .removeData( this.widgetName );
483 .unbind( "." + this.widgetName )
484 .removeAttr( "aria-disabled" )
486 this.widgetBaseClass + "-disabled " +
487 "ui-state-disabled" );
494 option: function( key, value ) {
497 if ( arguments.length === 0 ) {
498 // don't return a reference to the internal hash
499 return $.extend( {}, this.options );
502 if (typeof key === "string" ) {
503 if ( value === undefined ) {
504 return this.options[ key ];
507 options[ key ] = value;
510 this._setOptions( options );
514 _setOptions: function( options ) {
516 $.each( options, function( key, value ) {
517 self._setOption( key, value );
522 _setOption: function( key, value ) {
523 this.options[ key ] = value;
525 if ( key === "disabled" ) {
527 [ value ? "addClass" : "removeClass"](
528 this.widgetBaseClass + "-disabled" + " " +
529 "ui-state-disabled" )
530 .attr( "aria-disabled", value );
537 return this._setOption( "disabled", false );
539 disable: function() {
540 return this._setOption( "disabled", true );
543 _trigger: function( type, event, data ) {
544 var callback = this.options[ type ];
546 event = $.Event( event );
547 event.type = ( type === this.widgetEventPrefix ?
549 this.widgetEventPrefix + type ).toLowerCase();
552 // copy original event properties over to the new event
553 // this would happen if we could call $.event.fix instead of $.Event
554 // but we don't have a way to force an event to be fixed multiple times
555 if ( event.originalEvent ) {
556 for ( var i = $.event.props.length, prop; i; ) {
557 prop = $.event.props[ --i ];
558 event[ prop ] = event.originalEvent[ prop ];
562 this.element.trigger( event, data );
564 return !( $.isFunction(callback) &&
565 callback.call( this.element[0], event, data ) === false ||
566 event.isDefaultPrevented() );
572 * jQuery UI Mouse 1.8.10
574 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
575 * Dual licensed under the MIT or GPL Version 2 licenses.
576 * http://jquery.org/license
578 * http://docs.jquery.com/UI/Mouse
581 * jquery.ui.widget.js
583 (function( $, undefined ) {
585 $.widget("ui.mouse", {
587 cancel: ':input,option',
591 _mouseInit: function() {
595 .bind('mousedown.'+this.widgetName, function(event) {
596 return self._mouseDown(event);
598 .bind('click.'+this.widgetName, function(event) {
599 if (true === $.data(event.target, self.widgetName + '.preventClickEvent')) {
600 $.removeData(event.target, self.widgetName + '.preventClickEvent');
601 event.stopImmediatePropagation();
606 this.started = false;
609 // TODO: make sure destroying one instance of mouse doesn't mess with
610 // other instances of mouse
611 _mouseDestroy: function() {
612 this.element.unbind('.'+this.widgetName);
615 _mouseDown: function(event) {
616 // don't let more than one widget handle mouseStart
617 // TODO: figure out why we have to use originalEvent
618 event.originalEvent = event.originalEvent || {};
619 if (event.originalEvent.mouseHandled) { return; }
621 // we may have missed mouseup (out of window)
622 (this._mouseStarted && this._mouseUp(event));
624 this._mouseDownEvent = event;
627 btnIsLeft = (event.which == 1),
628 elIsCancel = (typeof this.options.cancel == "string" ? $(event.target).parents().add(event.target).filter(this.options.cancel).length : false);
629 if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
633 this.mouseDelayMet = !this.options.delay;
634 if (!this.mouseDelayMet) {
635 this._mouseDelayTimer = setTimeout(function() {
636 self.mouseDelayMet = true;
637 }, this.options.delay);
640 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
641 this._mouseStarted = (this._mouseStart(event) !== false);
642 if (!this._mouseStarted) {
643 event.preventDefault();
648 // these delegates are required to keep context
649 this._mouseMoveDelegate = function(event) {
650 return self._mouseMove(event);
652 this._mouseUpDelegate = function(event) {
653 return self._mouseUp(event);
656 .bind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
657 .bind('mouseup.'+this.widgetName, this._mouseUpDelegate);
659 event.preventDefault();
660 event.originalEvent.mouseHandled = true;
664 _mouseMove: function(event) {
665 // IE mouseup check - mouseup happened when mouse was out of window
666 if ($.browser.msie && !(document.documentMode >= 9) && !event.button) {
667 return this._mouseUp(event);
670 if (this._mouseStarted) {
671 this._mouseDrag(event);
672 return event.preventDefault();
675 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
677 (this._mouseStart(this._mouseDownEvent, event) !== false);
678 (this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
681 return !this._mouseStarted;
684 _mouseUp: function(event) {
686 .unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
687 .unbind('mouseup.'+this.widgetName, this._mouseUpDelegate);
689 if (this._mouseStarted) {
690 this._mouseStarted = false;
692 if (event.target == this._mouseDownEvent.target) {
693 $.data(event.target, this.widgetName + '.preventClickEvent', true);
696 this._mouseStop(event);
702 _mouseDistanceMet: function(event) {
704 Math.abs(this._mouseDownEvent.pageX - event.pageX),
705 Math.abs(this._mouseDownEvent.pageY - event.pageY)
706 ) >= this.options.distance
710 _mouseDelayMet: function(event) {
711 return this.mouseDelayMet;
714 // These are placeholder methods, to be overriden by extending plugin
715 _mouseStart: function(event) {},
716 _mouseDrag: function(event) {},
717 _mouseStop: function(event) {},
718 _mouseCapture: function(event) { return true; }
723 * jQuery UI Position 1.8.10
725 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
726 * Dual licensed under the MIT or GPL Version 2 licenses.
727 * http://jquery.org/license
729 * http://docs.jquery.com/UI/Position
731 (function( $, undefined ) {
735 var horizontalPositions = /left|center|right/,
736 verticalPositions = /top|center|bottom/,
738 _position = $.fn.position,
739 _offset = $.fn.offset;
741 $.fn.position = function( options ) {
742 if ( !options || !options.of ) {
743 return _position.apply( this, arguments );
746 // make a copy, we don't want to modify arguments
747 options = $.extend( {}, options );
749 var target = $( options.of ),
750 targetElem = target[0],
751 collision = ( options.collision || "flip" ).split( " " ),
752 offset = options.offset ? options.offset.split( " " ) : [ 0, 0 ],
757 if ( targetElem.nodeType === 9 ) {
758 targetWidth = target.width();
759 targetHeight = target.height();
760 basePosition = { top: 0, left: 0 };
761 // TODO: use $.isWindow() in 1.9
762 } else if ( targetElem.setTimeout ) {
763 targetWidth = target.width();
764 targetHeight = target.height();
765 basePosition = { top: target.scrollTop(), left: target.scrollLeft() };
766 } else if ( targetElem.preventDefault ) {
767 // force left top to allow flipping
768 options.at = "left top";
769 targetWidth = targetHeight = 0;
770 basePosition = { top: options.of.pageY, left: options.of.pageX };
772 targetWidth = target.outerWidth();
773 targetHeight = target.outerHeight();
774 basePosition = target.offset();
777 // force my and at to have valid horizontal and veritcal positions
778 // if a value is missing or invalid, it will be converted to center
779 $.each( [ "my", "at" ], function() {
780 var pos = ( options[this] || "" ).split( " " );
781 if ( pos.length === 1) {
782 pos = horizontalPositions.test( pos[0] ) ?
783 pos.concat( [center] ) :
784 verticalPositions.test( pos[0] ) ?
785 [ center ].concat( pos ) :
788 pos[ 0 ] = horizontalPositions.test( pos[0] ) ? pos[ 0 ] : center;
789 pos[ 1 ] = verticalPositions.test( pos[1] ) ? pos[ 1 ] : center;
790 options[ this ] = pos;
793 // normalize collision option
794 if ( collision.length === 1 ) {
795 collision[ 1 ] = collision[ 0 ];
798 // normalize offset option
799 offset[ 0 ] = parseInt( offset[0], 10 ) || 0;
800 if ( offset.length === 1 ) {
801 offset[ 1 ] = offset[ 0 ];
803 offset[ 1 ] = parseInt( offset[1], 10 ) || 0;
805 if ( options.at[0] === "right" ) {
806 basePosition.left += targetWidth;
807 } else if ( options.at[0] === center ) {
808 basePosition.left += targetWidth / 2;
811 if ( options.at[1] === "bottom" ) {
812 basePosition.top += targetHeight;
813 } else if ( options.at[1] === center ) {
814 basePosition.top += targetHeight / 2;
817 basePosition.left += offset[ 0 ];
818 basePosition.top += offset[ 1 ];
820 return this.each(function() {
821 var elem = $( this ),
822 elemWidth = elem.outerWidth(),
823 elemHeight = elem.outerHeight(),
824 marginLeft = parseInt( $.curCSS( this, "marginLeft", true ) ) || 0,
825 marginTop = parseInt( $.curCSS( this, "marginTop", true ) ) || 0,
826 collisionWidth = elemWidth + marginLeft +
827 ( parseInt( $.curCSS( this, "marginRight", true ) ) || 0 ),
828 collisionHeight = elemHeight + marginTop +
829 ( parseInt( $.curCSS( this, "marginBottom", true ) ) || 0 ),
830 position = $.extend( {}, basePosition ),
833 if ( options.my[0] === "right" ) {
834 position.left -= elemWidth;
835 } else if ( options.my[0] === center ) {
836 position.left -= elemWidth / 2;
839 if ( options.my[1] === "bottom" ) {
840 position.top -= elemHeight;
841 } else if ( options.my[1] === center ) {
842 position.top -= elemHeight / 2;
845 // prevent fractions (see #5280)
846 position.left = Math.round( position.left );
847 position.top = Math.round( position.top );
849 collisionPosition = {
850 left: position.left - marginLeft,
851 top: position.top - marginTop
854 $.each( [ "left", "top" ], function( i, dir ) {
855 if ( $.ui.position[ collision[i] ] ) {
856 $.ui.position[ collision[i] ][ dir ]( position, {
857 targetWidth: targetWidth,
858 targetHeight: targetHeight,
859 elemWidth: elemWidth,
860 elemHeight: elemHeight,
861 collisionPosition: collisionPosition,
862 collisionWidth: collisionWidth,
863 collisionHeight: collisionHeight,
871 if ( $.fn.bgiframe ) {
874 elem.offset( $.extend( position, { using: options.using } ) );
880 left: function( position, data ) {
881 var win = $( window ),
882 over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft();
883 position.left = over > 0 ? position.left - over : Math.max( position.left - data.collisionPosition.left, position.left );
885 top: function( position, data ) {
886 var win = $( window ),
887 over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop();
888 position.top = over > 0 ? position.top - over : Math.max( position.top - data.collisionPosition.top, position.top );
893 left: function( position, data ) {
894 if ( data.at[0] === center ) {
897 var win = $( window ),
898 over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft(),
899 myOffset = data.my[ 0 ] === "left" ?
901 data.my[ 0 ] === "right" ?
904 atOffset = data.at[ 0 ] === "left" ?
907 offset = -2 * data.offset[ 0 ];
908 position.left += data.collisionPosition.left < 0 ?
909 myOffset + atOffset + offset :
911 myOffset + atOffset + offset :
914 top: function( position, data ) {
915 if ( data.at[1] === center ) {
918 var win = $( window ),
919 over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop(),
920 myOffset = data.my[ 1 ] === "top" ?
922 data.my[ 1 ] === "bottom" ?
925 atOffset = data.at[ 1 ] === "top" ?
928 offset = -2 * data.offset[ 1 ];
929 position.top += data.collisionPosition.top < 0 ?
930 myOffset + atOffset + offset :
932 myOffset + atOffset + offset :
938 // offset setter from jQuery 1.4
939 if ( !$.offset.setOffset ) {
940 $.offset.setOffset = function( elem, options ) {
941 // set position first, in-case top/left are set even on static elem
942 if ( /static/.test( $.curCSS( elem, "position" ) ) ) {
943 elem.style.position = "relative";
945 var curElem = $( elem ),
946 curOffset = curElem.offset(),
947 curTop = parseInt( $.curCSS( elem, "top", true ), 10 ) || 0,
948 curLeft = parseInt( $.curCSS( elem, "left", true ), 10) || 0,
950 top: (options.top - curOffset.top) + curTop,
951 left: (options.left - curOffset.left) + curLeft
954 if ( 'using' in options ) {
955 options.using.call( elem, props );
957 curElem.css( props );
961 $.fn.offset = function( options ) {
962 var elem = this[ 0 ];
963 if ( !elem || !elem.ownerDocument ) { return null; }
965 return this.each(function() {
966 $.offset.setOffset( this, options );
969 return _offset.call( this );
975 * jQuery UI Draggable 1.8.10
977 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
978 * Dual licensed under the MIT or GPL Version 2 licenses.
979 * http://jquery.org/license
981 * http://docs.jquery.com/UI/Draggables
986 * jquery.ui.widget.js
988 (function( $, undefined ) {
990 $.widget("ui.draggable", $.ui.mouse, {
991 widgetEventPrefix: "drag",
996 connectToSortable: false,
1005 refreshPositions: false,
1007 revertDuration: 500,
1010 scrollSensitivity: 20,
1018 _create: function() {
1020 if (this.options.helper == 'original' && !(/^(?:r|a|f)/).test(this.element.css("position")))
1021 this.element[0].style.position = 'relative';
1023 (this.options.addClasses && this.element.addClass("ui-draggable"));
1024 (this.options.disabled && this.element.addClass("ui-draggable-disabled"));
1030 destroy: function() {
1031 if(!this.element.data('draggable')) return;
1033 .removeData("draggable")
1034 .unbind(".draggable")
1035 .removeClass("ui-draggable"
1036 + " ui-draggable-dragging"
1037 + " ui-draggable-disabled");
1038 this._mouseDestroy();
1043 _mouseCapture: function(event) {
1045 var o = this.options;
1047 // among others, prevent a drag on a resizable-handle
1048 if (this.helper || o.disabled || $(event.target).is('.ui-resizable-handle'))
1051 //Quit if we're not on a valid handle
1052 this.handle = this._getHandle(event);
1060 _mouseStart: function(event) {
1062 var o = this.options;
1064 //Create and append the visible helper
1065 this.helper = this._createHelper(event);
1067 //Cache the helper size
1068 this._cacheHelperProportions();
1070 //If ddmanager is used for droppables, set the global draggable
1072 $.ui.ddmanager.current = this;
1075 * - Position generation -
1076 * This block generates everything position related - it's the core of draggables.
1079 //Cache the margins of the original element
1080 this._cacheMargins();
1082 //Store the helper's css position
1083 this.cssPosition = this.helper.css("position");
1084 this.scrollParent = this.helper.scrollParent();
1086 //The element's absolute position on the page minus margins
1087 this.offset = this.positionAbs = this.element.offset();
1089 top: this.offset.top - this.margins.top,
1090 left: this.offset.left - this.margins.left
1093 $.extend(this.offset, {
1094 click: { //Where the click happened, relative to the element
1095 left: event.pageX - this.offset.left,
1096 top: event.pageY - this.offset.top
1098 parent: this._getParentOffset(),
1099 relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
1102 //Generate the original position
1103 this.originalPosition = this.position = this._generatePosition(event);
1104 this.originalPageX = event.pageX;
1105 this.originalPageY = event.pageY;
1107 //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
1108 (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
1110 //Set a containment if given in the options
1112 this._setContainment();
1114 //Trigger event + callbacks
1115 if(this._trigger("start", event) === false) {
1120 //Recache the helper size
1121 this._cacheHelperProportions();
1123 //Prepare the droppable offsets
1124 if ($.ui.ddmanager && !o.dropBehaviour)
1125 $.ui.ddmanager.prepareOffsets(this, event);
1127 this.helper.addClass("ui-draggable-dragging");
1128 this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position
1132 _mouseDrag: function(event, noPropagation) {
1134 //Compute the helpers position
1135 this.position = this._generatePosition(event);
1136 this.positionAbs = this._convertPositionTo("absolute");
1138 //Call plugins and callbacks and use the resulting position if something is returned
1139 if (!noPropagation) {
1140 var ui = this._uiHash();
1141 if(this._trigger('drag', event, ui) === false) {
1145 this.position = ui.position;
1148 if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
1149 if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
1150 if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
1155 _mouseStop: function(event) {
1157 //If we are using droppables, inform the manager about the drop
1158 var dropped = false;
1159 if ($.ui.ddmanager && !this.options.dropBehaviour)
1160 dropped = $.ui.ddmanager.drop(this, event);
1162 //if a drop comes from outside (a sortable)
1164 dropped = this.dropped;
1165 this.dropped = false;
1168 //if the original element is removed, don't bother to continue if helper is set to "original"
1169 if((!this.element[0] || !this.element[0].parentNode) && this.options.helper == "original")
1172 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))) {
1174 $(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() {
1175 if(self._trigger("stop", event) !== false) {
1180 if(this._trigger("stop", event) !== false) {
1188 cancel: function() {
1190 if(this.helper.is(".ui-draggable-dragging")) {
1200 _getHandle: function(event) {
1202 var handle = !this.options.handle || !$(this.options.handle, this.element).length ? true : false;
1203 $(this.options.handle, this.element)
1207 if(this == event.target) handle = true;
1214 _createHelper: function(event) {
1216 var o = this.options;
1217 var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper == 'clone' ? this.element.clone() : this.element);
1219 if(!helper.parents('body').length)
1220 helper.appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo));
1222 if(helper[0] != this.element[0] && !(/(fixed|absolute)/).test(helper.css("position")))
1223 helper.css("position", "absolute");
1229 _adjustOffsetFromHelper: function(obj) {
1230 if (typeof obj == 'string') {
1231 obj = obj.split(' ');
1233 if ($.isArray(obj)) {
1234 obj = {left: +obj[0], top: +obj[1] || 0};
1236 if ('left' in obj) {
1237 this.offset.click.left = obj.left + this.margins.left;
1239 if ('right' in obj) {
1240 this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
1243 this.offset.click.top = obj.top + this.margins.top;
1245 if ('bottom' in obj) {
1246 this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
1250 _getParentOffset: function() {
1252 //Get the offsetParent and cache its position
1253 this.offsetParent = this.helper.offsetParent();
1254 var po = this.offsetParent.offset();
1256 // This is a special case where we need to modify a offset calculated on start, since the following happened:
1257 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
1258 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
1259 // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
1260 if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) {
1261 po.left += this.scrollParent.scrollLeft();
1262 po.top += this.scrollParent.scrollTop();
1265 if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
1266 || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix
1267 po = { top: 0, left: 0 };
1270 top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
1271 left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
1276 _getRelativeOffset: function() {
1278 if(this.cssPosition == "relative") {
1279 var p = this.element.position();
1281 top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
1282 left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
1285 return { top: 0, left: 0 };
1290 _cacheMargins: function() {
1292 left: (parseInt(this.element.css("marginLeft"),10) || 0),
1293 top: (parseInt(this.element.css("marginTop"),10) || 0)
1297 _cacheHelperProportions: function() {
1298 this.helperProportions = {
1299 width: this.helper.outerWidth(),
1300 height: this.helper.outerHeight()
1304 _setContainment: function() {
1306 var o = this.options;
1307 if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
1308 if(o.containment == 'document' || o.containment == 'window') this.containment = [
1309 (o.containment == 'document' ? 0 : $(window).scrollLeft()) - this.offset.relative.left - this.offset.parent.left,
1310 (o.containment == 'document' ? 0 : $(window).scrollTop()) - this.offset.relative.top - this.offset.parent.top,
1311 (o.containment == 'document' ? 0 : $(window).scrollLeft()) + $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
1312 (o.containment == 'document' ? 0 : $(window).scrollTop()) + ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
1315 if(!(/^(document|window|parent)$/).test(o.containment) && o.containment.constructor != Array) {
1316 var ce = $(o.containment)[0]; if(!ce) return;
1317 var co = $(o.containment).offset();
1318 var over = ($(ce).css("overflow") != 'hidden');
1320 this.containment = [
1321 co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
1322 co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
1323 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,
1324 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
1326 } else if(o.containment.constructor == Array) {
1327 this.containment = o.containment;
1332 _convertPositionTo: function(d, pos) {
1334 if(!pos) pos = this.position;
1335 var mod = d == "absolute" ? 1 : -1;
1336 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);
1340 pos.top // The absolute mouse position
1341 + this.offset.relative.top * mod // Only for relative positioned nodes: Relative offset from element to offset parent
1342 + this.offset.parent.top * mod // The offsetParent's offset without borders (offset + border)
1343 - ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
1346 pos.left // The absolute mouse position
1347 + this.offset.relative.left * mod // Only for relative positioned nodes: Relative offset from element to offset parent
1348 + this.offset.parent.left * mod // The offsetParent's offset without borders (offset + border)
1349 - ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
1355 _generatePosition: function(event) {
1357 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);
1358 var pageX = event.pageX;
1359 var pageY = event.pageY;
1362 * - Position constraining -
1363 * Constrain the position to a mix of grid, containment.
1366 if(this.originalPosition) { //If we are not dragging yet, we won't check for options
1368 if(this.containment) {
1369 if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left;
1370 if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top;
1371 if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left;
1372 if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top;
1376 var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
1377 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;
1379 var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
1380 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;
1387 pageY // The absolute mouse position
1388 - this.offset.click.top // Click offset (relative to the element)
1389 - this.offset.relative.top // Only for relative positioned nodes: Relative offset from element to offset parent
1390 - this.offset.parent.top // The offsetParent's offset without borders (offset + border)
1391 + ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
1394 pageX // The absolute mouse position
1395 - this.offset.click.left // Click offset (relative to the element)
1396 - this.offset.relative.left // Only for relative positioned nodes: Relative offset from element to offset parent
1397 - this.offset.parent.left // The offsetParent's offset without borders (offset + border)
1398 + ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
1404 _clear: function() {
1405 this.helper.removeClass("ui-draggable-dragging");
1406 if(this.helper[0] != this.element[0] && !this.cancelHelperRemoval) this.helper.remove();
1407 //if($.ui.ddmanager) $.ui.ddmanager.current = null;
1409 this.cancelHelperRemoval = false;
1412 // From now on bulk stuff - mainly helpers
1414 _trigger: function(type, event, ui) {
1415 ui = ui || this._uiHash();
1416 $.ui.plugin.call(this, type, [event, ui]);
1417 if(type == "drag") this.positionAbs = this._convertPositionTo("absolute"); //The absolute position has to be recalculated after plugins
1418 return $.Widget.prototype._trigger.call(this, type, event, ui);
1423 _uiHash: function(event) {
1425 helper: this.helper,
1426 position: this.position,
1427 originalPosition: this.originalPosition,
1428 offset: this.positionAbs
1434 $.extend($.ui.draggable, {
1438 $.ui.plugin.add("draggable", "connectToSortable", {
1439 start: function(event, ui) {
1441 var inst = $(this).data("draggable"), o = inst.options,
1442 uiSortable = $.extend({}, ui, { item: inst.element });
1443 inst.sortables = [];
1444 $(o.connectToSortable).each(function() {
1445 var sortable = $.data(this, 'sortable');
1446 if (sortable && !sortable.options.disabled) {
1447 inst.sortables.push({
1449 shouldRevert: sortable.options.revert
1451 sortable._refreshItems(); //Do a one-time refresh at start to refresh the containerCache
1452 sortable._trigger("activate", event, uiSortable);
1457 stop: function(event, ui) {
1459 //If we are still over the sortable, we fake the stop event of the sortable, but also remove helper
1460 var inst = $(this).data("draggable"),
1461 uiSortable = $.extend({}, ui, { item: inst.element });
1463 $.each(inst.sortables, function() {
1464 if(this.instance.isOver) {
1466 this.instance.isOver = 0;
1468 inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance
1469 this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work)
1471 //The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: 'valid/invalid'
1472 if(this.shouldRevert) this.instance.options.revert = true;
1474 //Trigger the stop of the sortable
1475 this.instance._mouseStop(event);
1477 this.instance.options.helper = this.instance.options._helper;
1479 //If the helper has been the original item, restore properties in the sortable
1480 if(inst.options.helper == 'original')
1481 this.instance.currentItem.css({ top: 'auto', left: 'auto' });
1484 this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance
1485 this.instance._trigger("deactivate", event, uiSortable);
1491 drag: function(event, ui) {
1493 var inst = $(this).data("draggable"), self = this;
1495 var checkPos = function(o) {
1496 var dyClick = this.offset.click.top, dxClick = this.offset.click.left;
1497 var helperTop = this.positionAbs.top, helperLeft = this.positionAbs.left;
1498 var itemHeight = o.height, itemWidth = o.width;
1499 var itemTop = o.top, itemLeft = o.left;
1501 return $.ui.isOver(helperTop + dyClick, helperLeft + dxClick, itemTop, itemLeft, itemHeight, itemWidth);
1504 $.each(inst.sortables, function(i) {
1506 //Copy over some variables to allow calling the sortable's native _intersectsWith
1507 this.instance.positionAbs = inst.positionAbs;
1508 this.instance.helperProportions = inst.helperProportions;
1509 this.instance.offset.click = inst.offset.click;
1511 if(this.instance._intersectsWith(this.instance.containerCache)) {
1513 //If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once
1514 if(!this.instance.isOver) {
1516 this.instance.isOver = 1;
1517 //Now we fake the start of dragging for the sortable instance,
1518 //by cloning the list group item, appending it to the sortable and using it as inst.currentItem
1519 //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)
1520 this.instance.currentItem = $(self).clone().appendTo(this.instance.element).data("sortable-item", true);
1521 this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it
1522 this.instance.options.helper = function() { return ui.helper[0]; };
1524 event.target = this.instance.currentItem[0];
1525 this.instance._mouseCapture(event, true);
1526 this.instance._mouseStart(event, true, true);
1528 //Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes
1529 this.instance.offset.click.top = inst.offset.click.top;
1530 this.instance.offset.click.left = inst.offset.click.left;
1531 this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left;
1532 this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top;
1534 inst._trigger("toSortable", event);
1535 inst.dropped = this.instance.element; //draggable revert needs that
1536 //hack so receive/update callbacks work (mostly)
1537 inst.currentItem = inst.element;
1538 this.instance.fromOutside = inst;
1542 //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
1543 if(this.instance.currentItem) this.instance._mouseDrag(event);
1547 //If it doesn't intersect with the sortable, and it intersected before,
1548 //we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval
1549 if(this.instance.isOver) {
1551 this.instance.isOver = 0;
1552 this.instance.cancelHelperRemoval = true;
1554 //Prevent reverting on this forced stop
1555 this.instance.options.revert = false;
1557 // The out event needs to be triggered independently
1558 this.instance._trigger('out', event, this.instance._uiHash(this.instance));
1560 this.instance._mouseStop(event, true);
1561 this.instance.options.helper = this.instance.options._helper;
1563 //Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size
1564 this.instance.currentItem.remove();
1565 if(this.instance.placeholder) this.instance.placeholder.remove();
1567 inst._trigger("fromSortable", event);
1568 inst.dropped = false; //draggable revert needs that
1578 $.ui.plugin.add("draggable", "cursor", {
1579 start: function(event, ui) {
1580 var t = $('body'), o = $(this).data('draggable').options;
1581 if (t.css("cursor")) o._cursor = t.css("cursor");
1582 t.css("cursor", o.cursor);
1584 stop: function(event, ui) {
1585 var o = $(this).data('draggable').options;
1586 if (o._cursor) $('body').css("cursor", o._cursor);
1590 $.ui.plugin.add("draggable", "iframeFix", {
1591 start: function(event, ui) {
1592 var o = $(this).data('draggable').options;
1593 $(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() {
1594 $('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>')
1596 width: this.offsetWidth+"px", height: this.offsetHeight+"px",
1597 position: "absolute", opacity: "0.001", zIndex: 1000
1599 .css($(this).offset())
1603 stop: function(event, ui) {
1604 $("div.ui-draggable-iframeFix").each(function() { this.parentNode.removeChild(this); }); //Remove frame helpers
1608 $.ui.plugin.add("draggable", "opacity", {
1609 start: function(event, ui) {
1610 var t = $(ui.helper), o = $(this).data('draggable').options;
1611 if(t.css("opacity")) o._opacity = t.css("opacity");
1612 t.css('opacity', o.opacity);
1614 stop: function(event, ui) {
1615 var o = $(this).data('draggable').options;
1616 if(o._opacity) $(ui.helper).css('opacity', o._opacity);
1620 $.ui.plugin.add("draggable", "scroll", {
1621 start: function(event, ui) {
1622 var i = $(this).data("draggable");
1623 if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') i.overflowOffset = i.scrollParent.offset();
1625 drag: function(event, ui) {
1627 var i = $(this).data("draggable"), o = i.options, scrolled = false;
1629 if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') {
1631 if(!o.axis || o.axis != 'x') {
1632 if((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
1633 i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed;
1634 else if(event.pageY - i.overflowOffset.top < o.scrollSensitivity)
1635 i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed;
1638 if(!o.axis || o.axis != 'y') {
1639 if((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
1640 i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed;
1641 else if(event.pageX - i.overflowOffset.left < o.scrollSensitivity)
1642 i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed;
1647 if(!o.axis || o.axis != 'x') {
1648 if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
1649 scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
1650 else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
1651 scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
1654 if(!o.axis || o.axis != 'y') {
1655 if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
1656 scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
1657 else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
1658 scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
1663 if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
1664 $.ui.ddmanager.prepareOffsets(i, event);
1669 $.ui.plugin.add("draggable", "snap", {
1670 start: function(event, ui) {
1672 var i = $(this).data("draggable"), o = i.options;
1673 i.snapElements = [];
1675 $(o.snap.constructor != String ? ( o.snap.items || ':data(draggable)' ) : o.snap).each(function() {
1676 var $t = $(this); var $o = $t.offset();
1677 if(this != i.element[0]) i.snapElements.push({
1679 width: $t.outerWidth(), height: $t.outerHeight(),
1680 top: $o.top, left: $o.left
1685 drag: function(event, ui) {
1687 var inst = $(this).data("draggable"), o = inst.options;
1688 var d = o.snapTolerance;
1690 var x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
1691 y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
1693 for (var i = inst.snapElements.length - 1; i >= 0; i--){
1695 var l = inst.snapElements[i].left, r = l + inst.snapElements[i].width,
1696 t = inst.snapElements[i].top, b = t + inst.snapElements[i].height;
1698 //Yes, I know, this is insane ;)
1699 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))) {
1700 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 })));
1701 inst.snapElements[i].snapping = false;
1705 if(o.snapMode != 'inner') {
1706 var ts = Math.abs(t - y2) <= d;
1707 var bs = Math.abs(b - y1) <= d;
1708 var ls = Math.abs(l - x2) <= d;
1709 var rs = Math.abs(r - x1) <= d;
1710 if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
1711 if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top;
1712 if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left;
1713 if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left;
1716 var first = (ts || bs || ls || rs);
1718 if(o.snapMode != 'outer') {
1719 var ts = Math.abs(t - y1) <= d;
1720 var bs = Math.abs(b - y2) <= d;
1721 var ls = Math.abs(l - x1) <= d;
1722 var rs = Math.abs(r - x2) <= d;
1723 if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top;
1724 if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
1725 if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left;
1726 if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left;
1729 if(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first))
1730 (inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
1731 inst.snapElements[i].snapping = (ts || bs || ls || rs || first);
1738 $.ui.plugin.add("draggable", "stack", {
1739 start: function(event, ui) {
1741 var o = $(this).data("draggable").options;
1743 var group = $.makeArray($(o.stack)).sort(function(a,b) {
1744 return (parseInt($(a).css("zIndex"),10) || 0) - (parseInt($(b).css("zIndex"),10) || 0);
1746 if (!group.length) { return; }
1748 var min = parseInt(group[0].style.zIndex) || 0;
1749 $(group).each(function(i) {
1750 this.style.zIndex = min + i;
1753 this[0].style.zIndex = min + group.length;
1758 $.ui.plugin.add("draggable", "zIndex", {
1759 start: function(event, ui) {
1760 var t = $(ui.helper), o = $(this).data("draggable").options;
1761 if(t.css("zIndex")) o._zIndex = t.css("zIndex");
1762 t.css('zIndex', o.zIndex);
1764 stop: function(event, ui) {
1765 var o = $(this).data("draggable").options;
1766 if(o._zIndex) $(ui.helper).css('zIndex', o._zIndex);
1772 * jQuery UI Droppable 1.8.10
1774 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
1775 * Dual licensed under the MIT or GPL Version 2 licenses.
1776 * http://jquery.org/license
1778 * http://docs.jquery.com/UI/Droppables
1782 * jquery.ui.widget.js
1783 * jquery.ui.mouse.js
1784 * jquery.ui.draggable.js
1786 (function( $, undefined ) {
1788 $.widget("ui.droppable", {
1789 widgetEventPrefix: "drop",
1797 tolerance: 'intersect'
1799 _create: function() {
1801 var o = this.options, accept = o.accept;
1802 this.isover = 0; this.isout = 1;
1804 this.accept = $.isFunction(accept) ? accept : function(d) {
1805 return d.is(accept);
1808 //Store the droppable's proportions
1809 this.proportions = { width: this.element[0].offsetWidth, height: this.element[0].offsetHeight };
1811 // Add the reference and positions to the manager
1812 $.ui.ddmanager.droppables[o.scope] = $.ui.ddmanager.droppables[o.scope] || [];
1813 $.ui.ddmanager.droppables[o.scope].push(this);
1815 (o.addClasses && this.element.addClass("ui-droppable"));
1819 destroy: function() {
1820 var drop = $.ui.ddmanager.droppables[this.options.scope];
1821 for ( var i = 0; i < drop.length; i++ )
1822 if ( drop[i] == this )
1826 .removeClass("ui-droppable ui-droppable-disabled")
1827 .removeData("droppable")
1828 .unbind(".droppable");
1833 _setOption: function(key, value) {
1835 if(key == 'accept') {
1836 this.accept = $.isFunction(value) ? value : function(d) {
1840 $.Widget.prototype._setOption.apply(this, arguments);
1843 _activate: function(event) {
1844 var draggable = $.ui.ddmanager.current;
1845 if(this.options.activeClass) this.element.addClass(this.options.activeClass);
1846 (draggable && this._trigger('activate', event, this.ui(draggable)));
1849 _deactivate: function(event) {
1850 var draggable = $.ui.ddmanager.current;
1851 if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
1852 (draggable && this._trigger('deactivate', event, this.ui(draggable)));
1855 _over: function(event) {
1857 var draggable = $.ui.ddmanager.current;
1858 if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
1860 if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
1861 if(this.options.hoverClass) this.element.addClass(this.options.hoverClass);
1862 this._trigger('over', event, this.ui(draggable));
1867 _out: function(event) {
1869 var draggable = $.ui.ddmanager.current;
1870 if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
1872 if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
1873 if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
1874 this._trigger('out', event, this.ui(draggable));
1879 _drop: function(event,custom) {
1881 var draggable = custom || $.ui.ddmanager.current;
1882 if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return false; // Bail if draggable and droppable are same element
1884 var childrenIntersection = false;
1885 this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function() {
1886 var inst = $.data(this, 'droppable');
1889 && !inst.options.disabled
1890 && inst.options.scope == draggable.options.scope
1891 && inst.accept.call(inst.element[0], (draggable.currentItem || draggable.element))
1892 && $.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance)
1893 ) { childrenIntersection = true; return false; }
1895 if(childrenIntersection) return false;
1897 if(this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
1898 if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
1899 if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
1900 this._trigger('drop', event, this.ui(draggable));
1901 return this.element;
1910 draggable: (c.currentItem || c.element),
1912 position: c.position,
1913 offset: c.positionAbs
1919 $.extend($.ui.droppable, {
1923 $.ui.intersect = function(draggable, droppable, toleranceMode) {
1925 if (!droppable.offset) return false;
1927 var x1 = (draggable.positionAbs || draggable.position.absolute).left, x2 = x1 + draggable.helperProportions.width,
1928 y1 = (draggable.positionAbs || draggable.position.absolute).top, y2 = y1 + draggable.helperProportions.height;
1929 var l = droppable.offset.left, r = l + droppable.proportions.width,
1930 t = droppable.offset.top, b = t + droppable.proportions.height;
1932 switch (toleranceMode) {
1934 return (l <= x1 && x2 <= r
1935 && t <= y1 && y2 <= b);
1938 return (l < x1 + (draggable.helperProportions.width / 2) // Right Half
1939 && x2 - (draggable.helperProportions.width / 2) < r // Left Half
1940 && t < y1 + (draggable.helperProportions.height / 2) // Bottom Half
1941 && y2 - (draggable.helperProportions.height / 2) < b ); // Top Half
1944 var draggableLeft = ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left),
1945 draggableTop = ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top),
1946 isOver = $.ui.isOver(draggableTop, draggableLeft, t, l, droppable.proportions.height, droppable.proportions.width);
1951 (y1 >= t && y1 <= b) || // Top edge touching
1952 (y2 >= t && y2 <= b) || // Bottom edge touching
1953 (y1 < t && y2 > b) // Surrounded vertically
1955 (x1 >= l && x1 <= r) || // Left edge touching
1956 (x2 >= l && x2 <= r) || // Right edge touching
1957 (x1 < l && x2 > r) // Surrounded horizontally
1968 This manager tracks offsets of draggables and droppables
1972 droppables: { 'default': [] },
1973 prepareOffsets: function(t, event) {
1975 var m = $.ui.ddmanager.droppables[t.options.scope] || [];
1976 var type = event ? event.type : null; // workaround for #2317
1977 var list = (t.currentItem || t.element).find(":data(droppable)").andSelf();
1979 droppablesLoop: for (var i = 0; i < m.length; i++) {
1981 if(m[i].options.disabled || (t && !m[i].accept.call(m[i].element[0],(t.currentItem || t.element)))) continue; //No disabled and non-accepted
1982 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
1983 m[i].visible = m[i].element.css("display") != "none"; if(!m[i].visible) continue; //If the element is not visible, continue
1985 m[i].offset = m[i].element.offset();
1986 m[i].proportions = { width: m[i].element[0].offsetWidth, height: m[i].element[0].offsetHeight };
1988 if(type == "mousedown") m[i]._activate.call(m[i], event); //Activate the droppable if used directly from draggables
1993 drop: function(draggable, event) {
1995 var dropped = false;
1996 $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
1998 if(!this.options) return;
1999 if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance))
2000 dropped = dropped || this._drop.call(this, event);
2002 if (!this.options.disabled && this.visible && this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
2003 this.isout = 1; this.isover = 0;
2004 this._deactivate.call(this, event);
2011 drag: function(draggable, event) {
2013 //If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse.
2014 if(draggable.options.refreshPositions) $.ui.ddmanager.prepareOffsets(draggable, event);
2016 //Run through all droppables and check their positions based on specific tolerance options
2017 $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
2019 if(this.options.disabled || this.greedyChild || !this.visible) return;
2020 var intersects = $.ui.intersect(draggable, this, this.options.tolerance);
2022 var c = !intersects && this.isover == 1 ? 'isout' : (intersects && this.isover == 0 ? 'isover' : null);
2026 if (this.options.greedy) {
2027 var parent = this.element.parents(':data(droppable):eq(0)');
2028 if (parent.length) {
2029 parentInstance = $.data(parent[0], 'droppable');
2030 parentInstance.greedyChild = (c == 'isover' ? 1 : 0);
2034 // we just moved into a greedy child
2035 if (parentInstance && c == 'isover') {
2036 parentInstance['isover'] = 0;
2037 parentInstance['isout'] = 1;
2038 parentInstance._out.call(parentInstance, event);
2041 this[c] = 1; this[c == 'isout' ? 'isover' : 'isout'] = 0;
2042 this[c == "isover" ? "_over" : "_out"].call(this, event);
2044 // we just moved out of a greedy child
2045 if (parentInstance && c == 'isout') {
2046 parentInstance['isout'] = 0;
2047 parentInstance['isover'] = 1;
2048 parentInstance._over.call(parentInstance, event);
2057 * jQuery UI Resizable 1.8.10
2059 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
2060 * Dual licensed under the MIT or GPL Version 2 licenses.
2061 * http://jquery.org/license
2063 * http://docs.jquery.com/UI/Resizables
2067 * jquery.ui.mouse.js
2068 * jquery.ui.widget.js
2070 (function( $, undefined ) {
2072 $.widget("ui.resizable", $.ui.mouse, {
2073 widgetEventPrefix: "resize",
2077 animateDuration: "slow",
2078 animateEasing: "swing",
2092 _create: function() {
2094 var self = this, o = this.options;
2095 this.element.addClass("ui-resizable");
2098 _aspectRatio: !!(o.aspectRatio),
2099 aspectRatio: o.aspectRatio,
2100 originalElement: this.element,
2101 _proportionallyResizeElements: [],
2102 _helper: o.helper || o.ghost || o.animate ? o.helper || 'ui-resizable-helper' : null
2105 //Wrap the element if it cannot hold child nodes
2106 if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) {
2108 //Opera fix for relative positioning
2109 if (/relative/.test(this.element.css('position')) && $.browser.opera)
2110 this.element.css({ position: 'relative', top: 'auto', left: 'auto' });
2112 //Create a wrapper element and set the wrapper to the new current internal element
2114 $('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({
2115 position: this.element.css('position'),
2116 width: this.element.outerWidth(),
2117 height: this.element.outerHeight(),
2118 top: this.element.css('top'),
2119 left: this.element.css('left')
2123 //Overwrite the original this.element
2124 this.element = this.element.parent().data(
2125 "resizable", this.element.data('resizable')
2128 this.elementIsWrapper = true;
2130 //Move margins to the wrapper
2131 this.element.css({ marginLeft: this.originalElement.css("marginLeft"), marginTop: this.originalElement.css("marginTop"), marginRight: this.originalElement.css("marginRight"), marginBottom: this.originalElement.css("marginBottom") });
2132 this.originalElement.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0});
2134 //Prevent Safari textarea resize
2135 this.originalResizeStyle = this.originalElement.css('resize');
2136 this.originalElement.css('resize', 'none');
2138 //Push the actual element to our proportionallyResize internal array
2139 this._proportionallyResizeElements.push(this.originalElement.css({ position: 'static', zoom: 1, display: 'block' }));
2141 // avoid IE jump (hard set the margin)
2142 this.originalElement.css({ margin: this.originalElement.css('margin') });
2144 // fix handlers offset
2145 this._proportionallyResize();
2149 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' });
2150 if(this.handles.constructor == String) {
2152 if(this.handles == 'all') this.handles = 'n,e,s,w,se,sw,ne,nw';
2153 var n = this.handles.split(","); this.handles = {};
2155 for(var i = 0; i < n.length; i++) {
2157 var handle = $.trim(n[i]), hname = 'ui-resizable-'+handle;
2158 var axis = $('<div class="ui-resizable-handle ' + hname + '"></div>');
2160 // increase zIndex of sw, se, ne, nw axis
2161 //TODO : this modifies original option
2162 if(/sw|se|ne|nw/.test(handle)) axis.css({ zIndex: ++o.zIndex });
2164 //TODO : What's going on here?
2165 if ('se' == handle) {
2166 axis.addClass('ui-icon ui-icon-gripsmall-diagonal-se');
2169 //Insert into internal handles object and append to element
2170 this.handles[handle] = '.ui-resizable-'+handle;
2171 this.element.append(axis);
2176 this._renderAxis = function(target) {
2178 target = target || this.element;
2180 for(var i in this.handles) {
2182 if(this.handles[i].constructor == String)
2183 this.handles[i] = $(this.handles[i], this.element).show();
2185 //Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls)
2186 if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) {
2188 var axis = $(this.handles[i], this.element), padWrapper = 0;
2190 //Checking the correct pad and border
2191 padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth();
2193 //The padding type i have to apply...
2194 var padPos = [ 'padding',
2195 /ne|nw|n/.test(i) ? 'Top' :
2196 /se|sw|s/.test(i) ? 'Bottom' :
2197 /^e$/.test(i) ? 'Right' : 'Left' ].join("");
2199 target.css(padPos, padWrapper);
2201 this._proportionallyResize();
2205 //TODO: What's that good for? There's not anything to be executed left
2206 if(!$(this.handles[i]).length)
2212 //TODO: make renderAxis a prototype function
2213 this._renderAxis(this.element);
2215 this._handles = $('.ui-resizable-handle', this.element)
2216 .disableSelection();
2218 //Matching axis name
2219 this._handles.mouseover(function() {
2220 if (!self.resizing) {
2222 var axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);
2223 //Axis, default = se
2224 self.axis = axis && axis[1] ? axis[1] : 'se';
2228 //If we want to auto hide the elements
2230 this._handles.hide();
2232 .addClass("ui-resizable-autohide")
2234 $(this).removeClass("ui-resizable-autohide");
2235 self._handles.show();
2238 if (!self.resizing) {
2239 $(this).addClass("ui-resizable-autohide");
2240 self._handles.hide();
2245 //Initialize the mouse interaction
2250 destroy: function() {
2252 this._mouseDestroy();
2254 var _destroy = function(exp) {
2255 $(exp).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing")
2256 .removeData("resizable").unbind(".resizable").find('.ui-resizable-handle').remove();
2259 //TODO: Unwrap at same DOM position
2260 if (this.elementIsWrapper) {
2261 _destroy(this.element);
2262 var wrapper = this.element;
2264 this.originalElement.css({
2265 position: wrapper.css('position'),
2266 width: wrapper.outerWidth(),
2267 height: wrapper.outerHeight(),
2268 top: wrapper.css('top'),
2269 left: wrapper.css('left')
2274 this.originalElement.css('resize', this.originalResizeStyle);
2275 _destroy(this.originalElement);
2280 _mouseCapture: function(event) {
2282 for (var i in this.handles) {
2283 if ($(this.handles[i])[0] == event.target) {
2288 return !this.options.disabled && handle;
2291 _mouseStart: function(event) {
2293 var o = this.options, iniPos = this.element.position(), el = this.element;
2295 this.resizing = true;
2296 this.documentScroll = { top: $(document).scrollTop(), left: $(document).scrollLeft() };
2298 // bugfix for http://dev.jquery.com/ticket/1749
2299 if (el.is('.ui-draggable') || (/absolute/).test(el.css('position'))) {
2300 el.css({ position: 'absolute', top: iniPos.top, left: iniPos.left });
2303 //Opera fixing relative position
2304 if ($.browser.opera && (/relative/).test(el.css('position')))
2305 el.css({ position: 'relative', top: 'auto', left: 'auto' });
2307 this._renderProxy();
2309 var curleft = num(this.helper.css('left')), curtop = num(this.helper.css('top'));
2311 if (o.containment) {
2312 curleft += $(o.containment).scrollLeft() || 0;
2313 curtop += $(o.containment).scrollTop() || 0;
2316 //Store needed variables
2317 this.offset = this.helper.offset();
2318 this.position = { left: curleft, top: curtop };
2319 this.size = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
2320 this.originalSize = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
2321 this.originalPosition = { left: curleft, top: curtop };
2322 this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() };
2323 this.originalMousePosition = { left: event.pageX, top: event.pageY };
2326 this.aspectRatio = (typeof o.aspectRatio == 'number') ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1);
2328 var cursor = $('.ui-resizable-' + this.axis).css('cursor');
2329 $('body').css('cursor', cursor == 'auto' ? this.axis + '-resize' : cursor);
2331 el.addClass("ui-resizable-resizing");
2332 this._propagate("start", event);
2336 _mouseDrag: function(event) {
2338 //Increase performance, avoid regex
2339 var el = this.helper, o = this.options, props = {},
2340 self = this, smp = this.originalMousePosition, a = this.axis;
2342 var dx = (event.pageX-smp.left)||0, dy = (event.pageY-smp.top)||0;
2343 var trigger = this._change[a];
2344 if (!trigger) return false;
2346 // Calculate the attrs that will be change
2347 var data = trigger.apply(this, [event, dx, dy]), ie6 = $.browser.msie && $.browser.version < 7, csdif = this.sizeDiff;
2349 if (this._aspectRatio || event.shiftKey)
2350 data = this._updateRatio(data, event);
2352 data = this._respectSize(data, event);
2354 // plugins callbacks need to be called first
2355 this._propagate("resize", event);
2358 top: this.position.top + "px", left: this.position.left + "px",
2359 width: this.size.width + "px", height: this.size.height + "px"
2362 if (!this._helper && this._proportionallyResizeElements.length)
2363 this._proportionallyResize();
2365 this._updateCache(data);
2367 // calling the user callback at the end
2368 this._trigger('resize', event, this.ui());
2373 _mouseStop: function(event) {
2375 this.resizing = false;
2376 var o = this.options, self = this;
2379 var pr = this._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
2380 soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
2381 soffsetw = ista ? 0 : self.sizeDiff.width;
2383 var s = { width: (self.helper.width() - soffsetw), height: (self.helper.height() - soffseth) },
2384 left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
2385 top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
2388 this.element.css($.extend(s, { top: top, left: left }));
2390 self.helper.height(self.size.height);
2391 self.helper.width(self.size.width);
2393 if (this._helper && !o.animate) this._proportionallyResize();
2396 $('body').css('cursor', 'auto');
2398 this.element.removeClass("ui-resizable-resizing");
2400 this._propagate("stop", event);
2402 if (this._helper) this.helper.remove();
2407 _updateCache: function(data) {
2408 var o = this.options;
2409 this.offset = this.helper.offset();
2410 if (isNumber(data.left)) this.position.left = data.left;
2411 if (isNumber(data.top)) this.position.top = data.top;
2412 if (isNumber(data.height)) this.size.height = data.height;
2413 if (isNumber(data.width)) this.size.width = data.width;
2416 _updateRatio: function(data, event) {
2418 var o = this.options, cpos = this.position, csize = this.size, a = this.axis;
2420 if (data.height) data.width = (csize.height * this.aspectRatio);
2421 else if (data.width) data.height = (csize.width / this.aspectRatio);
2424 data.left = cpos.left + (csize.width - data.width);
2428 data.top = cpos.top + (csize.height - data.height);
2429 data.left = cpos.left + (csize.width - data.width);
2435 _respectSize: function(data, event) {
2437 var el = this.helper, o = this.options, pRatio = this._aspectRatio || event.shiftKey, a = this.axis,
2438 ismaxw = isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh = isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height),
2439 isminw = isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh = isNumber(data.height) && o.minHeight && (o.minHeight > data.height);
2441 if (isminw) data.width = o.minWidth;
2442 if (isminh) data.height = o.minHeight;
2443 if (ismaxw) data.width = o.maxWidth;
2444 if (ismaxh) data.height = o.maxHeight;
2446 var dw = this.originalPosition.left + this.originalSize.width, dh = this.position.top + this.size.height;
2447 var cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a);
2449 if (isminw && cw) data.left = dw - o.minWidth;
2450 if (ismaxw && cw) data.left = dw - o.maxWidth;
2451 if (isminh && ch) data.top = dh - o.minHeight;
2452 if (ismaxh && ch) data.top = dh - o.maxHeight;
2454 // fixing jump error on top/left - bug #2330
2455 var isNotwh = !data.width && !data.height;
2456 if (isNotwh && !data.left && data.top) data.top = null;
2457 else if (isNotwh && !data.top && data.left) data.left = null;
2462 _proportionallyResize: function() {
2464 var o = this.options;
2465 if (!this._proportionallyResizeElements.length) return;
2466 var element = this.helper || this.element;
2468 for (var i=0; i < this._proportionallyResizeElements.length; i++) {
2470 var prel = this._proportionallyResizeElements[i];
2472 if (!this.borderDif) {
2473 var b = [prel.css('borderTopWidth'), prel.css('borderRightWidth'), prel.css('borderBottomWidth'), prel.css('borderLeftWidth')],
2474 p = [prel.css('paddingTop'), prel.css('paddingRight'), prel.css('paddingBottom'), prel.css('paddingLeft')];
2476 this.borderDif = $.map(b, function(v, i) {
2477 var border = parseInt(v,10)||0, padding = parseInt(p[i],10)||0;
2478 return border + padding;
2482 if ($.browser.msie && !(!($(element).is(':hidden') || $(element).parents(':hidden').length)))
2486 height: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0,
2487 width: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0
2494 _renderProxy: function() {
2496 var el = this.element, o = this.options;
2497 this.elementOffset = el.offset();
2501 this.helper = this.helper || $('<div style="overflow:hidden;"></div>');
2503 // fix ie6 offset TODO: This seems broken
2504 var ie6 = $.browser.msie && $.browser.version < 7, ie6offset = (ie6 ? 1 : 0),
2505 pxyoffset = ( ie6 ? 2 : -1 );
2507 this.helper.addClass(this._helper).css({
2508 width: this.element.outerWidth() + pxyoffset,
2509 height: this.element.outerHeight() + pxyoffset,
2510 position: 'absolute',
2511 left: this.elementOffset.left - ie6offset +'px',
2512 top: this.elementOffset.top - ie6offset +'px',
2513 zIndex: ++o.zIndex //TODO: Don't modify option
2518 .disableSelection();
2521 this.helper = this.element;
2527 e: function(event, dx, dy) {
2528 return { width: this.originalSize.width + dx };
2530 w: function(event, dx, dy) {
2531 var o = this.options, cs = this.originalSize, sp = this.originalPosition;
2532 return { left: sp.left + dx, width: cs.width - dx };
2534 n: function(event, dx, dy) {
2535 var o = this.options, cs = this.originalSize, sp = this.originalPosition;
2536 return { top: sp.top + dy, height: cs.height - dy };
2538 s: function(event, dx, dy) {
2539 return { height: this.originalSize.height + dy };
2541 se: function(event, dx, dy) {
2542 return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
2544 sw: function(event, dx, dy) {
2545 return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
2547 ne: function(event, dx, dy) {
2548 return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
2550 nw: function(event, dx, dy) {
2551 return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
2555 _propagate: function(n, event) {
2556 $.ui.plugin.call(this, n, [event, this.ui()]);
2557 (n != "resize" && this._trigger(n, event, this.ui()));
2564 originalElement: this.originalElement,
2565 element: this.element,
2566 helper: this.helper,
2567 position: this.position,
2569 originalSize: this.originalSize,
2570 originalPosition: this.originalPosition
2576 $.extend($.ui.resizable, {
2581 * Resizable Extensions
2584 $.ui.plugin.add("resizable", "alsoResize", {
2586 start: function (event, ui) {
2587 var self = $(this).data("resizable"), o = self.options;
2589 var _store = function (exp) {
2590 $(exp).each(function() {
2592 el.data("resizable-alsoresize", {
2593 width: parseInt(el.width(), 10), height: parseInt(el.height(), 10),
2594 left: parseInt(el.css('left'), 10), top: parseInt(el.css('top'), 10),
2595 position: el.css('position') // to reset Opera on stop()
2600 if (typeof(o.alsoResize) == 'object' && !o.alsoResize.parentNode) {
2601 if (o.alsoResize.length) { o.alsoResize = o.alsoResize[0]; _store(o.alsoResize); }
2602 else { $.each(o.alsoResize, function (exp) { _store(exp); }); }
2604 _store(o.alsoResize);
2608 resize: function (event, ui) {
2609 var self = $(this).data("resizable"), o = self.options, os = self.originalSize, op = self.originalPosition;
2612 height: (self.size.height - os.height) || 0, width: (self.size.width - os.width) || 0,
2613 top: (self.position.top - op.top) || 0, left: (self.position.left - op.left) || 0
2616 _alsoResize = function (exp, c) {
2617 $(exp).each(function() {
2618 var el = $(this), start = $(this).data("resizable-alsoresize"), style = {},
2619 css = c && c.length ? c : el.parents(ui.originalElement[0]).length ? ['width', 'height'] : ['width', 'height', 'top', 'left'];
2621 $.each(css, function (i, prop) {
2622 var sum = (start[prop]||0) + (delta[prop]||0);
2623 if (sum && sum >= 0)
2624 style[prop] = sum || null;
2627 // Opera fixing relative position
2628 if ($.browser.opera && /relative/.test(el.css('position'))) {
2629 self._revertToRelativePosition = true;
2630 el.css({ position: 'absolute', top: 'auto', left: 'auto' });
2637 if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) {
2638 $.each(o.alsoResize, function (exp, c) { _alsoResize(exp, c); });
2640 _alsoResize(o.alsoResize);
2644 stop: function (event, ui) {
2645 var self = $(this).data("resizable"), o = self.options;
2647 var _reset = function (exp) {
2648 $(exp).each(function() {
2650 // reset position for Opera - no need to verify it was changed
2651 el.css({ position: el.data("resizable-alsoresize").position });
2655 if (self._revertToRelativePosition) {
2656 self._revertToRelativePosition = false;
2657 if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) {
2658 $.each(o.alsoResize, function (exp) { _reset(exp); });
2660 _reset(o.alsoResize);
2664 $(this).removeData("resizable-alsoresize");
2668 $.ui.plugin.add("resizable", "animate", {
2670 stop: function(event, ui) {
2671 var self = $(this).data("resizable"), o = self.options;
2673 var pr = self._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
2674 soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
2675 soffsetw = ista ? 0 : self.sizeDiff.width;
2677 var style = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },
2678 left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
2679 top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
2681 self.element.animate(
2682 $.extend(style, top && left ? { top: top, left: left } : {}), {
2683 duration: o.animateDuration,
2684 easing: o.animateEasing,
2688 width: parseInt(self.element.css('width'), 10),
2689 height: parseInt(self.element.css('height'), 10),
2690 top: parseInt(self.element.css('top'), 10),
2691 left: parseInt(self.element.css('left'), 10)
2694 if (pr && pr.length) $(pr[0]).css({ width: data.width, height: data.height });
2696 // propagating resize, and updating values for each animation step
2697 self._updateCache(data);
2698 self._propagate("resize", event);
2707 $.ui.plugin.add("resizable", "containment", {
2709 start: function(event, ui) {
2710 var self = $(this).data("resizable"), o = self.options, el = self.element;
2711 var oc = o.containment, ce = (oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc;
2714 self.containerElement = $(ce);
2716 if (/document/.test(oc) || oc == document) {
2717 self.containerOffset = { left: 0, top: 0 };
2718 self.containerPosition = { left: 0, top: 0 };
2721 element: $(document), left: 0, top: 0,
2722 width: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight
2726 // i'm a node, so compute top, left, right, bottom
2728 var element = $(ce), p = [];
2729 $([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) { p[i] = num(element.css("padding" + name)); });
2731 self.containerOffset = element.offset();
2732 self.containerPosition = element.position();
2733 self.containerSize = { height: (element.innerHeight() - p[3]), width: (element.innerWidth() - p[1]) };
2735 var co = self.containerOffset, ch = self.containerSize.height, cw = self.containerSize.width,
2736 width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw ), height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch);
2739 element: ce, left: co.left, top: co.top, width: width, height: height
2744 resize: function(event, ui) {
2745 var self = $(this).data("resizable"), o = self.options,
2746 ps = self.containerSize, co = self.containerOffset, cs = self.size, cp = self.position,
2747 pRatio = self._aspectRatio || event.shiftKey, cop = { top:0, left:0 }, ce = self.containerElement;
2749 if (ce[0] != document && (/static/).test(ce.css('position'))) cop = co;
2751 if (cp.left < (self._helper ? co.left : 0)) {
2752 self.size.width = self.size.width + (self._helper ? (self.position.left - co.left) : (self.position.left - cop.left));
2753 if (pRatio) self.size.height = self.size.width / o.aspectRatio;
2754 self.position.left = o.helper ? co.left : 0;
2757 if (cp.top < (self._helper ? co.top : 0)) {
2758 self.size.height = self.size.height + (self._helper ? (self.position.top - co.top) : self.position.top);
2759 if (pRatio) self.size.width = self.size.height * o.aspectRatio;
2760 self.position.top = self._helper ? co.top : 0;
2763 self.offset.left = self.parentData.left+self.position.left;
2764 self.offset.top = self.parentData.top+self.position.top;
2766 var woset = Math.abs( (self._helper ? self.offset.left - cop.left : (self.offset.left - cop.left)) + self.sizeDiff.width ),
2767 hoset = Math.abs( (self._helper ? self.offset.top - cop.top : (self.offset.top - co.top)) + self.sizeDiff.height );
2769 var isParent = self.containerElement.get(0) == self.element.parent().get(0),
2770 isOffsetRelative = /relative|absolute/.test(self.containerElement.css('position'));
2772 if(isParent && isOffsetRelative) woset -= self.parentData.left;
2774 if (woset + self.size.width >= self.parentData.width) {
2775 self.size.width = self.parentData.width - woset;
2776 if (pRatio) self.size.height = self.size.width / self.aspectRatio;
2779 if (hoset + self.size.height >= self.parentData.height) {
2780 self.size.height = self.parentData.height - hoset;
2781 if (pRatio) self.size.width = self.size.height * self.aspectRatio;
2785 stop: function(event, ui){
2786 var self = $(this).data("resizable"), o = self.options, cp = self.position,
2787 co = self.containerOffset, cop = self.containerPosition, ce = self.containerElement;
2789 var helper = $(self.helper), ho = helper.offset(), w = helper.outerWidth() - self.sizeDiff.width, h = helper.outerHeight() - self.sizeDiff.height;
2791 if (self._helper && !o.animate && (/relative/).test(ce.css('position')))
2792 $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
2794 if (self._helper && !o.animate && (/static/).test(ce.css('position')))
2795 $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
2800 $.ui.plugin.add("resizable", "ghost", {
2802 start: function(event, ui) {
2804 var self = $(this).data("resizable"), o = self.options, cs = self.size;
2806 self.ghost = self.originalElement.clone();
2808 .css({ opacity: .25, display: 'block', position: 'relative', height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 })
2809 .addClass('ui-resizable-ghost')
2810 .addClass(typeof o.ghost == 'string' ? o.ghost : '');
2812 self.ghost.appendTo(self.helper);
2816 resize: function(event, ui){
2817 var self = $(this).data("resizable"), o = self.options;
2818 if (self.ghost) self.ghost.css({ position: 'relative', height: self.size.height, width: self.size.width });
2821 stop: function(event, ui){
2822 var self = $(this).data("resizable"), o = self.options;
2823 if (self.ghost && self.helper) self.helper.get(0).removeChild(self.ghost.get(0));
2828 $.ui.plugin.add("resizable", "grid", {
2830 resize: function(event, ui) {
2831 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;
2832 o.grid = typeof o.grid == "number" ? [o.grid, o.grid] : o.grid;
2833 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);
2835 if (/^(se|s|e)$/.test(a)) {
2836 self.size.width = os.width + ox;
2837 self.size.height = os.height + oy;
2839 else if (/^(ne)$/.test(a)) {
2840 self.size.width = os.width + ox;
2841 self.size.height = os.height + oy;
2842 self.position.top = op.top - oy;
2844 else if (/^(sw)$/.test(a)) {
2845 self.size.width = os.width + ox;
2846 self.size.height = os.height + oy;
2847 self.position.left = op.left - ox;
2850 self.size.width = os.width + ox;
2851 self.size.height = os.height + oy;
2852 self.position.top = op.top - oy;
2853 self.position.left = op.left - ox;
2859 var num = function(v) {
2860 return parseInt(v, 10) || 0;
2863 var isNumber = function(value) {
2864 return !isNaN(parseInt(value, 10));
2869 * jQuery UI Selectable 1.8.10
2871 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
2872 * Dual licensed under the MIT or GPL Version 2 licenses.
2873 * http://jquery.org/license
2875 * http://docs.jquery.com/UI/Selectables
2879 * jquery.ui.mouse.js
2880 * jquery.ui.widget.js
2882 (function( $, undefined ) {
2884 $.widget("ui.selectable", $.ui.mouse, {
2892 _create: function() {
2895 this.element.addClass("ui-selectable");
2897 this.dragged = false;
2899 // cache selectee children based on filter
2901 this.refresh = function() {
2902 selectees = $(self.options.filter, self.element[0]);
2903 selectees.each(function() {
2904 var $this = $(this);
2905 var pos = $this.offset();
2906 $.data(this, "selectable-item", {
2911 right: pos.left + $this.outerWidth(),
2912 bottom: pos.top + $this.outerHeight(),
2913 startselected: false,
2914 selected: $this.hasClass('ui-selected'),
2915 selecting: $this.hasClass('ui-selecting'),
2916 unselecting: $this.hasClass('ui-unselecting')
2922 this.selectees = selectees.addClass("ui-selectee");
2926 this.helper = $("<div class='ui-selectable-helper'></div>");
2929 destroy: function() {
2931 .removeClass("ui-selectee")
2932 .removeData("selectable-item");
2934 .removeClass("ui-selectable ui-selectable-disabled")
2935 .removeData("selectable")
2936 .unbind(".selectable");
2937 this._mouseDestroy();
2942 _mouseStart: function(event) {
2945 this.opos = [event.pageX, event.pageY];
2947 if (this.options.disabled)
2950 var options = this.options;
2952 this.selectees = $(options.filter, this.element[0]);
2954 this._trigger("start", event);
2956 $(options.appendTo).append(this.helper);
2957 // position helper (lasso)
2959 "left": event.clientX,
2960 "top": event.clientY,
2965 if (options.autoRefresh) {
2969 this.selectees.filter('.ui-selected').each(function() {
2970 var selectee = $.data(this, "selectable-item");
2971 selectee.startselected = true;
2972 if (!event.metaKey) {
2973 selectee.$element.removeClass('ui-selected');
2974 selectee.selected = false;
2975 selectee.$element.addClass('ui-unselecting');
2976 selectee.unselecting = true;
2977 // selectable UNSELECTING callback
2978 self._trigger("unselecting", event, {
2979 unselecting: selectee.element
2984 $(event.target).parents().andSelf().each(function() {
2985 var selectee = $.data(this, "selectable-item");
2987 var doSelect = !event.metaKey || !selectee.$element.hasClass('ui-selected');
2989 .removeClass(doSelect ? "ui-unselecting" : "ui-selected")
2990 .addClass(doSelect ? "ui-selecting" : "ui-unselecting");
2991 selectee.unselecting = !doSelect;
2992 selectee.selecting = doSelect;
2993 selectee.selected = doSelect;
2994 // selectable (UN)SELECTING callback
2996 self._trigger("selecting", event, {
2997 selecting: selectee.element
3000 self._trigger("unselecting", event, {
3001 unselecting: selectee.element
3010 _mouseDrag: function(event) {
3012 this.dragged = true;
3014 if (this.options.disabled)
3017 var options = this.options;
3019 var x1 = this.opos[0], y1 = this.opos[1], x2 = event.pageX, y2 = event.pageY;
3020 if (x1 > x2) { var tmp = x2; x2 = x1; x1 = tmp; }
3021 if (y1 > y2) { var tmp = y2; y2 = y1; y1 = tmp; }
3022 this.helper.css({left: x1, top: y1, width: x2-x1, height: y2-y1});
3024 this.selectees.each(function() {
3025 var selectee = $.data(this, "selectable-item");
3026 //prevent helper from being selected if appendTo: selectable
3027 if (!selectee || selectee.element == self.element[0])
3030 if (options.tolerance == 'touch') {
3031 hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) );
3032 } else if (options.tolerance == 'fit') {
3033 hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2);
3038 if (selectee.selected) {
3039 selectee.$element.removeClass('ui-selected');
3040 selectee.selected = false;
3042 if (selectee.unselecting) {
3043 selectee.$element.removeClass('ui-unselecting');
3044 selectee.unselecting = false;
3046 if (!selectee.selecting) {
3047 selectee.$element.addClass('ui-selecting');
3048 selectee.selecting = true;
3049 // selectable SELECTING callback
3050 self._trigger("selecting", event, {
3051 selecting: selectee.element
3056 if (selectee.selecting) {
3057 if (event.metaKey && selectee.startselected) {
3058 selectee.$element.removeClass('ui-selecting');
3059 selectee.selecting = false;
3060 selectee.$element.addClass('ui-selected');
3061 selectee.selected = true;
3063 selectee.$element.removeClass('ui-selecting');
3064 selectee.selecting = false;
3065 if (selectee.startselected) {
3066 selectee.$element.addClass('ui-unselecting');
3067 selectee.unselecting = true;
3069 // selectable UNSELECTING callback
3070 self._trigger("unselecting", event, {
3071 unselecting: selectee.element
3075 if (selectee.selected) {
3076 if (!event.metaKey && !selectee.startselected) {
3077 selectee.$element.removeClass('ui-selected');
3078 selectee.selected = false;
3080 selectee.$element.addClass('ui-unselecting');
3081 selectee.unselecting = true;
3082 // selectable UNSELECTING callback
3083 self._trigger("unselecting", event, {
3084 unselecting: selectee.element
3094 _mouseStop: function(event) {
3097 this.dragged = false;
3099 var options = this.options;
3101 $('.ui-unselecting', this.element[0]).each(function() {
3102 var selectee = $.data(this, "selectable-item");
3103 selectee.$element.removeClass('ui-unselecting');
3104 selectee.unselecting = false;
3105 selectee.startselected = false;
3106 self._trigger("unselected", event, {
3107 unselected: selectee.element
3110 $('.ui-selecting', this.element[0]).each(function() {
3111 var selectee = $.data(this, "selectable-item");
3112 selectee.$element.removeClass('ui-selecting').addClass('ui-selected');
3113 selectee.selecting = false;
3114 selectee.selected = true;
3115 selectee.startselected = true;
3116 self._trigger("selected", event, {
3117 selected: selectee.element
3120 this._trigger("stop", event);
3122 this.helper.remove();
3129 $.extend($.ui.selectable, {
3135 * jQuery UI Sortable 1.8.10
3137 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
3138 * Dual licensed under the MIT or GPL Version 2 licenses.
3139 * http://jquery.org/license
3141 * http://docs.jquery.com/UI/Sortables
3145 * jquery.ui.mouse.js
3146 * jquery.ui.widget.js
3148 (function( $, undefined ) {
3150 $.widget("ui.sortable", $.ui.mouse, {
3151 widgetEventPrefix: "sort",
3160 forcePlaceholderSize: false,
3161 forceHelperSize: false,
3170 scrollSensitivity: 20,
3173 tolerance: "intersect",
3176 _create: function() {
3178 var o = this.options;
3179 this.containerCache = {};
3180 this.element.addClass("ui-sortable");
3185 //Let's determine if the items are floating
3186 this.floating = this.items.length ? (/left|right/).test(this.items[0].item.css('float')) : false;
3188 //Let's determine the parent's offset
3189 this.offset = this.element.offset();
3191 //Initialize mouse events for interaction
3196 destroy: function() {
3198 .removeClass("ui-sortable ui-sortable-disabled")
3199 .removeData("sortable")
3200 .unbind(".sortable");
3201 this._mouseDestroy();
3203 for ( var i = this.items.length - 1; i >= 0; i-- )
3204 this.items[i].item.removeData("sortable-item");
3209 _setOption: function(key, value){
3210 if ( key === "disabled" ) {
3211 this.options[ key ] = value;
3214 [ value ? "addClass" : "removeClass"]( "ui-sortable-disabled" );
3216 // Don't call widget base _setOption for disable as it adds ui-state-disabled class
3217 $.Widget.prototype._setOption.apply(this, arguments);
3221 _mouseCapture: function(event, overrideHandle) {
3223 if (this.reverting) {
3227 if(this.options.disabled || this.options.type == 'static') return false;
3229 //We have to refresh the items data once first
3230 this._refreshItems(event);
3232 //Find out if the clicked node (or one of its parents) is a actual item in this.items
3233 var currentItem = null, self = this, nodes = $(event.target).parents().each(function() {
3234 if($.data(this, 'sortable-item') == self) {
3235 currentItem = $(this);
3239 if($.data(event.target, 'sortable-item') == self) currentItem = $(event.target);
3241 if(!currentItem) return false;
3242 if(this.options.handle && !overrideHandle) {
3243 var validHandle = false;
3245 $(this.options.handle, currentItem).find("*").andSelf().each(function() { if(this == event.target) validHandle = true; });
3246 if(!validHandle) return false;
3249 this.currentItem = currentItem;
3250 this._removeCurrentsFromItems();
3255 _mouseStart: function(event, overrideHandle, noActivation) {
3257 var o = this.options, self = this;
3258 this.currentContainer = this;
3260 //We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture
3261 this.refreshPositions();
3263 //Create and append the visible helper
3264 this.helper = this._createHelper(event);
3266 //Cache the helper size
3267 this._cacheHelperProportions();
3270 * - Position generation -
3271 * This block generates everything position related - it's the core of draggables.
3274 //Cache the margins of the original element
3275 this._cacheMargins();
3277 //Get the next scrolling parent
3278 this.scrollParent = this.helper.scrollParent();
3280 //The element's absolute position on the page minus margins
3281 this.offset = this.currentItem.offset();
3283 top: this.offset.top - this.margins.top,
3284 left: this.offset.left - this.margins.left
3287 // Only after we got the offset, we can change the helper's position to absolute
3288 // TODO: Still need to figure out a way to make relative sorting possible
3289 this.helper.css("position", "absolute");
3290 this.cssPosition = this.helper.css("position");
3292 $.extend(this.offset, {
3293 click: { //Where the click happened, relative to the element
3294 left: event.pageX - this.offset.left,
3295 top: event.pageY - this.offset.top
3297 parent: this._getParentOffset(),
3298 relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
3301 //Generate the original position
3302 this.originalPosition = this._generatePosition(event);
3303 this.originalPageX = event.pageX;
3304 this.originalPageY = event.pageY;
3306 //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
3307 (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
3309 //Cache the former DOM position
3310 this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] };
3312 //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
3313 if(this.helper[0] != this.currentItem[0]) {
3314 this.currentItem.hide();
3317 //Create the placeholder
3318 this._createPlaceholder();
3320 //Set a containment if given in the options
3322 this._setContainment();
3324 if(o.cursor) { // cursor option
3325 if ($('body').css("cursor")) this._storedCursor = $('body').css("cursor");
3326 $('body').css("cursor", o.cursor);
3329 if(o.opacity) { // opacity option
3330 if (this.helper.css("opacity")) this._storedOpacity = this.helper.css("opacity");
3331 this.helper.css("opacity", o.opacity);
3334 if(o.zIndex) { // zIndex option
3335 if (this.helper.css("zIndex")) this._storedZIndex = this.helper.css("zIndex");
3336 this.helper.css("zIndex", o.zIndex);
3340 if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML')
3341 this.overflowOffset = this.scrollParent.offset();
3344 this._trigger("start", event, this._uiHash());
3346 //Recache the helper size
3347 if(!this._preserveHelperProportions)
3348 this._cacheHelperProportions();
3351 //Post 'activate' events to possible containers
3353 for (var i = this.containers.length - 1; i >= 0; i--) { this.containers[i]._trigger("activate", event, self._uiHash(this)); }
3356 //Prepare possible droppables
3358 $.ui.ddmanager.current = this;
3360 if ($.ui.ddmanager && !o.dropBehaviour)
3361 $.ui.ddmanager.prepareOffsets(this, event);
3363 this.dragging = true;
3365 this.helper.addClass("ui-sortable-helper");
3366 this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position
3371 _mouseDrag: function(event) {
3373 //Compute the helpers position
3374 this.position = this._generatePosition(event);
3375 this.positionAbs = this._convertPositionTo("absolute");
3377 if (!this.lastPositionAbs) {
3378 this.lastPositionAbs = this.positionAbs;
3382 if(this.options.scroll) {
3383 var o = this.options, scrolled = false;
3384 if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') {
3386 if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
3387 this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed;
3388 else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity)
3389 this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed;
3391 if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
3392 this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed;
3393 else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity)
3394 this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed;
3398 if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
3399 scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
3400 else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
3401 scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
3403 if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
3404 scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
3405 else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
3406 scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
3410 if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
3411 $.ui.ddmanager.prepareOffsets(this, event);
3414 //Regenerate the absolute position used for position checks
3415 this.positionAbs = this._convertPositionTo("absolute");
3417 //Set the helper position
3418 if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
3419 if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
3422 for (var i = this.items.length - 1; i >= 0; i--) {
3424 //Cache variables and intersection, continue if no intersection
3425 var item = this.items[i], itemElement = item.item[0], intersection = this._intersectsWithPointer(item);
3426 if (!intersection) continue;
3428 if(itemElement != this.currentItem[0] //cannot intersect with itself
3429 && this.placeholder[intersection == 1 ? "next" : "prev"]()[0] != itemElement //no useless actions that have been done before
3430 && !$.ui.contains(this.placeholder[0], itemElement) //no action if the item moved is the parent of the item checked
3431 && (this.options.type == 'semi-dynamic' ? !$.ui.contains(this.element[0], itemElement) : true)
3432 //&& itemElement.parentNode == this.placeholder[0].parentNode // only rearrange items within the same container
3435 this.direction = intersection == 1 ? "down" : "up";
3437 if (this.options.tolerance == "pointer" || this._intersectsWithSides(item)) {
3438 this._rearrange(event, item);
3443 this._trigger("change", event, this._uiHash());
3448 //Post events to containers
3449 this._contactContainers(event);
3451 //Interconnect with droppables
3452 if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
3455 this._trigger('sort', event, this._uiHash());
3457 this.lastPositionAbs = this.positionAbs;
3462 _mouseStop: function(event, noPropagation) {
3466 //If we are using droppables, inform the manager about the drop
3467 if ($.ui.ddmanager && !this.options.dropBehaviour)
3468 $.ui.ddmanager.drop(this, event);
3470 if(this.options.revert) {
3472 var cur = self.placeholder.offset();
3474 self.reverting = true;
3476 $(this.helper).animate({
3477 left: cur.left - this.offset.parent.left - self.margins.left + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollLeft),
3478 top: cur.top - this.offset.parent.top - self.margins.top + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollTop)
3479 }, parseInt(this.options.revert, 10) || 500, function() {
3483 this._clear(event, noPropagation);
3490 cancel: function() {
3496 this._mouseUp({ target: null });
3498 if(this.options.helper == "original")
3499 this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
3501 this.currentItem.show();
3503 //Post deactivating events to containers
3504 for (var i = this.containers.length - 1; i >= 0; i--){
3505 this.containers[i]._trigger("deactivate", null, self._uiHash(this));
3506 if(this.containers[i].containerCache.over) {
3507 this.containers[i]._trigger("out", null, self._uiHash(this));
3508 this.containers[i].containerCache.over = 0;
3514 if (this.placeholder) {
3515 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
3516 if(this.placeholder[0].parentNode) this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
3517 if(this.options.helper != "original" && this.helper && this.helper[0].parentNode) this.helper.remove();
3526 if(this.domPosition.prev) {
3527 $(this.domPosition.prev).after(this.currentItem);
3529 $(this.domPosition.parent).prepend(this.currentItem);
3537 serialize: function(o) {
3539 var items = this._getItemsAsjQuery(o && o.connected);
3540 var str = []; o = o || {};
3542 $(items).each(function() {
3543 var res = ($(o.item || this).attr(o.attribute || 'id') || '').match(o.expression || (/(.+)[-=_](.+)/));
3544 if(res) str.push((o.key || res[1]+'[]')+'='+(o.key && o.expression ? res[1] : res[2]));
3547 if(!str.length && o.key) {
3548 str.push(o.key + '=');
3551 return str.join('&');
3555 toArray: function(o) {
3557 var items = this._getItemsAsjQuery(o && o.connected);
3558 var ret = []; o = o || {};
3560 items.each(function() { ret.push($(o.item || this).attr(o.attribute || 'id') || ''); });
3565 /* Be careful with the following core functions */
3566 _intersectsWith: function(item) {
3568 var x1 = this.positionAbs.left,
3569 x2 = x1 + this.helperProportions.width,
3570 y1 = this.positionAbs.top,
3571 y2 = y1 + this.helperProportions.height;
3576 b = t + item.height;
3578 var dyClick = this.offset.click.top,
3579 dxClick = this.offset.click.left;
3581 var isOverElement = (y1 + dyClick) > t && (y1 + dyClick) < b && (x1 + dxClick) > l && (x1 + dxClick) < r;
3583 if( this.options.tolerance == "pointer"
3584 || this.options.forcePointerForContainers
3585 || (this.options.tolerance != "pointer" && this.helperProportions[this.floating ? 'width' : 'height'] > item[this.floating ? 'width' : 'height'])
3587 return isOverElement;
3590 return (l < x1 + (this.helperProportions.width / 2) // Right Half
3591 && x2 - (this.helperProportions.width / 2) < r // Left Half
3592 && t < y1 + (this.helperProportions.height / 2) // Bottom Half
3593 && y2 - (this.helperProportions.height / 2) < b ); // Top Half
3598 _intersectsWithPointer: function(item) {
3600 var isOverElementHeight = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height),
3601 isOverElementWidth = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width),
3602 isOverElement = isOverElementHeight && isOverElementWidth,
3603 verticalDirection = this._getDragVerticalDirection(),
3604 horizontalDirection = this._getDragHorizontalDirection();
3609 return this.floating ?
3610 ( ((horizontalDirection && horizontalDirection == "right") || verticalDirection == "down") ? 2 : 1 )
3611 : ( verticalDirection && (verticalDirection == "down" ? 2 : 1) );
3615 _intersectsWithSides: function(item) {
3617 var isOverBottomHalf = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height),
3618 isOverRightHalf = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width),
3619 verticalDirection = this._getDragVerticalDirection(),
3620 horizontalDirection = this._getDragHorizontalDirection();
3622 if (this.floating && horizontalDirection) {
3623 return ((horizontalDirection == "right" && isOverRightHalf) || (horizontalDirection == "left" && !isOverRightHalf));
3625 return verticalDirection && ((verticalDirection == "down" && isOverBottomHalf) || (verticalDirection == "up" && !isOverBottomHalf));
3630 _getDragVerticalDirection: function() {
3631 var delta = this.positionAbs.top - this.lastPositionAbs.top;
3632 return delta != 0 && (delta > 0 ? "down" : "up");
3635 _getDragHorizontalDirection: function() {
3636 var delta = this.positionAbs.left - this.lastPositionAbs.left;
3637 return delta != 0 && (delta > 0 ? "right" : "left");
3640 refresh: function(event) {
3641 this._refreshItems(event);
3642 this.refreshPositions();
3646 _connectWith: function() {
3647 var options = this.options;
3648 return options.connectWith.constructor == String
3649 ? [options.connectWith]
3650 : options.connectWith;
3653 _getItemsAsjQuery: function(connected) {
3658 var connectWith = this._connectWith();
3660 if(connectWith && connected) {
3661 for (var i = connectWith.length - 1; i >= 0; i--){
3662 var cur = $(connectWith[i]);
3663 for (var j = cur.length - 1; j >= 0; j--){
3664 var inst = $.data(cur[j], 'sortable');
3665 if(inst && inst != this && !inst.options.disabled) {
3666 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]);
3672 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]);
3674 for (var i = queries.length - 1; i >= 0; i--){
3675 queries[i][0].each(function() {
3684 _removeCurrentsFromItems: function() {
3686 var list = this.currentItem.find(":data(sortable-item)");
3688 for (var i=0; i < this.items.length; i++) {
3690 for (var j=0; j < list.length; j++) {
3691 if(list[j] == this.items[i].item[0])
3692 this.items.splice(i,1);
3699 _refreshItems: function(event) {
3702 this.containers = [this];
3703 var items = this.items;
3705 var queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]];
3706 var connectWith = this._connectWith();
3709 for (var i = connectWith.length - 1; i >= 0; i--){
3710 var cur = $(connectWith[i]);
3711 for (var j = cur.length - 1; j >= 0; j--){
3712 var inst = $.data(cur[j], 'sortable');
3713 if(inst && inst != this && !inst.options.disabled) {
3714 queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]);
3715 this.containers.push(inst);
3721 for (var i = queries.length - 1; i >= 0; i--) {
3722 var targetData = queries[i][1];
3723 var _queries = queries[i][0];
3725 for (var j=0, queriesLength = _queries.length; j < queriesLength; j++) {
3726 var item = $(_queries[j]);
3728 item.data('sortable-item', targetData); // Data for target checking (mouse manager)
3732 instance: targetData,
3733 width: 0, height: 0,
3741 refreshPositions: function(fast) {
3743 //This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change
3744 if(this.offsetParent && this.helper) {
3745 this.offset.parent = this._getParentOffset();
3748 for (var i = this.items.length - 1; i >= 0; i--){
3749 var item = this.items[i];
3751 var t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item;
3754 item.width = t.outerWidth();
3755 item.height = t.outerHeight();
3763 if(this.options.custom && this.options.custom.refreshContainers) {
3764 this.options.custom.refreshContainers.call(this);
3766 for (var i = this.containers.length - 1; i >= 0; i--){
3767 var p = this.containers[i].element.offset();
3768 this.containers[i].containerCache.left = p.left;
3769 this.containers[i].containerCache.top = p.top;
3770 this.containers[i].containerCache.width = this.containers[i].element.outerWidth();
3771 this.containers[i].containerCache.height = this.containers[i].element.outerHeight();
3778 _createPlaceholder: function(that) {
3780 var self = that || this, o = self.options;
3782 if(!o.placeholder || o.placeholder.constructor == String) {
3783 var className = o.placeholder;
3785 element: function() {
3787 var el = $(document.createElement(self.currentItem[0].nodeName))
3788 .addClass(className || self.currentItem[0].className+" ui-sortable-placeholder")
3789 .removeClass("ui-sortable-helper")[0];
3792 el.style.visibility = "hidden";
3796 update: function(container, p) {
3798 // 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that
3799 // 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified
3800 if(className && !o.forcePlaceholderSize) return;
3802 //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
3803 if(!p.height()) { p.height(self.currentItem.innerHeight() - parseInt(self.currentItem.css('paddingTop')||0, 10) - parseInt(self.currentItem.css('paddingBottom')||0, 10)); };
3804 if(!p.width()) { p.width(self.currentItem.innerWidth() - parseInt(self.currentItem.css('paddingLeft')||0, 10) - parseInt(self.currentItem.css('paddingRight')||0, 10)); };
3809 //Create the placeholder
3810 self.placeholder = $(o.placeholder.element.call(self.element, self.currentItem));
3812 //Append it after the actual current item
3813 self.currentItem.after(self.placeholder);
3815 //Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
3816 o.placeholder.update(self, self.placeholder);
3820 _contactContainers: function(event) {
3822 // get innermost container that intersects with item
3823 var innermostContainer = null, innermostIndex = null;
3826 for (var i = this.containers.length - 1; i >= 0; i--){
3828 // never consider a container that's located within the item itself
3829 if($.ui.contains(this.currentItem[0], this.containers[i].element[0]))
3832 if(this._intersectsWith(this.containers[i].containerCache)) {
3834 // if we've already found a container and it's more "inner" than this, then continue
3835 if(innermostContainer && $.ui.contains(this.containers[i].element[0], innermostContainer.element[0]))
3838 innermostContainer = this.containers[i];
3842 // container doesn't intersect. trigger "out" event if necessary
3843 if(this.containers[i].containerCache.over) {
3844 this.containers[i]._trigger("out", event, this._uiHash(this));
3845 this.containers[i].containerCache.over = 0;
3851 // if no intersecting containers found, return
3852 if(!innermostContainer) return;
3854 // move the item into the container if it's not there already
3855 if(this.containers.length === 1) {
3856 this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
3857 this.containers[innermostIndex].containerCache.over = 1;
3858 } else if(this.currentContainer != this.containers[innermostIndex]) {
3860 //When entering a new container, we will find the item with the least distance and append our item near it
3861 var dist = 10000; var itemWithLeastDistance = null; var base = this.positionAbs[this.containers[innermostIndex].floating ? 'left' : 'top'];
3862 for (var j = this.items.length - 1; j >= 0; j--) {
3863 if(!$.ui.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) continue;
3864 var cur = this.items[j][this.containers[innermostIndex].floating ? 'left' : 'top'];
3865 if(Math.abs(cur - base) < dist) {
3866 dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j];
3870 if(!itemWithLeastDistance && !this.options.dropOnEmpty) //Check if dropOnEmpty is enabled
3873 this.currentContainer = this.containers[innermostIndex];
3874 itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true);
3875 this._trigger("change", event, this._uiHash());
3876 this.containers[innermostIndex]._trigger("change", event, this._uiHash(this));
3878 //Update the placeholder
3879 this.options.placeholder.update(this.currentContainer, this.placeholder);
3881 this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
3882 this.containers[innermostIndex].containerCache.over = 1;
3888 _createHelper: function(event) {
3890 var o = this.options;
3891 var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper == 'clone' ? this.currentItem.clone() : this.currentItem);
3893 if(!helper.parents('body').length) //Add the helper to the DOM if that didn't happen already
3894 $(o.appendTo != 'parent' ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]);
3896 if(helper[0] == this.currentItem[0])
3897 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") };
3899 if(helper[0].style.width == '' || o.forceHelperSize) helper.width(this.currentItem.width());
3900 if(helper[0].style.height == '' || o.forceHelperSize) helper.height(this.currentItem.height());
3906 _adjustOffsetFromHelper: function(obj) {
3907 if (typeof obj == 'string') {
3908 obj = obj.split(' ');
3910 if ($.isArray(obj)) {
3911 obj = {left: +obj[0], top: +obj[1] || 0};
3913 if ('left' in obj) {
3914 this.offset.click.left = obj.left + this.margins.left;
3916 if ('right' in obj) {
3917 this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
3920 this.offset.click.top = obj.top + this.margins.top;
3922 if ('bottom' in obj) {
3923 this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
3927 _getParentOffset: function() {
3930 //Get the offsetParent and cache its position
3931 this.offsetParent = this.helper.offsetParent();
3932 var po = this.offsetParent.offset();
3934 // This is a special case where we need to modify a offset calculated on start, since the following happened:
3935 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
3936 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
3937 // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
3938 if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) {
3939 po.left += this.scrollParent.scrollLeft();
3940 po.top += this.scrollParent.scrollTop();
3943 if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
3944 || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix
3945 po = { top: 0, left: 0 };
3948 top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
3949 left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
3954 _getRelativeOffset: function() {
3956 if(this.cssPosition == "relative") {
3957 var p = this.currentItem.position();
3959 top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
3960 left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
3963 return { top: 0, left: 0 };
3968 _cacheMargins: function() {
3970 left: (parseInt(this.currentItem.css("marginLeft"),10) || 0),
3971 top: (parseInt(this.currentItem.css("marginTop"),10) || 0)
3975 _cacheHelperProportions: function() {
3976 this.helperProportions = {
3977 width: this.helper.outerWidth(),
3978 height: this.helper.outerHeight()
3982 _setContainment: function() {
3984 var o = this.options;
3985 if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
3986 if(o.containment == 'document' || o.containment == 'window') this.containment = [
3987 0 - this.offset.relative.left - this.offset.parent.left,
3988 0 - this.offset.relative.top - this.offset.parent.top,
3989 $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
3990 ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
3993 if(!(/^(document|window|parent)$/).test(o.containment)) {
3994 var ce = $(o.containment)[0];
3995 var co = $(o.containment).offset();
3996 var over = ($(ce).css("overflow") != 'hidden');
3998 this.containment = [
3999 co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
4000 co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
4001 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,
4002 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
4008 _convertPositionTo: function(d, pos) {
4010 if(!pos) pos = this.position;
4011 var mod = d == "absolute" ? 1 : -1;
4012 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);
4016 pos.top // The absolute mouse position
4017 + this.offset.relative.top * mod // Only for relative positioned nodes: Relative offset from element to offset parent
4018 + this.offset.parent.top * mod // The offsetParent's offset without borders (offset + border)
4019 - ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
4022 pos.left // The absolute mouse position
4023 + this.offset.relative.left * mod // Only for relative positioned nodes: Relative offset from element to offset parent
4024 + this.offset.parent.left * mod // The offsetParent's offset without borders (offset + border)
4025 - ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
4031 _generatePosition: function(event) {
4033 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);
4035 // This is another very weird special case that only happens for relative elements:
4036 // 1. If the css position is relative
4037 // 2. and the scroll parent is the document or similar to the offset parent
4038 // we have to refresh the relative offset during the scroll so there are no jumps
4039 if(this.cssPosition == 'relative' && !(this.scrollParent[0] != document && this.scrollParent[0] != this.offsetParent[0])) {
4040 this.offset.relative = this._getRelativeOffset();
4043 var pageX = event.pageX;
4044 var pageY = event.pageY;
4047 * - Position constraining -
4048 * Constrain the position to a mix of grid, containment.
4051 if(this.originalPosition) { //If we are not dragging yet, we won't check for options
4053 if(this.containment) {
4054 if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left;
4055 if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top;
4056 if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left;
4057 if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top;
4061 var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
4062 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;
4064 var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
4065 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;
4072 pageY // The absolute mouse position
4073 - this.offset.click.top // Click offset (relative to the element)
4074 - this.offset.relative.top // Only for relative positioned nodes: Relative offset from element to offset parent
4075 - this.offset.parent.top // The offsetParent's offset without borders (offset + border)
4076 + ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
4079 pageX // The absolute mouse position
4080 - this.offset.click.left // Click offset (relative to the element)
4081 - this.offset.relative.left // Only for relative positioned nodes: Relative offset from element to offset parent
4082 - this.offset.parent.left // The offsetParent's offset without borders (offset + border)
4083 + ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
4089 _rearrange: function(event, i, a, hardRefresh) {
4091 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));
4093 //Various things done here to improve the performance:
4094 // 1. we create a setTimeout, that calls refreshPositions
4095 // 2. on the instance, we have a counter variable, that get's higher after every append
4096 // 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same
4097 // 4. this lets only the last addition to the timeout stack through
4098 this.counter = this.counter ? ++this.counter : 1;
4099 var self = this, counter = this.counter;
4101 window.setTimeout(function() {
4102 if(counter == self.counter) self.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove
4107 _clear: function(event, noPropagation) {
4109 this.reverting = false;
4110 // We delay all events that have to be triggered to after the point where the placeholder has been removed and
4111 // everything else normalized again
4112 var delayedTriggers = [], self = this;
4114 // We first have to update the dom position of the actual currentItem
4115 // Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088)
4116 if(!this._noFinalSort && this.currentItem[0].parentNode) this.placeholder.before(this.currentItem);
4117 this._noFinalSort = null;
4119 if(this.helper[0] == this.currentItem[0]) {
4120 for(var i in this._storedCSS) {
4121 if(this._storedCSS[i] == 'auto' || this._storedCSS[i] == 'static') this._storedCSS[i] = '';
4123 this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
4125 this.currentItem.show();
4128 if(this.fromOutside && !noPropagation) delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); });
4129 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
4130 if(!$.ui.contains(this.element[0], this.currentItem[0])) { //Node was moved out of the current element
4131 if(!noPropagation) delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); });
4132 for (var i = this.containers.length - 1; i >= 0; i--){
4133 if($.ui.contains(this.containers[i].element[0], this.currentItem[0]) && !noPropagation) {
4134 delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); }; }).call(this, this.containers[i]));
4135 delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this)); }; }).call(this, this.containers[i]));
4140 //Post events to containers
4141 for (var i = this.containers.length - 1; i >= 0; i--){
4142 if(!noPropagation) delayedTriggers.push((function(c) { return function(event) { c._trigger("deactivate", event, this._uiHash(this)); }; }).call(this, this.containers[i]));
4143 if(this.containers[i].containerCache.over) {
4144 delayedTriggers.push((function(c) { return function(event) { c._trigger("out", event, this._uiHash(this)); }; }).call(this, this.containers[i]));
4145 this.containers[i].containerCache.over = 0;
4149 //Do what was originally in plugins
4150 if(this._storedCursor) $('body').css("cursor", this._storedCursor); //Reset cursor
4151 if(this._storedOpacity) this.helper.css("opacity", this._storedOpacity); //Reset opacity
4152 if(this._storedZIndex) this.helper.css("zIndex", this._storedZIndex == 'auto' ? '' : this._storedZIndex); //Reset z-index
4154 this.dragging = false;
4155 if(this.cancelHelperRemoval) {
4156 if(!noPropagation) {
4157 this._trigger("beforeStop", event, this._uiHash());
4158 for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events
4159 this._trigger("stop", event, this._uiHash());
4164 if(!noPropagation) this._trigger("beforeStop", event, this._uiHash());
4166 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
4167 this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
4169 if(this.helper[0] != this.currentItem[0]) this.helper.remove(); this.helper = null;
4171 if(!noPropagation) {
4172 for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events
4173 this._trigger("stop", event, this._uiHash());
4176 this.fromOutside = false;
4181 _trigger: function() {
4182 if ($.Widget.prototype._trigger.apply(this, arguments) === false) {
4187 _uiHash: function(inst) {
4188 var self = inst || this;
4190 helper: self.helper,
4191 placeholder: self.placeholder || $([]),
4192 position: self.position,
4193 originalPosition: self.originalPosition,
4194 offset: self.positionAbs,
4195 item: self.currentItem,
4196 sender: inst ? inst.element : null
4202 $.extend($.ui.sortable, {
4208 * jQuery UI Accordion 1.8.10
4210 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
4211 * Dual licensed under the MIT or GPL Version 2 licenses.
4212 * http://jquery.org/license
4214 * http://docs.jquery.com/UI/Accordion
4218 * jquery.ui.widget.js
4220 (function( $, undefined ) {
4222 $.widget( "ui.accordion", {
4231 header: "> li > :first-child,> :not(li):even",
4233 header: "ui-icon-triangle-1-e",
4234 headerSelected: "ui-icon-triangle-1-s"
4237 navigationFilter: function() {
4238 return this.href.toLowerCase() === location.href.toLowerCase();
4242 _create: function() {
4244 options = self.options;
4249 .addClass( "ui-accordion ui-widget ui-helper-reset" )
4250 // in lack of child-selectors in CSS
4251 // we need to mark top-LIs in a UL-accordion for some IE-fix
4253 .addClass( "ui-accordion-li-fix" );
4255 self.headers = self.element.find( options.header )
4256 .addClass( "ui-accordion-header ui-helper-reset ui-state-default ui-corner-all" )
4257 .bind( "mouseenter.accordion", function() {
4258 if ( options.disabled ) {
4261 $( this ).addClass( "ui-state-hover" );
4263 .bind( "mouseleave.accordion", function() {
4264 if ( options.disabled ) {
4267 $( this ).removeClass( "ui-state-hover" );
4269 .bind( "focus.accordion", function() {
4270 if ( options.disabled ) {
4273 $( this ).addClass( "ui-state-focus" );
4275 .bind( "blur.accordion", function() {
4276 if ( options.disabled ) {
4279 $( this ).removeClass( "ui-state-focus" );
4283 .addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" );
4285 if ( options.navigation ) {
4286 var current = self.element.find( "a" ).filter( options.navigationFilter ).eq( 0 );
4287 if ( current.length ) {
4288 var header = current.closest( ".ui-accordion-header" );
4289 if ( header.length ) {
4290 // anchor within header
4291 self.active = header;
4293 // anchor within content
4294 self.active = current.closest( ".ui-accordion-content" ).prev();
4299 self.active = self._findActive( self.active || options.active )
4300 .addClass( "ui-state-default ui-state-active" )
4301 .toggleClass( "ui-corner-all" )
4302 .toggleClass( "ui-corner-top" );
4303 self.active.next().addClass( "ui-accordion-content-active" );
4305 self._createIcons();
4309 self.element.attr( "role", "tablist" );
4312 .attr( "role", "tab" )
4313 .bind( "keydown.accordion", function( event ) {
4314 return self._keydown( event );
4317 .attr( "role", "tabpanel" );
4320 .not( self.active || "" )
4322 "aria-expanded": "false",
4328 // make sure at least one header is in the tab order
4329 if ( !self.active.length ) {
4330 self.headers.eq( 0 ).attr( "tabIndex", 0 );
4334 "aria-expanded": "true",
4339 // only need links in tab order for Safari
4340 if ( !$.browser.safari ) {
4341 self.headers.find( "a" ).attr( "tabIndex", -1 );
4344 if ( options.event ) {
4345 self.headers.bind( options.event.split(" ").join(".accordion ") + ".accordion", function(event) {
4346 self._clickHandler.call( self, event, this );
4347 event.preventDefault();
4352 _createIcons: function() {
4353 var options = this.options;
4354 if ( options.icons ) {
4355 $( "<span></span>" )
4356 .addClass( "ui-icon " + options.icons.header )
4357 .prependTo( this.headers );
4358 this.active.children( ".ui-icon" )
4359 .toggleClass(options.icons.header)
4360 .toggleClass(options.icons.headerSelected);
4361 this.element.addClass( "ui-accordion-icons" );
4365 _destroyIcons: function() {
4366 this.headers.children( ".ui-icon" ).remove();
4367 this.element.removeClass( "ui-accordion-icons" );
4370 destroy: function() {
4371 var options = this.options;
4374 .removeClass( "ui-accordion ui-widget ui-helper-reset" )
4375 .removeAttr( "role" );
4378 .unbind( ".accordion" )
4379 .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" )
4380 .removeAttr( "role" )
4381 .removeAttr( "aria-expanded" )
4382 .removeAttr( "tabIndex" );
4384 this.headers.find( "a" ).removeAttr( "tabIndex" );
4385 this._destroyIcons();
4386 var contents = this.headers.next()
4387 .css( "display", "" )
4388 .removeAttr( "role" )
4389 .removeClass( "ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-accordion-disabled ui-state-disabled" );
4390 if ( options.autoHeight || options.fillHeight ) {
4391 contents.css( "height", "" );
4394 return $.Widget.prototype.destroy.call( this );
4397 _setOption: function( key, value ) {
4398 $.Widget.prototype._setOption.apply( this, arguments );
4400 if ( key == "active" ) {
4401 this.activate( value );
4403 if ( key == "icons" ) {
4404 this._destroyIcons();
4406 this._createIcons();
4409 // #5332 - opacity doesn't cascade to positioned elements in IE
4410 // so we need to add the disabled class to the headers and panels
4411 if ( key == "disabled" ) {
4412 this.headers.add(this.headers.next())
4413 [ value ? "addClass" : "removeClass" ](
4414 "ui-accordion-disabled ui-state-disabled" );
4418 _keydown: function( event ) {
4419 if ( this.options.disabled || event.altKey || event.ctrlKey ) {
4423 var keyCode = $.ui.keyCode,
4424 length = this.headers.length,
4425 currentIndex = this.headers.index( event.target ),
4428 switch ( event.keyCode ) {
4431 toFocus = this.headers[ ( currentIndex + 1 ) % length ];
4435 toFocus = this.headers[ ( currentIndex - 1 + length ) % length ];
4439 this._clickHandler( { target: event.target }, event.target );
4440 event.preventDefault();
4444 $( event.target ).attr( "tabIndex", -1 );
4445 $( toFocus ).attr( "tabIndex", 0 );
4453 resize: function() {
4454 var options = this.options,
4457 if ( options.fillSpace ) {
4458 if ( $.browser.msie ) {
4459 var defOverflow = this.element.parent().css( "overflow" );
4460 this.element.parent().css( "overflow", "hidden");
4462 maxHeight = this.element.parent().height();
4463 if ($.browser.msie) {
4464 this.element.parent().css( "overflow", defOverflow );
4467 this.headers.each(function() {
4468 maxHeight -= $( this ).outerHeight( true );
4473 $( this ).height( Math.max( 0, maxHeight -
4474 $( this ).innerHeight() + $( this ).height() ) );
4476 .css( "overflow", "auto" );
4477 } else if ( options.autoHeight ) {
4481 maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() );
4483 .height( maxHeight );
4489 activate: function( index ) {
4490 // TODO this gets called on init, changing the option without an explicit call for that
4491 this.options.active = index;
4492 // call clickHandler with custom event
4493 var active = this._findActive( index )[ 0 ];
4494 this._clickHandler( { target: active }, active );
4499 _findActive: function( selector ) {
4501 ? typeof selector === "number"
4502 ? this.headers.filter( ":eq(" + selector + ")" )
4503 : this.headers.not( this.headers.not( selector ) )
4504 : selector === false
4506 : this.headers.filter( ":eq(0)" );
4509 // TODO isn't event.target enough? why the separate target argument?
4510 _clickHandler: function( event, target ) {
4511 var options = this.options;
4512 if ( options.disabled ) {
4516 // called only when using activate(false) to close all parts programmatically
4517 if ( !event.target ) {
4518 if ( !options.collapsible ) {
4522 .removeClass( "ui-state-active ui-corner-top" )
4523 .addClass( "ui-state-default ui-corner-all" )
4524 .children( ".ui-icon" )
4525 .removeClass( options.icons.headerSelected )
4526 .addClass( options.icons.header );
4527 this.active.next().addClass( "ui-accordion-content-active" );
4528 var toHide = this.active.next(),
4532 oldHeader: options.active,
4533 newContent: $( [] ),
4536 toShow = ( this.active = $( [] ) );
4537 this._toggle( toShow, toHide, data );
4541 // get the click target
4542 var clicked = $( event.currentTarget || target ),
4543 clickedIsActive = clicked[0] === this.active[0];
4545 // TODO the option is changed, is that correct?
4546 // TODO if it is correct, shouldn't that happen after determining that the click is valid?
4547 options.active = options.collapsible && clickedIsActive ?
4549 this.headers.index( clicked );
4551 // if animations are still active, or the active header is the target, ignore click
4552 if ( this.running || ( !options.collapsible && clickedIsActive ) ) {
4556 // find elements to show and hide
4557 var active = this.active,
4558 toShow = clicked.next(),
4559 toHide = this.active.next(),
4562 newHeader: clickedIsActive && options.collapsible ? $([]) : clicked,
4563 oldHeader: this.active,
4564 newContent: clickedIsActive && options.collapsible ? $([]) : toShow,
4567 down = this.headers.index( this.active[0] ) > this.headers.index( clicked[0] );
4569 // when the call to ._toggle() comes after the class changes
4570 // it causes a very odd bug in IE 8 (see #6720)
4571 this.active = clickedIsActive ? $([]) : clicked;
4572 this._toggle( toShow, toHide, data, clickedIsActive, down );
4576 .removeClass( "ui-state-active ui-corner-top" )
4577 .addClass( "ui-state-default ui-corner-all" )
4578 .children( ".ui-icon" )
4579 .removeClass( options.icons.headerSelected )
4580 .addClass( options.icons.header );
4581 if ( !clickedIsActive ) {
4583 .removeClass( "ui-state-default ui-corner-all" )
4584 .addClass( "ui-state-active ui-corner-top" )
4585 .children( ".ui-icon" )
4586 .removeClass( options.icons.header )
4587 .addClass( options.icons.headerSelected );
4590 .addClass( "ui-accordion-content-active" );
4596 _toggle: function( toShow, toHide, data, clickedIsActive, down ) {
4598 options = self.options;
4600 self.toShow = toShow;
4601 self.toHide = toHide;
4604 var complete = function() {
4608 return self._completed.apply( self, arguments );
4611 // trigger changestart event
4612 self._trigger( "changestart", null, self.data );
4614 // count elements to animate
4615 self.running = toHide.size() === 0 ? toShow.size() : toHide.size();
4617 if ( options.animated ) {
4618 var animOptions = {};
4620 if ( options.collapsible && clickedIsActive ) {
4626 autoHeight: options.autoHeight || options.fillSpace
4634 autoHeight: options.autoHeight || options.fillSpace
4638 if ( !options.proxied ) {
4639 options.proxied = options.animated;
4642 if ( !options.proxiedDuration ) {
4643 options.proxiedDuration = options.duration;
4646 options.animated = $.isFunction( options.proxied ) ?
4647 options.proxied( animOptions ) :
4650 options.duration = $.isFunction( options.proxiedDuration ) ?
4651 options.proxiedDuration( animOptions ) :
4652 options.proxiedDuration;
4654 var animations = $.ui.accordion.animations,
4655 duration = options.duration,
4656 easing = options.animated;
4658 if ( easing && !animations[ easing ] && !$.easing[ easing ] ) {
4661 if ( !animations[ easing ] ) {
4662 animations[ easing ] = function( options ) {
4663 this.slide( options, {
4665 duration: duration || 700
4670 animations[ easing ]( animOptions );
4672 if ( options.collapsible && clickedIsActive ) {
4682 // TODO assert that the blur and focus triggers are really necessary, remove otherwise
4685 "aria-expanded": "false",
4691 "aria-expanded": "true",
4697 _completed: function( cancel ) {
4698 this.running = cancel ? 0 : --this.running;
4699 if ( this.running ) {
4703 if ( this.options.clearStyle ) {
4704 this.toShow.add( this.toHide ).css({
4710 // other classes are removed before the animation; this one needs to stay until completed
4711 this.toHide.removeClass( "ui-accordion-content-active" );
4712 // Work around for rendering bug in IE (#5421)
4713 if ( this.toHide.length ) {
4714 this.toHide.parent()[0].className = this.toHide.parent()[0].className;
4717 this._trigger( "change", null, this.data );
4721 $.extend( $.ui.accordion, {
4724 slide: function( options, additions ) {
4725 options = $.extend({
4728 }, options, additions );
4729 if ( !options.toHide.size() ) {
4730 options.toShow.animate({
4733 paddingBottom: "show"
4737 if ( !options.toShow.size() ) {
4738 options.toHide.animate({
4741 paddingBottom: "hide"
4745 var overflow = options.toShow.css( "overflow" ),
4749 fxAttrs = [ "height", "paddingTop", "paddingBottom" ],
4751 // fix width before calculating height of hidden element
4752 var s = options.toShow;
4753 originalWidth = s[0].style.width;
4754 s.width( parseInt( s.parent().width(), 10 )
4755 - parseInt( s.css( "paddingLeft" ), 10 )
4756 - parseInt( s.css( "paddingRight" ), 10 )
4757 - ( parseInt( s.css( "borderLeftWidth" ), 10 ) || 0 )
4758 - ( parseInt( s.css( "borderRightWidth" ), 10) || 0 ) );
4760 $.each( fxAttrs, function( i, prop ) {
4761 hideProps[ prop ] = "hide";
4763 var parts = ( "" + $.css( options.toShow[0], prop ) ).match( /^([\d+-.]+)(.*)$/ );
4764 showProps[ prop ] = {
4766 unit: parts[ 2 ] || "px"
4769 options.toShow.css({ height: 0, overflow: "hidden" }).show();
4771 .filter( ":hidden" )
4772 .each( options.complete )
4774 .filter( ":visible" )
4775 .animate( hideProps, {
4776 step: function( now, settings ) {
4777 // only calculate the percent when animating height
4778 // IE gets very inconsistent results when animating elements
4779 // with small values, which is common for padding
4780 if ( settings.prop == "height" ) {
4781 percentDone = ( settings.end - settings.start === 0 ) ? 0 :
4782 ( settings.now - settings.start ) / ( settings.end - settings.start );
4785 options.toShow[ 0 ].style[ settings.prop ] =
4786 ( percentDone * showProps[ settings.prop ].value )
4787 + showProps[ settings.prop ].unit;
4789 duration: options.duration,
4790 easing: options.easing,
4791 complete: function() {
4792 if ( !options.autoHeight ) {
4793 options.toShow.css( "height", "" );
4795 options.toShow.css({
4796 width: originalWidth,
4803 bounceslide: function( options ) {
4804 this.slide( options, {
4805 easing: options.down ? "easeOutBounce" : "swing",
4806 duration: options.down ? 1000 : 200
4814 * jQuery UI Autocomplete 1.8.10
4816 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
4817 * Dual licensed under the MIT or GPL Version 2 licenses.
4818 * http://jquery.org/license
4820 * http://docs.jquery.com/UI/Autocomplete
4824 * jquery.ui.widget.js
4825 * jquery.ui.position.js
4827 (function( $, undefined ) {
4829 // used to prevent race conditions with remote data sources
4830 var requestIndex = 0;
4832 $.widget( "ui.autocomplete", {
4847 _create: function() {
4849 doc = this.element[ 0 ].ownerDocument,
4853 .addClass( "ui-autocomplete-input" )
4854 .attr( "autocomplete", "off" )
4855 // TODO verify these actually work as intended
4858 "aria-autocomplete": "list",
4859 "aria-haspopup": "true"
4861 .bind( "keydown.autocomplete", function( event ) {
4862 if ( self.options.disabled || self.element.attr( "readonly" ) ) {
4866 suppressKeyPress = false;
4867 var keyCode = $.ui.keyCode;
4868 switch( event.keyCode ) {
4869 case keyCode.PAGE_UP:
4870 self._move( "previousPage", event );
4872 case keyCode.PAGE_DOWN:
4873 self._move( "nextPage", event );
4876 self._move( "previous", event );
4877 // prevent moving cursor to beginning of text field in some browsers
4878 event.preventDefault();
4881 self._move( "next", event );
4882 // prevent moving cursor to end of text field in some browsers
4883 event.preventDefault();
4886 case keyCode.NUMPAD_ENTER:
4887 // when menu is open and has focus
4888 if ( self.menu.active ) {
4889 // #6055 - Opera still allows the keypress to occur
4890 // which causes forms to submit
4891 suppressKeyPress = true;
4892 event.preventDefault();
4894 //passthrough - ENTER and TAB both select the current element
4896 if ( !self.menu.active ) {
4899 self.menu.select( event );
4901 case keyCode.ESCAPE:
4902 self.element.val( self.term );
4903 self.close( event );
4906 // keypress is triggered before the input value is changed
4907 clearTimeout( self.searching );
4908 self.searching = setTimeout(function() {
4909 // only search if the value has changed
4910 if ( self.term != self.element.val() ) {
4911 self.selectedItem = null;
4912 self.search( null, event );
4914 }, self.options.delay );
4918 .bind( "keypress.autocomplete", function( event ) {
4919 if ( suppressKeyPress ) {
4920 suppressKeyPress = false;
4921 event.preventDefault();
4924 .bind( "focus.autocomplete", function() {
4925 if ( self.options.disabled ) {
4929 self.selectedItem = null;
4930 self.previous = self.element.val();
4932 .bind( "blur.autocomplete", function( event ) {
4933 if ( self.options.disabled ) {
4937 clearTimeout( self.searching );
4938 // clicks on the menu (or a button to trigger a search) will cause a blur event
4939 self.closing = setTimeout(function() {
4940 self.close( event );
4941 self._change( event );
4945 this.response = function() {
4946 return self._response.apply( self, arguments );
4948 this.menu = $( "<ul></ul>" )
4949 .addClass( "ui-autocomplete" )
4950 .appendTo( $( this.options.appendTo || "body", doc )[0] )
4951 // prevent the close-on-blur in case of a "slow" click on the menu (long mousedown)
4952 .mousedown(function( event ) {
4953 // clicking on the scrollbar causes focus to shift to the body
4954 // but we can't detect a mouseup or a click immediately afterward
4955 // so we have to track the next mousedown and close the menu if
4956 // the user clicks somewhere outside of the autocomplete
4957 var menuElement = self.menu.element[ 0 ];
4958 if ( !$( event.target ).closest( ".ui-menu-item" ).length ) {
4959 setTimeout(function() {
4960 $( document ).one( 'mousedown', function( event ) {
4961 if ( event.target !== self.element[ 0 ] &&
4962 event.target !== menuElement &&
4963 !$.ui.contains( menuElement, event.target ) ) {
4970 // use another timeout to make sure the blur-event-handler on the input was already triggered
4971 setTimeout(function() {
4972 clearTimeout( self.closing );
4976 focus: function( event, ui ) {
4977 var item = ui.item.data( "item.autocomplete" );
4978 if ( false !== self._trigger( "focus", event, { item: item } ) ) {
4979 // use value to match what will end up in the input, if it was a key event
4980 if ( /^key/.test(event.originalEvent.type) ) {
4981 self.element.val( item.value );
4985 selected: function( event, ui ) {
4986 var item = ui.item.data( "item.autocomplete" ),
4987 previous = self.previous;
4989 // only trigger when focus was lost (click on menu)
4990 if ( self.element[0] !== doc.activeElement ) {
4991 self.element.focus();
4992 self.previous = previous;
4993 // #6109 - IE triggers two focus events and the second
4994 // is asynchronous, so we need to reset the previous
4995 // term synchronously and asynchronously :-(
4996 setTimeout(function() {
4997 self.previous = previous;
4998 self.selectedItem = item;
5002 if ( false !== self._trigger( "select", event, { item: item } ) ) {
5003 self.element.val( item.value );
5005 // reset the term after the select event
5006 // this allows custom select handling to work properly
5007 self.term = self.element.val();
5009 self.close( event );
5010 self.selectedItem = item;
5012 blur: function( event, ui ) {
5013 // don't set the value of the text field if it's already correct
5014 // this prevents moving the cursor unnecessarily
5015 if ( self.menu.element.is(":visible") &&
5016 ( self.element.val() !== self.term ) ) {
5017 self.element.val( self.term );
5021 .zIndex( this.element.zIndex() + 1 )
5022 // workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
5023 .css({ top: 0, left: 0 })
5026 if ( $.fn.bgiframe ) {
5027 this.menu.element.bgiframe();
5031 destroy: function() {
5033 .removeClass( "ui-autocomplete-input" )
5034 .removeAttr( "autocomplete" )
5035 .removeAttr( "role" )
5036 .removeAttr( "aria-autocomplete" )
5037 .removeAttr( "aria-haspopup" );
5038 this.menu.element.remove();
5039 $.Widget.prototype.destroy.call( this );
5042 _setOption: function( key, value ) {
5043 $.Widget.prototype._setOption.apply( this, arguments );
5044 if ( key === "source" ) {
5047 if ( key === "appendTo" ) {
5048 this.menu.element.appendTo( $( value || "body", this.element[0].ownerDocument )[0] )
5050 if ( key === "disabled" && value && this.xhr ) {
5055 _initSource: function() {
5059 if ( $.isArray(this.options.source) ) {
5060 array = this.options.source;
5061 this.source = function( request, response ) {
5062 response( $.ui.autocomplete.filter(array, request.term) );
5064 } else if ( typeof this.options.source === "string" ) {
5065 url = this.options.source;
5066 this.source = function( request, response ) {
5074 autocompleteRequest: ++requestIndex,
5075 success: function( data, status ) {
5076 if ( this.autocompleteRequest === requestIndex ) {
5081 if ( this.autocompleteRequest === requestIndex ) {
5088 this.source = this.options.source;
5092 search: function( value, event ) {
5093 value = value != null ? value : this.element.val();
5095 // always save the actual value, not the one passed as an argument
5096 this.term = this.element.val();
5098 if ( value.length < this.options.minLength ) {
5099 return this.close( event );
5102 clearTimeout( this.closing );
5103 if ( this._trigger( "search", event ) === false ) {
5107 return this._search( value );
5110 _search: function( value ) {
5112 this.element.addClass( "ui-autocomplete-loading" );
5114 this.source( { term: value }, this.response );
5117 _response: function( content ) {
5118 if ( !this.options.disabled && content && content.length ) {
5119 content = this._normalize( content );
5120 this._suggest( content );
5121 this._trigger( "open" );
5126 if ( !this.pending ) {
5127 this.element.removeClass( "ui-autocomplete-loading" );
5131 close: function( event ) {
5132 clearTimeout( this.closing );
5133 if ( this.menu.element.is(":visible") ) {
5134 this.menu.element.hide();
5135 this.menu.deactivate();
5136 this._trigger( "close", event );
5140 _change: function( event ) {
5141 if ( this.previous !== this.element.val() ) {
5142 this._trigger( "change", event, { item: this.selectedItem } );
5146 _normalize: function( items ) {
5147 // assume all items have the right format when the first item is complete
5148 if ( items.length && items[0].label && items[0].value ) {
5151 return $.map( items, function(item) {
5152 if ( typeof item === "string" ) {
5159 label: item.label || item.value,
5160 value: item.value || item.label
5165 _suggest: function( items ) {
5166 var ul = this.menu.element
5168 .zIndex( this.element.zIndex() + 1 );
5169 this._renderMenu( ul, items );
5170 // TODO refresh should check if the active item is still in the dom, removing the need for a manual deactivate
5171 this.menu.deactivate();
5172 this.menu.refresh();
5174 // size and position menu
5177 ul.position( $.extend({
5179 }, this.options.position ));
5182 _resizeMenu: function() {
5183 var ul = this.menu.element;
5184 ul.outerWidth( Math.max(
5185 ul.width( "" ).outerWidth(),
5186 this.element.outerWidth()
5190 _renderMenu: function( ul, items ) {
5192 $.each( items, function( index, item ) {
5193 self._renderItem( ul, item );
5197 _renderItem: function( ul, item) {
5198 return $( "<li></li>" )
5199 .data( "item.autocomplete", item )
5200 .append( $( "<a></a>" ).text( item.label ) )
5204 _move: function( direction, event ) {
5205 if ( !this.menu.element.is(":visible") ) {
5206 this.search( null, event );
5209 if ( this.menu.first() && /^previous/.test(direction) ||
5210 this.menu.last() && /^next/.test(direction) ) {
5211 this.element.val( this.term );
5212 this.menu.deactivate();
5215 this.menu[ direction ]( event );
5218 widget: function() {
5219 return this.menu.element;
5223 $.extend( $.ui.autocomplete, {
5224 escapeRegex: function( value ) {
5225 return value.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
5227 filter: function(array, term) {
5228 var matcher = new RegExp( $.ui.autocomplete.escapeRegex(term), "i" );
5229 return $.grep( array, function(value) {
5230 return matcher.test( value.label || value.value || value );
5238 * jQuery UI Menu (not officially released)
5240 * This widget isn't yet finished and the API is subject to change. We plan to finish
5241 * it for the next release. You're welcome to give it a try anyway and give us feedback,
5242 * as long as you're okay with migrating your code later on. We can help with that, too.
5244 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
5245 * Dual licensed under the MIT or GPL Version 2 licenses.
5246 * http://jquery.org/license
5248 * http://docs.jquery.com/UI/Menu
5252 * jquery.ui.widget.js
5256 $.widget("ui.menu", {
5257 _create: function() {
5260 .addClass("ui-menu ui-widget ui-widget-content ui-corner-all")
5263 "aria-activedescendant": "ui-active-menuitem"
5265 .click(function( event ) {
5266 if ( !$( event.target ).closest( ".ui-menu-item a" ).length ) {
5270 event.preventDefault();
5271 self.select( event );
5276 refresh: function() {
5279 // don't refresh list items that are already adapted
5280 var items = this.element.children("li:not(.ui-menu-item):has(a)")
5281 .addClass("ui-menu-item")
5282 .attr("role", "menuitem");
5285 .addClass("ui-corner-all")
5286 .attr("tabindex", -1)
5287 // mouseenter doesn't work with event delegation
5288 .mouseenter(function( event ) {
5289 self.activate( event, $(this).parent() );
5291 .mouseleave(function() {
5296 activate: function( event, item ) {
5298 if (this.hasScroll()) {
5299 var offset = item.offset().top - this.element.offset().top,
5300 scroll = this.element.attr("scrollTop"),
5301 elementHeight = this.element.height();
5303 this.element.attr("scrollTop", scroll + offset);
5304 } else if (offset >= elementHeight) {
5305 this.element.attr("scrollTop", scroll + offset - elementHeight + item.height());
5308 this.active = item.eq(0)
5310 .addClass("ui-state-hover")
5311 .attr("id", "ui-active-menuitem")
5313 this._trigger("focus", event, { item: item });
5316 deactivate: function() {
5317 if (!this.active) { return; }
5319 this.active.children("a")
5320 .removeClass("ui-state-hover")
5322 this._trigger("blur");
5326 next: function(event) {
5327 this.move("next", ".ui-menu-item:first", event);
5330 previous: function(event) {
5331 this.move("prev", ".ui-menu-item:last", event);
5335 return this.active && !this.active.prevAll(".ui-menu-item").length;
5339 return this.active && !this.active.nextAll(".ui-menu-item").length;
5342 move: function(direction, edge, event) {
5344 this.activate(event, this.element.children(edge));
5347 var next = this.active[direction + "All"](".ui-menu-item").eq(0);
5349 this.activate(event, next);
5351 this.activate(event, this.element.children(edge));
5355 // TODO merge with previousPage
5356 nextPage: function(event) {
5357 if (this.hasScroll()) {
5358 // TODO merge with no-scroll-else
5359 if (!this.active || this.last()) {
5360 this.activate(event, this.element.children(".ui-menu-item:first"));
5363 var base = this.active.offset().top,
5364 height = this.element.height(),
5365 result = this.element.children(".ui-menu-item").filter(function() {
5366 var close = $(this).offset().top - base - height + $(this).height();
5367 // TODO improve approximation
5368 return close < 10 && close > -10;
5371 // TODO try to catch this earlier when scrollTop indicates the last page anyway
5372 if (!result.length) {
5373 result = this.element.children(".ui-menu-item:last");
5375 this.activate(event, result);
5377 this.activate(event, this.element.children(".ui-menu-item")
5378 .filter(!this.active || this.last() ? ":first" : ":last"));
5382 // TODO merge with nextPage
5383 previousPage: function(event) {
5384 if (this.hasScroll()) {
5385 // TODO merge with no-scroll-else
5386 if (!this.active || this.first()) {
5387 this.activate(event, this.element.children(".ui-menu-item:last"));
5391 var base = this.active.offset().top,
5392 height = this.element.height();
5393 result = this.element.children(".ui-menu-item").filter(function() {
5394 var close = $(this).offset().top - base + height - $(this).height();
5395 // TODO improve approximation
5396 return close < 10 && close > -10;
5399 // TODO try to catch this earlier when scrollTop indicates the last page anyway
5400 if (!result.length) {
5401 result = this.element.children(".ui-menu-item:first");
5403 this.activate(event, result);
5405 this.activate(event, this.element.children(".ui-menu-item")
5406 .filter(!this.active || this.first() ? ":last" : ":first"));
5410 hasScroll: function() {
5411 return this.element.height() < this.element.attr("scrollHeight");
5414 select: function( event ) {
5415 this._trigger("selected", event, { item: this.active });
5421 * jQuery UI Button 1.8.10
5423 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
5424 * Dual licensed under the MIT or GPL Version 2 licenses.
5425 * http://jquery.org/license
5427 * http://docs.jquery.com/UI/Button
5431 * jquery.ui.widget.js
5433 (function( $, undefined ) {
5436 baseClasses = "ui-button ui-widget ui-state-default ui-corner-all",
5437 stateClasses = "ui-state-hover ui-state-active ",
5438 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",
5439 formResetHandler = function( event ) {
5440 $( ":ui-button", event.target.form ).each(function() {
5441 var inst = $( this ).data( "button" );
5442 setTimeout(function() {
5447 radioGroup = function( radio ) {
5448 var name = radio.name,
5453 radios = $( form ).find( "[name='" + name + "']" );
5455 radios = $( "[name='" + name + "']", radio.ownerDocument )
5456 .filter(function() {
5464 $.widget( "ui.button", {
5474 _create: function() {
5475 this.element.closest( "form" )
5476 .unbind( "reset.button" )
5477 .bind( "reset.button", formResetHandler );
5479 if ( typeof this.options.disabled !== "boolean" ) {
5480 this.options.disabled = this.element.attr( "disabled" );
5483 this._determineButtonType();
5484 this.hasTitle = !!this.buttonElement.attr( "title" );
5487 options = this.options,
5488 toggleButton = this.type === "checkbox" || this.type === "radio",
5489 hoverClass = "ui-state-hover" + ( !toggleButton ? " ui-state-active" : "" ),
5490 focusClass = "ui-state-focus";
5492 if ( options.label === null ) {
5493 options.label = this.buttonElement.html();
5496 if ( this.element.is( ":disabled" ) ) {
5497 options.disabled = true;
5501 .addClass( baseClasses )
5502 .attr( "role", "button" )
5503 .bind( "mouseenter.button", function() {
5504 if ( options.disabled ) {
5507 $( this ).addClass( "ui-state-hover" );
5508 if ( this === lastActive ) {
5509 $( this ).addClass( "ui-state-active" );
5512 .bind( "mouseleave.button", function() {
5513 if ( options.disabled ) {
5516 $( this ).removeClass( hoverClass );
5518 .bind( "focus.button", function() {
5519 // no need to check disabled, focus won't be triggered anyway
5520 $( this ).addClass( focusClass );
5522 .bind( "blur.button", function() {
5523 $( this ).removeClass( focusClass );
5526 if ( toggleButton ) {
5527 this.element.bind( "change.button", function() {
5532 if ( this.type === "checkbox" ) {
5533 this.buttonElement.bind( "click.button", function() {
5534 if ( options.disabled ) {
5537 $( this ).toggleClass( "ui-state-active" );
5538 self.buttonElement.attr( "aria-pressed", self.element[0].checked );
5540 } else if ( this.type === "radio" ) {
5541 this.buttonElement.bind( "click.button", function() {
5542 if ( options.disabled ) {
5545 $( this ).addClass( "ui-state-active" );
5546 self.buttonElement.attr( "aria-pressed", true );
5548 var radio = self.element[ 0 ];
5552 return $( this ).button( "widget" )[ 0 ];
5554 .removeClass( "ui-state-active" )
5555 .attr( "aria-pressed", false );
5559 .bind( "mousedown.button", function() {
5560 if ( options.disabled ) {
5563 $( this ).addClass( "ui-state-active" );
5565 $( document ).one( "mouseup", function() {
5569 .bind( "mouseup.button", function() {
5570 if ( options.disabled ) {
5573 $( this ).removeClass( "ui-state-active" );
5575 .bind( "keydown.button", function(event) {
5576 if ( options.disabled ) {
5579 if ( event.keyCode == $.ui.keyCode.SPACE || event.keyCode == $.ui.keyCode.ENTER ) {
5580 $( this ).addClass( "ui-state-active" );
5583 .bind( "keyup.button", function() {
5584 $( this ).removeClass( "ui-state-active" );
5587 if ( this.buttonElement.is("a") ) {
5588 this.buttonElement.keyup(function(event) {
5589 if ( event.keyCode === $.ui.keyCode.SPACE ) {
5590 // TODO pass through original event correctly (just as 2nd argument doesn't work)
5597 // TODO: pull out $.Widget's handling for the disabled option into
5598 // $.Widget.prototype._setOptionDisabled so it's easy to proxy and can
5599 // be overridden by individual plugins
5600 this._setOption( "disabled", options.disabled );
5603 _determineButtonType: function() {
5605 if ( this.element.is(":checkbox") ) {
5606 this.type = "checkbox";
5608 if ( this.element.is(":radio") ) {
5609 this.type = "radio";
5611 if ( this.element.is("input") ) {
5612 this.type = "input";
5614 this.type = "button";
5619 if ( this.type === "checkbox" || this.type === "radio" ) {
5620 // we don't search against the document in case the element
5621 // is disconnected from the DOM
5622 this.buttonElement = this.element.parents().last()
5623 .find( "label[for=" + this.element.attr("id") + "]" );
5624 this.element.addClass( "ui-helper-hidden-accessible" );
5626 var checked = this.element.is( ":checked" );
5628 this.buttonElement.addClass( "ui-state-active" );
5630 this.buttonElement.attr( "aria-pressed", checked );
5632 this.buttonElement = this.element;
5636 widget: function() {
5637 return this.buttonElement;
5640 destroy: function() {
5642 .removeClass( "ui-helper-hidden-accessible" );
5644 .removeClass( baseClasses + " " + stateClasses + " " + typeClasses )
5645 .removeAttr( "role" )
5646 .removeAttr( "aria-pressed" )
5647 .html( this.buttonElement.find(".ui-button-text").html() );
5649 if ( !this.hasTitle ) {
5650 this.buttonElement.removeAttr( "title" );
5653 $.Widget.prototype.destroy.call( this );
5656 _setOption: function( key, value ) {
5657 $.Widget.prototype._setOption.apply( this, arguments );
5658 if ( key === "disabled" ) {
5660 this.element.attr( "disabled", true );
5662 this.element.removeAttr( "disabled" );
5665 this._resetButton();
5668 refresh: function() {
5669 var isDisabled = this.element.is( ":disabled" );
5670 if ( isDisabled !== this.options.disabled ) {
5671 this._setOption( "disabled", isDisabled );
5673 if ( this.type === "radio" ) {
5674 radioGroup( this.element[0] ).each(function() {
5675 if ( $( this ).is( ":checked" ) ) {
5676 $( this ).button( "widget" )
5677 .addClass( "ui-state-active" )
5678 .attr( "aria-pressed", true );
5680 $( this ).button( "widget" )
5681 .removeClass( "ui-state-active" )
5682 .attr( "aria-pressed", false );
5685 } else if ( this.type === "checkbox" ) {
5686 if ( this.element.is( ":checked" ) ) {
5688 .addClass( "ui-state-active" )
5689 .attr( "aria-pressed", true );
5692 .removeClass( "ui-state-active" )
5693 .attr( "aria-pressed", false );
5698 _resetButton: function() {
5699 if ( this.type === "input" ) {
5700 if ( this.options.label ) {
5701 this.element.val( this.options.label );
5705 var buttonElement = this.buttonElement.removeClass( typeClasses ),
5706 buttonText = $( "<span></span>" )
5707 .addClass( "ui-button-text" )
5708 .html( this.options.label )
5709 .appendTo( buttonElement.empty() )
5711 icons = this.options.icons,
5712 multipleIcons = icons.primary && icons.secondary,
5715 if ( icons.primary || icons.secondary ) {
5716 buttonClasses.push( "ui-button-text-icon" + ( multipleIcons ? "s" : ( icons.primary ? "-primary" : "-secondary" ) ) );
5718 if ( icons.primary ) {
5719 buttonElement.prepend( "<span class='ui-button-icon-primary ui-icon " + icons.primary + "'></span>" );
5722 if ( icons.secondary ) {
5723 buttonElement.append( "<span class='ui-button-icon-secondary ui-icon " + icons.secondary + "'></span>" );
5726 if ( !this.options.text ) {
5727 buttonClasses.push( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" );
5728 buttonElement.removeClass( "ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary" );
5730 if ( !this.hasTitle ) {
5731 buttonElement.attr( "title", buttonText );
5735 buttonClasses.push( "ui-button-text-only" );
5737 buttonElement.addClass( buttonClasses.join( " " ) );
5741 $.widget( "ui.buttonset", {
5743 items: ":button, :submit, :reset, :checkbox, :radio, a, :data(button)"
5746 _create: function() {
5747 this.element.addClass( "ui-buttonset" );
5754 _setOption: function( key, value ) {
5755 if ( key === "disabled" ) {
5756 this.buttons.button( "option", key, value );
5759 $.Widget.prototype._setOption.apply( this, arguments );
5762 refresh: function() {
5763 this.buttons = this.element.find( this.options.items )
5764 .filter( ":ui-button" )
5765 .button( "refresh" )
5767 .not( ":ui-button" )
5771 return $( this ).button( "widget" )[ 0 ];
5773 .removeClass( "ui-corner-all ui-corner-left ui-corner-right" )
5775 .addClass( "ui-corner-left" )
5778 .addClass( "ui-corner-right" )
5783 destroy: function() {
5784 this.element.removeClass( "ui-buttonset" );
5787 return $( this ).button( "widget" )[ 0 ];
5789 .removeClass( "ui-corner-left ui-corner-right" )
5791 .button( "destroy" );
5793 $.Widget.prototype.destroy.call( this );
5799 * jQuery UI Dialog 1.8.10
5801 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
5802 * Dual licensed under the MIT or GPL Version 2 licenses.
5803 * http://jquery.org/license
5805 * http://docs.jquery.com/UI/Dialog
5809 * jquery.ui.widget.js
5810 * jquery.ui.button.js
5811 * jquery.ui.draggable.js
5812 * jquery.ui.mouse.js
5813 * jquery.ui.position.js
5814 * jquery.ui.resizable.js
5816 (function( $, undefined ) {
5818 var uiDialogClasses =
5821 'ui-widget-content ' +
5823 sizeRelatedOptions = {
5832 resizableRelatedOptions = {
5839 $.widget("ui.dialog", {
5843 closeOnEscape: true,
5858 // ensure that the titlebar is never outside the document
5859 using: function(pos) {
5860 var topOffset = $(this).css(pos).offset().top;
5861 if (topOffset < 0) {
5862 $(this).css('top', pos.top - topOffset);
5874 _create: function() {
5875 this.originalTitle = this.element.attr('title');
5876 // #5742 - .attr() might return a DOMElement
5877 if ( typeof this.originalTitle !== "string" ) {
5878 this.originalTitle = "";
5881 this.options.title = this.options.title || this.originalTitle;
5883 options = self.options,
5885 title = options.title || ' ',
5886 titleId = $.ui.dialog.getTitleId(self.element),
5888 uiDialog = (self.uiDialog = $('<div></div>'))
5889 .appendTo(document.body)
5891 .addClass(uiDialogClasses + options.dialogClass)
5893 zIndex: options.zIndex
5895 // setting tabIndex makes the div focusable
5896 // setting outline to 0 prevents a border on focus in Mozilla
5897 .attr('tabIndex', -1).css('outline', 0).keydown(function(event) {
5898 if (options.closeOnEscape && event.keyCode &&
5899 event.keyCode === $.ui.keyCode.ESCAPE) {
5902 event.preventDefault();
5907 'aria-labelledby': titleId
5909 .mousedown(function(event) {
5910 self.moveToTop(false, event);
5913 uiDialogContent = self.element
5915 .removeAttr('title')
5917 'ui-dialog-content ' +
5918 'ui-widget-content')
5919 .appendTo(uiDialog),
5921 uiDialogTitlebar = (self.uiDialogTitlebar = $('<div></div>'))
5923 'ui-dialog-titlebar ' +
5924 'ui-widget-header ' +
5926 'ui-helper-clearfix'
5928 .prependTo(uiDialog),
5930 uiDialogTitlebarClose = $('<a href="#"></a>')
5932 'ui-dialog-titlebar-close ' +
5935 .attr('role', 'button')
5938 uiDialogTitlebarClose.addClass('ui-state-hover');
5941 uiDialogTitlebarClose.removeClass('ui-state-hover');
5945 uiDialogTitlebarClose.addClass('ui-state-focus');
5948 uiDialogTitlebarClose.removeClass('ui-state-focus');
5950 .click(function(event) {
5954 .appendTo(uiDialogTitlebar),
5956 uiDialogTitlebarCloseText = (self.uiDialogTitlebarCloseText = $('<span></span>'))
5959 'ui-icon-closethick'
5961 .text(options.closeText)
5962 .appendTo(uiDialogTitlebarClose),
5964 uiDialogTitle = $('<span></span>')
5965 .addClass('ui-dialog-title')
5966 .attr('id', titleId)
5968 .prependTo(uiDialogTitlebar);
5970 //handling of deprecated beforeclose (vs beforeClose) option
5971 //Ticket #4669 http://dev.jqueryui.com/ticket/4669
5972 //TODO: remove in 1.9pre
5973 if ($.isFunction(options.beforeclose) && !$.isFunction(options.beforeClose)) {
5974 options.beforeClose = options.beforeclose;
5977 uiDialogTitlebar.find("*").add(uiDialogTitlebar).disableSelection();
5979 if (options.draggable && $.fn.draggable) {
5980 self._makeDraggable();
5982 if (options.resizable && $.fn.resizable) {
5983 self._makeResizable();
5986 self._createButtons(options.buttons);
5987 self._isOpen = false;
5989 if ($.fn.bgiframe) {
5990 uiDialog.bgiframe();
5995 if ( this.options.autoOpen ) {
6000 destroy: function() {
6004 self.overlay.destroy();
6006 self.uiDialog.hide();
6009 .removeData('dialog')
6010 .removeClass('ui-dialog-content ui-widget-content')
6011 .hide().appendTo('body');
6012 self.uiDialog.remove();
6014 if (self.originalTitle) {
6015 self.element.attr('title', self.originalTitle);
6021 widget: function() {
6022 return this.uiDialog;
6025 close: function(event) {
6029 if (false === self._trigger('beforeClose', event)) {
6034 self.overlay.destroy();
6036 self.uiDialog.unbind('keypress.ui-dialog');
6038 self._isOpen = false;
6040 if (self.options.hide) {
6041 self.uiDialog.hide(self.options.hide, function() {
6042 self._trigger('close', event);
6045 self.uiDialog.hide();
6046 self._trigger('close', event);
6049 $.ui.dialog.overlay.resize();
6051 // adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
6052 if (self.options.modal) {
6054 $('.ui-dialog').each(function() {
6055 if (this !== self.uiDialog[0]) {
6056 thisZ = $(this).css('z-index');
6058 maxZ = Math.max(maxZ, thisZ);
6062 $.ui.dialog.maxZ = maxZ;
6068 isOpen: function() {
6069 return this._isOpen;
6072 // the force parameter allows us to move modal dialogs to their correct
6074 moveToTop: function(force, event) {
6076 options = self.options,
6079 if ((options.modal && !force) ||
6080 (!options.stack && !options.modal)) {
6081 return self._trigger('focus', event);
6084 if (options.zIndex > $.ui.dialog.maxZ) {
6085 $.ui.dialog.maxZ = options.zIndex;
6088 $.ui.dialog.maxZ += 1;
6089 self.overlay.$el.css('z-index', $.ui.dialog.overlay.maxZ = $.ui.dialog.maxZ);
6092 //Save and then restore scroll since Opera 9.5+ resets when parent z-Index is changed.
6093 // http://ui.jquery.com/bugs/ticket/3193
6094 saveScroll = { scrollTop: self.element.attr('scrollTop'), scrollLeft: self.element.attr('scrollLeft') };
6095 $.ui.dialog.maxZ += 1;
6096 self.uiDialog.css('z-index', $.ui.dialog.maxZ);
6097 self.element.attr(saveScroll);
6098 self._trigger('focus', event);
6104 if (this._isOpen) { return; }
6107 options = self.options,
6108 uiDialog = self.uiDialog;
6110 self.overlay = options.modal ? new $.ui.dialog.overlay(self) : null;
6112 self._position(options.position);
6113 uiDialog.show(options.show);
6114 self.moveToTop(true);
6116 // prevent tabbing out of modal dialogs
6117 if (options.modal) {
6118 uiDialog.bind('keypress.ui-dialog', function(event) {
6119 if (event.keyCode !== $.ui.keyCode.TAB) {
6123 var tabbables = $(':tabbable', this),
6124 first = tabbables.filter(':first'),
6125 last = tabbables.filter(':last');
6127 if (event.target === last[0] && !event.shiftKey) {
6130 } else if (event.target === first[0] && event.shiftKey) {
6137 // set focus to the first tabbable element in the content area or the first button
6138 // if there are no tabbable elements, set focus on the dialog itself
6139 $(self.element.find(':tabbable').get().concat(
6140 uiDialog.find('.ui-dialog-buttonpane :tabbable').get().concat(
6141 uiDialog.get()))).eq(0).focus();
6143 self._isOpen = true;
6144 self._trigger('open');
6149 _createButtons: function(buttons) {
6152 uiDialogButtonPane = $('<div></div>')
6154 'ui-dialog-buttonpane ' +
6155 'ui-widget-content ' +
6156 'ui-helper-clearfix'
6158 uiButtonSet = $( "<div></div>" )
6159 .addClass( "ui-dialog-buttonset" )
6160 .appendTo( uiDialogButtonPane );
6162 // if we already have a button pane, remove it
6163 self.uiDialog.find('.ui-dialog-buttonpane').remove();
6165 if (typeof buttons === 'object' && buttons !== null) {
6166 $.each(buttons, function() {
6167 return !(hasButtons = true);
6171 $.each(buttons, function(name, props) {
6172 props = $.isFunction( props ) ?
6173 { click: props, text: name } :
6175 var button = $('<button type="button"></button>')
6176 .attr( props, true )
6179 props.click.apply(self.element[0], arguments);
6181 .appendTo(uiButtonSet);
6186 uiDialogButtonPane.appendTo(self.uiDialog);
6190 _makeDraggable: function() {
6192 options = self.options,
6196 function filteredUi(ui) {
6198 position: ui.position,
6203 self.uiDialog.draggable({
6204 cancel: '.ui-dialog-content, .ui-dialog-titlebar-close',
6205 handle: '.ui-dialog-titlebar',
6206 containment: 'document',
6207 start: function(event, ui) {
6208 heightBeforeDrag = options.height === "auto" ? "auto" : $(this).height();
6209 $(this).height($(this).height()).addClass("ui-dialog-dragging");
6210 self._trigger('dragStart', event, filteredUi(ui));
6212 drag: function(event, ui) {
6213 self._trigger('drag', event, filteredUi(ui));
6215 stop: function(event, ui) {
6216 options.position = [ui.position.left - doc.scrollLeft(),
6217 ui.position.top - doc.scrollTop()];
6218 $(this).removeClass("ui-dialog-dragging").height(heightBeforeDrag);
6219 self._trigger('dragStop', event, filteredUi(ui));
6220 $.ui.dialog.overlay.resize();
6225 _makeResizable: function(handles) {
6226 handles = (handles === undefined ? this.options.resizable : handles);
6228 options = self.options,
6229 // .ui-resizable has position: relative defined in the stylesheet
6230 // but dialogs have to use absolute or fixed positioning
6231 position = self.uiDialog.css('position'),
6232 resizeHandles = (typeof handles === 'string' ?
6234 'n,e,s,w,se,sw,ne,nw'
6237 function filteredUi(ui) {
6239 originalPosition: ui.originalPosition,
6240 originalSize: ui.originalSize,
6241 position: ui.position,
6246 self.uiDialog.resizable({
6247 cancel: '.ui-dialog-content',
6248 containment: 'document',
6249 alsoResize: self.element,
6250 maxWidth: options.maxWidth,
6251 maxHeight: options.maxHeight,
6252 minWidth: options.minWidth,
6253 minHeight: self._minHeight(),
6254 handles: resizeHandles,
6255 start: function(event, ui) {
6256 $(this).addClass("ui-dialog-resizing");
6257 self._trigger('resizeStart', event, filteredUi(ui));
6259 resize: function(event, ui) {
6260 self._trigger('resize', event, filteredUi(ui));
6262 stop: function(event, ui) {
6263 $(this).removeClass("ui-dialog-resizing");
6264 options.height = $(this).height();
6265 options.width = $(this).width();
6266 self._trigger('resizeStop', event, filteredUi(ui));
6267 $.ui.dialog.overlay.resize();
6270 .css('position', position)
6271 .find('.ui-resizable-se').addClass('ui-icon ui-icon-grip-diagonal-se');
6274 _minHeight: function() {
6275 var options = this.options;
6277 if (options.height === 'auto') {
6278 return options.minHeight;
6280 return Math.min(options.minHeight, options.height);
6284 _position: function(position) {
6290 // deep extending converts arrays to objects in jQuery <= 1.3.2 :-(
6291 // if (typeof position == 'string' || $.isArray(position)) {
6292 // myAt = $.isArray(position) ? position : position.split(' ');
6294 if (typeof position === 'string' || (typeof position === 'object' && '0' in position)) {
6295 myAt = position.split ? position.split(' ') : [position[0], position[1]];
6296 if (myAt.length === 1) {
6300 $.each(['left', 'top'], function(i, offsetPosition) {
6301 if (+myAt[i] === myAt[i]) {
6302 offset[i] = myAt[i];
6303 myAt[i] = offsetPosition;
6310 offset: offset.join(" ")
6314 position = $.extend({}, $.ui.dialog.prototype.options.position, position);
6316 position = $.ui.dialog.prototype.options.position;
6319 // need to show the dialog to get the actual offset in the position plugin
6320 isVisible = this.uiDialog.is(':visible');
6322 this.uiDialog.show();
6325 // workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
6326 .css({ top: 0, left: 0 })
6327 .position($.extend({ of: window }, position));
6329 this.uiDialog.hide();
6333 _setOptions: function( options ) {
6335 resizableOptions = {},
6338 $.each( options, function( key, value ) {
6339 self._setOption( key, value );
6341 if ( key in sizeRelatedOptions ) {
6344 if ( key in resizableRelatedOptions ) {
6345 resizableOptions[ key ] = value;
6352 if ( this.uiDialog.is( ":data(resizable)" ) ) {
6353 this.uiDialog.resizable( "option", resizableOptions );
6357 _setOption: function(key, value){
6359 uiDialog = self.uiDialog;
6362 //handling of deprecated beforeclose (vs beforeClose) option
6363 //Ticket #4669 http://dev.jqueryui.com/ticket/4669
6364 //TODO: remove in 1.9pre
6366 key = "beforeClose";
6369 self._createButtons(value);
6372 // ensure that we always pass a string
6373 self.uiDialogTitlebarCloseText.text("" + value);
6377 .removeClass(self.options.dialogClass)
6378 .addClass(uiDialogClasses + value);
6382 uiDialog.addClass('ui-dialog-disabled');
6384 uiDialog.removeClass('ui-dialog-disabled');
6388 var isDraggable = uiDialog.is( ":data(draggable)" );
6389 if ( isDraggable && !value ) {
6390 uiDialog.draggable( "destroy" );
6393 if ( !isDraggable && value ) {
6394 self._makeDraggable();
6398 self._position(value);
6401 // currently resizable, becoming non-resizable
6402 var isResizable = uiDialog.is( ":data(resizable)" );
6403 if (isResizable && !value) {
6404 uiDialog.resizable('destroy');
6407 // currently resizable, changing handles
6408 if (isResizable && typeof value === 'string') {
6409 uiDialog.resizable('option', 'handles', value);
6412 // currently non-resizable, becoming resizable
6413 if (!isResizable && value !== false) {
6414 self._makeResizable(value);
6418 // convert whatever was passed in o a string, for html() to not throw up
6419 $(".ui-dialog-title", self.uiDialogTitlebar).html("" + (value || ' '));
6423 $.Widget.prototype._setOption.apply(self, arguments);
6427 /* If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
6428 * divs will both have width and height set, so we need to reset them
6430 var options = this.options,
6433 isVisible = this.uiDialog.is( ":visible" );
6435 // reset content sizing
6436 this.element.show().css({
6442 if (options.minWidth > options.width) {
6443 options.width = options.minWidth;
6446 // reset wrapper sizing
6447 // determine the height of all the non-content elements
6448 nonContentHeight = this.uiDialog.css({
6450 width: options.width
6453 minContentHeight = Math.max( 0, options.minHeight - nonContentHeight );
6455 if ( options.height === "auto" ) {
6456 // only needed for IE6 support
6457 if ( $.support.minHeight ) {
6459 minHeight: minContentHeight,
6463 this.uiDialog.show();
6464 var autoHeight = this.element.css( "height", "auto" ).height();
6466 this.uiDialog.hide();
6468 this.element.height( Math.max( autoHeight, minContentHeight ) );
6471 this.element.height( Math.max( options.height - nonContentHeight, 0 ) );
6474 if (this.uiDialog.is(':data(resizable)')) {
6475 this.uiDialog.resizable('option', 'minHeight', this._minHeight());
6480 $.extend($.ui.dialog, {
6486 getTitleId: function($el) {
6487 var id = $el.attr('id');
6492 return 'ui-dialog-title-' + id;
6495 overlay: function(dialog) {
6496 this.$el = $.ui.dialog.overlay.create(dialog);
6500 $.extend($.ui.dialog.overlay, {
6502 // reuse old instances due to IE memory leak with alpha transparency (see #5185)
6505 events: $.map('focus,mousedown,mouseup,keydown,keypress,click'.split(','),
6506 function(event) { return event + '.dialog-overlay'; }).join(' '),
6507 create: function(dialog) {
6508 if (this.instances.length === 0) {
6509 // prevent use of anchors and inputs
6510 // we use a setTimeout in case the overlay is created from an
6511 // event that we're going to be cancelling (see #2804)
6512 setTimeout(function() {
6513 // handle $(el).dialog().dialog('close') (see #4065)
6514 if ($.ui.dialog.overlay.instances.length) {
6515 $(document).bind($.ui.dialog.overlay.events, function(event) {
6516 // stop events if the z-index of the target is < the z-index of the overlay
6517 // we cannot return true when we don't want to cancel the event (#3523)
6518 if ($(event.target).zIndex() < $.ui.dialog.overlay.maxZ) {
6525 // allow closing by pressing the escape key
6526 $(document).bind('keydown.dialog-overlay', function(event) {
6527 if (dialog.options.closeOnEscape && event.keyCode &&
6528 event.keyCode === $.ui.keyCode.ESCAPE) {
6530 dialog.close(event);
6531 event.preventDefault();
6535 // handle window resize
6536 $(window).bind('resize.dialog-overlay', $.ui.dialog.overlay.resize);
6539 var $el = (this.oldInstances.pop() || $('<div></div>').addClass('ui-widget-overlay'))
6540 .appendTo(document.body)
6542 width: this.width(),
6543 height: this.height()
6546 if ($.fn.bgiframe) {
6550 this.instances.push($el);
6554 destroy: function($el) {
6555 var indexOf = $.inArray($el, this.instances);
6557 this.oldInstances.push(this.instances.splice(indexOf, 1)[0]);
6560 if (this.instances.length === 0) {
6561 $([document, window]).unbind('.dialog-overlay');
6566 // adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
6568 $.each(this.instances, function() {
6569 maxZ = Math.max(maxZ, this.css('z-index'));
6574 height: function() {
6578 if ($.browser.msie && $.browser.version < 7) {
6579 scrollHeight = Math.max(
6580 document.documentElement.scrollHeight,
6581 document.body.scrollHeight
6583 offsetHeight = Math.max(
6584 document.documentElement.offsetHeight,
6585 document.body.offsetHeight
6588 if (scrollHeight < offsetHeight) {
6589 return $(window).height() + 'px';
6591 return scrollHeight + 'px';
6593 // handle "good" browsers
6595 return $(document).height() + 'px';
6603 if ($.browser.msie && $.browser.version < 7) {
6604 scrollWidth = Math.max(
6605 document.documentElement.scrollWidth,
6606 document.body.scrollWidth
6608 offsetWidth = Math.max(
6609 document.documentElement.offsetWidth,
6610 document.body.offsetWidth
6613 if (scrollWidth < offsetWidth) {
6614 return $(window).width() + 'px';
6616 return scrollWidth + 'px';
6618 // handle "good" browsers
6620 return $(document).width() + 'px';
6624 resize: function() {
6625 /* If the dialog is draggable and the user drags it past the
6626 * right edge of the window, the document becomes wider so we
6627 * need to stretch the overlay. If the user then drags the
6628 * dialog back to the left, the document will become narrower,
6629 * so we need to shrink the overlay to the appropriate size.
6630 * This is handled by shrinking the overlay before setting it
6631 * to the full document size.
6633 var $overlays = $([]);
6634 $.each($.ui.dialog.overlay.instances, function() {
6635 $overlays = $overlays.add(this);
6642 width: $.ui.dialog.overlay.width(),
6643 height: $.ui.dialog.overlay.height()
6648 $.extend($.ui.dialog.overlay.prototype, {
6649 destroy: function() {
6650 $.ui.dialog.overlay.destroy(this.$el);
6656 * jQuery UI Slider 1.8.10
6658 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
6659 * Dual licensed under the MIT or GPL Version 2 licenses.
6660 * http://jquery.org/license
6662 * http://docs.jquery.com/UI/Slider
6666 * jquery.ui.mouse.js
6667 * jquery.ui.widget.js
6669 (function( $, undefined ) {
6671 // number of pages in a slider
6672 // (how many times can you page up/down to go through the whole range)
6675 $.widget( "ui.slider", $.ui.mouse, {
6677 widgetEventPrefix: "slide",
6684 orientation: "horizontal",
6691 _create: function() {
6695 this._keySliding = false;
6696 this._mouseSliding = false;
6697 this._animateOff = true;
6698 this._handleIndex = null;
6699 this._detectOrientation();
6703 .addClass( "ui-slider" +
6704 " ui-slider-" + this.orientation +
6706 " ui-widget-content" +
6710 this.element.addClass( "ui-slider-disabled ui-disabled" );
6716 if ( o.range === true ) {
6717 this.range = $( "<div></div>" );
6719 o.values = [ this._valueMin(), this._valueMin() ];
6721 if ( o.values.length && o.values.length !== 2 ) {
6722 o.values = [ o.values[0], o.values[0] ];
6725 this.range = $( "<div></div>" );
6729 .appendTo( this.element )
6730 .addClass( "ui-slider-range" );
6732 if ( o.range === "min" || o.range === "max" ) {
6733 this.range.addClass( "ui-slider-range-" + o.range );
6736 // note: this isn't the most fittingly semantic framework class for this element,
6737 // but worked best visually with a variety of themes
6738 this.range.addClass( "ui-widget-header" );
6741 if ( $( ".ui-slider-handle", this.element ).length === 0 ) {
6742 $( "<a href='#'></a>" )
6743 .appendTo( this.element )
6744 .addClass( "ui-slider-handle" );
6747 if ( o.values && o.values.length ) {
6748 while ( $(".ui-slider-handle", this.element).length < o.values.length ) {
6749 $( "<a href='#'></a>" )
6750 .appendTo( this.element )
6751 .addClass( "ui-slider-handle" );
6755 this.handles = $( ".ui-slider-handle", this.element )
6756 .addClass( "ui-state-default" +
6759 this.handle = this.handles.eq( 0 );
6761 this.handles.add( this.range ).filter( "a" )
6762 .click(function( event ) {
6763 event.preventDefault();
6766 if ( !o.disabled ) {
6767 $( this ).addClass( "ui-state-hover" );
6770 $( this ).removeClass( "ui-state-hover" );
6773 if ( !o.disabled ) {
6774 $( ".ui-slider .ui-state-focus" ).removeClass( "ui-state-focus" );
6775 $( this ).addClass( "ui-state-focus" );
6781 $( this ).removeClass( "ui-state-focus" );
6784 this.handles.each(function( i ) {
6785 $( this ).data( "index.ui-slider-handle", i );
6789 .keydown(function( event ) {
6791 index = $( this ).data( "index.ui-slider-handle" ),
6797 if ( self.options.disabled ) {
6801 switch ( event.keyCode ) {
6802 case $.ui.keyCode.HOME:
6803 case $.ui.keyCode.END:
6804 case $.ui.keyCode.PAGE_UP:
6805 case $.ui.keyCode.PAGE_DOWN:
6806 case $.ui.keyCode.UP:
6807 case $.ui.keyCode.RIGHT:
6808 case $.ui.keyCode.DOWN:
6809 case $.ui.keyCode.LEFT:
6811 if ( !self._keySliding ) {
6812 self._keySliding = true;
6813 $( this ).addClass( "ui-state-active" );
6814 allowed = self._start( event, index );
6815 if ( allowed === false ) {
6822 step = self.options.step;
6823 if ( self.options.values && self.options.values.length ) {
6824 curVal = newVal = self.values( index );
6826 curVal = newVal = self.value();
6829 switch ( event.keyCode ) {
6830 case $.ui.keyCode.HOME:
6831 newVal = self._valueMin();
6833 case $.ui.keyCode.END:
6834 newVal = self._valueMax();
6836 case $.ui.keyCode.PAGE_UP:
6837 newVal = self._trimAlignValue( curVal + ( (self._valueMax() - self._valueMin()) / numPages ) );
6839 case $.ui.keyCode.PAGE_DOWN:
6840 newVal = self._trimAlignValue( curVal - ( (self._valueMax() - self._valueMin()) / numPages ) );
6842 case $.ui.keyCode.UP:
6843 case $.ui.keyCode.RIGHT:
6844 if ( curVal === self._valueMax() ) {
6847 newVal = self._trimAlignValue( curVal + step );
6849 case $.ui.keyCode.DOWN:
6850 case $.ui.keyCode.LEFT:
6851 if ( curVal === self._valueMin() ) {
6854 newVal = self._trimAlignValue( curVal - step );
6858 self._slide( event, index, newVal );
6863 .keyup(function( event ) {
6864 var index = $( this ).data( "index.ui-slider-handle" );
6866 if ( self._keySliding ) {
6867 self._keySliding = false;
6868 self._stop( event, index );
6869 self._change( event, index );
6870 $( this ).removeClass( "ui-state-active" );
6875 this._refreshValue();
6877 this._animateOff = false;
6880 destroy: function() {
6881 this.handles.remove();
6882 this.range.remove();
6885 .removeClass( "ui-slider" +
6886 " ui-slider-horizontal" +
6887 " ui-slider-vertical" +
6888 " ui-slider-disabled" +
6890 " ui-widget-content" +
6892 .removeData( "slider" )
6893 .unbind( ".slider" );
6895 this._mouseDestroy();
6900 _mouseCapture: function( event ) {
6901 var o = this.options,
6916 this.elementSize = {
6917 width: this.element.outerWidth(),
6918 height: this.element.outerHeight()
6920 this.elementOffset = this.element.offset();
6922 position = { x: event.pageX, y: event.pageY };
6923 normValue = this._normValueFromMouse( position );
6924 distance = this._valueMax() - this._valueMin() + 1;
6926 this.handles.each(function( i ) {
6927 var thisDistance = Math.abs( normValue - self.values(i) );
6928 if ( distance > thisDistance ) {
6929 distance = thisDistance;
6930 closestHandle = $( this );
6935 // workaround for bug #3736 (if both handles of a range are at 0,
6936 // the first is always used as the one with least distance,
6937 // and moving it is obviously prevented by preventing negative ranges)
6938 if( o.range === true && this.values(1) === o.min ) {
6940 closestHandle = $( this.handles[index] );
6943 allowed = this._start( event, index );
6944 if ( allowed === false ) {
6947 this._mouseSliding = true;
6949 self._handleIndex = index;
6952 .addClass( "ui-state-active" )
6955 offset = closestHandle.offset();
6956 mouseOverHandle = !$( event.target ).parents().andSelf().is( ".ui-slider-handle" );
6957 this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
6958 left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
6959 top: event.pageY - offset.top -
6960 ( closestHandle.height() / 2 ) -
6961 ( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) -
6962 ( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) +
6963 ( parseInt( closestHandle.css("marginTop"), 10 ) || 0)
6966 if ( !this.handles.hasClass( "ui-state-hover" ) ) {
6967 this._slide( event, index, normValue );
6969 this._animateOff = true;
6973 _mouseStart: function( event ) {
6977 _mouseDrag: function( event ) {
6978 var position = { x: event.pageX, y: event.pageY },
6979 normValue = this._normValueFromMouse( position );
6981 this._slide( event, this._handleIndex, normValue );
6986 _mouseStop: function( event ) {
6987 this.handles.removeClass( "ui-state-active" );
6988 this._mouseSliding = false;
6990 this._stop( event, this._handleIndex );
6991 this._change( event, this._handleIndex );
6993 this._handleIndex = null;
6994 this._clickOffset = null;
6995 this._animateOff = false;
7000 _detectOrientation: function() {
7001 this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
7004 _normValueFromMouse: function( position ) {
7011 if ( this.orientation === "horizontal" ) {
7012 pixelTotal = this.elementSize.width;
7013 pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 );
7015 pixelTotal = this.elementSize.height;
7016 pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 );
7019 percentMouse = ( pixelMouse / pixelTotal );
7020 if ( percentMouse > 1 ) {
7023 if ( percentMouse < 0 ) {
7026 if ( this.orientation === "vertical" ) {
7027 percentMouse = 1 - percentMouse;
7030 valueTotal = this._valueMax() - this._valueMin();
7031 valueMouse = this._valueMin() + percentMouse * valueTotal;
7033 return this._trimAlignValue( valueMouse );
7036 _start: function( event, index ) {
7038 handle: this.handles[ index ],
7041 if ( this.options.values && this.options.values.length ) {
7042 uiHash.value = this.values( index );
7043 uiHash.values = this.values();
7045 return this._trigger( "start", event, uiHash );
7048 _slide: function( event, index, newVal ) {
7053 if ( this.options.values && this.options.values.length ) {
7054 otherVal = this.values( index ? 0 : 1 );
7056 if ( ( this.options.values.length === 2 && this.options.range === true ) &&
7057 ( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) )
7062 if ( newVal !== this.values( index ) ) {
7063 newValues = this.values();
7064 newValues[ index ] = newVal;
7065 // A slide can be canceled by returning false from the slide callback
7066 allowed = this._trigger( "slide", event, {
7067 handle: this.handles[ index ],
7071 otherVal = this.values( index ? 0 : 1 );
7072 if ( allowed !== false ) {
7073 this.values( index, newVal, true );
7077 if ( newVal !== this.value() ) {
7078 // A slide can be canceled by returning false from the slide callback
7079 allowed = this._trigger( "slide", event, {
7080 handle: this.handles[ index ],
7083 if ( allowed !== false ) {
7084 this.value( newVal );
7090 _stop: function( event, index ) {
7092 handle: this.handles[ index ],
7095 if ( this.options.values && this.options.values.length ) {
7096 uiHash.value = this.values( index );
7097 uiHash.values = this.values();
7100 this._trigger( "stop", event, uiHash );
7103 _change: function( event, index ) {
7104 if ( !this._keySliding && !this._mouseSliding ) {
7106 handle: this.handles[ index ],
7109 if ( this.options.values && this.options.values.length ) {
7110 uiHash.value = this.values( index );
7111 uiHash.values = this.values();
7114 this._trigger( "change", event, uiHash );
7118 value: function( newValue ) {
7119 if ( arguments.length ) {
7120 this.options.value = this._trimAlignValue( newValue );
7121 this._refreshValue();
7122 this._change( null, 0 );
7125 return this._value();
7128 values: function( index, newValue ) {
7133 if ( arguments.length > 1 ) {
7134 this.options.values[ index ] = this._trimAlignValue( newValue );
7135 this._refreshValue();
7136 this._change( null, index );
7139 if ( arguments.length ) {
7140 if ( $.isArray( arguments[ 0 ] ) ) {
7141 vals = this.options.values;
7142 newValues = arguments[ 0 ];
7143 for ( i = 0; i < vals.length; i += 1 ) {
7144 vals[ i ] = this._trimAlignValue( newValues[ i ] );
7145 this._change( null, i );
7147 this._refreshValue();
7149 if ( this.options.values && this.options.values.length ) {
7150 return this._values( index );
7152 return this.value();
7156 return this._values();
7160 _setOption: function( key, value ) {
7164 if ( $.isArray( this.options.values ) ) {
7165 valsLength = this.options.values.length;
7168 $.Widget.prototype._setOption.apply( this, arguments );
7173 this.handles.filter( ".ui-state-focus" ).blur();
7174 this.handles.removeClass( "ui-state-hover" );
7175 this.handles.attr( "disabled", "disabled" );
7176 this.element.addClass( "ui-disabled" );
7178 this.handles.removeAttr( "disabled" );
7179 this.element.removeClass( "ui-disabled" );
7183 this._detectOrientation();
7185 .removeClass( "ui-slider-horizontal ui-slider-vertical" )
7186 .addClass( "ui-slider-" + this.orientation );
7187 this._refreshValue();
7190 this._animateOff = true;
7191 this._refreshValue();
7192 this._change( null, 0 );
7193 this._animateOff = false;
7196 this._animateOff = true;
7197 this._refreshValue();
7198 for ( i = 0; i < valsLength; i += 1 ) {
7199 this._change( null, i );
7201 this._animateOff = false;
7206 //internal value getter
7207 // _value() returns value trimmed by min and max, aligned by step
7208 _value: function() {
7209 var val = this.options.value;
7210 val = this._trimAlignValue( val );
7215 //internal values getter
7216 // _values() returns array of values trimmed by min and max, aligned by step
7217 // _values( index ) returns single value trimmed by min and max, aligned by step
7218 _values: function( index ) {
7223 if ( arguments.length ) {
7224 val = this.options.values[ index ];
7225 val = this._trimAlignValue( val );
7229 // .slice() creates a copy of the array
7230 // this copy gets trimmed by min and max and then returned
7231 vals = this.options.values.slice();
7232 for ( i = 0; i < vals.length; i+= 1) {
7233 vals[ i ] = this._trimAlignValue( vals[ i ] );
7240 // returns the step-aligned value that val is closest to, between (inclusive) min and max
7241 _trimAlignValue: function( val ) {
7242 if ( val <= this._valueMin() ) {
7243 return this._valueMin();
7245 if ( val >= this._valueMax() ) {
7246 return this._valueMax();
7248 var step = ( this.options.step > 0 ) ? this.options.step : 1,
7249 valModStep = (val - this._valueMin()) % step;
7250 alignValue = val - valModStep;
7252 if ( Math.abs(valModStep) * 2 >= step ) {
7253 alignValue += ( valModStep > 0 ) ? step : ( -step );
7256 // Since JavaScript has problems with large floats, round
7257 // the final value to 5 digits after the decimal point (see #4124)
7258 return parseFloat( alignValue.toFixed(5) );
7261 _valueMin: function() {
7262 return this.options.min;
7265 _valueMax: function() {
7266 return this.options.max;
7269 _refreshValue: function() {
7270 var oRange = this.options.range,
7273 animate = ( !this._animateOff ) ? o.animate : false,
7281 if ( this.options.values && this.options.values.length ) {
7282 this.handles.each(function( i, j ) {
7283 valPercent = ( self.values(i) - self._valueMin() ) / ( self._valueMax() - self._valueMin() ) * 100;
7284 _set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
7285 $( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
7286 if ( self.options.range === true ) {
7287 if ( self.orientation === "horizontal" ) {
7289 self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate );
7292 self.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
7296 self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate );
7299 self.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
7303 lastValPercent = valPercent;
7306 value = this.value();
7307 valueMin = this._valueMin();
7308 valueMax = this._valueMax();
7309 valPercent = ( valueMax !== valueMin ) ?
7310 ( value - valueMin ) / ( valueMax - valueMin ) * 100 :
7312 _set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
7313 this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
7315 if ( oRange === "min" && this.orientation === "horizontal" ) {
7316 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate );
7318 if ( oRange === "max" && this.orientation === "horizontal" ) {
7319 this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
7321 if ( oRange === "min" && this.orientation === "vertical" ) {
7322 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate );
7324 if ( oRange === "max" && this.orientation === "vertical" ) {
7325 this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
7332 $.extend( $.ui.slider, {
7338 * jQuery UI Tabs 1.8.10
7340 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
7341 * Dual licensed under the MIT or GPL Version 2 licenses.
7342 * http://jquery.org/license
7344 * http://docs.jquery.com/UI/Tabs
7348 * jquery.ui.widget.js
7350 (function( $, undefined ) {
7355 function getNextTabId() {
7359 function getNextListId() {
7363 $.widget( "ui.tabs", {
7368 cookie: null, // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true }
7374 fx: null, // e.g. { height: 'toggle', opacity: 'toggle', duration: 200 }
7375 idPrefix: "ui-tabs-",
7377 panelTemplate: "<div></div>",
7381 spinner: "<em>Loading…</em>",
7382 tabTemplate: "<li><a href='#{href}'><span>#{label}</span></a></li>"
7385 _create: function() {
7386 this._tabify( true );
7389 _setOption: function( key, value ) {
7390 if ( key == "selected" ) {
7391 if (this.options.collapsible && value == this.options.selected ) {
7394 this.select( value );
7396 this.options[ key ] = value;
7401 _tabId: function( a ) {
7402 return a.title && a.title.replace( /\s/g, "_" ).replace( /[^\w\u00c0-\uFFFF-]/g, "" ) ||
7403 this.options.idPrefix + getNextTabId();
7406 _sanitizeSelector: function( hash ) {
7407 // we need this because an id may contain a ":"
7408 return hash.replace( /:/g, "\\:" );
7411 _cookie: function() {
7412 var cookie = this.cookie ||
7413 ( this.cookie = this.options.cookie.name || "ui-tabs-" + getNextListId() );
7414 return $.cookie.apply( null, [ cookie ].concat( $.makeArray( arguments ) ) );
7417 _ui: function( tab, panel ) {
7421 index: this.anchors.index( tab )
7425 _cleanup: function() {
7426 // restore all former loading tabs labels
7427 this.lis.filter( ".ui-state-processing" )
7428 .removeClass( "ui-state-processing" )
7429 .find( "span:data(label.tabs)" )
7432 el.html( el.data( "label.tabs" ) ).removeData( "label.tabs" );
7436 _tabify: function( init ) {
7439 fragmentId = /^#.+/; // Safari 2 reports '#' for an empty hash
7441 this.list = this.element.find( "ol,ul" ).eq( 0 );
7442 this.lis = $( " > li:has(a[href])", this.list );
7443 this.anchors = this.lis.map(function() {
7444 return $( "a", this )[ 0 ];
7446 this.panels = $( [] );
7448 this.anchors.each(function( i, a ) {
7449 var href = $( a ).attr( "href" );
7450 // For dynamically created HTML that contains a hash as href IE < 8 expands
7451 // such href to the full page url with hash and then misinterprets tab as ajax.
7452 // Same consideration applies for an added tab with a fragment identifier
7453 // since a[href=#fragment-identifier] does unexpectedly not match.
7454 // Thus normalize href attribute...
7455 var hrefBase = href.split( "#" )[ 0 ],
7457 if ( hrefBase && ( hrefBase === location.toString().split( "#" )[ 0 ] ||
7458 ( baseEl = $( "base" )[ 0 ]) && hrefBase === baseEl.href ) ) {
7464 if ( fragmentId.test( href ) ) {
7465 self.panels = self.panels.add( self.element.find( self._sanitizeSelector( href ) ) );
7467 // prevent loading the page itself if href is just "#"
7468 } else if ( href && href !== "#" ) {
7469 // required for restore on destroy
7470 $.data( a, "href.tabs", href );
7472 // TODO until #3808 is fixed strip fragment identifier from url
7473 // (IE fails to load from such url)
7474 $.data( a, "load.tabs", href.replace( /#.*$/, "" ) );
7476 var id = self._tabId( a );
7478 var $panel = self.element.find( "#" + id );
7479 if ( !$panel.length ) {
7480 $panel = $( o.panelTemplate )
7482 .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
7483 .insertAfter( self.panels[ i - 1 ] || self.list );
7484 $panel.data( "destroy.tabs", true );
7486 self.panels = self.panels.add( $panel );
7489 o.disabled.push( i );
7493 // initialization from scratch
7495 // attach necessary classes for styling
7496 this.element.addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" );
7497 this.list.addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" );
7498 this.lis.addClass( "ui-state-default ui-corner-top" );
7499 this.panels.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" );
7502 // use "selected" option or try to retrieve:
7503 // 1. from fragment identifier in url
7505 // 3. from selected class attribute on <li>
7506 if ( o.selected === undefined ) {
7507 if ( location.hash ) {
7508 this.anchors.each(function( i, a ) {
7509 if ( a.hash == location.hash ) {
7515 if ( typeof o.selected !== "number" && o.cookie ) {
7516 o.selected = parseInt( self._cookie(), 10 );
7518 if ( typeof o.selected !== "number" && this.lis.filter( ".ui-tabs-selected" ).length ) {
7519 o.selected = this.lis.index( this.lis.filter( ".ui-tabs-selected" ) );
7521 o.selected = o.selected || ( this.lis.length ? 0 : -1 );
7522 } else if ( o.selected === null ) { // usage of null is deprecated, TODO remove in next release
7526 // sanity check - default to first tab...
7527 o.selected = ( ( o.selected >= 0 && this.anchors[ o.selected ] ) || o.selected < 0 )
7531 // Take disabling tabs via class attribute from HTML
7532 // into account and update option properly.
7533 // A selected tab cannot become disabled.
7534 o.disabled = $.unique( o.disabled.concat(
7535 $.map( this.lis.filter( ".ui-state-disabled" ), function( n, i ) {
7536 return self.lis.index( n );
7540 if ( $.inArray( o.selected, o.disabled ) != -1 ) {
7541 o.disabled.splice( $.inArray( o.selected, o.disabled ), 1 );
7544 // highlight selected tab
7545 this.panels.addClass( "ui-tabs-hide" );
7546 this.lis.removeClass( "ui-tabs-selected ui-state-active" );
7547 // check for length avoids error when initializing empty list
7548 if ( o.selected >= 0 && this.anchors.length ) {
7549 self.element.find( self._sanitizeSelector( self.anchors[ o.selected ].hash ) ).removeClass( "ui-tabs-hide" );
7550 this.lis.eq( o.selected ).addClass( "ui-tabs-selected ui-state-active" );
7552 // seems to be expected behavior that the show callback is fired
7553 self.element.queue( "tabs", function() {
7554 self._trigger( "show", null,
7555 self._ui( self.anchors[ o.selected ], self.element.find( self._sanitizeSelector( self.anchors[ o.selected ].hash ) )[ 0 ] ) );
7558 this.load( o.selected );
7561 // clean up to avoid memory leaks in certain versions of IE 6
7562 // TODO: namespace this event
7563 $( window ).bind( "unload", function() {
7564 self.lis.add( self.anchors ).unbind( ".tabs" );
7565 self.lis = self.anchors = self.panels = null;
7567 // update selected after add/remove
7569 o.selected = this.lis.index( this.lis.filter( ".ui-tabs-selected" ) );
7572 // update collapsible
7573 // TODO: use .toggleClass()
7574 this.element[ o.collapsible ? "addClass" : "removeClass" ]( "ui-tabs-collapsible" );
7576 // set or update cookie after init and add/remove respectively
7578 this._cookie( o.selected, o.cookie );
7582 for ( var i = 0, li; ( li = this.lis[ i ] ); i++ ) {
7583 $( li )[ $.inArray( i, o.disabled ) != -1 &&
7584 // TODO: use .toggleClass()
7585 !$( li ).hasClass( "ui-tabs-selected" ) ? "addClass" : "removeClass" ]( "ui-state-disabled" );
7588 // reset cache if switching from cached to not cached
7589 if ( o.cache === false ) {
7590 this.anchors.removeData( "cache.tabs" );
7593 // remove all handlers before, tabify may run on existing tabs after add or option change
7594 this.lis.add( this.anchors ).unbind( ".tabs" );
7596 if ( o.event !== "mouseover" ) {
7597 var addState = function( state, el ) {
7598 if ( el.is( ":not(.ui-state-disabled)" ) ) {
7599 el.addClass( "ui-state-" + state );
7602 var removeState = function( state, el ) {
7603 el.removeClass( "ui-state-" + state );
7605 this.lis.bind( "mouseover.tabs" , function() {
7606 addState( "hover", $( this ) );
7608 this.lis.bind( "mouseout.tabs", function() {
7609 removeState( "hover", $( this ) );
7611 this.anchors.bind( "focus.tabs", function() {
7612 addState( "focus", $( this ).closest( "li" ) );
7614 this.anchors.bind( "blur.tabs", function() {
7615 removeState( "focus", $( this ).closest( "li" ) );
7619 // set up animations
7622 if ( $.isArray( o.fx ) ) {
7626 hideFx = showFx = o.fx;
7630 // Reset certain styles left over from animation
7631 // and prevent IE's ClearType bug...
7632 function resetStyle( $el, fx ) {
7633 $el.css( "display", "" );
7634 if ( !$.support.opacity && fx.opacity ) {
7635 $el[ 0 ].style.removeAttribute( "filter" );
7640 var showTab = showFx
7641 ? function( clicked, $show ) {
7642 $( clicked ).closest( "li" ).addClass( "ui-tabs-selected ui-state-active" );
7643 $show.hide().removeClass( "ui-tabs-hide" ) // avoid flicker that way
7644 .animate( showFx, showFx.duration || "normal", function() {
7645 resetStyle( $show, showFx );
7646 self._trigger( "show", null, self._ui( clicked, $show[ 0 ] ) );
7649 : function( clicked, $show ) {
7650 $( clicked ).closest( "li" ).addClass( "ui-tabs-selected ui-state-active" );
7651 $show.removeClass( "ui-tabs-hide" );
7652 self._trigger( "show", null, self._ui( clicked, $show[ 0 ] ) );
7655 // Hide a tab, $show is optional...
7656 var hideTab = hideFx
7657 ? function( clicked, $hide ) {
7658 $hide.animate( hideFx, hideFx.duration || "normal", function() {
7659 self.lis.removeClass( "ui-tabs-selected ui-state-active" );
7660 $hide.addClass( "ui-tabs-hide" );
7661 resetStyle( $hide, hideFx );
7662 self.element.dequeue( "tabs" );
7665 : function( clicked, $hide, $show ) {
7666 self.lis.removeClass( "ui-tabs-selected ui-state-active" );
7667 $hide.addClass( "ui-tabs-hide" );
7668 self.element.dequeue( "tabs" );
7671 // attach tab event handler, unbind to avoid duplicates from former tabifying...
7672 this.anchors.bind( o.event + ".tabs", function() {
7674 $li = $(el).closest( "li" ),
7675 $hide = self.panels.filter( ":not(.ui-tabs-hide)" ),
7676 $show = self.element.find( self._sanitizeSelector( el.hash ) );
7678 // If tab is already selected and not collapsible or tab disabled or
7679 // or is already loading or click callback returns false stop here.
7680 // Check if click handler returns false last so that it is not executed
7681 // for a disabled or loading tab!
7682 if ( ( $li.hasClass( "ui-tabs-selected" ) && !o.collapsible) ||
7683 $li.hasClass( "ui-state-disabled" ) ||
7684 $li.hasClass( "ui-state-processing" ) ||
7685 self.panels.filter( ":animated" ).length ||
7686 self._trigger( "select", null, self._ui( this, $show[ 0 ] ) ) === false ) {
7691 o.selected = self.anchors.index( this );
7695 // if tab may be closed
7696 if ( o.collapsible ) {
7697 if ( $li.hasClass( "ui-tabs-selected" ) ) {
7701 self._cookie( o.selected, o.cookie );
7704 self.element.queue( "tabs", function() {
7705 hideTab( el, $hide );
7706 }).dequeue( "tabs" );
7710 } else if ( !$hide.length ) {
7712 self._cookie( o.selected, o.cookie );
7715 self.element.queue( "tabs", function() {
7716 showTab( el, $show );
7719 // TODO make passing in node possible, see also http://dev.jqueryui.com/ticket/3171
7720 self.load( self.anchors.index( this ) );
7728 self._cookie( o.selected, o.cookie );
7732 if ( $show.length ) {
7733 if ( $hide.length ) {
7734 self.element.queue( "tabs", function() {
7735 hideTab( el, $hide );
7738 self.element.queue( "tabs", function() {
7739 showTab( el, $show );
7742 self.load( self.anchors.index( this ) );
7744 throw "jQuery UI Tabs: Mismatching fragment identifier.";
7747 // Prevent IE from keeping other link focussed when using the back button
7748 // and remove dotted border from clicked link. This is controlled via CSS
7749 // in modern browsers; blur() removes focus from address bar in Firefox
7750 // which can become a usability and annoying problem with tabs('rotate').
7751 if ( $.browser.msie ) {
7756 // disable click in any case
7757 this.anchors.bind( "click.tabs", function(){
7762 _getIndex: function( index ) {
7763 // meta-function to give users option to provide a href string instead of a numerical index.
7764 // also sanitizes numerical indexes to valid values.
7765 if ( typeof index == "string" ) {
7766 index = this.anchors.index( this.anchors.filter( "[href$=" + index + "]" ) );
7772 destroy: function() {
7773 var o = this.options;
7779 .removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" )
7780 .removeData( "tabs" );
7782 this.list.removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" );
7784 this.anchors.each(function() {
7785 var href = $.data( this, "href.tabs" );
7789 var $this = $( this ).unbind( ".tabs" );
7790 $.each( [ "href", "load", "cache" ], function( i, prefix ) {
7791 $this.removeData( prefix + ".tabs" );
7795 this.lis.unbind( ".tabs" ).add( this.panels ).each(function() {
7796 if ( $.data( this, "destroy.tabs" ) ) {
7799 $( this ).removeClass([
7806 "ui-state-disabled",
7808 "ui-widget-content",
7816 this._cookie( null, o.cookie );
7822 add: function( url, label, index ) {
7823 if ( index === undefined ) {
7824 index = this.anchors.length;
7829 $li = $( o.tabTemplate.replace( /#\{href\}/g, url ).replace( /#\{label\}/g, label ) ),
7830 id = !url.indexOf( "#" ) ? url.replace( "#", "" ) : this._tabId( $( "a", $li )[ 0 ] );
7832 $li.addClass( "ui-state-default ui-corner-top" ).data( "destroy.tabs", true );
7834 // try to find an existing element before creating a new one
7835 var $panel = self.element.find( "#" + id );
7836 if ( !$panel.length ) {
7837 $panel = $( o.panelTemplate )
7839 .data( "destroy.tabs", true );
7841 $panel.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide" );
7843 if ( index >= this.lis.length ) {
7844 $li.appendTo( this.list );
7845 $panel.appendTo( this.list[ 0 ].parentNode );
7847 $li.insertBefore( this.lis[ index ] );
7848 $panel.insertBefore( this.panels[ index ] );
7851 o.disabled = $.map( o.disabled, function( n, i ) {
7852 return n >= index ? ++n : n;
7857 if ( this.anchors.length == 1 ) {
7859 $li.addClass( "ui-tabs-selected ui-state-active" );
7860 $panel.removeClass( "ui-tabs-hide" );
7861 this.element.queue( "tabs", function() {
7862 self._trigger( "show", null, self._ui( self.anchors[ 0 ], self.panels[ 0 ] ) );
7868 this._trigger( "add", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
7872 remove: function( index ) {
7873 index = this._getIndex( index );
7874 var o = this.options,
7875 $li = this.lis.eq( index ).remove(),
7876 $panel = this.panels.eq( index ).remove();
7878 // If selected tab was removed focus tab to the right or
7879 // in case the last tab was removed the tab to the left.
7880 if ( $li.hasClass( "ui-tabs-selected" ) && this.anchors.length > 1) {
7881 this.select( index + ( index + 1 < this.anchors.length ? 1 : -1 ) );
7885 $.grep( o.disabled, function(n, i) {
7889 return n >= index ? --n : n;
7894 this._trigger( "remove", null, this._ui( $li.find( "a" )[ 0 ], $panel[ 0 ] ) );
7898 enable: function( index ) {
7899 index = this._getIndex( index );
7900 var o = this.options;
7901 if ( $.inArray( index, o.disabled ) == -1 ) {
7905 this.lis.eq( index ).removeClass( "ui-state-disabled" );
7906 o.disabled = $.grep( o.disabled, function( n, i ) {
7910 this._trigger( "enable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
7914 disable: function( index ) {
7915 index = this._getIndex( index );
7916 var self = this, o = this.options;
7917 // cannot disable already selected tab
7918 if ( index != o.selected ) {
7919 this.lis.eq( index ).addClass( "ui-state-disabled" );
7921 o.disabled.push( index );
7924 this._trigger( "disable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
7930 select: function( index ) {
7931 index = this._getIndex( index );
7932 if ( index == -1 ) {
7933 if ( this.options.collapsible && this.options.selected != -1 ) {
7934 index = this.options.selected;
7939 this.anchors.eq( index ).trigger( this.options.event + ".tabs" );
7943 load: function( index ) {
7944 index = this._getIndex( index );
7947 a = this.anchors.eq( index )[ 0 ],
7948 url = $.data( a, "load.tabs" );
7952 // not remote or from cache
7953 if ( !url || this.element.queue( "tabs" ).length !== 0 && $.data( a, "cache.tabs" ) ) {
7954 this.element.dequeue( "tabs" );
7958 // load remote from here on
7959 this.lis.eq( index ).addClass( "ui-state-processing" );
7962 var span = $( "span", a );
7963 span.data( "label.tabs", span.html() ).html( o.spinner );
7966 this.xhr = $.ajax( $.extend( {}, o.ajaxOptions, {
7968 success: function( r, s ) {
7969 self.element.find( self._sanitizeSelector( a.hash ) ).html( r );
7971 // take care of tab labels
7975 $.data( a, "cache.tabs", true );
7978 self._trigger( "load", null, self._ui( self.anchors[ index ], self.panels[ index ] ) );
7980 o.ajaxOptions.success( r, s );
7984 error: function( xhr, s, e ) {
7985 // take care of tab labels
7988 self._trigger( "load", null, self._ui( self.anchors[ index ], self.panels[ index ] ) );
7990 // Passing index avoid a race condition when this method is
7991 // called after the user has selected another tab.
7992 // Pass the anchor that initiated this request allows
7993 // loadError to manipulate the tab content panel via $(a.hash)
7994 o.ajaxOptions.error( xhr, s, index, a );
8000 // last, so that load event is fired before show...
8001 self.element.dequeue( "tabs" );
8007 // stop possibly running animations
8008 this.element.queue( [] );
8009 this.panels.stop( false, true );
8011 // "tabs" queue must not contain more than two elements,
8012 // which are the callbacks for the latest clicked tab...
8013 this.element.queue( "tabs", this.element.queue( "tabs" ).splice( -2, 2 ) );
8015 // terminate pending requests from other tabs
8021 // take care of tab labels
8026 url: function( index, url ) {
8027 this.anchors.eq( index ).removeData( "cache.tabs" ).data( "load.tabs", url );
8031 length: function() {
8032 return this.anchors.length;
8036 $.extend( $.ui.tabs, {
8047 $.extend( $.ui.tabs.prototype, {
8049 rotate: function( ms, continuing ) {
8053 var rotate = self._rotate || ( self._rotate = function( e ) {
8054 clearTimeout( self.rotation );
8055 self.rotation = setTimeout(function() {
8057 self.select( ++t < self.anchors.length ? t : 0 );
8061 e.stopPropagation();
8065 var stop = self._unrotate || ( self._unrotate = !continuing
8067 if (e.clientX) { // in case of a true click
8078 this.element.bind( "tabsshow", rotate );
8079 this.anchors.bind( o.event + ".tabs", stop );
8083 clearTimeout( self.rotation );
8084 this.element.unbind( "tabsshow", rotate );
8085 this.anchors.unbind( o.event + ".tabs", stop );
8086 delete this._rotate;
8087 delete this._unrotate;
8096 * jQuery UI Datepicker 1.8.10
8098 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
8099 * Dual licensed under the MIT or GPL Version 2 licenses.
8100 * http://jquery.org/license
8102 * http://docs.jquery.com/UI/Datepicker
8107 (function( $, undefined ) {
8109 $.extend($.ui, { datepicker: { version: "1.8.10" } });
8111 var PROP_NAME = 'datepicker';
8112 var dpuuid = new Date().getTime();
8114 /* Date picker manager.
8115 Use the singleton instance of this class, $.datepicker, to interact with the date picker.
8116 Settings for (groups of) date pickers are maintained in an instance object,
8117 allowing multiple different settings on the same page. */
8119 function Datepicker() {
8120 this.debug = false; // Change this to true to start debugging
8121 this._curInst = null; // The current instance in use
8122 this._keyEvent = false; // If the last event was a key event
8123 this._disabledInputs = []; // List of date picker inputs that have been disabled
8124 this._datepickerShowing = false; // True if the popup picker is showing , false if not
8125 this._inDialog = false; // True if showing within a "dialog", false if not
8126 this._mainDivId = 'ui-datepicker-div'; // The ID of the main datepicker division
8127 this._inlineClass = 'ui-datepicker-inline'; // The name of the inline marker class
8128 this._appendClass = 'ui-datepicker-append'; // The name of the append marker class
8129 this._triggerClass = 'ui-datepicker-trigger'; // The name of the trigger marker class
8130 this._dialogClass = 'ui-datepicker-dialog'; // The name of the dialog marker class
8131 this._disableClass = 'ui-datepicker-disabled'; // The name of the disabled covering marker class
8132 this._unselectableClass = 'ui-datepicker-unselectable'; // The name of the unselectable cell marker class
8133 this._currentClass = 'ui-datepicker-current-day'; // The name of the current day marker class
8134 this._dayOverClass = 'ui-datepicker-days-cell-over'; // The name of the day hover marker class
8135 this.regional = []; // Available regional settings, indexed by language code
8136 this.regional[''] = { // Default regional settings
8137 closeText: 'Done', // Display text for close link
8138 prevText: 'Prev', // Display text for previous month link
8139 nextText: 'Next', // Display text for next month link
8140 currentText: 'Today', // Display text for current month link
8141 monthNames: ['January','February','March','April','May','June',
8142 'July','August','September','October','November','December'], // Names of months for drop-down and formatting
8143 monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], // For formatting
8144 dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], // For formatting
8145 dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], // For formatting
8146 dayNamesMin: ['Su','Mo','Tu','We','Th','Fr','Sa'], // Column headings for days starting at Sunday
8147 weekHeader: 'Wk', // Column header for week of the year
8148 dateFormat: 'mm/dd/yy', // See format options on parseDate
8149 firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
8150 isRTL: false, // True if right-to-left language, false if left-to-right
8151 showMonthAfterYear: false, // True if the year select precedes month, false for month then year
8152 yearSuffix: '' // Additional text to append to the year in the month headers
8154 this._defaults = { // Global defaults for all the date picker instances
8155 showOn: 'focus', // 'focus' for popup on focus,
8156 // 'button' for trigger button, or 'both' for either
8157 showAnim: 'fadeIn', // Name of jQuery animation for popup
8158 showOptions: {}, // Options for enhanced animations
8159 defaultDate: null, // Used when field is blank: actual date,
8160 // +/-number for offset from today, null for today
8161 appendText: '', // Display text following the input box, e.g. showing the format
8162 buttonText: '...', // Text for trigger button
8163 buttonImage: '', // URL for trigger button image
8164 buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
8165 hideIfNoPrevNext: false, // True to hide next/previous month links
8166 // if not applicable, false to just disable them
8167 navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
8168 gotoCurrent: false, // True if today link goes back to current selection instead
8169 changeMonth: false, // True if month can be selected directly, false if only prev/next
8170 changeYear: false, // True if year can be selected directly, false if only prev/next
8171 yearRange: 'c-10:c+10', // Range of years to display in drop-down,
8172 // either relative to today's year (-nn:+nn), relative to currently displayed year
8173 // (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
8174 showOtherMonths: false, // True to show dates in other months, false to leave blank
8175 selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
8176 showWeek: false, // True to show week of the year, false to not show it
8177 calculateWeek: this.iso8601Week, // How to calculate the week of the year,
8178 // takes a Date and returns the number of the week for it
8179 shortYearCutoff: '+10', // Short year values < this are in the current century,
8180 // > this are in the previous century,
8181 // string value starting with '+' for current year + value
8182 minDate: null, // The earliest selectable date, or null for no limit
8183 maxDate: null, // The latest selectable date, or null for no limit
8184 duration: 'fast', // Duration of display/closure
8185 beforeShowDay: null, // Function that takes a date and returns an array with
8186 // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or '',
8187 // [2] = cell title (optional), e.g. $.datepicker.noWeekends
8188 beforeShow: null, // Function that takes an input field and
8189 // returns a set of custom settings for the date picker
8190 onSelect: null, // Define a callback function when a date is selected
8191 onChangeMonthYear: null, // Define a callback function when the month or year is changed
8192 onClose: null, // Define a callback function when the datepicker is closed
8193 numberOfMonths: 1, // Number of months to show at a time
8194 showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
8195 stepMonths: 1, // Number of months to step back/forward
8196 stepBigMonths: 12, // Number of months to step back/forward for the big links
8197 altField: '', // Selector for an alternate field to store selected dates into
8198 altFormat: '', // The date format to use for the alternate field
8199 constrainInput: true, // The input is constrained by the current date format
8200 showButtonPanel: false, // True to show button panel, false to not show it
8201 autoSize: false // True to size the input for the date format, false to leave as is
8203 $.extend(this._defaults, this.regional['']);
8204 this.dpDiv = $('<div id="' + this._mainDivId + '" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>');
8207 $.extend(Datepicker.prototype, {
8208 /* Class name added to elements to indicate already configured with a date picker. */
8209 markerClassName: 'hasDatepicker',
8211 /* Debug logging (if enabled). */
8214 console.log.apply('', arguments);
8217 // TODO rename to "widget" when switching to widget factory
8218 _widgetDatepicker: function() {
8222 /* Override the default settings for all instances of the date picker.
8223 @param settings object - the new settings to use as defaults (anonymous object)
8224 @return the manager object */
8225 setDefaults: function(settings) {
8226 extendRemove(this._defaults, settings || {});
8230 /* Attach the date picker to a jQuery selection.
8231 @param target element - the target input field or division or span
8232 @param settings object - the new settings to use for this date picker instance (anonymous) */
8233 _attachDatepicker: function(target, settings) {
8234 // check for settings on the control itself - in namespace 'date:'
8235 var inlineSettings = null;
8236 for (var attrName in this._defaults) {
8237 var attrValue = target.getAttribute('date:' + attrName);
8239 inlineSettings = inlineSettings || {};
8241 inlineSettings[attrName] = eval(attrValue);
8243 inlineSettings[attrName] = attrValue;
8247 var nodeName = target.nodeName.toLowerCase();
8248 var inline = (nodeName == 'div' || nodeName == 'span');
8251 target.id = 'dp' + this.uuid;
8253 var inst = this._newInst($(target), inline);
8254 inst.settings = $.extend({}, settings || {}, inlineSettings || {});
8255 if (nodeName == 'input') {
8256 this._connectDatepicker(target, inst);
8257 } else if (inline) {
8258 this._inlineDatepicker(target, inst);
8262 /* Create a new instance object. */
8263 _newInst: function(target, inline) {
8264 var id = target[0].id.replace(/([^A-Za-z0-9_-])/g, '\\\\$1'); // escape jQuery meta chars
8265 return {id: id, input: target, // associated target
8266 selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
8267 drawMonth: 0, drawYear: 0, // month being drawn
8268 inline: inline, // is datepicker inline or not
8269 dpDiv: (!inline ? this.dpDiv : // presentation div
8270 $('<div class="' + this._inlineClass + ' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>'))};
8273 /* Attach the date picker to an input field. */
8274 _connectDatepicker: function(target, inst) {
8275 var input = $(target);
8276 inst.append = $([]);
8277 inst.trigger = $([]);
8278 if (input.hasClass(this.markerClassName))
8280 this._attachments(input, inst);
8281 input.addClass(this.markerClassName).keydown(this._doKeyDown).
8282 keypress(this._doKeyPress).keyup(this._doKeyUp).
8283 bind("setData.datepicker", function(event, key, value) {
8284 inst.settings[key] = value;
8285 }).bind("getData.datepicker", function(event, key) {
8286 return this._get(inst, key);
8288 this._autoSize(inst);
8289 $.data(target, PROP_NAME, inst);
8292 /* Make attachments based on settings. */
8293 _attachments: function(input, inst) {
8294 var appendText = this._get(inst, 'appendText');
8295 var isRTL = this._get(inst, 'isRTL');
8297 inst.append.remove();
8299 inst.append = $('<span class="' + this._appendClass + '">' + appendText + '</span>');
8300 input[isRTL ? 'before' : 'after'](inst.append);
8302 input.unbind('focus', this._showDatepicker);
8304 inst.trigger.remove();
8305 var showOn = this._get(inst, 'showOn');
8306 if (showOn == 'focus' || showOn == 'both') // pop-up date picker when in the marked field
8307 input.focus(this._showDatepicker);
8308 if (showOn == 'button' || showOn == 'both') { // pop-up date picker when button clicked
8309 var buttonText = this._get(inst, 'buttonText');
8310 var buttonImage = this._get(inst, 'buttonImage');
8311 inst.trigger = $(this._get(inst, 'buttonImageOnly') ?
8312 $('<img/>').addClass(this._triggerClass).
8313 attr({ src: buttonImage, alt: buttonText, title: buttonText }) :
8314 $('<button type="button"></button>').addClass(this._triggerClass).
8315 html(buttonImage == '' ? buttonText : $('<img/>').attr(
8316 { src:buttonImage, alt:buttonText, title:buttonText })));
8317 input[isRTL ? 'before' : 'after'](inst.trigger);
8318 inst.trigger.click(function() {
8319 if ($.datepicker._datepickerShowing && $.datepicker._lastInput == input[0])
8320 $.datepicker._hideDatepicker();
8322 $.datepicker._showDatepicker(input[0]);
8328 /* Apply the maximum length for the date format. */
8329 _autoSize: function(inst) {
8330 if (this._get(inst, 'autoSize') && !inst.inline) {
8331 var date = new Date(2009, 12 - 1, 20); // Ensure double digits
8332 var dateFormat = this._get(inst, 'dateFormat');
8333 if (dateFormat.match(/[DM]/)) {
8334 var findMax = function(names) {
8337 for (var i = 0; i < names.length; i++) {
8338 if (names[i].length > max) {
8339 max = names[i].length;
8345 date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ?
8346 'monthNames' : 'monthNamesShort'))));
8347 date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ?
8348 'dayNames' : 'dayNamesShort'))) + 20 - date.getDay());
8350 inst.input.attr('size', this._formatDate(inst, date).length);
8354 /* Attach an inline date picker to a div. */
8355 _inlineDatepicker: function(target, inst) {
8356 var divSpan = $(target);
8357 if (divSpan.hasClass(this.markerClassName))
8359 divSpan.addClass(this.markerClassName).append(inst.dpDiv).
8360 bind("setData.datepicker", function(event, key, value){
8361 inst.settings[key] = value;
8362 }).bind("getData.datepicker", function(event, key){
8363 return this._get(inst, key);
8365 $.data(target, PROP_NAME, inst);
8366 this._setDate(inst, this._getDefaultDate(inst), true);
8367 this._updateDatepicker(inst);
8368 this._updateAlternate(inst);
8372 /* Pop-up the date picker in a "dialog" box.
8373 @param input element - ignored
8374 @param date string or Date - the initial date to display
8375 @param onSelect function - the function to call when a date is selected
8376 @param settings object - update the dialog date picker instance's settings (anonymous object)
8377 @param pos int[2] - coordinates for the dialog's position within the screen or
8378 event - with x/y coordinates or
8379 leave empty for default (screen centre)
8380 @return the manager object */
8381 _dialogDatepicker: function(input, date, onSelect, settings, pos) {
8382 var inst = this._dialogInst; // internal instance
8385 var id = 'dp' + this.uuid;
8386 this._dialogInput = $('<input type="text" id="' + id +
8387 '" style="position: absolute; top: -100px; width: 0px; z-index: -10;"/>');
8388 this._dialogInput.keydown(this._doKeyDown);
8389 $('body').append(this._dialogInput);
8390 inst = this._dialogInst = this._newInst(this._dialogInput, false);
8392 $.data(this._dialogInput[0], PROP_NAME, inst);
8394 extendRemove(inst.settings, settings || {});
8395 date = (date && date.constructor == Date ? this._formatDate(inst, date) : date);
8396 this._dialogInput.val(date);
8398 this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);
8400 var browserWidth = document.documentElement.clientWidth;
8401 var browserHeight = document.documentElement.clientHeight;
8402 var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
8403 var scrollY = document.documentElement.scrollTop || document.body.scrollTop;
8404 this._pos = // should use actual width/height below
8405 [(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY];
8408 // move input on screen for focus, but hidden behind dialog
8409 this._dialogInput.css('left', (this._pos[0] + 20) + 'px').css('top', this._pos[1] + 'px');
8410 inst.settings.onSelect = onSelect;
8411 this._inDialog = true;
8412 this.dpDiv.addClass(this._dialogClass);
8413 this._showDatepicker(this._dialogInput[0]);
8415 $.blockUI(this.dpDiv);
8416 $.data(this._dialogInput[0], PROP_NAME, inst);
8420 /* Detach a datepicker from its control.
8421 @param target element - the target input field or division or span */
8422 _destroyDatepicker: function(target) {
8423 var $target = $(target);
8424 var inst = $.data(target, PROP_NAME);
8425 if (!$target.hasClass(this.markerClassName)) {
8428 var nodeName = target.nodeName.toLowerCase();
8429 $.removeData(target, PROP_NAME);
8430 if (nodeName == 'input') {
8431 inst.append.remove();
8432 inst.trigger.remove();
8433 $target.removeClass(this.markerClassName).
8434 unbind('focus', this._showDatepicker).
8435 unbind('keydown', this._doKeyDown).
8436 unbind('keypress', this._doKeyPress).
8437 unbind('keyup', this._doKeyUp);
8438 } else if (nodeName == 'div' || nodeName == 'span')
8439 $target.removeClass(this.markerClassName).empty();
8442 /* Enable the date picker to a jQuery selection.
8443 @param target element - the target input field or division or span */
8444 _enableDatepicker: function(target) {
8445 var $target = $(target);
8446 var inst = $.data(target, PROP_NAME);
8447 if (!$target.hasClass(this.markerClassName)) {
8450 var nodeName = target.nodeName.toLowerCase();
8451 if (nodeName == 'input') {
8452 target.disabled = false;
8453 inst.trigger.filter('button').
8454 each(function() { this.disabled = false; }).end().
8455 filter('img').css({opacity: '1.0', cursor: ''});
8457 else if (nodeName == 'div' || nodeName == 'span') {
8458 var inline = $target.children('.' + this._inlineClass);
8459 inline.children().removeClass('ui-state-disabled');
8461 this._disabledInputs = $.map(this._disabledInputs,
8462 function(value) { return (value == target ? null : value); }); // delete entry
8465 /* Disable the date picker to a jQuery selection.
8466 @param target element - the target input field or division or span */
8467 _disableDatepicker: function(target) {
8468 var $target = $(target);
8469 var inst = $.data(target, PROP_NAME);
8470 if (!$target.hasClass(this.markerClassName)) {
8473 var nodeName = target.nodeName.toLowerCase();
8474 if (nodeName == 'input') {
8475 target.disabled = true;
8476 inst.trigger.filter('button').
8477 each(function() { this.disabled = true; }).end().
8478 filter('img').css({opacity: '0.5', cursor: 'default'});
8480 else if (nodeName == 'div' || nodeName == 'span') {
8481 var inline = $target.children('.' + this._inlineClass);
8482 inline.children().addClass('ui-state-disabled');
8484 this._disabledInputs = $.map(this._disabledInputs,
8485 function(value) { return (value == target ? null : value); }); // delete entry
8486 this._disabledInputs[this._disabledInputs.length] = target;
8489 /* Is the first field in a jQuery collection disabled as a datepicker?
8490 @param target element - the target input field or division or span
8491 @return boolean - true if disabled, false if enabled */
8492 _isDisabledDatepicker: function(target) {
8496 for (var i = 0; i < this._disabledInputs.length; i++) {
8497 if (this._disabledInputs[i] == target)
8503 /* Retrieve the instance data for the target control.
8504 @param target element - the target input field or division or span
8505 @return object - the associated instance data
8506 @throws error if a jQuery problem getting data */
8507 _getInst: function(target) {
8509 return $.data(target, PROP_NAME);
8512 throw 'Missing instance data for this datepicker';
8516 /* Update or retrieve the settings for a date picker attached to an input field or division.
8517 @param target element - the target input field or division or span
8518 @param name object - the new settings to update or
8519 string - the name of the setting to change or retrieve,
8520 when retrieving also 'all' for all instance settings or
8521 'defaults' for all global defaults
8522 @param value any - the new value for the setting
8523 (omit if above is an object or to retrieve a value) */
8524 _optionDatepicker: function(target, name, value) {
8525 var inst = this._getInst(target);
8526 if (arguments.length == 2 && typeof name == 'string') {
8527 return (name == 'defaults' ? $.extend({}, $.datepicker._defaults) :
8528 (inst ? (name == 'all' ? $.extend({}, inst.settings) :
8529 this._get(inst, name)) : null));
8531 var settings = name || {};
8532 if (typeof name == 'string') {
8534 settings[name] = value;
8537 if (this._curInst == inst) {
8538 this._hideDatepicker();
8540 var date = this._getDateDatepicker(target, true);
8541 extendRemove(inst.settings, settings);
8542 this._attachments($(target), inst);
8543 this._autoSize(inst);
8544 this._setDateDatepicker(target, date);
8545 this._updateDatepicker(inst);
8549 // change method deprecated
8550 _changeDatepicker: function(target, name, value) {
8551 this._optionDatepicker(target, name, value);
8554 /* Redraw the date picker attached to an input field or division.
8555 @param target element - the target input field or division or span */
8556 _refreshDatepicker: function(target) {
8557 var inst = this._getInst(target);
8559 this._updateDatepicker(inst);
8563 /* Set the dates for a jQuery selection.
8564 @param target element - the target input field or division or span
8565 @param date Date - the new date */
8566 _setDateDatepicker: function(target, date) {
8567 var inst = this._getInst(target);
8569 this._setDate(inst, date);
8570 this._updateDatepicker(inst);
8571 this._updateAlternate(inst);
8575 /* Get the date(s) for the first entry in a jQuery selection.
8576 @param target element - the target input field or division or span
8577 @param noDefault boolean - true if no default date is to be used
8578 @return Date - the current date */
8579 _getDateDatepicker: function(target, noDefault) {
8580 var inst = this._getInst(target);
8581 if (inst && !inst.inline)
8582 this._setDateFromField(inst, noDefault);
8583 return (inst ? this._getDate(inst) : null);
8586 /* Handle keystrokes. */
8587 _doKeyDown: function(event) {
8588 var inst = $.datepicker._getInst(event.target);
8590 var isRTL = inst.dpDiv.is('.ui-datepicker-rtl');
8591 inst._keyEvent = true;
8592 if ($.datepicker._datepickerShowing)
8593 switch (event.keyCode) {
8594 case 9: $.datepicker._hideDatepicker();
8596 break; // hide on tab out
8597 case 13: var sel = $('td.' + $.datepicker._dayOverClass + ':not(.' +
8598 $.datepicker._currentClass + ')', inst.dpDiv);
8600 $.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);
8602 $.datepicker._hideDatepicker();
8603 return false; // don't submit the form
8604 break; // select the value on enter
8605 case 27: $.datepicker._hideDatepicker();
8606 break; // hide on escape
8607 case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
8608 -$.datepicker._get(inst, 'stepBigMonths') :
8609 -$.datepicker._get(inst, 'stepMonths')), 'M');
8610 break; // previous month/year on page up/+ ctrl
8611 case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
8612 +$.datepicker._get(inst, 'stepBigMonths') :
8613 +$.datepicker._get(inst, 'stepMonths')), 'M');
8614 break; // next month/year on page down/+ ctrl
8615 case 35: if (event.ctrlKey || event.metaKey) $.datepicker._clearDate(event.target);
8616 handled = event.ctrlKey || event.metaKey;
8617 break; // clear on ctrl or command +end
8618 case 36: if (event.ctrlKey || event.metaKey) $.datepicker._gotoToday(event.target);
8619 handled = event.ctrlKey || event.metaKey;
8620 break; // current on ctrl or command +home
8621 case 37: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), 'D');
8622 handled = event.ctrlKey || event.metaKey;
8623 // -1 day on ctrl or command +left
8624 if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
8625 -$.datepicker._get(inst, 'stepBigMonths') :
8626 -$.datepicker._get(inst, 'stepMonths')), 'M');
8627 // next month/year on alt +left on Mac
8629 case 38: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, -7, 'D');
8630 handled = event.ctrlKey || event.metaKey;
8631 break; // -1 week on ctrl or command +up
8632 case 39: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), 'D');
8633 handled = event.ctrlKey || event.metaKey;
8634 // +1 day on ctrl or command +right
8635 if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
8636 +$.datepicker._get(inst, 'stepBigMonths') :
8637 +$.datepicker._get(inst, 'stepMonths')), 'M');
8638 // next month/year on alt +right
8640 case 40: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, +7, 'D');
8641 handled = event.ctrlKey || event.metaKey;
8642 break; // +1 week on ctrl or command +down
8643 default: handled = false;
8645 else if (event.keyCode == 36 && event.ctrlKey) // display the date picker on ctrl+home
8646 $.datepicker._showDatepicker(this);
8651 event.preventDefault();
8652 event.stopPropagation();
8656 /* Filter entered characters - based on date format. */
8657 _doKeyPress: function(event) {
8658 var inst = $.datepicker._getInst(event.target);
8659 if ($.datepicker._get(inst, 'constrainInput')) {
8660 var chars = $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat'));
8661 var chr = String.fromCharCode(event.charCode == undefined ? event.keyCode : event.charCode);
8662 return event.ctrlKey || event.metaKey || (chr < ' ' || !chars || chars.indexOf(chr) > -1);
8666 /* Synchronise manual entry and field/alternate field. */
8667 _doKeyUp: function(event) {
8668 var inst = $.datepicker._getInst(event.target);
8669 if (inst.input.val() != inst.lastVal) {
8671 var date = $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
8672 (inst.input ? inst.input.val() : null),
8673 $.datepicker._getFormatConfig(inst));
8674 if (date) { // only if valid
8675 $.datepicker._setDateFromField(inst);
8676 $.datepicker._updateAlternate(inst);
8677 $.datepicker._updateDatepicker(inst);
8681 $.datepicker.log(event);
8687 /* Pop-up the date picker for a given input field.
8688 @param input element - the input field attached to the date picker or
8689 event - if triggered by focus */
8690 _showDatepicker: function(input) {
8691 input = input.target || input;
8692 if (input.nodeName.toLowerCase() != 'input') // find from button/image trigger
8693 input = $('input', input.parentNode)[0];
8694 if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput == input) // already here
8696 var inst = $.datepicker._getInst(input);
8697 if ($.datepicker._curInst && $.datepicker._curInst != inst) {
8698 $.datepicker._curInst.dpDiv.stop(true, true);
8700 var beforeShow = $.datepicker._get(inst, 'beforeShow');
8701 extendRemove(inst.settings, (beforeShow ? beforeShow.apply(input, [input, inst]) : {}));
8702 inst.lastVal = null;
8703 $.datepicker._lastInput = input;
8704 $.datepicker._setDateFromField(inst);
8705 if ($.datepicker._inDialog) // hide cursor
8707 if (!$.datepicker._pos) { // position below input
8708 $.datepicker._pos = $.datepicker._findPos(input);
8709 $.datepicker._pos[1] += input.offsetHeight; // add the height
8711 var isFixed = false;
8712 $(input).parents().each(function() {
8713 isFixed |= $(this).css('position') == 'fixed';
8716 if (isFixed && $.browser.opera) { // correction for Opera when fixed and scrolled
8717 $.datepicker._pos[0] -= document.documentElement.scrollLeft;
8718 $.datepicker._pos[1] -= document.documentElement.scrollTop;
8720 var offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]};
8721 $.datepicker._pos = null;
8722 //to avoid flashes on Firefox
8724 // determine sizing offscreen
8725 inst.dpDiv.css({position: 'absolute', display: 'block', top: '-1000px'});
8726 $.datepicker._updateDatepicker(inst);
8727 // fix width for dynamic number of date pickers
8728 // and adjust position before showing
8729 offset = $.datepicker._checkOffset(inst, offset, isFixed);
8730 inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ?
8731 'static' : (isFixed ? 'fixed' : 'absolute')), display: 'none',
8732 left: offset.left + 'px', top: offset.top + 'px'});
8734 var showAnim = $.datepicker._get(inst, 'showAnim');
8735 var duration = $.datepicker._get(inst, 'duration');
8736 var postProcess = function() {
8737 $.datepicker._datepickerShowing = true;
8738 var cover = inst.dpDiv.find('iframe.ui-datepicker-cover'); // IE6- only
8739 if( !! cover.length ){
8740 var borders = $.datepicker._getBorders(inst.dpDiv);
8741 cover.css({left: -borders[0], top: -borders[1],
8742 width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()});
8745 inst.dpDiv.zIndex($(input).zIndex()+1);
8746 if ($.effects && $.effects[showAnim])
8747 inst.dpDiv.show(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
8749 inst.dpDiv[showAnim || 'show']((showAnim ? duration : null), postProcess);
8750 if (!showAnim || !duration)
8752 if (inst.input.is(':visible') && !inst.input.is(':disabled'))
8754 $.datepicker._curInst = inst;
8758 /* Generate the date picker content. */
8759 _updateDatepicker: function(inst) {
8761 var borders = $.datepicker._getBorders(inst.dpDiv);
8762 inst.dpDiv.empty().append(this._generateHTML(inst));
8763 var cover = inst.dpDiv.find('iframe.ui-datepicker-cover'); // IE6- only
8764 if( !!cover.length ){ //avoid call to outerXXXX() when not in IE6
8765 cover.css({left: -borders[0], top: -borders[1], width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()})
8767 inst.dpDiv.find('button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a')
8768 .bind('mouseout', function(){
8769 $(this).removeClass('ui-state-hover');
8770 if(this.className.indexOf('ui-datepicker-prev') != -1) $(this).removeClass('ui-datepicker-prev-hover');
8771 if(this.className.indexOf('ui-datepicker-next') != -1) $(this).removeClass('ui-datepicker-next-hover');
8773 .bind('mouseover', function(){
8774 if (!self._isDisabledDatepicker( inst.inline ? inst.dpDiv.parent()[0] : inst.input[0])) {
8775 $(this).parents('.ui-datepicker-calendar').find('a').removeClass('ui-state-hover');
8776 $(this).addClass('ui-state-hover');
8777 if(this.className.indexOf('ui-datepicker-prev') != -1) $(this).addClass('ui-datepicker-prev-hover');
8778 if(this.className.indexOf('ui-datepicker-next') != -1) $(this).addClass('ui-datepicker-next-hover');
8782 .find('.' + this._dayOverClass + ' a')
8783 .trigger('mouseover')
8785 var numMonths = this._getNumberOfMonths(inst);
8786 var cols = numMonths[1];
8789 inst.dpDiv.addClass('ui-datepicker-multi-' + cols).css('width', (width * cols) + 'em');
8791 inst.dpDiv.removeClass('ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4').width('');
8792 inst.dpDiv[(numMonths[0] != 1 || numMonths[1] != 1 ? 'add' : 'remove') +
8793 'Class']('ui-datepicker-multi');
8794 inst.dpDiv[(this._get(inst, 'isRTL') ? 'add' : 'remove') +
8795 'Class']('ui-datepicker-rtl');
8796 if (inst == $.datepicker._curInst && $.datepicker._datepickerShowing && inst.input &&
8797 // #6694 - don't focus the input if it's already focused
8798 // this breaks the change event in IE
8799 inst.input.is(':visible') && !inst.input.is(':disabled') && inst.input[0] != document.activeElement)
8801 // deffered render of the years select (to avoid flashes on Firefox)
8802 if( inst.yearshtml ){
8803 var origyearshtml = inst.yearshtml;
8804 setTimeout(function(){
8805 //assure that inst.yearshtml didn't change.
8806 if( origyearshtml === inst.yearshtml ){
8807 inst.dpDiv.find('select.ui-datepicker-year:first').replaceWith(inst.yearshtml);
8809 origyearshtml = inst.yearshtml = null;
8814 /* Retrieve the size of left and top borders for an element.
8815 @param elem (jQuery object) the element of interest
8816 @return (number[2]) the left and top borders */
8817 _getBorders: function(elem) {
8818 var convert = function(value) {
8819 return {thin: 1, medium: 2, thick: 3}[value] || value;
8821 return [parseFloat(convert(elem.css('border-left-width'))),
8822 parseFloat(convert(elem.css('border-top-width')))];
8825 /* Check positioning to remain on screen. */
8826 _checkOffset: function(inst, offset, isFixed) {
8827 var dpWidth = inst.dpDiv.outerWidth();
8828 var dpHeight = inst.dpDiv.outerHeight();
8829 var inputWidth = inst.input ? inst.input.outerWidth() : 0;
8830 var inputHeight = inst.input ? inst.input.outerHeight() : 0;
8831 var viewWidth = document.documentElement.clientWidth + $(document).scrollLeft();
8832 var viewHeight = document.documentElement.clientHeight + $(document).scrollTop();
8834 offset.left -= (this._get(inst, 'isRTL') ? (dpWidth - inputWidth) : 0);
8835 offset.left -= (isFixed && offset.left == inst.input.offset().left) ? $(document).scrollLeft() : 0;
8836 offset.top -= (isFixed && offset.top == (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;
8838 // now check if datepicker is showing outside window viewport - move to a better place if so.
8839 offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?
8840 Math.abs(offset.left + dpWidth - viewWidth) : 0);
8841 offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?
8842 Math.abs(dpHeight + inputHeight) : 0);
8847 /* Find an object's position on the screen. */
8848 _findPos: function(obj) {
8849 var inst = this._getInst(obj);
8850 var isRTL = this._get(inst, 'isRTL');
8851 while (obj && (obj.type == 'hidden' || obj.nodeType != 1 || $.expr.filters.hidden(obj))) {
8852 obj = obj[isRTL ? 'previousSibling' : 'nextSibling'];
8854 var position = $(obj).offset();
8855 return [position.left, position.top];
8858 /* Hide the date picker from view.
8859 @param input element - the input field attached to the date picker */
8860 _hideDatepicker: function(input) {
8861 var inst = this._curInst;
8862 if (!inst || (input && inst != $.data(input, PROP_NAME)))
8864 if (this._datepickerShowing) {
8865 var showAnim = this._get(inst, 'showAnim');
8866 var duration = this._get(inst, 'duration');
8867 var postProcess = function() {
8868 $.datepicker._tidyDialog(inst);
8869 this._curInst = null;
8871 if ($.effects && $.effects[showAnim])
8872 inst.dpDiv.hide(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
8874 inst.dpDiv[(showAnim == 'slideDown' ? 'slideUp' :
8875 (showAnim == 'fadeIn' ? 'fadeOut' : 'hide'))]((showAnim ? duration : null), postProcess);
8878 var onClose = this._get(inst, 'onClose');
8880 onClose.apply((inst.input ? inst.input[0] : null),
8881 [(inst.input ? inst.input.val() : ''), inst]); // trigger custom callback
8882 this._datepickerShowing = false;
8883 this._lastInput = null;
8884 if (this._inDialog) {
8885 this._dialogInput.css({ position: 'absolute', left: '0', top: '-100px' });
8888 $('body').append(this.dpDiv);
8891 this._inDialog = false;
8895 /* Tidy up after a dialog display. */
8896 _tidyDialog: function(inst) {
8897 inst.dpDiv.removeClass(this._dialogClass).unbind('.ui-datepicker-calendar');
8900 /* Close date picker if clicked elsewhere. */
8901 _checkExternalClick: function(event) {
8902 if (!$.datepicker._curInst)
8904 var $target = $(event.target);
8905 if ($target[0].id != $.datepicker._mainDivId &&
8906 $target.parents('#' + $.datepicker._mainDivId).length == 0 &&
8907 !$target.hasClass($.datepicker.markerClassName) &&
8908 !$target.hasClass($.datepicker._triggerClass) &&
8909 $.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI))
8910 $.datepicker._hideDatepicker();
8913 /* Adjust one of the date sub-fields. */
8914 _adjustDate: function(id, offset, period) {
8916 var inst = this._getInst(target[0]);
8917 if (this._isDisabledDatepicker(target[0])) {
8920 this._adjustInstDate(inst, offset +
8921 (period == 'M' ? this._get(inst, 'showCurrentAtPos') : 0), // undo positioning
8923 this._updateDatepicker(inst);
8926 /* Action for current link. */
8927 _gotoToday: function(id) {
8929 var inst = this._getInst(target[0]);
8930 if (this._get(inst, 'gotoCurrent') && inst.currentDay) {
8931 inst.selectedDay = inst.currentDay;
8932 inst.drawMonth = inst.selectedMonth = inst.currentMonth;
8933 inst.drawYear = inst.selectedYear = inst.currentYear;
8936 var date = new Date();
8937 inst.selectedDay = date.getDate();
8938 inst.drawMonth = inst.selectedMonth = date.getMonth();
8939 inst.drawYear = inst.selectedYear = date.getFullYear();
8941 this._notifyChange(inst);
8942 this._adjustDate(target);
8945 /* Action for selecting a new month/year. */
8946 _selectMonthYear: function(id, select, period) {
8948 var inst = this._getInst(target[0]);
8949 inst._selectingMonthYear = false;
8950 inst['selected' + (period == 'M' ? 'Month' : 'Year')] =
8951 inst['draw' + (period == 'M' ? 'Month' : 'Year')] =
8952 parseInt(select.options[select.selectedIndex].value,10);
8953 this._notifyChange(inst);
8954 this._adjustDate(target);
8957 /* Restore input focus after not changing month/year. */
8958 _clickMonthYear: function(id) {
8960 var inst = this._getInst(target[0]);
8961 if (inst.input && inst._selectingMonthYear) {
8962 setTimeout(function() {
8966 inst._selectingMonthYear = !inst._selectingMonthYear;
8969 /* Action for selecting a day. */
8970 _selectDay: function(id, month, year, td) {
8972 if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) {
8975 var inst = this._getInst(target[0]);
8976 inst.selectedDay = inst.currentDay = $('a', td).html();
8977 inst.selectedMonth = inst.currentMonth = month;
8978 inst.selectedYear = inst.currentYear = year;
8979 this._selectDate(id, this._formatDate(inst,
8980 inst.currentDay, inst.currentMonth, inst.currentYear));
8983 /* Erase the input field and hide the date picker. */
8984 _clearDate: function(id) {
8986 var inst = this._getInst(target[0]);
8987 this._selectDate(target, '');
8990 /* Update the input field with the selected date. */
8991 _selectDate: function(id, dateStr) {
8993 var inst = this._getInst(target[0]);
8994 dateStr = (dateStr != null ? dateStr : this._formatDate(inst));
8996 inst.input.val(dateStr);
8997 this._updateAlternate(inst);
8998 var onSelect = this._get(inst, 'onSelect');
9000 onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); // trigger custom callback
9001 else if (inst.input)
9002 inst.input.trigger('change'); // fire the change event
9004 this._updateDatepicker(inst);
9006 this._hideDatepicker();
9007 this._lastInput = inst.input[0];
9008 if (typeof(inst.input[0]) != 'object')
9009 inst.input.focus(); // restore focus
9010 this._lastInput = null;
9014 /* Update any alternate field to synchronise with the main field. */
9015 _updateAlternate: function(inst) {
9016 var altField = this._get(inst, 'altField');
9017 if (altField) { // update alternate field too
9018 var altFormat = this._get(inst, 'altFormat') || this._get(inst, 'dateFormat');
9019 var date = this._getDate(inst);
9020 var dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst));
9021 $(altField).each(function() { $(this).val(dateStr); });
9025 /* Set as beforeShowDay function to prevent selection of weekends.
9026 @param date Date - the date to customise
9027 @return [boolean, string] - is this date selectable?, what is its CSS class? */
9028 noWeekends: function(date) {
9029 var day = date.getDay();
9030 return [(day > 0 && day < 6), ''];
9033 /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
9034 @param date Date - the date to get the week for
9035 @return number - the number of the week within the year that contains this date */
9036 iso8601Week: function(date) {
9037 var checkDate = new Date(date.getTime());
9038 // Find Thursday of this week starting on Monday
9039 checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7));
9040 var time = checkDate.getTime();
9041 checkDate.setMonth(0); // Compare with Jan 1
9042 checkDate.setDate(1);
9043 return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
9046 /* Parse a string value into a date object.
9047 See formatDate below for the possible formats.
9049 @param format string - the expected format of the date
9050 @param value string - the date in the above format
9051 @param settings Object - attributes include:
9052 shortYearCutoff number - the cutoff year for determining the century (optional)
9053 dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
9054 dayNames string[7] - names of the days from Sunday (optional)
9055 monthNamesShort string[12] - abbreviated names of the months (optional)
9056 monthNames string[12] - names of the months (optional)
9057 @return Date - the extracted date value or null if value is blank */
9058 parseDate: function (format, value, settings) {
9059 if (format == null || value == null)
9060 throw 'Invalid arguments';
9061 value = (typeof value == 'object' ? value.toString() : value + '');
9064 var shortYearCutoff = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff;
9065 shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff :
9066 new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
9067 var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
9068 var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
9069 var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
9070 var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
9075 var literal = false;
9076 // Check whether a format character is doubled
9077 var lookAhead = function(match) {
9078 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
9083 // Extract a number from the string value
9084 var getNumber = function(match) {
9085 var isDoubled = lookAhead(match);
9086 var size = (match == '@' ? 14 : (match == '!' ? 20 :
9087 (match == 'y' && isDoubled ? 4 : (match == 'o' ? 3 : 2))));
9088 var digits = new RegExp('^\\d{1,' + size + '}');
9089 var num = value.substring(iValue).match(digits);
9091 throw 'Missing number at position ' + iValue;
9092 iValue += num[0].length;
9093 return parseInt(num[0], 10);
9095 // Extract a name from the string value and convert to an index
9096 var getName = function(match, shortNames, longNames) {
9097 var names = (lookAhead(match) ? longNames : shortNames);
9098 for (var i = 0; i < names.length; i++) {
9099 if (value.substr(iValue, names[i].length).toLowerCase() == names[i].toLowerCase()) {
9100 iValue += names[i].length;
9104 throw 'Unknown name at position ' + iValue;
9106 // Confirm that a literal character matches the string value
9107 var checkLiteral = function() {
9108 if (value.charAt(iValue) != format.charAt(iFormat))
9109 throw 'Unexpected literal at position ' + iValue;
9113 for (var iFormat = 0; iFormat < format.length; iFormat++) {
9115 if (format.charAt(iFormat) == "'" && !lookAhead("'"))
9120 switch (format.charAt(iFormat)) {
9122 day = getNumber('d');
9125 getName('D', dayNamesShort, dayNames);
9128 doy = getNumber('o');
9131 month = getNumber('m');
9134 month = getName('M', monthNamesShort, monthNames);
9137 year = getNumber('y');
9140 var date = new Date(getNumber('@'));
9141 year = date.getFullYear();
9142 month = date.getMonth() + 1;
9143 day = date.getDate();
9146 var date = new Date((getNumber('!') - this._ticksTo1970) / 10000);
9147 year = date.getFullYear();
9148 month = date.getMonth() + 1;
9149 day = date.getDate();
9162 year = new Date().getFullYear();
9163 else if (year < 100)
9164 year += new Date().getFullYear() - new Date().getFullYear() % 100 +
9165 (year <= shortYearCutoff ? 0 : -100);
9170 var dim = this._getDaysInMonth(year, month - 1);
9177 var date = this._daylightSavingAdjust(new Date(year, month - 1, day));
9178 if (date.getFullYear() != year || date.getMonth() + 1 != month || date.getDate() != day)
9179 throw 'Invalid date'; // E.g. 31/02/*
9183 /* Standard date formats. */
9184 ATOM: 'yy-mm-dd', // RFC 3339 (ISO 8601)
9185 COOKIE: 'D, dd M yy',
9186 ISO_8601: 'yy-mm-dd',
9187 RFC_822: 'D, d M y',
9188 RFC_850: 'DD, dd-M-y',
9189 RFC_1036: 'D, d M y',
9190 RFC_1123: 'D, d M yy',
9191 RFC_2822: 'D, d M yy',
9192 RSS: 'D, d M y', // RFC 822
9195 W3C: 'yy-mm-dd', // ISO 8601
9197 _ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) +
9198 Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000),
9200 /* Format a date object into a string value.
9201 The format can be combinations of the following:
9202 d - day of month (no leading zero)
9203 dd - day of month (two digit)
9204 o - day of year (no leading zeros)
9205 oo - day of year (three digit)
9208 m - month of year (no leading zero)
9209 mm - month of year (two digit)
9210 M - month name short
9211 MM - month name long
9212 y - year (two digit)
9213 yy - year (four digit)
9214 @ - Unix timestamp (ms since 01/01/1970)
9215 ! - Windows ticks (100ns since 01/01/0001)
9216 '...' - literal text
9219 @param format string - the desired format of the date
9220 @param date Date - the date value to format
9221 @param settings Object - attributes include:
9222 dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
9223 dayNames string[7] - names of the days from Sunday (optional)
9224 monthNamesShort string[12] - abbreviated names of the months (optional)
9225 monthNames string[12] - names of the months (optional)
9226 @return string - the date in the above format */
9227 formatDate: function (format, date, settings) {
9230 var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
9231 var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
9232 var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
9233 var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
9234 // Check whether a format character is doubled
9235 var lookAhead = function(match) {
9236 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
9241 // Format a number, with leading zero if necessary
9242 var formatNumber = function(match, value, len) {
9243 var num = '' + value;
9244 if (lookAhead(match))
9245 while (num.length < len)
9249 // Format a name, short or long as requested
9250 var formatName = function(match, value, shortNames, longNames) {
9251 return (lookAhead(match) ? longNames[value] : shortNames[value]);
9254 var literal = false;
9256 for (var iFormat = 0; iFormat < format.length; iFormat++) {
9258 if (format.charAt(iFormat) == "'" && !lookAhead("'"))
9261 output += format.charAt(iFormat);
9263 switch (format.charAt(iFormat)) {
9265 output += formatNumber('d', date.getDate(), 2);
9268 output += formatName('D', date.getDay(), dayNamesShort, dayNames);
9271 output += formatNumber('o',
9272 (date.getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000, 3);
9275 output += formatNumber('m', date.getMonth() + 1, 2);
9278 output += formatName('M', date.getMonth(), monthNamesShort, monthNames);
9281 output += (lookAhead('y') ? date.getFullYear() :
9282 (date.getYear() % 100 < 10 ? '0' : '') + date.getYear() % 100);
9285 output += date.getTime();
9288 output += date.getTime() * 10000 + this._ticksTo1970;
9297 output += format.charAt(iFormat);
9303 /* Extract all possible characters from the date format. */
9304 _possibleChars: function (format) {
9306 var literal = false;
9307 // Check whether a format character is doubled
9308 var lookAhead = function(match) {
9309 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
9314 for (var iFormat = 0; iFormat < format.length; iFormat++)
9316 if (format.charAt(iFormat) == "'" && !lookAhead("'"))
9319 chars += format.charAt(iFormat);
9321 switch (format.charAt(iFormat)) {
9322 case 'd': case 'm': case 'y': case '@':
9323 chars += '0123456789';
9326 return null; // Accept anything
9334 chars += format.charAt(iFormat);
9339 /* Get a setting value, defaulting if necessary. */
9340 _get: function(inst, name) {
9341 return inst.settings[name] !== undefined ?
9342 inst.settings[name] : this._defaults[name];
9345 /* Parse existing date and initialise date picker. */
9346 _setDateFromField: function(inst, noDefault) {
9347 if (inst.input.val() == inst.lastVal) {
9350 var dateFormat = this._get(inst, 'dateFormat');
9351 var dates = inst.lastVal = inst.input ? inst.input.val() : null;
9352 var date, defaultDate;
9353 date = defaultDate = this._getDefaultDate(inst);
9354 var settings = this._getFormatConfig(inst);
9356 date = this.parseDate(dateFormat, dates, settings) || defaultDate;
9359 dates = (noDefault ? '' : dates);
9361 inst.selectedDay = date.getDate();
9362 inst.drawMonth = inst.selectedMonth = date.getMonth();
9363 inst.drawYear = inst.selectedYear = date.getFullYear();
9364 inst.currentDay = (dates ? date.getDate() : 0);
9365 inst.currentMonth = (dates ? date.getMonth() : 0);
9366 inst.currentYear = (dates ? date.getFullYear() : 0);
9367 this._adjustInstDate(inst);
9370 /* Retrieve the default date shown on opening. */
9371 _getDefaultDate: function(inst) {
9372 return this._restrictMinMax(inst,
9373 this._determineDate(inst, this._get(inst, 'defaultDate'), new Date()));
9376 /* A date may be specified as an exact value or a relative one. */
9377 _determineDate: function(inst, date, defaultDate) {
9378 var offsetNumeric = function(offset) {
9379 var date = new Date();
9380 date.setDate(date.getDate() + offset);
9383 var offsetString = function(offset) {
9385 return $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
9386 offset, $.datepicker._getFormatConfig(inst));
9391 var date = (offset.toLowerCase().match(/^c/) ?
9392 $.datepicker._getDate(inst) : null) || new Date();
9393 var year = date.getFullYear();
9394 var month = date.getMonth();
9395 var day = date.getDate();
9396 var pattern = /([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g;
9397 var matches = pattern.exec(offset);
9399 switch (matches[2] || 'd') {
9400 case 'd' : case 'D' :
9401 day += parseInt(matches[1],10); break;
9402 case 'w' : case 'W' :
9403 day += parseInt(matches[1],10) * 7; break;
9404 case 'm' : case 'M' :
9405 month += parseInt(matches[1],10);
9406 day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
9408 case 'y': case 'Y' :
9409 year += parseInt(matches[1],10);
9410 day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
9413 matches = pattern.exec(offset);
9415 return new Date(year, month, day);
9417 var newDate = (date == null || date === '' ? defaultDate : (typeof date == 'string' ? offsetString(date) :
9418 (typeof date == 'number' ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : new Date(date.getTime()))));
9419 newDate = (newDate && newDate.toString() == 'Invalid Date' ? defaultDate : newDate);
9421 newDate.setHours(0);
9422 newDate.setMinutes(0);
9423 newDate.setSeconds(0);
9424 newDate.setMilliseconds(0);
9426 return this._daylightSavingAdjust(newDate);
9429 /* Handle switch to/from daylight saving.
9430 Hours may be non-zero on daylight saving cut-over:
9431 > 12 when midnight changeover, but then cannot generate
9432 midnight datetime, so jump to 1AM, otherwise reset.
9433 @param date (Date) the date to check
9434 @return (Date) the corrected date */
9435 _daylightSavingAdjust: function(date) {
9436 if (!date) return null;
9437 date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
9441 /* Set the date(s) directly. */
9442 _setDate: function(inst, date, noChange) {
9444 var origMonth = inst.selectedMonth;
9445 var origYear = inst.selectedYear;
9446 var newDate = this._restrictMinMax(inst, this._determineDate(inst, date, new Date()));
9447 inst.selectedDay = inst.currentDay = newDate.getDate();
9448 inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth();
9449 inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear();
9450 if ((origMonth != inst.selectedMonth || origYear != inst.selectedYear) && !noChange)
9451 this._notifyChange(inst);
9452 this._adjustInstDate(inst);
9454 inst.input.val(clear ? '' : this._formatDate(inst));
9458 /* Retrieve the date(s) directly. */
9459 _getDate: function(inst) {
9460 var startDate = (!inst.currentYear || (inst.input && inst.input.val() == '') ? null :
9461 this._daylightSavingAdjust(new Date(
9462 inst.currentYear, inst.currentMonth, inst.currentDay)));
9466 /* Generate the HTML for the current state of the date picker. */
9467 _generateHTML: function(inst) {
9468 var today = new Date();
9469 today = this._daylightSavingAdjust(
9470 new Date(today.getFullYear(), today.getMonth(), today.getDate())); // clear time
9471 var isRTL = this._get(inst, 'isRTL');
9472 var showButtonPanel = this._get(inst, 'showButtonPanel');
9473 var hideIfNoPrevNext = this._get(inst, 'hideIfNoPrevNext');
9474 var navigationAsDateFormat = this._get(inst, 'navigationAsDateFormat');
9475 var numMonths = this._getNumberOfMonths(inst);
9476 var showCurrentAtPos = this._get(inst, 'showCurrentAtPos');
9477 var stepMonths = this._get(inst, 'stepMonths');
9478 var isMultiMonth = (numMonths[0] != 1 || numMonths[1] != 1);
9479 var currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) :
9480 new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
9481 var minDate = this._getMinMaxDate(inst, 'min');
9482 var maxDate = this._getMinMaxDate(inst, 'max');
9483 var drawMonth = inst.drawMonth - showCurrentAtPos;
9484 var drawYear = inst.drawYear;
9485 if (drawMonth < 0) {
9490 var maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),
9491 maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate()));
9492 maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);
9493 while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {
9495 if (drawMonth < 0) {
9501 inst.drawMonth = drawMonth;
9502 inst.drawYear = drawYear;
9503 var prevText = this._get(inst, 'prevText');
9504 prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText,
9505 this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),
9506 this._getFormatConfig(inst)));
9507 var prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?
9508 '<a class="ui-datepicker-prev ui-corner-all" onclick="DP_jQuery_' + dpuuid +
9509 '.datepicker._adjustDate(\'#' + inst.id + '\', -' + stepMonths + ', \'M\');"' +
9510 ' title="' + prevText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>' :
9511 (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>'));
9512 var nextText = this._get(inst, 'nextText');
9513 nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText,
9514 this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),
9515 this._getFormatConfig(inst)));
9516 var next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?
9517 '<a class="ui-datepicker-next ui-corner-all" onclick="DP_jQuery_' + dpuuid +
9518 '.datepicker._adjustDate(\'#' + inst.id + '\', +' + stepMonths + ', \'M\');"' +
9519 ' title="' + nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>' :
9520 (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>'));
9521 var currentText = this._get(inst, 'currentText');
9522 var gotoDate = (this._get(inst, 'gotoCurrent') && inst.currentDay ? currentDate : today);
9523 currentText = (!navigationAsDateFormat ? currentText :
9524 this.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));
9525 var controls = (!inst.inline ? '<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" onclick="DP_jQuery_' + dpuuid +
9526 '.datepicker._hideDatepicker();">' + this._get(inst, 'closeText') + '</button>' : '');
9527 var buttonPanel = (showButtonPanel) ? '<div class="ui-datepicker-buttonpane ui-widget-content">' + (isRTL ? controls : '') +
9528 (this._isInRange(inst, gotoDate) ? '<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" onclick="DP_jQuery_' + dpuuid +
9529 '.datepicker._gotoToday(\'#' + inst.id + '\');"' +
9530 '>' + currentText + '</button>' : '') + (isRTL ? '' : controls) + '</div>' : '';
9531 var firstDay = parseInt(this._get(inst, 'firstDay'),10);
9532 firstDay = (isNaN(firstDay) ? 0 : firstDay);
9533 var showWeek = this._get(inst, 'showWeek');
9534 var dayNames = this._get(inst, 'dayNames');
9535 var dayNamesShort = this._get(inst, 'dayNamesShort');
9536 var dayNamesMin = this._get(inst, 'dayNamesMin');
9537 var monthNames = this._get(inst, 'monthNames');
9538 var monthNamesShort = this._get(inst, 'monthNamesShort');
9539 var beforeShowDay = this._get(inst, 'beforeShowDay');
9540 var showOtherMonths = this._get(inst, 'showOtherMonths');
9541 var selectOtherMonths = this._get(inst, 'selectOtherMonths');
9542 var calculateWeek = this._get(inst, 'calculateWeek') || this.iso8601Week;
9543 var defaultDate = this._getDefaultDate(inst);
9545 for (var row = 0; row < numMonths[0]; row++) {
9547 for (var col = 0; col < numMonths[1]; col++) {
9548 var selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay));
9549 var cornerClass = ' ui-corner-all';
9552 calender += '<div class="ui-datepicker-group';
9553 if (numMonths[1] > 1)
9555 case 0: calender += ' ui-datepicker-group-first';
9556 cornerClass = ' ui-corner-' + (isRTL ? 'right' : 'left'); break;
9557 case numMonths[1]-1: calender += ' ui-datepicker-group-last';
9558 cornerClass = ' ui-corner-' + (isRTL ? 'left' : 'right'); break;
9559 default: calender += ' ui-datepicker-group-middle'; cornerClass = ''; break;
9563 calender += '<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix' + cornerClass + '">' +
9564 (/all|left/.test(cornerClass) && row == 0 ? (isRTL ? next : prev) : '') +
9565 (/all|right/.test(cornerClass) && row == 0 ? (isRTL ? prev : next) : '') +
9566 this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,
9567 row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers
9568 '</div><table class="ui-datepicker-calendar"><thead>' +
9570 var thead = (showWeek ? '<th class="ui-datepicker-week-col">' + this._get(inst, 'weekHeader') + '</th>' : '');
9571 for (var dow = 0; dow < 7; dow++) { // days of the week
9572 var day = (dow + firstDay) % 7;
9573 thead += '<th' + ((dow + firstDay + 6) % 7 >= 5 ? ' class="ui-datepicker-week-end"' : '') + '>' +
9574 '<span title="' + dayNames[day] + '">' + dayNamesMin[day] + '</span></th>';
9576 calender += thead + '</tr></thead><tbody>';
9577 var daysInMonth = this._getDaysInMonth(drawYear, drawMonth);
9578 if (drawYear == inst.selectedYear && drawMonth == inst.selectedMonth)
9579 inst.selectedDay = Math.min(inst.selectedDay, daysInMonth);
9580 var leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;
9581 var numRows = (isMultiMonth ? 6 : Math.ceil((leadDays + daysInMonth) / 7)); // calculate the number of rows to generate
9582 var printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
9583 for (var dRow = 0; dRow < numRows; dRow++) { // create date picker rows
9585 var tbody = (!showWeek ? '' : '<td class="ui-datepicker-week-col">' +
9586 this._get(inst, 'calculateWeek')(printDate) + '</td>');
9587 for (var dow = 0; dow < 7; dow++) { // create date picker days
9588 var daySettings = (beforeShowDay ?
9589 beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, '']);
9590 var otherMonth = (printDate.getMonth() != drawMonth);
9591 var unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] ||
9592 (minDate && printDate < minDate) || (maxDate && printDate > maxDate);
9593 tbody += '<td class="' +
9594 ((dow + firstDay + 6) % 7 >= 5 ? ' ui-datepicker-week-end' : '') + // highlight weekends
9595 (otherMonth ? ' ui-datepicker-other-month' : '') + // highlight days from other months
9596 ((printDate.getTime() == selectedDate.getTime() && drawMonth == inst.selectedMonth && inst._keyEvent) || // user pressed key
9597 (defaultDate.getTime() == printDate.getTime() && defaultDate.getTime() == selectedDate.getTime()) ?
9598 // or defaultDate is current printedDate and defaultDate is selectedDate
9599 ' ' + this._dayOverClass : '') + // highlight selected day
9600 (unselectable ? ' ' + this._unselectableClass + ' ui-state-disabled': '') + // highlight unselectable days
9601 (otherMonth && !showOtherMonths ? '' : ' ' + daySettings[1] + // highlight custom dates
9602 (printDate.getTime() == currentDate.getTime() ? ' ' + this._currentClass : '') + // highlight selected day
9603 (printDate.getTime() == today.getTime() ? ' ui-datepicker-today' : '')) + '"' + // highlight today (if different)
9604 ((!otherMonth || showOtherMonths) && daySettings[2] ? ' title="' + daySettings[2] + '"' : '') + // cell title
9605 (unselectable ? '' : ' onclick="DP_jQuery_' + dpuuid + '.datepicker._selectDay(\'#' +
9606 inst.id + '\',' + printDate.getMonth() + ',' + printDate.getFullYear() + ', this);return false;"') + '>' + // actions
9607 (otherMonth && !showOtherMonths ? ' ' : // display for other months
9608 (unselectable ? '<span class="ui-state-default">' + printDate.getDate() + '</span>' : '<a class="ui-state-default' +
9609 (printDate.getTime() == today.getTime() ? ' ui-state-highlight' : '') +
9610 (printDate.getTime() == currentDate.getTime() ? ' ui-state-active' : '') + // highlight selected day
9611 (otherMonth ? ' ui-priority-secondary' : '') + // distinguish dates from other months
9612 '" href="#">' + printDate.getDate() + '</a>')) + '</td>'; // display selectable date
9613 printDate.setDate(printDate.getDate() + 1);
9614 printDate = this._daylightSavingAdjust(printDate);
9616 calender += tbody + '</tr>';
9619 if (drawMonth > 11) {
9623 calender += '</tbody></table>' + (isMultiMonth ? '</div>' +
9624 ((numMonths[0] > 0 && col == numMonths[1]-1) ? '<div class="ui-datepicker-row-break"></div>' : '') : '');
9629 html += buttonPanel + ($.browser.msie && parseInt($.browser.version,10) < 7 && !inst.inline ?
9630 '<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>' : '');
9631 inst._keyEvent = false;
9635 /* Generate the month and year header. */
9636 _generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate,
9637 secondary, monthNames, monthNamesShort) {
9638 var changeMonth = this._get(inst, 'changeMonth');
9639 var changeYear = this._get(inst, 'changeYear');
9640 var showMonthAfterYear = this._get(inst, 'showMonthAfterYear');
9641 var html = '<div class="ui-datepicker-title">';
9644 if (secondary || !changeMonth)
9645 monthHtml += '<span class="ui-datepicker-month">' + monthNames[drawMonth] + '</span>';
9647 var inMinYear = (minDate && minDate.getFullYear() == drawYear);
9648 var inMaxYear = (maxDate && maxDate.getFullYear() == drawYear);
9649 monthHtml += '<select class="ui-datepicker-month" ' +
9650 'onchange="DP_jQuery_' + dpuuid + '.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'M\');" ' +
9651 'onclick="DP_jQuery_' + dpuuid + '.datepicker._clickMonthYear(\'#' + inst.id + '\');"' +
9653 for (var month = 0; month < 12; month++) {
9654 if ((!inMinYear || month >= minDate.getMonth()) &&
9655 (!inMaxYear || month <= maxDate.getMonth()))
9656 monthHtml += '<option value="' + month + '"' +
9657 (month == drawMonth ? ' selected="selected"' : '') +
9658 '>' + monthNamesShort[month] + '</option>';
9660 monthHtml += '</select>';
9662 if (!showMonthAfterYear)
9663 html += monthHtml + (secondary || !(changeMonth && changeYear) ? ' ' : '');
9665 inst.yearshtml = '';
9666 if (secondary || !changeYear)
9667 html += '<span class="ui-datepicker-year">' + drawYear + '</span>';
9669 // determine range of years to display
9670 var years = this._get(inst, 'yearRange').split(':');
9671 var thisYear = new Date().getFullYear();
9672 var determineYear = function(value) {
9673 var year = (value.match(/c[+-].*/) ? drawYear + parseInt(value.substring(1), 10) :
9674 (value.match(/[+-].*/) ? thisYear + parseInt(value, 10) :
9675 parseInt(value, 10)));
9676 return (isNaN(year) ? thisYear : year);
9678 var year = determineYear(years[0]);
9679 var endYear = Math.max(year, determineYear(years[1] || ''));
9680 year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
9681 endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
9682 inst.yearshtml += '<select class="ui-datepicker-year" ' +
9683 'onchange="DP_jQuery_' + dpuuid + '.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'Y\');" ' +
9684 'onclick="DP_jQuery_' + dpuuid + '.datepicker._clickMonthYear(\'#' + inst.id + '\');"' +
9686 for (; year <= endYear; year++) {
9687 inst.yearshtml += '<option value="' + year + '"' +
9688 (year == drawYear ? ' selected="selected"' : '') +
9689 '>' + year + '</option>';
9691 inst.yearshtml += '</select>';
9692 //when showing there is no need for later update
9693 if( ! $.browser.mozilla ){
9694 html += inst.yearshtml;
9695 inst.yearshtml = null;
9697 // will be replaced later with inst.yearshtml
9698 html += '<select class="ui-datepicker-year"><option value="' + drawYear + '" selected="selected">' + drawYear + '</option></select>';
9701 html += this._get(inst, 'yearSuffix');
9702 if (showMonthAfterYear)
9703 html += (secondary || !(changeMonth && changeYear) ? ' ' : '') + monthHtml;
9704 html += '</div>'; // Close datepicker_header
9708 /* Adjust one of the date sub-fields. */
9709 _adjustInstDate: function(inst, offset, period) {
9710 var year = inst.drawYear + (period == 'Y' ? offset : 0);
9711 var month = inst.drawMonth + (period == 'M' ? offset : 0);
9712 var day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) +
9713 (period == 'D' ? offset : 0);
9714 var date = this._restrictMinMax(inst,
9715 this._daylightSavingAdjust(new Date(year, month, day)));
9716 inst.selectedDay = date.getDate();
9717 inst.drawMonth = inst.selectedMonth = date.getMonth();
9718 inst.drawYear = inst.selectedYear = date.getFullYear();
9719 if (period == 'M' || period == 'Y')
9720 this._notifyChange(inst);
9723 /* Ensure a date is within any min/max bounds. */
9724 _restrictMinMax: function(inst, date) {
9725 var minDate = this._getMinMaxDate(inst, 'min');
9726 var maxDate = this._getMinMaxDate(inst, 'max');
9727 var newDate = (minDate && date < minDate ? minDate : date);
9728 newDate = (maxDate && newDate > maxDate ? maxDate : newDate);
9732 /* Notify change of month/year. */
9733 _notifyChange: function(inst) {
9734 var onChange = this._get(inst, 'onChangeMonthYear');
9736 onChange.apply((inst.input ? inst.input[0] : null),
9737 [inst.selectedYear, inst.selectedMonth + 1, inst]);
9740 /* Determine the number of months to show. */
9741 _getNumberOfMonths: function(inst) {
9742 var numMonths = this._get(inst, 'numberOfMonths');
9743 return (numMonths == null ? [1, 1] : (typeof numMonths == 'number' ? [1, numMonths] : numMonths));
9746 /* Determine the current maximum date - ensure no time components are set. */
9747 _getMinMaxDate: function(inst, minMax) {
9748 return this._determineDate(inst, this._get(inst, minMax + 'Date'), null);
9751 /* Find the number of days in a given month. */
9752 _getDaysInMonth: function(year, month) {
9753 return 32 - this._daylightSavingAdjust(new Date(year, month, 32)).getDate();
9756 /* Find the day of the week of the first of a month. */
9757 _getFirstDayOfMonth: function(year, month) {
9758 return new Date(year, month, 1).getDay();
9761 /* Determines if we should allow a "next/prev" month display change. */
9762 _canAdjustMonth: function(inst, offset, curYear, curMonth) {
9763 var numMonths = this._getNumberOfMonths(inst);
9764 var date = this._daylightSavingAdjust(new Date(curYear,
9765 curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1));
9767 date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
9768 return this._isInRange(inst, date);
9771 /* Is the given date in the accepted range? */
9772 _isInRange: function(inst, date) {
9773 var minDate = this._getMinMaxDate(inst, 'min');
9774 var maxDate = this._getMinMaxDate(inst, 'max');
9775 return ((!minDate || date.getTime() >= minDate.getTime()) &&
9776 (!maxDate || date.getTime() <= maxDate.getTime()));
9779 /* Provide the configuration settings for formatting/parsing. */
9780 _getFormatConfig: function(inst) {
9781 var shortYearCutoff = this._get(inst, 'shortYearCutoff');
9782 shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff :
9783 new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
9784 return {shortYearCutoff: shortYearCutoff,
9785 dayNamesShort: this._get(inst, 'dayNamesShort'), dayNames: this._get(inst, 'dayNames'),
9786 monthNamesShort: this._get(inst, 'monthNamesShort'), monthNames: this._get(inst, 'monthNames')};
9789 /* Format the given date for display. */
9790 _formatDate: function(inst, day, month, year) {
9792 inst.currentDay = inst.selectedDay;
9793 inst.currentMonth = inst.selectedMonth;
9794 inst.currentYear = inst.selectedYear;
9796 var date = (day ? (typeof day == 'object' ? day :
9797 this._daylightSavingAdjust(new Date(year, month, day))) :
9798 this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
9799 return this.formatDate(this._get(inst, 'dateFormat'), date, this._getFormatConfig(inst));
9803 /* jQuery extend now ignores nulls! */
9804 function extendRemove(target, props) {
9805 $.extend(target, props);
9806 for (var name in props)
9807 if (props[name] == null || props[name] == undefined)
9808 target[name] = props[name];
9812 /* Determine whether an object is an array. */
9813 function isArray(a) {
9814 return (a && (($.browser.safari && typeof a == 'object' && a.length) ||
9815 (a.constructor && a.constructor.toString().match(/\Array\(\)/))));
9818 /* Invoke the datepicker functionality.
9819 @param options string - a command, optionally followed by additional parameters or
9820 Object - settings for attaching new datepicker functionality
9821 @return jQuery object */
9822 $.fn.datepicker = function(options){
9824 /* Verify an empty collection wasn't passed - Fixes #6976 */
9825 if ( !this.length ) {
9829 /* Initialise the date picker. */
9830 if (!$.datepicker.initialized) {
9831 $(document).mousedown($.datepicker._checkExternalClick).
9832 find('body').append($.datepicker.dpDiv);
9833 $.datepicker.initialized = true;
9836 var otherArgs = Array.prototype.slice.call(arguments, 1);
9837 if (typeof options == 'string' && (options == 'isDisabled' || options == 'getDate' || options == 'widget'))
9838 return $.datepicker['_' + options + 'Datepicker'].
9839 apply($.datepicker, [this[0]].concat(otherArgs));
9840 if (options == 'option' && arguments.length == 2 && typeof arguments[1] == 'string')
9841 return $.datepicker['_' + options + 'Datepicker'].
9842 apply($.datepicker, [this[0]].concat(otherArgs));
9843 return this.each(function() {
9844 typeof options == 'string' ?
9845 $.datepicker['_' + options + 'Datepicker'].
9846 apply($.datepicker, [this].concat(otherArgs)) :
9847 $.datepicker._attachDatepicker(this, options);
9851 $.datepicker = new Datepicker(); // singleton instance
9852 $.datepicker.initialized = false;
9853 $.datepicker.uuid = new Date().getTime();
9854 $.datepicker.version = "1.8.10";
9856 // Workaround for #4055
9857 // Add another global to avoid noConflict issues with inline event handlers
9858 window['DP_jQuery_' + dpuuid] = $;
9862 * jQuery UI Progressbar 1.8.10
9864 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
9865 * Dual licensed under the MIT or GPL Version 2 licenses.
9866 * http://jquery.org/license
9868 * http://docs.jquery.com/UI/Progressbar
9872 * jquery.ui.widget.js
9874 (function( $, undefined ) {
9876 $.widget( "ui.progressbar", {
9884 _create: function() {
9886 .addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
9888 role: "progressbar",
9889 "aria-valuemin": this.min,
9890 "aria-valuemax": this.options.max,
9891 "aria-valuenow": this._value()
9894 this.valueDiv = $( "<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>" )
9895 .appendTo( this.element );
9897 this.oldValue = this._value();
9898 this._refreshValue();
9901 destroy: function() {
9903 .removeClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
9904 .removeAttr( "role" )
9905 .removeAttr( "aria-valuemin" )
9906 .removeAttr( "aria-valuemax" )
9907 .removeAttr( "aria-valuenow" );
9909 this.valueDiv.remove();
9911 $.Widget.prototype.destroy.apply( this, arguments );
9914 value: function( newValue ) {
9915 if ( newValue === undefined ) {
9916 return this._value();
9919 this._setOption( "value", newValue );
9923 _setOption: function( key, value ) {
9924 if ( key === "value" ) {
9925 this.options.value = value;
9926 this._refreshValue();
9927 if ( this._value() === this.options.max ) {
9928 this._trigger( "complete" );
9932 $.Widget.prototype._setOption.apply( this, arguments );
9935 _value: function() {
9936 var val = this.options.value;
9937 // normalize invalid value
9938 if ( typeof val !== "number" ) {
9941 return Math.min( this.options.max, Math.max( this.min, val ) );
9944 _percentage: function() {
9945 return 100 * this._value() / this.options.max;
9948 _refreshValue: function() {
9949 var value = this.value();
9950 var percentage = this._percentage();
9952 if ( this.oldValue !== value ) {
9953 this.oldValue = value;
9954 this._trigger( "change" );
9958 .toggleClass( "ui-corner-right", value === this.options.max )
9959 .width( percentage.toFixed(0) + "%" );
9960 this.element.attr( "aria-valuenow", value );
9964 $.extend( $.ui.progressbar, {
9970 * jQuery UI Effects 1.8.10
9972 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
9973 * Dual licensed under the MIT or GPL Version 2 licenses.
9974 * http://jquery.org/license
9976 * http://docs.jquery.com/UI/Effects/
9978 ;jQuery.effects || (function($, undefined) {
9984 /******************************************************************************/
9985 /****************************** COLOR ANIMATIONS ******************************/
9986 /******************************************************************************/
9988 // override the animation for color styles
9989 $.each(['backgroundColor', 'borderBottomColor', 'borderLeftColor',
9990 'borderRightColor', 'borderTopColor', 'borderColor', 'color', 'outlineColor'],
9992 $.fx.step[attr] = function(fx) {
9993 if (!fx.colorInit) {
9994 fx.start = getColor(fx.elem, attr);
9995 fx.end = getRGB(fx.end);
9996 fx.colorInit = true;
9999 fx.elem.style[attr] = 'rgb(' +
10000 Math.max(Math.min(parseInt((fx.pos * (fx.end[0] - fx.start[0])) + fx.start[0], 10), 255), 0) + ',' +
10001 Math.max(Math.min(parseInt((fx.pos * (fx.end[1] - fx.start[1])) + fx.start[1], 10), 255), 0) + ',' +
10002 Math.max(Math.min(parseInt((fx.pos * (fx.end[2] - fx.start[2])) + fx.start[2], 10), 255), 0) + ')';
10006 // Color Conversion functions from highlightFade
10007 // By Blair Mitchelmore
10008 // http://jquery.offput.ca/highlightFade/
10010 // Parse strings looking for color tuples [255,255,255]
10011 function getRGB(color) {
10014 // Check if we're already dealing with an array of colors
10015 if ( color && color.constructor == Array && color.length == 3 )
10018 // Look for rgb(num,num,num)
10019 if (result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(color))
10020 return [parseInt(result[1],10), parseInt(result[2],10), parseInt(result[3],10)];
10022 // Look for rgb(num%,num%,num%)
10023 if (result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(color))
10024 return [parseFloat(result[1])*2.55, parseFloat(result[2])*2.55, parseFloat(result[3])*2.55];
10026 // Look for #a0b1c2
10027 if (result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(color))
10028 return [parseInt(result[1],16), parseInt(result[2],16), parseInt(result[3],16)];
10031 if (result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(color))
10032 return [parseInt(result[1]+result[1],16), parseInt(result[2]+result[2],16), parseInt(result[3]+result[3],16)];
10034 // Look for rgba(0, 0, 0, 0) == transparent in Safari 3
10035 if (result = /rgba\(0, 0, 0, 0\)/.exec(color))
10036 return colors['transparent'];
10038 // Otherwise, we're most likely dealing with a named color
10039 return colors[$.trim(color).toLowerCase()];
10042 function getColor(elem, attr) {
10046 color = $.curCSS(elem, attr);
10048 // Keep going until we find an element that has color, or we hit the body
10049 if ( color != '' && color != 'transparent' || $.nodeName(elem, "body") )
10052 attr = "backgroundColor";
10053 } while ( elem = elem.parentNode );
10055 return getRGB(color);
10058 // Some named colors to work with
10059 // From Interface by Stefan Petre
10060 // http://interface.eyecon.ro/
10064 azure:[240,255,255],
10065 beige:[245,245,220],
10070 darkblue:[0,0,139],
10071 darkcyan:[0,139,139],
10072 darkgrey:[169,169,169],
10073 darkgreen:[0,100,0],
10074 darkkhaki:[189,183,107],
10075 darkmagenta:[139,0,139],
10076 darkolivegreen:[85,107,47],
10077 darkorange:[255,140,0],
10078 darkorchid:[153,50,204],
10080 darksalmon:[233,150,122],
10081 darkviolet:[148,0,211],
10082 fuchsia:[255,0,255],
10086 khaki:[240,230,140],
10087 lightblue:[173,216,230],
10088 lightcyan:[224,255,255],
10089 lightgreen:[144,238,144],
10090 lightgrey:[211,211,211],
10091 lightpink:[255,182,193],
10092 lightyellow:[255,255,224],
10094 magenta:[255,0,255],
10098 orange:[255,165,0],
10099 pink:[255,192,203],
10100 purple:[128,0,128],
10101 violet:[128,0,128],
10103 silver:[192,192,192],
10104 white:[255,255,255],
10105 yellow:[255,255,0],
10106 transparent: [255,255,255]
10111 /******************************************************************************/
10112 /****************************** CLASS ANIMATIONS ******************************/
10113 /******************************************************************************/
10115 var classAnimationActions = ['add', 'remove', 'toggle'],
10116 shorthandStyles = {
10128 function getElementStyles() {
10129 var style = document.defaultView
10130 ? document.defaultView.getComputedStyle(this, null)
10131 : this.currentStyle,
10136 // webkit enumerates style porperties
10137 if (style && style.length && style[0] && style[style[0]]) {
10138 var len = style.length;
10141 if (typeof style[key] == 'string') {
10142 camelCase = key.replace(/\-(\w)/g, function(all, letter){
10143 return letter.toUpperCase();
10145 newStyle[camelCase] = style[key];
10149 for (key in style) {
10150 if (typeof style[key] === 'string') {
10151 newStyle[key] = style[key];
10159 function filterStyles(styles) {
10161 for (name in styles) {
10162 value = styles[name];
10164 // ignore null and undefined values
10166 // ignore functions (when does this occur?)
10167 $.isFunction(value) ||
10168 // shorthand styles that need to be expanded
10169 name in shorthandStyles ||
10170 // ignore scrollbars (break in IE)
10171 (/scrollbar/).test(name) ||
10173 // only colors or values that can be converted to numbers
10174 (!(/color/i).test(name) && isNaN(parseFloat(value)))
10176 delete styles[name];
10183 function styleDifference(oldStyle, newStyle) {
10184 var diff = { _: 0 }, // http://dev.jquery.com/ticket/5459
10187 for (name in newStyle) {
10188 if (oldStyle[name] != newStyle[name]) {
10189 diff[name] = newStyle[name];
10196 $.effects.animateClass = function(value, duration, easing, callback) {
10197 if ($.isFunction(easing)) {
10202 return this.queue('fx', function() {
10203 var that = $(this),
10204 originalStyleAttr = that.attr('style') || ' ',
10205 originalStyle = filterStyles(getElementStyles.call(this)),
10207 className = that.attr('className');
10209 $.each(classAnimationActions, function(i, action) {
10210 if (value[action]) {
10211 that[action + 'Class'](value[action]);
10214 newStyle = filterStyles(getElementStyles.call(this));
10215 that.attr('className', className);
10217 that.animate(styleDifference(originalStyle, newStyle), duration, easing, function() {
10218 $.each(classAnimationActions, function(i, action) {
10219 if (value[action]) { that[action + 'Class'](value[action]); }
10221 // work around bug in IE by clearing the cssText before setting it
10222 if (typeof that.attr('style') == 'object') {
10223 that.attr('style').cssText = '';
10224 that.attr('style').cssText = originalStyleAttr;
10226 that.attr('style', originalStyleAttr);
10228 if (callback) { callback.apply(this, arguments); }
10231 // $.animate adds a function to the end of the queue
10232 // but we want it at the front
10233 var queue = $.queue(this),
10234 anim = queue.splice(queue.length - 1, 1)[0];
10235 queue.splice(1, 0, anim);
10241 _addClass: $.fn.addClass,
10242 addClass: function(classNames, speed, easing, callback) {
10243 return speed ? $.effects.animateClass.apply(this, [{ add: classNames },speed,easing,callback]) : this._addClass(classNames);
10246 _removeClass: $.fn.removeClass,
10247 removeClass: function(classNames,speed,easing,callback) {
10248 return speed ? $.effects.animateClass.apply(this, [{ remove: classNames },speed,easing,callback]) : this._removeClass(classNames);
10251 _toggleClass: $.fn.toggleClass,
10252 toggleClass: function(classNames, force, speed, easing, callback) {
10253 if ( typeof force == "boolean" || force === undefined ) {
10255 // without speed parameter;
10256 return this._toggleClass(classNames, force);
10258 return $.effects.animateClass.apply(this, [(force?{add:classNames}:{remove:classNames}),speed,easing,callback]);
10261 // without switch parameter;
10262 return $.effects.animateClass.apply(this, [{ toggle: classNames },force,speed,easing]);
10266 switchClass: function(remove,add,speed,easing,callback) {
10267 return $.effects.animateClass.apply(this, [{ add: add, remove: remove },speed,easing,callback]);
10273 /******************************************************************************/
10274 /*********************************** EFFECTS **********************************/
10275 /******************************************************************************/
10277 $.extend($.effects, {
10280 // Saves a set of properties in a data storage
10281 save: function(element, set) {
10282 for(var i=0; i < set.length; i++) {
10283 if(set[i] !== null) element.data("ec.storage."+set[i], element[0].style[set[i]]);
10287 // Restores a set of previously saved properties from a data storage
10288 restore: function(element, set) {
10289 for(var i=0; i < set.length; i++) {
10290 if(set[i] !== null) element.css(set[i], element.data("ec.storage."+set[i]));
10294 setMode: function(el, mode) {
10295 if (mode == 'toggle') mode = el.is(':hidden') ? 'show' : 'hide'; // Set for toggle
10299 getBaseline: function(origin, original) { // Translates a [top,left] array into a baseline value
10300 // this should be a little more flexible in the future to handle a string & hash
10302 switch (origin[0]) {
10303 case 'top': y = 0; break;
10304 case 'middle': y = 0.5; break;
10305 case 'bottom': y = 1; break;
10306 default: y = origin[0] / original.height;
10308 switch (origin[1]) {
10309 case 'left': x = 0; break;
10310 case 'center': x = 0.5; break;
10311 case 'right': x = 1; break;
10312 default: x = origin[1] / original.width;
10314 return {x: x, y: y};
10317 // Wraps the element around a wrapper that copies position properties
10318 createWrapper: function(element) {
10320 // if the element is already wrapped, return it
10321 if (element.parent().is('.ui-effects-wrapper')) {
10322 return element.parent();
10325 // wrap the element
10327 width: element.outerWidth(true),
10328 height: element.outerHeight(true),
10329 'float': element.css('float')
10331 wrapper = $('<div></div>')
10332 .addClass('ui-effects-wrapper')
10335 background: 'transparent',
10341 element.wrap(wrapper);
10342 wrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually loose the reference to the wrapped element
10344 // transfer positioning properties to the wrapper
10345 if (element.css('position') == 'static') {
10346 wrapper.css({ position: 'relative' });
10347 element.css({ position: 'relative' });
10350 position: element.css('position'),
10351 zIndex: element.css('z-index')
10353 $.each(['top', 'left', 'bottom', 'right'], function(i, pos) {
10354 props[pos] = element.css(pos);
10355 if (isNaN(parseInt(props[pos], 10))) {
10356 props[pos] = 'auto';
10359 element.css({position: 'relative', top: 0, left: 0, right: 'auto', bottom: 'auto' });
10362 return wrapper.css(props).show();
10365 removeWrapper: function(element) {
10366 if (element.parent().is('.ui-effects-wrapper'))
10367 return element.parent().replaceWith(element);
10371 setTransition: function(element, list, factor, value) {
10372 value = value || {};
10373 $.each(list, function(i, x){
10374 unit = element.cssUnit(x);
10375 if (unit[0] > 0) value[x] = unit[0] * factor + unit[1];
10382 function _normalizeArguments(effect, options, speed, callback) {
10383 // shift params for method overloading
10384 if (typeof effect == 'object') {
10385 callback = options;
10388 effect = options.effect;
10390 if ($.isFunction(options)) {
10391 callback = options;
10395 if (typeof options == 'number' || $.fx.speeds[options]) {
10400 if ($.isFunction(speed)) {
10405 options = options || {};
10407 speed = speed || options.duration;
10408 speed = $.fx.off ? 0 : typeof speed == 'number'
10409 ? speed : speed in $.fx.speeds ? $.fx.speeds[speed] : $.fx.speeds._default;
10411 callback = callback || options.complete;
10413 return [effect, options, speed, callback];
10416 function standardSpeed( speed ) {
10417 // valid standard speeds
10418 if ( !speed || typeof speed === "number" || $.fx.speeds[ speed ] ) {
10422 // invalid strings - treat as "normal" speed
10423 if ( typeof speed === "string" && !$.effects[ speed ] ) {
10431 effect: function(effect, options, speed, callback) {
10432 var args = _normalizeArguments.apply(this, arguments),
10433 // TODO: make effects take actual parameters instead of a hash
10439 mode = args2.options.mode,
10440 effectMethod = $.effects[effect];
10442 if ( $.fx.off || !effectMethod ) {
10443 // delegate to the original method (e.g., .show()) if possible
10445 return this[ mode ]( args2.duration, args2.callback );
10447 return this.each(function() {
10448 if ( args2.callback ) {
10449 args2.callback.call( this );
10455 return effectMethod.call(this, args2);
10459 show: function(speed) {
10460 if ( standardSpeed( speed ) ) {
10461 return this._show.apply(this, arguments);
10463 var args = _normalizeArguments.apply(this, arguments);
10464 args[1].mode = 'show';
10465 return this.effect.apply(this, args);
10470 hide: function(speed) {
10471 if ( standardSpeed( speed ) ) {
10472 return this._hide.apply(this, arguments);
10474 var args = _normalizeArguments.apply(this, arguments);
10475 args[1].mode = 'hide';
10476 return this.effect.apply(this, args);
10480 // jQuery core overloads toggle and creates _toggle
10481 __toggle: $.fn.toggle,
10482 toggle: function(speed) {
10483 if ( standardSpeed( speed ) || typeof speed === "boolean" || $.isFunction( speed ) ) {
10484 return this.__toggle.apply(this, arguments);
10486 var args = _normalizeArguments.apply(this, arguments);
10487 args[1].mode = 'toggle';
10488 return this.effect.apply(this, args);
10492 // helper functions
10493 cssUnit: function(key) {
10494 var style = this.css(key), val = [];
10495 $.each( ['em','px','%','pt'], function(i, unit){
10496 if(style.indexOf(unit) > 0)
10497 val = [parseFloat(style), unit];
10505 /******************************************************************************/
10506 /*********************************** EASING ***********************************/
10507 /******************************************************************************/
10510 * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
10512 * Uses the built in easing capabilities added In jQuery 1.1
10513 * to offer multiple easing options
10515 * TERMS OF USE - jQuery Easing
10517 * Open source under the BSD License.
10519 * Copyright 2008 George McGinley Smith
10520 * All rights reserved.
10522 * Redistribution and use in source and binary forms, with or without modification,
10523 * are permitted provided that the following conditions are met:
10525 * Redistributions of source code must retain the above copyright notice, this list of
10526 * conditions and the following disclaimer.
10527 * Redistributions in binary form must reproduce the above copyright notice, this list
10528 * of conditions and the following disclaimer in the documentation and/or other materials
10529 * provided with the distribution.
10531 * Neither the name of the author nor the names of contributors may be used to endorse
10532 * or promote products derived from this software without specific prior written permission.
10534 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
10535 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
10536 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
10537 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
10538 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
10539 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
10540 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
10541 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
10542 * OF THE POSSIBILITY OF SUCH DAMAGE.
10546 // t: current time, b: begInnIng value, c: change In value, d: duration
10547 $.easing.jswing = $.easing.swing;
10551 def: 'easeOutQuad',
10552 swing: function (x, t, b, c, d) {
10553 //alert($.easing.default);
10554 return $.easing[$.easing.def](x, t, b, c, d);
10556 easeInQuad: function (x, t, b, c, d) {
10557 return c*(t/=d)*t + b;
10559 easeOutQuad: function (x, t, b, c, d) {
10560 return -c *(t/=d)*(t-2) + b;
10562 easeInOutQuad: function (x, t, b, c, d) {
10563 if ((t/=d/2) < 1) return c/2*t*t + b;
10564 return -c/2 * ((--t)*(t-2) - 1) + b;
10566 easeInCubic: function (x, t, b, c, d) {
10567 return c*(t/=d)*t*t + b;
10569 easeOutCubic: function (x, t, b, c, d) {
10570 return c*((t=t/d-1)*t*t + 1) + b;
10572 easeInOutCubic: function (x, t, b, c, d) {
10573 if ((t/=d/2) < 1) return c/2*t*t*t + b;
10574 return c/2*((t-=2)*t*t + 2) + b;
10576 easeInQuart: function (x, t, b, c, d) {
10577 return c*(t/=d)*t*t*t + b;
10579 easeOutQuart: function (x, t, b, c, d) {
10580 return -c * ((t=t/d-1)*t*t*t - 1) + b;
10582 easeInOutQuart: function (x, t, b, c, d) {
10583 if ((t/=d/2) < 1) return c/2*t*t*t*t + b;
10584 return -c/2 * ((t-=2)*t*t*t - 2) + b;
10586 easeInQuint: function (x, t, b, c, d) {
10587 return c*(t/=d)*t*t*t*t + b;
10589 easeOutQuint: function (x, t, b, c, d) {
10590 return c*((t=t/d-1)*t*t*t*t + 1) + b;
10592 easeInOutQuint: function (x, t, b, c, d) {
10593 if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b;
10594 return c/2*((t-=2)*t*t*t*t + 2) + b;
10596 easeInSine: function (x, t, b, c, d) {
10597 return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
10599 easeOutSine: function (x, t, b, c, d) {
10600 return c * Math.sin(t/d * (Math.PI/2)) + b;
10602 easeInOutSine: function (x, t, b, c, d) {
10603 return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
10605 easeInExpo: function (x, t, b, c, d) {
10606 return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
10608 easeOutExpo: function (x, t, b, c, d) {
10609 return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
10611 easeInOutExpo: function (x, t, b, c, d) {
10612 if (t==0) return b;
10613 if (t==d) return b+c;
10614 if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
10615 return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
10617 easeInCirc: function (x, t, b, c, d) {
10618 return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
10620 easeOutCirc: function (x, t, b, c, d) {
10621 return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
10623 easeInOutCirc: function (x, t, b, c, d) {
10624 if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
10625 return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
10627 easeInElastic: function (x, t, b, c, d) {
10628 var s=1.70158;var p=0;var a=c;
10629 if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3;
10630 if (a < Math.abs(c)) { a=c; var s=p/4; }
10631 else var s = p/(2*Math.PI) * Math.asin (c/a);
10632 return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
10634 easeOutElastic: function (x, t, b, c, d) {
10635 var s=1.70158;var p=0;var a=c;
10636 if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3;
10637 if (a < Math.abs(c)) { a=c; var s=p/4; }
10638 else var s = p/(2*Math.PI) * Math.asin (c/a);
10639 return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
10641 easeInOutElastic: function (x, t, b, c, d) {
10642 var s=1.70158;var p=0;var a=c;
10643 if (t==0) return b; if ((t/=d/2)==2) return b+c; if (!p) p=d*(.3*1.5);
10644 if (a < Math.abs(c)) { a=c; var s=p/4; }
10645 else var s = p/(2*Math.PI) * Math.asin (c/a);
10646 if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
10647 return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
10649 easeInBack: function (x, t, b, c, d, s) {
10650 if (s == undefined) s = 1.70158;
10651 return c*(t/=d)*t*((s+1)*t - s) + b;
10653 easeOutBack: function (x, t, b, c, d, s) {
10654 if (s == undefined) s = 1.70158;
10655 return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
10657 easeInOutBack: function (x, t, b, c, d, s) {
10658 if (s == undefined) s = 1.70158;
10659 if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
10660 return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
10662 easeInBounce: function (x, t, b, c, d) {
10663 return c - $.easing.easeOutBounce (x, d-t, 0, c, d) + b;
10665 easeOutBounce: function (x, t, b, c, d) {
10666 if ((t/=d) < (1/2.75)) {
10667 return c*(7.5625*t*t) + b;
10668 } else if (t < (2/2.75)) {
10669 return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
10670 } else if (t < (2.5/2.75)) {
10671 return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
10673 return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
10676 easeInOutBounce: function (x, t, b, c, d) {
10677 if (t < d/2) return $.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b;
10678 return $.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b;
10684 * TERMS OF USE - EASING EQUATIONS
10686 * Open source under the BSD License.
10688 * Copyright 2001 Robert Penner
10689 * All rights reserved.
10691 * Redistribution and use in source and binary forms, with or without modification,
10692 * are permitted provided that the following conditions are met:
10694 * Redistributions of source code must retain the above copyright notice, this list of
10695 * conditions and the following disclaimer.
10696 * Redistributions in binary form must reproduce the above copyright notice, this list
10697 * of conditions and the following disclaimer in the documentation and/or other materials
10698 * provided with the distribution.
10700 * Neither the name of the author nor the names of contributors may be used to endorse
10701 * or promote products derived from this software without specific prior written permission.
10703 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
10704 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
10705 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
10706 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
10707 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
10708 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
10709 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
10710 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
10711 * OF THE POSSIBILITY OF SUCH DAMAGE.
10717 * jQuery UI Effects Blind 1.8.10
10719 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
10720 * Dual licensed under the MIT or GPL Version 2 licenses.
10721 * http://jquery.org/license
10723 * http://docs.jquery.com/UI/Effects/Blind
10726 * jquery.effects.core.js
10728 (function( $, undefined ) {
10730 $.effects.blind = function(o) {
10732 return this.queue(function() {
10735 var el = $(this), props = ['position','top','bottom','left','right'];
10738 var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
10739 var direction = o.options.direction || 'vertical'; // Default direction
10742 $.effects.save(el, props); el.show(); // Save & Show
10743 var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
10744 var ref = (direction == 'vertical') ? 'height' : 'width';
10745 var distance = (direction == 'vertical') ? wrapper.height() : wrapper.width();
10746 if(mode == 'show') wrapper.css(ref, 0); // Shift
10749 var animation = {};
10750 animation[ref] = mode == 'show' ? distance : 0;
10753 wrapper.animate(animation, o.duration, o.options.easing, function() {
10754 if(mode == 'hide') el.hide(); // Hide
10755 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
10756 if(o.callback) o.callback.apply(el[0], arguments); // Callback
10766 * jQuery UI Effects Bounce 1.8.10
10768 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
10769 * Dual licensed under the MIT or GPL Version 2 licenses.
10770 * http://jquery.org/license
10772 * http://docs.jquery.com/UI/Effects/Bounce
10775 * jquery.effects.core.js
10777 (function( $, undefined ) {
10779 $.effects.bounce = function(o) {
10781 return this.queue(function() {
10784 var el = $(this), props = ['position','top','bottom','left','right'];
10787 var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
10788 var direction = o.options.direction || 'up'; // Default direction
10789 var distance = o.options.distance || 20; // Default distance
10790 var times = o.options.times || 5; // Default # of times
10791 var speed = o.duration || 250; // Default speed per bounce
10792 if (/show|hide/.test(mode)) props.push('opacity'); // Avoid touching opacity to prevent clearType and PNG issues in IE
10795 $.effects.save(el, props); el.show(); // Save & Show
10796 $.effects.createWrapper(el); // Create Wrapper
10797 var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
10798 var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
10799 var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) / 3 : el.outerWidth({margin:true}) / 3);
10800 if (mode == 'show') el.css('opacity', 0).css(ref, motion == 'pos' ? -distance : distance); // Shift
10801 if (mode == 'hide') distance = distance / (times * 2);
10802 if (mode != 'hide') times--;
10805 if (mode == 'show') { // Show Bounce
10806 var animation = {opacity: 1};
10807 animation[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
10808 el.animate(animation, speed / 2, o.options.easing);
10809 distance = distance / 2;
10812 for (var i = 0; i < times; i++) { // Bounces
10813 var animation1 = {}, animation2 = {};
10814 animation1[ref] = (motion == 'pos' ? '-=' : '+=') + distance;
10815 animation2[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
10816 el.animate(animation1, speed / 2, o.options.easing).animate(animation2, speed / 2, o.options.easing);
10817 distance = (mode == 'hide') ? distance * 2 : distance / 2;
10819 if (mode == 'hide') { // Last Bounce
10820 var animation = {opacity: 0};
10821 animation[ref] = (motion == 'pos' ? '-=' : '+=') + distance;
10822 el.animate(animation, speed / 2, o.options.easing, function(){
10824 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
10825 if(o.callback) o.callback.apply(this, arguments); // Callback
10828 var animation1 = {}, animation2 = {};
10829 animation1[ref] = (motion == 'pos' ? '-=' : '+=') + distance;
10830 animation2[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
10831 el.animate(animation1, speed / 2, o.options.easing).animate(animation2, speed / 2, o.options.easing, function(){
10832 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
10833 if(o.callback) o.callback.apply(this, arguments); // Callback
10836 el.queue('fx', function() { el.dequeue(); });
10844 * jQuery UI Effects Clip 1.8.10
10846 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
10847 * Dual licensed under the MIT or GPL Version 2 licenses.
10848 * http://jquery.org/license
10850 * http://docs.jquery.com/UI/Effects/Clip
10853 * jquery.effects.core.js
10855 (function( $, undefined ) {
10857 $.effects.clip = function(o) {
10859 return this.queue(function() {
10862 var el = $(this), props = ['position','top','bottom','left','right','height','width'];
10865 var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
10866 var direction = o.options.direction || 'vertical'; // Default direction
10869 $.effects.save(el, props); el.show(); // Save & Show
10870 var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
10871 var animate = el[0].tagName == 'IMG' ? wrapper : el;
10873 size: (direction == 'vertical') ? 'height' : 'width',
10874 position: (direction == 'vertical') ? 'top' : 'left'
10876 var distance = (direction == 'vertical') ? animate.height() : animate.width();
10877 if(mode == 'show') { animate.css(ref.size, 0); animate.css(ref.position, distance / 2); } // Shift
10880 var animation = {};
10881 animation[ref.size] = mode == 'show' ? distance : 0;
10882 animation[ref.position] = mode == 'show' ? 0 : distance / 2;
10885 animate.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
10886 if(mode == 'hide') el.hide(); // Hide
10887 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
10888 if(o.callback) o.callback.apply(el[0], arguments); // Callback
10898 * jQuery UI Effects Drop 1.8.10
10900 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
10901 * Dual licensed under the MIT or GPL Version 2 licenses.
10902 * http://jquery.org/license
10904 * http://docs.jquery.com/UI/Effects/Drop
10907 * jquery.effects.core.js
10909 (function( $, undefined ) {
10911 $.effects.drop = function(o) {
10913 return this.queue(function() {
10916 var el = $(this), props = ['position','top','bottom','left','right','opacity'];
10919 var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
10920 var direction = o.options.direction || 'left'; // Default Direction
10923 $.effects.save(el, props); el.show(); // Save & Show
10924 $.effects.createWrapper(el); // Create Wrapper
10925 var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
10926 var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
10927 var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) / 2 : el.outerWidth({margin:true}) / 2);
10928 if (mode == 'show') el.css('opacity', 0).css(ref, motion == 'pos' ? -distance : distance); // Shift
10931 var animation = {opacity: mode == 'show' ? 1 : 0};
10932 animation[ref] = (mode == 'show' ? (motion == 'pos' ? '+=' : '-=') : (motion == 'pos' ? '-=' : '+=')) + distance;
10935 el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
10936 if(mode == 'hide') el.hide(); // Hide
10937 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
10938 if(o.callback) o.callback.apply(this, arguments); // Callback
10948 * jQuery UI Effects Explode 1.8.10
10950 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
10951 * Dual licensed under the MIT or GPL Version 2 licenses.
10952 * http://jquery.org/license
10954 * http://docs.jquery.com/UI/Effects/Explode
10957 * jquery.effects.core.js
10959 (function( $, undefined ) {
10961 $.effects.explode = function(o) {
10963 return this.queue(function() {
10965 var rows = o.options.pieces ? Math.round(Math.sqrt(o.options.pieces)) : 3;
10966 var cells = o.options.pieces ? Math.round(Math.sqrt(o.options.pieces)) : 3;
10968 o.options.mode = o.options.mode == 'toggle' ? ($(this).is(':visible') ? 'hide' : 'show') : o.options.mode;
10969 var el = $(this).show().css('visibility', 'hidden');
10970 var offset = el.offset();
10972 //Substract the margins - not fixing the problem yet.
10973 offset.top -= parseInt(el.css("marginTop"),10) || 0;
10974 offset.left -= parseInt(el.css("marginLeft"),10) || 0;
10976 var width = el.outerWidth(true);
10977 var height = el.outerHeight(true);
10979 for(var i=0;i<rows;i++) { // =
10980 for(var j=0;j<cells;j++) { // ||
10984 .wrap('<div></div>')
10986 position: 'absolute',
10987 visibility: 'visible',
10988 left: -j*(width/cells),
10989 top: -i*(height/rows)
10992 .addClass('ui-effects-explode')
10994 position: 'absolute',
10995 overflow: 'hidden',
10996 width: width/cells,
10997 height: height/rows,
10998 left: offset.left + j*(width/cells) + (o.options.mode == 'show' ? (j-Math.floor(cells/2))*(width/cells) : 0),
10999 top: offset.top + i*(height/rows) + (o.options.mode == 'show' ? (i-Math.floor(rows/2))*(height/rows) : 0),
11000 opacity: o.options.mode == 'show' ? 0 : 1
11002 left: offset.left + j*(width/cells) + (o.options.mode == 'show' ? 0 : (j-Math.floor(cells/2))*(width/cells)),
11003 top: offset.top + i*(height/rows) + (o.options.mode == 'show' ? 0 : (i-Math.floor(rows/2))*(height/rows)),
11004 opacity: o.options.mode == 'show' ? 1 : 0
11005 }, o.duration || 500);
11009 // Set a timeout, to call the callback approx. when the other animations have finished
11010 setTimeout(function() {
11012 o.options.mode == 'show' ? el.css({ visibility: 'visible' }) : el.css({ visibility: 'visible' }).hide();
11013 if(o.callback) o.callback.apply(el[0]); // Callback
11016 $('div.ui-effects-explode').remove();
11018 }, o.duration || 500);
11027 * jQuery UI Effects Fade 1.8.10
11029 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
11030 * Dual licensed under the MIT or GPL Version 2 licenses.
11031 * http://jquery.org/license
11033 * http://docs.jquery.com/UI/Effects/Fade
11036 * jquery.effects.core.js
11038 (function( $, undefined ) {
11040 $.effects.fade = function(o) {
11041 return this.queue(function() {
11042 var elem = $(this),
11043 mode = $.effects.setMode(elem, o.options.mode || 'hide');
11045 elem.animate({ opacity: mode }, {
11047 duration: o.duration,
11048 easing: o.options.easing,
11049 complete: function() {
11050 (o.callback && o.callback.apply(this, arguments));
11059 * jQuery UI Effects Fold 1.8.10
11061 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
11062 * Dual licensed under the MIT or GPL Version 2 licenses.
11063 * http://jquery.org/license
11065 * http://docs.jquery.com/UI/Effects/Fold
11068 * jquery.effects.core.js
11070 (function( $, undefined ) {
11072 $.effects.fold = function(o) {
11074 return this.queue(function() {
11077 var el = $(this), props = ['position','top','bottom','left','right'];
11080 var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
11081 var size = o.options.size || 15; // Default fold size
11082 var horizFirst = !(!o.options.horizFirst); // Ensure a boolean value
11083 var duration = o.duration ? o.duration / 2 : $.fx.speeds._default / 2;
11086 $.effects.save(el, props); el.show(); // Save & Show
11087 var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
11088 var widthFirst = ((mode == 'show') != horizFirst);
11089 var ref = widthFirst ? ['width', 'height'] : ['height', 'width'];
11090 var distance = widthFirst ? [wrapper.width(), wrapper.height()] : [wrapper.height(), wrapper.width()];
11091 var percent = /([0-9]+)%/.exec(size);
11092 if(percent) size = parseInt(percent[1],10) / 100 * distance[mode == 'hide' ? 0 : 1];
11093 if(mode == 'show') wrapper.css(horizFirst ? {height: 0, width: size} : {height: size, width: 0}); // Shift
11096 var animation1 = {}, animation2 = {};
11097 animation1[ref[0]] = mode == 'show' ? distance[0] : size;
11098 animation2[ref[1]] = mode == 'show' ? distance[1] : 0;
11101 wrapper.animate(animation1, duration, o.options.easing)
11102 .animate(animation2, duration, o.options.easing, function() {
11103 if(mode == 'hide') el.hide(); // Hide
11104 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
11105 if(o.callback) o.callback.apply(el[0], arguments); // Callback
11115 * jQuery UI Effects Highlight 1.8.10
11117 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
11118 * Dual licensed under the MIT or GPL Version 2 licenses.
11119 * http://jquery.org/license
11121 * http://docs.jquery.com/UI/Effects/Highlight
11124 * jquery.effects.core.js
11126 (function( $, undefined ) {
11128 $.effects.highlight = function(o) {
11129 return this.queue(function() {
11130 var elem = $(this),
11131 props = ['backgroundImage', 'backgroundColor', 'opacity'],
11132 mode = $.effects.setMode(elem, o.options.mode || 'show'),
11134 backgroundColor: elem.css('backgroundColor')
11137 if (mode == 'hide') {
11138 animation.opacity = 0;
11141 $.effects.save(elem, props);
11145 backgroundImage: 'none',
11146 backgroundColor: o.options.color || '#ffff99'
11148 .animate(animation, {
11150 duration: o.duration,
11151 easing: o.options.easing,
11152 complete: function() {
11153 (mode == 'hide' && elem.hide());
11154 $.effects.restore(elem, props);
11155 (mode == 'show' && !$.support.opacity && this.style.removeAttribute('filter'));
11156 (o.callback && o.callback.apply(this, arguments));
11165 * jQuery UI Effects Pulsate 1.8.10
11167 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
11168 * Dual licensed under the MIT or GPL Version 2 licenses.
11169 * http://jquery.org/license
11171 * http://docs.jquery.com/UI/Effects/Pulsate
11174 * jquery.effects.core.js
11176 (function( $, undefined ) {
11178 $.effects.pulsate = function(o) {
11179 return this.queue(function() {
11180 var elem = $(this),
11181 mode = $.effects.setMode(elem, o.options.mode || 'show');
11182 times = ((o.options.times || 5) * 2) - 1;
11183 duration = o.duration ? o.duration / 2 : $.fx.speeds._default / 2,
11184 isVisible = elem.is(':visible'),
11188 elem.css('opacity', 0).show();
11192 if ((mode == 'hide' && isVisible) || (mode == 'show' && !isVisible)) {
11196 for (var i = 0; i < times; i++) {
11197 elem.animate({ opacity: animateTo }, duration, o.options.easing);
11198 animateTo = (animateTo + 1) % 2;
11201 elem.animate({ opacity: animateTo }, duration, o.options.easing, function() {
11202 if (animateTo == 0) {
11205 (o.callback && o.callback.apply(this, arguments));
11209 .queue('fx', function() { elem.dequeue(); })
11216 * jQuery UI Effects Scale 1.8.10
11218 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
11219 * Dual licensed under the MIT or GPL Version 2 licenses.
11220 * http://jquery.org/license
11222 * http://docs.jquery.com/UI/Effects/Scale
11225 * jquery.effects.core.js
11227 (function( $, undefined ) {
11229 $.effects.puff = function(o) {
11230 return this.queue(function() {
11231 var elem = $(this),
11232 mode = $.effects.setMode(elem, o.options.mode || 'hide'),
11233 percent = parseInt(o.options.percent, 10) || 150,
11234 factor = percent / 100,
11235 original = { height: elem.height(), width: elem.width() };
11237 $.extend(o.options, {
11240 percent: mode == 'hide' ? percent : 100,
11241 from: mode == 'hide'
11244 height: original.height * factor,
11245 width: original.width * factor
11249 elem.effect('scale', o.options, o.duration, o.callback);
11254 $.effects.scale = function(o) {
11256 return this.queue(function() {
11262 var options = $.extend(true, {}, o.options);
11263 var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
11264 var percent = parseInt(o.options.percent,10) || (parseInt(o.options.percent,10) == 0 ? 0 : (mode == 'hide' ? 0 : 100)); // Set default scaling percent
11265 var direction = o.options.direction || 'both'; // Set default axis
11266 var origin = o.options.origin; // The origin of the scaling
11267 if (mode != 'effect') { // Set default origin and restore for show/hide
11268 options.origin = origin || ['middle','center'];
11269 options.restore = true;
11271 var original = {height: el.height(), width: el.width()}; // Save original
11272 el.from = o.options.from || (mode == 'show' ? {height: 0, width: 0} : original); // Default from state
11275 var factor = { // Set scaling factor
11276 y: direction != 'horizontal' ? (percent / 100) : 1,
11277 x: direction != 'vertical' ? (percent / 100) : 1
11279 el.to = {height: original.height * factor.y, width: original.width * factor.x}; // Set to state
11281 if (o.options.fade) { // Fade option to support puff
11282 if (mode == 'show') {el.from.opacity = 0; el.to.opacity = 1;};
11283 if (mode == 'hide') {el.from.opacity = 1; el.to.opacity = 0;};
11287 options.from = el.from; options.to = el.to; options.mode = mode;
11290 el.effect('size', options, o.duration, o.callback);
11296 $.effects.size = function(o) {
11298 return this.queue(function() {
11301 var el = $(this), props = ['position','top','bottom','left','right','width','height','overflow','opacity'];
11302 var props1 = ['position','top','bottom','left','right','overflow','opacity']; // Always restore
11303 var props2 = ['width','height','overflow']; // Copy for children
11304 var cProps = ['fontSize'];
11305 var vProps = ['borderTopWidth', 'borderBottomWidth', 'paddingTop', 'paddingBottom'];
11306 var hProps = ['borderLeftWidth', 'borderRightWidth', 'paddingLeft', 'paddingRight'];
11309 var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
11310 var restore = o.options.restore || false; // Default restore
11311 var scale = o.options.scale || 'both'; // Default scale mode
11312 var origin = o.options.origin; // The origin of the sizing
11313 var original = {height: el.height(), width: el.width()}; // Save original
11314 el.from = o.options.from || original; // Default from state
11315 el.to = o.options.to || original; // Default to state
11317 if (origin) { // Calculate baseline shifts
11318 var baseline = $.effects.getBaseline(origin, original);
11319 el.from.top = (original.height - el.from.height) * baseline.y;
11320 el.from.left = (original.width - el.from.width) * baseline.x;
11321 el.to.top = (original.height - el.to.height) * baseline.y;
11322 el.to.left = (original.width - el.to.width) * baseline.x;
11324 var factor = { // Set scaling factor
11325 from: {y: el.from.height / original.height, x: el.from.width / original.width},
11326 to: {y: el.to.height / original.height, x: el.to.width / original.width}
11328 if (scale == 'box' || scale == 'both') { // Scale the css box
11329 if (factor.from.y != factor.to.y) { // Vertical props scaling
11330 props = props.concat(vProps);
11331 el.from = $.effects.setTransition(el, vProps, factor.from.y, el.from);
11332 el.to = $.effects.setTransition(el, vProps, factor.to.y, el.to);
11334 if (factor.from.x != factor.to.x) { // Horizontal props scaling
11335 props = props.concat(hProps);
11336 el.from = $.effects.setTransition(el, hProps, factor.from.x, el.from);
11337 el.to = $.effects.setTransition(el, hProps, factor.to.x, el.to);
11340 if (scale == 'content' || scale == 'both') { // Scale the content
11341 if (factor.from.y != factor.to.y) { // Vertical props scaling
11342 props = props.concat(cProps);
11343 el.from = $.effects.setTransition(el, cProps, factor.from.y, el.from);
11344 el.to = $.effects.setTransition(el, cProps, factor.to.y, el.to);
11347 $.effects.save(el, restore ? props : props1); el.show(); // Save & Show
11348 $.effects.createWrapper(el); // Create Wrapper
11349 el.css('overflow','hidden').css(el.from); // Shift
11352 if (scale == 'content' || scale == 'both') { // Scale the children
11353 vProps = vProps.concat(['marginTop','marginBottom']).concat(cProps); // Add margins/font-size
11354 hProps = hProps.concat(['marginLeft','marginRight']); // Add margins
11355 props2 = props.concat(vProps).concat(hProps); // Concat
11356 el.find("*[width]").each(function(){
11358 if (restore) $.effects.save(child, props2);
11359 var c_original = {height: child.height(), width: child.width()}; // Save original
11360 child.from = {height: c_original.height * factor.from.y, width: c_original.width * factor.from.x};
11361 child.to = {height: c_original.height * factor.to.y, width: c_original.width * factor.to.x};
11362 if (factor.from.y != factor.to.y) { // Vertical props scaling
11363 child.from = $.effects.setTransition(child, vProps, factor.from.y, child.from);
11364 child.to = $.effects.setTransition(child, vProps, factor.to.y, child.to);
11366 if (factor.from.x != factor.to.x) { // Horizontal props scaling
11367 child.from = $.effects.setTransition(child, hProps, factor.from.x, child.from);
11368 child.to = $.effects.setTransition(child, hProps, factor.to.x, child.to);
11370 child.css(child.from); // Shift children
11371 child.animate(child.to, o.duration, o.options.easing, function(){
11372 if (restore) $.effects.restore(child, props2); // Restore children
11373 }); // Animate children
11378 el.animate(el.to, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
11379 if (el.to.opacity === 0) {
11380 el.css('opacity', el.from.opacity);
11382 if(mode == 'hide') el.hide(); // Hide
11383 $.effects.restore(el, restore ? props : props1); $.effects.removeWrapper(el); // Restore
11384 if(o.callback) o.callback.apply(this, arguments); // Callback
11394 * jQuery UI Effects Shake 1.8.10
11396 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
11397 * Dual licensed under the MIT or GPL Version 2 licenses.
11398 * http://jquery.org/license
11400 * http://docs.jquery.com/UI/Effects/Shake
11403 * jquery.effects.core.js
11405 (function( $, undefined ) {
11407 $.effects.shake = function(o) {
11409 return this.queue(function() {
11412 var el = $(this), props = ['position','top','bottom','left','right'];
11415 var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
11416 var direction = o.options.direction || 'left'; // Default direction
11417 var distance = o.options.distance || 20; // Default distance
11418 var times = o.options.times || 3; // Default # of times
11419 var speed = o.duration || o.options.duration || 140; // Default speed per shake
11422 $.effects.save(el, props); el.show(); // Save & Show
11423 $.effects.createWrapper(el); // Create Wrapper
11424 var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
11425 var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
11428 var animation = {}, animation1 = {}, animation2 = {};
11429 animation[ref] = (motion == 'pos' ? '-=' : '+=') + distance;
11430 animation1[ref] = (motion == 'pos' ? '+=' : '-=') + distance * 2;
11431 animation2[ref] = (motion == 'pos' ? '-=' : '+=') + distance * 2;
11434 el.animate(animation, speed, o.options.easing);
11435 for (var i = 1; i < times; i++) { // Shakes
11436 el.animate(animation1, speed, o.options.easing).animate(animation2, speed, o.options.easing);
11438 el.animate(animation1, speed, o.options.easing).
11439 animate(animation, speed / 2, o.options.easing, function(){ // Last shake
11440 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
11441 if(o.callback) o.callback.apply(this, arguments); // Callback
11443 el.queue('fx', function() { el.dequeue(); });
11451 * jQuery UI Effects Slide 1.8.10
11453 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
11454 * Dual licensed under the MIT or GPL Version 2 licenses.
11455 * http://jquery.org/license
11457 * http://docs.jquery.com/UI/Effects/Slide
11460 * jquery.effects.core.js
11462 (function( $, undefined ) {
11464 $.effects.slide = function(o) {
11466 return this.queue(function() {
11469 var el = $(this), props = ['position','top','bottom','left','right'];
11472 var mode = $.effects.setMode(el, o.options.mode || 'show'); // Set Mode
11473 var direction = o.options.direction || 'left'; // Default Direction
11476 $.effects.save(el, props); el.show(); // Save & Show
11477 $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
11478 var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
11479 var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
11480 var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) : el.outerWidth({margin:true}));
11481 if (mode == 'show') el.css(ref, motion == 'pos' ? (isNaN(distance) ? "-" + distance : -distance) : distance); // Shift
11484 var animation = {};
11485 animation[ref] = (mode == 'show' ? (motion == 'pos' ? '+=' : '-=') : (motion == 'pos' ? '-=' : '+=')) + distance;
11488 el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
11489 if(mode == 'hide') el.hide(); // Hide
11490 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
11491 if(o.callback) o.callback.apply(this, arguments); // Callback
11501 * jQuery UI Effects Transfer 1.8.10
11503 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
11504 * Dual licensed under the MIT or GPL Version 2 licenses.
11505 * http://jquery.org/license
11507 * http://docs.jquery.com/UI/Effects/Transfer
11510 * jquery.effects.core.js
11512 (function( $, undefined ) {
11514 $.effects.transfer = function(o) {
11515 return this.queue(function() {
11516 var elem = $(this),
11517 target = $(o.options.to),
11518 endPosition = target.offset(),
11520 top: endPosition.top,
11521 left: endPosition.left,
11522 height: target.innerHeight(),
11523 width: target.innerWidth()
11525 startPosition = elem.offset(),
11526 transfer = $('<div class="ui-effects-transfer"></div>')
11527 .appendTo(document.body)
11528 .addClass(o.options.className)
11530 top: startPosition.top,
11531 left: startPosition.left,
11532 height: elem.innerHeight(),
11533 width: elem.innerWidth(),
11534 position: 'absolute'
11536 .animate(animation, o.duration, o.options.easing, function() {
11538 (o.callback && o.callback.apply(elem[0], arguments));