Add OK and Cancel button for grid editing
[phpmyadmin/arisferyanto.git] / js / jquery / jquery-ui-1.8.16.custom.js
blobfc8d9d1a76ea92afabce92ef86ab28384addef6e
1 /*!
2 * jQuery UI 1.8.16
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
9 */
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
15 $.ui = $.ui || {};
16 if ( $.ui.version ) {
17 return;
20 $.extend( $.ui, {
21 version: "1.8.16",
23 keyCode: {
24 ALT: 18,
25 BACKSPACE: 8,
26 CAPS_LOCK: 20,
27 COMMA: 188,
28 COMMAND: 91,
29 COMMAND_LEFT: 91, // COMMAND
30 COMMAND_RIGHT: 93,
31 CONTROL: 17,
32 DELETE: 46,
33 DOWN: 40,
34 END: 35,
35 ENTER: 13,
36 ESCAPE: 27,
37 HOME: 36,
38 INSERT: 45,
39 LEFT: 37,
40 MENU: 93, // COMMAND_RIGHT
41 NUMPAD_ADD: 107,
42 NUMPAD_DECIMAL: 110,
43 NUMPAD_DIVIDE: 111,
44 NUMPAD_ENTER: 108,
45 NUMPAD_MULTIPLY: 106,
46 NUMPAD_SUBTRACT: 109,
47 PAGE_DOWN: 34,
48 PAGE_UP: 33,
49 PERIOD: 190,
50 RIGHT: 39,
51 SHIFT: 16,
52 SPACE: 32,
53 TAB: 9,
54 UP: 38,
55 WINDOWS: 91 // COMMAND
57 });
59 // plugins
60 $.fn.extend({
61 propAttr: $.fn.prop || $.fn.attr,
63 _focus: $.fn.focus,
64 focus: function( delay, fn ) {
65 return typeof delay === "number" ?
66 this.each(function() {
67 var elem = this;
68 setTimeout(function() {
69 $( elem ).focus();
70 if ( fn ) {
71 fn.call( elem );
73 }, delay );
74 }) :
75 this._focus.apply( this, arguments );
78 scrollParent: function() {
79 var scrollParent;
80 if (($.browser.msie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) {
81 scrollParent = this.parents().filter(function() {
82 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 }).eq(0);
84 } else {
85 scrollParent = this.parents().filter(function() {
86 return (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
87 }).eq(0);
90 return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent;
93 zIndex: function( zIndex ) {
94 if ( zIndex !== undefined ) {
95 return this.css( "zIndex", zIndex );
98 if ( this.length ) {
99 var elem = $( this[ 0 ] ), position, value;
100 while ( elem.length && elem[ 0 ] !== document ) {
101 // Ignore z-index if position is set to a value where z-index is ignored by the browser
102 // This makes behavior of this function consistent across browsers
103 // WebKit always returns auto if the element is positioned
104 position = elem.css( "position" );
105 if ( position === "absolute" || position === "relative" || position === "fixed" ) {
106 // IE returns 0 when zIndex is not specified
107 // other browsers return a string
108 // we ignore the case of nested elements with an explicit value of 0
109 // <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
110 value = parseInt( elem.css( "zIndex" ), 10 );
111 if ( !isNaN( value ) && value !== 0 ) {
112 return value;
115 elem = elem.parent();
119 return 0;
122 disableSelection: function() {
123 return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) +
124 ".ui-disableSelection", function( event ) {
125 event.preventDefault();
129 enableSelection: function() {
130 return this.unbind( ".ui-disableSelection" );
134 $.each( [ "Width", "Height" ], function( i, name ) {
135 var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
136 type = name.toLowerCase(),
137 orig = {
138 innerWidth: $.fn.innerWidth,
139 innerHeight: $.fn.innerHeight,
140 outerWidth: $.fn.outerWidth,
141 outerHeight: $.fn.outerHeight
144 function reduce( elem, size, border, margin ) {
145 $.each( side, function() {
146 size -= parseFloat( $.curCSS( elem, "padding" + this, true) ) || 0;
147 if ( border ) {
148 size -= parseFloat( $.curCSS( elem, "border" + this + "Width", true) ) || 0;
150 if ( margin ) {
151 size -= parseFloat( $.curCSS( elem, "margin" + this, true) ) || 0;
154 return size;
157 $.fn[ "inner" + name ] = function( size ) {
158 if ( size === undefined ) {
159 return orig[ "inner" + name ].call( this );
162 return this.each(function() {
163 $( this ).css( type, reduce( this, size ) + "px" );
167 $.fn[ "outer" + name] = function( size, margin ) {
168 if ( typeof size !== "number" ) {
169 return orig[ "outer" + name ].call( this, size );
172 return this.each(function() {
173 $( this).css( type, reduce( this, size, true, margin ) + "px" );
178 // selectors
179 function focusable( element, isTabIndexNotNaN ) {
180 var nodeName = element.nodeName.toLowerCase();
181 if ( "area" === nodeName ) {
182 var map = element.parentNode,
183 mapName = map.name,
184 img;
185 if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
186 return false;
188 img = $( "img[usemap=#" + mapName + "]" )[0];
189 return !!img && visible( img );
191 return ( /input|select|textarea|button|object/.test( nodeName )
192 ? !element.disabled
193 : "a" == nodeName
194 ? element.href || isTabIndexNotNaN
195 : isTabIndexNotNaN)
196 // the element and all of its ancestors must be visible
197 && visible( element );
200 function visible( element ) {
201 return !$( element ).parents().andSelf().filter(function() {
202 return $.curCSS( this, "visibility" ) === "hidden" ||
203 $.expr.filters.hidden( this );
204 }).length;
207 $.extend( $.expr[ ":" ], {
208 data: function( elem, i, match ) {
209 return !!$.data( elem, match[ 3 ] );
212 focusable: function( element ) {
213 return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) );
216 tabbable: function( element ) {
217 var tabIndex = $.attr( element, "tabindex" ),
218 isTabIndexNaN = isNaN( tabIndex );
219 return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN );
223 // support
224 $(function() {
225 var body = document.body,
226 div = body.appendChild( div = document.createElement( "div" ) );
228 $.extend( div.style, {
229 minHeight: "100px",
230 height: "auto",
231 padding: 0,
232 borderWidth: 0
235 $.support.minHeight = div.offsetHeight === 100;
236 $.support.selectstart = "onselectstart" in div;
238 // set display to none to avoid a layout bug in IE
239 // http://dev.jquery.com/ticket/4014
240 body.removeChild( div ).style.display = "none";
247 // deprecated
248 $.extend( $.ui, {
249 // $.ui.plugin is deprecated. Use the proxy pattern instead.
250 plugin: {
251 add: function( module, option, set ) {
252 var proto = $.ui[ module ].prototype;
253 for ( var i in set ) {
254 proto.plugins[ i ] = proto.plugins[ i ] || [];
255 proto.plugins[ i ].push( [ option, set[ i ] ] );
258 call: function( instance, name, args ) {
259 var set = instance.plugins[ name ];
260 if ( !set || !instance.element[ 0 ].parentNode ) {
261 return;
264 for ( var i = 0; i < set.length; i++ ) {
265 if ( instance.options[ set[ i ][ 0 ] ] ) {
266 set[ i ][ 1 ].apply( instance.element, args );
272 // will be deprecated when we switch to jQuery 1.4 - use jQuery.contains()
273 contains: function( a, b ) {
274 return document.compareDocumentPosition ?
275 a.compareDocumentPosition( b ) & 16 :
276 a !== b && a.contains( b );
279 // only used by resizable
280 hasScroll: function( el, a ) {
282 //If overflow is hidden, the element might have extra content, but the user wants to hide it
283 if ( $( el ).css( "overflow" ) === "hidden") {
284 return false;
287 var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
288 has = false;
290 if ( el[ scroll ] > 0 ) {
291 return true;
294 // TODO: determine which cases actually cause this to happen
295 // if the element doesn't have the scroll set, see if it's possible to
296 // set the scroll
297 el[ scroll ] = 1;
298 has = ( el[ scroll ] > 0 );
299 el[ scroll ] = 0;
300 return has;
303 // these are odd functions, fix the API or move into individual plugins
304 isOverAxis: function( x, reference, size ) {
305 //Determines when x coordinate is over "b" element axis
306 return ( x > reference ) && ( x < ( reference + size ) );
308 isOver: function( y, x, top, left, height, width ) {
309 //Determines when x, y coordinates is over "b" element
310 return $.ui.isOverAxis( y, top, height ) && $.ui.isOverAxis( x, left, width );
314 })( jQuery );
316 * jQuery UI Widget 1.8.16
318 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
319 * Dual licensed under the MIT or GPL Version 2 licenses.
320 * http://jquery.org/license
322 * http://docs.jquery.com/UI/Widget
324 (function( $, undefined ) {
326 // jQuery 1.4+
327 if ( $.cleanData ) {
328 var _cleanData = $.cleanData;
329 $.cleanData = function( elems ) {
330 for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
331 try {
332 $( elem ).triggerHandler( "remove" );
333 // http://bugs.jquery.com/ticket/8235
334 } catch( e ) {}
336 _cleanData( elems );
338 } else {
339 var _remove = $.fn.remove;
340 $.fn.remove = function( selector, keepData ) {
341 return this.each(function() {
342 if ( !keepData ) {
343 if ( !selector || $.filter( selector, [ this ] ).length ) {
344 $( "*", this ).add( [ this ] ).each(function() {
345 try {
346 $( this ).triggerHandler( "remove" );
347 // http://bugs.jquery.com/ticket/8235
348 } catch( e ) {}
352 return _remove.call( $(this), selector, keepData );
357 $.widget = function( name, base, prototype ) {
358 var namespace = name.split( "." )[ 0 ],
359 fullName;
360 name = name.split( "." )[ 1 ];
361 fullName = namespace + "-" + name;
363 if ( !prototype ) {
364 prototype = base;
365 base = $.Widget;
368 // create selector for plugin
369 $.expr[ ":" ][ fullName ] = function( elem ) {
370 return !!$.data( elem, name );
373 $[ namespace ] = $[ namespace ] || {};
374 $[ namespace ][ name ] = function( options, element ) {
375 // allow instantiation without initializing for simple inheritance
376 if ( arguments.length ) {
377 this._createWidget( options, element );
381 var basePrototype = new base();
382 // we need to make the options hash a property directly on the new instance
383 // otherwise we'll modify the options hash on the prototype that we're
384 // inheriting from
385 // $.each( basePrototype, function( key, val ) {
386 // if ( $.isPlainObject(val) ) {
387 // basePrototype[ key ] = $.extend( {}, val );
388 // }
389 // });
390 basePrototype.options = $.extend( true, {}, basePrototype.options );
391 $[ namespace ][ name ].prototype = $.extend( true, basePrototype, {
392 namespace: namespace,
393 widgetName: name,
394 widgetEventPrefix: $[ namespace ][ name ].prototype.widgetEventPrefix || name,
395 widgetBaseClass: fullName
396 }, prototype );
398 $.widget.bridge( name, $[ namespace ][ name ] );
401 $.widget.bridge = function( name, object ) {
402 $.fn[ name ] = function( options ) {
403 var isMethodCall = typeof options === "string",
404 args = Array.prototype.slice.call( arguments, 1 ),
405 returnValue = this;
407 // allow multiple hashes to be passed on init
408 options = !isMethodCall && args.length ?
409 $.extend.apply( null, [ true, options ].concat(args) ) :
410 options;
412 // prevent calls to internal methods
413 if ( isMethodCall && options.charAt( 0 ) === "_" ) {
414 return returnValue;
417 if ( isMethodCall ) {
418 this.each(function() {
419 var instance = $.data( this, name ),
420 methodValue = instance && $.isFunction( instance[options] ) ?
421 instance[ options ].apply( instance, args ) :
422 instance;
423 // TODO: add this back in 1.9 and use $.error() (see #5972)
424 // if ( !instance ) {
425 // throw "cannot call methods on " + name + " prior to initialization; " +
426 // "attempted to call method '" + options + "'";
427 // }
428 // if ( !$.isFunction( instance[options] ) ) {
429 // throw "no such method '" + options + "' for " + name + " widget instance";
430 // }
431 // var methodValue = instance[ options ].apply( instance, args );
432 if ( methodValue !== instance && methodValue !== undefined ) {
433 returnValue = methodValue;
434 return false;
437 } else {
438 this.each(function() {
439 var instance = $.data( this, name );
440 if ( instance ) {
441 instance.option( options || {} )._init();
442 } else {
443 $.data( this, name, new object( options, this ) );
448 return returnValue;
452 $.Widget = function( options, element ) {
453 // allow instantiation without initializing for simple inheritance
454 if ( arguments.length ) {
455 this._createWidget( options, element );
459 $.Widget.prototype = {
460 widgetName: "widget",
461 widgetEventPrefix: "",
462 options: {
463 disabled: false
465 _createWidget: function( options, element ) {
466 // $.widget.bridge stores the plugin instance, but we do it anyway
467 // so that it's stored even before the _create function runs
468 $.data( element, this.widgetName, this );
469 this.element = $( element );
470 this.options = $.extend( true, {},
471 this.options,
472 this._getCreateOptions(),
473 options );
475 var self = this;
476 this.element.bind( "remove." + this.widgetName, function() {
477 self.destroy();
480 this._create();
481 this._trigger( "create" );
482 this._init();
484 _getCreateOptions: function() {
485 return $.metadata && $.metadata.get( this.element[0] )[ this.widgetName ];
487 _create: function() {},
488 _init: function() {},
490 destroy: function() {
491 this.element
492 .unbind( "." + this.widgetName )
493 .removeData( this.widgetName );
494 this.widget()
495 .unbind( "." + this.widgetName )
496 .removeAttr( "aria-disabled" )
497 .removeClass(
498 this.widgetBaseClass + "-disabled " +
499 "ui-state-disabled" );
502 widget: function() {
503 return this.element;
506 option: function( key, value ) {
507 var options = key;
509 if ( arguments.length === 0 ) {
510 // don't return a reference to the internal hash
511 return $.extend( {}, this.options );
514 if (typeof key === "string" ) {
515 if ( value === undefined ) {
516 return this.options[ key ];
518 options = {};
519 options[ key ] = value;
522 this._setOptions( options );
524 return this;
526 _setOptions: function( options ) {
527 var self = this;
528 $.each( options, function( key, value ) {
529 self._setOption( key, value );
532 return this;
534 _setOption: function( key, value ) {
535 this.options[ key ] = value;
537 if ( key === "disabled" ) {
538 this.widget()
539 [ value ? "addClass" : "removeClass"](
540 this.widgetBaseClass + "-disabled" + " " +
541 "ui-state-disabled" )
542 .attr( "aria-disabled", value );
545 return this;
548 enable: function() {
549 return this._setOption( "disabled", false );
551 disable: function() {
552 return this._setOption( "disabled", true );
555 _trigger: function( type, event, data ) {
556 var callback = this.options[ type ];
558 event = $.Event( event );
559 event.type = ( type === this.widgetEventPrefix ?
560 type :
561 this.widgetEventPrefix + type ).toLowerCase();
562 data = data || {};
564 // copy original event properties over to the new event
565 // this would happen if we could call $.event.fix instead of $.Event
566 // but we don't have a way to force an event to be fixed multiple times
567 if ( event.originalEvent ) {
568 for ( var i = $.event.props.length, prop; i; ) {
569 prop = $.event.props[ --i ];
570 event[ prop ] = event.originalEvent[ prop ];
574 this.element.trigger( event, data );
576 return !( $.isFunction(callback) &&
577 callback.call( this.element[0], event, data ) === false ||
578 event.isDefaultPrevented() );
582 })( jQuery );
584 * jQuery UI Mouse 1.8.16
586 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
587 * Dual licensed under the MIT or GPL Version 2 licenses.
588 * http://jquery.org/license
590 * http://docs.jquery.com/UI/Mouse
592 * Depends:
593 * jquery.ui.widget.js
595 (function( $, undefined ) {
597 var mouseHandled = false;
598 $( document ).mouseup( function( e ) {
599 mouseHandled = false;
602 $.widget("ui.mouse", {
603 options: {
604 cancel: ':input,option',
605 distance: 1,
606 delay: 0
608 _mouseInit: function() {
609 var self = this;
611 this.element
612 .bind('mousedown.'+this.widgetName, function(event) {
613 return self._mouseDown(event);
615 .bind('click.'+this.widgetName, function(event) {
616 if (true === $.data(event.target, self.widgetName + '.preventClickEvent')) {
617 $.removeData(event.target, self.widgetName + '.preventClickEvent');
618 event.stopImmediatePropagation();
619 return false;
623 this.started = false;
626 // TODO: make sure destroying one instance of mouse doesn't mess with
627 // other instances of mouse
628 _mouseDestroy: function() {
629 this.element.unbind('.'+this.widgetName);
632 _mouseDown: function(event) {
633 // don't let more than one widget handle mouseStart
634 if( mouseHandled ) { return };
636 // we may have missed mouseup (out of window)
637 (this._mouseStarted && this._mouseUp(event));
639 this._mouseDownEvent = event;
641 var self = this,
642 btnIsLeft = (event.which == 1),
643 // event.target.nodeName works around a bug in IE 8 with
644 // disabled inputs (#7620)
645 elIsCancel = (typeof this.options.cancel == "string" && event.target.nodeName ? $(event.target).closest(this.options.cancel).length : false);
646 if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
647 return true;
650 this.mouseDelayMet = !this.options.delay;
651 if (!this.mouseDelayMet) {
652 this._mouseDelayTimer = setTimeout(function() {
653 self.mouseDelayMet = true;
654 }, this.options.delay);
657 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
658 this._mouseStarted = (this._mouseStart(event) !== false);
659 if (!this._mouseStarted) {
660 event.preventDefault();
661 return true;
665 // Click event may never have fired (Gecko & Opera)
666 if (true === $.data(event.target, this.widgetName + '.preventClickEvent')) {
667 $.removeData(event.target, this.widgetName + '.preventClickEvent');
670 // these delegates are required to keep context
671 this._mouseMoveDelegate = function(event) {
672 return self._mouseMove(event);
674 this._mouseUpDelegate = function(event) {
675 return self._mouseUp(event);
677 $(document)
678 .bind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
679 .bind('mouseup.'+this.widgetName, this._mouseUpDelegate);
681 event.preventDefault();
683 mouseHandled = true;
684 return true;
687 _mouseMove: function(event) {
688 // IE mouseup check - mouseup happened when mouse was out of window
689 if ($.browser.msie && !(document.documentMode >= 9) && !event.button) {
690 return this._mouseUp(event);
693 if (this._mouseStarted) {
694 this._mouseDrag(event);
695 return event.preventDefault();
698 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
699 this._mouseStarted =
700 (this._mouseStart(this._mouseDownEvent, event) !== false);
701 (this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
704 return !this._mouseStarted;
707 _mouseUp: function(event) {
708 $(document)
709 .unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
710 .unbind('mouseup.'+this.widgetName, this._mouseUpDelegate);
712 if (this._mouseStarted) {
713 this._mouseStarted = false;
715 if (event.target == this._mouseDownEvent.target) {
716 $.data(event.target, this.widgetName + '.preventClickEvent', true);
719 this._mouseStop(event);
722 return false;
725 _mouseDistanceMet: function(event) {
726 return (Math.max(
727 Math.abs(this._mouseDownEvent.pageX - event.pageX),
728 Math.abs(this._mouseDownEvent.pageY - event.pageY)
729 ) >= this.options.distance
733 _mouseDelayMet: function(event) {
734 return this.mouseDelayMet;
737 // These are placeholder methods, to be overriden by extending plugin
738 _mouseStart: function(event) {},
739 _mouseDrag: function(event) {},
740 _mouseStop: function(event) {},
741 _mouseCapture: function(event) { return true; }
744 })(jQuery);
746 * jQuery UI Position 1.8.16
748 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
749 * Dual licensed under the MIT or GPL Version 2 licenses.
750 * http://jquery.org/license
752 * http://docs.jquery.com/UI/Position
754 (function( $, undefined ) {
756 $.ui = $.ui || {};
758 var horizontalPositions = /left|center|right/,
759 verticalPositions = /top|center|bottom/,
760 center = "center",
761 _position = $.fn.position,
762 _offset = $.fn.offset;
764 $.fn.position = function( options ) {
765 if ( !options || !options.of ) {
766 return _position.apply( this, arguments );
769 // make a copy, we don't want to modify arguments
770 options = $.extend( {}, options );
772 var target = $( options.of ),
773 targetElem = target[0],
774 collision = ( options.collision || "flip" ).split( " " ),
775 offset = options.offset ? options.offset.split( " " ) : [ 0, 0 ],
776 targetWidth,
777 targetHeight,
778 basePosition;
780 if ( targetElem.nodeType === 9 ) {
781 targetWidth = target.width();
782 targetHeight = target.height();
783 basePosition = { top: 0, left: 0 };
784 // TODO: use $.isWindow() in 1.9
785 } else if ( targetElem.setTimeout ) {
786 targetWidth = target.width();
787 targetHeight = target.height();
788 basePosition = { top: target.scrollTop(), left: target.scrollLeft() };
789 } else if ( targetElem.preventDefault ) {
790 // force left top to allow flipping
791 options.at = "left top";
792 targetWidth = targetHeight = 0;
793 basePosition = { top: options.of.pageY, left: options.of.pageX };
794 } else {
795 targetWidth = target.outerWidth();
796 targetHeight = target.outerHeight();
797 basePosition = target.offset();
800 // force my and at to have valid horizontal and veritcal positions
801 // if a value is missing or invalid, it will be converted to center
802 $.each( [ "my", "at" ], function() {
803 var pos = ( options[this] || "" ).split( " " );
804 if ( pos.length === 1) {
805 pos = horizontalPositions.test( pos[0] ) ?
806 pos.concat( [center] ) :
807 verticalPositions.test( pos[0] ) ?
808 [ center ].concat( pos ) :
809 [ center, center ];
811 pos[ 0 ] = horizontalPositions.test( pos[0] ) ? pos[ 0 ] : center;
812 pos[ 1 ] = verticalPositions.test( pos[1] ) ? pos[ 1 ] : center;
813 options[ this ] = pos;
816 // normalize collision option
817 if ( collision.length === 1 ) {
818 collision[ 1 ] = collision[ 0 ];
821 // normalize offset option
822 offset[ 0 ] = parseInt( offset[0], 10 ) || 0;
823 if ( offset.length === 1 ) {
824 offset[ 1 ] = offset[ 0 ];
826 offset[ 1 ] = parseInt( offset[1], 10 ) || 0;
828 if ( options.at[0] === "right" ) {
829 basePosition.left += targetWidth;
830 } else if ( options.at[0] === center ) {
831 basePosition.left += targetWidth / 2;
834 if ( options.at[1] === "bottom" ) {
835 basePosition.top += targetHeight;
836 } else if ( options.at[1] === center ) {
837 basePosition.top += targetHeight / 2;
840 basePosition.left += offset[ 0 ];
841 basePosition.top += offset[ 1 ];
843 return this.each(function() {
844 var elem = $( this ),
845 elemWidth = elem.outerWidth(),
846 elemHeight = elem.outerHeight(),
847 marginLeft = parseInt( $.curCSS( this, "marginLeft", true ) ) || 0,
848 marginTop = parseInt( $.curCSS( this, "marginTop", true ) ) || 0,
849 collisionWidth = elemWidth + marginLeft +
850 ( parseInt( $.curCSS( this, "marginRight", true ) ) || 0 ),
851 collisionHeight = elemHeight + marginTop +
852 ( parseInt( $.curCSS( this, "marginBottom", true ) ) || 0 ),
853 position = $.extend( {}, basePosition ),
854 collisionPosition;
856 if ( options.my[0] === "right" ) {
857 position.left -= elemWidth;
858 } else if ( options.my[0] === center ) {
859 position.left -= elemWidth / 2;
862 if ( options.my[1] === "bottom" ) {
863 position.top -= elemHeight;
864 } else if ( options.my[1] === center ) {
865 position.top -= elemHeight / 2;
868 // prevent fractions (see #5280)
869 position.left = Math.round( position.left );
870 position.top = Math.round( position.top );
872 collisionPosition = {
873 left: position.left - marginLeft,
874 top: position.top - marginTop
877 $.each( [ "left", "top" ], function( i, dir ) {
878 if ( $.ui.position[ collision[i] ] ) {
879 $.ui.position[ collision[i] ][ dir ]( position, {
880 targetWidth: targetWidth,
881 targetHeight: targetHeight,
882 elemWidth: elemWidth,
883 elemHeight: elemHeight,
884 collisionPosition: collisionPosition,
885 collisionWidth: collisionWidth,
886 collisionHeight: collisionHeight,
887 offset: offset,
888 my: options.my,
889 at: options.at
894 if ( $.fn.bgiframe ) {
895 elem.bgiframe();
897 elem.offset( $.extend( position, { using: options.using } ) );
901 $.ui.position = {
902 fit: {
903 left: function( position, data ) {
904 var win = $( window ),
905 over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft();
906 position.left = over > 0 ? position.left - over : Math.max( position.left - data.collisionPosition.left, position.left );
908 top: function( position, data ) {
909 var win = $( window ),
910 over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop();
911 position.top = over > 0 ? position.top - over : Math.max( position.top - data.collisionPosition.top, position.top );
915 flip: {
916 left: function( position, data ) {
917 if ( data.at[0] === center ) {
918 return;
920 var win = $( window ),
921 over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft(),
922 myOffset = data.my[ 0 ] === "left" ?
923 -data.elemWidth :
924 data.my[ 0 ] === "right" ?
925 data.elemWidth :
927 atOffset = data.at[ 0 ] === "left" ?
928 data.targetWidth :
929 -data.targetWidth,
930 offset = -2 * data.offset[ 0 ];
931 position.left += data.collisionPosition.left < 0 ?
932 myOffset + atOffset + offset :
933 over > 0 ?
934 myOffset + atOffset + offset :
937 top: function( position, data ) {
938 if ( data.at[1] === center ) {
939 return;
941 var win = $( window ),
942 over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop(),
943 myOffset = data.my[ 1 ] === "top" ?
944 -data.elemHeight :
945 data.my[ 1 ] === "bottom" ?
946 data.elemHeight :
948 atOffset = data.at[ 1 ] === "top" ?
949 data.targetHeight :
950 -data.targetHeight,
951 offset = -2 * data.offset[ 1 ];
952 position.top += data.collisionPosition.top < 0 ?
953 myOffset + atOffset + offset :
954 over > 0 ?
955 myOffset + atOffset + offset :
961 // offset setter from jQuery 1.4
962 if ( !$.offset.setOffset ) {
963 $.offset.setOffset = function( elem, options ) {
964 // set position first, in-case top/left are set even on static elem
965 if ( /static/.test( $.curCSS( elem, "position" ) ) ) {
966 elem.style.position = "relative";
968 var curElem = $( elem ),
969 curOffset = curElem.offset(),
970 curTop = parseInt( $.curCSS( elem, "top", true ), 10 ) || 0,
971 curLeft = parseInt( $.curCSS( elem, "left", true ), 10) || 0,
972 props = {
973 top: (options.top - curOffset.top) + curTop,
974 left: (options.left - curOffset.left) + curLeft
977 if ( 'using' in options ) {
978 options.using.call( elem, props );
979 } else {
980 curElem.css( props );
984 $.fn.offset = function( options ) {
985 var elem = this[ 0 ];
986 if ( !elem || !elem.ownerDocument ) { return null; }
987 if ( options ) {
988 return this.each(function() {
989 $.offset.setOffset( this, options );
992 return _offset.call( this );
996 }( jQuery ));
998 * jQuery UI Draggable 1.8.16
1000 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
1001 * Dual licensed under the MIT or GPL Version 2 licenses.
1002 * http://jquery.org/license
1004 * http://docs.jquery.com/UI/Draggables
1006 * Depends:
1007 * jquery.ui.core.js
1008 * jquery.ui.mouse.js
1009 * jquery.ui.widget.js
1011 (function( $, undefined ) {
1013 $.widget("ui.draggable", $.ui.mouse, {
1014 widgetEventPrefix: "drag",
1015 options: {
1016 addClasses: true,
1017 appendTo: "parent",
1018 axis: false,
1019 connectToSortable: false,
1020 containment: false,
1021 cursor: "auto",
1022 cursorAt: false,
1023 grid: false,
1024 handle: false,
1025 helper: "original",
1026 iframeFix: false,
1027 opacity: false,
1028 refreshPositions: false,
1029 revert: false,
1030 revertDuration: 500,
1031 scope: "default",
1032 scroll: true,
1033 scrollSensitivity: 20,
1034 scrollSpeed: 20,
1035 snap: false,
1036 snapMode: "both",
1037 snapTolerance: 20,
1038 stack: false,
1039 zIndex: false
1041 _create: function() {
1043 if (this.options.helper == 'original' && !(/^(?:r|a|f)/).test(this.element.css("position")))
1044 this.element[0].style.position = 'relative';
1046 (this.options.addClasses && this.element.addClass("ui-draggable"));
1047 (this.options.disabled && this.element.addClass("ui-draggable-disabled"));
1049 this._mouseInit();
1053 destroy: function() {
1054 if(!this.element.data('draggable')) return;
1055 this.element
1056 .removeData("draggable")
1057 .unbind(".draggable")
1058 .removeClass("ui-draggable"
1059 + " ui-draggable-dragging"
1060 + " ui-draggable-disabled");
1061 this._mouseDestroy();
1063 return this;
1066 _mouseCapture: function(event) {
1068 var o = this.options;
1070 // among others, prevent a drag on a resizable-handle
1071 if (this.helper || o.disabled || $(event.target).is('.ui-resizable-handle'))
1072 return false;
1074 //Quit if we're not on a valid handle
1075 this.handle = this._getHandle(event);
1076 if (!this.handle)
1077 return false;
1079 if ( o.iframeFix ) {
1080 $(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() {
1081 $('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>')
1082 .css({
1083 width: this.offsetWidth+"px", height: this.offsetHeight+"px",
1084 position: "absolute", opacity: "0.001", zIndex: 1000
1086 .css($(this).offset())
1087 .appendTo("body");
1091 return true;
1095 _mouseStart: function(event) {
1097 var o = this.options;
1099 //Create and append the visible helper
1100 this.helper = this._createHelper(event);
1102 //Cache the helper size
1103 this._cacheHelperProportions();
1105 //If ddmanager is used for droppables, set the global draggable
1106 if($.ui.ddmanager)
1107 $.ui.ddmanager.current = this;
1110 * - Position generation -
1111 * This block generates everything position related - it's the core of draggables.
1114 //Cache the margins of the original element
1115 this._cacheMargins();
1117 //Store the helper's css position
1118 this.cssPosition = this.helper.css("position");
1119 this.scrollParent = this.helper.scrollParent();
1121 //The element's absolute position on the page minus margins
1122 this.offset = this.positionAbs = this.element.offset();
1123 this.offset = {
1124 top: this.offset.top - this.margins.top,
1125 left: this.offset.left - this.margins.left
1128 $.extend(this.offset, {
1129 click: { //Where the click happened, relative to the element
1130 left: event.pageX - this.offset.left,
1131 top: event.pageY - this.offset.top
1133 parent: this._getParentOffset(),
1134 relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
1137 //Generate the original position
1138 this.originalPosition = this.position = this._generatePosition(event);
1139 this.originalPageX = event.pageX;
1140 this.originalPageY = event.pageY;
1142 //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
1143 (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
1145 //Set a containment if given in the options
1146 if(o.containment)
1147 this._setContainment();
1149 //Trigger event + callbacks
1150 if(this._trigger("start", event) === false) {
1151 this._clear();
1152 return false;
1155 //Recache the helper size
1156 this._cacheHelperProportions();
1158 //Prepare the droppable offsets
1159 if ($.ui.ddmanager && !o.dropBehaviour)
1160 $.ui.ddmanager.prepareOffsets(this, event);
1162 this.helper.addClass("ui-draggable-dragging");
1163 this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position
1165 //If the ddmanager is used for droppables, inform the manager that dragging has started (see #5003)
1166 if ( $.ui.ddmanager ) $.ui.ddmanager.dragStart(this, event);
1168 return true;
1171 _mouseDrag: function(event, noPropagation) {
1173 //Compute the helpers position
1174 this.position = this._generatePosition(event);
1175 this.positionAbs = this._convertPositionTo("absolute");
1177 //Call plugins and callbacks and use the resulting position if something is returned
1178 if (!noPropagation) {
1179 var ui = this._uiHash();
1180 if(this._trigger('drag', event, ui) === false) {
1181 this._mouseUp({});
1182 return false;
1184 this.position = ui.position;
1187 if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
1188 if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
1189 if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
1191 return false;
1194 _mouseStop: function(event) {
1196 //If we are using droppables, inform the manager about the drop
1197 var dropped = false;
1198 if ($.ui.ddmanager && !this.options.dropBehaviour)
1199 dropped = $.ui.ddmanager.drop(this, event);
1201 //if a drop comes from outside (a sortable)
1202 if(this.dropped) {
1203 dropped = this.dropped;
1204 this.dropped = false;
1207 //if the original element is removed, don't bother to continue if helper is set to "original"
1208 if((!this.element[0] || !this.element[0].parentNode) && this.options.helper == "original")
1209 return false;
1211 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))) {
1212 var self = this;
1213 $(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() {
1214 if(self._trigger("stop", event) !== false) {
1215 self._clear();
1218 } else {
1219 if(this._trigger("stop", event) !== false) {
1220 this._clear();
1224 return false;
1227 _mouseUp: function(event) {
1228 if (this.options.iframeFix === true) {
1229 $("div.ui-draggable-iframeFix").each(function() {
1230 this.parentNode.removeChild(this);
1231 }); //Remove frame helpers
1234 //If the ddmanager is used for droppables, inform the manager that dragging has stopped (see #5003)
1235 if( $.ui.ddmanager ) $.ui.ddmanager.dragStop(this, event);
1237 return $.ui.mouse.prototype._mouseUp.call(this, event);
1240 cancel: function() {
1242 if(this.helper.is(".ui-draggable-dragging")) {
1243 this._mouseUp({});
1244 } else {
1245 this._clear();
1248 return this;
1252 _getHandle: function(event) {
1254 var handle = !this.options.handle || !$(this.options.handle, this.element).length ? true : false;
1255 $(this.options.handle, this.element)
1256 .find("*")
1257 .andSelf()
1258 .each(function() {
1259 if(this == event.target) handle = true;
1262 return handle;
1266 _createHelper: function(event) {
1268 var o = this.options;
1269 var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper == 'clone' ? this.element.clone().removeAttr('id') : this.element);
1271 if(!helper.parents('body').length)
1272 helper.appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo));
1274 if(helper[0] != this.element[0] && !(/(fixed|absolute)/).test(helper.css("position")))
1275 helper.css("position", "absolute");
1277 return helper;
1281 _adjustOffsetFromHelper: function(obj) {
1282 if (typeof obj == 'string') {
1283 obj = obj.split(' ');
1285 if ($.isArray(obj)) {
1286 obj = {left: +obj[0], top: +obj[1] || 0};
1288 if ('left' in obj) {
1289 this.offset.click.left = obj.left + this.margins.left;
1291 if ('right' in obj) {
1292 this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
1294 if ('top' in obj) {
1295 this.offset.click.top = obj.top + this.margins.top;
1297 if ('bottom' in obj) {
1298 this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
1302 _getParentOffset: function() {
1304 //Get the offsetParent and cache its position
1305 this.offsetParent = this.helper.offsetParent();
1306 var po = this.offsetParent.offset();
1308 // This is a special case where we need to modify a offset calculated on start, since the following happened:
1309 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
1310 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
1311 // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
1312 if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) {
1313 po.left += this.scrollParent.scrollLeft();
1314 po.top += this.scrollParent.scrollTop();
1317 if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
1318 || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix
1319 po = { top: 0, left: 0 };
1321 return {
1322 top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
1323 left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
1328 _getRelativeOffset: function() {
1330 if(this.cssPosition == "relative") {
1331 var p = this.element.position();
1332 return {
1333 top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
1334 left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
1336 } else {
1337 return { top: 0, left: 0 };
1342 _cacheMargins: function() {
1343 this.margins = {
1344 left: (parseInt(this.element.css("marginLeft"),10) || 0),
1345 top: (parseInt(this.element.css("marginTop"),10) || 0),
1346 right: (parseInt(this.element.css("marginRight"),10) || 0),
1347 bottom: (parseInt(this.element.css("marginBottom"),10) || 0)
1351 _cacheHelperProportions: function() {
1352 this.helperProportions = {
1353 width: this.helper.outerWidth(),
1354 height: this.helper.outerHeight()
1358 _setContainment: function() {
1360 var o = this.options;
1361 if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
1362 if(o.containment == 'document' || o.containment == 'window') this.containment = [
1363 o.containment == 'document' ? 0 : $(window).scrollLeft() - this.offset.relative.left - this.offset.parent.left,
1364 o.containment == 'document' ? 0 : $(window).scrollTop() - this.offset.relative.top - this.offset.parent.top,
1365 (o.containment == 'document' ? 0 : $(window).scrollLeft()) + $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
1366 (o.containment == 'document' ? 0 : $(window).scrollTop()) + ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
1369 if(!(/^(document|window|parent)$/).test(o.containment) && o.containment.constructor != Array) {
1370 var c = $(o.containment);
1371 var ce = c[0]; if(!ce) return;
1372 var co = c.offset();
1373 var over = ($(ce).css("overflow") != 'hidden');
1375 this.containment = [
1376 (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0),
1377 (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0),
1378 (over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left - this.margins.right,
1379 (over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top - this.margins.bottom
1381 this.relative_container = c;
1383 } else if(o.containment.constructor == Array) {
1384 this.containment = o.containment;
1389 _convertPositionTo: function(d, pos) {
1391 if(!pos) pos = this.position;
1392 var mod = d == "absolute" ? 1 : -1;
1393 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);
1395 return {
1396 top: (
1397 pos.top // The absolute mouse position
1398 + this.offset.relative.top * mod // Only for relative positioned nodes: Relative offset from element to offset parent
1399 + this.offset.parent.top * mod // The offsetParent's offset without borders (offset + border)
1400 - ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
1402 left: (
1403 pos.left // The absolute mouse position
1404 + this.offset.relative.left * mod // Only for relative positioned nodes: Relative offset from element to offset parent
1405 + this.offset.parent.left * mod // The offsetParent's offset without borders (offset + border)
1406 - ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
1412 _generatePosition: function(event) {
1414 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);
1415 var pageX = event.pageX;
1416 var pageY = event.pageY;
1419 * - Position constraining -
1420 * Constrain the position to a mix of grid, containment.
1423 if(this.originalPosition) { //If we are not dragging yet, we won't check for options
1424 var containment;
1425 if(this.containment) {
1426 if (this.relative_container){
1427 var co = this.relative_container.offset();
1428 containment = [ this.containment[0] + co.left,
1429 this.containment[1] + co.top,
1430 this.containment[2] + co.left,
1431 this.containment[3] + co.top ];
1433 else {
1434 containment = this.containment;
1437 if(event.pageX - this.offset.click.left < containment[0]) pageX = containment[0] + this.offset.click.left;
1438 if(event.pageY - this.offset.click.top < containment[1]) pageY = containment[1] + this.offset.click.top;
1439 if(event.pageX - this.offset.click.left > containment[2]) pageX = containment[2] + this.offset.click.left;
1440 if(event.pageY - this.offset.click.top > containment[3]) pageY = containment[3] + this.offset.click.top;
1443 if(o.grid) {
1444 //Check for grid elements set to 0 to prevent divide by 0 error causing invalid argument errors in IE (see ticket #6950)
1445 var top = o.grid[1] ? this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1] : this.originalPageY;
1446 pageY = containment ? (!(top - this.offset.click.top < containment[1] || top - this.offset.click.top > containment[3]) ? top : (!(top - this.offset.click.top < containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;
1448 var left = o.grid[0] ? this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0] : this.originalPageX;
1449 pageX = containment ? (!(left - this.offset.click.left < containment[0] || left - this.offset.click.left > containment[2]) ? left : (!(left - this.offset.click.left < containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
1454 return {
1455 top: (
1456 pageY // The absolute mouse position
1457 - this.offset.click.top // Click offset (relative to the element)
1458 - this.offset.relative.top // Only for relative positioned nodes: Relative offset from element to offset parent
1459 - this.offset.parent.top // The offsetParent's offset without borders (offset + border)
1460 + ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
1462 left: (
1463 pageX // The absolute mouse position
1464 - this.offset.click.left // Click offset (relative to the element)
1465 - this.offset.relative.left // Only for relative positioned nodes: Relative offset from element to offset parent
1466 - this.offset.parent.left // The offsetParent's offset without borders (offset + border)
1467 + ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
1473 _clear: function() {
1474 this.helper.removeClass("ui-draggable-dragging");
1475 if(this.helper[0] != this.element[0] && !this.cancelHelperRemoval) this.helper.remove();
1476 //if($.ui.ddmanager) $.ui.ddmanager.current = null;
1477 this.helper = null;
1478 this.cancelHelperRemoval = false;
1481 // From now on bulk stuff - mainly helpers
1483 _trigger: function(type, event, ui) {
1484 ui = ui || this._uiHash();
1485 $.ui.plugin.call(this, type, [event, ui]);
1486 if(type == "drag") this.positionAbs = this._convertPositionTo("absolute"); //The absolute position has to be recalculated after plugins
1487 return $.Widget.prototype._trigger.call(this, type, event, ui);
1490 plugins: {},
1492 _uiHash: function(event) {
1493 return {
1494 helper: this.helper,
1495 position: this.position,
1496 originalPosition: this.originalPosition,
1497 offset: this.positionAbs
1503 $.extend($.ui.draggable, {
1504 version: "1.8.16"
1507 $.ui.plugin.add("draggable", "connectToSortable", {
1508 start: function(event, ui) {
1510 var inst = $(this).data("draggable"), o = inst.options,
1511 uiSortable = $.extend({}, ui, { item: inst.element });
1512 inst.sortables = [];
1513 $(o.connectToSortable).each(function() {
1514 var sortable = $.data(this, 'sortable');
1515 if (sortable && !sortable.options.disabled) {
1516 inst.sortables.push({
1517 instance: sortable,
1518 shouldRevert: sortable.options.revert
1520 sortable.refreshPositions(); // Call the sortable's refreshPositions at drag start to refresh the containerCache since the sortable container cache is used in drag and needs to be up to date (this will ensure it's initialised as well as being kept in step with any changes that might have happened on the page).
1521 sortable._trigger("activate", event, uiSortable);
1526 stop: function(event, ui) {
1528 //If we are still over the sortable, we fake the stop event of the sortable, but also remove helper
1529 var inst = $(this).data("draggable"),
1530 uiSortable = $.extend({}, ui, { item: inst.element });
1532 $.each(inst.sortables, function() {
1533 if(this.instance.isOver) {
1535 this.instance.isOver = 0;
1537 inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance
1538 this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work)
1540 //The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: 'valid/invalid'
1541 if(this.shouldRevert) this.instance.options.revert = true;
1543 //Trigger the stop of the sortable
1544 this.instance._mouseStop(event);
1546 this.instance.options.helper = this.instance.options._helper;
1548 //If the helper has been the original item, restore properties in the sortable
1549 if(inst.options.helper == 'original')
1550 this.instance.currentItem.css({ top: 'auto', left: 'auto' });
1552 } else {
1553 this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance
1554 this.instance._trigger("deactivate", event, uiSortable);
1560 drag: function(event, ui) {
1562 var inst = $(this).data("draggable"), self = this;
1564 var checkPos = function(o) {
1565 var dyClick = this.offset.click.top, dxClick = this.offset.click.left;
1566 var helperTop = this.positionAbs.top, helperLeft = this.positionAbs.left;
1567 var itemHeight = o.height, itemWidth = o.width;
1568 var itemTop = o.top, itemLeft = o.left;
1570 return $.ui.isOver(helperTop + dyClick, helperLeft + dxClick, itemTop, itemLeft, itemHeight, itemWidth);
1573 $.each(inst.sortables, function(i) {
1575 //Copy over some variables to allow calling the sortable's native _intersectsWith
1576 this.instance.positionAbs = inst.positionAbs;
1577 this.instance.helperProportions = inst.helperProportions;
1578 this.instance.offset.click = inst.offset.click;
1580 if(this.instance._intersectsWith(this.instance.containerCache)) {
1582 //If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once
1583 if(!this.instance.isOver) {
1585 this.instance.isOver = 1;
1586 //Now we fake the start of dragging for the sortable instance,
1587 //by cloning the list group item, appending it to the sortable and using it as inst.currentItem
1588 //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)
1589 this.instance.currentItem = $(self).clone().removeAttr('id').appendTo(this.instance.element).data("sortable-item", true);
1590 this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it
1591 this.instance.options.helper = function() { return ui.helper[0]; };
1593 event.target = this.instance.currentItem[0];
1594 this.instance._mouseCapture(event, true);
1595 this.instance._mouseStart(event, true, true);
1597 //Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes
1598 this.instance.offset.click.top = inst.offset.click.top;
1599 this.instance.offset.click.left = inst.offset.click.left;
1600 this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left;
1601 this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top;
1603 inst._trigger("toSortable", event);
1604 inst.dropped = this.instance.element; //draggable revert needs that
1605 //hack so receive/update callbacks work (mostly)
1606 inst.currentItem = inst.element;
1607 this.instance.fromOutside = inst;
1611 //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
1612 if(this.instance.currentItem) this.instance._mouseDrag(event);
1614 } else {
1616 //If it doesn't intersect with the sortable, and it intersected before,
1617 //we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval
1618 if(this.instance.isOver) {
1620 this.instance.isOver = 0;
1621 this.instance.cancelHelperRemoval = true;
1623 //Prevent reverting on this forced stop
1624 this.instance.options.revert = false;
1626 // The out event needs to be triggered independently
1627 this.instance._trigger('out', event, this.instance._uiHash(this.instance));
1629 this.instance._mouseStop(event, true);
1630 this.instance.options.helper = this.instance.options._helper;
1632 //Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size
1633 this.instance.currentItem.remove();
1634 if(this.instance.placeholder) this.instance.placeholder.remove();
1636 inst._trigger("fromSortable", event);
1637 inst.dropped = false; //draggable revert needs that
1647 $.ui.plugin.add("draggable", "cursor", {
1648 start: function(event, ui) {
1649 var t = $('body'), o = $(this).data('draggable').options;
1650 if (t.css("cursor")) o._cursor = t.css("cursor");
1651 t.css("cursor", o.cursor);
1653 stop: function(event, ui) {
1654 var o = $(this).data('draggable').options;
1655 if (o._cursor) $('body').css("cursor", o._cursor);
1659 $.ui.plugin.add("draggable", "opacity", {
1660 start: function(event, ui) {
1661 var t = $(ui.helper), o = $(this).data('draggable').options;
1662 if(t.css("opacity")) o._opacity = t.css("opacity");
1663 t.css('opacity', o.opacity);
1665 stop: function(event, ui) {
1666 var o = $(this).data('draggable').options;
1667 if(o._opacity) $(ui.helper).css('opacity', o._opacity);
1671 $.ui.plugin.add("draggable", "scroll", {
1672 start: function(event, ui) {
1673 var i = $(this).data("draggable");
1674 if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') i.overflowOffset = i.scrollParent.offset();
1676 drag: function(event, ui) {
1678 var i = $(this).data("draggable"), o = i.options, scrolled = false;
1680 if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') {
1682 if(!o.axis || o.axis != 'x') {
1683 if((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
1684 i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed;
1685 else if(event.pageY - i.overflowOffset.top < o.scrollSensitivity)
1686 i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed;
1689 if(!o.axis || o.axis != 'y') {
1690 if((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
1691 i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed;
1692 else if(event.pageX - i.overflowOffset.left < o.scrollSensitivity)
1693 i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed;
1696 } else {
1698 if(!o.axis || o.axis != 'x') {
1699 if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
1700 scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
1701 else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
1702 scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
1705 if(!o.axis || o.axis != 'y') {
1706 if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
1707 scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
1708 else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
1709 scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
1714 if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
1715 $.ui.ddmanager.prepareOffsets(i, event);
1720 $.ui.plugin.add("draggable", "snap", {
1721 start: function(event, ui) {
1723 var i = $(this).data("draggable"), o = i.options;
1724 i.snapElements = [];
1726 $(o.snap.constructor != String ? ( o.snap.items || ':data(draggable)' ) : o.snap).each(function() {
1727 var $t = $(this); var $o = $t.offset();
1728 if(this != i.element[0]) i.snapElements.push({
1729 item: this,
1730 width: $t.outerWidth(), height: $t.outerHeight(),
1731 top: $o.top, left: $o.left
1736 drag: function(event, ui) {
1738 var inst = $(this).data("draggable"), o = inst.options;
1739 var d = o.snapTolerance;
1741 var x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
1742 y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
1744 for (var i = inst.snapElements.length - 1; i >= 0; i--){
1746 var l = inst.snapElements[i].left, r = l + inst.snapElements[i].width,
1747 t = inst.snapElements[i].top, b = t + inst.snapElements[i].height;
1749 //Yes, I know, this is insane ;)
1750 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))) {
1751 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 })));
1752 inst.snapElements[i].snapping = false;
1753 continue;
1756 if(o.snapMode != 'inner') {
1757 var ts = Math.abs(t - y2) <= d;
1758 var bs = Math.abs(b - y1) <= d;
1759 var ls = Math.abs(l - x2) <= d;
1760 var rs = Math.abs(r - x1) <= d;
1761 if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
1762 if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top;
1763 if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left;
1764 if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left;
1767 var first = (ts || bs || ls || rs);
1769 if(o.snapMode != 'outer') {
1770 var ts = Math.abs(t - y1) <= d;
1771 var bs = Math.abs(b - y2) <= d;
1772 var ls = Math.abs(l - x1) <= d;
1773 var rs = Math.abs(r - x2) <= d;
1774 if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top;
1775 if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
1776 if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left;
1777 if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left;
1780 if(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first))
1781 (inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
1782 inst.snapElements[i].snapping = (ts || bs || ls || rs || first);
1789 $.ui.plugin.add("draggable", "stack", {
1790 start: function(event, ui) {
1792 var o = $(this).data("draggable").options;
1794 var group = $.makeArray($(o.stack)).sort(function(a,b) {
1795 return (parseInt($(a).css("zIndex"),10) || 0) - (parseInt($(b).css("zIndex"),10) || 0);
1797 if (!group.length) { return; }
1799 var min = parseInt(group[0].style.zIndex) || 0;
1800 $(group).each(function(i) {
1801 this.style.zIndex = min + i;
1804 this[0].style.zIndex = min + group.length;
1809 $.ui.plugin.add("draggable", "zIndex", {
1810 start: function(event, ui) {
1811 var t = $(ui.helper), o = $(this).data("draggable").options;
1812 if(t.css("zIndex")) o._zIndex = t.css("zIndex");
1813 t.css('zIndex', o.zIndex);
1815 stop: function(event, ui) {
1816 var o = $(this).data("draggable").options;
1817 if(o._zIndex) $(ui.helper).css('zIndex', o._zIndex);
1821 })(jQuery);
1823 * jQuery UI Droppable 1.8.16
1825 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
1826 * Dual licensed under the MIT or GPL Version 2 licenses.
1827 * http://jquery.org/license
1829 * http://docs.jquery.com/UI/Droppables
1831 * Depends:
1832 * jquery.ui.core.js
1833 * jquery.ui.widget.js
1834 * jquery.ui.mouse.js
1835 * jquery.ui.draggable.js
1837 (function( $, undefined ) {
1839 $.widget("ui.droppable", {
1840 widgetEventPrefix: "drop",
1841 options: {
1842 accept: '*',
1843 activeClass: false,
1844 addClasses: true,
1845 greedy: false,
1846 hoverClass: false,
1847 scope: 'default',
1848 tolerance: 'intersect'
1850 _create: function() {
1852 var o = this.options, accept = o.accept;
1853 this.isover = 0; this.isout = 1;
1855 this.accept = $.isFunction(accept) ? accept : function(d) {
1856 return d.is(accept);
1859 //Store the droppable's proportions
1860 this.proportions = { width: this.element[0].offsetWidth, height: this.element[0].offsetHeight };
1862 // Add the reference and positions to the manager
1863 $.ui.ddmanager.droppables[o.scope] = $.ui.ddmanager.droppables[o.scope] || [];
1864 $.ui.ddmanager.droppables[o.scope].push(this);
1866 (o.addClasses && this.element.addClass("ui-droppable"));
1870 destroy: function() {
1871 var drop = $.ui.ddmanager.droppables[this.options.scope];
1872 for ( var i = 0; i < drop.length; i++ )
1873 if ( drop[i] == this )
1874 drop.splice(i, 1);
1876 this.element
1877 .removeClass("ui-droppable ui-droppable-disabled")
1878 .removeData("droppable")
1879 .unbind(".droppable");
1881 return this;
1884 _setOption: function(key, value) {
1886 if(key == 'accept') {
1887 this.accept = $.isFunction(value) ? value : function(d) {
1888 return d.is(value);
1891 $.Widget.prototype._setOption.apply(this, arguments);
1894 _activate: function(event) {
1895 var draggable = $.ui.ddmanager.current;
1896 if(this.options.activeClass) this.element.addClass(this.options.activeClass);
1897 (draggable && this._trigger('activate', event, this.ui(draggable)));
1900 _deactivate: function(event) {
1901 var draggable = $.ui.ddmanager.current;
1902 if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
1903 (draggable && this._trigger('deactivate', event, this.ui(draggable)));
1906 _over: function(event) {
1908 var draggable = $.ui.ddmanager.current;
1909 if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
1911 if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
1912 if(this.options.hoverClass) this.element.addClass(this.options.hoverClass);
1913 this._trigger('over', event, this.ui(draggable));
1918 _out: function(event) {
1920 var draggable = $.ui.ddmanager.current;
1921 if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
1923 if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
1924 if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
1925 this._trigger('out', event, this.ui(draggable));
1930 _drop: function(event,custom) {
1932 var draggable = custom || $.ui.ddmanager.current;
1933 if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return false; // Bail if draggable and droppable are same element
1935 var childrenIntersection = false;
1936 this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function() {
1937 var inst = $.data(this, 'droppable');
1939 inst.options.greedy
1940 && !inst.options.disabled
1941 && inst.options.scope == draggable.options.scope
1942 && inst.accept.call(inst.element[0], (draggable.currentItem || draggable.element))
1943 && $.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance)
1944 ) { childrenIntersection = true; return false; }
1946 if(childrenIntersection) return false;
1948 if(this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
1949 if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
1950 if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
1951 this._trigger('drop', event, this.ui(draggable));
1952 return this.element;
1955 return false;
1959 ui: function(c) {
1960 return {
1961 draggable: (c.currentItem || c.element),
1962 helper: c.helper,
1963 position: c.position,
1964 offset: c.positionAbs
1970 $.extend($.ui.droppable, {
1971 version: "1.8.16"
1974 $.ui.intersect = function(draggable, droppable, toleranceMode) {
1976 if (!droppable.offset) return false;
1978 var x1 = (draggable.positionAbs || draggable.position.absolute).left, x2 = x1 + draggable.helperProportions.width,
1979 y1 = (draggable.positionAbs || draggable.position.absolute).top, y2 = y1 + draggable.helperProportions.height;
1980 var l = droppable.offset.left, r = l + droppable.proportions.width,
1981 t = droppable.offset.top, b = t + droppable.proportions.height;
1983 switch (toleranceMode) {
1984 case 'fit':
1985 return (l <= x1 && x2 <= r
1986 && t <= y1 && y2 <= b);
1987 break;
1988 case 'intersect':
1989 return (l < x1 + (draggable.helperProportions.width / 2) // Right Half
1990 && x2 - (draggable.helperProportions.width / 2) < r // Left Half
1991 && t < y1 + (draggable.helperProportions.height / 2) // Bottom Half
1992 && y2 - (draggable.helperProportions.height / 2) < b ); // Top Half
1993 break;
1994 case 'pointer':
1995 var draggableLeft = ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left),
1996 draggableTop = ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top),
1997 isOver = $.ui.isOver(draggableTop, draggableLeft, t, l, droppable.proportions.height, droppable.proportions.width);
1998 return isOver;
1999 break;
2000 case 'touch':
2001 return (
2002 (y1 >= t && y1 <= b) || // Top edge touching
2003 (y2 >= t && y2 <= b) || // Bottom edge touching
2004 (y1 < t && y2 > b) // Surrounded vertically
2005 ) && (
2006 (x1 >= l && x1 <= r) || // Left edge touching
2007 (x2 >= l && x2 <= r) || // Right edge touching
2008 (x1 < l && x2 > r) // Surrounded horizontally
2010 break;
2011 default:
2012 return false;
2013 break;
2019 This manager tracks offsets of draggables and droppables
2021 $.ui.ddmanager = {
2022 current: null,
2023 droppables: { 'default': [] },
2024 prepareOffsets: function(t, event) {
2026 var m = $.ui.ddmanager.droppables[t.options.scope] || [];
2027 var type = event ? event.type : null; // workaround for #2317
2028 var list = (t.currentItem || t.element).find(":data(droppable)").andSelf();
2030 droppablesLoop: for (var i = 0; i < m.length; i++) {
2032 if(m[i].options.disabled || (t && !m[i].accept.call(m[i].element[0],(t.currentItem || t.element)))) continue; //No disabled and non-accepted
2033 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
2034 m[i].visible = m[i].element.css("display") != "none"; if(!m[i].visible) continue; //If the element is not visible, continue
2036 if(type == "mousedown") m[i]._activate.call(m[i], event); //Activate the droppable if used directly from draggables
2038 m[i].offset = m[i].element.offset();
2039 m[i].proportions = { width: m[i].element[0].offsetWidth, height: m[i].element[0].offsetHeight };
2044 drop: function(draggable, event) {
2046 var dropped = false;
2047 $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
2049 if(!this.options) return;
2050 if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance))
2051 dropped = dropped || this._drop.call(this, event);
2053 if (!this.options.disabled && this.visible && this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
2054 this.isout = 1; this.isover = 0;
2055 this._deactivate.call(this, event);
2059 return dropped;
2062 dragStart: function( draggable, event ) {
2063 //Listen for scrolling so that if the dragging causes scrolling the position of the droppables can be recalculated (see #5003)
2064 draggable.element.parents( ":not(body,html)" ).bind( "scroll.droppable", function() {
2065 if( !draggable.options.refreshPositions ) $.ui.ddmanager.prepareOffsets( draggable, event );
2068 drag: function(draggable, event) {
2070 //If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse.
2071 if(draggable.options.refreshPositions) $.ui.ddmanager.prepareOffsets(draggable, event);
2073 //Run through all droppables and check their positions based on specific tolerance options
2074 $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
2076 if(this.options.disabled || this.greedyChild || !this.visible) return;
2077 var intersects = $.ui.intersect(draggable, this, this.options.tolerance);
2079 var c = !intersects && this.isover == 1 ? 'isout' : (intersects && this.isover == 0 ? 'isover' : null);
2080 if(!c) return;
2082 var parentInstance;
2083 if (this.options.greedy) {
2084 var parent = this.element.parents(':data(droppable):eq(0)');
2085 if (parent.length) {
2086 parentInstance = $.data(parent[0], 'droppable');
2087 parentInstance.greedyChild = (c == 'isover' ? 1 : 0);
2091 // we just moved into a greedy child
2092 if (parentInstance && c == 'isover') {
2093 parentInstance['isover'] = 0;
2094 parentInstance['isout'] = 1;
2095 parentInstance._out.call(parentInstance, event);
2098 this[c] = 1; this[c == 'isout' ? 'isover' : 'isout'] = 0;
2099 this[c == "isover" ? "_over" : "_out"].call(this, event);
2101 // we just moved out of a greedy child
2102 if (parentInstance && c == 'isout') {
2103 parentInstance['isout'] = 0;
2104 parentInstance['isover'] = 1;
2105 parentInstance._over.call(parentInstance, event);
2110 dragStop: function( draggable, event ) {
2111 draggable.element.parents( ":not(body,html)" ).unbind( "scroll.droppable" );
2112 //Call prepareOffsets one final time since IE does not fire return scroll events when overflow was caused by drag (see #5003)
2113 if( !draggable.options.refreshPositions ) $.ui.ddmanager.prepareOffsets( draggable, event );
2117 })(jQuery);
2119 * jQuery UI Resizable 1.8.16
2121 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
2122 * Dual licensed under the MIT or GPL Version 2 licenses.
2123 * http://jquery.org/license
2125 * http://docs.jquery.com/UI/Resizables
2127 * Depends:
2128 * jquery.ui.core.js
2129 * jquery.ui.mouse.js
2130 * jquery.ui.widget.js
2132 (function( $, undefined ) {
2134 $.widget("ui.resizable", $.ui.mouse, {
2135 widgetEventPrefix: "resize",
2136 options: {
2137 alsoResize: false,
2138 animate: false,
2139 animateDuration: "slow",
2140 animateEasing: "swing",
2141 aspectRatio: false,
2142 autoHide: false,
2143 containment: false,
2144 ghost: false,
2145 grid: false,
2146 handles: "e,s,se",
2147 helper: false,
2148 maxHeight: null,
2149 maxWidth: null,
2150 minHeight: 10,
2151 minWidth: 10,
2152 zIndex: 1000
2154 _create: function() {
2156 var self = this, o = this.options;
2157 this.element.addClass("ui-resizable");
2159 $.extend(this, {
2160 _aspectRatio: !!(o.aspectRatio),
2161 aspectRatio: o.aspectRatio,
2162 originalElement: this.element,
2163 _proportionallyResizeElements: [],
2164 _helper: o.helper || o.ghost || o.animate ? o.helper || 'ui-resizable-helper' : null
2167 //Wrap the element if it cannot hold child nodes
2168 if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) {
2170 //Opera fix for relative positioning
2171 if (/relative/.test(this.element.css('position')) && $.browser.opera)
2172 this.element.css({ position: 'relative', top: 'auto', left: 'auto' });
2174 //Create a wrapper element and set the wrapper to the new current internal element
2175 this.element.wrap(
2176 $('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({
2177 position: this.element.css('position'),
2178 width: this.element.outerWidth(),
2179 height: this.element.outerHeight(),
2180 top: this.element.css('top'),
2181 left: this.element.css('left')
2185 //Overwrite the original this.element
2186 this.element = this.element.parent().data(
2187 "resizable", this.element.data('resizable')
2190 this.elementIsWrapper = true;
2192 //Move margins to the wrapper
2193 this.element.css({ marginLeft: this.originalElement.css("marginLeft"), marginTop: this.originalElement.css("marginTop"), marginRight: this.originalElement.css("marginRight"), marginBottom: this.originalElement.css("marginBottom") });
2194 this.originalElement.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0});
2196 //Prevent Safari textarea resize
2197 this.originalResizeStyle = this.originalElement.css('resize');
2198 this.originalElement.css('resize', 'none');
2200 //Push the actual element to our proportionallyResize internal array
2201 this._proportionallyResizeElements.push(this.originalElement.css({ position: 'static', zoom: 1, display: 'block' }));
2203 // avoid IE jump (hard set the margin)
2204 this.originalElement.css({ margin: this.originalElement.css('margin') });
2206 // fix handlers offset
2207 this._proportionallyResize();
2211 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' });
2212 if(this.handles.constructor == String) {
2214 if(this.handles == 'all') this.handles = 'n,e,s,w,se,sw,ne,nw';
2215 var n = this.handles.split(","); this.handles = {};
2217 for(var i = 0; i < n.length; i++) {
2219 var handle = $.trim(n[i]), hname = 'ui-resizable-'+handle;
2220 var axis = $('<div class="ui-resizable-handle ' + hname + '"></div>');
2222 // increase zIndex of sw, se, ne, nw axis
2223 //TODO : this modifies original option
2224 if(/sw|se|ne|nw/.test(handle)) axis.css({ zIndex: ++o.zIndex });
2226 //TODO : What's going on here?
2227 if ('se' == handle) {
2228 axis.addClass('ui-icon ui-icon-gripsmall-diagonal-se');
2231 //Insert into internal handles object and append to element
2232 this.handles[handle] = '.ui-resizable-'+handle;
2233 this.element.append(axis);
2238 this._renderAxis = function(target) {
2240 target = target || this.element;
2242 for(var i in this.handles) {
2244 if(this.handles[i].constructor == String)
2245 this.handles[i] = $(this.handles[i], this.element).show();
2247 //Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls)
2248 if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) {
2250 var axis = $(this.handles[i], this.element), padWrapper = 0;
2252 //Checking the correct pad and border
2253 padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth();
2255 //The padding type i have to apply...
2256 var padPos = [ 'padding',
2257 /ne|nw|n/.test(i) ? 'Top' :
2258 /se|sw|s/.test(i) ? 'Bottom' :
2259 /^e$/.test(i) ? 'Right' : 'Left' ].join("");
2261 target.css(padPos, padWrapper);
2263 this._proportionallyResize();
2267 //TODO: What's that good for? There's not anything to be executed left
2268 if(!$(this.handles[i]).length)
2269 continue;
2274 //TODO: make renderAxis a prototype function
2275 this._renderAxis(this.element);
2277 this._handles = $('.ui-resizable-handle', this.element)
2278 .disableSelection();
2280 //Matching axis name
2281 this._handles.mouseover(function() {
2282 if (!self.resizing) {
2283 if (this.className)
2284 var axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);
2285 //Axis, default = se
2286 self.axis = axis && axis[1] ? axis[1] : 'se';
2290 //If we want to auto hide the elements
2291 if (o.autoHide) {
2292 this._handles.hide();
2293 $(this.element)
2294 .addClass("ui-resizable-autohide")
2295 .hover(function() {
2296 if (o.disabled) return;
2297 $(this).removeClass("ui-resizable-autohide");
2298 self._handles.show();
2300 function(){
2301 if (o.disabled) return;
2302 if (!self.resizing) {
2303 $(this).addClass("ui-resizable-autohide");
2304 self._handles.hide();
2309 //Initialize the mouse interaction
2310 this._mouseInit();
2314 destroy: function() {
2316 this._mouseDestroy();
2318 var _destroy = function(exp) {
2319 $(exp).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing")
2320 .removeData("resizable").unbind(".resizable").find('.ui-resizable-handle').remove();
2323 //TODO: Unwrap at same DOM position
2324 if (this.elementIsWrapper) {
2325 _destroy(this.element);
2326 var wrapper = this.element;
2327 wrapper.after(
2328 this.originalElement.css({
2329 position: wrapper.css('position'),
2330 width: wrapper.outerWidth(),
2331 height: wrapper.outerHeight(),
2332 top: wrapper.css('top'),
2333 left: wrapper.css('left')
2335 ).remove();
2338 this.originalElement.css('resize', this.originalResizeStyle);
2339 _destroy(this.originalElement);
2341 return this;
2344 _mouseCapture: function(event) {
2345 var handle = false;
2346 for (var i in this.handles) {
2347 if ($(this.handles[i])[0] == event.target) {
2348 handle = true;
2352 return !this.options.disabled && handle;
2355 _mouseStart: function(event) {
2357 var o = this.options, iniPos = this.element.position(), el = this.element;
2359 this.resizing = true;
2360 this.documentScroll = { top: $(document).scrollTop(), left: $(document).scrollLeft() };
2362 // bugfix for http://dev.jquery.com/ticket/1749
2363 if (el.is('.ui-draggable') || (/absolute/).test(el.css('position'))) {
2364 el.css({ position: 'absolute', top: iniPos.top, left: iniPos.left });
2367 //Opera fixing relative position
2368 if ($.browser.opera && (/relative/).test(el.css('position')))
2369 el.css({ position: 'relative', top: 'auto', left: 'auto' });
2371 this._renderProxy();
2373 var curleft = num(this.helper.css('left')), curtop = num(this.helper.css('top'));
2375 if (o.containment) {
2376 curleft += $(o.containment).scrollLeft() || 0;
2377 curtop += $(o.containment).scrollTop() || 0;
2380 //Store needed variables
2381 this.offset = this.helper.offset();
2382 this.position = { left: curleft, top: curtop };
2383 this.size = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
2384 this.originalSize = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
2385 this.originalPosition = { left: curleft, top: curtop };
2386 this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() };
2387 this.originalMousePosition = { left: event.pageX, top: event.pageY };
2389 //Aspect Ratio
2390 this.aspectRatio = (typeof o.aspectRatio == 'number') ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1);
2392 var cursor = $('.ui-resizable-' + this.axis).css('cursor');
2393 $('body').css('cursor', cursor == 'auto' ? this.axis + '-resize' : cursor);
2395 el.addClass("ui-resizable-resizing");
2396 this._propagate("start", event);
2397 return true;
2400 _mouseDrag: function(event) {
2402 //Increase performance, avoid regex
2403 var el = this.helper, o = this.options, props = {},
2404 self = this, smp = this.originalMousePosition, a = this.axis;
2406 var dx = (event.pageX-smp.left)||0, dy = (event.pageY-smp.top)||0;
2407 var trigger = this._change[a];
2408 if (!trigger) return false;
2410 // Calculate the attrs that will be change
2411 var data = trigger.apply(this, [event, dx, dy]), ie6 = $.browser.msie && $.browser.version < 7, csdif = this.sizeDiff;
2413 // Put this in the mouseDrag handler since the user can start pressing shift while resizing
2414 this._updateVirtualBoundaries(event.shiftKey);
2415 if (this._aspectRatio || event.shiftKey)
2416 data = this._updateRatio(data, event);
2418 data = this._respectSize(data, event);
2420 // plugins callbacks need to be called first
2421 this._propagate("resize", event);
2423 el.css({
2424 top: this.position.top + "px", left: this.position.left + "px",
2425 width: this.size.width + "px", height: this.size.height + "px"
2428 if (!this._helper && this._proportionallyResizeElements.length)
2429 this._proportionallyResize();
2431 this._updateCache(data);
2433 // calling the user callback at the end
2434 this._trigger('resize', event, this.ui());
2436 return false;
2439 _mouseStop: function(event) {
2441 this.resizing = false;
2442 var o = this.options, self = this;
2444 if(this._helper) {
2445 var pr = this._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
2446 soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
2447 soffsetw = ista ? 0 : self.sizeDiff.width;
2449 var s = { width: (self.helper.width() - soffsetw), height: (self.helper.height() - soffseth) },
2450 left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
2451 top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
2453 if (!o.animate)
2454 this.element.css($.extend(s, { top: top, left: left }));
2456 self.helper.height(self.size.height);
2457 self.helper.width(self.size.width);
2459 if (this._helper && !o.animate) this._proportionallyResize();
2462 $('body').css('cursor', 'auto');
2464 this.element.removeClass("ui-resizable-resizing");
2466 this._propagate("stop", event);
2468 if (this._helper) this.helper.remove();
2469 return false;
2473 _updateVirtualBoundaries: function(forceAspectRatio) {
2474 var o = this.options, pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b;
2476 b = {
2477 minWidth: isNumber(o.minWidth) ? o.minWidth : 0,
2478 maxWidth: isNumber(o.maxWidth) ? o.maxWidth : Infinity,
2479 minHeight: isNumber(o.minHeight) ? o.minHeight : 0,
2480 maxHeight: isNumber(o.maxHeight) ? o.maxHeight : Infinity
2483 if(this._aspectRatio || forceAspectRatio) {
2484 // We want to create an enclosing box whose aspect ration is the requested one
2485 // First, compute the "projected" size for each dimension based on the aspect ratio and other dimension
2486 pMinWidth = b.minHeight * this.aspectRatio;
2487 pMinHeight = b.minWidth / this.aspectRatio;
2488 pMaxWidth = b.maxHeight * this.aspectRatio;
2489 pMaxHeight = b.maxWidth / this.aspectRatio;
2491 if(pMinWidth > b.minWidth) b.minWidth = pMinWidth;
2492 if(pMinHeight > b.minHeight) b.minHeight = pMinHeight;
2493 if(pMaxWidth < b.maxWidth) b.maxWidth = pMaxWidth;
2494 if(pMaxHeight < b.maxHeight) b.maxHeight = pMaxHeight;
2496 this._vBoundaries = b;
2499 _updateCache: function(data) {
2500 var o = this.options;
2501 this.offset = this.helper.offset();
2502 if (isNumber(data.left)) this.position.left = data.left;
2503 if (isNumber(data.top)) this.position.top = data.top;
2504 if (isNumber(data.height)) this.size.height = data.height;
2505 if (isNumber(data.width)) this.size.width = data.width;
2508 _updateRatio: function(data, event) {
2510 var o = this.options, cpos = this.position, csize = this.size, a = this.axis;
2512 if (isNumber(data.height)) data.width = (data.height * this.aspectRatio);
2513 else if (isNumber(data.width)) data.height = (data.width / this.aspectRatio);
2515 if (a == 'sw') {
2516 data.left = cpos.left + (csize.width - data.width);
2517 data.top = null;
2519 if (a == 'nw') {
2520 data.top = cpos.top + (csize.height - data.height);
2521 data.left = cpos.left + (csize.width - data.width);
2524 return data;
2527 _respectSize: function(data, event) {
2529 var el = this.helper, o = this._vBoundaries, pRatio = this._aspectRatio || event.shiftKey, a = this.axis,
2530 ismaxw = isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh = isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height),
2531 isminw = isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh = isNumber(data.height) && o.minHeight && (o.minHeight > data.height);
2533 if (isminw) data.width = o.minWidth;
2534 if (isminh) data.height = o.minHeight;
2535 if (ismaxw) data.width = o.maxWidth;
2536 if (ismaxh) data.height = o.maxHeight;
2538 var dw = this.originalPosition.left + this.originalSize.width, dh = this.position.top + this.size.height;
2539 var cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a);
2541 if (isminw && cw) data.left = dw - o.minWidth;
2542 if (ismaxw && cw) data.left = dw - o.maxWidth;
2543 if (isminh && ch) data.top = dh - o.minHeight;
2544 if (ismaxh && ch) data.top = dh - o.maxHeight;
2546 // fixing jump error on top/left - bug #2330
2547 var isNotwh = !data.width && !data.height;
2548 if (isNotwh && !data.left && data.top) data.top = null;
2549 else if (isNotwh && !data.top && data.left) data.left = null;
2551 return data;
2554 _proportionallyResize: function() {
2556 var o = this.options;
2557 if (!this._proportionallyResizeElements.length) return;
2558 var element = this.helper || this.element;
2560 for (var i=0; i < this._proportionallyResizeElements.length; i++) {
2562 var prel = this._proportionallyResizeElements[i];
2564 if (!this.borderDif) {
2565 var b = [prel.css('borderTopWidth'), prel.css('borderRightWidth'), prel.css('borderBottomWidth'), prel.css('borderLeftWidth')],
2566 p = [prel.css('paddingTop'), prel.css('paddingRight'), prel.css('paddingBottom'), prel.css('paddingLeft')];
2568 this.borderDif = $.map(b, function(v, i) {
2569 var border = parseInt(v,10)||0, padding = parseInt(p[i],10)||0;
2570 return border + padding;
2574 if ($.browser.msie && !(!($(element).is(':hidden') || $(element).parents(':hidden').length)))
2575 continue;
2577 prel.css({
2578 height: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0,
2579 width: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0
2586 _renderProxy: function() {
2588 var el = this.element, o = this.options;
2589 this.elementOffset = el.offset();
2591 if(this._helper) {
2593 this.helper = this.helper || $('<div style="overflow:hidden;"></div>');
2595 // fix ie6 offset TODO: This seems broken
2596 var ie6 = $.browser.msie && $.browser.version < 7, ie6offset = (ie6 ? 1 : 0),
2597 pxyoffset = ( ie6 ? 2 : -1 );
2599 this.helper.addClass(this._helper).css({
2600 width: this.element.outerWidth() + pxyoffset,
2601 height: this.element.outerHeight() + pxyoffset,
2602 position: 'absolute',
2603 left: this.elementOffset.left - ie6offset +'px',
2604 top: this.elementOffset.top - ie6offset +'px',
2605 zIndex: ++o.zIndex //TODO: Don't modify option
2608 this.helper
2609 .appendTo("body")
2610 .disableSelection();
2612 } else {
2613 this.helper = this.element;
2618 _change: {
2619 e: function(event, dx, dy) {
2620 return { width: this.originalSize.width + dx };
2622 w: function(event, dx, dy) {
2623 var o = this.options, cs = this.originalSize, sp = this.originalPosition;
2624 return { left: sp.left + dx, width: cs.width - dx };
2626 n: function(event, dx, dy) {
2627 var o = this.options, cs = this.originalSize, sp = this.originalPosition;
2628 return { top: sp.top + dy, height: cs.height - dy };
2630 s: function(event, dx, dy) {
2631 return { height: this.originalSize.height + dy };
2633 se: function(event, dx, dy) {
2634 return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
2636 sw: function(event, dx, dy) {
2637 return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
2639 ne: function(event, dx, dy) {
2640 return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
2642 nw: function(event, dx, dy) {
2643 return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
2647 _propagate: function(n, event) {
2648 $.ui.plugin.call(this, n, [event, this.ui()]);
2649 (n != "resize" && this._trigger(n, event, this.ui()));
2652 plugins: {},
2654 ui: function() {
2655 return {
2656 originalElement: this.originalElement,
2657 element: this.element,
2658 helper: this.helper,
2659 position: this.position,
2660 size: this.size,
2661 originalSize: this.originalSize,
2662 originalPosition: this.originalPosition
2668 $.extend($.ui.resizable, {
2669 version: "1.8.16"
2673 * Resizable Extensions
2676 $.ui.plugin.add("resizable", "alsoResize", {
2678 start: function (event, ui) {
2679 var self = $(this).data("resizable"), o = self.options;
2681 var _store = function (exp) {
2682 $(exp).each(function() {
2683 var el = $(this);
2684 el.data("resizable-alsoresize", {
2685 width: parseInt(el.width(), 10), height: parseInt(el.height(), 10),
2686 left: parseInt(el.css('left'), 10), top: parseInt(el.css('top'), 10),
2687 position: el.css('position') // to reset Opera on stop()
2692 if (typeof(o.alsoResize) == 'object' && !o.alsoResize.parentNode) {
2693 if (o.alsoResize.length) { o.alsoResize = o.alsoResize[0]; _store(o.alsoResize); }
2694 else { $.each(o.alsoResize, function (exp) { _store(exp); }); }
2695 }else{
2696 _store(o.alsoResize);
2700 resize: function (event, ui) {
2701 var self = $(this).data("resizable"), o = self.options, os = self.originalSize, op = self.originalPosition;
2703 var delta = {
2704 height: (self.size.height - os.height) || 0, width: (self.size.width - os.width) || 0,
2705 top: (self.position.top - op.top) || 0, left: (self.position.left - op.left) || 0
2708 _alsoResize = function (exp, c) {
2709 $(exp).each(function() {
2710 var el = $(this), start = $(this).data("resizable-alsoresize"), style = {},
2711 css = c && c.length ? c : el.parents(ui.originalElement[0]).length ? ['width', 'height'] : ['width', 'height', 'top', 'left'];
2713 $.each(css, function (i, prop) {
2714 var sum = (start[prop]||0) + (delta[prop]||0);
2715 if (sum && sum >= 0)
2716 style[prop] = sum || null;
2719 // Opera fixing relative position
2720 if ($.browser.opera && /relative/.test(el.css('position'))) {
2721 self._revertToRelativePosition = true;
2722 el.css({ position: 'absolute', top: 'auto', left: 'auto' });
2725 el.css(style);
2729 if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) {
2730 $.each(o.alsoResize, function (exp, c) { _alsoResize(exp, c); });
2731 }else{
2732 _alsoResize(o.alsoResize);
2736 stop: function (event, ui) {
2737 var self = $(this).data("resizable"), o = self.options;
2739 var _reset = function (exp) {
2740 $(exp).each(function() {
2741 var el = $(this);
2742 // reset position for Opera - no need to verify it was changed
2743 el.css({ position: el.data("resizable-alsoresize").position });
2747 if (self._revertToRelativePosition) {
2748 self._revertToRelativePosition = false;
2749 if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) {
2750 $.each(o.alsoResize, function (exp) { _reset(exp); });
2751 }else{
2752 _reset(o.alsoResize);
2756 $(this).removeData("resizable-alsoresize");
2760 $.ui.plugin.add("resizable", "animate", {
2762 stop: function(event, ui) {
2763 var self = $(this).data("resizable"), o = self.options;
2765 var pr = self._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
2766 soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
2767 soffsetw = ista ? 0 : self.sizeDiff.width;
2769 var style = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },
2770 left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
2771 top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
2773 self.element.animate(
2774 $.extend(style, top && left ? { top: top, left: left } : {}), {
2775 duration: o.animateDuration,
2776 easing: o.animateEasing,
2777 step: function() {
2779 var data = {
2780 width: parseInt(self.element.css('width'), 10),
2781 height: parseInt(self.element.css('height'), 10),
2782 top: parseInt(self.element.css('top'), 10),
2783 left: parseInt(self.element.css('left'), 10)
2786 if (pr && pr.length) $(pr[0]).css({ width: data.width, height: data.height });
2788 // propagating resize, and updating values for each animation step
2789 self._updateCache(data);
2790 self._propagate("resize", event);
2799 $.ui.plugin.add("resizable", "containment", {
2801 start: function(event, ui) {
2802 var self = $(this).data("resizable"), o = self.options, el = self.element;
2803 var oc = o.containment, ce = (oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc;
2804 if (!ce) return;
2806 self.containerElement = $(ce);
2808 if (/document/.test(oc) || oc == document) {
2809 self.containerOffset = { left: 0, top: 0 };
2810 self.containerPosition = { left: 0, top: 0 };
2812 self.parentData = {
2813 element: $(document), left: 0, top: 0,
2814 width: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight
2818 // i'm a node, so compute top, left, right, bottom
2819 else {
2820 var element = $(ce), p = [];
2821 $([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) { p[i] = num(element.css("padding" + name)); });
2823 self.containerOffset = element.offset();
2824 self.containerPosition = element.position();
2825 self.containerSize = { height: (element.innerHeight() - p[3]), width: (element.innerWidth() - p[1]) };
2827 var co = self.containerOffset, ch = self.containerSize.height, cw = self.containerSize.width,
2828 width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw ), height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch);
2830 self.parentData = {
2831 element: ce, left: co.left, top: co.top, width: width, height: height
2836 resize: function(event, ui) {
2837 var self = $(this).data("resizable"), o = self.options,
2838 ps = self.containerSize, co = self.containerOffset, cs = self.size, cp = self.position,
2839 pRatio = self._aspectRatio || event.shiftKey, cop = { top:0, left:0 }, ce = self.containerElement;
2841 if (ce[0] != document && (/static/).test(ce.css('position'))) cop = co;
2843 if (cp.left < (self._helper ? co.left : 0)) {
2844 self.size.width = self.size.width + (self._helper ? (self.position.left - co.left) : (self.position.left - cop.left));
2845 if (pRatio) self.size.height = self.size.width / o.aspectRatio;
2846 self.position.left = o.helper ? co.left : 0;
2849 if (cp.top < (self._helper ? co.top : 0)) {
2850 self.size.height = self.size.height + (self._helper ? (self.position.top - co.top) : self.position.top);
2851 if (pRatio) self.size.width = self.size.height * o.aspectRatio;
2852 self.position.top = self._helper ? co.top : 0;
2855 self.offset.left = self.parentData.left+self.position.left;
2856 self.offset.top = self.parentData.top+self.position.top;
2858 var woset = Math.abs( (self._helper ? self.offset.left - cop.left : (self.offset.left - cop.left)) + self.sizeDiff.width ),
2859 hoset = Math.abs( (self._helper ? self.offset.top - cop.top : (self.offset.top - co.top)) + self.sizeDiff.height );
2861 var isParent = self.containerElement.get(0) == self.element.parent().get(0),
2862 isOffsetRelative = /relative|absolute/.test(self.containerElement.css('position'));
2864 if(isParent && isOffsetRelative) woset -= self.parentData.left;
2866 if (woset + self.size.width >= self.parentData.width) {
2867 self.size.width = self.parentData.width - woset;
2868 if (pRatio) self.size.height = self.size.width / self.aspectRatio;
2871 if (hoset + self.size.height >= self.parentData.height) {
2872 self.size.height = self.parentData.height - hoset;
2873 if (pRatio) self.size.width = self.size.height * self.aspectRatio;
2877 stop: function(event, ui){
2878 var self = $(this).data("resizable"), o = self.options, cp = self.position,
2879 co = self.containerOffset, cop = self.containerPosition, ce = self.containerElement;
2881 var helper = $(self.helper), ho = helper.offset(), w = helper.outerWidth() - self.sizeDiff.width, h = helper.outerHeight() - self.sizeDiff.height;
2883 if (self._helper && !o.animate && (/relative/).test(ce.css('position')))
2884 $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
2886 if (self._helper && !o.animate && (/static/).test(ce.css('position')))
2887 $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
2892 $.ui.plugin.add("resizable", "ghost", {
2894 start: function(event, ui) {
2896 var self = $(this).data("resizable"), o = self.options, cs = self.size;
2898 self.ghost = self.originalElement.clone();
2899 self.ghost
2900 .css({ opacity: .25, display: 'block', position: 'relative', height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 })
2901 .addClass('ui-resizable-ghost')
2902 .addClass(typeof o.ghost == 'string' ? o.ghost : '');
2904 self.ghost.appendTo(self.helper);
2908 resize: function(event, ui){
2909 var self = $(this).data("resizable"), o = self.options;
2910 if (self.ghost) self.ghost.css({ position: 'relative', height: self.size.height, width: self.size.width });
2913 stop: function(event, ui){
2914 var self = $(this).data("resizable"), o = self.options;
2915 if (self.ghost && self.helper) self.helper.get(0).removeChild(self.ghost.get(0));
2920 $.ui.plugin.add("resizable", "grid", {
2922 resize: function(event, ui) {
2923 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;
2924 o.grid = typeof o.grid == "number" ? [o.grid, o.grid] : o.grid;
2925 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);
2927 if (/^(se|s|e)$/.test(a)) {
2928 self.size.width = os.width + ox;
2929 self.size.height = os.height + oy;
2931 else if (/^(ne)$/.test(a)) {
2932 self.size.width = os.width + ox;
2933 self.size.height = os.height + oy;
2934 self.position.top = op.top - oy;
2936 else if (/^(sw)$/.test(a)) {
2937 self.size.width = os.width + ox;
2938 self.size.height = os.height + oy;
2939 self.position.left = op.left - ox;
2941 else {
2942 self.size.width = os.width + ox;
2943 self.size.height = os.height + oy;
2944 self.position.top = op.top - oy;
2945 self.position.left = op.left - ox;
2951 var num = function(v) {
2952 return parseInt(v, 10) || 0;
2955 var isNumber = function(value) {
2956 return !isNaN(parseInt(value, 10));
2959 })(jQuery);
2961 * jQuery UI Selectable 1.8.16
2963 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
2964 * Dual licensed under the MIT or GPL Version 2 licenses.
2965 * http://jquery.org/license
2967 * http://docs.jquery.com/UI/Selectables
2969 * Depends:
2970 * jquery.ui.core.js
2971 * jquery.ui.mouse.js
2972 * jquery.ui.widget.js
2974 (function( $, undefined ) {
2976 $.widget("ui.selectable", $.ui.mouse, {
2977 options: {
2978 appendTo: 'body',
2979 autoRefresh: true,
2980 distance: 0,
2981 filter: '*',
2982 tolerance: 'touch'
2984 _create: function() {
2985 var self = this;
2987 this.element.addClass("ui-selectable");
2989 this.dragged = false;
2991 // cache selectee children based on filter
2992 var selectees;
2993 this.refresh = function() {
2994 selectees = $(self.options.filter, self.element[0]);
2995 selectees.each(function() {
2996 var $this = $(this);
2997 var pos = $this.offset();
2998 $.data(this, "selectable-item", {
2999 element: this,
3000 $element: $this,
3001 left: pos.left,
3002 top: pos.top,
3003 right: pos.left + $this.outerWidth(),
3004 bottom: pos.top + $this.outerHeight(),
3005 startselected: false,
3006 selected: $this.hasClass('ui-selected'),
3007 selecting: $this.hasClass('ui-selecting'),
3008 unselecting: $this.hasClass('ui-unselecting')
3012 this.refresh();
3014 this.selectees = selectees.addClass("ui-selectee");
3016 this._mouseInit();
3018 this.helper = $("<div class='ui-selectable-helper'></div>");
3021 destroy: function() {
3022 this.selectees
3023 .removeClass("ui-selectee")
3024 .removeData("selectable-item");
3025 this.element
3026 .removeClass("ui-selectable ui-selectable-disabled")
3027 .removeData("selectable")
3028 .unbind(".selectable");
3029 this._mouseDestroy();
3031 return this;
3034 _mouseStart: function(event) {
3035 var self = this;
3037 this.opos = [event.pageX, event.pageY];
3039 if (this.options.disabled)
3040 return;
3042 var options = this.options;
3044 this.selectees = $(options.filter, this.element[0]);
3046 this._trigger("start", event);
3048 $(options.appendTo).append(this.helper);
3049 // position helper (lasso)
3050 this.helper.css({
3051 "left": event.clientX,
3052 "top": event.clientY,
3053 "width": 0,
3054 "height": 0
3057 if (options.autoRefresh) {
3058 this.refresh();
3061 this.selectees.filter('.ui-selected').each(function() {
3062 var selectee = $.data(this, "selectable-item");
3063 selectee.startselected = true;
3064 if (!event.metaKey) {
3065 selectee.$element.removeClass('ui-selected');
3066 selectee.selected = false;
3067 selectee.$element.addClass('ui-unselecting');
3068 selectee.unselecting = true;
3069 // selectable UNSELECTING callback
3070 self._trigger("unselecting", event, {
3071 unselecting: selectee.element
3076 $(event.target).parents().andSelf().each(function() {
3077 var selectee = $.data(this, "selectable-item");
3078 if (selectee) {
3079 var doSelect = !event.metaKey || !selectee.$element.hasClass('ui-selected');
3080 selectee.$element
3081 .removeClass(doSelect ? "ui-unselecting" : "ui-selected")
3082 .addClass(doSelect ? "ui-selecting" : "ui-unselecting");
3083 selectee.unselecting = !doSelect;
3084 selectee.selecting = doSelect;
3085 selectee.selected = doSelect;
3086 // selectable (UN)SELECTING callback
3087 if (doSelect) {
3088 self._trigger("selecting", event, {
3089 selecting: selectee.element
3091 } else {
3092 self._trigger("unselecting", event, {
3093 unselecting: selectee.element
3096 return false;
3102 _mouseDrag: function(event) {
3103 var self = this;
3104 this.dragged = true;
3106 if (this.options.disabled)
3107 return;
3109 var options = this.options;
3111 var x1 = this.opos[0], y1 = this.opos[1], x2 = event.pageX, y2 = event.pageY;
3112 if (x1 > x2) { var tmp = x2; x2 = x1; x1 = tmp; }
3113 if (y1 > y2) { var tmp = y2; y2 = y1; y1 = tmp; }
3114 this.helper.css({left: x1, top: y1, width: x2-x1, height: y2-y1});
3116 this.selectees.each(function() {
3117 var selectee = $.data(this, "selectable-item");
3118 //prevent helper from being selected if appendTo: selectable
3119 if (!selectee || selectee.element == self.element[0])
3120 return;
3121 var hit = false;
3122 if (options.tolerance == 'touch') {
3123 hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) );
3124 } else if (options.tolerance == 'fit') {
3125 hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2);
3128 if (hit) {
3129 // SELECT
3130 if (selectee.selected) {
3131 selectee.$element.removeClass('ui-selected');
3132 selectee.selected = false;
3134 if (selectee.unselecting) {
3135 selectee.$element.removeClass('ui-unselecting');
3136 selectee.unselecting = false;
3138 if (!selectee.selecting) {
3139 selectee.$element.addClass('ui-selecting');
3140 selectee.selecting = true;
3141 // selectable SELECTING callback
3142 self._trigger("selecting", event, {
3143 selecting: selectee.element
3146 } else {
3147 // UNSELECT
3148 if (selectee.selecting) {
3149 if (event.metaKey && selectee.startselected) {
3150 selectee.$element.removeClass('ui-selecting');
3151 selectee.selecting = false;
3152 selectee.$element.addClass('ui-selected');
3153 selectee.selected = true;
3154 } else {
3155 selectee.$element.removeClass('ui-selecting');
3156 selectee.selecting = false;
3157 if (selectee.startselected) {
3158 selectee.$element.addClass('ui-unselecting');
3159 selectee.unselecting = true;
3161 // selectable UNSELECTING callback
3162 self._trigger("unselecting", event, {
3163 unselecting: selectee.element
3167 if (selectee.selected) {
3168 if (!event.metaKey && !selectee.startselected) {
3169 selectee.$element.removeClass('ui-selected');
3170 selectee.selected = false;
3172 selectee.$element.addClass('ui-unselecting');
3173 selectee.unselecting = true;
3174 // selectable UNSELECTING callback
3175 self._trigger("unselecting", event, {
3176 unselecting: selectee.element
3183 return false;
3186 _mouseStop: function(event) {
3187 var self = this;
3189 this.dragged = false;
3191 var options = this.options;
3193 $('.ui-unselecting', this.element[0]).each(function() {
3194 var selectee = $.data(this, "selectable-item");
3195 selectee.$element.removeClass('ui-unselecting');
3196 selectee.unselecting = false;
3197 selectee.startselected = false;
3198 self._trigger("unselected", event, {
3199 unselected: selectee.element
3202 $('.ui-selecting', this.element[0]).each(function() {
3203 var selectee = $.data(this, "selectable-item");
3204 selectee.$element.removeClass('ui-selecting').addClass('ui-selected');
3205 selectee.selecting = false;
3206 selectee.selected = true;
3207 selectee.startselected = true;
3208 self._trigger("selected", event, {
3209 selected: selectee.element
3212 this._trigger("stop", event);
3214 this.helper.remove();
3216 return false;
3221 $.extend($.ui.selectable, {
3222 version: "1.8.16"
3225 })(jQuery);
3227 * jQuery UI Sortable 1.8.16
3229 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
3230 * Dual licensed under the MIT or GPL Version 2 licenses.
3231 * http://jquery.org/license
3233 * http://docs.jquery.com/UI/Sortables
3235 * Depends:
3236 * jquery.ui.core.js
3237 * jquery.ui.mouse.js
3238 * jquery.ui.widget.js
3240 (function( $, undefined ) {
3242 $.widget("ui.sortable", $.ui.mouse, {
3243 widgetEventPrefix: "sort",
3244 options: {
3245 appendTo: "parent",
3246 axis: false,
3247 connectWith: false,
3248 containment: false,
3249 cursor: 'auto',
3250 cursorAt: false,
3251 dropOnEmpty: true,
3252 forcePlaceholderSize: false,
3253 forceHelperSize: false,
3254 grid: false,
3255 handle: false,
3256 helper: "original",
3257 items: '> *',
3258 opacity: false,
3259 placeholder: false,
3260 revert: false,
3261 scroll: true,
3262 scrollSensitivity: 20,
3263 scrollSpeed: 20,
3264 scope: "default",
3265 tolerance: "intersect",
3266 zIndex: 1000
3268 _create: function() {
3270 var o = this.options;
3271 this.containerCache = {};
3272 this.element.addClass("ui-sortable");
3274 //Get the items
3275 this.refresh();
3277 //Let's determine if the items are being displayed horizontally
3278 this.floating = this.items.length ? o.axis === 'x' || (/left|right/).test(this.items[0].item.css('float')) || (/inline|table-cell/).test(this.items[0].item.css('display')) : false;
3280 //Let's determine the parent's offset
3281 this.offset = this.element.offset();
3283 //Initialize mouse events for interaction
3284 this._mouseInit();
3288 destroy: function() {
3289 this.element
3290 .removeClass("ui-sortable ui-sortable-disabled")
3291 .removeData("sortable")
3292 .unbind(".sortable");
3293 this._mouseDestroy();
3295 for ( var i = this.items.length - 1; i >= 0; i-- )
3296 this.items[i].item.removeData("sortable-item");
3298 return this;
3301 _setOption: function(key, value){
3302 if ( key === "disabled" ) {
3303 this.options[ key ] = value;
3305 this.widget()
3306 [ value ? "addClass" : "removeClass"]( "ui-sortable-disabled" );
3307 } else {
3308 // Don't call widget base _setOption for disable as it adds ui-state-disabled class
3309 $.Widget.prototype._setOption.apply(this, arguments);
3313 _mouseCapture: function(event, overrideHandle) {
3315 if (this.reverting) {
3316 return false;
3319 if(this.options.disabled || this.options.type == 'static') return false;
3321 //We have to refresh the items data once first
3322 this._refreshItems(event);
3324 //Find out if the clicked node (or one of its parents) is a actual item in this.items
3325 var currentItem = null, self = this, nodes = $(event.target).parents().each(function() {
3326 if($.data(this, 'sortable-item') == self) {
3327 currentItem = $(this);
3328 return false;
3331 if($.data(event.target, 'sortable-item') == self) currentItem = $(event.target);
3333 if(!currentItem) return false;
3334 if(this.options.handle && !overrideHandle) {
3335 var validHandle = false;
3337 $(this.options.handle, currentItem).find("*").andSelf().each(function() { if(this == event.target) validHandle = true; });
3338 if(!validHandle) return false;
3341 this.currentItem = currentItem;
3342 this._removeCurrentsFromItems();
3343 return true;
3347 _mouseStart: function(event, overrideHandle, noActivation) {
3349 var o = this.options, self = this;
3350 this.currentContainer = this;
3352 //We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture
3353 this.refreshPositions();
3355 //Create and append the visible helper
3356 this.helper = this._createHelper(event);
3358 //Cache the helper size
3359 this._cacheHelperProportions();
3362 * - Position generation -
3363 * This block generates everything position related - it's the core of draggables.
3366 //Cache the margins of the original element
3367 this._cacheMargins();
3369 //Get the next scrolling parent
3370 this.scrollParent = this.helper.scrollParent();
3372 //The element's absolute position on the page minus margins
3373 this.offset = this.currentItem.offset();
3374 this.offset = {
3375 top: this.offset.top - this.margins.top,
3376 left: this.offset.left - this.margins.left
3379 // Only after we got the offset, we can change the helper's position to absolute
3380 // TODO: Still need to figure out a way to make relative sorting possible
3381 this.helper.css("position", "absolute");
3382 this.cssPosition = this.helper.css("position");
3384 $.extend(this.offset, {
3385 click: { //Where the click happened, relative to the element
3386 left: event.pageX - this.offset.left,
3387 top: event.pageY - this.offset.top
3389 parent: this._getParentOffset(),
3390 relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
3393 //Generate the original position
3394 this.originalPosition = this._generatePosition(event);
3395 this.originalPageX = event.pageX;
3396 this.originalPageY = event.pageY;
3398 //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
3399 (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
3401 //Cache the former DOM position
3402 this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] };
3404 //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
3405 if(this.helper[0] != this.currentItem[0]) {
3406 this.currentItem.hide();
3409 //Create the placeholder
3410 this._createPlaceholder();
3412 //Set a containment if given in the options
3413 if(o.containment)
3414 this._setContainment();
3416 if(o.cursor) { // cursor option
3417 if ($('body').css("cursor")) this._storedCursor = $('body').css("cursor");
3418 $('body').css("cursor", o.cursor);
3421 if(o.opacity) { // opacity option
3422 if (this.helper.css("opacity")) this._storedOpacity = this.helper.css("opacity");
3423 this.helper.css("opacity", o.opacity);
3426 if(o.zIndex) { // zIndex option
3427 if (this.helper.css("zIndex")) this._storedZIndex = this.helper.css("zIndex");
3428 this.helper.css("zIndex", o.zIndex);
3431 //Prepare scrolling
3432 if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML')
3433 this.overflowOffset = this.scrollParent.offset();
3435 //Call callbacks
3436 this._trigger("start", event, this._uiHash());
3438 //Recache the helper size
3439 if(!this._preserveHelperProportions)
3440 this._cacheHelperProportions();
3443 //Post 'activate' events to possible containers
3444 if(!noActivation) {
3445 for (var i = this.containers.length - 1; i >= 0; i--) { this.containers[i]._trigger("activate", event, self._uiHash(this)); }
3448 //Prepare possible droppables
3449 if($.ui.ddmanager)
3450 $.ui.ddmanager.current = this;
3452 if ($.ui.ddmanager && !o.dropBehaviour)
3453 $.ui.ddmanager.prepareOffsets(this, event);
3455 this.dragging = true;
3457 this.helper.addClass("ui-sortable-helper");
3458 this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position
3459 return true;
3463 _mouseDrag: function(event) {
3465 //Compute the helpers position
3466 this.position = this._generatePosition(event);
3467 this.positionAbs = this._convertPositionTo("absolute");
3469 if (!this.lastPositionAbs) {
3470 this.lastPositionAbs = this.positionAbs;
3473 //Do scrolling
3474 if(this.options.scroll) {
3475 var o = this.options, scrolled = false;
3476 if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') {
3478 if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
3479 this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed;
3480 else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity)
3481 this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed;
3483 if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
3484 this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed;
3485 else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity)
3486 this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed;
3488 } else {
3490 if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
3491 scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
3492 else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
3493 scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
3495 if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
3496 scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
3497 else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
3498 scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
3502 if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
3503 $.ui.ddmanager.prepareOffsets(this, event);
3506 //Regenerate the absolute position used for position checks
3507 this.positionAbs = this._convertPositionTo("absolute");
3509 //Set the helper position
3510 if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
3511 if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
3513 //Rearrange
3514 for (var i = this.items.length - 1; i >= 0; i--) {
3516 //Cache variables and intersection, continue if no intersection
3517 var item = this.items[i], itemElement = item.item[0], intersection = this._intersectsWithPointer(item);
3518 if (!intersection) continue;
3520 if(itemElement != this.currentItem[0] //cannot intersect with itself
3521 && this.placeholder[intersection == 1 ? "next" : "prev"]()[0] != itemElement //no useless actions that have been done before
3522 && !$.ui.contains(this.placeholder[0], itemElement) //no action if the item moved is the parent of the item checked
3523 && (this.options.type == 'semi-dynamic' ? !$.ui.contains(this.element[0], itemElement) : true)
3524 //&& itemElement.parentNode == this.placeholder[0].parentNode // only rearrange items within the same container
3527 this.direction = intersection == 1 ? "down" : "up";
3529 if (this.options.tolerance == "pointer" || this._intersectsWithSides(item)) {
3530 this._rearrange(event, item);
3531 } else {
3532 break;
3535 this._trigger("change", event, this._uiHash());
3536 break;
3540 //Post events to containers
3541 this._contactContainers(event);
3543 //Interconnect with droppables
3544 if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
3546 //Call callbacks
3547 this._trigger('sort', event, this._uiHash());
3549 this.lastPositionAbs = this.positionAbs;
3550 return false;
3554 _mouseStop: function(event, noPropagation) {
3556 if(!event) return;
3558 //If we are using droppables, inform the manager about the drop
3559 if ($.ui.ddmanager && !this.options.dropBehaviour)
3560 $.ui.ddmanager.drop(this, event);
3562 if(this.options.revert) {
3563 var self = this;
3564 var cur = self.placeholder.offset();
3566 self.reverting = true;
3568 $(this.helper).animate({
3569 left: cur.left - this.offset.parent.left - self.margins.left + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollLeft),
3570 top: cur.top - this.offset.parent.top - self.margins.top + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollTop)
3571 }, parseInt(this.options.revert, 10) || 500, function() {
3572 self._clear(event);
3574 } else {
3575 this._clear(event, noPropagation);
3578 return false;
3582 cancel: function() {
3584 var self = this;
3586 if(this.dragging) {
3588 this._mouseUp({ target: null });
3590 if(this.options.helper == "original")
3591 this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
3592 else
3593 this.currentItem.show();
3595 //Post deactivating events to containers
3596 for (var i = this.containers.length - 1; i >= 0; i--){
3597 this.containers[i]._trigger("deactivate", null, self._uiHash(this));
3598 if(this.containers[i].containerCache.over) {
3599 this.containers[i]._trigger("out", null, self._uiHash(this));
3600 this.containers[i].containerCache.over = 0;
3606 if (this.placeholder) {
3607 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
3608 if(this.placeholder[0].parentNode) this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
3609 if(this.options.helper != "original" && this.helper && this.helper[0].parentNode) this.helper.remove();
3611 $.extend(this, {
3612 helper: null,
3613 dragging: false,
3614 reverting: false,
3615 _noFinalSort: null
3618 if(this.domPosition.prev) {
3619 $(this.domPosition.prev).after(this.currentItem);
3620 } else {
3621 $(this.domPosition.parent).prepend(this.currentItem);
3625 return this;
3629 serialize: function(o) {
3631 var items = this._getItemsAsjQuery(o && o.connected);
3632 var str = []; o = o || {};
3634 $(items).each(function() {
3635 var res = ($(o.item || this).attr(o.attribute || 'id') || '').match(o.expression || (/(.+)[-=_](.+)/));
3636 if(res) str.push((o.key || res[1]+'[]')+'='+(o.key && o.expression ? res[1] : res[2]));
3639 if(!str.length && o.key) {
3640 str.push(o.key + '=');
3643 return str.join('&');
3647 toArray: function(o) {
3649 var items = this._getItemsAsjQuery(o && o.connected);
3650 var ret = []; o = o || {};
3652 items.each(function() { ret.push($(o.item || this).attr(o.attribute || 'id') || ''); });
3653 return ret;
3657 /* Be careful with the following core functions */
3658 _intersectsWith: function(item) {
3660 var x1 = this.positionAbs.left,
3661 x2 = x1 + this.helperProportions.width,
3662 y1 = this.positionAbs.top,
3663 y2 = y1 + this.helperProportions.height;
3665 var l = item.left,
3666 r = l + item.width,
3667 t = item.top,
3668 b = t + item.height;
3670 var dyClick = this.offset.click.top,
3671 dxClick = this.offset.click.left;
3673 var isOverElement = (y1 + dyClick) > t && (y1 + dyClick) < b && (x1 + dxClick) > l && (x1 + dxClick) < r;
3675 if( this.options.tolerance == "pointer"
3676 || this.options.forcePointerForContainers
3677 || (this.options.tolerance != "pointer" && this.helperProportions[this.floating ? 'width' : 'height'] > item[this.floating ? 'width' : 'height'])
3679 return isOverElement;
3680 } else {
3682 return (l < x1 + (this.helperProportions.width / 2) // Right Half
3683 && x2 - (this.helperProportions.width / 2) < r // Left Half
3684 && t < y1 + (this.helperProportions.height / 2) // Bottom Half
3685 && y2 - (this.helperProportions.height / 2) < b ); // Top Half
3690 _intersectsWithPointer: function(item) {
3692 var isOverElementHeight = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height),
3693 isOverElementWidth = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width),
3694 isOverElement = isOverElementHeight && isOverElementWidth,
3695 verticalDirection = this._getDragVerticalDirection(),
3696 horizontalDirection = this._getDragHorizontalDirection();
3698 if (!isOverElement)
3699 return false;
3701 return this.floating ?
3702 ( ((horizontalDirection && horizontalDirection == "right") || verticalDirection == "down") ? 2 : 1 )
3703 : ( verticalDirection && (verticalDirection == "down" ? 2 : 1) );
3707 _intersectsWithSides: function(item) {
3709 var isOverBottomHalf = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height),
3710 isOverRightHalf = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width),
3711 verticalDirection = this._getDragVerticalDirection(),
3712 horizontalDirection = this._getDragHorizontalDirection();
3714 if (this.floating && horizontalDirection) {
3715 return ((horizontalDirection == "right" && isOverRightHalf) || (horizontalDirection == "left" && !isOverRightHalf));
3716 } else {
3717 return verticalDirection && ((verticalDirection == "down" && isOverBottomHalf) || (verticalDirection == "up" && !isOverBottomHalf));
3722 _getDragVerticalDirection: function() {
3723 var delta = this.positionAbs.top - this.lastPositionAbs.top;
3724 return delta != 0 && (delta > 0 ? "down" : "up");
3727 _getDragHorizontalDirection: function() {
3728 var delta = this.positionAbs.left - this.lastPositionAbs.left;
3729 return delta != 0 && (delta > 0 ? "right" : "left");
3732 refresh: function(event) {
3733 this._refreshItems(event);
3734 this.refreshPositions();
3735 return this;
3738 _connectWith: function() {
3739 var options = this.options;
3740 return options.connectWith.constructor == String
3741 ? [options.connectWith]
3742 : options.connectWith;
3745 _getItemsAsjQuery: function(connected) {
3747 var self = this;
3748 var items = [];
3749 var queries = [];
3750 var connectWith = this._connectWith();
3752 if(connectWith && connected) {
3753 for (var i = connectWith.length - 1; i >= 0; i--){
3754 var cur = $(connectWith[i]);
3755 for (var j = cur.length - 1; j >= 0; j--){
3756 var inst = $.data(cur[j], 'sortable');
3757 if(inst && inst != this && !inst.options.disabled) {
3758 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]);
3764 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]);
3766 for (var i = queries.length - 1; i >= 0; i--){
3767 queries[i][0].each(function() {
3768 items.push(this);
3772 return $(items);
3776 _removeCurrentsFromItems: function() {
3778 var list = this.currentItem.find(":data(sortable-item)");
3780 for (var i=0; i < this.items.length; i++) {
3782 for (var j=0; j < list.length; j++) {
3783 if(list[j] == this.items[i].item[0])
3784 this.items.splice(i,1);
3791 _refreshItems: function(event) {
3793 this.items = [];
3794 this.containers = [this];
3795 var items = this.items;
3796 var self = this;
3797 var queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]];
3798 var connectWith = this._connectWith();
3800 if(connectWith) {
3801 for (var i = connectWith.length - 1; i >= 0; i--){
3802 var cur = $(connectWith[i]);
3803 for (var j = cur.length - 1; j >= 0; j--){
3804 var inst = $.data(cur[j], 'sortable');
3805 if(inst && inst != this && !inst.options.disabled) {
3806 queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]);
3807 this.containers.push(inst);
3813 for (var i = queries.length - 1; i >= 0; i--) {
3814 var targetData = queries[i][1];
3815 var _queries = queries[i][0];
3817 for (var j=0, queriesLength = _queries.length; j < queriesLength; j++) {
3818 var item = $(_queries[j]);
3820 item.data('sortable-item', targetData); // Data for target checking (mouse manager)
3822 items.push({
3823 item: item,
3824 instance: targetData,
3825 width: 0, height: 0,
3826 left: 0, top: 0
3833 refreshPositions: function(fast) {
3835 //This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change
3836 if(this.offsetParent && this.helper) {
3837 this.offset.parent = this._getParentOffset();
3840 for (var i = this.items.length - 1; i >= 0; i--){
3841 var item = this.items[i];
3843 //We ignore calculating positions of all connected containers when we're not over them
3844 if(item.instance != this.currentContainer && this.currentContainer && item.item[0] != this.currentItem[0])
3845 continue;
3847 var t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item;
3849 if (!fast) {
3850 item.width = t.outerWidth();
3851 item.height = t.outerHeight();
3854 var p = t.offset();
3855 item.left = p.left;
3856 item.top = p.top;
3859 if(this.options.custom && this.options.custom.refreshContainers) {
3860 this.options.custom.refreshContainers.call(this);
3861 } else {
3862 for (var i = this.containers.length - 1; i >= 0; i--){
3863 var p = this.containers[i].element.offset();
3864 this.containers[i].containerCache.left = p.left;
3865 this.containers[i].containerCache.top = p.top;
3866 this.containers[i].containerCache.width = this.containers[i].element.outerWidth();
3867 this.containers[i].containerCache.height = this.containers[i].element.outerHeight();
3871 return this;
3874 _createPlaceholder: function(that) {
3876 var self = that || this, o = self.options;
3878 if(!o.placeholder || o.placeholder.constructor == String) {
3879 var className = o.placeholder;
3880 o.placeholder = {
3881 element: function() {
3883 var el = $(document.createElement(self.currentItem[0].nodeName))
3884 .addClass(className || self.currentItem[0].className+" ui-sortable-placeholder")
3885 .removeClass("ui-sortable-helper")[0];
3887 if(!className)
3888 el.style.visibility = "hidden";
3890 return el;
3892 update: function(container, p) {
3894 // 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that
3895 // 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified
3896 if(className && !o.forcePlaceholderSize) return;
3898 //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
3899 if(!p.height()) { p.height(self.currentItem.innerHeight() - parseInt(self.currentItem.css('paddingTop')||0, 10) - parseInt(self.currentItem.css('paddingBottom')||0, 10)); };
3900 if(!p.width()) { p.width(self.currentItem.innerWidth() - parseInt(self.currentItem.css('paddingLeft')||0, 10) - parseInt(self.currentItem.css('paddingRight')||0, 10)); };
3905 //Create the placeholder
3906 self.placeholder = $(o.placeholder.element.call(self.element, self.currentItem));
3908 //Append it after the actual current item
3909 self.currentItem.after(self.placeholder);
3911 //Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
3912 o.placeholder.update(self, self.placeholder);
3916 _contactContainers: function(event) {
3918 // get innermost container that intersects with item
3919 var innermostContainer = null, innermostIndex = null;
3922 for (var i = this.containers.length - 1; i >= 0; i--){
3924 // never consider a container that's located within the item itself
3925 if($.ui.contains(this.currentItem[0], this.containers[i].element[0]))
3926 continue;
3928 if(this._intersectsWith(this.containers[i].containerCache)) {
3930 // if we've already found a container and it's more "inner" than this, then continue
3931 if(innermostContainer && $.ui.contains(this.containers[i].element[0], innermostContainer.element[0]))
3932 continue;
3934 innermostContainer = this.containers[i];
3935 innermostIndex = i;
3937 } else {
3938 // container doesn't intersect. trigger "out" event if necessary
3939 if(this.containers[i].containerCache.over) {
3940 this.containers[i]._trigger("out", event, this._uiHash(this));
3941 this.containers[i].containerCache.over = 0;
3947 // if no intersecting containers found, return
3948 if(!innermostContainer) return;
3950 // move the item into the container if it's not there already
3951 if(this.containers.length === 1) {
3952 this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
3953 this.containers[innermostIndex].containerCache.over = 1;
3954 } else if(this.currentContainer != this.containers[innermostIndex]) {
3956 //When entering a new container, we will find the item with the least distance and append our item near it
3957 var dist = 10000; var itemWithLeastDistance = null; var base = this.positionAbs[this.containers[innermostIndex].floating ? 'left' : 'top'];
3958 for (var j = this.items.length - 1; j >= 0; j--) {
3959 if(!$.ui.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) continue;
3960 var cur = this.items[j][this.containers[innermostIndex].floating ? 'left' : 'top'];
3961 if(Math.abs(cur - base) < dist) {
3962 dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j];
3966 if(!itemWithLeastDistance && !this.options.dropOnEmpty) //Check if dropOnEmpty is enabled
3967 return;
3969 this.currentContainer = this.containers[innermostIndex];
3970 itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true);
3971 this._trigger("change", event, this._uiHash());
3972 this.containers[innermostIndex]._trigger("change", event, this._uiHash(this));
3974 //Update the placeholder
3975 this.options.placeholder.update(this.currentContainer, this.placeholder);
3977 this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
3978 this.containers[innermostIndex].containerCache.over = 1;
3984 _createHelper: function(event) {
3986 var o = this.options;
3987 var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper == 'clone' ? this.currentItem.clone() : this.currentItem);
3989 if(!helper.parents('body').length) //Add the helper to the DOM if that didn't happen already
3990 $(o.appendTo != 'parent' ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]);
3992 if(helper[0] == this.currentItem[0])
3993 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") };
3995 if(helper[0].style.width == '' || o.forceHelperSize) helper.width(this.currentItem.width());
3996 if(helper[0].style.height == '' || o.forceHelperSize) helper.height(this.currentItem.height());
3998 return helper;
4002 _adjustOffsetFromHelper: function(obj) {
4003 if (typeof obj == 'string') {
4004 obj = obj.split(' ');
4006 if ($.isArray(obj)) {
4007 obj = {left: +obj[0], top: +obj[1] || 0};
4009 if ('left' in obj) {
4010 this.offset.click.left = obj.left + this.margins.left;
4012 if ('right' in obj) {
4013 this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
4015 if ('top' in obj) {
4016 this.offset.click.top = obj.top + this.margins.top;
4018 if ('bottom' in obj) {
4019 this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
4023 _getParentOffset: function() {
4026 //Get the offsetParent and cache its position
4027 this.offsetParent = this.helper.offsetParent();
4028 var po = this.offsetParent.offset();
4030 // This is a special case where we need to modify a offset calculated on start, since the following happened:
4031 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
4032 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
4033 // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
4034 if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) {
4035 po.left += this.scrollParent.scrollLeft();
4036 po.top += this.scrollParent.scrollTop();
4039 if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
4040 || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix
4041 po = { top: 0, left: 0 };
4043 return {
4044 top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
4045 left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
4050 _getRelativeOffset: function() {
4052 if(this.cssPosition == "relative") {
4053 var p = this.currentItem.position();
4054 return {
4055 top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
4056 left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
4058 } else {
4059 return { top: 0, left: 0 };
4064 _cacheMargins: function() {
4065 this.margins = {
4066 left: (parseInt(this.currentItem.css("marginLeft"),10) || 0),
4067 top: (parseInt(this.currentItem.css("marginTop"),10) || 0)
4071 _cacheHelperProportions: function() {
4072 this.helperProportions = {
4073 width: this.helper.outerWidth(),
4074 height: this.helper.outerHeight()
4078 _setContainment: function() {
4080 var o = this.options;
4081 if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
4082 if(o.containment == 'document' || o.containment == 'window') this.containment = [
4083 0 - this.offset.relative.left - this.offset.parent.left,
4084 0 - this.offset.relative.top - this.offset.parent.top,
4085 $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
4086 ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
4089 if(!(/^(document|window|parent)$/).test(o.containment)) {
4090 var ce = $(o.containment)[0];
4091 var co = $(o.containment).offset();
4092 var over = ($(ce).css("overflow") != 'hidden');
4094 this.containment = [
4095 co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
4096 co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
4097 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,
4098 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
4104 _convertPositionTo: function(d, pos) {
4106 if(!pos) pos = this.position;
4107 var mod = d == "absolute" ? 1 : -1;
4108 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);
4110 return {
4111 top: (
4112 pos.top // The absolute mouse position
4113 + this.offset.relative.top * mod // Only for relative positioned nodes: Relative offset from element to offset parent
4114 + this.offset.parent.top * mod // The offsetParent's offset without borders (offset + border)
4115 - ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
4117 left: (
4118 pos.left // The absolute mouse position
4119 + this.offset.relative.left * mod // Only for relative positioned nodes: Relative offset from element to offset parent
4120 + this.offset.parent.left * mod // The offsetParent's offset without borders (offset + border)
4121 - ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
4127 _generatePosition: function(event) {
4129 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);
4131 // This is another very weird special case that only happens for relative elements:
4132 // 1. If the css position is relative
4133 // 2. and the scroll parent is the document or similar to the offset parent
4134 // we have to refresh the relative offset during the scroll so there are no jumps
4135 if(this.cssPosition == 'relative' && !(this.scrollParent[0] != document && this.scrollParent[0] != this.offsetParent[0])) {
4136 this.offset.relative = this._getRelativeOffset();
4139 var pageX = event.pageX;
4140 var pageY = event.pageY;
4143 * - Position constraining -
4144 * Constrain the position to a mix of grid, containment.
4147 if(this.originalPosition) { //If we are not dragging yet, we won't check for options
4149 if(this.containment) {
4150 if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left;
4151 if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top;
4152 if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left;
4153 if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top;
4156 if(o.grid) {
4157 var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
4158 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;
4160 var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
4161 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;
4166 return {
4167 top: (
4168 pageY // The absolute mouse position
4169 - this.offset.click.top // Click offset (relative to the element)
4170 - this.offset.relative.top // Only for relative positioned nodes: Relative offset from element to offset parent
4171 - this.offset.parent.top // The offsetParent's offset without borders (offset + border)
4172 + ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
4174 left: (
4175 pageX // The absolute mouse position
4176 - this.offset.click.left // Click offset (relative to the element)
4177 - this.offset.relative.left // Only for relative positioned nodes: Relative offset from element to offset parent
4178 - this.offset.parent.left // The offsetParent's offset without borders (offset + border)
4179 + ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
4185 _rearrange: function(event, i, a, hardRefresh) {
4187 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));
4189 //Various things done here to improve the performance:
4190 // 1. we create a setTimeout, that calls refreshPositions
4191 // 2. on the instance, we have a counter variable, that get's higher after every append
4192 // 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same
4193 // 4. this lets only the last addition to the timeout stack through
4194 this.counter = this.counter ? ++this.counter : 1;
4195 var self = this, counter = this.counter;
4197 window.setTimeout(function() {
4198 if(counter == self.counter) self.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove
4199 },0);
4203 _clear: function(event, noPropagation) {
4205 this.reverting = false;
4206 // We delay all events that have to be triggered to after the point where the placeholder has been removed and
4207 // everything else normalized again
4208 var delayedTriggers = [], self = this;
4210 // We first have to update the dom position of the actual currentItem
4211 // Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088)
4212 if(!this._noFinalSort && this.currentItem.parent().length) this.placeholder.before(this.currentItem);
4213 this._noFinalSort = null;
4215 if(this.helper[0] == this.currentItem[0]) {
4216 for(var i in this._storedCSS) {
4217 if(this._storedCSS[i] == 'auto' || this._storedCSS[i] == 'static') this._storedCSS[i] = '';
4219 this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
4220 } else {
4221 this.currentItem.show();
4224 if(this.fromOutside && !noPropagation) delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); });
4225 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
4226 if(!$.ui.contains(this.element[0], this.currentItem[0])) { //Node was moved out of the current element
4227 if(!noPropagation) delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); });
4228 for (var i = this.containers.length - 1; i >= 0; i--){
4229 if($.ui.contains(this.containers[i].element[0], this.currentItem[0]) && !noPropagation) {
4230 delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); }; }).call(this, this.containers[i]));
4231 delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this)); }; }).call(this, this.containers[i]));
4236 //Post events to containers
4237 for (var i = this.containers.length - 1; i >= 0; i--){
4238 if(!noPropagation) delayedTriggers.push((function(c) { return function(event) { c._trigger("deactivate", event, this._uiHash(this)); }; }).call(this, this.containers[i]));
4239 if(this.containers[i].containerCache.over) {
4240 delayedTriggers.push((function(c) { return function(event) { c._trigger("out", event, this._uiHash(this)); }; }).call(this, this.containers[i]));
4241 this.containers[i].containerCache.over = 0;
4245 //Do what was originally in plugins
4246 if(this._storedCursor) $('body').css("cursor", this._storedCursor); //Reset cursor
4247 if(this._storedOpacity) this.helper.css("opacity", this._storedOpacity); //Reset opacity
4248 if(this._storedZIndex) this.helper.css("zIndex", this._storedZIndex == 'auto' ? '' : this._storedZIndex); //Reset z-index
4250 this.dragging = false;
4251 if(this.cancelHelperRemoval) {
4252 if(!noPropagation) {
4253 this._trigger("beforeStop", event, this._uiHash());
4254 for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events
4255 this._trigger("stop", event, this._uiHash());
4257 return false;
4260 if(!noPropagation) this._trigger("beforeStop", event, this._uiHash());
4262 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
4263 this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
4265 if(this.helper[0] != this.currentItem[0]) this.helper.remove(); this.helper = null;
4267 if(!noPropagation) {
4268 for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events
4269 this._trigger("stop", event, this._uiHash());
4272 this.fromOutside = false;
4273 return true;
4277 _trigger: function() {
4278 if ($.Widget.prototype._trigger.apply(this, arguments) === false) {
4279 this.cancel();
4283 _uiHash: function(inst) {
4284 var self = inst || this;
4285 return {
4286 helper: self.helper,
4287 placeholder: self.placeholder || $([]),
4288 position: self.position,
4289 originalPosition: self.originalPosition,
4290 offset: self.positionAbs,
4291 item: self.currentItem,
4292 sender: inst ? inst.element : null
4298 $.extend($.ui.sortable, {
4299 version: "1.8.16"
4302 })(jQuery);
4304 * jQuery UI Accordion 1.8.16
4306 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
4307 * Dual licensed under the MIT or GPL Version 2 licenses.
4308 * http://jquery.org/license
4310 * http://docs.jquery.com/UI/Accordion
4312 * Depends:
4313 * jquery.ui.core.js
4314 * jquery.ui.widget.js
4316 (function( $, undefined ) {
4318 $.widget( "ui.accordion", {
4319 options: {
4320 active: 0,
4321 animated: "slide",
4322 autoHeight: true,
4323 clearStyle: false,
4324 collapsible: false,
4325 event: "click",
4326 fillSpace: false,
4327 header: "> li > :first-child,> :not(li):even",
4328 icons: {
4329 header: "ui-icon-triangle-1-e",
4330 headerSelected: "ui-icon-triangle-1-s"
4332 navigation: false,
4333 navigationFilter: function() {
4334 return this.href.toLowerCase() === location.href.toLowerCase();
4338 _create: function() {
4339 var self = this,
4340 options = self.options;
4342 self.running = 0;
4344 self.element
4345 .addClass( "ui-accordion ui-widget ui-helper-reset" )
4346 // in lack of child-selectors in CSS
4347 // we need to mark top-LIs in a UL-accordion for some IE-fix
4348 .children( "li" )
4349 .addClass( "ui-accordion-li-fix" );
4351 self.headers = self.element.find( options.header )
4352 .addClass( "ui-accordion-header ui-helper-reset ui-state-default ui-corner-all" )
4353 .bind( "mouseenter.accordion", function() {
4354 if ( options.disabled ) {
4355 return;
4357 $( this ).addClass( "ui-state-hover" );
4359 .bind( "mouseleave.accordion", function() {
4360 if ( options.disabled ) {
4361 return;
4363 $( this ).removeClass( "ui-state-hover" );
4365 .bind( "focus.accordion", function() {
4366 if ( options.disabled ) {
4367 return;
4369 $( this ).addClass( "ui-state-focus" );
4371 .bind( "blur.accordion", function() {
4372 if ( options.disabled ) {
4373 return;
4375 $( this ).removeClass( "ui-state-focus" );
4378 self.headers.next()
4379 .addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" );
4381 if ( options.navigation ) {
4382 var current = self.element.find( "a" ).filter( options.navigationFilter ).eq( 0 );
4383 if ( current.length ) {
4384 var header = current.closest( ".ui-accordion-header" );
4385 if ( header.length ) {
4386 // anchor within header
4387 self.active = header;
4388 } else {
4389 // anchor within content
4390 self.active = current.closest( ".ui-accordion-content" ).prev();
4395 self.active = self._findActive( self.active || options.active )
4396 .addClass( "ui-state-default ui-state-active" )
4397 .toggleClass( "ui-corner-all" )
4398 .toggleClass( "ui-corner-top" );
4399 self.active.next().addClass( "ui-accordion-content-active" );
4401 self._createIcons();
4402 self.resize();
4404 // ARIA
4405 self.element.attr( "role", "tablist" );
4407 self.headers
4408 .attr( "role", "tab" )
4409 .bind( "keydown.accordion", function( event ) {
4410 return self._keydown( event );
4412 .next()
4413 .attr( "role", "tabpanel" );
4415 self.headers
4416 .not( self.active || "" )
4417 .attr({
4418 "aria-expanded": "false",
4419 "aria-selected": "false",
4420 tabIndex: -1
4422 .next()
4423 .hide();
4425 // make sure at least one header is in the tab order
4426 if ( !self.active.length ) {
4427 self.headers.eq( 0 ).attr( "tabIndex", 0 );
4428 } else {
4429 self.active
4430 .attr({
4431 "aria-expanded": "true",
4432 "aria-selected": "true",
4433 tabIndex: 0
4437 // only need links in tab order for Safari
4438 if ( !$.browser.safari ) {
4439 self.headers.find( "a" ).attr( "tabIndex", -1 );
4442 if ( options.event ) {
4443 self.headers.bind( options.event.split(" ").join(".accordion ") + ".accordion", function(event) {
4444 self._clickHandler.call( self, event, this );
4445 event.preventDefault();
4450 _createIcons: function() {
4451 var options = this.options;
4452 if ( options.icons ) {
4453 $( "<span></span>" )
4454 .addClass( "ui-icon " + options.icons.header )
4455 .prependTo( this.headers );
4456 this.active.children( ".ui-icon" )
4457 .toggleClass(options.icons.header)
4458 .toggleClass(options.icons.headerSelected);
4459 this.element.addClass( "ui-accordion-icons" );
4463 _destroyIcons: function() {
4464 this.headers.children( ".ui-icon" ).remove();
4465 this.element.removeClass( "ui-accordion-icons" );
4468 destroy: function() {
4469 var options = this.options;
4471 this.element
4472 .removeClass( "ui-accordion ui-widget ui-helper-reset" )
4473 .removeAttr( "role" );
4475 this.headers
4476 .unbind( ".accordion" )
4477 .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" )
4478 .removeAttr( "role" )
4479 .removeAttr( "aria-expanded" )
4480 .removeAttr( "aria-selected" )
4481 .removeAttr( "tabIndex" );
4483 this.headers.find( "a" ).removeAttr( "tabIndex" );
4484 this._destroyIcons();
4485 var contents = this.headers.next()
4486 .css( "display", "" )
4487 .removeAttr( "role" )
4488 .removeClass( "ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-accordion-disabled ui-state-disabled" );
4489 if ( options.autoHeight || options.fillHeight ) {
4490 contents.css( "height", "" );
4493 return $.Widget.prototype.destroy.call( this );
4496 _setOption: function( key, value ) {
4497 $.Widget.prototype._setOption.apply( this, arguments );
4499 if ( key == "active" ) {
4500 this.activate( value );
4502 if ( key == "icons" ) {
4503 this._destroyIcons();
4504 if ( value ) {
4505 this._createIcons();
4508 // #5332 - opacity doesn't cascade to positioned elements in IE
4509 // so we need to add the disabled class to the headers and panels
4510 if ( key == "disabled" ) {
4511 this.headers.add(this.headers.next())
4512 [ value ? "addClass" : "removeClass" ](
4513 "ui-accordion-disabled ui-state-disabled" );
4517 _keydown: function( event ) {
4518 if ( this.options.disabled || event.altKey || event.ctrlKey ) {
4519 return;
4522 var keyCode = $.ui.keyCode,
4523 length = this.headers.length,
4524 currentIndex = this.headers.index( event.target ),
4525 toFocus = false;
4527 switch ( event.keyCode ) {
4528 case keyCode.RIGHT:
4529 case keyCode.DOWN:
4530 toFocus = this.headers[ ( currentIndex + 1 ) % length ];
4531 break;
4532 case keyCode.LEFT:
4533 case keyCode.UP:
4534 toFocus = this.headers[ ( currentIndex - 1 + length ) % length ];
4535 break;
4536 case keyCode.SPACE:
4537 case keyCode.ENTER:
4538 this._clickHandler( { target: event.target }, event.target );
4539 event.preventDefault();
4542 if ( toFocus ) {
4543 $( event.target ).attr( "tabIndex", -1 );
4544 $( toFocus ).attr( "tabIndex", 0 );
4545 toFocus.focus();
4546 return false;
4549 return true;
4552 resize: function() {
4553 var options = this.options,
4554 maxHeight;
4556 if ( options.fillSpace ) {
4557 if ( $.browser.msie ) {
4558 var defOverflow = this.element.parent().css( "overflow" );
4559 this.element.parent().css( "overflow", "hidden");
4561 maxHeight = this.element.parent().height();
4562 if ($.browser.msie) {
4563 this.element.parent().css( "overflow", defOverflow );
4566 this.headers.each(function() {
4567 maxHeight -= $( this ).outerHeight( true );
4570 this.headers.next()
4571 .each(function() {
4572 $( this ).height( Math.max( 0, maxHeight -
4573 $( this ).innerHeight() + $( this ).height() ) );
4575 .css( "overflow", "auto" );
4576 } else if ( options.autoHeight ) {
4577 maxHeight = 0;
4578 this.headers.next()
4579 .each(function() {
4580 maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() );
4582 .height( maxHeight );
4585 return this;
4588 activate: function( index ) {
4589 // TODO this gets called on init, changing the option without an explicit call for that
4590 this.options.active = index;
4591 // call clickHandler with custom event
4592 var active = this._findActive( index )[ 0 ];
4593 this._clickHandler( { target: active }, active );
4595 return this;
4598 _findActive: function( selector ) {
4599 return selector
4600 ? typeof selector === "number"
4601 ? this.headers.filter( ":eq(" + selector + ")" )
4602 : this.headers.not( this.headers.not( selector ) )
4603 : selector === false
4604 ? $( [] )
4605 : this.headers.filter( ":eq(0)" );
4608 // TODO isn't event.target enough? why the separate target argument?
4609 _clickHandler: function( event, target ) {
4610 var options = this.options;
4611 if ( options.disabled ) {
4612 return;
4615 // called only when using activate(false) to close all parts programmatically
4616 if ( !event.target ) {
4617 if ( !options.collapsible ) {
4618 return;
4620 this.active
4621 .removeClass( "ui-state-active ui-corner-top" )
4622 .addClass( "ui-state-default ui-corner-all" )
4623 .children( ".ui-icon" )
4624 .removeClass( options.icons.headerSelected )
4625 .addClass( options.icons.header );
4626 this.active.next().addClass( "ui-accordion-content-active" );
4627 var toHide = this.active.next(),
4628 data = {
4629 options: options,
4630 newHeader: $( [] ),
4631 oldHeader: options.active,
4632 newContent: $( [] ),
4633 oldContent: toHide
4635 toShow = ( this.active = $( [] ) );
4636 this._toggle( toShow, toHide, data );
4637 return;
4640 // get the click target
4641 var clicked = $( event.currentTarget || target ),
4642 clickedIsActive = clicked[0] === this.active[0];
4644 // TODO the option is changed, is that correct?
4645 // TODO if it is correct, shouldn't that happen after determining that the click is valid?
4646 options.active = options.collapsible && clickedIsActive ?
4647 false :
4648 this.headers.index( clicked );
4650 // if animations are still active, or the active header is the target, ignore click
4651 if ( this.running || ( !options.collapsible && clickedIsActive ) ) {
4652 return;
4655 // find elements to show and hide
4656 var active = this.active,
4657 toShow = clicked.next(),
4658 toHide = this.active.next(),
4659 data = {
4660 options: options,
4661 newHeader: clickedIsActive && options.collapsible ? $([]) : clicked,
4662 oldHeader: this.active,
4663 newContent: clickedIsActive && options.collapsible ? $([]) : toShow,
4664 oldContent: toHide
4666 down = this.headers.index( this.active[0] ) > this.headers.index( clicked[0] );
4668 // when the call to ._toggle() comes after the class changes
4669 // it causes a very odd bug in IE 8 (see #6720)
4670 this.active = clickedIsActive ? $([]) : clicked;
4671 this._toggle( toShow, toHide, data, clickedIsActive, down );
4673 // switch classes
4674 active
4675 .removeClass( "ui-state-active ui-corner-top" )
4676 .addClass( "ui-state-default ui-corner-all" )
4677 .children( ".ui-icon" )
4678 .removeClass( options.icons.headerSelected )
4679 .addClass( options.icons.header );
4680 if ( !clickedIsActive ) {
4681 clicked
4682 .removeClass( "ui-state-default ui-corner-all" )
4683 .addClass( "ui-state-active ui-corner-top" )
4684 .children( ".ui-icon" )
4685 .removeClass( options.icons.header )
4686 .addClass( options.icons.headerSelected );
4687 clicked
4688 .next()
4689 .addClass( "ui-accordion-content-active" );
4692 return;
4695 _toggle: function( toShow, toHide, data, clickedIsActive, down ) {
4696 var self = this,
4697 options = self.options;
4699 self.toShow = toShow;
4700 self.toHide = toHide;
4701 self.data = data;
4703 var complete = function() {
4704 if ( !self ) {
4705 return;
4707 return self._completed.apply( self, arguments );
4710 // trigger changestart event
4711 self._trigger( "changestart", null, self.data );
4713 // count elements to animate
4714 self.running = toHide.size() === 0 ? toShow.size() : toHide.size();
4716 if ( options.animated ) {
4717 var animOptions = {};
4719 if ( options.collapsible && clickedIsActive ) {
4720 animOptions = {
4721 toShow: $( [] ),
4722 toHide: toHide,
4723 complete: complete,
4724 down: down,
4725 autoHeight: options.autoHeight || options.fillSpace
4727 } else {
4728 animOptions = {
4729 toShow: toShow,
4730 toHide: toHide,
4731 complete: complete,
4732 down: down,
4733 autoHeight: options.autoHeight || options.fillSpace
4737 if ( !options.proxied ) {
4738 options.proxied = options.animated;
4741 if ( !options.proxiedDuration ) {
4742 options.proxiedDuration = options.duration;
4745 options.animated = $.isFunction( options.proxied ) ?
4746 options.proxied( animOptions ) :
4747 options.proxied;
4749 options.duration = $.isFunction( options.proxiedDuration ) ?
4750 options.proxiedDuration( animOptions ) :
4751 options.proxiedDuration;
4753 var animations = $.ui.accordion.animations,
4754 duration = options.duration,
4755 easing = options.animated;
4757 if ( easing && !animations[ easing ] && !$.easing[ easing ] ) {
4758 easing = "slide";
4760 if ( !animations[ easing ] ) {
4761 animations[ easing ] = function( options ) {
4762 this.slide( options, {
4763 easing: easing,
4764 duration: duration || 700
4769 animations[ easing ]( animOptions );
4770 } else {
4771 if ( options.collapsible && clickedIsActive ) {
4772 toShow.toggle();
4773 } else {
4774 toHide.hide();
4775 toShow.show();
4778 complete( true );
4781 // TODO assert that the blur and focus triggers are really necessary, remove otherwise
4782 toHide.prev()
4783 .attr({
4784 "aria-expanded": "false",
4785 "aria-selected": "false",
4786 tabIndex: -1
4788 .blur();
4789 toShow.prev()
4790 .attr({
4791 "aria-expanded": "true",
4792 "aria-selected": "true",
4793 tabIndex: 0
4795 .focus();
4798 _completed: function( cancel ) {
4799 this.running = cancel ? 0 : --this.running;
4800 if ( this.running ) {
4801 return;
4804 if ( this.options.clearStyle ) {
4805 this.toShow.add( this.toHide ).css({
4806 height: "",
4807 overflow: ""
4811 // other classes are removed before the animation; this one needs to stay until completed
4812 this.toHide.removeClass( "ui-accordion-content-active" );
4813 // Work around for rendering bug in IE (#5421)
4814 if ( this.toHide.length ) {
4815 this.toHide.parent()[0].className = this.toHide.parent()[0].className;
4818 this._trigger( "change", null, this.data );
4822 $.extend( $.ui.accordion, {
4823 version: "1.8.16",
4824 animations: {
4825 slide: function( options, additions ) {
4826 options = $.extend({
4827 easing: "swing",
4828 duration: 300
4829 }, options, additions );
4830 if ( !options.toHide.size() ) {
4831 options.toShow.animate({
4832 height: "show",
4833 paddingTop: "show",
4834 paddingBottom: "show"
4835 }, options );
4836 return;
4838 if ( !options.toShow.size() ) {
4839 options.toHide.animate({
4840 height: "hide",
4841 paddingTop: "hide",
4842 paddingBottom: "hide"
4843 }, options );
4844 return;
4846 var overflow = options.toShow.css( "overflow" ),
4847 percentDone = 0,
4848 showProps = {},
4849 hideProps = {},
4850 fxAttrs = [ "height", "paddingTop", "paddingBottom" ],
4851 originalWidth;
4852 // fix width before calculating height of hidden element
4853 var s = options.toShow;
4854 originalWidth = s[0].style.width;
4855 s.width( parseInt( s.parent().width(), 10 )
4856 - parseInt( s.css( "paddingLeft" ), 10 )
4857 - parseInt( s.css( "paddingRight" ), 10 )
4858 - ( parseInt( s.css( "borderLeftWidth" ), 10 ) || 0 )
4859 - ( parseInt( s.css( "borderRightWidth" ), 10) || 0 ) );
4861 $.each( fxAttrs, function( i, prop ) {
4862 hideProps[ prop ] = "hide";
4864 var parts = ( "" + $.css( options.toShow[0], prop ) ).match( /^([\d+-.]+)(.*)$/ );
4865 showProps[ prop ] = {
4866 value: parts[ 1 ],
4867 unit: parts[ 2 ] || "px"
4870 options.toShow.css({ height: 0, overflow: "hidden" }).show();
4871 options.toHide
4872 .filter( ":hidden" )
4873 .each( options.complete )
4874 .end()
4875 .filter( ":visible" )
4876 .animate( hideProps, {
4877 step: function( now, settings ) {
4878 // only calculate the percent when animating height
4879 // IE gets very inconsistent results when animating elements
4880 // with small values, which is common for padding
4881 if ( settings.prop == "height" ) {
4882 percentDone = ( settings.end - settings.start === 0 ) ? 0 :
4883 ( settings.now - settings.start ) / ( settings.end - settings.start );
4886 options.toShow[ 0 ].style[ settings.prop ] =
4887 ( percentDone * showProps[ settings.prop ].value )
4888 + showProps[ settings.prop ].unit;
4890 duration: options.duration,
4891 easing: options.easing,
4892 complete: function() {
4893 if ( !options.autoHeight ) {
4894 options.toShow.css( "height", "" );
4896 options.toShow.css({
4897 width: originalWidth,
4898 overflow: overflow
4900 options.complete();
4904 bounceslide: function( options ) {
4905 this.slide( options, {
4906 easing: options.down ? "easeOutBounce" : "swing",
4907 duration: options.down ? 1000 : 200
4913 })( jQuery );
4915 * jQuery UI Autocomplete 1.8.16
4917 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
4918 * Dual licensed under the MIT or GPL Version 2 licenses.
4919 * http://jquery.org/license
4921 * http://docs.jquery.com/UI/Autocomplete
4923 * Depends:
4924 * jquery.ui.core.js
4925 * jquery.ui.widget.js
4926 * jquery.ui.position.js
4928 (function( $, undefined ) {
4930 // used to prevent race conditions with remote data sources
4931 var requestIndex = 0;
4933 $.widget( "ui.autocomplete", {
4934 options: {
4935 appendTo: "body",
4936 autoFocus: false,
4937 delay: 300,
4938 minLength: 1,
4939 position: {
4940 my: "left top",
4941 at: "left bottom",
4942 collision: "none"
4944 source: null
4947 pending: 0,
4949 _create: function() {
4950 var self = this,
4951 doc = this.element[ 0 ].ownerDocument,
4952 suppressKeyPress;
4954 this.element
4955 .addClass( "ui-autocomplete-input" )
4956 .attr( "autocomplete", "off" )
4957 // TODO verify these actually work as intended
4958 .attr({
4959 role: "textbox",
4960 "aria-autocomplete": "list",
4961 "aria-haspopup": "true"
4963 .bind( "keydown.autocomplete", function( event ) {
4964 if ( self.options.disabled || self.element.propAttr( "readOnly" ) ) {
4965 return;
4968 suppressKeyPress = false;
4969 var keyCode = $.ui.keyCode;
4970 switch( event.keyCode ) {
4971 case keyCode.PAGE_UP:
4972 self._move( "previousPage", event );
4973 break;
4974 case keyCode.PAGE_DOWN:
4975 self._move( "nextPage", event );
4976 break;
4977 case keyCode.UP:
4978 self._move( "previous", event );
4979 // prevent moving cursor to beginning of text field in some browsers
4980 event.preventDefault();
4981 break;
4982 case keyCode.DOWN:
4983 self._move( "next", event );
4984 // prevent moving cursor to end of text field in some browsers
4985 event.preventDefault();
4986 break;
4987 case keyCode.ENTER:
4988 case keyCode.NUMPAD_ENTER:
4989 // when menu is open and has focus
4990 if ( self.menu.active ) {
4991 // #6055 - Opera still allows the keypress to occur
4992 // which causes forms to submit
4993 suppressKeyPress = true;
4994 event.preventDefault();
4996 //passthrough - ENTER and TAB both select the current element
4997 case keyCode.TAB:
4998 if ( !self.menu.active ) {
4999 return;
5001 self.menu.select( event );
5002 break;
5003 case keyCode.ESCAPE:
5004 self.element.val( self.term );
5005 self.close( event );
5006 break;
5007 default:
5008 // keypress is triggered before the input value is changed
5009 clearTimeout( self.searching );
5010 self.searching = setTimeout(function() {
5011 // only search if the value has changed
5012 if ( self.term != self.element.val() ) {
5013 self.selectedItem = null;
5014 self.search( null, event );
5016 }, self.options.delay );
5017 break;
5020 .bind( "keypress.autocomplete", function( event ) {
5021 if ( suppressKeyPress ) {
5022 suppressKeyPress = false;
5023 event.preventDefault();
5026 .bind( "focus.autocomplete", function() {
5027 if ( self.options.disabled ) {
5028 return;
5031 self.selectedItem = null;
5032 self.previous = self.element.val();
5034 .bind( "blur.autocomplete", function( event ) {
5035 if ( self.options.disabled ) {
5036 return;
5039 clearTimeout( self.searching );
5040 // clicks on the menu (or a button to trigger a search) will cause a blur event
5041 self.closing = setTimeout(function() {
5042 self.close( event );
5043 self._change( event );
5044 }, 150 );
5046 this._initSource();
5047 this.response = function() {
5048 return self._response.apply( self, arguments );
5050 this.menu = $( "<ul></ul>" )
5051 .addClass( "ui-autocomplete" )
5052 .appendTo( $( this.options.appendTo || "body", doc )[0] )
5053 // prevent the close-on-blur in case of a "slow" click on the menu (long mousedown)
5054 .mousedown(function( event ) {
5055 // clicking on the scrollbar causes focus to shift to the body
5056 // but we can't detect a mouseup or a click immediately afterward
5057 // so we have to track the next mousedown and close the menu if
5058 // the user clicks somewhere outside of the autocomplete
5059 var menuElement = self.menu.element[ 0 ];
5060 if ( !$( event.target ).closest( ".ui-menu-item" ).length ) {
5061 setTimeout(function() {
5062 $( document ).one( 'mousedown', function( event ) {
5063 if ( event.target !== self.element[ 0 ] &&
5064 event.target !== menuElement &&
5065 !$.ui.contains( menuElement, event.target ) ) {
5066 self.close();
5069 }, 1 );
5072 // use another timeout to make sure the blur-event-handler on the input was already triggered
5073 setTimeout(function() {
5074 clearTimeout( self.closing );
5075 }, 13);
5077 .menu({
5078 focus: function( event, ui ) {
5079 var item = ui.item.data( "item.autocomplete" );
5080 if ( false !== self._trigger( "focus", event, { item: item } ) ) {
5081 // use value to match what will end up in the input, if it was a key event
5082 if ( /^key/.test(event.originalEvent.type) ) {
5083 self.element.val( item.value );
5087 selected: function( event, ui ) {
5088 var item = ui.item.data( "item.autocomplete" ),
5089 previous = self.previous;
5091 // only trigger when focus was lost (click on menu)
5092 if ( self.element[0] !== doc.activeElement ) {
5093 self.element.focus();
5094 self.previous = previous;
5095 // #6109 - IE triggers two focus events and the second
5096 // is asynchronous, so we need to reset the previous
5097 // term synchronously and asynchronously :-(
5098 setTimeout(function() {
5099 self.previous = previous;
5100 self.selectedItem = item;
5101 }, 1);
5104 if ( false !== self._trigger( "select", event, { item: item } ) ) {
5105 self.element.val( item.value );
5107 // reset the term after the select event
5108 // this allows custom select handling to work properly
5109 self.term = self.element.val();
5111 self.close( event );
5112 self.selectedItem = item;
5114 blur: function( event, ui ) {
5115 // don't set the value of the text field if it's already correct
5116 // this prevents moving the cursor unnecessarily
5117 if ( self.menu.element.is(":visible") &&
5118 ( self.element.val() !== self.term ) ) {
5119 self.element.val( self.term );
5123 .zIndex( this.element.zIndex() + 1 )
5124 // workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
5125 .css({ top: 0, left: 0 })
5126 .hide()
5127 .data( "menu" );
5128 if ( $.fn.bgiframe ) {
5129 this.menu.element.bgiframe();
5133 destroy: function() {
5134 this.element
5135 .removeClass( "ui-autocomplete-input" )
5136 .removeAttr( "autocomplete" )
5137 .removeAttr( "role" )
5138 .removeAttr( "aria-autocomplete" )
5139 .removeAttr( "aria-haspopup" );
5140 this.menu.element.remove();
5141 $.Widget.prototype.destroy.call( this );
5144 _setOption: function( key, value ) {
5145 $.Widget.prototype._setOption.apply( this, arguments );
5146 if ( key === "source" ) {
5147 this._initSource();
5149 if ( key === "appendTo" ) {
5150 this.menu.element.appendTo( $( value || "body", this.element[0].ownerDocument )[0] )
5152 if ( key === "disabled" && value && this.xhr ) {
5153 this.xhr.abort();
5157 _initSource: function() {
5158 var self = this,
5159 array,
5160 url;
5161 if ( $.isArray(this.options.source) ) {
5162 array = this.options.source;
5163 this.source = function( request, response ) {
5164 response( $.ui.autocomplete.filter(array, request.term) );
5166 } else if ( typeof this.options.source === "string" ) {
5167 url = this.options.source;
5168 this.source = function( request, response ) {
5169 if ( self.xhr ) {
5170 self.xhr.abort();
5172 self.xhr = $.ajax({
5173 url: url,
5174 data: request,
5175 dataType: "json",
5176 autocompleteRequest: ++requestIndex,
5177 success: function( data, status ) {
5178 if ( this.autocompleteRequest === requestIndex ) {
5179 response( data );
5182 error: function() {
5183 if ( this.autocompleteRequest === requestIndex ) {
5184 response( [] );
5189 } else {
5190 this.source = this.options.source;
5194 search: function( value, event ) {
5195 value = value != null ? value : this.element.val();
5197 // always save the actual value, not the one passed as an argument
5198 this.term = this.element.val();
5200 if ( value.length < this.options.minLength ) {
5201 return this.close( event );
5204 clearTimeout( this.closing );
5205 if ( this._trigger( "search", event ) === false ) {
5206 return;
5209 return this._search( value );
5212 _search: function( value ) {
5213 this.pending++;
5214 this.element.addClass( "ui-autocomplete-loading" );
5216 this.source( { term: value }, this.response );
5219 _response: function( content ) {
5220 if ( !this.options.disabled && content && content.length ) {
5221 content = this._normalize( content );
5222 this._suggest( content );
5223 this._trigger( "open" );
5224 } else {
5225 this.close();
5227 this.pending--;
5228 if ( !this.pending ) {
5229 this.element.removeClass( "ui-autocomplete-loading" );
5233 close: function( event ) {
5234 clearTimeout( this.closing );
5235 if ( this.menu.element.is(":visible") ) {
5236 this.menu.element.hide();
5237 this.menu.deactivate();
5238 this._trigger( "close", event );
5242 _change: function( event ) {
5243 if ( this.previous !== this.element.val() ) {
5244 this._trigger( "change", event, { item: this.selectedItem } );
5248 _normalize: function( items ) {
5249 // assume all items have the right format when the first item is complete
5250 if ( items.length && items[0].label && items[0].value ) {
5251 return items;
5253 return $.map( items, function(item) {
5254 if ( typeof item === "string" ) {
5255 return {
5256 label: item,
5257 value: item
5260 return $.extend({
5261 label: item.label || item.value,
5262 value: item.value || item.label
5263 }, item );
5267 _suggest: function( items ) {
5268 var ul = this.menu.element
5269 .empty()
5270 .zIndex( this.element.zIndex() + 1 );
5271 this._renderMenu( ul, items );
5272 // TODO refresh should check if the active item is still in the dom, removing the need for a manual deactivate
5273 this.menu.deactivate();
5274 this.menu.refresh();
5276 // size and position menu
5277 ul.show();
5278 this._resizeMenu();
5279 ul.position( $.extend({
5280 of: this.element
5281 }, this.options.position ));
5283 if ( this.options.autoFocus ) {
5284 this.menu.next( new $.Event("mouseover") );
5288 _resizeMenu: function() {
5289 var ul = this.menu.element;
5290 ul.outerWidth( Math.max(
5291 ul.width( "" ).outerWidth(),
5292 this.element.outerWidth()
5293 ) );
5296 _renderMenu: function( ul, items ) {
5297 var self = this;
5298 $.each( items, function( index, item ) {
5299 self._renderItem( ul, item );
5303 _renderItem: function( ul, item) {
5304 return $( "<li></li>" )
5305 .data( "item.autocomplete", item )
5306 .append( $( "<a></a>" ).text( item.label ) )
5307 .appendTo( ul );
5310 _move: function( direction, event ) {
5311 if ( !this.menu.element.is(":visible") ) {
5312 this.search( null, event );
5313 return;
5315 if ( this.menu.first() && /^previous/.test(direction) ||
5316 this.menu.last() && /^next/.test(direction) ) {
5317 this.element.val( this.term );
5318 this.menu.deactivate();
5319 return;
5321 this.menu[ direction ]( event );
5324 widget: function() {
5325 return this.menu.element;
5329 $.extend( $.ui.autocomplete, {
5330 escapeRegex: function( value ) {
5331 return value.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
5333 filter: function(array, term) {
5334 var matcher = new RegExp( $.ui.autocomplete.escapeRegex(term), "i" );
5335 return $.grep( array, function(value) {
5336 return matcher.test( value.label || value.value || value );
5341 }( jQuery ));
5344 * jQuery UI Menu (not officially released)
5346 * This widget isn't yet finished and the API is subject to change. We plan to finish
5347 * it for the next release. You're welcome to give it a try anyway and give us feedback,
5348 * as long as you're okay with migrating your code later on. We can help with that, too.
5350 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
5351 * Dual licensed under the MIT or GPL Version 2 licenses.
5352 * http://jquery.org/license
5354 * http://docs.jquery.com/UI/Menu
5356 * Depends:
5357 * jquery.ui.core.js
5358 * jquery.ui.widget.js
5360 (function($) {
5362 $.widget("ui.menu", {
5363 _create: function() {
5364 var self = this;
5365 this.element
5366 .addClass("ui-menu ui-widget ui-widget-content ui-corner-all")
5367 .attr({
5368 role: "listbox",
5369 "aria-activedescendant": "ui-active-menuitem"
5371 .click(function( event ) {
5372 if ( !$( event.target ).closest( ".ui-menu-item a" ).length ) {
5373 return;
5375 // temporary
5376 event.preventDefault();
5377 self.select( event );
5379 this.refresh();
5382 refresh: function() {
5383 var self = this;
5385 // don't refresh list items that are already adapted
5386 var items = this.element.children("li:not(.ui-menu-item):has(a)")
5387 .addClass("ui-menu-item")
5388 .attr("role", "menuitem");
5390 items.children("a")
5391 .addClass("ui-corner-all")
5392 .attr("tabindex", -1)
5393 // mouseenter doesn't work with event delegation
5394 .mouseenter(function( event ) {
5395 self.activate( event, $(this).parent() );
5397 .mouseleave(function() {
5398 self.deactivate();
5402 activate: function( event, item ) {
5403 this.deactivate();
5404 if (this.hasScroll()) {
5405 var offset = item.offset().top - this.element.offset().top,
5406 scroll = this.element.scrollTop(),
5407 elementHeight = this.element.height();
5408 if (offset < 0) {
5409 this.element.scrollTop( scroll + offset);
5410 } else if (offset >= elementHeight) {
5411 this.element.scrollTop( scroll + offset - elementHeight + item.height());
5414 this.active = item.eq(0)
5415 .children("a")
5416 .addClass("ui-state-hover")
5417 .attr("id", "ui-active-menuitem")
5418 .end();
5419 this._trigger("focus", event, { item: item });
5422 deactivate: function() {
5423 if (!this.active) { return; }
5425 this.active.children("a")
5426 .removeClass("ui-state-hover")
5427 .removeAttr("id");
5428 this._trigger("blur");
5429 this.active = null;
5432 next: function(event) {
5433 this.move("next", ".ui-menu-item:first", event);
5436 previous: function(event) {
5437 this.move("prev", ".ui-menu-item:last", event);
5440 first: function() {
5441 return this.active && !this.active.prevAll(".ui-menu-item").length;
5444 last: function() {
5445 return this.active && !this.active.nextAll(".ui-menu-item").length;
5448 move: function(direction, edge, event) {
5449 if (!this.active) {
5450 this.activate(event, this.element.children(edge));
5451 return;
5453 var next = this.active[direction + "All"](".ui-menu-item").eq(0);
5454 if (next.length) {
5455 this.activate(event, next);
5456 } else {
5457 this.activate(event, this.element.children(edge));
5461 // TODO merge with previousPage
5462 nextPage: function(event) {
5463 if (this.hasScroll()) {
5464 // TODO merge with no-scroll-else
5465 if (!this.active || this.last()) {
5466 this.activate(event, this.element.children(".ui-menu-item:first"));
5467 return;
5469 var base = this.active.offset().top,
5470 height = this.element.height(),
5471 result = this.element.children(".ui-menu-item").filter(function() {
5472 var close = $(this).offset().top - base - height + $(this).height();
5473 // TODO improve approximation
5474 return close < 10 && close > -10;
5477 // TODO try to catch this earlier when scrollTop indicates the last page anyway
5478 if (!result.length) {
5479 result = this.element.children(".ui-menu-item:last");
5481 this.activate(event, result);
5482 } else {
5483 this.activate(event, this.element.children(".ui-menu-item")
5484 .filter(!this.active || this.last() ? ":first" : ":last"));
5488 // TODO merge with nextPage
5489 previousPage: function(event) {
5490 if (this.hasScroll()) {
5491 // TODO merge with no-scroll-else
5492 if (!this.active || this.first()) {
5493 this.activate(event, this.element.children(".ui-menu-item:last"));
5494 return;
5497 var base = this.active.offset().top,
5498 height = this.element.height();
5499 result = this.element.children(".ui-menu-item").filter(function() {
5500 var close = $(this).offset().top - base + height - $(this).height();
5501 // TODO improve approximation
5502 return close < 10 && close > -10;
5505 // TODO try to catch this earlier when scrollTop indicates the last page anyway
5506 if (!result.length) {
5507 result = this.element.children(".ui-menu-item:first");
5509 this.activate(event, result);
5510 } else {
5511 this.activate(event, this.element.children(".ui-menu-item")
5512 .filter(!this.active || this.first() ? ":last" : ":first"));
5516 hasScroll: function() {
5517 return this.element.height() < this.element[ $.fn.prop ? "prop" : "attr" ]("scrollHeight");
5520 select: function( event ) {
5521 this._trigger("selected", event, { item: this.active });
5525 }(jQuery));
5527 * jQuery UI Button 1.8.16
5529 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
5530 * Dual licensed under the MIT or GPL Version 2 licenses.
5531 * http://jquery.org/license
5533 * http://docs.jquery.com/UI/Button
5535 * Depends:
5536 * jquery.ui.core.js
5537 * jquery.ui.widget.js
5539 (function( $, undefined ) {
5541 var lastActive, startXPos, startYPos, clickDragged,
5542 baseClasses = "ui-button ui-widget ui-state-default ui-corner-all",
5543 stateClasses = "ui-state-hover ui-state-active ",
5544 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",
5545 formResetHandler = function() {
5546 var buttons = $( this ).find( ":ui-button" );
5547 setTimeout(function() {
5548 buttons.button( "refresh" );
5549 }, 1 );
5551 radioGroup = function( radio ) {
5552 var name = radio.name,
5553 form = radio.form,
5554 radios = $( [] );
5555 if ( name ) {
5556 if ( form ) {
5557 radios = $( form ).find( "[name='" + name + "']" );
5558 } else {
5559 radios = $( "[name='" + name + "']", radio.ownerDocument )
5560 .filter(function() {
5561 return !this.form;
5565 return radios;
5568 $.widget( "ui.button", {
5569 options: {
5570 disabled: null,
5571 text: true,
5572 label: null,
5573 icons: {
5574 primary: null,
5575 secondary: null
5578 _create: function() {
5579 this.element.closest( "form" )
5580 .unbind( "reset.button" )
5581 .bind( "reset.button", formResetHandler );
5583 if ( typeof this.options.disabled !== "boolean" ) {
5584 this.options.disabled = this.element.propAttr( "disabled" );
5587 this._determineButtonType();
5588 this.hasTitle = !!this.buttonElement.attr( "title" );
5590 var self = this,
5591 options = this.options,
5592 toggleButton = this.type === "checkbox" || this.type === "radio",
5593 hoverClass = "ui-state-hover" + ( !toggleButton ? " ui-state-active" : "" ),
5594 focusClass = "ui-state-focus";
5596 if ( options.label === null ) {
5597 options.label = this.buttonElement.html();
5600 if ( this.element.is( ":disabled" ) ) {
5601 options.disabled = true;
5604 this.buttonElement
5605 .addClass( baseClasses )
5606 .attr( "role", "button" )
5607 .bind( "mouseenter.button", function() {
5608 if ( options.disabled ) {
5609 return;
5611 $( this ).addClass( "ui-state-hover" );
5612 if ( this === lastActive ) {
5613 $( this ).addClass( "ui-state-active" );
5616 .bind( "mouseleave.button", function() {
5617 if ( options.disabled ) {
5618 return;
5620 $( this ).removeClass( hoverClass );
5622 .bind( "click.button", function( event ) {
5623 if ( options.disabled ) {
5624 event.preventDefault();
5625 event.stopImmediatePropagation();
5629 this.element
5630 .bind( "focus.button", function() {
5631 // no need to check disabled, focus won't be triggered anyway
5632 self.buttonElement.addClass( focusClass );
5634 .bind( "blur.button", function() {
5635 self.buttonElement.removeClass( focusClass );
5638 if ( toggleButton ) {
5639 this.element.bind( "change.button", function() {
5640 if ( clickDragged ) {
5641 return;
5643 self.refresh();
5645 // if mouse moves between mousedown and mouseup (drag) set clickDragged flag
5646 // prevents issue where button state changes but checkbox/radio checked state
5647 // does not in Firefox (see ticket #6970)
5648 this.buttonElement
5649 .bind( "mousedown.button", function( event ) {
5650 if ( options.disabled ) {
5651 return;
5653 clickDragged = false;
5654 startXPos = event.pageX;
5655 startYPos = event.pageY;
5657 .bind( "mouseup.button", function( event ) {
5658 if ( options.disabled ) {
5659 return;
5661 if ( startXPos !== event.pageX || startYPos !== event.pageY ) {
5662 clickDragged = true;
5667 if ( this.type === "checkbox" ) {
5668 this.buttonElement.bind( "click.button", function() {
5669 if ( options.disabled || clickDragged ) {
5670 return false;
5672 $( this ).toggleClass( "ui-state-active" );
5673 self.buttonElement.attr( "aria-pressed", self.element[0].checked );
5675 } else if ( this.type === "radio" ) {
5676 this.buttonElement.bind( "click.button", function() {
5677 if ( options.disabled || clickDragged ) {
5678 return false;
5680 $( this ).addClass( "ui-state-active" );
5681 self.buttonElement.attr( "aria-pressed", "true" );
5683 var radio = self.element[ 0 ];
5684 radioGroup( radio )
5685 .not( radio )
5686 .map(function() {
5687 return $( this ).button( "widget" )[ 0 ];
5689 .removeClass( "ui-state-active" )
5690 .attr( "aria-pressed", "false" );
5692 } else {
5693 this.buttonElement
5694 .bind( "mousedown.button", function() {
5695 if ( options.disabled ) {
5696 return false;
5698 $( this ).addClass( "ui-state-active" );
5699 lastActive = this;
5700 $( document ).one( "mouseup", function() {
5701 lastActive = null;
5704 .bind( "mouseup.button", function() {
5705 if ( options.disabled ) {
5706 return false;
5708 $( this ).removeClass( "ui-state-active" );
5710 .bind( "keydown.button", function(event) {
5711 if ( options.disabled ) {
5712 return false;
5714 if ( event.keyCode == $.ui.keyCode.SPACE || event.keyCode == $.ui.keyCode.ENTER ) {
5715 $( this ).addClass( "ui-state-active" );
5718 .bind( "keyup.button", function() {
5719 $( this ).removeClass( "ui-state-active" );
5722 if ( this.buttonElement.is("a") ) {
5723 this.buttonElement.keyup(function(event) {
5724 if ( event.keyCode === $.ui.keyCode.SPACE ) {
5725 // TODO pass through original event correctly (just as 2nd argument doesn't work)
5726 $( this ).click();
5732 // TODO: pull out $.Widget's handling for the disabled option into
5733 // $.Widget.prototype._setOptionDisabled so it's easy to proxy and can
5734 // be overridden by individual plugins
5735 this._setOption( "disabled", options.disabled );
5736 this._resetButton();
5739 _determineButtonType: function() {
5741 if ( this.element.is(":checkbox") ) {
5742 this.type = "checkbox";
5743 } else if ( this.element.is(":radio") ) {
5744 this.type = "radio";
5745 } else if ( this.element.is("input") ) {
5746 this.type = "input";
5747 } else {
5748 this.type = "button";
5751 if ( this.type === "checkbox" || this.type === "radio" ) {
5752 // we don't search against the document in case the element
5753 // is disconnected from the DOM
5754 var ancestor = this.element.parents().filter(":last"),
5755 labelSelector = "label[for='" + this.element.attr("id") + "']";
5756 this.buttonElement = ancestor.find( labelSelector );
5757 if ( !this.buttonElement.length ) {
5758 ancestor = ancestor.length ? ancestor.siblings() : this.element.siblings();
5759 this.buttonElement = ancestor.filter( labelSelector );
5760 if ( !this.buttonElement.length ) {
5761 this.buttonElement = ancestor.find( labelSelector );
5764 this.element.addClass( "ui-helper-hidden-accessible" );
5766 var checked = this.element.is( ":checked" );
5767 if ( checked ) {
5768 this.buttonElement.addClass( "ui-state-active" );
5770 this.buttonElement.attr( "aria-pressed", checked );
5771 } else {
5772 this.buttonElement = this.element;
5776 widget: function() {
5777 return this.buttonElement;
5780 destroy: function() {
5781 this.element
5782 .removeClass( "ui-helper-hidden-accessible" );
5783 this.buttonElement
5784 .removeClass( baseClasses + " " + stateClasses + " " + typeClasses )
5785 .removeAttr( "role" )
5786 .removeAttr( "aria-pressed" )
5787 .html( this.buttonElement.find(".ui-button-text").html() );
5789 if ( !this.hasTitle ) {
5790 this.buttonElement.removeAttr( "title" );
5793 $.Widget.prototype.destroy.call( this );
5796 _setOption: function( key, value ) {
5797 $.Widget.prototype._setOption.apply( this, arguments );
5798 if ( key === "disabled" ) {
5799 if ( value ) {
5800 this.element.propAttr( "disabled", true );
5801 } else {
5802 this.element.propAttr( "disabled", false );
5804 return;
5806 this._resetButton();
5809 refresh: function() {
5810 var isDisabled = this.element.is( ":disabled" );
5811 if ( isDisabled !== this.options.disabled ) {
5812 this._setOption( "disabled", isDisabled );
5814 if ( this.type === "radio" ) {
5815 radioGroup( this.element[0] ).each(function() {
5816 if ( $( this ).is( ":checked" ) ) {
5817 $( this ).button( "widget" )
5818 .addClass( "ui-state-active" )
5819 .attr( "aria-pressed", "true" );
5820 } else {
5821 $( this ).button( "widget" )
5822 .removeClass( "ui-state-active" )
5823 .attr( "aria-pressed", "false" );
5826 } else if ( this.type === "checkbox" ) {
5827 if ( this.element.is( ":checked" ) ) {
5828 this.buttonElement
5829 .addClass( "ui-state-active" )
5830 .attr( "aria-pressed", "true" );
5831 } else {
5832 this.buttonElement
5833 .removeClass( "ui-state-active" )
5834 .attr( "aria-pressed", "false" );
5839 _resetButton: function() {
5840 if ( this.type === "input" ) {
5841 if ( this.options.label ) {
5842 this.element.val( this.options.label );
5844 return;
5846 var buttonElement = this.buttonElement.removeClass( typeClasses ),
5847 buttonText = $( "<span></span>" )
5848 .addClass( "ui-button-text" )
5849 .html( this.options.label )
5850 .appendTo( buttonElement.empty() )
5851 .text(),
5852 icons = this.options.icons,
5853 multipleIcons = icons.primary && icons.secondary,
5854 buttonClasses = [];
5856 if ( icons.primary || icons.secondary ) {
5857 if ( this.options.text ) {
5858 buttonClasses.push( "ui-button-text-icon" + ( multipleIcons ? "s" : ( icons.primary ? "-primary" : "-secondary" ) ) );
5861 if ( icons.primary ) {
5862 buttonElement.prepend( "<span class='ui-button-icon-primary ui-icon " + icons.primary + "'></span>" );
5865 if ( icons.secondary ) {
5866 buttonElement.append( "<span class='ui-button-icon-secondary ui-icon " + icons.secondary + "'></span>" );
5869 if ( !this.options.text ) {
5870 buttonClasses.push( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" );
5872 if ( !this.hasTitle ) {
5873 buttonElement.attr( "title", buttonText );
5876 } else {
5877 buttonClasses.push( "ui-button-text-only" );
5879 buttonElement.addClass( buttonClasses.join( " " ) );
5883 $.widget( "ui.buttonset", {
5884 options: {
5885 items: ":button, :submit, :reset, :checkbox, :radio, a, :data(button)"
5888 _create: function() {
5889 this.element.addClass( "ui-buttonset" );
5892 _init: function() {
5893 this.refresh();
5896 _setOption: function( key, value ) {
5897 if ( key === "disabled" ) {
5898 this.buttons.button( "option", key, value );
5901 $.Widget.prototype._setOption.apply( this, arguments );
5904 refresh: function() {
5905 var ltr = this.element.css( "direction" ) === "ltr";
5907 this.buttons = this.element.find( this.options.items )
5908 .filter( ":ui-button" )
5909 .button( "refresh" )
5910 .end()
5911 .not( ":ui-button" )
5912 .button()
5913 .end()
5914 .map(function() {
5915 return $( this ).button( "widget" )[ 0 ];
5917 .removeClass( "ui-corner-all ui-corner-left ui-corner-right" )
5918 .filter( ":first" )
5919 .addClass( ltr ? "ui-corner-left" : "ui-corner-right" )
5920 .end()
5921 .filter( ":last" )
5922 .addClass( ltr ? "ui-corner-right" : "ui-corner-left" )
5923 .end()
5924 .end();
5927 destroy: function() {
5928 this.element.removeClass( "ui-buttonset" );
5929 this.buttons
5930 .map(function() {
5931 return $( this ).button( "widget" )[ 0 ];
5933 .removeClass( "ui-corner-left ui-corner-right" )
5934 .end()
5935 .button( "destroy" );
5937 $.Widget.prototype.destroy.call( this );
5941 }( jQuery ) );
5943 * jQuery UI Dialog 1.8.16
5945 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
5946 * Dual licensed under the MIT or GPL Version 2 licenses.
5947 * http://jquery.org/license
5949 * http://docs.jquery.com/UI/Dialog
5951 * Depends:
5952 * jquery.ui.core.js
5953 * jquery.ui.widget.js
5954 * jquery.ui.button.js
5955 * jquery.ui.draggable.js
5956 * jquery.ui.mouse.js
5957 * jquery.ui.position.js
5958 * jquery.ui.resizable.js
5960 (function( $, undefined ) {
5962 var uiDialogClasses =
5963 'ui-dialog ' +
5964 'ui-widget ' +
5965 'ui-widget-content ' +
5966 'ui-corner-all ',
5967 sizeRelatedOptions = {
5968 buttons: true,
5969 height: true,
5970 maxHeight: true,
5971 maxWidth: true,
5972 minHeight: true,
5973 minWidth: true,
5974 width: true
5976 resizableRelatedOptions = {
5977 maxHeight: true,
5978 maxWidth: true,
5979 minHeight: true,
5980 minWidth: true
5982 // support for jQuery 1.3.2 - handle common attrFn methods for dialog
5983 attrFn = $.attrFn || {
5984 val: true,
5985 css: true,
5986 html: true,
5987 text: true,
5988 data: true,
5989 width: true,
5990 height: true,
5991 offset: true,
5992 click: true
5995 $.widget("ui.dialog", {
5996 options: {
5997 autoOpen: true,
5998 buttons: {},
5999 closeOnEscape: true,
6000 closeText: 'close',
6001 dialogClass: '',
6002 draggable: true,
6003 hide: null,
6004 height: 'auto',
6005 maxHeight: false,
6006 maxWidth: false,
6007 minHeight: 150,
6008 minWidth: 150,
6009 modal: false,
6010 position: {
6011 my: 'center',
6012 at: 'center',
6013 collision: 'fit',
6014 // ensure that the titlebar is never outside the document
6015 using: function(pos) {
6016 var topOffset = $(this).css(pos).offset().top;
6017 if (topOffset < 0) {
6018 $(this).css('top', pos.top - topOffset);
6022 resizable: true,
6023 show: null,
6024 stack: true,
6025 title: '',
6026 width: 300,
6027 zIndex: 1000
6030 _create: function() {
6031 this.originalTitle = this.element.attr('title');
6032 // #5742 - .attr() might return a DOMElement
6033 if ( typeof this.originalTitle !== "string" ) {
6034 this.originalTitle = "";
6037 this.options.title = this.options.title || this.originalTitle;
6038 var self = this,
6039 options = self.options,
6041 title = options.title || '&#160;',
6042 titleId = $.ui.dialog.getTitleId(self.element),
6044 uiDialog = (self.uiDialog = $('<div></div>'))
6045 .appendTo(document.body)
6046 .hide()
6047 .addClass(uiDialogClasses + options.dialogClass)
6048 .css({
6049 zIndex: options.zIndex
6051 // setting tabIndex makes the div focusable
6052 // setting outline to 0 prevents a border on focus in Mozilla
6053 .attr('tabIndex', -1).css('outline', 0).keydown(function(event) {
6054 if (options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode &&
6055 event.keyCode === $.ui.keyCode.ESCAPE) {
6057 self.close(event);
6058 event.preventDefault();
6061 .attr({
6062 role: 'dialog',
6063 'aria-labelledby': titleId
6065 .mousedown(function(event) {
6066 self.moveToTop(false, event);
6069 uiDialogContent = self.element
6070 .show()
6071 .removeAttr('title')
6072 .addClass(
6073 'ui-dialog-content ' +
6074 'ui-widget-content')
6075 .appendTo(uiDialog),
6077 uiDialogTitlebar = (self.uiDialogTitlebar = $('<div></div>'))
6078 .addClass(
6079 'ui-dialog-titlebar ' +
6080 'ui-widget-header ' +
6081 'ui-corner-all ' +
6082 'ui-helper-clearfix'
6084 .prependTo(uiDialog),
6086 uiDialogTitlebarClose = $('<a href="#"></a>')
6087 .addClass(
6088 'ui-dialog-titlebar-close ' +
6089 'ui-corner-all'
6091 .attr('role', 'button')
6092 .hover(
6093 function() {
6094 uiDialogTitlebarClose.addClass('ui-state-hover');
6096 function() {
6097 uiDialogTitlebarClose.removeClass('ui-state-hover');
6100 .focus(function() {
6101 uiDialogTitlebarClose.addClass('ui-state-focus');
6103 .blur(function() {
6104 uiDialogTitlebarClose.removeClass('ui-state-focus');
6106 .click(function(event) {
6107 self.close(event);
6108 return false;
6110 .appendTo(uiDialogTitlebar),
6112 uiDialogTitlebarCloseText = (self.uiDialogTitlebarCloseText = $('<span></span>'))
6113 .addClass(
6114 'ui-icon ' +
6115 'ui-icon-closethick'
6117 .text(options.closeText)
6118 .appendTo(uiDialogTitlebarClose),
6120 uiDialogTitle = $('<span></span>')
6121 .addClass('ui-dialog-title')
6122 .attr('id', titleId)
6123 .html(title)
6124 .prependTo(uiDialogTitlebar);
6126 //handling of deprecated beforeclose (vs beforeClose) option
6127 //Ticket #4669 http://dev.jqueryui.com/ticket/4669
6128 //TODO: remove in 1.9pre
6129 if ($.isFunction(options.beforeclose) && !$.isFunction(options.beforeClose)) {
6130 options.beforeClose = options.beforeclose;
6133 uiDialogTitlebar.find("*").add(uiDialogTitlebar).disableSelection();
6135 if (options.draggable && $.fn.draggable) {
6136 self._makeDraggable();
6138 if (options.resizable && $.fn.resizable) {
6139 self._makeResizable();
6142 self._createButtons(options.buttons);
6143 self._isOpen = false;
6145 if ($.fn.bgiframe) {
6146 uiDialog.bgiframe();
6150 _init: function() {
6151 if ( this.options.autoOpen ) {
6152 this.open();
6156 destroy: function() {
6157 var self = this;
6159 if (self.overlay) {
6160 self.overlay.destroy();
6162 self.uiDialog.hide();
6163 self.element
6164 .unbind('.dialog')
6165 .removeData('dialog')
6166 .removeClass('ui-dialog-content ui-widget-content')
6167 .hide().appendTo('body');
6168 self.uiDialog.remove();
6170 if (self.originalTitle) {
6171 self.element.attr('title', self.originalTitle);
6174 return self;
6177 widget: function() {
6178 return this.uiDialog;
6181 close: function(event) {
6182 var self = this,
6183 maxZ, thisZ;
6185 if (false === self._trigger('beforeClose', event)) {
6186 return;
6189 if (self.overlay) {
6190 self.overlay.destroy();
6192 self.uiDialog.unbind('keypress.ui-dialog');
6194 self._isOpen = false;
6196 if (self.options.hide) {
6197 self.uiDialog.hide(self.options.hide, function() {
6198 self._trigger('close', event);
6200 } else {
6201 self.uiDialog.hide();
6202 self._trigger('close', event);
6205 $.ui.dialog.overlay.resize();
6207 // adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
6208 if (self.options.modal) {
6209 maxZ = 0;
6210 $('.ui-dialog').each(function() {
6211 if (this !== self.uiDialog[0]) {
6212 thisZ = $(this).css('z-index');
6213 if(!isNaN(thisZ)) {
6214 maxZ = Math.max(maxZ, thisZ);
6218 $.ui.dialog.maxZ = maxZ;
6221 return self;
6224 isOpen: function() {
6225 return this._isOpen;
6228 // the force parameter allows us to move modal dialogs to their correct
6229 // position on open
6230 moveToTop: function(force, event) {
6231 var self = this,
6232 options = self.options,
6233 saveScroll;
6235 if ((options.modal && !force) ||
6236 (!options.stack && !options.modal)) {
6237 return self._trigger('focus', event);
6240 if (options.zIndex > $.ui.dialog.maxZ) {
6241 $.ui.dialog.maxZ = options.zIndex;
6243 if (self.overlay) {
6244 $.ui.dialog.maxZ += 1;
6245 self.overlay.$el.css('z-index', $.ui.dialog.overlay.maxZ = $.ui.dialog.maxZ);
6248 //Save and then restore scroll since Opera 9.5+ resets when parent z-Index is changed.
6249 // http://ui.jquery.com/bugs/ticket/3193
6250 saveScroll = { scrollTop: self.element.scrollTop(), scrollLeft: self.element.scrollLeft() };
6251 $.ui.dialog.maxZ += 1;
6252 self.uiDialog.css('z-index', $.ui.dialog.maxZ);
6253 self.element.attr(saveScroll);
6254 self._trigger('focus', event);
6256 return self;
6259 open: function() {
6260 if (this._isOpen) { return; }
6262 var self = this,
6263 options = self.options,
6264 uiDialog = self.uiDialog;
6266 self.overlay = options.modal ? new $.ui.dialog.overlay(self) : null;
6267 self._size();
6268 self._position(options.position);
6269 uiDialog.show(options.show);
6270 self.moveToTop(true);
6272 // prevent tabbing out of modal dialogs
6273 if (options.modal) {
6274 uiDialog.bind('keypress.ui-dialog', function(event) {
6275 if (event.keyCode !== $.ui.keyCode.TAB) {
6276 return;
6279 var tabbables = $(':tabbable', this),
6280 first = tabbables.filter(':first'),
6281 last = tabbables.filter(':last');
6283 if (event.target === last[0] && !event.shiftKey) {
6284 first.focus(1);
6285 return false;
6286 } else if (event.target === first[0] && event.shiftKey) {
6287 last.focus(1);
6288 return false;
6293 // set focus to the first tabbable element in the content area or the first button
6294 // if there are no tabbable elements, set focus on the dialog itself
6295 $(self.element.find(':tabbable').get().concat(
6296 uiDialog.find('.ui-dialog-buttonpane :tabbable').get().concat(
6297 uiDialog.get()))).eq(0).focus();
6299 self._isOpen = true;
6300 self._trigger('open');
6302 return self;
6305 _createButtons: function(buttons) {
6306 var self = this,
6307 hasButtons = false,
6308 uiDialogButtonPane = $('<div></div>')
6309 .addClass(
6310 'ui-dialog-buttonpane ' +
6311 'ui-widget-content ' +
6312 'ui-helper-clearfix'
6314 uiButtonSet = $( "<div></div>" )
6315 .addClass( "ui-dialog-buttonset" )
6316 .appendTo( uiDialogButtonPane );
6318 // if we already have a button pane, remove it
6319 self.uiDialog.find('.ui-dialog-buttonpane').remove();
6321 if (typeof buttons === 'object' && buttons !== null) {
6322 $.each(buttons, function() {
6323 return !(hasButtons = true);
6326 if (hasButtons) {
6327 $.each(buttons, function(name, props) {
6328 props = $.isFunction( props ) ?
6329 { click: props, text: name } :
6330 props;
6331 var button = $('<button type="button"></button>')
6332 .click(function() {
6333 props.click.apply(self.element[0], arguments);
6335 .appendTo(uiButtonSet);
6336 // can't use .attr( props, true ) with jQuery 1.3.2.
6337 $.each( props, function( key, value ) {
6338 if ( key === "click" ) {
6339 return;
6341 if ( key in attrFn ) {
6342 button[ key ]( value );
6343 } else {
6344 button.attr( key, value );
6347 if ($.fn.button) {
6348 button.button();
6351 uiDialogButtonPane.appendTo(self.uiDialog);
6355 _makeDraggable: function() {
6356 var self = this,
6357 options = self.options,
6358 doc = $(document),
6359 heightBeforeDrag;
6361 function filteredUi(ui) {
6362 return {
6363 position: ui.position,
6364 offset: ui.offset
6368 self.uiDialog.draggable({
6369 cancel: '.ui-dialog-content, .ui-dialog-titlebar-close',
6370 handle: '.ui-dialog-titlebar',
6371 containment: 'document',
6372 start: function(event, ui) {
6373 heightBeforeDrag = options.height === "auto" ? "auto" : $(this).height();
6374 $(this).height($(this).height()).addClass("ui-dialog-dragging");
6375 self._trigger('dragStart', event, filteredUi(ui));
6377 drag: function(event, ui) {
6378 self._trigger('drag', event, filteredUi(ui));
6380 stop: function(event, ui) {
6381 options.position = [ui.position.left - doc.scrollLeft(),
6382 ui.position.top - doc.scrollTop()];
6383 $(this).removeClass("ui-dialog-dragging").height(heightBeforeDrag);
6384 self._trigger('dragStop', event, filteredUi(ui));
6385 $.ui.dialog.overlay.resize();
6390 _makeResizable: function(handles) {
6391 handles = (handles === undefined ? this.options.resizable : handles);
6392 var self = this,
6393 options = self.options,
6394 // .ui-resizable has position: relative defined in the stylesheet
6395 // but dialogs have to use absolute or fixed positioning
6396 position = self.uiDialog.css('position'),
6397 resizeHandles = (typeof handles === 'string' ?
6398 handles :
6399 'n,e,s,w,se,sw,ne,nw'
6402 function filteredUi(ui) {
6403 return {
6404 originalPosition: ui.originalPosition,
6405 originalSize: ui.originalSize,
6406 position: ui.position,
6407 size: ui.size
6411 self.uiDialog.resizable({
6412 cancel: '.ui-dialog-content',
6413 containment: 'document',
6414 alsoResize: self.element,
6415 maxWidth: options.maxWidth,
6416 maxHeight: options.maxHeight,
6417 minWidth: options.minWidth,
6418 minHeight: self._minHeight(),
6419 handles: resizeHandles,
6420 start: function(event, ui) {
6421 $(this).addClass("ui-dialog-resizing");
6422 self._trigger('resizeStart', event, filteredUi(ui));
6424 resize: function(event, ui) {
6425 self._trigger('resize', event, filteredUi(ui));
6427 stop: function(event, ui) {
6428 $(this).removeClass("ui-dialog-resizing");
6429 options.height = $(this).height();
6430 options.width = $(this).width();
6431 self._trigger('resizeStop', event, filteredUi(ui));
6432 $.ui.dialog.overlay.resize();
6435 .css('position', position)
6436 .find('.ui-resizable-se').addClass('ui-icon ui-icon-grip-diagonal-se');
6439 _minHeight: function() {
6440 var options = this.options;
6442 if (options.height === 'auto') {
6443 return options.minHeight;
6444 } else {
6445 return Math.min(options.minHeight, options.height);
6449 _position: function(position) {
6450 var myAt = [],
6451 offset = [0, 0],
6452 isVisible;
6454 if (position) {
6455 // deep extending converts arrays to objects in jQuery <= 1.3.2 :-(
6456 // if (typeof position == 'string' || $.isArray(position)) {
6457 // myAt = $.isArray(position) ? position : position.split(' ');
6459 if (typeof position === 'string' || (typeof position === 'object' && '0' in position)) {
6460 myAt = position.split ? position.split(' ') : [position[0], position[1]];
6461 if (myAt.length === 1) {
6462 myAt[1] = myAt[0];
6465 $.each(['left', 'top'], function(i, offsetPosition) {
6466 if (+myAt[i] === myAt[i]) {
6467 offset[i] = myAt[i];
6468 myAt[i] = offsetPosition;
6472 position = {
6473 my: myAt.join(" "),
6474 at: myAt.join(" "),
6475 offset: offset.join(" ")
6479 position = $.extend({}, $.ui.dialog.prototype.options.position, position);
6480 } else {
6481 position = $.ui.dialog.prototype.options.position;
6484 // need to show the dialog to get the actual offset in the position plugin
6485 isVisible = this.uiDialog.is(':visible');
6486 if (!isVisible) {
6487 this.uiDialog.show();
6489 this.uiDialog
6490 // workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
6491 .css({ top: 0, left: 0 })
6492 .position($.extend({ of: window }, position));
6493 if (!isVisible) {
6494 this.uiDialog.hide();
6498 _setOptions: function( options ) {
6499 var self = this,
6500 resizableOptions = {},
6501 resize = false;
6503 $.each( options, function( key, value ) {
6504 self._setOption( key, value );
6506 if ( key in sizeRelatedOptions ) {
6507 resize = true;
6509 if ( key in resizableRelatedOptions ) {
6510 resizableOptions[ key ] = value;
6514 if ( resize ) {
6515 this._size();
6517 if ( this.uiDialog.is( ":data(resizable)" ) ) {
6518 this.uiDialog.resizable( "option", resizableOptions );
6522 _setOption: function(key, value){
6523 var self = this,
6524 uiDialog = self.uiDialog;
6526 switch (key) {
6527 //handling of deprecated beforeclose (vs beforeClose) option
6528 //Ticket #4669 http://dev.jqueryui.com/ticket/4669
6529 //TODO: remove in 1.9pre
6530 case "beforeclose":
6531 key = "beforeClose";
6532 break;
6533 case "buttons":
6534 self._createButtons(value);
6535 break;
6536 case "closeText":
6537 // ensure that we always pass a string
6538 self.uiDialogTitlebarCloseText.text("" + value);
6539 break;
6540 case "dialogClass":
6541 uiDialog
6542 .removeClass(self.options.dialogClass)
6543 .addClass(uiDialogClasses + value);
6544 break;
6545 case "disabled":
6546 if (value) {
6547 uiDialog.addClass('ui-dialog-disabled');
6548 } else {
6549 uiDialog.removeClass('ui-dialog-disabled');
6551 break;
6552 case "draggable":
6553 var isDraggable = uiDialog.is( ":data(draggable)" );
6554 if ( isDraggable && !value ) {
6555 uiDialog.draggable( "destroy" );
6558 if ( !isDraggable && value ) {
6559 self._makeDraggable();
6561 break;
6562 case "position":
6563 self._position(value);
6564 break;
6565 case "resizable":
6566 // currently resizable, becoming non-resizable
6567 var isResizable = uiDialog.is( ":data(resizable)" );
6568 if (isResizable && !value) {
6569 uiDialog.resizable('destroy');
6572 // currently resizable, changing handles
6573 if (isResizable && typeof value === 'string') {
6574 uiDialog.resizable('option', 'handles', value);
6577 // currently non-resizable, becoming resizable
6578 if (!isResizable && value !== false) {
6579 self._makeResizable(value);
6581 break;
6582 case "title":
6583 // convert whatever was passed in o a string, for html() to not throw up
6584 $(".ui-dialog-title", self.uiDialogTitlebar).html("" + (value || '&#160;'));
6585 break;
6588 $.Widget.prototype._setOption.apply(self, arguments);
6591 _size: function() {
6592 /* If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
6593 * divs will both have width and height set, so we need to reset them
6595 var options = this.options,
6596 nonContentHeight,
6597 minContentHeight,
6598 isVisible = this.uiDialog.is( ":visible" );
6600 // reset content sizing
6601 this.element.show().css({
6602 width: 'auto',
6603 minHeight: 0,
6604 height: 0
6607 if (options.minWidth > options.width) {
6608 options.width = options.minWidth;
6611 // reset wrapper sizing
6612 // determine the height of all the non-content elements
6613 nonContentHeight = this.uiDialog.css({
6614 height: 'auto',
6615 width: options.width
6617 .height();
6618 minContentHeight = Math.max( 0, options.minHeight - nonContentHeight );
6620 if ( options.height === "auto" ) {
6621 // only needed for IE6 support
6622 if ( $.support.minHeight ) {
6623 this.element.css({
6624 minHeight: minContentHeight,
6625 height: "auto"
6627 } else {
6628 this.uiDialog.show();
6629 var autoHeight = this.element.css( "height", "auto" ).height();
6630 if ( !isVisible ) {
6631 this.uiDialog.hide();
6633 this.element.height( Math.max( autoHeight, minContentHeight ) );
6635 } else {
6636 this.element.height( Math.max( options.height - nonContentHeight, 0 ) );
6639 if (this.uiDialog.is(':data(resizable)')) {
6640 this.uiDialog.resizable('option', 'minHeight', this._minHeight());
6645 $.extend($.ui.dialog, {
6646 version: "1.8.16",
6648 uuid: 0,
6649 maxZ: 0,
6651 getTitleId: function($el) {
6652 var id = $el.attr('id');
6653 if (!id) {
6654 this.uuid += 1;
6655 id = this.uuid;
6657 return 'ui-dialog-title-' + id;
6660 overlay: function(dialog) {
6661 this.$el = $.ui.dialog.overlay.create(dialog);
6665 $.extend($.ui.dialog.overlay, {
6666 instances: [],
6667 // reuse old instances due to IE memory leak with alpha transparency (see #5185)
6668 oldInstances: [],
6669 maxZ: 0,
6670 events: $.map('focus,mousedown,mouseup,keydown,keypress,click'.split(','),
6671 function(event) { return event + '.dialog-overlay'; }).join(' '),
6672 create: function(dialog) {
6673 if (this.instances.length === 0) {
6674 // prevent use of anchors and inputs
6675 // we use a setTimeout in case the overlay is created from an
6676 // event that we're going to be cancelling (see #2804)
6677 setTimeout(function() {
6678 // handle $(el).dialog().dialog('close') (see #4065)
6679 if ($.ui.dialog.overlay.instances.length) {
6680 $(document).bind($.ui.dialog.overlay.events, function(event) {
6681 // stop events if the z-index of the target is < the z-index of the overlay
6682 // we cannot return true when we don't want to cancel the event (#3523)
6683 if ($(event.target).zIndex() < $.ui.dialog.overlay.maxZ) {
6684 return false;
6688 }, 1);
6690 // allow closing by pressing the escape key
6691 $(document).bind('keydown.dialog-overlay', function(event) {
6692 if (dialog.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode &&
6693 event.keyCode === $.ui.keyCode.ESCAPE) {
6695 dialog.close(event);
6696 event.preventDefault();
6700 // handle window resize
6701 $(window).bind('resize.dialog-overlay', $.ui.dialog.overlay.resize);
6704 var $el = (this.oldInstances.pop() || $('<div></div>').addClass('ui-widget-overlay'))
6705 .appendTo(document.body)
6706 .css({
6707 width: this.width(),
6708 height: this.height()
6711 if ($.fn.bgiframe) {
6712 $el.bgiframe();
6715 this.instances.push($el);
6716 return $el;
6719 destroy: function($el) {
6720 var indexOf = $.inArray($el, this.instances);
6721 if (indexOf != -1){
6722 this.oldInstances.push(this.instances.splice(indexOf, 1)[0]);
6725 if (this.instances.length === 0) {
6726 $([document, window]).unbind('.dialog-overlay');
6729 $el.remove();
6731 // adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
6732 var maxZ = 0;
6733 $.each(this.instances, function() {
6734 maxZ = Math.max(maxZ, this.css('z-index'));
6736 this.maxZ = maxZ;
6739 height: function() {
6740 var scrollHeight,
6741 offsetHeight;
6742 // handle IE 6
6743 if ($.browser.msie && $.browser.version < 7) {
6744 scrollHeight = Math.max(
6745 document.documentElement.scrollHeight,
6746 document.body.scrollHeight
6748 offsetHeight = Math.max(
6749 document.documentElement.offsetHeight,
6750 document.body.offsetHeight
6753 if (scrollHeight < offsetHeight) {
6754 return $(window).height() + 'px';
6755 } else {
6756 return scrollHeight + 'px';
6758 // handle "good" browsers
6759 } else {
6760 return $(document).height() + 'px';
6764 width: function() {
6765 var scrollWidth,
6766 offsetWidth;
6767 // handle IE
6768 if ( $.browser.msie ) {
6769 scrollWidth = Math.max(
6770 document.documentElement.scrollWidth,
6771 document.body.scrollWidth
6773 offsetWidth = Math.max(
6774 document.documentElement.offsetWidth,
6775 document.body.offsetWidth
6778 if (scrollWidth < offsetWidth) {
6779 return $(window).width() + 'px';
6780 } else {
6781 return scrollWidth + 'px';
6783 // handle "good" browsers
6784 } else {
6785 return $(document).width() + 'px';
6789 resize: function() {
6790 /* If the dialog is draggable and the user drags it past the
6791 * right edge of the window, the document becomes wider so we
6792 * need to stretch the overlay. If the user then drags the
6793 * dialog back to the left, the document will become narrower,
6794 * so we need to shrink the overlay to the appropriate size.
6795 * This is handled by shrinking the overlay before setting it
6796 * to the full document size.
6798 var $overlays = $([]);
6799 $.each($.ui.dialog.overlay.instances, function() {
6800 $overlays = $overlays.add(this);
6803 $overlays.css({
6804 width: 0,
6805 height: 0
6806 }).css({
6807 width: $.ui.dialog.overlay.width(),
6808 height: $.ui.dialog.overlay.height()
6813 $.extend($.ui.dialog.overlay.prototype, {
6814 destroy: function() {
6815 $.ui.dialog.overlay.destroy(this.$el);
6819 }(jQuery));
6821 * jQuery UI Slider 1.8.16
6823 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
6824 * Dual licensed under the MIT or GPL Version 2 licenses.
6825 * http://jquery.org/license
6827 * http://docs.jquery.com/UI/Slider
6829 * Depends:
6830 * jquery.ui.core.js
6831 * jquery.ui.mouse.js
6832 * jquery.ui.widget.js
6834 (function( $, undefined ) {
6836 // number of pages in a slider
6837 // (how many times can you page up/down to go through the whole range)
6838 var numPages = 5;
6840 $.widget( "ui.slider", $.ui.mouse, {
6842 widgetEventPrefix: "slide",
6844 options: {
6845 animate: false,
6846 distance: 0,
6847 max: 100,
6848 min: 0,
6849 orientation: "horizontal",
6850 range: false,
6851 step: 1,
6852 value: 0,
6853 values: null
6856 _create: function() {
6857 var self = this,
6858 o = this.options,
6859 existingHandles = this.element.find( ".ui-slider-handle" ).addClass( "ui-state-default ui-corner-all" ),
6860 handle = "<a class='ui-slider-handle ui-state-default ui-corner-all' href='#'></a>",
6861 handleCount = ( o.values && o.values.length ) || 1,
6862 handles = [];
6864 this._keySliding = false;
6865 this._mouseSliding = false;
6866 this._animateOff = true;
6867 this._handleIndex = null;
6868 this._detectOrientation();
6869 this._mouseInit();
6871 this.element
6872 .addClass( "ui-slider" +
6873 " ui-slider-" + this.orientation +
6874 " ui-widget" +
6875 " ui-widget-content" +
6876 " ui-corner-all" +
6877 ( o.disabled ? " ui-slider-disabled ui-disabled" : "" ) );
6879 this.range = $([]);
6881 if ( o.range ) {
6882 if ( o.range === true ) {
6883 if ( !o.values ) {
6884 o.values = [ this._valueMin(), this._valueMin() ];
6886 if ( o.values.length && o.values.length !== 2 ) {
6887 o.values = [ o.values[0], o.values[0] ];
6891 this.range = $( "<div></div>" )
6892 .appendTo( this.element )
6893 .addClass( "ui-slider-range" +
6894 // note: this isn't the most fittingly semantic framework class for this element,
6895 // but worked best visually with a variety of themes
6896 " ui-widget-header" +
6897 ( ( o.range === "min" || o.range === "max" ) ? " ui-slider-range-" + o.range : "" ) );
6900 for ( var i = existingHandles.length; i < handleCount; i += 1 ) {
6901 handles.push( handle );
6904 this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( self.element ) );
6906 this.handle = this.handles.eq( 0 );
6908 this.handles.add( this.range ).filter( "a" )
6909 .click(function( event ) {
6910 event.preventDefault();
6912 .hover(function() {
6913 if ( !o.disabled ) {
6914 $( this ).addClass( "ui-state-hover" );
6916 }, function() {
6917 $( this ).removeClass( "ui-state-hover" );
6919 .focus(function() {
6920 if ( !o.disabled ) {
6921 $( ".ui-slider .ui-state-focus" ).removeClass( "ui-state-focus" );
6922 $( this ).addClass( "ui-state-focus" );
6923 } else {
6924 $( this ).blur();
6927 .blur(function() {
6928 $( this ).removeClass( "ui-state-focus" );
6931 this.handles.each(function( i ) {
6932 $( this ).data( "index.ui-slider-handle", i );
6935 this.handles
6936 .keydown(function( event ) {
6937 var ret = true,
6938 index = $( this ).data( "index.ui-slider-handle" ),
6939 allowed,
6940 curVal,
6941 newVal,
6942 step;
6944 if ( self.options.disabled ) {
6945 return;
6948 switch ( event.keyCode ) {
6949 case $.ui.keyCode.HOME:
6950 case $.ui.keyCode.END:
6951 case $.ui.keyCode.PAGE_UP:
6952 case $.ui.keyCode.PAGE_DOWN:
6953 case $.ui.keyCode.UP:
6954 case $.ui.keyCode.RIGHT:
6955 case $.ui.keyCode.DOWN:
6956 case $.ui.keyCode.LEFT:
6957 ret = false;
6958 if ( !self._keySliding ) {
6959 self._keySliding = true;
6960 $( this ).addClass( "ui-state-active" );
6961 allowed = self._start( event, index );
6962 if ( allowed === false ) {
6963 return;
6966 break;
6969 step = self.options.step;
6970 if ( self.options.values && self.options.values.length ) {
6971 curVal = newVal = self.values( index );
6972 } else {
6973 curVal = newVal = self.value();
6976 switch ( event.keyCode ) {
6977 case $.ui.keyCode.HOME:
6978 newVal = self._valueMin();
6979 break;
6980 case $.ui.keyCode.END:
6981 newVal = self._valueMax();
6982 break;
6983 case $.ui.keyCode.PAGE_UP:
6984 newVal = self._trimAlignValue( curVal + ( (self._valueMax() - self._valueMin()) / numPages ) );
6985 break;
6986 case $.ui.keyCode.PAGE_DOWN:
6987 newVal = self._trimAlignValue( curVal - ( (self._valueMax() - self._valueMin()) / numPages ) );
6988 break;
6989 case $.ui.keyCode.UP:
6990 case $.ui.keyCode.RIGHT:
6991 if ( curVal === self._valueMax() ) {
6992 return;
6994 newVal = self._trimAlignValue( curVal + step );
6995 break;
6996 case $.ui.keyCode.DOWN:
6997 case $.ui.keyCode.LEFT:
6998 if ( curVal === self._valueMin() ) {
6999 return;
7001 newVal = self._trimAlignValue( curVal - step );
7002 break;
7005 self._slide( event, index, newVal );
7007 return ret;
7010 .keyup(function( event ) {
7011 var index = $( this ).data( "index.ui-slider-handle" );
7013 if ( self._keySliding ) {
7014 self._keySliding = false;
7015 self._stop( event, index );
7016 self._change( event, index );
7017 $( this ).removeClass( "ui-state-active" );
7022 this._refreshValue();
7024 this._animateOff = false;
7027 destroy: function() {
7028 this.handles.remove();
7029 this.range.remove();
7031 this.element
7032 .removeClass( "ui-slider" +
7033 " ui-slider-horizontal" +
7034 " ui-slider-vertical" +
7035 " ui-slider-disabled" +
7036 " ui-widget" +
7037 " ui-widget-content" +
7038 " ui-corner-all" )
7039 .removeData( "slider" )
7040 .unbind( ".slider" );
7042 this._mouseDestroy();
7044 return this;
7047 _mouseCapture: function( event ) {
7048 var o = this.options,
7049 position,
7050 normValue,
7051 distance,
7052 closestHandle,
7053 self,
7054 index,
7055 allowed,
7056 offset,
7057 mouseOverHandle;
7059 if ( o.disabled ) {
7060 return false;
7063 this.elementSize = {
7064 width: this.element.outerWidth(),
7065 height: this.element.outerHeight()
7067 this.elementOffset = this.element.offset();
7069 position = { x: event.pageX, y: event.pageY };
7070 normValue = this._normValueFromMouse( position );
7071 distance = this._valueMax() - this._valueMin() + 1;
7072 self = this;
7073 this.handles.each(function( i ) {
7074 var thisDistance = Math.abs( normValue - self.values(i) );
7075 if ( distance > thisDistance ) {
7076 distance = thisDistance;
7077 closestHandle = $( this );
7078 index = i;
7082 // workaround for bug #3736 (if both handles of a range are at 0,
7083 // the first is always used as the one with least distance,
7084 // and moving it is obviously prevented by preventing negative ranges)
7085 if( o.range === true && this.values(1) === o.min ) {
7086 index += 1;
7087 closestHandle = $( this.handles[index] );
7090 allowed = this._start( event, index );
7091 if ( allowed === false ) {
7092 return false;
7094 this._mouseSliding = true;
7096 self._handleIndex = index;
7098 closestHandle
7099 .addClass( "ui-state-active" )
7100 .focus();
7102 offset = closestHandle.offset();
7103 mouseOverHandle = !$( event.target ).parents().andSelf().is( ".ui-slider-handle" );
7104 this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
7105 left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
7106 top: event.pageY - offset.top -
7107 ( closestHandle.height() / 2 ) -
7108 ( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) -
7109 ( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) +
7110 ( parseInt( closestHandle.css("marginTop"), 10 ) || 0)
7113 if ( !this.handles.hasClass( "ui-state-hover" ) ) {
7114 this._slide( event, index, normValue );
7116 this._animateOff = true;
7117 return true;
7120 _mouseStart: function( event ) {
7121 return true;
7124 _mouseDrag: function( event ) {
7125 var position = { x: event.pageX, y: event.pageY },
7126 normValue = this._normValueFromMouse( position );
7128 this._slide( event, this._handleIndex, normValue );
7130 return false;
7133 _mouseStop: function( event ) {
7134 this.handles.removeClass( "ui-state-active" );
7135 this._mouseSliding = false;
7137 this._stop( event, this._handleIndex );
7138 this._change( event, this._handleIndex );
7140 this._handleIndex = null;
7141 this._clickOffset = null;
7142 this._animateOff = false;
7144 return false;
7147 _detectOrientation: function() {
7148 this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
7151 _normValueFromMouse: function( position ) {
7152 var pixelTotal,
7153 pixelMouse,
7154 percentMouse,
7155 valueTotal,
7156 valueMouse;
7158 if ( this.orientation === "horizontal" ) {
7159 pixelTotal = this.elementSize.width;
7160 pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 );
7161 } else {
7162 pixelTotal = this.elementSize.height;
7163 pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 );
7166 percentMouse = ( pixelMouse / pixelTotal );
7167 if ( percentMouse > 1 ) {
7168 percentMouse = 1;
7170 if ( percentMouse < 0 ) {
7171 percentMouse = 0;
7173 if ( this.orientation === "vertical" ) {
7174 percentMouse = 1 - percentMouse;
7177 valueTotal = this._valueMax() - this._valueMin();
7178 valueMouse = this._valueMin() + percentMouse * valueTotal;
7180 return this._trimAlignValue( valueMouse );
7183 _start: function( event, index ) {
7184 var uiHash = {
7185 handle: this.handles[ index ],
7186 value: this.value()
7188 if ( this.options.values && this.options.values.length ) {
7189 uiHash.value = this.values( index );
7190 uiHash.values = this.values();
7192 return this._trigger( "start", event, uiHash );
7195 _slide: function( event, index, newVal ) {
7196 var otherVal,
7197 newValues,
7198 allowed;
7200 if ( this.options.values && this.options.values.length ) {
7201 otherVal = this.values( index ? 0 : 1 );
7203 if ( ( this.options.values.length === 2 && this.options.range === true ) &&
7204 ( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) )
7206 newVal = otherVal;
7209 if ( newVal !== this.values( index ) ) {
7210 newValues = this.values();
7211 newValues[ index ] = newVal;
7212 // A slide can be canceled by returning false from the slide callback
7213 allowed = this._trigger( "slide", event, {
7214 handle: this.handles[ index ],
7215 value: newVal,
7216 values: newValues
7217 } );
7218 otherVal = this.values( index ? 0 : 1 );
7219 if ( allowed !== false ) {
7220 this.values( index, newVal, true );
7223 } else {
7224 if ( newVal !== this.value() ) {
7225 // A slide can be canceled by returning false from the slide callback
7226 allowed = this._trigger( "slide", event, {
7227 handle: this.handles[ index ],
7228 value: newVal
7229 } );
7230 if ( allowed !== false ) {
7231 this.value( newVal );
7237 _stop: function( event, index ) {
7238 var uiHash = {
7239 handle: this.handles[ index ],
7240 value: this.value()
7242 if ( this.options.values && this.options.values.length ) {
7243 uiHash.value = this.values( index );
7244 uiHash.values = this.values();
7247 this._trigger( "stop", event, uiHash );
7250 _change: function( event, index ) {
7251 if ( !this._keySliding && !this._mouseSliding ) {
7252 var uiHash = {
7253 handle: this.handles[ index ],
7254 value: this.value()
7256 if ( this.options.values && this.options.values.length ) {
7257 uiHash.value = this.values( index );
7258 uiHash.values = this.values();
7261 this._trigger( "change", event, uiHash );
7265 value: function( newValue ) {
7266 if ( arguments.length ) {
7267 this.options.value = this._trimAlignValue( newValue );
7268 this._refreshValue();
7269 this._change( null, 0 );
7270 return;
7273 return this._value();
7276 values: function( index, newValue ) {
7277 var vals,
7278 newValues,
7281 if ( arguments.length > 1 ) {
7282 this.options.values[ index ] = this._trimAlignValue( newValue );
7283 this._refreshValue();
7284 this._change( null, index );
7285 return;
7288 if ( arguments.length ) {
7289 if ( $.isArray( arguments[ 0 ] ) ) {
7290 vals = this.options.values;
7291 newValues = arguments[ 0 ];
7292 for ( i = 0; i < vals.length; i += 1 ) {
7293 vals[ i ] = this._trimAlignValue( newValues[ i ] );
7294 this._change( null, i );
7296 this._refreshValue();
7297 } else {
7298 if ( this.options.values && this.options.values.length ) {
7299 return this._values( index );
7300 } else {
7301 return this.value();
7304 } else {
7305 return this._values();
7309 _setOption: function( key, value ) {
7310 var i,
7311 valsLength = 0;
7313 if ( $.isArray( this.options.values ) ) {
7314 valsLength = this.options.values.length;
7317 $.Widget.prototype._setOption.apply( this, arguments );
7319 switch ( key ) {
7320 case "disabled":
7321 if ( value ) {
7322 this.handles.filter( ".ui-state-focus" ).blur();
7323 this.handles.removeClass( "ui-state-hover" );
7324 this.handles.propAttr( "disabled", true );
7325 this.element.addClass( "ui-disabled" );
7326 } else {
7327 this.handles.propAttr( "disabled", false );
7328 this.element.removeClass( "ui-disabled" );
7330 break;
7331 case "orientation":
7332 this._detectOrientation();
7333 this.element
7334 .removeClass( "ui-slider-horizontal ui-slider-vertical" )
7335 .addClass( "ui-slider-" + this.orientation );
7336 this._refreshValue();
7337 break;
7338 case "value":
7339 this._animateOff = true;
7340 this._refreshValue();
7341 this._change( null, 0 );
7342 this._animateOff = false;
7343 break;
7344 case "values":
7345 this._animateOff = true;
7346 this._refreshValue();
7347 for ( i = 0; i < valsLength; i += 1 ) {
7348 this._change( null, i );
7350 this._animateOff = false;
7351 break;
7355 //internal value getter
7356 // _value() returns value trimmed by min and max, aligned by step
7357 _value: function() {
7358 var val = this.options.value;
7359 val = this._trimAlignValue( val );
7361 return val;
7364 //internal values getter
7365 // _values() returns array of values trimmed by min and max, aligned by step
7366 // _values( index ) returns single value trimmed by min and max, aligned by step
7367 _values: function( index ) {
7368 var val,
7369 vals,
7372 if ( arguments.length ) {
7373 val = this.options.values[ index ];
7374 val = this._trimAlignValue( val );
7376 return val;
7377 } else {
7378 // .slice() creates a copy of the array
7379 // this copy gets trimmed by min and max and then returned
7380 vals = this.options.values.slice();
7381 for ( i = 0; i < vals.length; i+= 1) {
7382 vals[ i ] = this._trimAlignValue( vals[ i ] );
7385 return vals;
7389 // returns the step-aligned value that val is closest to, between (inclusive) min and max
7390 _trimAlignValue: function( val ) {
7391 if ( val <= this._valueMin() ) {
7392 return this._valueMin();
7394 if ( val >= this._valueMax() ) {
7395 return this._valueMax();
7397 var step = ( this.options.step > 0 ) ? this.options.step : 1,
7398 valModStep = (val - this._valueMin()) % step,
7399 alignValue = val - valModStep;
7401 if ( Math.abs(valModStep) * 2 >= step ) {
7402 alignValue += ( valModStep > 0 ) ? step : ( -step );
7405 // Since JavaScript has problems with large floats, round
7406 // the final value to 5 digits after the decimal point (see #4124)
7407 return parseFloat( alignValue.toFixed(5) );
7410 _valueMin: function() {
7411 return this.options.min;
7414 _valueMax: function() {
7415 return this.options.max;
7418 _refreshValue: function() {
7419 var oRange = this.options.range,
7420 o = this.options,
7421 self = this,
7422 animate = ( !this._animateOff ) ? o.animate : false,
7423 valPercent,
7424 _set = {},
7425 lastValPercent,
7426 value,
7427 valueMin,
7428 valueMax;
7430 if ( this.options.values && this.options.values.length ) {
7431 this.handles.each(function( i, j ) {
7432 valPercent = ( self.values(i) - self._valueMin() ) / ( self._valueMax() - self._valueMin() ) * 100;
7433 _set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
7434 $( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
7435 if ( self.options.range === true ) {
7436 if ( self.orientation === "horizontal" ) {
7437 if ( i === 0 ) {
7438 self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate );
7440 if ( i === 1 ) {
7441 self.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
7443 } else {
7444 if ( i === 0 ) {
7445 self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate );
7447 if ( i === 1 ) {
7448 self.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
7452 lastValPercent = valPercent;
7454 } else {
7455 value = this.value();
7456 valueMin = this._valueMin();
7457 valueMax = this._valueMax();
7458 valPercent = ( valueMax !== valueMin ) ?
7459 ( value - valueMin ) / ( valueMax - valueMin ) * 100 :
7461 _set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
7462 this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
7464 if ( oRange === "min" && this.orientation === "horizontal" ) {
7465 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate );
7467 if ( oRange === "max" && this.orientation === "horizontal" ) {
7468 this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
7470 if ( oRange === "min" && this.orientation === "vertical" ) {
7471 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate );
7473 if ( oRange === "max" && this.orientation === "vertical" ) {
7474 this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
7481 $.extend( $.ui.slider, {
7482 version: "1.8.16"
7485 }(jQuery));
7487 * jQuery UI Tabs 1.8.16
7489 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
7490 * Dual licensed under the MIT or GPL Version 2 licenses.
7491 * http://jquery.org/license
7493 * http://docs.jquery.com/UI/Tabs
7495 * Depends:
7496 * jquery.ui.core.js
7497 * jquery.ui.widget.js
7499 (function( $, undefined ) {
7501 var tabId = 0,
7502 listId = 0;
7504 function getNextTabId() {
7505 return ++tabId;
7508 function getNextListId() {
7509 return ++listId;
7512 $.widget( "ui.tabs", {
7513 options: {
7514 add: null,
7515 ajaxOptions: null,
7516 cache: false,
7517 cookie: null, // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true }
7518 collapsible: false,
7519 disable: null,
7520 disabled: [],
7521 enable: null,
7522 event: "click",
7523 fx: null, // e.g. { height: 'toggle', opacity: 'toggle', duration: 200 }
7524 idPrefix: "ui-tabs-",
7525 load: null,
7526 panelTemplate: "<div></div>",
7527 remove: null,
7528 select: null,
7529 show: null,
7530 spinner: "<em>Loading&#8230;</em>",
7531 tabTemplate: "<li><a href='#{href}'><span>#{label}</span></a></li>"
7534 _create: function() {
7535 this._tabify( true );
7538 _setOption: function( key, value ) {
7539 if ( key == "selected" ) {
7540 if (this.options.collapsible && value == this.options.selected ) {
7541 return;
7543 this.select( value );
7544 } else {
7545 this.options[ key ] = value;
7546 this._tabify();
7550 _tabId: function( a ) {
7551 return a.title && a.title.replace( /\s/g, "_" ).replace( /[^\w\u00c0-\uFFFF-]/g, "" ) ||
7552 this.options.idPrefix + getNextTabId();
7555 _sanitizeSelector: function( hash ) {
7556 // we need this because an id may contain a ":"
7557 return hash.replace( /:/g, "\\:" );
7560 _cookie: function() {
7561 var cookie = this.cookie ||
7562 ( this.cookie = this.options.cookie.name || "ui-tabs-" + getNextListId() );
7563 return $.cookie.apply( null, [ cookie ].concat( $.makeArray( arguments ) ) );
7566 _ui: function( tab, panel ) {
7567 return {
7568 tab: tab,
7569 panel: panel,
7570 index: this.anchors.index( tab )
7574 _cleanup: function() {
7575 // restore all former loading tabs labels
7576 this.lis.filter( ".ui-state-processing" )
7577 .removeClass( "ui-state-processing" )
7578 .find( "span:data(label.tabs)" )
7579 .each(function() {
7580 var el = $( this );
7581 el.html( el.data( "label.tabs" ) ).removeData( "label.tabs" );
7585 _tabify: function( init ) {
7586 var self = this,
7587 o = this.options,
7588 fragmentId = /^#.+/; // Safari 2 reports '#' for an empty hash
7590 this.list = this.element.find( "ol,ul" ).eq( 0 );
7591 this.lis = $( " > li:has(a[href])", this.list );
7592 this.anchors = this.lis.map(function() {
7593 return $( "a", this )[ 0 ];
7595 this.panels = $( [] );
7597 this.anchors.each(function( i, a ) {
7598 var href = $( a ).attr( "href" );
7599 // For dynamically created HTML that contains a hash as href IE < 8 expands
7600 // such href to the full page url with hash and then misinterprets tab as ajax.
7601 // Same consideration applies for an added tab with a fragment identifier
7602 // since a[href=#fragment-identifier] does unexpectedly not match.
7603 // Thus normalize href attribute...
7604 var hrefBase = href.split( "#" )[ 0 ],
7605 baseEl;
7606 if ( hrefBase && ( hrefBase === location.toString().split( "#" )[ 0 ] ||
7607 ( baseEl = $( "base" )[ 0 ]) && hrefBase === baseEl.href ) ) {
7608 href = a.hash;
7609 a.href = href;
7612 // inline tab
7613 if ( fragmentId.test( href ) ) {
7614 self.panels = self.panels.add( self.element.find( self._sanitizeSelector( href ) ) );
7615 // remote tab
7616 // prevent loading the page itself if href is just "#"
7617 } else if ( href && href !== "#" ) {
7618 // required for restore on destroy
7619 $.data( a, "href.tabs", href );
7621 // TODO until #3808 is fixed strip fragment identifier from url
7622 // (IE fails to load from such url)
7623 $.data( a, "load.tabs", href.replace( /#.*$/, "" ) );
7625 var id = self._tabId( a );
7626 a.href = "#" + id;
7627 var $panel = self.element.find( "#" + id );
7628 if ( !$panel.length ) {
7629 $panel = $( o.panelTemplate )
7630 .attr( "id", id )
7631 .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
7632 .insertAfter( self.panels[ i - 1 ] || self.list );
7633 $panel.data( "destroy.tabs", true );
7635 self.panels = self.panels.add( $panel );
7636 // invalid tab href
7637 } else {
7638 o.disabled.push( i );
7642 // initialization from scratch
7643 if ( init ) {
7644 // attach necessary classes for styling
7645 this.element.addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" );
7646 this.list.addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" );
7647 this.lis.addClass( "ui-state-default ui-corner-top" );
7648 this.panels.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" );
7650 // Selected tab
7651 // use "selected" option or try to retrieve:
7652 // 1. from fragment identifier in url
7653 // 2. from cookie
7654 // 3. from selected class attribute on <li>
7655 if ( o.selected === undefined ) {
7656 if ( location.hash ) {
7657 this.anchors.each(function( i, a ) {
7658 if ( a.hash == location.hash ) {
7659 o.selected = i;
7660 return false;
7664 if ( typeof o.selected !== "number" && o.cookie ) {
7665 o.selected = parseInt( self._cookie(), 10 );
7667 if ( typeof o.selected !== "number" && this.lis.filter( ".ui-tabs-selected" ).length ) {
7668 o.selected = this.lis.index( this.lis.filter( ".ui-tabs-selected" ) );
7670 o.selected = o.selected || ( this.lis.length ? 0 : -1 );
7671 } else if ( o.selected === null ) { // usage of null is deprecated, TODO remove in next release
7672 o.selected = -1;
7675 // sanity check - default to first tab...
7676 o.selected = ( ( o.selected >= 0 && this.anchors[ o.selected ] ) || o.selected < 0 )
7677 ? o.selected
7678 : 0;
7680 // Take disabling tabs via class attribute from HTML
7681 // into account and update option properly.
7682 // A selected tab cannot become disabled.
7683 o.disabled = $.unique( o.disabled.concat(
7684 $.map( this.lis.filter( ".ui-state-disabled" ), function( n, i ) {
7685 return self.lis.index( n );
7687 ) ).sort();
7689 if ( $.inArray( o.selected, o.disabled ) != -1 ) {
7690 o.disabled.splice( $.inArray( o.selected, o.disabled ), 1 );
7693 // highlight selected tab
7694 this.panels.addClass( "ui-tabs-hide" );
7695 this.lis.removeClass( "ui-tabs-selected ui-state-active" );
7696 // check for length avoids error when initializing empty list
7697 if ( o.selected >= 0 && this.anchors.length ) {
7698 self.element.find( self._sanitizeSelector( self.anchors[ o.selected ].hash ) ).removeClass( "ui-tabs-hide" );
7699 this.lis.eq( o.selected ).addClass( "ui-tabs-selected ui-state-active" );
7701 // seems to be expected behavior that the show callback is fired
7702 self.element.queue( "tabs", function() {
7703 self._trigger( "show", null,
7704 self._ui( self.anchors[ o.selected ], self.element.find( self._sanitizeSelector( self.anchors[ o.selected ].hash ) )[ 0 ] ) );
7707 this.load( o.selected );
7710 // clean up to avoid memory leaks in certain versions of IE 6
7711 // TODO: namespace this event
7712 $( window ).bind( "unload", function() {
7713 self.lis.add( self.anchors ).unbind( ".tabs" );
7714 self.lis = self.anchors = self.panels = null;
7716 // update selected after add/remove
7717 } else {
7718 o.selected = this.lis.index( this.lis.filter( ".ui-tabs-selected" ) );
7721 // update collapsible
7722 // TODO: use .toggleClass()
7723 this.element[ o.collapsible ? "addClass" : "removeClass" ]( "ui-tabs-collapsible" );
7725 // set or update cookie after init and add/remove respectively
7726 if ( o.cookie ) {
7727 this._cookie( o.selected, o.cookie );
7730 // disable tabs
7731 for ( var i = 0, li; ( li = this.lis[ i ] ); i++ ) {
7732 $( li )[ $.inArray( i, o.disabled ) != -1 &&
7733 // TODO: use .toggleClass()
7734 !$( li ).hasClass( "ui-tabs-selected" ) ? "addClass" : "removeClass" ]( "ui-state-disabled" );
7737 // reset cache if switching from cached to not cached
7738 if ( o.cache === false ) {
7739 this.anchors.removeData( "cache.tabs" );
7742 // remove all handlers before, tabify may run on existing tabs after add or option change
7743 this.lis.add( this.anchors ).unbind( ".tabs" );
7745 if ( o.event !== "mouseover" ) {
7746 var addState = function( state, el ) {
7747 if ( el.is( ":not(.ui-state-disabled)" ) ) {
7748 el.addClass( "ui-state-" + state );
7751 var removeState = function( state, el ) {
7752 el.removeClass( "ui-state-" + state );
7754 this.lis.bind( "mouseover.tabs" , function() {
7755 addState( "hover", $( this ) );
7757 this.lis.bind( "mouseout.tabs", function() {
7758 removeState( "hover", $( this ) );
7760 this.anchors.bind( "focus.tabs", function() {
7761 addState( "focus", $( this ).closest( "li" ) );
7763 this.anchors.bind( "blur.tabs", function() {
7764 removeState( "focus", $( this ).closest( "li" ) );
7768 // set up animations
7769 var hideFx, showFx;
7770 if ( o.fx ) {
7771 if ( $.isArray( o.fx ) ) {
7772 hideFx = o.fx[ 0 ];
7773 showFx = o.fx[ 1 ];
7774 } else {
7775 hideFx = showFx = o.fx;
7779 // Reset certain styles left over from animation
7780 // and prevent IE's ClearType bug...
7781 function resetStyle( $el, fx ) {
7782 $el.css( "display", "" );
7783 if ( !$.support.opacity && fx.opacity ) {
7784 $el[ 0 ].style.removeAttribute( "filter" );
7788 // Show a tab...
7789 var showTab = showFx
7790 ? function( clicked, $show ) {
7791 $( clicked ).closest( "li" ).addClass( "ui-tabs-selected ui-state-active" );
7792 $show.hide().removeClass( "ui-tabs-hide" ) // avoid flicker that way
7793 .animate( showFx, showFx.duration || "normal", function() {
7794 resetStyle( $show, showFx );
7795 self._trigger( "show", null, self._ui( clicked, $show[ 0 ] ) );
7798 : function( clicked, $show ) {
7799 $( clicked ).closest( "li" ).addClass( "ui-tabs-selected ui-state-active" );
7800 $show.removeClass( "ui-tabs-hide" );
7801 self._trigger( "show", null, self._ui( clicked, $show[ 0 ] ) );
7804 // Hide a tab, $show is optional...
7805 var hideTab = hideFx
7806 ? function( clicked, $hide ) {
7807 $hide.animate( hideFx, hideFx.duration || "normal", function() {
7808 self.lis.removeClass( "ui-tabs-selected ui-state-active" );
7809 $hide.addClass( "ui-tabs-hide" );
7810 resetStyle( $hide, hideFx );
7811 self.element.dequeue( "tabs" );
7814 : function( clicked, $hide, $show ) {
7815 self.lis.removeClass( "ui-tabs-selected ui-state-active" );
7816 $hide.addClass( "ui-tabs-hide" );
7817 self.element.dequeue( "tabs" );
7820 // attach tab event handler, unbind to avoid duplicates from former tabifying...
7821 this.anchors.bind( o.event + ".tabs", function() {
7822 var el = this,
7823 $li = $(el).closest( "li" ),
7824 $hide = self.panels.filter( ":not(.ui-tabs-hide)" ),
7825 $show = self.element.find( self._sanitizeSelector( el.hash ) );
7827 // If tab is already selected and not collapsible or tab disabled or
7828 // or is already loading or click callback returns false stop here.
7829 // Check if click handler returns false last so that it is not executed
7830 // for a disabled or loading tab!
7831 if ( ( $li.hasClass( "ui-tabs-selected" ) && !o.collapsible) ||
7832 $li.hasClass( "ui-state-disabled" ) ||
7833 $li.hasClass( "ui-state-processing" ) ||
7834 self.panels.filter( ":animated" ).length ||
7835 self._trigger( "select", null, self._ui( this, $show[ 0 ] ) ) === false ) {
7836 this.blur();
7837 return false;
7840 o.selected = self.anchors.index( this );
7842 self.abort();
7844 // if tab may be closed
7845 if ( o.collapsible ) {
7846 if ( $li.hasClass( "ui-tabs-selected" ) ) {
7847 o.selected = -1;
7849 if ( o.cookie ) {
7850 self._cookie( o.selected, o.cookie );
7853 self.element.queue( "tabs", function() {
7854 hideTab( el, $hide );
7855 }).dequeue( "tabs" );
7857 this.blur();
7858 return false;
7859 } else if ( !$hide.length ) {
7860 if ( o.cookie ) {
7861 self._cookie( o.selected, o.cookie );
7864 self.element.queue( "tabs", function() {
7865 showTab( el, $show );
7868 // TODO make passing in node possible, see also http://dev.jqueryui.com/ticket/3171
7869 self.load( self.anchors.index( this ) );
7871 this.blur();
7872 return false;
7876 if ( o.cookie ) {
7877 self._cookie( o.selected, o.cookie );
7880 // show new tab
7881 if ( $show.length ) {
7882 if ( $hide.length ) {
7883 self.element.queue( "tabs", function() {
7884 hideTab( el, $hide );
7887 self.element.queue( "tabs", function() {
7888 showTab( el, $show );
7891 self.load( self.anchors.index( this ) );
7892 } else {
7893 throw "jQuery UI Tabs: Mismatching fragment identifier.";
7896 // Prevent IE from keeping other link focussed when using the back button
7897 // and remove dotted border from clicked link. This is controlled via CSS
7898 // in modern browsers; blur() removes focus from address bar in Firefox
7899 // which can become a usability and annoying problem with tabs('rotate').
7900 if ( $.browser.msie ) {
7901 this.blur();
7905 // disable click in any case
7906 this.anchors.bind( "click.tabs", function(){
7907 return false;
7911 _getIndex: function( index ) {
7912 // meta-function to give users option to provide a href string instead of a numerical index.
7913 // also sanitizes numerical indexes to valid values.
7914 if ( typeof index == "string" ) {
7915 index = this.anchors.index( this.anchors.filter( "[href$=" + index + "]" ) );
7918 return index;
7921 destroy: function() {
7922 var o = this.options;
7924 this.abort();
7926 this.element
7927 .unbind( ".tabs" )
7928 .removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" )
7929 .removeData( "tabs" );
7931 this.list.removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" );
7933 this.anchors.each(function() {
7934 var href = $.data( this, "href.tabs" );
7935 if ( href ) {
7936 this.href = href;
7938 var $this = $( this ).unbind( ".tabs" );
7939 $.each( [ "href", "load", "cache" ], function( i, prefix ) {
7940 $this.removeData( prefix + ".tabs" );
7944 this.lis.unbind( ".tabs" ).add( this.panels ).each(function() {
7945 if ( $.data( this, "destroy.tabs" ) ) {
7946 $( this ).remove();
7947 } else {
7948 $( this ).removeClass([
7949 "ui-state-default",
7950 "ui-corner-top",
7951 "ui-tabs-selected",
7952 "ui-state-active",
7953 "ui-state-hover",
7954 "ui-state-focus",
7955 "ui-state-disabled",
7956 "ui-tabs-panel",
7957 "ui-widget-content",
7958 "ui-corner-bottom",
7959 "ui-tabs-hide"
7960 ].join( " " ) );
7964 if ( o.cookie ) {
7965 this._cookie( null, o.cookie );
7968 return this;
7971 add: function( url, label, index ) {
7972 if ( index === undefined ) {
7973 index = this.anchors.length;
7976 var self = this,
7977 o = this.options,
7978 $li = $( o.tabTemplate.replace( /#\{href\}/g, url ).replace( /#\{label\}/g, label ) ),
7979 id = !url.indexOf( "#" ) ? url.replace( "#", "" ) : this._tabId( $( "a", $li )[ 0 ] );
7981 $li.addClass( "ui-state-default ui-corner-top" ).data( "destroy.tabs", true );
7983 // try to find an existing element before creating a new one
7984 var $panel = self.element.find( "#" + id );
7985 if ( !$panel.length ) {
7986 $panel = $( o.panelTemplate )
7987 .attr( "id", id )
7988 .data( "destroy.tabs", true );
7990 $panel.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide" );
7992 if ( index >= this.lis.length ) {
7993 $li.appendTo( this.list );
7994 $panel.appendTo( this.list[ 0 ].parentNode );
7995 } else {
7996 $li.insertBefore( this.lis[ index ] );
7997 $panel.insertBefore( this.panels[ index ] );
8000 o.disabled = $.map( o.disabled, function( n, i ) {
8001 return n >= index ? ++n : n;
8004 this._tabify();
8006 if ( this.anchors.length == 1 ) {
8007 o.selected = 0;
8008 $li.addClass( "ui-tabs-selected ui-state-active" );
8009 $panel.removeClass( "ui-tabs-hide" );
8010 this.element.queue( "tabs", function() {
8011 self._trigger( "show", null, self._ui( self.anchors[ 0 ], self.panels[ 0 ] ) );
8014 this.load( 0 );
8017 this._trigger( "add", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
8018 return this;
8021 remove: function( index ) {
8022 index = this._getIndex( index );
8023 var o = this.options,
8024 $li = this.lis.eq( index ).remove(),
8025 $panel = this.panels.eq( index ).remove();
8027 // If selected tab was removed focus tab to the right or
8028 // in case the last tab was removed the tab to the left.
8029 if ( $li.hasClass( "ui-tabs-selected" ) && this.anchors.length > 1) {
8030 this.select( index + ( index + 1 < this.anchors.length ? 1 : -1 ) );
8033 o.disabled = $.map(
8034 $.grep( o.disabled, function(n, i) {
8035 return n != index;
8037 function( n, i ) {
8038 return n >= index ? --n : n;
8041 this._tabify();
8043 this._trigger( "remove", null, this._ui( $li.find( "a" )[ 0 ], $panel[ 0 ] ) );
8044 return this;
8047 enable: function( index ) {
8048 index = this._getIndex( index );
8049 var o = this.options;
8050 if ( $.inArray( index, o.disabled ) == -1 ) {
8051 return;
8054 this.lis.eq( index ).removeClass( "ui-state-disabled" );
8055 o.disabled = $.grep( o.disabled, function( n, i ) {
8056 return n != index;
8059 this._trigger( "enable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
8060 return this;
8063 disable: function( index ) {
8064 index = this._getIndex( index );
8065 var self = this, o = this.options;
8066 // cannot disable already selected tab
8067 if ( index != o.selected ) {
8068 this.lis.eq( index ).addClass( "ui-state-disabled" );
8070 o.disabled.push( index );
8071 o.disabled.sort();
8073 this._trigger( "disable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
8076 return this;
8079 select: function( index ) {
8080 index = this._getIndex( index );
8081 if ( index == -1 ) {
8082 if ( this.options.collapsible && this.options.selected != -1 ) {
8083 index = this.options.selected;
8084 } else {
8085 return this;
8088 this.anchors.eq( index ).trigger( this.options.event + ".tabs" );
8089 return this;
8092 load: function( index ) {
8093 index = this._getIndex( index );
8094 var self = this,
8095 o = this.options,
8096 a = this.anchors.eq( index )[ 0 ],
8097 url = $.data( a, "load.tabs" );
8099 this.abort();
8101 // not remote or from cache
8102 if ( !url || this.element.queue( "tabs" ).length !== 0 && $.data( a, "cache.tabs" ) ) {
8103 this.element.dequeue( "tabs" );
8104 return;
8107 // load remote from here on
8108 this.lis.eq( index ).addClass( "ui-state-processing" );
8110 if ( o.spinner ) {
8111 var span = $( "span", a );
8112 span.data( "label.tabs", span.html() ).html( o.spinner );
8115 this.xhr = $.ajax( $.extend( {}, o.ajaxOptions, {
8116 url: url,
8117 success: function( r, s ) {
8118 self.element.find( self._sanitizeSelector( a.hash ) ).html( r );
8120 // take care of tab labels
8121 self._cleanup();
8123 if ( o.cache ) {
8124 $.data( a, "cache.tabs", true );
8127 self._trigger( "load", null, self._ui( self.anchors[ index ], self.panels[ index ] ) );
8128 try {
8129 o.ajaxOptions.success( r, s );
8131 catch ( e ) {}
8133 error: function( xhr, s, e ) {
8134 // take care of tab labels
8135 self._cleanup();
8137 self._trigger( "load", null, self._ui( self.anchors[ index ], self.panels[ index ] ) );
8138 try {
8139 // Passing index avoid a race condition when this method is
8140 // called after the user has selected another tab.
8141 // Pass the anchor that initiated this request allows
8142 // loadError to manipulate the tab content panel via $(a.hash)
8143 o.ajaxOptions.error( xhr, s, index, a );
8145 catch ( e ) {}
8147 } ) );
8149 // last, so that load event is fired before show...
8150 self.element.dequeue( "tabs" );
8152 return this;
8155 abort: function() {
8156 // stop possibly running animations
8157 this.element.queue( [] );
8158 this.panels.stop( false, true );
8160 // "tabs" queue must not contain more than two elements,
8161 // which are the callbacks for the latest clicked tab...
8162 this.element.queue( "tabs", this.element.queue( "tabs" ).splice( -2, 2 ) );
8164 // terminate pending requests from other tabs
8165 if ( this.xhr ) {
8166 this.xhr.abort();
8167 delete this.xhr;
8170 // take care of tab labels
8171 this._cleanup();
8172 return this;
8175 url: function( index, url ) {
8176 this.anchors.eq( index ).removeData( "cache.tabs" ).data( "load.tabs", url );
8177 return this;
8180 length: function() {
8181 return this.anchors.length;
8185 $.extend( $.ui.tabs, {
8186 version: "1.8.16"
8190 * Tabs Extensions
8194 * Rotate
8196 $.extend( $.ui.tabs.prototype, {
8197 rotation: null,
8198 rotate: function( ms, continuing ) {
8199 var self = this,
8200 o = this.options;
8202 var rotate = self._rotate || ( self._rotate = function( e ) {
8203 clearTimeout( self.rotation );
8204 self.rotation = setTimeout(function() {
8205 var t = o.selected;
8206 self.select( ++t < self.anchors.length ? t : 0 );
8207 }, ms );
8209 if ( e ) {
8210 e.stopPropagation();
8214 var stop = self._unrotate || ( self._unrotate = !continuing
8215 ? function(e) {
8216 if (e.clientX) { // in case of a true click
8217 self.rotate(null);
8220 : function( e ) {
8221 t = o.selected;
8222 rotate();
8225 // start rotation
8226 if ( ms ) {
8227 this.element.bind( "tabsshow", rotate );
8228 this.anchors.bind( o.event + ".tabs", stop );
8229 rotate();
8230 // stop rotation
8231 } else {
8232 clearTimeout( self.rotation );
8233 this.element.unbind( "tabsshow", rotate );
8234 this.anchors.unbind( o.event + ".tabs", stop );
8235 delete this._rotate;
8236 delete this._unrotate;
8239 return this;
8243 })( jQuery );
8245 * jQuery UI Datepicker 1.8.16
8247 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
8248 * Dual licensed under the MIT or GPL Version 2 licenses.
8249 * http://jquery.org/license
8251 * http://docs.jquery.com/UI/Datepicker
8253 * Depends:
8254 * jquery.ui.core.js
8256 (function( $, undefined ) {
8258 $.extend($.ui, { datepicker: { version: "1.8.16" } });
8260 var PROP_NAME = 'datepicker';
8261 var dpuuid = new Date().getTime();
8262 var instActive;
8264 /* Date picker manager.
8265 Use the singleton instance of this class, $.datepicker, to interact with the date picker.
8266 Settings for (groups of) date pickers are maintained in an instance object,
8267 allowing multiple different settings on the same page. */
8269 function Datepicker() {
8270 this.debug = false; // Change this to true to start debugging
8271 this._curInst = null; // The current instance in use
8272 this._keyEvent = false; // If the last event was a key event
8273 this._disabledInputs = []; // List of date picker inputs that have been disabled
8274 this._datepickerShowing = false; // True if the popup picker is showing , false if not
8275 this._inDialog = false; // True if showing within a "dialog", false if not
8276 this._mainDivId = 'ui-datepicker-div'; // The ID of the main datepicker division
8277 this._inlineClass = 'ui-datepicker-inline'; // The name of the inline marker class
8278 this._appendClass = 'ui-datepicker-append'; // The name of the append marker class
8279 this._triggerClass = 'ui-datepicker-trigger'; // The name of the trigger marker class
8280 this._dialogClass = 'ui-datepicker-dialog'; // The name of the dialog marker class
8281 this._disableClass = 'ui-datepicker-disabled'; // The name of the disabled covering marker class
8282 this._unselectableClass = 'ui-datepicker-unselectable'; // The name of the unselectable cell marker class
8283 this._currentClass = 'ui-datepicker-current-day'; // The name of the current day marker class
8284 this._dayOverClass = 'ui-datepicker-days-cell-over'; // The name of the day hover marker class
8285 this.regional = []; // Available regional settings, indexed by language code
8286 this.regional[''] = { // Default regional settings
8287 closeText: 'Done', // Display text for close link
8288 prevText: 'Prev', // Display text for previous month link
8289 nextText: 'Next', // Display text for next month link
8290 currentText: 'Today', // Display text for current month link
8291 monthNames: ['January','February','March','April','May','June',
8292 'July','August','September','October','November','December'], // Names of months for drop-down and formatting
8293 monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], // For formatting
8294 dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], // For formatting
8295 dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], // For formatting
8296 dayNamesMin: ['Su','Mo','Tu','We','Th','Fr','Sa'], // Column headings for days starting at Sunday
8297 weekHeader: 'Wk', // Column header for week of the year
8298 dateFormat: 'mm/dd/yy', // See format options on parseDate
8299 firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
8300 isRTL: false, // True if right-to-left language, false if left-to-right
8301 showMonthAfterYear: false, // True if the year select precedes month, false for month then year
8302 yearSuffix: '' // Additional text to append to the year in the month headers
8304 this._defaults = { // Global defaults for all the date picker instances
8305 showOn: 'focus', // 'focus' for popup on focus,
8306 // 'button' for trigger button, or 'both' for either
8307 showAnim: 'fadeIn', // Name of jQuery animation for popup
8308 showOptions: {}, // Options for enhanced animations
8309 defaultDate: null, // Used when field is blank: actual date,
8310 // +/-number for offset from today, null for today
8311 appendText: '', // Display text following the input box, e.g. showing the format
8312 buttonText: '...', // Text for trigger button
8313 buttonImage: '', // URL for trigger button image
8314 buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
8315 hideIfNoPrevNext: false, // True to hide next/previous month links
8316 // if not applicable, false to just disable them
8317 navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
8318 gotoCurrent: false, // True if today link goes back to current selection instead
8319 changeMonth: false, // True if month can be selected directly, false if only prev/next
8320 changeYear: false, // True if year can be selected directly, false if only prev/next
8321 yearRange: 'c-10:c+10', // Range of years to display in drop-down,
8322 // either relative to today's year (-nn:+nn), relative to currently displayed year
8323 // (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
8324 showOtherMonths: false, // True to show dates in other months, false to leave blank
8325 selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
8326 showWeek: false, // True to show week of the year, false to not show it
8327 calculateWeek: this.iso8601Week, // How to calculate the week of the year,
8328 // takes a Date and returns the number of the week for it
8329 shortYearCutoff: '+10', // Short year values < this are in the current century,
8330 // > this are in the previous century,
8331 // string value starting with '+' for current year + value
8332 minDate: null, // The earliest selectable date, or null for no limit
8333 maxDate: null, // The latest selectable date, or null for no limit
8334 duration: 'fast', // Duration of display/closure
8335 beforeShowDay: null, // Function that takes a date and returns an array with
8336 // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or '',
8337 // [2] = cell title (optional), e.g. $.datepicker.noWeekends
8338 beforeShow: null, // Function that takes an input field and
8339 // returns a set of custom settings for the date picker
8340 onSelect: null, // Define a callback function when a date is selected
8341 onChangeMonthYear: null, // Define a callback function when the month or year is changed
8342 onClose: null, // Define a callback function when the datepicker is closed
8343 numberOfMonths: 1, // Number of months to show at a time
8344 showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
8345 stepMonths: 1, // Number of months to step back/forward
8346 stepBigMonths: 12, // Number of months to step back/forward for the big links
8347 altField: '', // Selector for an alternate field to store selected dates into
8348 altFormat: '', // The date format to use for the alternate field
8349 constrainInput: true, // The input is constrained by the current date format
8350 showButtonPanel: false, // True to show button panel, false to not show it
8351 autoSize: false, // True to size the input for the date format, false to leave as is
8352 disabled: false // The initial disabled state
8354 $.extend(this._defaults, this.regional['']);
8355 this.dpDiv = bindHover($('<div id="' + this._mainDivId + '" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>'));
8358 $.extend(Datepicker.prototype, {
8359 /* Class name added to elements to indicate already configured with a date picker. */
8360 markerClassName: 'hasDatepicker',
8362 //Keep track of the maximum number of rows displayed (see #7043)
8363 maxRows: 4,
8365 /* Debug logging (if enabled). */
8366 log: function () {
8367 if (this.debug)
8368 console.log.apply('', arguments);
8371 // TODO rename to "widget" when switching to widget factory
8372 _widgetDatepicker: function() {
8373 return this.dpDiv;
8376 /* Override the default settings for all instances of the date picker.
8377 @param settings object - the new settings to use as defaults (anonymous object)
8378 @return the manager object */
8379 setDefaults: function(settings) {
8380 extendRemove(this._defaults, settings || {});
8381 return this;
8384 /* Attach the date picker to a jQuery selection.
8385 @param target element - the target input field or division or span
8386 @param settings object - the new settings to use for this date picker instance (anonymous) */
8387 _attachDatepicker: function(target, settings) {
8388 // check for settings on the control itself - in namespace 'date:'
8389 var inlineSettings = null;
8390 for (var attrName in this._defaults) {
8391 var attrValue = target.getAttribute('date:' + attrName);
8392 if (attrValue) {
8393 inlineSettings = inlineSettings || {};
8394 try {
8395 inlineSettings[attrName] = eval(attrValue);
8396 } catch (err) {
8397 inlineSettings[attrName] = attrValue;
8401 var nodeName = target.nodeName.toLowerCase();
8402 var inline = (nodeName == 'div' || nodeName == 'span');
8403 if (!target.id) {
8404 this.uuid += 1;
8405 target.id = 'dp' + this.uuid;
8407 var inst = this._newInst($(target), inline);
8408 inst.settings = $.extend({}, settings || {}, inlineSettings || {});
8409 if (nodeName == 'input') {
8410 this._connectDatepicker(target, inst);
8411 } else if (inline) {
8412 this._inlineDatepicker(target, inst);
8416 /* Create a new instance object. */
8417 _newInst: function(target, inline) {
8418 var id = target[0].id.replace(/([^A-Za-z0-9_-])/g, '\\\\$1'); // escape jQuery meta chars
8419 return {id: id, input: target, // associated target
8420 selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
8421 drawMonth: 0, drawYear: 0, // month being drawn
8422 inline: inline, // is datepicker inline or not
8423 dpDiv: (!inline ? this.dpDiv : // presentation div
8424 bindHover($('<div class="' + this._inlineClass + ' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>')))};
8427 /* Attach the date picker to an input field. */
8428 _connectDatepicker: function(target, inst) {
8429 var input = $(target);
8430 inst.append = $([]);
8431 inst.trigger = $([]);
8432 if (input.hasClass(this.markerClassName))
8433 return;
8434 this._attachments(input, inst);
8435 input.addClass(this.markerClassName).keydown(this._doKeyDown).
8436 keypress(this._doKeyPress).keyup(this._doKeyUp).
8437 bind("setData.datepicker", function(event, key, value) {
8438 inst.settings[key] = value;
8439 }).bind("getData.datepicker", function(event, key) {
8440 return this._get(inst, key);
8442 this._autoSize(inst);
8443 $.data(target, PROP_NAME, inst);
8444 //If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665)
8445 if( inst.settings.disabled ) {
8446 this._disableDatepicker( target );
8450 /* Make attachments based on settings. */
8451 _attachments: function(input, inst) {
8452 var appendText = this._get(inst, 'appendText');
8453 var isRTL = this._get(inst, 'isRTL');
8454 if (inst.append)
8455 inst.append.remove();
8456 if (appendText) {
8457 inst.append = $('<span class="' + this._appendClass + '">' + appendText + '</span>');
8458 input[isRTL ? 'before' : 'after'](inst.append);
8460 input.unbind('focus', this._showDatepicker);
8461 if (inst.trigger)
8462 inst.trigger.remove();
8463 var showOn = this._get(inst, 'showOn');
8464 if (showOn == 'focus' || showOn == 'both') // pop-up date picker when in the marked field
8465 input.focus(this._showDatepicker);
8466 if (showOn == 'button' || showOn == 'both') { // pop-up date picker when button clicked
8467 var buttonText = this._get(inst, 'buttonText');
8468 var buttonImage = this._get(inst, 'buttonImage');
8469 inst.trigger = $(this._get(inst, 'buttonImageOnly') ?
8470 $('<img/>').addClass(this._triggerClass).
8471 attr({ src: buttonImage, alt: buttonText, title: buttonText }) :
8472 $('<button type="button"></button>').addClass(this._triggerClass).
8473 html(buttonImage == '' ? buttonText : $('<img/>').attr(
8474 { src:buttonImage, alt:buttonText, title:buttonText })));
8475 input[isRTL ? 'before' : 'after'](inst.trigger);
8476 inst.trigger.click(function() {
8477 if ($.datepicker._datepickerShowing && $.datepicker._lastInput == input[0])
8478 $.datepicker._hideDatepicker();
8479 else
8480 $.datepicker._showDatepicker(input[0]);
8481 return false;
8486 /* Apply the maximum length for the date format. */
8487 _autoSize: function(inst) {
8488 if (this._get(inst, 'autoSize') && !inst.inline) {
8489 var date = new Date(2009, 12 - 1, 20); // Ensure double digits
8490 var dateFormat = this._get(inst, 'dateFormat');
8491 if (dateFormat.match(/[DM]/)) {
8492 var findMax = function(names) {
8493 var max = 0;
8494 var maxI = 0;
8495 for (var i = 0; i < names.length; i++) {
8496 if (names[i].length > max) {
8497 max = names[i].length;
8498 maxI = i;
8501 return maxI;
8503 date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ?
8504 'monthNames' : 'monthNamesShort'))));
8505 date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ?
8506 'dayNames' : 'dayNamesShort'))) + 20 - date.getDay());
8508 inst.input.attr('size', this._formatDate(inst, date).length);
8512 /* Attach an inline date picker to a div. */
8513 _inlineDatepicker: function(target, inst) {
8514 var divSpan = $(target);
8515 if (divSpan.hasClass(this.markerClassName))
8516 return;
8517 divSpan.addClass(this.markerClassName).append(inst.dpDiv).
8518 bind("setData.datepicker", function(event, key, value){
8519 inst.settings[key] = value;
8520 }).bind("getData.datepicker", function(event, key){
8521 return this._get(inst, key);
8523 $.data(target, PROP_NAME, inst);
8524 this._setDate(inst, this._getDefaultDate(inst), true);
8525 this._updateDatepicker(inst);
8526 this._updateAlternate(inst);
8527 //If disabled option is true, disable the datepicker before showing it (see ticket #5665)
8528 if( inst.settings.disabled ) {
8529 this._disableDatepicker( target );
8531 // Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements
8532 // http://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height
8533 inst.dpDiv.css( "display", "block" );
8536 /* Pop-up the date picker in a "dialog" box.
8537 @param input element - ignored
8538 @param date string or Date - the initial date to display
8539 @param onSelect function - the function to call when a date is selected
8540 @param settings object - update the dialog date picker instance's settings (anonymous object)
8541 @param pos int[2] - coordinates for the dialog's position within the screen or
8542 event - with x/y coordinates or
8543 leave empty for default (screen centre)
8544 @return the manager object */
8545 _dialogDatepicker: function(input, date, onSelect, settings, pos) {
8546 var inst = this._dialogInst; // internal instance
8547 if (!inst) {
8548 this.uuid += 1;
8549 var id = 'dp' + this.uuid;
8550 this._dialogInput = $('<input type="text" id="' + id +
8551 '" style="position: absolute; top: -100px; width: 0px; z-index: -10;"/>');
8552 this._dialogInput.keydown(this._doKeyDown);
8553 $('body').append(this._dialogInput);
8554 inst = this._dialogInst = this._newInst(this._dialogInput, false);
8555 inst.settings = {};
8556 $.data(this._dialogInput[0], PROP_NAME, inst);
8558 extendRemove(inst.settings, settings || {});
8559 date = (date && date.constructor == Date ? this._formatDate(inst, date) : date);
8560 this._dialogInput.val(date);
8562 this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);
8563 if (!this._pos) {
8564 var browserWidth = document.documentElement.clientWidth;
8565 var browserHeight = document.documentElement.clientHeight;
8566 var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
8567 var scrollY = document.documentElement.scrollTop || document.body.scrollTop;
8568 this._pos = // should use actual width/height below
8569 [(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY];
8572 // move input on screen for focus, but hidden behind dialog
8573 this._dialogInput.css('left', (this._pos[0] + 20) + 'px').css('top', this._pos[1] + 'px');
8574 inst.settings.onSelect = onSelect;
8575 this._inDialog = true;
8576 this.dpDiv.addClass(this._dialogClass);
8577 this._showDatepicker(this._dialogInput[0]);
8578 if ($.blockUI)
8579 $.blockUI(this.dpDiv);
8580 $.data(this._dialogInput[0], PROP_NAME, inst);
8581 return this;
8584 /* Detach a datepicker from its control.
8585 @param target element - the target input field or division or span */
8586 _destroyDatepicker: function(target) {
8587 var $target = $(target);
8588 var inst = $.data(target, PROP_NAME);
8589 if (!$target.hasClass(this.markerClassName)) {
8590 return;
8592 var nodeName = target.nodeName.toLowerCase();
8593 $.removeData(target, PROP_NAME);
8594 if (nodeName == 'input') {
8595 inst.append.remove();
8596 inst.trigger.remove();
8597 $target.removeClass(this.markerClassName).
8598 unbind('focus', this._showDatepicker).
8599 unbind('keydown', this._doKeyDown).
8600 unbind('keypress', this._doKeyPress).
8601 unbind('keyup', this._doKeyUp);
8602 } else if (nodeName == 'div' || nodeName == 'span')
8603 $target.removeClass(this.markerClassName).empty();
8606 /* Enable the date picker to a jQuery selection.
8607 @param target element - the target input field or division or span */
8608 _enableDatepicker: function(target) {
8609 var $target = $(target);
8610 var inst = $.data(target, PROP_NAME);
8611 if (!$target.hasClass(this.markerClassName)) {
8612 return;
8614 var nodeName = target.nodeName.toLowerCase();
8615 if (nodeName == 'input') {
8616 target.disabled = false;
8617 inst.trigger.filter('button').
8618 each(function() { this.disabled = false; }).end().
8619 filter('img').css({opacity: '1.0', cursor: ''});
8621 else if (nodeName == 'div' || nodeName == 'span') {
8622 var inline = $target.children('.' + this._inlineClass);
8623 inline.children().removeClass('ui-state-disabled');
8624 inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
8625 removeAttr("disabled");
8627 this._disabledInputs = $.map(this._disabledInputs,
8628 function(value) { return (value == target ? null : value); }); // delete entry
8631 /* Disable the date picker to a jQuery selection.
8632 @param target element - the target input field or division or span */
8633 _disableDatepicker: function(target) {
8634 var $target = $(target);
8635 var inst = $.data(target, PROP_NAME);
8636 if (!$target.hasClass(this.markerClassName)) {
8637 return;
8639 var nodeName = target.nodeName.toLowerCase();
8640 if (nodeName == 'input') {
8641 target.disabled = true;
8642 inst.trigger.filter('button').
8643 each(function() { this.disabled = true; }).end().
8644 filter('img').css({opacity: '0.5', cursor: 'default'});
8646 else if (nodeName == 'div' || nodeName == 'span') {
8647 var inline = $target.children('.' + this._inlineClass);
8648 inline.children().addClass('ui-state-disabled');
8649 inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
8650 attr("disabled", "disabled");
8652 this._disabledInputs = $.map(this._disabledInputs,
8653 function(value) { return (value == target ? null : value); }); // delete entry
8654 this._disabledInputs[this._disabledInputs.length] = target;
8657 /* Is the first field in a jQuery collection disabled as a datepicker?
8658 @param target element - the target input field or division or span
8659 @return boolean - true if disabled, false if enabled */
8660 _isDisabledDatepicker: function(target) {
8661 if (!target) {
8662 return false;
8664 for (var i = 0; i < this._disabledInputs.length; i++) {
8665 if (this._disabledInputs[i] == target)
8666 return true;
8668 return false;
8671 /* Retrieve the instance data for the target control.
8672 @param target element - the target input field or division or span
8673 @return object - the associated instance data
8674 @throws error if a jQuery problem getting data */
8675 _getInst: function(target) {
8676 try {
8677 return $.data(target, PROP_NAME);
8679 catch (err) {
8680 throw 'Missing instance data for this datepicker';
8684 /* Update or retrieve the settings for a date picker attached to an input field or division.
8685 @param target element - the target input field or division or span
8686 @param name object - the new settings to update or
8687 string - the name of the setting to change or retrieve,
8688 when retrieving also 'all' for all instance settings or
8689 'defaults' for all global defaults
8690 @param value any - the new value for the setting
8691 (omit if above is an object or to retrieve a value) */
8692 _optionDatepicker: function(target, name, value) {
8693 var inst = this._getInst(target);
8694 if (arguments.length == 2 && typeof name == 'string') {
8695 return (name == 'defaults' ? $.extend({}, $.datepicker._defaults) :
8696 (inst ? (name == 'all' ? $.extend({}, inst.settings) :
8697 this._get(inst, name)) : null));
8699 var settings = name || {};
8700 if (typeof name == 'string') {
8701 settings = {};
8702 settings[name] = value;
8704 if (inst) {
8705 if (this._curInst == inst) {
8706 this._hideDatepicker();
8708 var date = this._getDateDatepicker(target, true);
8709 var minDate = this._getMinMaxDate(inst, 'min');
8710 var maxDate = this._getMinMaxDate(inst, 'max');
8711 extendRemove(inst.settings, settings);
8712 // reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided
8713 if (minDate !== null && settings['dateFormat'] !== undefined && settings['minDate'] === undefined)
8714 inst.settings.minDate = this._formatDate(inst, minDate);
8715 if (maxDate !== null && settings['dateFormat'] !== undefined && settings['maxDate'] === undefined)
8716 inst.settings.maxDate = this._formatDate(inst, maxDate);
8717 this._attachments($(target), inst);
8718 this._autoSize(inst);
8719 this._setDate(inst, date);
8720 this._updateAlternate(inst);
8721 this._updateDatepicker(inst);
8725 // change method deprecated
8726 _changeDatepicker: function(target, name, value) {
8727 this._optionDatepicker(target, name, value);
8730 /* Redraw the date picker attached to an input field or division.
8731 @param target element - the target input field or division or span */
8732 _refreshDatepicker: function(target) {
8733 var inst = this._getInst(target);
8734 if (inst) {
8735 this._updateDatepicker(inst);
8739 /* Set the dates for a jQuery selection.
8740 @param target element - the target input field or division or span
8741 @param date Date - the new date */
8742 _setDateDatepicker: function(target, date) {
8743 var inst = this._getInst(target);
8744 if (inst) {
8745 this._setDate(inst, date);
8746 this._updateDatepicker(inst);
8747 this._updateAlternate(inst);
8751 /* Get the date(s) for the first entry in a jQuery selection.
8752 @param target element - the target input field or division or span
8753 @param noDefault boolean - true if no default date is to be used
8754 @return Date - the current date */
8755 _getDateDatepicker: function(target, noDefault) {
8756 var inst = this._getInst(target);
8757 if (inst && !inst.inline)
8758 this._setDateFromField(inst, noDefault);
8759 return (inst ? this._getDate(inst) : null);
8762 /* Handle keystrokes. */
8763 _doKeyDown: function(event) {
8764 var inst = $.datepicker._getInst(event.target);
8765 var handled = true;
8766 var isRTL = inst.dpDiv.is('.ui-datepicker-rtl');
8767 inst._keyEvent = true;
8768 if ($.datepicker._datepickerShowing)
8769 switch (event.keyCode) {
8770 case 9: $.datepicker._hideDatepicker();
8771 handled = false;
8772 break; // hide on tab out
8773 case 13: var sel = $('td.' + $.datepicker._dayOverClass + ':not(.' +
8774 $.datepicker._currentClass + ')', inst.dpDiv);
8775 if (sel[0])
8776 $.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);
8777 var onSelect = $.datepicker._get(inst, 'onSelect');
8778 if (onSelect) {
8779 var dateStr = $.datepicker._formatDate(inst);
8781 // trigger custom callback
8782 onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);
8784 else
8785 $.datepicker._hideDatepicker();
8786 return false; // don't submit the form
8787 break; // select the value on enter
8788 case 27: $.datepicker._hideDatepicker();
8789 break; // hide on escape
8790 case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
8791 -$.datepicker._get(inst, 'stepBigMonths') :
8792 -$.datepicker._get(inst, 'stepMonths')), 'M');
8793 break; // previous month/year on page up/+ ctrl
8794 case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
8795 +$.datepicker._get(inst, 'stepBigMonths') :
8796 +$.datepicker._get(inst, 'stepMonths')), 'M');
8797 break; // next month/year on page down/+ ctrl
8798 case 35: if (event.ctrlKey || event.metaKey) $.datepicker._clearDate(event.target);
8799 handled = event.ctrlKey || event.metaKey;
8800 break; // clear on ctrl or command +end
8801 case 36: if (event.ctrlKey || event.metaKey) $.datepicker._gotoToday(event.target);
8802 handled = event.ctrlKey || event.metaKey;
8803 break; // current on ctrl or command +home
8804 case 37: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), 'D');
8805 handled = event.ctrlKey || event.metaKey;
8806 // -1 day on ctrl or command +left
8807 if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
8808 -$.datepicker._get(inst, 'stepBigMonths') :
8809 -$.datepicker._get(inst, 'stepMonths')), 'M');
8810 // next month/year on alt +left on Mac
8811 break;
8812 case 38: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, -7, 'D');
8813 handled = event.ctrlKey || event.metaKey;
8814 break; // -1 week on ctrl or command +up
8815 case 39: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), 'D');
8816 handled = event.ctrlKey || event.metaKey;
8817 // +1 day on ctrl or command +right
8818 if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
8819 +$.datepicker._get(inst, 'stepBigMonths') :
8820 +$.datepicker._get(inst, 'stepMonths')), 'M');
8821 // next month/year on alt +right
8822 break;
8823 case 40: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, +7, 'D');
8824 handled = event.ctrlKey || event.metaKey;
8825 break; // +1 week on ctrl or command +down
8826 default: handled = false;
8828 else if (event.keyCode == 36 && event.ctrlKey) // display the date picker on ctrl+home
8829 $.datepicker._showDatepicker(this);
8830 else {
8831 handled = false;
8833 if (handled) {
8834 event.preventDefault();
8835 event.stopPropagation();
8839 /* Filter entered characters - based on date format. */
8840 _doKeyPress: function(event) {
8841 var inst = $.datepicker._getInst(event.target);
8842 if ($.datepicker._get(inst, 'constrainInput')) {
8843 var chars = $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat'));
8844 var chr = String.fromCharCode(event.charCode == undefined ? event.keyCode : event.charCode);
8845 return event.ctrlKey || event.metaKey || (chr < ' ' || !chars || chars.indexOf(chr) > -1);
8849 /* Synchronise manual entry and field/alternate field. */
8850 _doKeyUp: function(event) {
8851 var inst = $.datepicker._getInst(event.target);
8852 if (inst.input.val() != inst.lastVal) {
8853 try {
8854 var date = $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
8855 (inst.input ? inst.input.val() : null),
8856 $.datepicker._getFormatConfig(inst));
8857 if (date) { // only if valid
8858 $.datepicker._setDateFromField(inst);
8859 $.datepicker._updateAlternate(inst);
8860 $.datepicker._updateDatepicker(inst);
8863 catch (event) {
8864 $.datepicker.log(event);
8867 return true;
8870 /* Pop-up the date picker for a given input field.
8871 If false returned from beforeShow event handler do not show.
8872 @param input element - the input field attached to the date picker or
8873 event - if triggered by focus */
8874 _showDatepicker: function(input) {
8875 input = input.target || input;
8876 if (input.nodeName.toLowerCase() != 'input') // find from button/image trigger
8877 input = $('input', input.parentNode)[0];
8878 if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput == input) // already here
8879 return;
8880 var inst = $.datepicker._getInst(input);
8881 if ($.datepicker._curInst && $.datepicker._curInst != inst) {
8882 if ( $.datepicker._datepickerShowing ) {
8883 $.datepicker._triggerOnClose($.datepicker._curInst);
8885 $.datepicker._curInst.dpDiv.stop(true, true);
8887 var beforeShow = $.datepicker._get(inst, 'beforeShow');
8888 var beforeShowSettings = beforeShow ? beforeShow.apply(input, [input, inst]) : {};
8889 if(beforeShowSettings === false){
8890 //false
8891 return;
8893 extendRemove(inst.settings, beforeShowSettings);
8894 inst.lastVal = null;
8895 $.datepicker._lastInput = input;
8896 $.datepicker._setDateFromField(inst);
8897 if ($.datepicker._inDialog) // hide cursor
8898 input.value = '';
8899 if (!$.datepicker._pos) { // position below input
8900 $.datepicker._pos = $.datepicker._findPos(input);
8901 $.datepicker._pos[1] += input.offsetHeight; // add the height
8903 var isFixed = false;
8904 $(input).parents().each(function() {
8905 isFixed |= $(this).css('position') == 'fixed';
8906 return !isFixed;
8908 if (isFixed && $.browser.opera) { // correction for Opera when fixed and scrolled
8909 $.datepicker._pos[0] -= document.documentElement.scrollLeft;
8910 $.datepicker._pos[1] -= document.documentElement.scrollTop;
8912 var offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]};
8913 $.datepicker._pos = null;
8914 //to avoid flashes on Firefox
8915 inst.dpDiv.empty();
8916 // determine sizing offscreen
8917 inst.dpDiv.css({position: 'absolute', display: 'block', top: '-1000px'});
8918 $.datepicker._updateDatepicker(inst);
8919 // fix width for dynamic number of date pickers
8920 // and adjust position before showing
8921 offset = $.datepicker._checkOffset(inst, offset, isFixed);
8922 inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ?
8923 'static' : (isFixed ? 'fixed' : 'absolute')), display: 'none',
8924 left: offset.left + 'px', top: offset.top + 'px'});
8925 if (!inst.inline) {
8926 var showAnim = $.datepicker._get(inst, 'showAnim');
8927 var duration = $.datepicker._get(inst, 'duration');
8928 var postProcess = function() {
8929 var cover = inst.dpDiv.find('iframe.ui-datepicker-cover'); // IE6- only
8930 if( !! cover.length ){
8931 var borders = $.datepicker._getBorders(inst.dpDiv);
8932 cover.css({left: -borders[0], top: -borders[1],
8933 width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()});
8936 inst.dpDiv.zIndex($(input).zIndex()+1);
8937 $.datepicker._datepickerShowing = true;
8938 if ($.effects && $.effects[showAnim])
8939 inst.dpDiv.show(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
8940 else
8941 inst.dpDiv[showAnim || 'show']((showAnim ? duration : null), postProcess);
8942 if (!showAnim || !duration)
8943 postProcess();
8944 if (inst.input.is(':visible') && !inst.input.is(':disabled'))
8945 inst.input.focus();
8946 $.datepicker._curInst = inst;
8950 /* Generate the date picker content. */
8951 _updateDatepicker: function(inst) {
8952 var self = this;
8953 self.maxRows = 4; //Reset the max number of rows being displayed (see #7043)
8954 var borders = $.datepicker._getBorders(inst.dpDiv);
8955 instActive = inst; // for delegate hover events
8956 inst.dpDiv.empty().append(this._generateHTML(inst));
8957 var cover = inst.dpDiv.find('iframe.ui-datepicker-cover'); // IE6- only
8958 if( !!cover.length ){ //avoid call to outerXXXX() when not in IE6
8959 cover.css({left: -borders[0], top: -borders[1], width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()})
8961 inst.dpDiv.find('.' + this._dayOverClass + ' a').mouseover();
8962 var numMonths = this._getNumberOfMonths(inst);
8963 var cols = numMonths[1];
8964 var width = 17;
8965 inst.dpDiv.removeClass('ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4').width('');
8966 if (cols > 1)
8967 inst.dpDiv.addClass('ui-datepicker-multi-' + cols).css('width', (width * cols) + 'em');
8968 inst.dpDiv[(numMonths[0] != 1 || numMonths[1] != 1 ? 'add' : 'remove') +
8969 'Class']('ui-datepicker-multi');
8970 inst.dpDiv[(this._get(inst, 'isRTL') ? 'add' : 'remove') +
8971 'Class']('ui-datepicker-rtl');
8972 if (inst == $.datepicker._curInst && $.datepicker._datepickerShowing && inst.input &&
8973 // #6694 - don't focus the input if it's already focused
8974 // this breaks the change event in IE
8975 inst.input.is(':visible') && !inst.input.is(':disabled') && inst.input[0] != document.activeElement)
8976 inst.input.focus();
8977 // deffered render of the years select (to avoid flashes on Firefox)
8978 if( inst.yearshtml ){
8979 var origyearshtml = inst.yearshtml;
8980 setTimeout(function(){
8981 //assure that inst.yearshtml didn't change.
8982 if( origyearshtml === inst.yearshtml && inst.yearshtml ){
8983 inst.dpDiv.find('select.ui-datepicker-year:first').replaceWith(inst.yearshtml);
8985 origyearshtml = inst.yearshtml = null;
8986 }, 0);
8990 /* Retrieve the size of left and top borders for an element.
8991 @param elem (jQuery object) the element of interest
8992 @return (number[2]) the left and top borders */
8993 _getBorders: function(elem) {
8994 var convert = function(value) {
8995 return {thin: 1, medium: 2, thick: 3}[value] || value;
8997 return [parseFloat(convert(elem.css('border-left-width'))),
8998 parseFloat(convert(elem.css('border-top-width')))];
9001 /* Check positioning to remain on screen. */
9002 _checkOffset: function(inst, offset, isFixed) {
9003 var dpWidth = inst.dpDiv.outerWidth();
9004 var dpHeight = inst.dpDiv.outerHeight();
9005 var inputWidth = inst.input ? inst.input.outerWidth() : 0;
9006 var inputHeight = inst.input ? inst.input.outerHeight() : 0;
9007 var viewWidth = document.documentElement.clientWidth + $(document).scrollLeft();
9008 var viewHeight = document.documentElement.clientHeight + $(document).scrollTop();
9010 offset.left -= (this._get(inst, 'isRTL') ? (dpWidth - inputWidth) : 0);
9011 offset.left -= (isFixed && offset.left == inst.input.offset().left) ? $(document).scrollLeft() : 0;
9012 offset.top -= (isFixed && offset.top == (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;
9014 // now check if datepicker is showing outside window viewport - move to a better place if so.
9015 offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?
9016 Math.abs(offset.left + dpWidth - viewWidth) : 0);
9017 offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?
9018 Math.abs(dpHeight + inputHeight) : 0);
9020 return offset;
9023 /* Find an object's position on the screen. */
9024 _findPos: function(obj) {
9025 var inst = this._getInst(obj);
9026 var isRTL = this._get(inst, 'isRTL');
9027 while (obj && (obj.type == 'hidden' || obj.nodeType != 1 || $.expr.filters.hidden(obj))) {
9028 obj = obj[isRTL ? 'previousSibling' : 'nextSibling'];
9030 var position = $(obj).offset();
9031 return [position.left, position.top];
9034 /* Trigger custom callback of onClose. */
9035 _triggerOnClose: function(inst) {
9036 var onClose = this._get(inst, 'onClose');
9037 if (onClose)
9038 onClose.apply((inst.input ? inst.input[0] : null),
9039 [(inst.input ? inst.input.val() : ''), inst]);
9042 /* Hide the date picker from view.
9043 @param input element - the input field attached to the date picker */
9044 _hideDatepicker: function(input) {
9045 var inst = this._curInst;
9046 if (!inst || (input && inst != $.data(input, PROP_NAME)))
9047 return;
9048 if (this._datepickerShowing) {
9049 var showAnim = this._get(inst, 'showAnim');
9050 var duration = this._get(inst, 'duration');
9051 var postProcess = function() {
9052 $.datepicker._tidyDialog(inst);
9053 this._curInst = null;
9055 if ($.effects && $.effects[showAnim])
9056 inst.dpDiv.hide(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
9057 else
9058 inst.dpDiv[(showAnim == 'slideDown' ? 'slideUp' :
9059 (showAnim == 'fadeIn' ? 'fadeOut' : 'hide'))]((showAnim ? duration : null), postProcess);
9060 if (!showAnim)
9061 postProcess();
9062 $.datepicker._triggerOnClose(inst);
9063 this._datepickerShowing = false;
9064 this._lastInput = null;
9065 if (this._inDialog) {
9066 this._dialogInput.css({ position: 'absolute', left: '0', top: '-100px' });
9067 if ($.blockUI) {
9068 $.unblockUI();
9069 $('body').append(this.dpDiv);
9072 this._inDialog = false;
9076 /* Tidy up after a dialog display. */
9077 _tidyDialog: function(inst) {
9078 inst.dpDiv.removeClass(this._dialogClass).unbind('.ui-datepicker-calendar');
9081 /* Close date picker if clicked elsewhere. */
9082 _checkExternalClick: function(event) {
9083 if (!$.datepicker._curInst)
9084 return;
9085 var $target = $(event.target);
9086 if ($target[0].id != $.datepicker._mainDivId &&
9087 $target.parents('#' + $.datepicker._mainDivId).length == 0 &&
9088 !$target.hasClass($.datepicker.markerClassName) &&
9089 !$target.hasClass($.datepicker._triggerClass) &&
9090 $.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI))
9091 $.datepicker._hideDatepicker();
9094 /* Adjust one of the date sub-fields. */
9095 _adjustDate: function(id, offset, period) {
9096 var target = $(id);
9097 var inst = this._getInst(target[0]);
9098 if (this._isDisabledDatepicker(target[0])) {
9099 return;
9101 this._adjustInstDate(inst, offset +
9102 (period == 'M' ? this._get(inst, 'showCurrentAtPos') : 0), // undo positioning
9103 period);
9104 this._updateDatepicker(inst);
9107 /* Action for current link. */
9108 _gotoToday: function(id) {
9109 var target = $(id);
9110 var inst = this._getInst(target[0]);
9111 if (this._get(inst, 'gotoCurrent') && inst.currentDay) {
9112 inst.selectedDay = inst.currentDay;
9113 inst.drawMonth = inst.selectedMonth = inst.currentMonth;
9114 inst.drawYear = inst.selectedYear = inst.currentYear;
9116 else {
9117 var date = new Date();
9118 inst.selectedDay = date.getDate();
9119 inst.drawMonth = inst.selectedMonth = date.getMonth();
9120 inst.drawYear = inst.selectedYear = date.getFullYear();
9122 this._notifyChange(inst);
9123 this._adjustDate(target);
9126 /* Action for selecting a new month/year. */
9127 _selectMonthYear: function(id, select, period) {
9128 var target = $(id);
9129 var inst = this._getInst(target[0]);
9130 inst['selected' + (period == 'M' ? 'Month' : 'Year')] =
9131 inst['draw' + (period == 'M' ? 'Month' : 'Year')] =
9132 parseInt(select.options[select.selectedIndex].value,10);
9133 this._notifyChange(inst);
9134 this._adjustDate(target);
9137 /* Action for selecting a day. */
9138 _selectDay: function(id, month, year, td) {
9139 var target = $(id);
9140 if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) {
9141 return;
9143 var inst = this._getInst(target[0]);
9144 inst.selectedDay = inst.currentDay = $('a', td).html();
9145 inst.selectedMonth = inst.currentMonth = month;
9146 inst.selectedYear = inst.currentYear = year;
9147 this._selectDate(id, this._formatDate(inst,
9148 inst.currentDay, inst.currentMonth, inst.currentYear));
9151 /* Erase the input field and hide the date picker. */
9152 _clearDate: function(id) {
9153 var target = $(id);
9154 var inst = this._getInst(target[0]);
9155 this._selectDate(target, '');
9158 /* Update the input field with the selected date. */
9159 _selectDate: function(id, dateStr) {
9160 var target = $(id);
9161 var inst = this._getInst(target[0]);
9162 dateStr = (dateStr != null ? dateStr : this._formatDate(inst));
9163 if (inst.input)
9164 inst.input.val(dateStr);
9165 this._updateAlternate(inst);
9166 var onSelect = this._get(inst, 'onSelect');
9167 if (onSelect)
9168 onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); // trigger custom callback
9169 else if (inst.input)
9170 inst.input.trigger('change'); // fire the change event
9171 if (inst.inline)
9172 this._updateDatepicker(inst);
9173 else {
9174 this._hideDatepicker();
9175 this._lastInput = inst.input[0];
9176 if (typeof(inst.input[0]) != 'object')
9177 inst.input.focus(); // restore focus
9178 this._lastInput = null;
9182 /* Update any alternate field to synchronise with the main field. */
9183 _updateAlternate: function(inst) {
9184 var altField = this._get(inst, 'altField');
9185 if (altField) { // update alternate field too
9186 var altFormat = this._get(inst, 'altFormat') || this._get(inst, 'dateFormat');
9187 var date = this._getDate(inst);
9188 var dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst));
9189 $(altField).each(function() { $(this).val(dateStr); });
9193 /* Set as beforeShowDay function to prevent selection of weekends.
9194 @param date Date - the date to customise
9195 @return [boolean, string] - is this date selectable?, what is its CSS class? */
9196 noWeekends: function(date) {
9197 var day = date.getDay();
9198 return [(day > 0 && day < 6), ''];
9201 /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
9202 @param date Date - the date to get the week for
9203 @return number - the number of the week within the year that contains this date */
9204 iso8601Week: function(date) {
9205 var checkDate = new Date(date.getTime());
9206 // Find Thursday of this week starting on Monday
9207 checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7));
9208 var time = checkDate.getTime();
9209 checkDate.setMonth(0); // Compare with Jan 1
9210 checkDate.setDate(1);
9211 return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
9214 /* Parse a string value into a date object.
9215 See formatDate below for the possible formats.
9217 @param format string - the expected format of the date
9218 @param value string - the date in the above format
9219 @param settings Object - attributes include:
9220 shortYearCutoff number - the cutoff year for determining the century (optional)
9221 dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
9222 dayNames string[7] - names of the days from Sunday (optional)
9223 monthNamesShort string[12] - abbreviated names of the months (optional)
9224 monthNames string[12] - names of the months (optional)
9225 @return Date - the extracted date value or null if value is blank */
9226 parseDate: function (format, value, settings) {
9227 if (format == null || value == null)
9228 throw 'Invalid arguments';
9229 value = (typeof value == 'object' ? value.toString() : value + '');
9230 if (value == '')
9231 return null;
9232 var shortYearCutoff = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff;
9233 shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff :
9234 new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
9235 var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
9236 var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
9237 var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
9238 var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
9239 var year = -1;
9240 var month = -1;
9241 var day = -1;
9242 var doy = -1;
9243 var literal = false;
9244 // Check whether a format character is doubled
9245 var lookAhead = function(match) {
9246 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
9247 if (matches)
9248 iFormat++;
9249 return matches;
9251 // Extract a number from the string value
9252 var getNumber = function(match) {
9253 var isDoubled = lookAhead(match);
9254 var size = (match == '@' ? 14 : (match == '!' ? 20 :
9255 (match == 'y' && isDoubled ? 4 : (match == 'o' ? 3 : 2))));
9256 var digits = new RegExp('^\\d{1,' + size + '}');
9257 var num = value.substring(iValue).match(digits);
9258 if (!num)
9259 throw 'Missing number at position ' + iValue;
9260 iValue += num[0].length;
9261 return parseInt(num[0], 10);
9263 // Extract a name from the string value and convert to an index
9264 var getName = function(match, shortNames, longNames) {
9265 var names = $.map(lookAhead(match) ? longNames : shortNames, function (v, k) {
9266 return [ [k, v] ];
9267 }).sort(function (a, b) {
9268 return -(a[1].length - b[1].length);
9270 var index = -1;
9271 $.each(names, function (i, pair) {
9272 var name = pair[1];
9273 if (value.substr(iValue, name.length).toLowerCase() == name.toLowerCase()) {
9274 index = pair[0];
9275 iValue += name.length;
9276 return false;
9279 if (index != -1)
9280 return index + 1;
9281 else
9282 throw 'Unknown name at position ' + iValue;
9284 // Confirm that a literal character matches the string value
9285 var checkLiteral = function() {
9286 if (value.charAt(iValue) != format.charAt(iFormat))
9287 throw 'Unexpected literal at position ' + iValue;
9288 iValue++;
9290 var iValue = 0;
9291 for (var iFormat = 0; iFormat < format.length; iFormat++) {
9292 if (literal)
9293 if (format.charAt(iFormat) == "'" && !lookAhead("'"))
9294 literal = false;
9295 else
9296 checkLiteral();
9297 else
9298 switch (format.charAt(iFormat)) {
9299 case 'd':
9300 day = getNumber('d');
9301 break;
9302 case 'D':
9303 getName('D', dayNamesShort, dayNames);
9304 break;
9305 case 'o':
9306 doy = getNumber('o');
9307 break;
9308 case 'm':
9309 month = getNumber('m');
9310 break;
9311 case 'M':
9312 month = getName('M', monthNamesShort, monthNames);
9313 break;
9314 case 'y':
9315 year = getNumber('y');
9316 break;
9317 case '@':
9318 var date = new Date(getNumber('@'));
9319 year = date.getFullYear();
9320 month = date.getMonth() + 1;
9321 day = date.getDate();
9322 break;
9323 case '!':
9324 var date = new Date((getNumber('!') - this._ticksTo1970) / 10000);
9325 year = date.getFullYear();
9326 month = date.getMonth() + 1;
9327 day = date.getDate();
9328 break;
9329 case "'":
9330 if (lookAhead("'"))
9331 checkLiteral();
9332 else
9333 literal = true;
9334 break;
9335 default:
9336 checkLiteral();
9339 if (iValue < value.length){
9340 throw "Extra/unparsed characters found in date: " + value.substring(iValue);
9342 if (year == -1)
9343 year = new Date().getFullYear();
9344 else if (year < 100)
9345 year += new Date().getFullYear() - new Date().getFullYear() % 100 +
9346 (year <= shortYearCutoff ? 0 : -100);
9347 if (doy > -1) {
9348 month = 1;
9349 day = doy;
9350 do {
9351 var dim = this._getDaysInMonth(year, month - 1);
9352 if (day <= dim)
9353 break;
9354 month++;
9355 day -= dim;
9356 } while (true);
9358 var date = this._daylightSavingAdjust(new Date(year, month - 1, day));
9359 if (date.getFullYear() != year || date.getMonth() + 1 != month || date.getDate() != day)
9360 throw 'Invalid date'; // E.g. 31/02/00
9361 return date;
9364 /* Standard date formats. */
9365 ATOM: 'yy-mm-dd', // RFC 3339 (ISO 8601)
9366 COOKIE: 'D, dd M yy',
9367 ISO_8601: 'yy-mm-dd',
9368 RFC_822: 'D, d M y',
9369 RFC_850: 'DD, dd-M-y',
9370 RFC_1036: 'D, d M y',
9371 RFC_1123: 'D, d M yy',
9372 RFC_2822: 'D, d M yy',
9373 RSS: 'D, d M y', // RFC 822
9374 TICKS: '!',
9375 TIMESTAMP: '@',
9376 W3C: 'yy-mm-dd', // ISO 8601
9378 _ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) +
9379 Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000),
9381 /* Format a date object into a string value.
9382 The format can be combinations of the following:
9383 d - day of month (no leading zero)
9384 dd - day of month (two digit)
9385 o - day of year (no leading zeros)
9386 oo - day of year (three digit)
9387 D - day name short
9388 DD - day name long
9389 m - month of year (no leading zero)
9390 mm - month of year (two digit)
9391 M - month name short
9392 MM - month name long
9393 y - year (two digit)
9394 yy - year (four digit)
9395 @ - Unix timestamp (ms since 01/01/1970)
9396 ! - Windows ticks (100ns since 01/01/0001)
9397 '...' - literal text
9398 '' - single quote
9400 @param format string - the desired format of the date
9401 @param date Date - the date value to format
9402 @param settings Object - attributes include:
9403 dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
9404 dayNames string[7] - names of the days from Sunday (optional)
9405 monthNamesShort string[12] - abbreviated names of the months (optional)
9406 monthNames string[12] - names of the months (optional)
9407 @return string - the date in the above format */
9408 formatDate: function (format, date, settings) {
9409 if (!date)
9410 return '';
9411 var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
9412 var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
9413 var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
9414 var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
9415 // Check whether a format character is doubled
9416 var lookAhead = function(match) {
9417 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
9418 if (matches)
9419 iFormat++;
9420 return matches;
9422 // Format a number, with leading zero if necessary
9423 var formatNumber = function(match, value, len) {
9424 var num = '' + value;
9425 if (lookAhead(match))
9426 while (num.length < len)
9427 num = '0' + num;
9428 return num;
9430 // Format a name, short or long as requested
9431 var formatName = function(match, value, shortNames, longNames) {
9432 return (lookAhead(match) ? longNames[value] : shortNames[value]);
9434 var output = '';
9435 var literal = false;
9436 if (date)
9437 for (var iFormat = 0; iFormat < format.length; iFormat++) {
9438 if (literal)
9439 if (format.charAt(iFormat) == "'" && !lookAhead("'"))
9440 literal = false;
9441 else
9442 output += format.charAt(iFormat);
9443 else
9444 switch (format.charAt(iFormat)) {
9445 case 'd':
9446 output += formatNumber('d', date.getDate(), 2);
9447 break;
9448 case 'D':
9449 output += formatName('D', date.getDay(), dayNamesShort, dayNames);
9450 break;
9451 case 'o':
9452 output += formatNumber('o',
9453 Math.round((new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000), 3);
9454 break;
9455 case 'm':
9456 output += formatNumber('m', date.getMonth() + 1, 2);
9457 break;
9458 case 'M':
9459 output += formatName('M', date.getMonth(), monthNamesShort, monthNames);
9460 break;
9461 case 'y':
9462 output += (lookAhead('y') ? date.getFullYear() :
9463 (date.getYear() % 100 < 10 ? '0' : '') + date.getYear() % 100);
9464 break;
9465 case '@':
9466 output += date.getTime();
9467 break;
9468 case '!':
9469 output += date.getTime() * 10000 + this._ticksTo1970;
9470 break;
9471 case "'":
9472 if (lookAhead("'"))
9473 output += "'";
9474 else
9475 literal = true;
9476 break;
9477 default:
9478 output += format.charAt(iFormat);
9481 return output;
9484 /* Extract all possible characters from the date format. */
9485 _possibleChars: function (format) {
9486 var chars = '';
9487 var literal = false;
9488 // Check whether a format character is doubled
9489 var lookAhead = function(match) {
9490 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
9491 if (matches)
9492 iFormat++;
9493 return matches;
9495 for (var iFormat = 0; iFormat < format.length; iFormat++)
9496 if (literal)
9497 if (format.charAt(iFormat) == "'" && !lookAhead("'"))
9498 literal = false;
9499 else
9500 chars += format.charAt(iFormat);
9501 else
9502 switch (format.charAt(iFormat)) {
9503 case 'd': case 'm': case 'y': case '@':
9504 chars += '0123456789';
9505 break;
9506 case 'D': case 'M':
9507 return null; // Accept anything
9508 case "'":
9509 if (lookAhead("'"))
9510 chars += "'";
9511 else
9512 literal = true;
9513 break;
9514 default:
9515 chars += format.charAt(iFormat);
9517 return chars;
9520 /* Get a setting value, defaulting if necessary. */
9521 _get: function(inst, name) {
9522 return inst.settings[name] !== undefined ?
9523 inst.settings[name] : this._defaults[name];
9526 /* Parse existing date and initialise date picker. */
9527 _setDateFromField: function(inst, noDefault) {
9528 if (inst.input.val() == inst.lastVal) {
9529 return;
9531 var dateFormat = this._get(inst, 'dateFormat');
9532 var dates = inst.lastVal = inst.input ? inst.input.val() : null;
9533 var date, defaultDate;
9534 date = defaultDate = this._getDefaultDate(inst);
9535 var settings = this._getFormatConfig(inst);
9536 try {
9537 date = this.parseDate(dateFormat, dates, settings) || defaultDate;
9538 } catch (event) {
9539 this.log(event);
9540 dates = (noDefault ? '' : dates);
9542 inst.selectedDay = date.getDate();
9543 inst.drawMonth = inst.selectedMonth = date.getMonth();
9544 inst.drawYear = inst.selectedYear = date.getFullYear();
9545 inst.currentDay = (dates ? date.getDate() : 0);
9546 inst.currentMonth = (dates ? date.getMonth() : 0);
9547 inst.currentYear = (dates ? date.getFullYear() : 0);
9548 this._adjustInstDate(inst);
9551 /* Retrieve the default date shown on opening. */
9552 _getDefaultDate: function(inst) {
9553 return this._restrictMinMax(inst,
9554 this._determineDate(inst, this._get(inst, 'defaultDate'), new Date()));
9557 /* A date may be specified as an exact value or a relative one. */
9558 _determineDate: function(inst, date, defaultDate) {
9559 var offsetNumeric = function(offset) {
9560 var date = new Date();
9561 date.setDate(date.getDate() + offset);
9562 return date;
9564 var offsetString = function(offset) {
9565 try {
9566 return $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
9567 offset, $.datepicker._getFormatConfig(inst));
9569 catch (e) {
9570 // Ignore
9572 var date = (offset.toLowerCase().match(/^c/) ?
9573 $.datepicker._getDate(inst) : null) || new Date();
9574 var year = date.getFullYear();
9575 var month = date.getMonth();
9576 var day = date.getDate();
9577 var pattern = /([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g;
9578 var matches = pattern.exec(offset);
9579 while (matches) {
9580 switch (matches[2] || 'd') {
9581 case 'd' : case 'D' :
9582 day += parseInt(matches[1],10); break;
9583 case 'w' : case 'W' :
9584 day += parseInt(matches[1],10) * 7; break;
9585 case 'm' : case 'M' :
9586 month += parseInt(matches[1],10);
9587 day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
9588 break;
9589 case 'y': case 'Y' :
9590 year += parseInt(matches[1],10);
9591 day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
9592 break;
9594 matches = pattern.exec(offset);
9596 return new Date(year, month, day);
9598 var newDate = (date == null || date === '' ? defaultDate : (typeof date == 'string' ? offsetString(date) :
9599 (typeof date == 'number' ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : new Date(date.getTime()))));
9600 newDate = (newDate && newDate.toString() == 'Invalid Date' ? defaultDate : newDate);
9601 if (newDate) {
9602 newDate.setHours(0);
9603 newDate.setMinutes(0);
9604 newDate.setSeconds(0);
9605 newDate.setMilliseconds(0);
9607 return this._daylightSavingAdjust(newDate);
9610 /* Handle switch to/from daylight saving.
9611 Hours may be non-zero on daylight saving cut-over:
9612 > 12 when midnight changeover, but then cannot generate
9613 midnight datetime, so jump to 1AM, otherwise reset.
9614 @param date (Date) the date to check
9615 @return (Date) the corrected date */
9616 _daylightSavingAdjust: function(date) {
9617 if (!date) return null;
9618 date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
9619 return date;
9622 /* Set the date(s) directly. */
9623 _setDate: function(inst, date, noChange) {
9624 var clear = !date;
9625 var origMonth = inst.selectedMonth;
9626 var origYear = inst.selectedYear;
9627 var newDate = this._restrictMinMax(inst, this._determineDate(inst, date, new Date()));
9628 inst.selectedDay = inst.currentDay = newDate.getDate();
9629 inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth();
9630 inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear();
9631 if ((origMonth != inst.selectedMonth || origYear != inst.selectedYear) && !noChange)
9632 this._notifyChange(inst);
9633 this._adjustInstDate(inst);
9634 if (inst.input) {
9635 inst.input.val(clear ? '' : this._formatDate(inst));
9639 /* Retrieve the date(s) directly. */
9640 _getDate: function(inst) {
9641 var startDate = (!inst.currentYear || (inst.input && inst.input.val() == '') ? null :
9642 this._daylightSavingAdjust(new Date(
9643 inst.currentYear, inst.currentMonth, inst.currentDay)));
9644 return startDate;
9647 /* Generate the HTML for the current state of the date picker. */
9648 _generateHTML: function(inst) {
9649 var today = new Date();
9650 today = this._daylightSavingAdjust(
9651 new Date(today.getFullYear(), today.getMonth(), today.getDate())); // clear time
9652 var isRTL = this._get(inst, 'isRTL');
9653 var showButtonPanel = this._get(inst, 'showButtonPanel');
9654 var hideIfNoPrevNext = this._get(inst, 'hideIfNoPrevNext');
9655 var navigationAsDateFormat = this._get(inst, 'navigationAsDateFormat');
9656 var numMonths = this._getNumberOfMonths(inst);
9657 var showCurrentAtPos = this._get(inst, 'showCurrentAtPos');
9658 var stepMonths = this._get(inst, 'stepMonths');
9659 var isMultiMonth = (numMonths[0] != 1 || numMonths[1] != 1);
9660 var currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) :
9661 new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
9662 var minDate = this._getMinMaxDate(inst, 'min');
9663 var maxDate = this._getMinMaxDate(inst, 'max');
9664 var drawMonth = inst.drawMonth - showCurrentAtPos;
9665 var drawYear = inst.drawYear;
9666 if (drawMonth < 0) {
9667 drawMonth += 12;
9668 drawYear--;
9670 if (maxDate) {
9671 var maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),
9672 maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate()));
9673 maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);
9674 while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {
9675 drawMonth--;
9676 if (drawMonth < 0) {
9677 drawMonth = 11;
9678 drawYear--;
9682 inst.drawMonth = drawMonth;
9683 inst.drawYear = drawYear;
9684 var prevText = this._get(inst, 'prevText');
9685 prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText,
9686 this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),
9687 this._getFormatConfig(inst)));
9688 var prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?
9689 '<a class="ui-datepicker-prev ui-corner-all" onclick="DP_jQuery_' + dpuuid +
9690 '.datepicker._adjustDate(\'#' + inst.id + '\', -' + stepMonths + ', \'M\');"' +
9691 ' title="' + prevText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>' :
9692 (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>'));
9693 var nextText = this._get(inst, 'nextText');
9694 nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText,
9695 this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),
9696 this._getFormatConfig(inst)));
9697 var next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?
9698 '<a class="ui-datepicker-next ui-corner-all" onclick="DP_jQuery_' + dpuuid +
9699 '.datepicker._adjustDate(\'#' + inst.id + '\', +' + stepMonths + ', \'M\');"' +
9700 ' title="' + nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>' :
9701 (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>'));
9702 var currentText = this._get(inst, 'currentText');
9703 var gotoDate = (this._get(inst, 'gotoCurrent') && inst.currentDay ? currentDate : today);
9704 currentText = (!navigationAsDateFormat ? currentText :
9705 this.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));
9706 var controls = (!inst.inline ? '<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" onclick="DP_jQuery_' + dpuuid +
9707 '.datepicker._hideDatepicker();">' + this._get(inst, 'closeText') + '</button>' : '');
9708 var buttonPanel = (showButtonPanel) ? '<div class="ui-datepicker-buttonpane ui-widget-content">' + (isRTL ? controls : '') +
9709 (this._isInRange(inst, gotoDate) ? '<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" onclick="DP_jQuery_' + dpuuid +
9710 '.datepicker._gotoToday(\'#' + inst.id + '\');"' +
9711 '>' + currentText + '</button>' : '') + (isRTL ? '' : controls) + '</div>' : '';
9712 var firstDay = parseInt(this._get(inst, 'firstDay'),10);
9713 firstDay = (isNaN(firstDay) ? 0 : firstDay);
9714 var showWeek = this._get(inst, 'showWeek');
9715 var dayNames = this._get(inst, 'dayNames');
9716 var dayNamesShort = this._get(inst, 'dayNamesShort');
9717 var dayNamesMin = this._get(inst, 'dayNamesMin');
9718 var monthNames = this._get(inst, 'monthNames');
9719 var monthNamesShort = this._get(inst, 'monthNamesShort');
9720 var beforeShowDay = this._get(inst, 'beforeShowDay');
9721 var showOtherMonths = this._get(inst, 'showOtherMonths');
9722 var selectOtherMonths = this._get(inst, 'selectOtherMonths');
9723 var calculateWeek = this._get(inst, 'calculateWeek') || this.iso8601Week;
9724 var defaultDate = this._getDefaultDate(inst);
9725 var html = '';
9726 for (var row = 0; row < numMonths[0]; row++) {
9727 var group = '';
9728 this.maxRows = 4;
9729 for (var col = 0; col < numMonths[1]; col++) {
9730 var selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay));
9731 var cornerClass = ' ui-corner-all';
9732 var calender = '';
9733 if (isMultiMonth) {
9734 calender += '<div class="ui-datepicker-group';
9735 if (numMonths[1] > 1)
9736 switch (col) {
9737 case 0: calender += ' ui-datepicker-group-first';
9738 cornerClass = ' ui-corner-' + (isRTL ? 'right' : 'left'); break;
9739 case numMonths[1]-1: calender += ' ui-datepicker-group-last';
9740 cornerClass = ' ui-corner-' + (isRTL ? 'left' : 'right'); break;
9741 default: calender += ' ui-datepicker-group-middle'; cornerClass = ''; break;
9743 calender += '">';
9745 calender += '<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix' + cornerClass + '">' +
9746 (/all|left/.test(cornerClass) && row == 0 ? (isRTL ? next : prev) : '') +
9747 (/all|right/.test(cornerClass) && row == 0 ? (isRTL ? prev : next) : '') +
9748 this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,
9749 row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers
9750 '</div><table class="ui-datepicker-calendar"><thead>' +
9751 '<tr>';
9752 var thead = (showWeek ? '<th class="ui-datepicker-week-col">' + this._get(inst, 'weekHeader') + '</th>' : '');
9753 for (var dow = 0; dow < 7; dow++) { // days of the week
9754 var day = (dow + firstDay) % 7;
9755 thead += '<th' + ((dow + firstDay + 6) % 7 >= 5 ? ' class="ui-datepicker-week-end"' : '') + '>' +
9756 '<span title="' + dayNames[day] + '">' + dayNamesMin[day] + '</span></th>';
9758 calender += thead + '</tr></thead><tbody>';
9759 var daysInMonth = this._getDaysInMonth(drawYear, drawMonth);
9760 if (drawYear == inst.selectedYear && drawMonth == inst.selectedMonth)
9761 inst.selectedDay = Math.min(inst.selectedDay, daysInMonth);
9762 var leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;
9763 var curRows = Math.ceil((leadDays + daysInMonth) / 7); // calculate the number of rows to generate
9764 var numRows = (isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows); //If multiple months, use the higher number of rows (see #7043)
9765 this.maxRows = numRows;
9766 var printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
9767 for (var dRow = 0; dRow < numRows; dRow++) { // create date picker rows
9768 calender += '<tr>';
9769 var tbody = (!showWeek ? '' : '<td class="ui-datepicker-week-col">' +
9770 this._get(inst, 'calculateWeek')(printDate) + '</td>');
9771 for (var dow = 0; dow < 7; dow++) { // create date picker days
9772 var daySettings = (beforeShowDay ?
9773 beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, '']);
9774 var otherMonth = (printDate.getMonth() != drawMonth);
9775 var unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] ||
9776 (minDate && printDate < minDate) || (maxDate && printDate > maxDate);
9777 tbody += '<td class="' +
9778 ((dow + firstDay + 6) % 7 >= 5 ? ' ui-datepicker-week-end' : '') + // highlight weekends
9779 (otherMonth ? ' ui-datepicker-other-month' : '') + // highlight days from other months
9780 ((printDate.getTime() == selectedDate.getTime() && drawMonth == inst.selectedMonth && inst._keyEvent) || // user pressed key
9781 (defaultDate.getTime() == printDate.getTime() && defaultDate.getTime() == selectedDate.getTime()) ?
9782 // or defaultDate is current printedDate and defaultDate is selectedDate
9783 ' ' + this._dayOverClass : '') + // highlight selected day
9784 (unselectable ? ' ' + this._unselectableClass + ' ui-state-disabled': '') + // highlight unselectable days
9785 (otherMonth && !showOtherMonths ? '' : ' ' + daySettings[1] + // highlight custom dates
9786 (printDate.getTime() == currentDate.getTime() ? ' ' + this._currentClass : '') + // highlight selected day
9787 (printDate.getTime() == today.getTime() ? ' ui-datepicker-today' : '')) + '"' + // highlight today (if different)
9788 ((!otherMonth || showOtherMonths) && daySettings[2] ? ' title="' + daySettings[2] + '"' : '') + // cell title
9789 (unselectable ? '' : ' onclick="DP_jQuery_' + dpuuid + '.datepicker._selectDay(\'#' +
9790 inst.id + '\',' + printDate.getMonth() + ',' + printDate.getFullYear() + ', this);return false;"') + '>' + // actions
9791 (otherMonth && !showOtherMonths ? '&#xa0;' : // display for other months
9792 (unselectable ? '<span class="ui-state-default">' + printDate.getDate() + '</span>' : '<a class="ui-state-default' +
9793 (printDate.getTime() == today.getTime() ? ' ui-state-highlight' : '') +
9794 (printDate.getTime() == currentDate.getTime() ? ' ui-state-active' : '') + // highlight selected day
9795 (otherMonth ? ' ui-priority-secondary' : '') + // distinguish dates from other months
9796 '" href="#">' + printDate.getDate() + '</a>')) + '</td>'; // display selectable date
9797 printDate.setDate(printDate.getDate() + 1);
9798 printDate = this._daylightSavingAdjust(printDate);
9800 calender += tbody + '</tr>';
9802 drawMonth++;
9803 if (drawMonth > 11) {
9804 drawMonth = 0;
9805 drawYear++;
9807 calender += '</tbody></table>' + (isMultiMonth ? '</div>' +
9808 ((numMonths[0] > 0 && col == numMonths[1]-1) ? '<div class="ui-datepicker-row-break"></div>' : '') : '');
9809 group += calender;
9811 html += group;
9813 html += buttonPanel + ($.browser.msie && parseInt($.browser.version,10) < 7 && !inst.inline ?
9814 '<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>' : '');
9815 inst._keyEvent = false;
9816 return html;
9819 /* Generate the month and year header. */
9820 _generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate,
9821 secondary, monthNames, monthNamesShort) {
9822 var changeMonth = this._get(inst, 'changeMonth');
9823 var changeYear = this._get(inst, 'changeYear');
9824 var showMonthAfterYear = this._get(inst, 'showMonthAfterYear');
9825 var html = '<div class="ui-datepicker-title">';
9826 var monthHtml = '';
9827 // month selection
9828 if (secondary || !changeMonth)
9829 monthHtml += '<span class="ui-datepicker-month">' + monthNames[drawMonth] + '</span>';
9830 else {
9831 var inMinYear = (minDate && minDate.getFullYear() == drawYear);
9832 var inMaxYear = (maxDate && maxDate.getFullYear() == drawYear);
9833 monthHtml += '<select class="ui-datepicker-month" ' +
9834 'onchange="DP_jQuery_' + dpuuid + '.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'M\');" ' +
9835 '>';
9836 for (var month = 0; month < 12; month++) {
9837 if ((!inMinYear || month >= minDate.getMonth()) &&
9838 (!inMaxYear || month <= maxDate.getMonth()))
9839 monthHtml += '<option value="' + month + '"' +
9840 (month == drawMonth ? ' selected="selected"' : '') +
9841 '>' + monthNamesShort[month] + '</option>';
9843 monthHtml += '</select>';
9845 if (!showMonthAfterYear)
9846 html += monthHtml + (secondary || !(changeMonth && changeYear) ? '&#xa0;' : '');
9847 // year selection
9848 if ( !inst.yearshtml ) {
9849 inst.yearshtml = '';
9850 if (secondary || !changeYear)
9851 html += '<span class="ui-datepicker-year">' + drawYear + '</span>';
9852 else {
9853 // determine range of years to display
9854 var years = this._get(inst, 'yearRange').split(':');
9855 var thisYear = new Date().getFullYear();
9856 var determineYear = function(value) {
9857 var year = (value.match(/c[+-].*/) ? drawYear + parseInt(value.substring(1), 10) :
9858 (value.match(/[+-].*/) ? thisYear + parseInt(value, 10) :
9859 parseInt(value, 10)));
9860 return (isNaN(year) ? thisYear : year);
9862 var year = determineYear(years[0]);
9863 var endYear = Math.max(year, determineYear(years[1] || ''));
9864 year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
9865 endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
9866 inst.yearshtml += '<select class="ui-datepicker-year" ' +
9867 'onchange="DP_jQuery_' + dpuuid + '.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'Y\');" ' +
9868 '>';
9869 for (; year <= endYear; year++) {
9870 inst.yearshtml += '<option value="' + year + '"' +
9871 (year == drawYear ? ' selected="selected"' : '') +
9872 '>' + year + '</option>';
9874 inst.yearshtml += '</select>';
9876 html += inst.yearshtml;
9877 inst.yearshtml = null;
9880 html += this._get(inst, 'yearSuffix');
9881 if (showMonthAfterYear)
9882 html += (secondary || !(changeMonth && changeYear) ? '&#xa0;' : '') + monthHtml;
9883 html += '</div>'; // Close datepicker_header
9884 return html;
9887 /* Adjust one of the date sub-fields. */
9888 _adjustInstDate: function(inst, offset, period) {
9889 var year = inst.drawYear + (period == 'Y' ? offset : 0);
9890 var month = inst.drawMonth + (period == 'M' ? offset : 0);
9891 var day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) +
9892 (period == 'D' ? offset : 0);
9893 var date = this._restrictMinMax(inst,
9894 this._daylightSavingAdjust(new Date(year, month, day)));
9895 inst.selectedDay = date.getDate();
9896 inst.drawMonth = inst.selectedMonth = date.getMonth();
9897 inst.drawYear = inst.selectedYear = date.getFullYear();
9898 if (period == 'M' || period == 'Y')
9899 this._notifyChange(inst);
9902 /* Ensure a date is within any min/max bounds. */
9903 _restrictMinMax: function(inst, date) {
9904 var minDate = this._getMinMaxDate(inst, 'min');
9905 var maxDate = this._getMinMaxDate(inst, 'max');
9906 var newDate = (minDate && date < minDate ? minDate : date);
9907 newDate = (maxDate && newDate > maxDate ? maxDate : newDate);
9908 return newDate;
9911 /* Notify change of month/year. */
9912 _notifyChange: function(inst) {
9913 var onChange = this._get(inst, 'onChangeMonthYear');
9914 if (onChange)
9915 onChange.apply((inst.input ? inst.input[0] : null),
9916 [inst.selectedYear, inst.selectedMonth + 1, inst]);
9919 /* Determine the number of months to show. */
9920 _getNumberOfMonths: function(inst) {
9921 var numMonths = this._get(inst, 'numberOfMonths');
9922 return (numMonths == null ? [1, 1] : (typeof numMonths == 'number' ? [1, numMonths] : numMonths));
9925 /* Determine the current maximum date - ensure no time components are set. */
9926 _getMinMaxDate: function(inst, minMax) {
9927 return this._determineDate(inst, this._get(inst, minMax + 'Date'), null);
9930 /* Find the number of days in a given month. */
9931 _getDaysInMonth: function(year, month) {
9932 return 32 - this._daylightSavingAdjust(new Date(year, month, 32)).getDate();
9935 /* Find the day of the week of the first of a month. */
9936 _getFirstDayOfMonth: function(year, month) {
9937 return new Date(year, month, 1).getDay();
9940 /* Determines if we should allow a "next/prev" month display change. */
9941 _canAdjustMonth: function(inst, offset, curYear, curMonth) {
9942 var numMonths = this._getNumberOfMonths(inst);
9943 var date = this._daylightSavingAdjust(new Date(curYear,
9944 curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1));
9945 if (offset < 0)
9946 date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
9947 return this._isInRange(inst, date);
9950 /* Is the given date in the accepted range? */
9951 _isInRange: function(inst, date) {
9952 var minDate = this._getMinMaxDate(inst, 'min');
9953 var maxDate = this._getMinMaxDate(inst, 'max');
9954 return ((!minDate || date.getTime() >= minDate.getTime()) &&
9955 (!maxDate || date.getTime() <= maxDate.getTime()));
9958 /* Provide the configuration settings for formatting/parsing. */
9959 _getFormatConfig: function(inst) {
9960 var shortYearCutoff = this._get(inst, 'shortYearCutoff');
9961 shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff :
9962 new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
9963 return {shortYearCutoff: shortYearCutoff,
9964 dayNamesShort: this._get(inst, 'dayNamesShort'), dayNames: this._get(inst, 'dayNames'),
9965 monthNamesShort: this._get(inst, 'monthNamesShort'), monthNames: this._get(inst, 'monthNames')};
9968 /* Format the given date for display. */
9969 _formatDate: function(inst, day, month, year) {
9970 if (!day) {
9971 inst.currentDay = inst.selectedDay;
9972 inst.currentMonth = inst.selectedMonth;
9973 inst.currentYear = inst.selectedYear;
9975 var date = (day ? (typeof day == 'object' ? day :
9976 this._daylightSavingAdjust(new Date(year, month, day))) :
9977 this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
9978 return this.formatDate(this._get(inst, 'dateFormat'), date, this._getFormatConfig(inst));
9983 * Bind hover events for datepicker elements.
9984 * Done via delegate so the binding only occurs once in the lifetime of the parent div.
9985 * Global instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker.
9987 function bindHover(dpDiv) {
9988 var selector = 'button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a';
9989 return dpDiv.bind('mouseout', function(event) {
9990 var elem = $( event.target ).closest( selector );
9991 if ( !elem.length ) {
9992 return;
9994 elem.removeClass( "ui-state-hover ui-datepicker-prev-hover ui-datepicker-next-hover" );
9996 .bind('mouseover', function(event) {
9997 var elem = $( event.target ).closest( selector );
9998 if ($.datepicker._isDisabledDatepicker( instActive.inline ? dpDiv.parent()[0] : instActive.input[0]) ||
9999 !elem.length ) {
10000 return;
10002 elem.parents('.ui-datepicker-calendar').find('a').removeClass('ui-state-hover');
10003 elem.addClass('ui-state-hover');
10004 if (elem.hasClass('ui-datepicker-prev')) elem.addClass('ui-datepicker-prev-hover');
10005 if (elem.hasClass('ui-datepicker-next')) elem.addClass('ui-datepicker-next-hover');
10009 /* jQuery extend now ignores nulls! */
10010 function extendRemove(target, props) {
10011 $.extend(target, props);
10012 for (var name in props)
10013 if (props[name] == null || props[name] == undefined)
10014 target[name] = props[name];
10015 return target;
10018 /* Determine whether an object is an array. */
10019 function isArray(a) {
10020 return (a && (($.browser.safari && typeof a == 'object' && a.length) ||
10021 (a.constructor && a.constructor.toString().match(/\Array\(\)/))));
10024 /* Invoke the datepicker functionality.
10025 @param options string - a command, optionally followed by additional parameters or
10026 Object - settings for attaching new datepicker functionality
10027 @return jQuery object */
10028 $.fn.datepicker = function(options){
10030 /* Verify an empty collection wasn't passed - Fixes #6976 */
10031 if ( !this.length ) {
10032 return this;
10035 /* Initialise the date picker. */
10036 if (!$.datepicker.initialized) {
10037 $(document).mousedown($.datepicker._checkExternalClick).
10038 find('body').append($.datepicker.dpDiv);
10039 $.datepicker.initialized = true;
10042 var otherArgs = Array.prototype.slice.call(arguments, 1);
10043 if (typeof options == 'string' && (options == 'isDisabled' || options == 'getDate' || options == 'widget'))
10044 return $.datepicker['_' + options + 'Datepicker'].
10045 apply($.datepicker, [this[0]].concat(otherArgs));
10046 if (options == 'option' && arguments.length == 2 && typeof arguments[1] == 'string')
10047 return $.datepicker['_' + options + 'Datepicker'].
10048 apply($.datepicker, [this[0]].concat(otherArgs));
10049 return this.each(function() {
10050 typeof options == 'string' ?
10051 $.datepicker['_' + options + 'Datepicker'].
10052 apply($.datepicker, [this].concat(otherArgs)) :
10053 $.datepicker._attachDatepicker(this, options);
10057 $.datepicker = new Datepicker(); // singleton instance
10058 $.datepicker.initialized = false;
10059 $.datepicker.uuid = new Date().getTime();
10060 $.datepicker.version = "1.8.16";
10062 // Workaround for #4055
10063 // Add another global to avoid noConflict issues with inline event handlers
10064 window['DP_jQuery_' + dpuuid] = $;
10066 })(jQuery);
10068 * jQuery UI Progressbar 1.8.16
10070 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
10071 * Dual licensed under the MIT or GPL Version 2 licenses.
10072 * http://jquery.org/license
10074 * http://docs.jquery.com/UI/Progressbar
10076 * Depends:
10077 * jquery.ui.core.js
10078 * jquery.ui.widget.js
10080 (function( $, undefined ) {
10082 $.widget( "ui.progressbar", {
10083 options: {
10084 value: 0,
10085 max: 100
10088 min: 0,
10090 _create: function() {
10091 this.element
10092 .addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
10093 .attr({
10094 role: "progressbar",
10095 "aria-valuemin": this.min,
10096 "aria-valuemax": this.options.max,
10097 "aria-valuenow": this._value()
10100 this.valueDiv = $( "<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>" )
10101 .appendTo( this.element );
10103 this.oldValue = this._value();
10104 this._refreshValue();
10107 destroy: function() {
10108 this.element
10109 .removeClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
10110 .removeAttr( "role" )
10111 .removeAttr( "aria-valuemin" )
10112 .removeAttr( "aria-valuemax" )
10113 .removeAttr( "aria-valuenow" );
10115 this.valueDiv.remove();
10117 $.Widget.prototype.destroy.apply( this, arguments );
10120 value: function( newValue ) {
10121 if ( newValue === undefined ) {
10122 return this._value();
10125 this._setOption( "value", newValue );
10126 return this;
10129 _setOption: function( key, value ) {
10130 if ( key === "value" ) {
10131 this.options.value = value;
10132 this._refreshValue();
10133 if ( this._value() === this.options.max ) {
10134 this._trigger( "complete" );
10138 $.Widget.prototype._setOption.apply( this, arguments );
10141 _value: function() {
10142 var val = this.options.value;
10143 // normalize invalid value
10144 if ( typeof val !== "number" ) {
10145 val = 0;
10147 return Math.min( this.options.max, Math.max( this.min, val ) );
10150 _percentage: function() {
10151 return 100 * this._value() / this.options.max;
10154 _refreshValue: function() {
10155 var value = this.value();
10156 var percentage = this._percentage();
10158 if ( this.oldValue !== value ) {
10159 this.oldValue = value;
10160 this._trigger( "change" );
10163 this.valueDiv
10164 .toggle( value > this.min )
10165 .toggleClass( "ui-corner-right", value === this.options.max )
10166 .width( percentage.toFixed(0) + "%" );
10167 this.element.attr( "aria-valuenow", value );
10171 $.extend( $.ui.progressbar, {
10172 version: "1.8.16"
10175 })( jQuery );
10177 * jQuery UI Effects 1.8.16
10179 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
10180 * Dual licensed under the MIT or GPL Version 2 licenses.
10181 * http://jquery.org/license
10183 * http://docs.jquery.com/UI/Effects/
10185 ;jQuery.effects || (function($, undefined) {
10187 $.effects = {};
10191 /******************************************************************************/
10192 /****************************** COLOR ANIMATIONS ******************************/
10193 /******************************************************************************/
10195 // override the animation for color styles
10196 $.each(['backgroundColor', 'borderBottomColor', 'borderLeftColor',
10197 'borderRightColor', 'borderTopColor', 'borderColor', 'color', 'outlineColor'],
10198 function(i, attr) {
10199 $.fx.step[attr] = function(fx) {
10200 if (!fx.colorInit) {
10201 fx.start = getColor(fx.elem, attr);
10202 fx.end = getRGB(fx.end);
10203 fx.colorInit = true;
10206 fx.elem.style[attr] = 'rgb(' +
10207 Math.max(Math.min(parseInt((fx.pos * (fx.end[0] - fx.start[0])) + fx.start[0], 10), 255), 0) + ',' +
10208 Math.max(Math.min(parseInt((fx.pos * (fx.end[1] - fx.start[1])) + fx.start[1], 10), 255), 0) + ',' +
10209 Math.max(Math.min(parseInt((fx.pos * (fx.end[2] - fx.start[2])) + fx.start[2], 10), 255), 0) + ')';
10213 // Color Conversion functions from highlightFade
10214 // By Blair Mitchelmore
10215 // http://jquery.offput.ca/highlightFade/
10217 // Parse strings looking for color tuples [255,255,255]
10218 function getRGB(color) {
10219 var result;
10221 // Check if we're already dealing with an array of colors
10222 if ( color && color.constructor == Array && color.length == 3 )
10223 return color;
10225 // Look for rgb(num,num,num)
10226 if (result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(color))
10227 return [parseInt(result[1],10), parseInt(result[2],10), parseInt(result[3],10)];
10229 // Look for rgb(num%,num%,num%)
10230 if (result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(color))
10231 return [parseFloat(result[1])*2.55, parseFloat(result[2])*2.55, parseFloat(result[3])*2.55];
10233 // Look for #a0b1c2
10234 if (result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(color))
10235 return [parseInt(result[1],16), parseInt(result[2],16), parseInt(result[3],16)];
10237 // Look for #fff
10238 if (result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(color))
10239 return [parseInt(result[1]+result[1],16), parseInt(result[2]+result[2],16), parseInt(result[3]+result[3],16)];
10241 // Look for rgba(0, 0, 0, 0) == transparent in Safari 3
10242 if (result = /rgba\(0, 0, 0, 0\)/.exec(color))
10243 return colors['transparent'];
10245 // Otherwise, we're most likely dealing with a named color
10246 return colors[$.trim(color).toLowerCase()];
10249 function getColor(elem, attr) {
10250 var color;
10252 do {
10253 color = $.curCSS(elem, attr);
10255 // Keep going until we find an element that has color, or we hit the body
10256 if ( color != '' && color != 'transparent' || $.nodeName(elem, "body") )
10257 break;
10259 attr = "backgroundColor";
10260 } while ( elem = elem.parentNode );
10262 return getRGB(color);
10265 // Some named colors to work with
10266 // From Interface by Stefan Petre
10267 // http://interface.eyecon.ro/
10269 var colors = {
10270 aqua:[0,255,255],
10271 azure:[240,255,255],
10272 beige:[245,245,220],
10273 black:[0,0,0],
10274 blue:[0,0,255],
10275 brown:[165,42,42],
10276 cyan:[0,255,255],
10277 darkblue:[0,0,139],
10278 darkcyan:[0,139,139],
10279 darkgrey:[169,169,169],
10280 darkgreen:[0,100,0],
10281 darkkhaki:[189,183,107],
10282 darkmagenta:[139,0,139],
10283 darkolivegreen:[85,107,47],
10284 darkorange:[255,140,0],
10285 darkorchid:[153,50,204],
10286 darkred:[139,0,0],
10287 darksalmon:[233,150,122],
10288 darkviolet:[148,0,211],
10289 fuchsia:[255,0,255],
10290 gold:[255,215,0],
10291 green:[0,128,0],
10292 indigo:[75,0,130],
10293 khaki:[240,230,140],
10294 lightblue:[173,216,230],
10295 lightcyan:[224,255,255],
10296 lightgreen:[144,238,144],
10297 lightgrey:[211,211,211],
10298 lightpink:[255,182,193],
10299 lightyellow:[255,255,224],
10300 lime:[0,255,0],
10301 magenta:[255,0,255],
10302 maroon:[128,0,0],
10303 navy:[0,0,128],
10304 olive:[128,128,0],
10305 orange:[255,165,0],
10306 pink:[255,192,203],
10307 purple:[128,0,128],
10308 violet:[128,0,128],
10309 red:[255,0,0],
10310 silver:[192,192,192],
10311 white:[255,255,255],
10312 yellow:[255,255,0],
10313 transparent: [255,255,255]
10318 /******************************************************************************/
10319 /****************************** CLASS ANIMATIONS ******************************/
10320 /******************************************************************************/
10322 var classAnimationActions = ['add', 'remove', 'toggle'],
10323 shorthandStyles = {
10324 border: 1,
10325 borderBottom: 1,
10326 borderColor: 1,
10327 borderLeft: 1,
10328 borderRight: 1,
10329 borderTop: 1,
10330 borderWidth: 1,
10331 margin: 1,
10332 padding: 1
10335 function getElementStyles() {
10336 var style = document.defaultView
10337 ? document.defaultView.getComputedStyle(this, null)
10338 : this.currentStyle,
10339 newStyle = {},
10340 key,
10341 camelCase;
10343 // webkit enumerates style porperties
10344 if (style && style.length && style[0] && style[style[0]]) {
10345 var len = style.length;
10346 while (len--) {
10347 key = style[len];
10348 if (typeof style[key] == 'string') {
10349 camelCase = key.replace(/\-(\w)/g, function(all, letter){
10350 return letter.toUpperCase();
10352 newStyle[camelCase] = style[key];
10355 } else {
10356 for (key in style) {
10357 if (typeof style[key] === 'string') {
10358 newStyle[key] = style[key];
10363 return newStyle;
10366 function filterStyles(styles) {
10367 var name, value;
10368 for (name in styles) {
10369 value = styles[name];
10370 if (
10371 // ignore null and undefined values
10372 value == null ||
10373 // ignore functions (when does this occur?)
10374 $.isFunction(value) ||
10375 // shorthand styles that need to be expanded
10376 name in shorthandStyles ||
10377 // ignore scrollbars (break in IE)
10378 (/scrollbar/).test(name) ||
10380 // only colors or values that can be converted to numbers
10381 (!(/color/i).test(name) && isNaN(parseFloat(value)))
10383 delete styles[name];
10387 return styles;
10390 function styleDifference(oldStyle, newStyle) {
10391 var diff = { _: 0 }, // http://dev.jquery.com/ticket/5459
10392 name;
10394 for (name in newStyle) {
10395 if (oldStyle[name] != newStyle[name]) {
10396 diff[name] = newStyle[name];
10400 return diff;
10403 $.effects.animateClass = function(value, duration, easing, callback) {
10404 if ($.isFunction(easing)) {
10405 callback = easing;
10406 easing = null;
10409 return this.queue(function() {
10410 var that = $(this),
10411 originalStyleAttr = that.attr('style') || ' ',
10412 originalStyle = filterStyles(getElementStyles.call(this)),
10413 newStyle,
10414 className = that.attr('class');
10416 $.each(classAnimationActions, function(i, action) {
10417 if (value[action]) {
10418 that[action + 'Class'](value[action]);
10421 newStyle = filterStyles(getElementStyles.call(this));
10422 that.attr('class', className);
10424 that.animate(styleDifference(originalStyle, newStyle), {
10425 queue: false,
10426 duration: duration,
10427 easing: easing,
10428 complete: function() {
10429 $.each(classAnimationActions, function(i, action) {
10430 if (value[action]) { that[action + 'Class'](value[action]); }
10432 // work around bug in IE by clearing the cssText before setting it
10433 if (typeof that.attr('style') == 'object') {
10434 that.attr('style').cssText = '';
10435 that.attr('style').cssText = originalStyleAttr;
10436 } else {
10437 that.attr('style', originalStyleAttr);
10439 if (callback) { callback.apply(this, arguments); }
10440 $.dequeue( this );
10446 $.fn.extend({
10447 _addClass: $.fn.addClass,
10448 addClass: function(classNames, speed, easing, callback) {
10449 return speed ? $.effects.animateClass.apply(this, [{ add: classNames },speed,easing,callback]) : this._addClass(classNames);
10452 _removeClass: $.fn.removeClass,
10453 removeClass: function(classNames,speed,easing,callback) {
10454 return speed ? $.effects.animateClass.apply(this, [{ remove: classNames },speed,easing,callback]) : this._removeClass(classNames);
10457 _toggleClass: $.fn.toggleClass,
10458 toggleClass: function(classNames, force, speed, easing, callback) {
10459 if ( typeof force == "boolean" || force === undefined ) {
10460 if ( !speed ) {
10461 // without speed parameter;
10462 return this._toggleClass(classNames, force);
10463 } else {
10464 return $.effects.animateClass.apply(this, [(force?{add:classNames}:{remove:classNames}),speed,easing,callback]);
10466 } else {
10467 // without switch parameter;
10468 return $.effects.animateClass.apply(this, [{ toggle: classNames },force,speed,easing]);
10472 switchClass: function(remove,add,speed,easing,callback) {
10473 return $.effects.animateClass.apply(this, [{ add: add, remove: remove },speed,easing,callback]);
10479 /******************************************************************************/
10480 /*********************************** EFFECTS **********************************/
10481 /******************************************************************************/
10483 $.extend($.effects, {
10484 version: "1.8.16",
10486 // Saves a set of properties in a data storage
10487 save: function(element, set) {
10488 for(var i=0; i < set.length; i++) {
10489 if(set[i] !== null) element.data("ec.storage."+set[i], element[0].style[set[i]]);
10493 // Restores a set of previously saved properties from a data storage
10494 restore: function(element, set) {
10495 for(var i=0; i < set.length; i++) {
10496 if(set[i] !== null) element.css(set[i], element.data("ec.storage."+set[i]));
10500 setMode: function(el, mode) {
10501 if (mode == 'toggle') mode = el.is(':hidden') ? 'show' : 'hide'; // Set for toggle
10502 return mode;
10505 getBaseline: function(origin, original) { // Translates a [top,left] array into a baseline value
10506 // this should be a little more flexible in the future to handle a string & hash
10507 var y, x;
10508 switch (origin[0]) {
10509 case 'top': y = 0; break;
10510 case 'middle': y = 0.5; break;
10511 case 'bottom': y = 1; break;
10512 default: y = origin[0] / original.height;
10514 switch (origin[1]) {
10515 case 'left': x = 0; break;
10516 case 'center': x = 0.5; break;
10517 case 'right': x = 1; break;
10518 default: x = origin[1] / original.width;
10520 return {x: x, y: y};
10523 // Wraps the element around a wrapper that copies position properties
10524 createWrapper: function(element) {
10526 // if the element is already wrapped, return it
10527 if (element.parent().is('.ui-effects-wrapper')) {
10528 return element.parent();
10531 // wrap the element
10532 var props = {
10533 width: element.outerWidth(true),
10534 height: element.outerHeight(true),
10535 'float': element.css('float')
10537 wrapper = $('<div></div>')
10538 .addClass('ui-effects-wrapper')
10539 .css({
10540 fontSize: '100%',
10541 background: 'transparent',
10542 border: 'none',
10543 margin: 0,
10544 padding: 0
10546 active = document.activeElement;
10548 element.wrap(wrapper);
10550 // Fixes #7595 - Elements lose focus when wrapped.
10551 if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
10552 $( active ).focus();
10555 wrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually loose the reference to the wrapped element
10557 // transfer positioning properties to the wrapper
10558 if (element.css('position') == 'static') {
10559 wrapper.css({ position: 'relative' });
10560 element.css({ position: 'relative' });
10561 } else {
10562 $.extend(props, {
10563 position: element.css('position'),
10564 zIndex: element.css('z-index')
10566 $.each(['top', 'left', 'bottom', 'right'], function(i, pos) {
10567 props[pos] = element.css(pos);
10568 if (isNaN(parseInt(props[pos], 10))) {
10569 props[pos] = 'auto';
10572 element.css({position: 'relative', top: 0, left: 0, right: 'auto', bottom: 'auto' });
10575 return wrapper.css(props).show();
10578 removeWrapper: function(element) {
10579 var parent,
10580 active = document.activeElement;
10582 if (element.parent().is('.ui-effects-wrapper')) {
10583 parent = element.parent().replaceWith(element);
10584 // Fixes #7595 - Elements lose focus when wrapped.
10585 if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
10586 $( active ).focus();
10588 return parent;
10591 return element;
10594 setTransition: function(element, list, factor, value) {
10595 value = value || {};
10596 $.each(list, function(i, x){
10597 unit = element.cssUnit(x);
10598 if (unit[0] > 0) value[x] = unit[0] * factor + unit[1];
10600 return value;
10605 function _normalizeArguments(effect, options, speed, callback) {
10606 // shift params for method overloading
10607 if (typeof effect == 'object') {
10608 callback = options;
10609 speed = null;
10610 options = effect;
10611 effect = options.effect;
10613 if ($.isFunction(options)) {
10614 callback = options;
10615 speed = null;
10616 options = {};
10618 if (typeof options == 'number' || $.fx.speeds[options]) {
10619 callback = speed;
10620 speed = options;
10621 options = {};
10623 if ($.isFunction(speed)) {
10624 callback = speed;
10625 speed = null;
10628 options = options || {};
10630 speed = speed || options.duration;
10631 speed = $.fx.off ? 0 : typeof speed == 'number'
10632 ? speed : speed in $.fx.speeds ? $.fx.speeds[speed] : $.fx.speeds._default;
10634 callback = callback || options.complete;
10636 return [effect, options, speed, callback];
10639 function standardSpeed( speed ) {
10640 // valid standard speeds
10641 if ( !speed || typeof speed === "number" || $.fx.speeds[ speed ] ) {
10642 return true;
10645 // invalid strings - treat as "normal" speed
10646 if ( typeof speed === "string" && !$.effects[ speed ] ) {
10647 return true;
10650 return false;
10653 $.fn.extend({
10654 effect: function(effect, options, speed, callback) {
10655 var args = _normalizeArguments.apply(this, arguments),
10656 // TODO: make effects take actual parameters instead of a hash
10657 args2 = {
10658 options: args[1],
10659 duration: args[2],
10660 callback: args[3]
10662 mode = args2.options.mode,
10663 effectMethod = $.effects[effect];
10665 if ( $.fx.off || !effectMethod ) {
10666 // delegate to the original method (e.g., .show()) if possible
10667 if ( mode ) {
10668 return this[ mode ]( args2.duration, args2.callback );
10669 } else {
10670 return this.each(function() {
10671 if ( args2.callback ) {
10672 args2.callback.call( this );
10678 return effectMethod.call(this, args2);
10681 _show: $.fn.show,
10682 show: function(speed) {
10683 if ( standardSpeed( speed ) ) {
10684 return this._show.apply(this, arguments);
10685 } else {
10686 var args = _normalizeArguments.apply(this, arguments);
10687 args[1].mode = 'show';
10688 return this.effect.apply(this, args);
10692 _hide: $.fn.hide,
10693 hide: function(speed) {
10694 if ( standardSpeed( speed ) ) {
10695 return this._hide.apply(this, arguments);
10696 } else {
10697 var args = _normalizeArguments.apply(this, arguments);
10698 args[1].mode = 'hide';
10699 return this.effect.apply(this, args);
10703 // jQuery core overloads toggle and creates _toggle
10704 __toggle: $.fn.toggle,
10705 toggle: function(speed) {
10706 if ( standardSpeed( speed ) || typeof speed === "boolean" || $.isFunction( speed ) ) {
10707 return this.__toggle.apply(this, arguments);
10708 } else {
10709 var args = _normalizeArguments.apply(this, arguments);
10710 args[1].mode = 'toggle';
10711 return this.effect.apply(this, args);
10715 // helper functions
10716 cssUnit: function(key) {
10717 var style = this.css(key), val = [];
10718 $.each( ['em','px','%','pt'], function(i, unit){
10719 if(style.indexOf(unit) > 0)
10720 val = [parseFloat(style), unit];
10722 return val;
10728 /******************************************************************************/
10729 /*********************************** EASING ***********************************/
10730 /******************************************************************************/
10733 * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
10735 * Uses the built in easing capabilities added In jQuery 1.1
10736 * to offer multiple easing options
10738 * TERMS OF USE - jQuery Easing
10740 * Open source under the BSD License.
10742 * Copyright 2008 George McGinley Smith
10743 * All rights reserved.
10745 * Redistribution and use in source and binary forms, with or without modification,
10746 * are permitted provided that the following conditions are met:
10748 * Redistributions of source code must retain the above copyright notice, this list of
10749 * conditions and the following disclaimer.
10750 * Redistributions in binary form must reproduce the above copyright notice, this list
10751 * of conditions and the following disclaimer in the documentation and/or other materials
10752 * provided with the distribution.
10754 * Neither the name of the author nor the names of contributors may be used to endorse
10755 * or promote products derived from this software without specific prior written permission.
10757 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
10758 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
10759 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
10760 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
10761 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
10762 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
10763 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
10764 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
10765 * OF THE POSSIBILITY OF SUCH DAMAGE.
10769 // t: current time, b: begInnIng value, c: change In value, d: duration
10770 $.easing.jswing = $.easing.swing;
10772 $.extend($.easing,
10774 def: 'easeOutQuad',
10775 swing: function (x, t, b, c, d) {
10776 //alert($.easing.default);
10777 return $.easing[$.easing.def](x, t, b, c, d);
10779 easeInQuad: function (x, t, b, c, d) {
10780 return c*(t/=d)*t + b;
10782 easeOutQuad: function (x, t, b, c, d) {
10783 return -c *(t/=d)*(t-2) + b;
10785 easeInOutQuad: function (x, t, b, c, d) {
10786 if ((t/=d/2) < 1) return c/2*t*t + b;
10787 return -c/2 * ((--t)*(t-2) - 1) + b;
10789 easeInCubic: function (x, t, b, c, d) {
10790 return c*(t/=d)*t*t + b;
10792 easeOutCubic: function (x, t, b, c, d) {
10793 return c*((t=t/d-1)*t*t + 1) + b;
10795 easeInOutCubic: function (x, t, b, c, d) {
10796 if ((t/=d/2) < 1) return c/2*t*t*t + b;
10797 return c/2*((t-=2)*t*t + 2) + b;
10799 easeInQuart: function (x, t, b, c, d) {
10800 return c*(t/=d)*t*t*t + b;
10802 easeOutQuart: function (x, t, b, c, d) {
10803 return -c * ((t=t/d-1)*t*t*t - 1) + b;
10805 easeInOutQuart: function (x, t, b, c, d) {
10806 if ((t/=d/2) < 1) return c/2*t*t*t*t + b;
10807 return -c/2 * ((t-=2)*t*t*t - 2) + b;
10809 easeInQuint: function (x, t, b, c, d) {
10810 return c*(t/=d)*t*t*t*t + b;
10812 easeOutQuint: function (x, t, b, c, d) {
10813 return c*((t=t/d-1)*t*t*t*t + 1) + b;
10815 easeInOutQuint: function (x, t, b, c, d) {
10816 if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b;
10817 return c/2*((t-=2)*t*t*t*t + 2) + b;
10819 easeInSine: function (x, t, b, c, d) {
10820 return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
10822 easeOutSine: function (x, t, b, c, d) {
10823 return c * Math.sin(t/d * (Math.PI/2)) + b;
10825 easeInOutSine: function (x, t, b, c, d) {
10826 return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
10828 easeInExpo: function (x, t, b, c, d) {
10829 return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
10831 easeOutExpo: function (x, t, b, c, d) {
10832 return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
10834 easeInOutExpo: function (x, t, b, c, d) {
10835 if (t==0) return b;
10836 if (t==d) return b+c;
10837 if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
10838 return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
10840 easeInCirc: function (x, t, b, c, d) {
10841 return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
10843 easeOutCirc: function (x, t, b, c, d) {
10844 return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
10846 easeInOutCirc: function (x, t, b, c, d) {
10847 if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
10848 return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
10850 easeInElastic: function (x, t, b, c, d) {
10851 var s=1.70158;var p=0;var a=c;
10852 if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3;
10853 if (a < Math.abs(c)) { a=c; var s=p/4; }
10854 else var s = p/(2*Math.PI) * Math.asin (c/a);
10855 return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
10857 easeOutElastic: function (x, t, b, c, d) {
10858 var s=1.70158;var p=0;var a=c;
10859 if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3;
10860 if (a < Math.abs(c)) { a=c; var s=p/4; }
10861 else var s = p/(2*Math.PI) * Math.asin (c/a);
10862 return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
10864 easeInOutElastic: function (x, t, b, c, d) {
10865 var s=1.70158;var p=0;var a=c;
10866 if (t==0) return b; if ((t/=d/2)==2) return b+c; if (!p) p=d*(.3*1.5);
10867 if (a < Math.abs(c)) { a=c; var s=p/4; }
10868 else var s = p/(2*Math.PI) * Math.asin (c/a);
10869 if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
10870 return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
10872 easeInBack: function (x, t, b, c, d, s) {
10873 if (s == undefined) s = 1.70158;
10874 return c*(t/=d)*t*((s+1)*t - s) + b;
10876 easeOutBack: function (x, t, b, c, d, s) {
10877 if (s == undefined) s = 1.70158;
10878 return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
10880 easeInOutBack: function (x, t, b, c, d, s) {
10881 if (s == undefined) s = 1.70158;
10882 if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
10883 return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
10885 easeInBounce: function (x, t, b, c, d) {
10886 return c - $.easing.easeOutBounce (x, d-t, 0, c, d) + b;
10888 easeOutBounce: function (x, t, b, c, d) {
10889 if ((t/=d) < (1/2.75)) {
10890 return c*(7.5625*t*t) + b;
10891 } else if (t < (2/2.75)) {
10892 return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
10893 } else if (t < (2.5/2.75)) {
10894 return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
10895 } else {
10896 return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
10899 easeInOutBounce: function (x, t, b, c, d) {
10900 if (t < d/2) return $.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b;
10901 return $.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b;
10907 * TERMS OF USE - EASING EQUATIONS
10909 * Open source under the BSD License.
10911 * Copyright 2001 Robert Penner
10912 * All rights reserved.
10914 * Redistribution and use in source and binary forms, with or without modification,
10915 * are permitted provided that the following conditions are met:
10917 * Redistributions of source code must retain the above copyright notice, this list of
10918 * conditions and the following disclaimer.
10919 * Redistributions in binary form must reproduce the above copyright notice, this list
10920 * of conditions and the following disclaimer in the documentation and/or other materials
10921 * provided with the distribution.
10923 * Neither the name of the author nor the names of contributors may be used to endorse
10924 * or promote products derived from this software without specific prior written permission.
10926 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
10927 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
10928 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
10929 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
10930 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
10931 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
10932 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
10933 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
10934 * OF THE POSSIBILITY OF SUCH DAMAGE.
10938 })(jQuery);
10940 * jQuery UI Effects Blind 1.8.16
10942 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
10943 * Dual licensed under the MIT or GPL Version 2 licenses.
10944 * http://jquery.org/license
10946 * http://docs.jquery.com/UI/Effects/Blind
10948 * Depends:
10949 * jquery.effects.core.js
10951 (function( $, undefined ) {
10953 $.effects.blind = function(o) {
10955 return this.queue(function() {
10957 // Create element
10958 var el = $(this), props = ['position','top','bottom','left','right'];
10960 // Set options
10961 var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
10962 var direction = o.options.direction || 'vertical'; // Default direction
10964 // Adjust
10965 $.effects.save(el, props); el.show(); // Save & Show
10966 var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
10967 var ref = (direction == 'vertical') ? 'height' : 'width';
10968 var distance = (direction == 'vertical') ? wrapper.height() : wrapper.width();
10969 if(mode == 'show') wrapper.css(ref, 0); // Shift
10971 // Animation
10972 var animation = {};
10973 animation[ref] = mode == 'show' ? distance : 0;
10975 // Animate
10976 wrapper.animate(animation, o.duration, o.options.easing, function() {
10977 if(mode == 'hide') el.hide(); // Hide
10978 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
10979 if(o.callback) o.callback.apply(el[0], arguments); // Callback
10980 el.dequeue();
10987 })(jQuery);
10989 * jQuery UI Effects Bounce 1.8.16
10991 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
10992 * Dual licensed under the MIT or GPL Version 2 licenses.
10993 * http://jquery.org/license
10995 * http://docs.jquery.com/UI/Effects/Bounce
10997 * Depends:
10998 * jquery.effects.core.js
11000 (function( $, undefined ) {
11002 $.effects.bounce = function(o) {
11004 return this.queue(function() {
11006 // Create element
11007 var el = $(this), props = ['position','top','bottom','left','right'];
11009 // Set options
11010 var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
11011 var direction = o.options.direction || 'up'; // Default direction
11012 var distance = o.options.distance || 20; // Default distance
11013 var times = o.options.times || 5; // Default # of times
11014 var speed = o.duration || 250; // Default speed per bounce
11015 if (/show|hide/.test(mode)) props.push('opacity'); // Avoid touching opacity to prevent clearType and PNG issues in IE
11017 // Adjust
11018 $.effects.save(el, props); el.show(); // Save & Show
11019 $.effects.createWrapper(el); // Create Wrapper
11020 var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
11021 var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
11022 var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) / 3 : el.outerWidth({margin:true}) / 3);
11023 if (mode == 'show') el.css('opacity', 0).css(ref, motion == 'pos' ? -distance : distance); // Shift
11024 if (mode == 'hide') distance = distance / (times * 2);
11025 if (mode != 'hide') times--;
11027 // Animate
11028 if (mode == 'show') { // Show Bounce
11029 var animation = {opacity: 1};
11030 animation[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
11031 el.animate(animation, speed / 2, o.options.easing);
11032 distance = distance / 2;
11033 times--;
11035 for (var i = 0; i < times; i++) { // Bounces
11036 var animation1 = {}, animation2 = {};
11037 animation1[ref] = (motion == 'pos' ? '-=' : '+=') + distance;
11038 animation2[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
11039 el.animate(animation1, speed / 2, o.options.easing).animate(animation2, speed / 2, o.options.easing);
11040 distance = (mode == 'hide') ? distance * 2 : distance / 2;
11042 if (mode == 'hide') { // Last Bounce
11043 var animation = {opacity: 0};
11044 animation[ref] = (motion == 'pos' ? '-=' : '+=') + distance;
11045 el.animate(animation, speed / 2, o.options.easing, function(){
11046 el.hide(); // Hide
11047 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
11048 if(o.callback) o.callback.apply(this, arguments); // Callback
11050 } else {
11051 var animation1 = {}, animation2 = {};
11052 animation1[ref] = (motion == 'pos' ? '-=' : '+=') + distance;
11053 animation2[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
11054 el.animate(animation1, speed / 2, o.options.easing).animate(animation2, speed / 2, o.options.easing, function(){
11055 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
11056 if(o.callback) o.callback.apply(this, arguments); // Callback
11059 el.queue('fx', function() { el.dequeue(); });
11060 el.dequeue();
11065 })(jQuery);
11067 * jQuery UI Effects Clip 1.8.16
11069 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
11070 * Dual licensed under the MIT or GPL Version 2 licenses.
11071 * http://jquery.org/license
11073 * http://docs.jquery.com/UI/Effects/Clip
11075 * Depends:
11076 * jquery.effects.core.js
11078 (function( $, undefined ) {
11080 $.effects.clip = function(o) {
11082 return this.queue(function() {
11084 // Create element
11085 var el = $(this), props = ['position','top','bottom','left','right','height','width'];
11087 // Set options
11088 var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
11089 var direction = o.options.direction || 'vertical'; // Default direction
11091 // Adjust
11092 $.effects.save(el, props); el.show(); // Save & Show
11093 var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
11094 var animate = el[0].tagName == 'IMG' ? wrapper : el;
11095 var ref = {
11096 size: (direction == 'vertical') ? 'height' : 'width',
11097 position: (direction == 'vertical') ? 'top' : 'left'
11099 var distance = (direction == 'vertical') ? animate.height() : animate.width();
11100 if(mode == 'show') { animate.css(ref.size, 0); animate.css(ref.position, distance / 2); } // Shift
11102 // Animation
11103 var animation = {};
11104 animation[ref.size] = mode == 'show' ? distance : 0;
11105 animation[ref.position] = mode == 'show' ? 0 : distance / 2;
11107 // Animate
11108 animate.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
11109 if(mode == 'hide') el.hide(); // Hide
11110 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
11111 if(o.callback) o.callback.apply(el[0], arguments); // Callback
11112 el.dequeue();
11113 }});
11119 })(jQuery);
11121 * jQuery UI Effects Drop 1.8.16
11123 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
11124 * Dual licensed under the MIT or GPL Version 2 licenses.
11125 * http://jquery.org/license
11127 * http://docs.jquery.com/UI/Effects/Drop
11129 * Depends:
11130 * jquery.effects.core.js
11132 (function( $, undefined ) {
11134 $.effects.drop = function(o) {
11136 return this.queue(function() {
11138 // Create element
11139 var el = $(this), props = ['position','top','bottom','left','right','opacity'];
11141 // Set options
11142 var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
11143 var direction = o.options.direction || 'left'; // Default Direction
11145 // Adjust
11146 $.effects.save(el, props); el.show(); // Save & Show
11147 $.effects.createWrapper(el); // Create Wrapper
11148 var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
11149 var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
11150 var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) / 2 : el.outerWidth({margin:true}) / 2);
11151 if (mode == 'show') el.css('opacity', 0).css(ref, motion == 'pos' ? -distance : distance); // Shift
11153 // Animation
11154 var animation = {opacity: mode == 'show' ? 1 : 0};
11155 animation[ref] = (mode == 'show' ? (motion == 'pos' ? '+=' : '-=') : (motion == 'pos' ? '-=' : '+=')) + distance;
11157 // Animate
11158 el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
11159 if(mode == 'hide') el.hide(); // Hide
11160 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
11161 if(o.callback) o.callback.apply(this, arguments); // Callback
11162 el.dequeue();
11163 }});
11169 })(jQuery);
11171 * jQuery UI Effects Explode 1.8.16
11173 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
11174 * Dual licensed under the MIT or GPL Version 2 licenses.
11175 * http://jquery.org/license
11177 * http://docs.jquery.com/UI/Effects/Explode
11179 * Depends:
11180 * jquery.effects.core.js
11182 (function( $, undefined ) {
11184 $.effects.explode = function(o) {
11186 return this.queue(function() {
11188 var rows = o.options.pieces ? Math.round(Math.sqrt(o.options.pieces)) : 3;
11189 var cells = o.options.pieces ? Math.round(Math.sqrt(o.options.pieces)) : 3;
11191 o.options.mode = o.options.mode == 'toggle' ? ($(this).is(':visible') ? 'hide' : 'show') : o.options.mode;
11192 var el = $(this).show().css('visibility', 'hidden');
11193 var offset = el.offset();
11195 //Substract the margins - not fixing the problem yet.
11196 offset.top -= parseInt(el.css("marginTop"),10) || 0;
11197 offset.left -= parseInt(el.css("marginLeft"),10) || 0;
11199 var width = el.outerWidth(true);
11200 var height = el.outerHeight(true);
11202 for(var i=0;i<rows;i++) { // =
11203 for(var j=0;j<cells;j++) { // ||
11205 .clone()
11206 .appendTo('body')
11207 .wrap('<div></div>')
11208 .css({
11209 position: 'absolute',
11210 visibility: 'visible',
11211 left: -j*(width/cells),
11212 top: -i*(height/rows)
11214 .parent()
11215 .addClass('ui-effects-explode')
11216 .css({
11217 position: 'absolute',
11218 overflow: 'hidden',
11219 width: width/cells,
11220 height: height/rows,
11221 left: offset.left + j*(width/cells) + (o.options.mode == 'show' ? (j-Math.floor(cells/2))*(width/cells) : 0),
11222 top: offset.top + i*(height/rows) + (o.options.mode == 'show' ? (i-Math.floor(rows/2))*(height/rows) : 0),
11223 opacity: o.options.mode == 'show' ? 0 : 1
11224 }).animate({
11225 left: offset.left + j*(width/cells) + (o.options.mode == 'show' ? 0 : (j-Math.floor(cells/2))*(width/cells)),
11226 top: offset.top + i*(height/rows) + (o.options.mode == 'show' ? 0 : (i-Math.floor(rows/2))*(height/rows)),
11227 opacity: o.options.mode == 'show' ? 1 : 0
11228 }, o.duration || 500);
11232 // Set a timeout, to call the callback approx. when the other animations have finished
11233 setTimeout(function() {
11235 o.options.mode == 'show' ? el.css({ visibility: 'visible' }) : el.css({ visibility: 'visible' }).hide();
11236 if(o.callback) o.callback.apply(el[0]); // Callback
11237 el.dequeue();
11239 $('div.ui-effects-explode').remove();
11241 }, o.duration || 500);
11248 })(jQuery);
11250 * jQuery UI Effects Fade 1.8.16
11252 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
11253 * Dual licensed under the MIT or GPL Version 2 licenses.
11254 * http://jquery.org/license
11256 * http://docs.jquery.com/UI/Effects/Fade
11258 * Depends:
11259 * jquery.effects.core.js
11261 (function( $, undefined ) {
11263 $.effects.fade = function(o) {
11264 return this.queue(function() {
11265 var elem = $(this),
11266 mode = $.effects.setMode(elem, o.options.mode || 'hide');
11268 elem.animate({ opacity: mode }, {
11269 queue: false,
11270 duration: o.duration,
11271 easing: o.options.easing,
11272 complete: function() {
11273 (o.callback && o.callback.apply(this, arguments));
11274 elem.dequeue();
11280 })(jQuery);
11282 * jQuery UI Effects Fold 1.8.16
11284 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
11285 * Dual licensed under the MIT or GPL Version 2 licenses.
11286 * http://jquery.org/license
11288 * http://docs.jquery.com/UI/Effects/Fold
11290 * Depends:
11291 * jquery.effects.core.js
11293 (function( $, undefined ) {
11295 $.effects.fold = function(o) {
11297 return this.queue(function() {
11299 // Create element
11300 var el = $(this), props = ['position','top','bottom','left','right'];
11302 // Set options
11303 var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
11304 var size = o.options.size || 15; // Default fold size
11305 var horizFirst = !(!o.options.horizFirst); // Ensure a boolean value
11306 var duration = o.duration ? o.duration / 2 : $.fx.speeds._default / 2;
11308 // Adjust
11309 $.effects.save(el, props); el.show(); // Save & Show
11310 var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
11311 var widthFirst = ((mode == 'show') != horizFirst);
11312 var ref = widthFirst ? ['width', 'height'] : ['height', 'width'];
11313 var distance = widthFirst ? [wrapper.width(), wrapper.height()] : [wrapper.height(), wrapper.width()];
11314 var percent = /([0-9]+)%/.exec(size);
11315 if(percent) size = parseInt(percent[1],10) / 100 * distance[mode == 'hide' ? 0 : 1];
11316 if(mode == 'show') wrapper.css(horizFirst ? {height: 0, width: size} : {height: size, width: 0}); // Shift
11318 // Animation
11319 var animation1 = {}, animation2 = {};
11320 animation1[ref[0]] = mode == 'show' ? distance[0] : size;
11321 animation2[ref[1]] = mode == 'show' ? distance[1] : 0;
11323 // Animate
11324 wrapper.animate(animation1, duration, o.options.easing)
11325 .animate(animation2, duration, o.options.easing, function() {
11326 if(mode == 'hide') el.hide(); // Hide
11327 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
11328 if(o.callback) o.callback.apply(el[0], arguments); // Callback
11329 el.dequeue();
11336 })(jQuery);
11338 * jQuery UI Effects Highlight 1.8.16
11340 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
11341 * Dual licensed under the MIT or GPL Version 2 licenses.
11342 * http://jquery.org/license
11344 * http://docs.jquery.com/UI/Effects/Highlight
11346 * Depends:
11347 * jquery.effects.core.js
11349 (function( $, undefined ) {
11351 $.effects.highlight = function(o) {
11352 return this.queue(function() {
11353 var elem = $(this),
11354 props = ['backgroundImage', 'backgroundColor', 'opacity'],
11355 mode = $.effects.setMode(elem, o.options.mode || 'show'),
11356 animation = {
11357 backgroundColor: elem.css('backgroundColor')
11360 if (mode == 'hide') {
11361 animation.opacity = 0;
11364 $.effects.save(elem, props);
11365 elem
11366 .show()
11367 .css({
11368 backgroundImage: 'none',
11369 backgroundColor: o.options.color || '#ffff99'
11371 .animate(animation, {
11372 queue: false,
11373 duration: o.duration,
11374 easing: o.options.easing,
11375 complete: function() {
11376 (mode == 'hide' && elem.hide());
11377 $.effects.restore(elem, props);
11378 (mode == 'show' && !$.support.opacity && this.style.removeAttribute('filter'));
11379 (o.callback && o.callback.apply(this, arguments));
11380 elem.dequeue();
11386 })(jQuery);
11388 * jQuery UI Effects Pulsate 1.8.16
11390 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
11391 * Dual licensed under the MIT or GPL Version 2 licenses.
11392 * http://jquery.org/license
11394 * http://docs.jquery.com/UI/Effects/Pulsate
11396 * Depends:
11397 * jquery.effects.core.js
11399 (function( $, undefined ) {
11401 $.effects.pulsate = function(o) {
11402 return this.queue(function() {
11403 var elem = $(this),
11404 mode = $.effects.setMode(elem, o.options.mode || 'show');
11405 times = ((o.options.times || 5) * 2) - 1;
11406 duration = o.duration ? o.duration / 2 : $.fx.speeds._default / 2,
11407 isVisible = elem.is(':visible'),
11408 animateTo = 0;
11410 if (!isVisible) {
11411 elem.css('opacity', 0).show();
11412 animateTo = 1;
11415 if ((mode == 'hide' && isVisible) || (mode == 'show' && !isVisible)) {
11416 times--;
11419 for (var i = 0; i < times; i++) {
11420 elem.animate({ opacity: animateTo }, duration, o.options.easing);
11421 animateTo = (animateTo + 1) % 2;
11424 elem.animate({ opacity: animateTo }, duration, o.options.easing, function() {
11425 if (animateTo == 0) {
11426 elem.hide();
11428 (o.callback && o.callback.apply(this, arguments));
11431 elem
11432 .queue('fx', function() { elem.dequeue(); })
11433 .dequeue();
11437 })(jQuery);
11439 * jQuery UI Effects Scale 1.8.16
11441 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
11442 * Dual licensed under the MIT or GPL Version 2 licenses.
11443 * http://jquery.org/license
11445 * http://docs.jquery.com/UI/Effects/Scale
11447 * Depends:
11448 * jquery.effects.core.js
11450 (function( $, undefined ) {
11452 $.effects.puff = function(o) {
11453 return this.queue(function() {
11454 var elem = $(this),
11455 mode = $.effects.setMode(elem, o.options.mode || 'hide'),
11456 percent = parseInt(o.options.percent, 10) || 150,
11457 factor = percent / 100,
11458 original = { height: elem.height(), width: elem.width() };
11460 $.extend(o.options, {
11461 fade: true,
11462 mode: mode,
11463 percent: mode == 'hide' ? percent : 100,
11464 from: mode == 'hide'
11465 ? original
11467 height: original.height * factor,
11468 width: original.width * factor
11472 elem.effect('scale', o.options, o.duration, o.callback);
11473 elem.dequeue();
11477 $.effects.scale = function(o) {
11479 return this.queue(function() {
11481 // Create element
11482 var el = $(this);
11484 // Set options
11485 var options = $.extend(true, {}, o.options);
11486 var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
11487 var percent = parseInt(o.options.percent,10) || (parseInt(o.options.percent,10) == 0 ? 0 : (mode == 'hide' ? 0 : 100)); // Set default scaling percent
11488 var direction = o.options.direction || 'both'; // Set default axis
11489 var origin = o.options.origin; // The origin of the scaling
11490 if (mode != 'effect') { // Set default origin and restore for show/hide
11491 options.origin = origin || ['middle','center'];
11492 options.restore = true;
11494 var original = {height: el.height(), width: el.width()}; // Save original
11495 el.from = o.options.from || (mode == 'show' ? {height: 0, width: 0} : original); // Default from state
11497 // Adjust
11498 var factor = { // Set scaling factor
11499 y: direction != 'horizontal' ? (percent / 100) : 1,
11500 x: direction != 'vertical' ? (percent / 100) : 1
11502 el.to = {height: original.height * factor.y, width: original.width * factor.x}; // Set to state
11504 if (o.options.fade) { // Fade option to support puff
11505 if (mode == 'show') {el.from.opacity = 0; el.to.opacity = 1;};
11506 if (mode == 'hide') {el.from.opacity = 1; el.to.opacity = 0;};
11509 // Animation
11510 options.from = el.from; options.to = el.to; options.mode = mode;
11512 // Animate
11513 el.effect('size', options, o.duration, o.callback);
11514 el.dequeue();
11519 $.effects.size = function(o) {
11521 return this.queue(function() {
11523 // Create element
11524 var el = $(this), props = ['position','top','bottom','left','right','width','height','overflow','opacity'];
11525 var props1 = ['position','top','bottom','left','right','overflow','opacity']; // Always restore
11526 var props2 = ['width','height','overflow']; // Copy for children
11527 var cProps = ['fontSize'];
11528 var vProps = ['borderTopWidth', 'borderBottomWidth', 'paddingTop', 'paddingBottom'];
11529 var hProps = ['borderLeftWidth', 'borderRightWidth', 'paddingLeft', 'paddingRight'];
11531 // Set options
11532 var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
11533 var restore = o.options.restore || false; // Default restore
11534 var scale = o.options.scale || 'both'; // Default scale mode
11535 var origin = o.options.origin; // The origin of the sizing
11536 var original = {height: el.height(), width: el.width()}; // Save original
11537 el.from = o.options.from || original; // Default from state
11538 el.to = o.options.to || original; // Default to state
11539 // Adjust
11540 if (origin) { // Calculate baseline shifts
11541 var baseline = $.effects.getBaseline(origin, original);
11542 el.from.top = (original.height - el.from.height) * baseline.y;
11543 el.from.left = (original.width - el.from.width) * baseline.x;
11544 el.to.top = (original.height - el.to.height) * baseline.y;
11545 el.to.left = (original.width - el.to.width) * baseline.x;
11547 var factor = { // Set scaling factor
11548 from: {y: el.from.height / original.height, x: el.from.width / original.width},
11549 to: {y: el.to.height / original.height, x: el.to.width / original.width}
11551 if (scale == 'box' || scale == 'both') { // Scale the css box
11552 if (factor.from.y != factor.to.y) { // Vertical props scaling
11553 props = props.concat(vProps);
11554 el.from = $.effects.setTransition(el, vProps, factor.from.y, el.from);
11555 el.to = $.effects.setTransition(el, vProps, factor.to.y, el.to);
11557 if (factor.from.x != factor.to.x) { // Horizontal props scaling
11558 props = props.concat(hProps);
11559 el.from = $.effects.setTransition(el, hProps, factor.from.x, el.from);
11560 el.to = $.effects.setTransition(el, hProps, factor.to.x, el.to);
11563 if (scale == 'content' || scale == 'both') { // Scale the content
11564 if (factor.from.y != factor.to.y) { // Vertical props scaling
11565 props = props.concat(cProps);
11566 el.from = $.effects.setTransition(el, cProps, factor.from.y, el.from);
11567 el.to = $.effects.setTransition(el, cProps, factor.to.y, el.to);
11570 $.effects.save(el, restore ? props : props1); el.show(); // Save & Show
11571 $.effects.createWrapper(el); // Create Wrapper
11572 el.css('overflow','hidden').css(el.from); // Shift
11574 // Animate
11575 if (scale == 'content' || scale == 'both') { // Scale the children
11576 vProps = vProps.concat(['marginTop','marginBottom']).concat(cProps); // Add margins/font-size
11577 hProps = hProps.concat(['marginLeft','marginRight']); // Add margins
11578 props2 = props.concat(vProps).concat(hProps); // Concat
11579 el.find("*[width]").each(function(){
11580 child = $(this);
11581 if (restore) $.effects.save(child, props2);
11582 var c_original = {height: child.height(), width: child.width()}; // Save original
11583 child.from = {height: c_original.height * factor.from.y, width: c_original.width * factor.from.x};
11584 child.to = {height: c_original.height * factor.to.y, width: c_original.width * factor.to.x};
11585 if (factor.from.y != factor.to.y) { // Vertical props scaling
11586 child.from = $.effects.setTransition(child, vProps, factor.from.y, child.from);
11587 child.to = $.effects.setTransition(child, vProps, factor.to.y, child.to);
11589 if (factor.from.x != factor.to.x) { // Horizontal props scaling
11590 child.from = $.effects.setTransition(child, hProps, factor.from.x, child.from);
11591 child.to = $.effects.setTransition(child, hProps, factor.to.x, child.to);
11593 child.css(child.from); // Shift children
11594 child.animate(child.to, o.duration, o.options.easing, function(){
11595 if (restore) $.effects.restore(child, props2); // Restore children
11596 }); // Animate children
11600 // Animate
11601 el.animate(el.to, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
11602 if (el.to.opacity === 0) {
11603 el.css('opacity', el.from.opacity);
11605 if(mode == 'hide') el.hide(); // Hide
11606 $.effects.restore(el, restore ? props : props1); $.effects.removeWrapper(el); // Restore
11607 if(o.callback) o.callback.apply(this, arguments); // Callback
11608 el.dequeue();
11609 }});
11615 })(jQuery);
11617 * jQuery UI Effects Shake 1.8.16
11619 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
11620 * Dual licensed under the MIT or GPL Version 2 licenses.
11621 * http://jquery.org/license
11623 * http://docs.jquery.com/UI/Effects/Shake
11625 * Depends:
11626 * jquery.effects.core.js
11628 (function( $, undefined ) {
11630 $.effects.shake = function(o) {
11632 return this.queue(function() {
11634 // Create element
11635 var el = $(this), props = ['position','top','bottom','left','right'];
11637 // Set options
11638 var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
11639 var direction = o.options.direction || 'left'; // Default direction
11640 var distance = o.options.distance || 20; // Default distance
11641 var times = o.options.times || 3; // Default # of times
11642 var speed = o.duration || o.options.duration || 140; // Default speed per shake
11644 // Adjust
11645 $.effects.save(el, props); el.show(); // Save & Show
11646 $.effects.createWrapper(el); // Create Wrapper
11647 var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
11648 var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
11650 // Animation
11651 var animation = {}, animation1 = {}, animation2 = {};
11652 animation[ref] = (motion == 'pos' ? '-=' : '+=') + distance;
11653 animation1[ref] = (motion == 'pos' ? '+=' : '-=') + distance * 2;
11654 animation2[ref] = (motion == 'pos' ? '-=' : '+=') + distance * 2;
11656 // Animate
11657 el.animate(animation, speed, o.options.easing);
11658 for (var i = 1; i < times; i++) { // Shakes
11659 el.animate(animation1, speed, o.options.easing).animate(animation2, speed, o.options.easing);
11661 el.animate(animation1, speed, o.options.easing).
11662 animate(animation, speed / 2, o.options.easing, function(){ // Last shake
11663 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
11664 if(o.callback) o.callback.apply(this, arguments); // Callback
11666 el.queue('fx', function() { el.dequeue(); });
11667 el.dequeue();
11672 })(jQuery);
11674 * jQuery UI Effects Slide 1.8.16
11676 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
11677 * Dual licensed under the MIT or GPL Version 2 licenses.
11678 * http://jquery.org/license
11680 * http://docs.jquery.com/UI/Effects/Slide
11682 * Depends:
11683 * jquery.effects.core.js
11685 (function( $, undefined ) {
11687 $.effects.slide = function(o) {
11689 return this.queue(function() {
11691 // Create element
11692 var el = $(this), props = ['position','top','bottom','left','right'];
11694 // Set options
11695 var mode = $.effects.setMode(el, o.options.mode || 'show'); // Set Mode
11696 var direction = o.options.direction || 'left'; // Default Direction
11698 // Adjust
11699 $.effects.save(el, props); el.show(); // Save & Show
11700 $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
11701 var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
11702 var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
11703 var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) : el.outerWidth({margin:true}));
11704 if (mode == 'show') el.css(ref, motion == 'pos' ? (isNaN(distance) ? "-" + distance : -distance) : distance); // Shift
11706 // Animation
11707 var animation = {};
11708 animation[ref] = (mode == 'show' ? (motion == 'pos' ? '+=' : '-=') : (motion == 'pos' ? '-=' : '+=')) + distance;
11710 // Animate
11711 el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
11712 if(mode == 'hide') el.hide(); // Hide
11713 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
11714 if(o.callback) o.callback.apply(this, arguments); // Callback
11715 el.dequeue();
11716 }});
11722 })(jQuery);
11724 * jQuery UI Effects Transfer 1.8.16
11726 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
11727 * Dual licensed under the MIT or GPL Version 2 licenses.
11728 * http://jquery.org/license
11730 * http://docs.jquery.com/UI/Effects/Transfer
11732 * Depends:
11733 * jquery.effects.core.js
11735 (function( $, undefined ) {
11737 $.effects.transfer = function(o) {
11738 return this.queue(function() {
11739 var elem = $(this),
11740 target = $(o.options.to),
11741 endPosition = target.offset(),
11742 animation = {
11743 top: endPosition.top,
11744 left: endPosition.left,
11745 height: target.innerHeight(),
11746 width: target.innerWidth()
11748 startPosition = elem.offset(),
11749 transfer = $('<div class="ui-effects-transfer"></div>')
11750 .appendTo(document.body)
11751 .addClass(o.options.className)
11752 .css({
11753 top: startPosition.top,
11754 left: startPosition.left,
11755 height: elem.innerHeight(),
11756 width: elem.innerWidth(),
11757 position: 'absolute'
11759 .animate(animation, o.duration, o.options.easing, function() {
11760 transfer.remove();
11761 (o.callback && o.callback.apply(elem[0], arguments));
11762 elem.dequeue();
11767 })(jQuery);