Undefined variables when nothing is uploaded into a BLOB column
[phpmyadmin-themes.git] / js / jquery / jquery-ui-1.8.custom.js
blob1c7f3641d16a03fb49f212c4c03162669f2b0d80
1 /*!
2  * jQuery UI 1.8
3  *
4  * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
5  * Dual licensed under the MIT (MIT-LICENSE.txt)
6  * and GPL (GPL-LICENSE.txt) licenses.
7  *
8  * http://docs.jquery.com/UI
9  */
10 ;jQuery.ui || (function($) {
12 //Helper functions and ui object
13 $.ui = {
14         version: "1.8",
16         // $.ui.plugin is deprecated.  Use the proxy pattern instead.
17         plugin: {
18                 add: function(module, option, set) {
19                         var proto = $.ui[module].prototype;
20                         for(var i in set) {
21                                 proto.plugins[i] = proto.plugins[i] || [];
22                                 proto.plugins[i].push([option, set[i]]);
23                         }
24                 },
25                 call: function(instance, name, args) {
26                         var set = instance.plugins[name];
27                         if(!set || !instance.element[0].parentNode) { return; }
29                         for (var i = 0; i < set.length; i++) {
30                                 if (instance.options[set[i][0]]) {
31                                         set[i][1].apply(instance.element, args);
32                                 }
33                         }
34                 }
35         },
37         contains: function(a, b) {
38                 return document.compareDocumentPosition
39                         ? a.compareDocumentPosition(b) & 16
40                         : a !== b && a.contains(b);
41         },
43         hasScroll: function(el, a) {
45                 //If overflow is hidden, the element might have extra content, but the user wants to hide it
46                 if ($(el).css('overflow') == 'hidden') { return false; }
48                 var scroll = (a && a == 'left') ? 'scrollLeft' : 'scrollTop',
49                         has = false;
51                 if (el[scroll] > 0) { return true; }
53                 // TODO: determine which cases actually cause this to happen
54                 // if the element doesn't have the scroll set, see if it's possible to
55                 // set the scroll
56                 el[scroll] = 1;
57                 has = (el[scroll] > 0);
58                 el[scroll] = 0;
59                 return has;
60         },
62         isOverAxis: function(x, reference, size) {
63                 //Determines when x coordinate is over "b" element axis
64                 return (x > reference) && (x < (reference + size));
65         },
67         isOver: function(y, x, top, left, height, width) {
68                 //Determines when x, y coordinates is over "b" element
69                 return $.ui.isOverAxis(y, top, height) && $.ui.isOverAxis(x, left, width);
70         },
72         keyCode: {
73                 BACKSPACE: 8,
74                 CAPS_LOCK: 20,
75                 COMMA: 188,
76                 CONTROL: 17,
77                 DELETE: 46,
78                 DOWN: 40,
79                 END: 35,
80                 ENTER: 13,
81                 ESCAPE: 27,
82                 HOME: 36,
83                 INSERT: 45,
84                 LEFT: 37,
85                 NUMPAD_ADD: 107,
86                 NUMPAD_DECIMAL: 110,
87                 NUMPAD_DIVIDE: 111,
88                 NUMPAD_ENTER: 108,
89                 NUMPAD_MULTIPLY: 106,
90                 NUMPAD_SUBTRACT: 109,
91                 PAGE_DOWN: 34,
92                 PAGE_UP: 33,
93                 PERIOD: 190,
94                 RIGHT: 39,
95                 SHIFT: 16,
96                 SPACE: 32,
97                 TAB: 9,
98                 UP: 38
99         }
102 //jQuery plugins
103 $.fn.extend({
104         _focus: $.fn.focus,
105         focus: function(delay, fn) {
106                 return typeof delay === 'number'
107                         ? this.each(function() {
108                                 var elem = this;
109                                 setTimeout(function() {
110                                         $(elem).focus();
111                                         (fn && fn.call(elem));
112                                 }, delay);
113                         })
114                         : this._focus.apply(this, arguments);
115         },
116         
117         enableSelection: function() {
118                 return this
119                         .attr('unselectable', 'off')
120                         .css('MozUserSelect', '')
121                         .unbind('selectstart.ui');
122         },
124         disableSelection: function() {
125                 return this
126                         .attr('unselectable', 'on')
127                         .css('MozUserSelect', 'none')
128                         .bind('selectstart.ui', function() { return false; });
129         },
131         scrollParent: function() {
132                 var scrollParent;
133                 if(($.browser.msie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) {
134                         scrollParent = this.parents().filter(function() {
135                                 return (/(relative|absolute|fixed)/).test($.curCSS(this,'position',1)) && (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
136                         }).eq(0);
137                 } else {
138                         scrollParent = this.parents().filter(function() {
139                                 return (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
140                         }).eq(0);
141                 }
143                 return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent;
144         },
146         zIndex: function(zIndex) {
147                 if (zIndex !== undefined) {
148                         return this.css('zIndex', zIndex);
149                 }
150                 
151                 if (this.length) {
152                         var elem = $(this[0]), position, value;
153                         while (elem.length && elem[0] !== document) {
154                                 // Ignore z-index if position is set to a value where z-index is ignored by the browser
155                                 // This makes behavior of this function consistent across browsers
156                                 // WebKit always returns auto if the element is positioned
157                                 position = elem.css('position');
158                                 if (position == 'absolute' || position == 'relative' || position == 'fixed')
159                                 {
160                                         // IE returns 0 when zIndex is not specified
161                                         // other browsers return a string
162                                         // we ignore the case of nested elements with an explicit value of 0
163                                         // <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
164                                         value = parseInt(elem.css('zIndex'));
165                                         if (!isNaN(value) && value != 0) {
166                                                 return value;
167                                         }
168                                 }
169                                 elem = elem.parent();
170                         }
171                 }
173                 return 0;
174         }
178 //Additional selectors
179 $.extend($.expr[':'], {
180         data: function(elem, i, match) {
181                 return !!$.data(elem, match[3]);
182         },
184         focusable: function(element) {
185                 var nodeName = element.nodeName.toLowerCase(),
186                         tabIndex = $.attr(element, 'tabindex');
187                 return (/input|select|textarea|button|object/.test(nodeName)
188                         ? !element.disabled
189                         : 'a' == nodeName || 'area' == nodeName
190                                 ? element.href || !isNaN(tabIndex)
191                                 : !isNaN(tabIndex))
192                         // the element and all of its ancestors must be visible
193                         // the browser may report that the area is hidden
194                         && !$(element)['area' == nodeName ? 'parents' : 'closest'](':hidden').length;
195         },
197         tabbable: function(element) {
198                 var tabIndex = $.attr(element, 'tabindex');
199                 return (isNaN(tabIndex) || tabIndex >= 0) && $(element).is(':focusable');
200         }
203 })(jQuery);
205  * jQuery UI Widget 1.8
207  * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
208  * Dual licensed under the MIT (MIT-LICENSE.txt)
209  * and GPL (GPL-LICENSE.txt) licenses.
211  * http://docs.jquery.com/UI/Widget
212  */
213 (function( $ ) {
215 var _remove = $.fn.remove;
217 $.fn.remove = function( selector, keepData ) {
218         return this.each(function() {
219                 if ( !keepData ) {
220                         if ( !selector || $.filter( selector, [ this ] ).length ) {
221                                 $( "*", this ).add( this ).each(function() {
222                                         $( this ).triggerHandler( "remove" );
223                                 });
224                         }
225                 }
226                 return _remove.call( $(this), selector, keepData );
227         });
230 $.widget = function( name, base, prototype ) {
231         var namespace = name.split( "." )[ 0 ],
232                 fullName;
233         name = name.split( "." )[ 1 ];
234         fullName = namespace + "-" + name;
236         if ( !prototype ) {
237                 prototype = base;
238                 base = $.Widget;
239         }
241         // create selector for plugin
242         $.expr[ ":" ][ fullName ] = function( elem ) {
243                 return !!$.data( elem, name );
244         };
246         $[ namespace ] = $[ namespace ] || {};
247         $[ namespace ][ name ] = function( options, element ) {
248                 // allow instantiation without initializing for simple inheritance
249                 if ( arguments.length ) {
250                         this._createWidget( options, element );
251                 }
252         };
254         var basePrototype = new base();
255         // we need to make the options hash a property directly on the new instance
256         // otherwise we'll modify the options hash on the prototype that we're
257         // inheriting from
258 //      $.each( basePrototype, function( key, val ) {
259 //              if ( $.isPlainObject(val) ) {
260 //                      basePrototype[ key ] = $.extend( {}, val );
261 //              }
262 //      });
263         basePrototype.options = $.extend( {}, basePrototype.options );
264         $[ namespace ][ name ].prototype = $.extend( true, basePrototype, {
265                 namespace: namespace,
266                 widgetName: name,
267                 widgetEventPrefix: $[ namespace ][ name ].prototype.widgetEventPrefix || name,
268                 widgetBaseClass: fullName
269         }, prototype );
271         $.widget.bridge( name, $[ namespace ][ name ] );
274 $.widget.bridge = function( name, object ) {
275         $.fn[ name ] = function( options ) {
276                 var isMethodCall = typeof options === "string",
277                         args = Array.prototype.slice.call( arguments, 1 ),
278                         returnValue = this;
280                 // allow multiple hashes to be passed on init
281                 options = !isMethodCall && args.length ?
282                         $.extend.apply( null, [ true, options ].concat(args) ) :
283                         options;
285                 // prevent calls to internal methods
286                 if ( isMethodCall && options.substring( 0, 1 ) === "_" ) {
287                         return returnValue;
288                 }
290                 if ( isMethodCall ) {
291                         this.each(function() {
292                                 var instance = $.data( this, name ),
293                                         methodValue = instance && $.isFunction( instance[options] ) ?
294                                                 instance[ options ].apply( instance, args ) :
295                                                 instance;
296                                 if ( methodValue !== instance && methodValue !== undefined ) {
297                                         returnValue = methodValue;
298                                         return false;
299                                 }
300                         });
301                 } else {
302                         this.each(function() {
303                                 var instance = $.data( this, name );
304                                 if ( instance ) {
305                                         if ( options ) {
306                                                 instance.option( options );
307                                         }
308                                         instance._init();
309                                 } else {
310                                         $.data( this, name, new object( options, this ) );
311                                 }
312                         });
313                 }
315                 return returnValue;
316         };
319 $.Widget = function( options, element ) {
320         // allow instantiation without initializing for simple inheritance
321         if ( arguments.length ) {
322                 this._createWidget( options, element );
323         }
326 $.Widget.prototype = {
327         widgetName: "widget",
328         widgetEventPrefix: "",
329         options: {
330                 disabled: false
331         },
332         _createWidget: function( options, element ) {
333                 // $.widget.bridge stores the plugin instance, but we do it anyway
334                 // so that it's stored even before the _create function runs
335                 this.element = $( element ).data( this.widgetName, this );
336                 this.options = $.extend( true, {},
337                         this.options,
338                         $.metadata && $.metadata.get( element )[ this.widgetName ],
339                         options );
341                 var self = this;
342                 this.element.bind( "remove." + this.widgetName, function() {
343                         self.destroy();
344                 });
346                 this._create();
347                 this._init();
348         },
349         _create: function() {},
350         _init: function() {},
352         destroy: function() {
353                 this.element
354                         .unbind( "." + this.widgetName )
355                         .removeData( this.widgetName );
356                 this.widget()
357                         .unbind( "." + this.widgetName )
358                         .removeAttr( "aria-disabled" )
359                         .removeClass(
360                                 this.widgetBaseClass + "-disabled " +
361                                 this.namespace + "-state-disabled" );
362         },
364         widget: function() {
365                 return this.element;
366         },
368         option: function( key, value ) {
369                 var options = key,
370                         self = this;
372                 if ( arguments.length === 0 ) {
373                         // don't return a reference to the internal hash
374                         return $.extend( {}, self.options );
375                 }
377                 if  (typeof key === "string" ) {
378                         if ( value === undefined ) {
379                                 return this.options[ key ];
380                         }
381                         options = {};
382                         options[ key ] = value;
383                 }
385                 $.each( options, function( key, value ) {
386                         self._setOption( key, value );
387                 });
389                 return self;
390         },
391         _setOption: function( key, value ) {
392                 this.options[ key ] = value;
394                 if ( key === "disabled" ) {
395                         this.widget()
396                                 [ value ? "addClass" : "removeClass"](
397                                         this.widgetBaseClass + "-disabled" + " " +
398                                         this.namespace + "-state-disabled" )
399                                 .attr( "aria-disabled", value );
400                 }
402                 return this;
403         },
405         enable: function() {
406                 return this._setOption( "disabled", false );
407         },
408         disable: function() {
409                 return this._setOption( "disabled", true );
410         },
412         _trigger: function( type, event, data ) {
413                 var callback = this.options[ type ];
415                 event = $.Event( event );
416                 event.type = ( type === this.widgetEventPrefix ?
417                         type :
418                         this.widgetEventPrefix + type ).toLowerCase();
419                 data = data || {};
421                 // copy original event properties over to the new event
422                 // this would happen if we could call $.event.fix instead of $.Event
423                 // but we don't have a way to force an event to be fixed multiple times
424                 if ( event.originalEvent ) {
425                         for ( var i = $.event.props.length, prop; i; ) {
426                                 prop = $.event.props[ --i ];
427                                 event[ prop ] = event.originalEvent[ prop ];
428                         }
429                 }
431                 this.element.trigger( event, data );
433                 return !( $.isFunction(callback) &&
434                         callback.call( this.element[0], event, data ) === false ||
435                         event.isDefaultPrevented() );
436         }
439 })( jQuery );
441  * jQuery UI Mouse 1.8
443  * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
444  * Dual licensed under the MIT (MIT-LICENSE.txt)
445  * and GPL (GPL-LICENSE.txt) licenses.
447  * http://docs.jquery.com/UI/Mouse
449  * Depends:
450  *      jquery.ui.widget.js
451  */
452 (function($) {
454 $.widget("ui.mouse", {
455         options: {
456                 cancel: ':input,option',
457                 distance: 1,
458                 delay: 0
459         },
460         _mouseInit: function() {
461                 var self = this;
463                 this.element
464                         .bind('mousedown.'+this.widgetName, function(event) {
465                                 return self._mouseDown(event);
466                         })
467                         .bind('click.'+this.widgetName, function(event) {
468                                 if(self._preventClickEvent) {
469                                         self._preventClickEvent = false;
470                                         event.stopImmediatePropagation();
471                                         return false;
472                                 }
473                         });
475                 this.started = false;
476         },
478         // TODO: make sure destroying one instance of mouse doesn't mess with
479         // other instances of mouse
480         _mouseDestroy: function() {
481                 this.element.unbind('.'+this.widgetName);
482         },
484         _mouseDown: function(event) {
485                 // don't let more than one widget handle mouseStart
486                 // TODO: figure out why we have to use originalEvent
487                 event.originalEvent = event.originalEvent || {};
488                 if (event.originalEvent.mouseHandled) { return; }
490                 // we may have missed mouseup (out of window)
491                 (this._mouseStarted && this._mouseUp(event));
493                 this._mouseDownEvent = event;
495                 var self = this,
496                         btnIsLeft = (event.which == 1),
497                         elIsCancel = (typeof this.options.cancel == "string" ? $(event.target).parents().add(event.target).filter(this.options.cancel).length : false);
498                 if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
499                         return true;
500                 }
502                 this.mouseDelayMet = !this.options.delay;
503                 if (!this.mouseDelayMet) {
504                         this._mouseDelayTimer = setTimeout(function() {
505                                 self.mouseDelayMet = true;
506                         }, this.options.delay);
507                 }
509                 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
510                         this._mouseStarted = (this._mouseStart(event) !== false);
511                         if (!this._mouseStarted) {
512                                 event.preventDefault();
513                                 return true;
514                         }
515                 }
517                 // these delegates are required to keep context
518                 this._mouseMoveDelegate = function(event) {
519                         return self._mouseMove(event);
520                 };
521                 this._mouseUpDelegate = function(event) {
522                         return self._mouseUp(event);
523                 };
524                 $(document)
525                         .bind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
526                         .bind('mouseup.'+this.widgetName, this._mouseUpDelegate);
528                 // preventDefault() is used to prevent the selection of text here -
529                 // however, in Safari, this causes select boxes not to be selectable
530                 // anymore, so this fix is needed
531                 ($.browser.safari || event.preventDefault());
533                 event.originalEvent.mouseHandled = true;
534                 return true;
535         },
537         _mouseMove: function(event) {
538                 // IE mouseup check - mouseup happened when mouse was out of window
539                 if ($.browser.msie && !event.button) {
540                         return this._mouseUp(event);
541                 }
543                 if (this._mouseStarted) {
544                         this._mouseDrag(event);
545                         return event.preventDefault();
546                 }
548                 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
549                         this._mouseStarted =
550                                 (this._mouseStart(this._mouseDownEvent, event) !== false);
551                         (this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
552                 }
554                 return !this._mouseStarted;
555         },
557         _mouseUp: function(event) {
558                 $(document)
559                         .unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
560                         .unbind('mouseup.'+this.widgetName, this._mouseUpDelegate);
562                 if (this._mouseStarted) {
563                         this._mouseStarted = false;
564                         this._preventClickEvent = (event.target == this._mouseDownEvent.target);
565                         this._mouseStop(event);
566                 }
568                 return false;
569         },
571         _mouseDistanceMet: function(event) {
572                 return (Math.max(
573                                 Math.abs(this._mouseDownEvent.pageX - event.pageX),
574                                 Math.abs(this._mouseDownEvent.pageY - event.pageY)
575                         ) >= this.options.distance
576                 );
577         },
579         _mouseDelayMet: function(event) {
580                 return this.mouseDelayMet;
581         },
583         // These are placeholder methods, to be overriden by extending plugin
584         _mouseStart: function(event) {},
585         _mouseDrag: function(event) {},
586         _mouseStop: function(event) {},
587         _mouseCapture: function(event) { return true; }
590 })(jQuery);
592  * jQuery UI Position 1.8
594  * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
595  * Dual licensed under the MIT (MIT-LICENSE.txt)
596  * and GPL (GPL-LICENSE.txt) licenses.
598  * http://docs.jquery.com/UI/Position
599  */
600 (function( $ ) {
602 $.ui = $.ui || {};
604 var horizontalPositions = /left|center|right/,
605         horizontalDefault = "center",
606         verticalPositions = /top|center|bottom/,
607         verticalDefault = "center",
608         _position = $.fn.position,
609         _offset = $.fn.offset;
611 $.fn.position = function( options ) {
612         if ( !options || !options.of ) {
613                 return _position.apply( this, arguments );
614         }
616         // make a copy, we don't want to modify arguments
617         options = $.extend( {}, options );
619         var target = $( options.of ),
620                 collision = ( options.collision || "flip" ).split( " " ),
621                 offset = options.offset ? options.offset.split( " " ) : [ 0, 0 ],
622                 targetWidth,
623                 targetHeight,
624                 basePosition;
626         if ( options.of.nodeType === 9 ) {
627                 targetWidth = target.width();
628                 targetHeight = target.height();
629                 basePosition = { top: 0, left: 0 };
630         } else if ( options.of.scrollTo && options.of.document ) {
631                 targetWidth = target.width();
632                 targetHeight = target.height();
633                 basePosition = { top: target.scrollTop(), left: target.scrollLeft() };
634         } else if ( options.of.preventDefault ) {
635                 // force left top to allow flipping
636                 options.at = "left top";
637                 targetWidth = targetHeight = 0;
638                 basePosition = { top: options.of.pageY, left: options.of.pageX };
639         } else {
640                 targetWidth = target.outerWidth();
641                 targetHeight = target.outerHeight();
642                 basePosition = target.offset();
643         }
645         // force my and at to have valid horizontal and veritcal positions
646         // if a value is missing or invalid, it will be converted to center 
647         $.each( [ "my", "at" ], function() {
648                 var pos = ( options[this] || "" ).split( " " );
649                 if ( pos.length === 1) {
650                         pos = horizontalPositions.test( pos[0] ) ?
651                                 pos.concat( [verticalDefault] ) :
652                                 verticalPositions.test( pos[0] ) ?
653                                         [ horizontalDefault ].concat( pos ) :
654                                         [ horizontalDefault, verticalDefault ];
655                 }
656                 pos[ 0 ] = horizontalPositions.test( pos[0] ) ? pos[ 0 ] : horizontalDefault;
657                 pos[ 1 ] = verticalPositions.test( pos[1] ) ? pos[ 1 ] : verticalDefault;
658                 options[ this ] = pos;
659         });
661         // normalize collision option
662         if ( collision.length === 1 ) {
663                 collision[ 1 ] = collision[ 0 ];
664         }
666         // normalize offset option
667         offset[ 0 ] = parseInt( offset[0], 10 ) || 0;
668         if ( offset.length === 1 ) {
669                 offset[ 1 ] = offset[ 0 ];
670         }
671         offset[ 1 ] = parseInt( offset[1], 10 ) || 0;
673         if ( options.at[0] === "right" ) {
674                 basePosition.left += targetWidth;
675         } else if (options.at[0] === horizontalDefault ) {
676                 basePosition.left += targetWidth / 2;
677         }
679         if ( options.at[1] === "bottom" ) {
680                 basePosition.top += targetHeight;
681         } else if ( options.at[1] === verticalDefault ) {
682                 basePosition.top += targetHeight / 2;
683         }
685         basePosition.left += offset[ 0 ];
686         basePosition.top += offset[ 1 ];
688         return this.each(function() {
689                 var elem = $( this ),
690                         elemWidth = elem.outerWidth(),
691                         elemHeight = elem.outerHeight(),
692                         position = $.extend( {}, basePosition );
694                 if ( options.my[0] === "right" ) {
695                         position.left -= elemWidth;
696                 } else if ( options.my[0] === horizontalDefault ) {
697                         position.left -= elemWidth / 2;
698                 }
700                 if ( options.my[1] === "bottom" ) {
701                         position.top -= elemHeight;
702                 } else if ( options.my[1] === verticalDefault ) {
703                         position.top -= elemHeight / 2;
704                 }
706                 $.each( [ "left", "top" ], function( i, dir ) {
707                         if ( $.ui.position[ collision[i] ] ) {
708                                 $.ui.position[ collision[i] ][ dir ]( position, {
709                                         targetWidth: targetWidth,
710                                         targetHeight: targetHeight,
711                                         elemWidth: elemWidth,
712                                         elemHeight: elemHeight,
713                                         offset: offset,
714                                         my: options.my,
715                                         at: options.at
716                                 });
717                         }
718                 });
720                 if ( $.fn.bgiframe ) {
721                         elem.bgiframe();
722                 }
723                 elem.offset( $.extend( position, { using: options.using } ) );
724         });
727 $.ui.position = {
728         fit: {
729                 left: function( position, data ) {
730                         var win = $( window ),
731                                 over = position.left + data.elemWidth - win.width() - win.scrollLeft();
732                         position.left = over > 0 ? position.left - over : Math.max( 0, position.left );
733                 },
734                 top: function( position, data ) {
735                         var win = $( window ),
736                                 over = position.top + data.elemHeight - win.height() - win.scrollTop();
737                         position.top = over > 0 ? position.top - over : Math.max( 0, position.top );
738                 }
739         },
741         flip: {
742                 left: function( position, data ) {
743                         if ( data.at[0] === "center" ) {
744                                 return;
745                         }
746                         var win = $( window ),
747                                 over = position.left + data.elemWidth - win.width() - win.scrollLeft(),
748                                 myOffset = data.my[ 0 ] === "left" ?
749                                         -data.elemWidth :
750                                         data.my[ 0 ] === "right" ?
751                                                 data.elemWidth :
752                                                 0,
753                                 offset = -2 * data.offset[ 0 ];
754                         position.left += position.left < 0 ?
755                                 myOffset + data.targetWidth + offset :
756                                 over > 0 ?
757                                         myOffset - data.targetWidth + offset :
758                                         0;
759                 },
760                 top: function( position, data ) {
761                         if ( data.at[1] === "center" ) {
762                                 return;
763                         }
764                         var win = $( window ),
765                                 over = position.top + data.elemHeight - win.height() - win.scrollTop(),
766                                 myOffset = data.my[ 1 ] === "top" ?
767                                         -data.elemHeight :
768                                         data.my[ 1 ] === "bottom" ?
769                                                 data.elemHeight :
770                                                 0,
771                                 atOffset = data.at[ 1 ] === "top" ?
772                                         data.targetHeight :
773                                         -data.targetHeight,
774                                 offset = -2 * data.offset[ 1 ];
775                         position.top += position.top < 0 ?
776                                 myOffset + data.targetHeight + offset :
777                                 over > 0 ?
778                                         myOffset + atOffset + offset :
779                                         0;
780                 }
781         }
784 // offset setter from jQuery 1.4
785 if ( !$.offset.setOffset ) {
786         $.offset.setOffset = function( elem, options ) {
787                 // set position first, in-case top/left are set even on static elem
788                 if ( /static/.test( $.curCSS( elem, "position" ) ) ) {
789                         elem.style.position = "relative";
790                 }
791                 var curElem   = $( elem ),
792                         curOffset = curElem.offset(),
793                         curTop    = parseInt( $.curCSS( elem, "top",  true ), 10 ) || 0,
794                         curLeft   = parseInt( $.curCSS( elem, "left", true ), 10)  || 0,
795                         props     = {
796                                 top:  (options.top  - curOffset.top)  + curTop,
797                                 left: (options.left - curOffset.left) + curLeft
798                         };
799                 
800                 if ( 'using' in options ) {
801                         options.using.call( elem, props );
802                 } else {
803                         curElem.css( props );
804                 }
805         };
807         $.fn.offset = function( options ) {
808                 var elem = this[ 0 ];
809                 if ( !elem || !elem.ownerDocument ) { return null; }
810                 if ( options ) { 
811                         return this.each(function() {
812                                 $.offset.setOffset( this, options );
813                         });
814                 }
815                 return _offset.call( this );
816         };
819 }( jQuery ));
821  * jQuery UI Draggable 1.8
823  * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
824  * Dual licensed under the MIT (MIT-LICENSE.txt)
825  * and GPL (GPL-LICENSE.txt) licenses.
827  * http://docs.jquery.com/UI/Draggables
829  * Depends:
830  *      jquery.ui.core.js
831  *      jquery.ui.mouse.js
832  *      jquery.ui.widget.js
833  */
834 (function($) {
836 $.widget("ui.draggable", $.ui.mouse, {
837         widgetEventPrefix: "drag",
838         options: {
839                 addClasses: true,
840                 appendTo: "parent",
841                 axis: false,
842                 connectToSortable: false,
843                 containment: false,
844                 cursor: "auto",
845                 cursorAt: false,
846                 grid: false,
847                 handle: false,
848                 helper: "original",
849                 iframeFix: false,
850                 opacity: false,
851                 refreshPositions: false,
852                 revert: false,
853                 revertDuration: 500,
854                 scope: "default",
855                 scroll: true,
856                 scrollSensitivity: 20,
857                 scrollSpeed: 20,
858                 snap: false,
859                 snapMode: "both",
860                 snapTolerance: 20,
861                 stack: false,
862                 zIndex: false
863         },
864         _create: function() {
866                 if (this.options.helper == 'original' && !(/^(?:r|a|f)/).test(this.element.css("position")))
867                         this.element[0].style.position = 'relative';
869                 (this.options.addClasses && this.element.addClass("ui-draggable"));
870                 (this.options.disabled && this.element.addClass("ui-draggable-disabled"));
872                 this._mouseInit();
874         },
876         destroy: function() {
877                 if(!this.element.data('draggable')) return;
878                 this.element
879                         .removeData("draggable")
880                         .unbind(".draggable")
881                         .removeClass("ui-draggable"
882                                 + " ui-draggable-dragging"
883                                 + " ui-draggable-disabled");
884                 this._mouseDestroy();
886                 return this;
887         },
889         _mouseCapture: function(event) {
891                 var o = this.options;
893                 // among others, prevent a drag on a resizable-handle
894                 if (this.helper || o.disabled || $(event.target).is('.ui-resizable-handle'))
895                         return false;
897                 //Quit if we're not on a valid handle
898                 this.handle = this._getHandle(event);
899                 if (!this.handle)
900                         return false;
902                 return true;
904         },
906         _mouseStart: function(event) {
908                 var o = this.options;
910                 //Create and append the visible helper
911                 this.helper = this._createHelper(event);
913                 //Cache the helper size
914                 this._cacheHelperProportions();
916                 //If ddmanager is used for droppables, set the global draggable
917                 if($.ui.ddmanager)
918                         $.ui.ddmanager.current = this;
920                 /*
921                  * - Position generation -
922                  * This block generates everything position related - it's the core of draggables.
923                  */
925                 //Cache the margins of the original element
926                 this._cacheMargins();
928                 //Store the helper's css position
929                 this.cssPosition = this.helper.css("position");
930                 this.scrollParent = this.helper.scrollParent();
932                 //The element's absolute position on the page minus margins
933                 this.offset = this.positionAbs = this.element.offset();
934                 this.offset = {
935                         top: this.offset.top - this.margins.top,
936                         left: this.offset.left - this.margins.left
937                 };
939                 $.extend(this.offset, {
940                         click: { //Where the click happened, relative to the element
941                                 left: event.pageX - this.offset.left,
942                                 top: event.pageY - this.offset.top
943                         },
944                         parent: this._getParentOffset(),
945                         relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
946                 });
948                 //Generate the original position
949                 this.originalPosition = this.position = this._generatePosition(event);
950                 this.originalPageX = event.pageX;
951                 this.originalPageY = event.pageY;
953                 //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
954                 (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
956                 //Set a containment if given in the options
957                 if(o.containment)
958                         this._setContainment();
960                 //Trigger event + callbacks
961                 if(this._trigger("start", event) === false) {
962                         this._clear();
963                         return false;
964                 }
966                 //Recache the helper size
967                 this._cacheHelperProportions();
969                 //Prepare the droppable offsets
970                 if ($.ui.ddmanager && !o.dropBehaviour)
971                         $.ui.ddmanager.prepareOffsets(this, event);
973                 this.helper.addClass("ui-draggable-dragging");
974                 this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position
975                 return true;
976         },
978         _mouseDrag: function(event, noPropagation) {
980                 //Compute the helpers position
981                 this.position = this._generatePosition(event);
982                 this.positionAbs = this._convertPositionTo("absolute");
984                 //Call plugins and callbacks and use the resulting position if something is returned
985                 if (!noPropagation) {
986                         var ui = this._uiHash();
987                         if(this._trigger('drag', event, ui) === false) {
988                                 this._mouseUp({});
989                                 return false;
990                         }
991                         this.position = ui.position;
992                 }
994                 if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
995                 if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
996                 if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
998                 return false;
999         },
1001         _mouseStop: function(event) {
1003                 //If we are using droppables, inform the manager about the drop
1004                 var dropped = false;
1005                 if ($.ui.ddmanager && !this.options.dropBehaviour)
1006                         dropped = $.ui.ddmanager.drop(this, event);
1008                 //if a drop comes from outside (a sortable)
1009                 if(this.dropped) {
1010                         dropped = this.dropped;
1011                         this.dropped = false;
1012                 }
1013                 
1014                 //if the original element is removed, don't bother to continue
1015                 if(!this.element[0] || !this.element[0].parentNode)
1016                         return false;
1018                 if((this.options.revert == "invalid" && !dropped) || (this.options.revert == "valid" && dropped) || this.options.revert === true || ($.isFunction(this.options.revert) && this.options.revert.call(this.element, dropped))) {
1019                         var self = this;
1020                         $(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() {
1021                                 if(self._trigger("stop", event) !== false) {
1022                                         self._clear();
1023                                 }
1024                         });
1025                 } else {
1026                         if(this._trigger("stop", event) !== false) {
1027                                 this._clear();
1028                         }
1029                 }
1031                 return false;
1032         },
1033         
1034         cancel: function() {
1035                 
1036                 if(this.helper.is(".ui-draggable-dragging")) {
1037                         this._mouseUp({});
1038                 } else {
1039                         this._clear();
1040                 }
1041                 
1042                 return this;
1043                 
1044         },
1046         _getHandle: function(event) {
1048                 var handle = !this.options.handle || !$(this.options.handle, this.element).length ? true : false;
1049                 $(this.options.handle, this.element)
1050                         .find("*")
1051                         .andSelf()
1052                         .each(function() {
1053                                 if(this == event.target) handle = true;
1054                         });
1056                 return handle;
1058         },
1060         _createHelper: function(event) {
1062                 var o = this.options;
1063                 var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper == 'clone' ? this.element.clone() : this.element);
1065                 if(!helper.parents('body').length)
1066                         helper.appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo));
1068                 if(helper[0] != this.element[0] && !(/(fixed|absolute)/).test(helper.css("position")))
1069                         helper.css("position", "absolute");
1071                 return helper;
1073         },
1075         _adjustOffsetFromHelper: function(obj) {
1076                 if (typeof obj == 'string') {
1077                         obj = obj.split(' ');
1078                 }
1079                 if ($.isArray(obj)) {
1080                         obj = {left: +obj[0], top: +obj[1] || 0};
1081                 }
1082                 if ('left' in obj) {
1083                         this.offset.click.left = obj.left + this.margins.left;
1084                 }
1085                 if ('right' in obj) {
1086                         this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
1087                 }
1088                 if ('top' in obj) {
1089                         this.offset.click.top = obj.top + this.margins.top;
1090                 }
1091                 if ('bottom' in obj) {
1092                         this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
1093                 }
1094         },
1096         _getParentOffset: function() {
1098                 //Get the offsetParent and cache its position
1099                 this.offsetParent = this.helper.offsetParent();
1100                 var po = this.offsetParent.offset();
1102                 // This is a special case where we need to modify a offset calculated on start, since the following happened:
1103                 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
1104                 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
1105                 //    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
1106                 if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) {
1107                         po.left += this.scrollParent.scrollLeft();
1108                         po.top += this.scrollParent.scrollTop();
1109                 }
1111                 if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
1112                 || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix
1113                         po = { top: 0, left: 0 };
1115                 return {
1116                         top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
1117                         left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
1118                 };
1120         },
1122         _getRelativeOffset: function() {
1124                 if(this.cssPosition == "relative") {
1125                         var p = this.element.position();
1126                         return {
1127                                 top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
1128                                 left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
1129                         };
1130                 } else {
1131                         return { top: 0, left: 0 };
1132                 }
1134         },
1136         _cacheMargins: function() {
1137                 this.margins = {
1138                         left: (parseInt(this.element.css("marginLeft"),10) || 0),
1139                         top: (parseInt(this.element.css("marginTop"),10) || 0)
1140                 };
1141         },
1143         _cacheHelperProportions: function() {
1144                 this.helperProportions = {
1145                         width: this.helper.outerWidth(),
1146                         height: this.helper.outerHeight()
1147                 };
1148         },
1150         _setContainment: function() {
1152                 var o = this.options;
1153                 if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
1154                 if(o.containment == 'document' || o.containment == 'window') this.containment = [
1155                         0 - this.offset.relative.left - this.offset.parent.left,
1156                         0 - this.offset.relative.top - this.offset.parent.top,
1157                         $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
1158                         ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
1159                 ];
1161                 if(!(/^(document|window|parent)$/).test(o.containment) && o.containment.constructor != Array) {
1162                         var ce = $(o.containment)[0]; if(!ce) return;
1163                         var co = $(o.containment).offset();
1164                         var over = ($(ce).css("overflow") != 'hidden');
1166                         this.containment = [
1167                                 co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
1168                                 co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
1169                                 co.left+(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left,
1170                                 co.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top
1171                         ];
1172                 } else if(o.containment.constructor == Array) {
1173                         this.containment = o.containment;
1174                 }
1176         },
1178         _convertPositionTo: function(d, pos) {
1180                 if(!pos) pos = this.position;
1181                 var mod = d == "absolute" ? 1 : -1;
1182                 var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
1184                 return {
1185                         top: (
1186                                 pos.top                                                                                                                                 // The absolute mouse position
1187                                 + this.offset.relative.top * mod                                                                                // Only for relative positioned nodes: Relative offset from element to offset parent
1188                                 + this.offset.parent.top * mod                                                                                  // The offsetParent's offset without borders (offset + border)
1189                                 - ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
1190                         ),
1191                         left: (
1192                                 pos.left                                                                                                                                // The absolute mouse position
1193                                 + this.offset.relative.left * mod                                                                               // Only for relative positioned nodes: Relative offset from element to offset parent
1194                                 + this.offset.parent.left * mod                                                                                 // The offsetParent's offset without borders (offset + border)
1195                                 - ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
1196                         )
1197                 };
1199         },
1201         _generatePosition: function(event) {
1203                 var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
1204                 var pageX = event.pageX;
1205                 var pageY = event.pageY;
1207                 /*
1208                  * - Position constraining -
1209                  * Constrain the position to a mix of grid, containment.
1210                  */
1212                 if(this.originalPosition) { //If we are not dragging yet, we won't check for options
1214                         if(this.containment) {
1215                                 if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left;
1216                                 if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top;
1217                                 if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left;
1218                                 if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top;
1219                         }
1221                         if(o.grid) {
1222                                 var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
1223                                 pageY = this.containment ? (!(top - this.offset.click.top < this.containment[1] || top - this.offset.click.top > this.containment[3]) ? top : (!(top - this.offset.click.top < this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;
1225                                 var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
1226                                 pageX = this.containment ? (!(left - this.offset.click.left < this.containment[0] || left - this.offset.click.left > this.containment[2]) ? left : (!(left - this.offset.click.left < this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
1227                         }
1229                 }
1231                 return {
1232                         top: (
1233                                 pageY                                                                                                                           // The absolute mouse position
1234                                 - this.offset.click.top                                                                                                 // Click offset (relative to the element)
1235                                 - this.offset.relative.top                                                                                              // Only for relative positioned nodes: Relative offset from element to offset parent
1236                                 - this.offset.parent.top                                                                                                // The offsetParent's offset without borders (offset + border)
1237                                 + ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
1238                         ),
1239                         left: (
1240                                 pageX                                                                                                                           // The absolute mouse position
1241                                 - this.offset.click.left                                                                                                // Click offset (relative to the element)
1242                                 - this.offset.relative.left                                                                                             // Only for relative positioned nodes: Relative offset from element to offset parent
1243                                 - this.offset.parent.left                                                                                               // The offsetParent's offset without borders (offset + border)
1244                                 + ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
1245                         )
1246                 };
1248         },
1250         _clear: function() {
1251                 this.helper.removeClass("ui-draggable-dragging");
1252                 if(this.helper[0] != this.element[0] && !this.cancelHelperRemoval) this.helper.remove();
1253                 //if($.ui.ddmanager) $.ui.ddmanager.current = null;
1254                 this.helper = null;
1255                 this.cancelHelperRemoval = false;
1256         },
1258         // From now on bulk stuff - mainly helpers
1260         _trigger: function(type, event, ui) {
1261                 ui = ui || this._uiHash();
1262                 $.ui.plugin.call(this, type, [event, ui]);
1263                 if(type == "drag") this.positionAbs = this._convertPositionTo("absolute"); //The absolute position has to be recalculated after plugins
1264                 return $.Widget.prototype._trigger.call(this, type, event, ui);
1265         },
1267         plugins: {},
1269         _uiHash: function(event) {
1270                 return {
1271                         helper: this.helper,
1272                         position: this.position,
1273                         originalPosition: this.originalPosition,
1274                         offset: this.positionAbs
1275                 };
1276         }
1280 $.extend($.ui.draggable, {
1281         version: "1.8"
1284 $.ui.plugin.add("draggable", "connectToSortable", {
1285         start: function(event, ui) {
1287                 var inst = $(this).data("draggable"), o = inst.options,
1288                         uiSortable = $.extend({}, ui, { item: inst.element });
1289                 inst.sortables = [];
1290                 $(o.connectToSortable).each(function() {
1291                         var sortable = $.data(this, 'sortable');
1292                         if (sortable && !sortable.options.disabled) {
1293                                 inst.sortables.push({
1294                                         instance: sortable,
1295                                         shouldRevert: sortable.options.revert
1296                                 });
1297                                 sortable._refreshItems();       //Do a one-time refresh at start to refresh the containerCache
1298                                 sortable._trigger("activate", event, uiSortable);
1299                         }
1300                 });
1302         },
1303         stop: function(event, ui) {
1305                 //If we are still over the sortable, we fake the stop event of the sortable, but also remove helper
1306                 var inst = $(this).data("draggable"),
1307                         uiSortable = $.extend({}, ui, { item: inst.element });
1309                 $.each(inst.sortables, function() {
1310                         if(this.instance.isOver) {
1312                                 this.instance.isOver = 0;
1314                                 inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance
1315                                 this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work)
1317                                 //The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: 'valid/invalid'
1318                                 if(this.shouldRevert) this.instance.options.revert = true;
1320                                 //Trigger the stop of the sortable
1321                                 this.instance._mouseStop(event);
1323                                 this.instance.options.helper = this.instance.options._helper;
1325                                 //If the helper has been the original item, restore properties in the sortable
1326                                 if(inst.options.helper == 'original')
1327                                         this.instance.currentItem.css({ top: 'auto', left: 'auto' });
1329                         } else {
1330                                 this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance
1331                                 this.instance._trigger("deactivate", event, uiSortable);
1332                         }
1334                 });
1336         },
1337         drag: function(event, ui) {
1339                 var inst = $(this).data("draggable"), self = this;
1341                 var checkPos = function(o) {
1342                         var dyClick = this.offset.click.top, dxClick = this.offset.click.left;
1343                         var helperTop = this.positionAbs.top, helperLeft = this.positionAbs.left;
1344                         var itemHeight = o.height, itemWidth = o.width;
1345                         var itemTop = o.top, itemLeft = o.left;
1347                         return $.ui.isOver(helperTop + dyClick, helperLeft + dxClick, itemTop, itemLeft, itemHeight, itemWidth);
1348                 };
1350                 $.each(inst.sortables, function(i) {
1351                         
1352                         //Copy over some variables to allow calling the sortable's native _intersectsWith
1353                         this.instance.positionAbs = inst.positionAbs;
1354                         this.instance.helperProportions = inst.helperProportions;
1355                         this.instance.offset.click = inst.offset.click;
1356                         
1357                         if(this.instance._intersectsWith(this.instance.containerCache)) {
1359                                 //If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once
1360                                 if(!this.instance.isOver) {
1362                                         this.instance.isOver = 1;
1363                                         //Now we fake the start of dragging for the sortable instance,
1364                                         //by cloning the list group item, appending it to the sortable and using it as inst.currentItem
1365                                         //We can then fire the start event of the sortable with our passed browser event, and our own helper (so it doesn't create a new one)
1366                                         this.instance.currentItem = $(self).clone().appendTo(this.instance.element).data("sortable-item", true);
1367                                         this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it
1368                                         this.instance.options.helper = function() { return ui.helper[0]; };
1370                                         event.target = this.instance.currentItem[0];
1371                                         this.instance._mouseCapture(event, true);
1372                                         this.instance._mouseStart(event, true, true);
1374                                         //Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes
1375                                         this.instance.offset.click.top = inst.offset.click.top;
1376                                         this.instance.offset.click.left = inst.offset.click.left;
1377                                         this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left;
1378                                         this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top;
1380                                         inst._trigger("toSortable", event);
1381                                         inst.dropped = this.instance.element; //draggable revert needs that
1382                                         //hack so receive/update callbacks work (mostly)
1383                                         inst.currentItem = inst.element;
1384                                         this.instance.fromOutside = inst;
1386                                 }
1388                                 //Provided we did all the previous steps, we can fire the drag event of the sortable on every draggable drag, when it intersects with the sortable
1389                                 if(this.instance.currentItem) this.instance._mouseDrag(event);
1391                         } else {
1393                                 //If it doesn't intersect with the sortable, and it intersected before,
1394                                 //we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval
1395                                 if(this.instance.isOver) {
1397                                         this.instance.isOver = 0;
1398                                         this.instance.cancelHelperRemoval = true;
1399                                         
1400                                         //Prevent reverting on this forced stop
1401                                         this.instance.options.revert = false;
1402                                         
1403                                         // The out event needs to be triggered independently
1404                                         this.instance._trigger('out', event, this.instance._uiHash(this.instance));
1405                                         
1406                                         this.instance._mouseStop(event, true);
1407                                         this.instance.options.helper = this.instance.options._helper;
1409                                         //Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size
1410                                         this.instance.currentItem.remove();
1411                                         if(this.instance.placeholder) this.instance.placeholder.remove();
1413                                         inst._trigger("fromSortable", event);
1414                                         inst.dropped = false; //draggable revert needs that
1415                                 }
1417                         };
1419                 });
1421         }
1424 $.ui.plugin.add("draggable", "cursor", {
1425         start: function(event, ui) {
1426                 var t = $('body'), o = $(this).data('draggable').options;
1427                 if (t.css("cursor")) o._cursor = t.css("cursor");
1428                 t.css("cursor", o.cursor);
1429         },
1430         stop: function(event, ui) {
1431                 var o = $(this).data('draggable').options;
1432                 if (o._cursor) $('body').css("cursor", o._cursor);
1433         }
1436 $.ui.plugin.add("draggable", "iframeFix", {
1437         start: function(event, ui) {
1438                 var o = $(this).data('draggable').options;
1439                 $(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() {
1440                         $('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>')
1441                         .css({
1442                                 width: this.offsetWidth+"px", height: this.offsetHeight+"px",
1443                                 position: "absolute", opacity: "0.001", zIndex: 1000
1444                         })
1445                         .css($(this).offset())
1446                         .appendTo("body");
1447                 });
1448         },
1449         stop: function(event, ui) {
1450                 $("div.ui-draggable-iframeFix").each(function() { this.parentNode.removeChild(this); }); //Remove frame helpers
1451         }
1454 $.ui.plugin.add("draggable", "opacity", {
1455         start: function(event, ui) {
1456                 var t = $(ui.helper), o = $(this).data('draggable').options;
1457                 if(t.css("opacity")) o._opacity = t.css("opacity");
1458                 t.css('opacity', o.opacity);
1459         },
1460         stop: function(event, ui) {
1461                 var o = $(this).data('draggable').options;
1462                 if(o._opacity) $(ui.helper).css('opacity', o._opacity);
1463         }
1466 $.ui.plugin.add("draggable", "scroll", {
1467         start: function(event, ui) {
1468                 var i = $(this).data("draggable");
1469                 if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') i.overflowOffset = i.scrollParent.offset();
1470         },
1471         drag: function(event, ui) {
1473                 var i = $(this).data("draggable"), o = i.options, scrolled = false;
1475                 if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') {
1477                         if(!o.axis || o.axis != 'x') {
1478                                 if((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
1479                                         i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed;
1480                                 else if(event.pageY - i.overflowOffset.top < o.scrollSensitivity)
1481                                         i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed;
1482                         }
1484                         if(!o.axis || o.axis != 'y') {
1485                                 if((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
1486                                         i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed;
1487                                 else if(event.pageX - i.overflowOffset.left < o.scrollSensitivity)
1488                                         i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed;
1489                         }
1491                 } else {
1493                         if(!o.axis || o.axis != 'x') {
1494                                 if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
1495                                         scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
1496                                 else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
1497                                         scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
1498                         }
1500                         if(!o.axis || o.axis != 'y') {
1501                                 if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
1502                                         scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
1503                                 else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
1504                                         scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
1505                         }
1507                 }
1509                 if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
1510                         $.ui.ddmanager.prepareOffsets(i, event);
1512         }
1515 $.ui.plugin.add("draggable", "snap", {
1516         start: function(event, ui) {
1518                 var i = $(this).data("draggable"), o = i.options;
1519                 i.snapElements = [];
1521                 $(o.snap.constructor != String ? ( o.snap.items || ':data(draggable)' ) : o.snap).each(function() {
1522                         var $t = $(this); var $o = $t.offset();
1523                         if(this != i.element[0]) i.snapElements.push({
1524                                 item: this,
1525                                 width: $t.outerWidth(), height: $t.outerHeight(),
1526                                 top: $o.top, left: $o.left
1527                         });
1528                 });
1530         },
1531         drag: function(event, ui) {
1533                 var inst = $(this).data("draggable"), o = inst.options;
1534                 var d = o.snapTolerance;
1536                 var x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
1537                         y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
1539                 for (var i = inst.snapElements.length - 1; i >= 0; i--){
1541                         var l = inst.snapElements[i].left, r = l + inst.snapElements[i].width,
1542                                 t = inst.snapElements[i].top, b = t + inst.snapElements[i].height;
1544                         //Yes, I know, this is insane ;)
1545                         if(!((l-d < x1 && x1 < r+d && t-d < y1 && y1 < b+d) || (l-d < x1 && x1 < r+d && t-d < y2 && y2 < b+d) || (l-d < x2 && x2 < r+d && t-d < y1 && y1 < b+d) || (l-d < x2 && x2 < r+d && t-d < y2 && y2 < b+d))) {
1546                                 if(inst.snapElements[i].snapping) (inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
1547                                 inst.snapElements[i].snapping = false;
1548                                 continue;
1549                         }
1551                         if(o.snapMode != 'inner') {
1552                                 var ts = Math.abs(t - y2) <= d;
1553                                 var bs = Math.abs(b - y1) <= d;
1554                                 var ls = Math.abs(l - x2) <= d;
1555                                 var rs = Math.abs(r - x1) <= d;
1556                                 if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
1557                                 if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top;
1558                                 if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left;
1559                                 if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left;
1560                         }
1562                         var first = (ts || bs || ls || rs);
1564                         if(o.snapMode != 'outer') {
1565                                 var ts = Math.abs(t - y1) <= d;
1566                                 var bs = Math.abs(b - y2) <= d;
1567                                 var ls = Math.abs(l - x1) <= d;
1568                                 var rs = Math.abs(r - x2) <= d;
1569                                 if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top;
1570                                 if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
1571                                 if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left;
1572                                 if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left;
1573                         }
1575                         if(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first))
1576                                 (inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
1577                         inst.snapElements[i].snapping = (ts || bs || ls || rs || first);
1579                 };
1581         }
1584 $.ui.plugin.add("draggable", "stack", {
1585         start: function(event, ui) {
1587                 var o = $(this).data("draggable").options;
1589                 var group = $.makeArray($(o.stack)).sort(function(a,b) {
1590                         return (parseInt($(a).css("zIndex"),10) || 0) - (parseInt($(b).css("zIndex"),10) || 0);
1591                 });
1592                 if (!group.length) { return; }
1593                 
1594                 var min = parseInt(group[0].style.zIndex) || 0;
1595                 $(group).each(function(i) {
1596                         this.style.zIndex = min + i;
1597                 });
1599                 this[0].style.zIndex = min + group.length;
1601         }
1604 $.ui.plugin.add("draggable", "zIndex", {
1605         start: function(event, ui) {
1606                 var t = $(ui.helper), o = $(this).data("draggable").options;
1607                 if(t.css("zIndex")) o._zIndex = t.css("zIndex");
1608                 t.css('zIndex', o.zIndex);
1609         },
1610         stop: function(event, ui) {
1611                 var o = $(this).data("draggable").options;
1612                 if(o._zIndex) $(ui.helper).css('zIndex', o._zIndex);
1613         }
1616 })(jQuery);
1618  * jQuery UI Droppable 1.8
1620  * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
1621  * Dual licensed under the MIT (MIT-LICENSE.txt)
1622  * and GPL (GPL-LICENSE.txt) licenses.
1624  * http://docs.jquery.com/UI/Droppables
1626  * Depends:
1627  *      jquery.ui.core.js
1628  *      jquery.ui.widget.js
1629  *      jquery.ui.mouse.js
1630  *      jquery.ui.draggable.js
1631  */
1632 (function($) {
1634 $.widget("ui.droppable", {
1635         widgetEventPrefix: "drop",
1636         options: {
1637                 accept: '*',
1638                 activeClass: false,
1639                 addClasses: true,
1640                 greedy: false,
1641                 hoverClass: false,
1642                 scope: 'default',
1643                 tolerance: 'intersect'
1644         },
1645         _create: function() {
1647                 var o = this.options, accept = o.accept;
1648                 this.isover = 0; this.isout = 1;
1650                 this.accept = $.isFunction(accept) ? accept : function(d) {
1651                         return d.is(accept);
1652                 };
1654                 //Store the droppable's proportions
1655                 this.proportions = { width: this.element[0].offsetWidth, height: this.element[0].offsetHeight };
1657                 // Add the reference and positions to the manager
1658                 $.ui.ddmanager.droppables[o.scope] = $.ui.ddmanager.droppables[o.scope] || [];
1659                 $.ui.ddmanager.droppables[o.scope].push(this);
1661                 (o.addClasses && this.element.addClass("ui-droppable"));
1663         },
1665         destroy: function() {
1666                 var drop = $.ui.ddmanager.droppables[this.options.scope];
1667                 for ( var i = 0; i < drop.length; i++ )
1668                         if ( drop[i] == this )
1669                                 drop.splice(i, 1);
1671                 this.element
1672                         .removeClass("ui-droppable ui-droppable-disabled")
1673                         .removeData("droppable")
1674                         .unbind(".droppable");
1676                 return this;
1677         },
1679         _setOption: function(key, value) {
1681                 if(key == 'accept') {
1682                         this.accept = $.isFunction(value) ? value : function(d) {
1683                                 return d.is(value);
1684                         };
1685                 }
1686                 $.Widget.prototype._setOption.apply(this, arguments);
1687         },
1689         _activate: function(event) {
1690                 var draggable = $.ui.ddmanager.current;
1691                 if(this.options.activeClass) this.element.addClass(this.options.activeClass);
1692                 (draggable && this._trigger('activate', event, this.ui(draggable)));
1693         },
1695         _deactivate: function(event) {
1696                 var draggable = $.ui.ddmanager.current;
1697                 if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
1698                 (draggable && this._trigger('deactivate', event, this.ui(draggable)));
1699         },
1701         _over: function(event) {
1703                 var draggable = $.ui.ddmanager.current;
1704                 if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
1706                 if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
1707                         if(this.options.hoverClass) this.element.addClass(this.options.hoverClass);
1708                         this._trigger('over', event, this.ui(draggable));
1709                 }
1711         },
1713         _out: function(event) {
1715                 var draggable = $.ui.ddmanager.current;
1716                 if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
1718                 if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
1719                         if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
1720                         this._trigger('out', event, this.ui(draggable));
1721                 }
1723         },
1725         _drop: function(event,custom) {
1727                 var draggable = custom || $.ui.ddmanager.current;
1728                 if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return false; // Bail if draggable and droppable are same element
1730                 var childrenIntersection = false;
1731                 this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function() {
1732                         var inst = $.data(this, 'droppable');
1733                         if(
1734                                 inst.options.greedy
1735                                 && !inst.options.disabled
1736                                 && inst.options.scope == draggable.options.scope
1737                                 && inst.accept.call(inst.element[0], (draggable.currentItem || draggable.element))
1738                                 && $.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance)
1739                         ) { childrenIntersection = true; return false; }
1740                 });
1741                 if(childrenIntersection) return false;
1743                 if(this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
1744                         if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
1745                         if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
1746                         this._trigger('drop', event, this.ui(draggable));
1747                         return this.element;
1748                 }
1750                 return false;
1752         },
1754         ui: function(c) {
1755                 return {
1756                         draggable: (c.currentItem || c.element),
1757                         helper: c.helper,
1758                         position: c.position,
1759                         offset: c.positionAbs
1760                 };
1761         }
1765 $.extend($.ui.droppable, {
1766         version: "1.8"
1769 $.ui.intersect = function(draggable, droppable, toleranceMode) {
1771         if (!droppable.offset) return false;
1773         var x1 = (draggable.positionAbs || draggable.position.absolute).left, x2 = x1 + draggable.helperProportions.width,
1774                 y1 = (draggable.positionAbs || draggable.position.absolute).top, y2 = y1 + draggable.helperProportions.height;
1775         var l = droppable.offset.left, r = l + droppable.proportions.width,
1776                 t = droppable.offset.top, b = t + droppable.proportions.height;
1778         switch (toleranceMode) {
1779                 case 'fit':
1780                         return (l < x1 && x2 < r
1781                                 && t < y1 && y2 < b);
1782                         break;
1783                 case 'intersect':
1784                         return (l < x1 + (draggable.helperProportions.width / 2) // Right Half
1785                                 && x2 - (draggable.helperProportions.width / 2) < r // Left Half
1786                                 && t < y1 + (draggable.helperProportions.height / 2) // Bottom Half
1787                                 && y2 - (draggable.helperProportions.height / 2) < b ); // Top Half
1788                         break;
1789                 case 'pointer':
1790                         var draggableLeft = ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left),
1791                                 draggableTop = ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top),
1792                                 isOver = $.ui.isOver(draggableTop, draggableLeft, t, l, droppable.proportions.height, droppable.proportions.width);
1793                         return isOver;
1794                         break;
1795                 case 'touch':
1796                         return (
1797                                         (y1 >= t && y1 <= b) || // Top edge touching
1798                                         (y2 >= t && y2 <= b) || // Bottom edge touching
1799                                         (y1 < t && y2 > b)              // Surrounded vertically
1800                                 ) && (
1801                                         (x1 >= l && x1 <= r) || // Left edge touching
1802                                         (x2 >= l && x2 <= r) || // Right edge touching
1803                                         (x1 < l && x2 > r)              // Surrounded horizontally
1804                                 );
1805                         break;
1806                 default:
1807                         return false;
1808                         break;
1809                 }
1814         This manager tracks offsets of draggables and droppables
1816 $.ui.ddmanager = {
1817         current: null,
1818         droppables: { 'default': [] },
1819         prepareOffsets: function(t, event) {
1821                 var m = $.ui.ddmanager.droppables[t.options.scope] || [];
1822                 var type = event ? event.type : null; // workaround for #2317
1823                 var list = (t.currentItem || t.element).find(":data(droppable)").andSelf();
1825                 droppablesLoop: for (var i = 0; i < m.length; i++) {
1827                         if(m[i].options.disabled || (t && !m[i].accept.call(m[i].element[0],(t.currentItem || t.element)))) continue;   //No disabled and non-accepted
1828                         for (var j=0; j < list.length; j++) { if(list[j] == m[i].element[0]) { m[i].proportions.height = 0; continue droppablesLoop; } }; //Filter out elements in the current dragged item
1829                         m[i].visible = m[i].element.css("display") != "none"; if(!m[i].visible) continue;                                                                       //If the element is not visible, continue
1831                         m[i].offset = m[i].element.offset();
1832                         m[i].proportions = { width: m[i].element[0].offsetWidth, height: m[i].element[0].offsetHeight };
1834                         if(type == "mousedown") m[i]._activate.call(m[i], event); //Activate the droppable if used directly from draggables
1836                 }
1838         },
1839         drop: function(draggable, event) {
1841                 var dropped = false;
1842                 $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
1844                         if(!this.options) return;
1845                         if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance))
1846                                 dropped = dropped || this._drop.call(this, event);
1848                         if (!this.options.disabled && this.visible && this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
1849                                 this.isout = 1; this.isover = 0;
1850                                 this._deactivate.call(this, event);
1851                         }
1853                 });
1854                 return dropped;
1856         },
1857         drag: function(draggable, event) {
1859                 //If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse.
1860                 if(draggable.options.refreshPositions) $.ui.ddmanager.prepareOffsets(draggable, event);
1862                 //Run through all droppables and check their positions based on specific tolerance options
1863                 $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
1865                         if(this.options.disabled || this.greedyChild || !this.visible) return;
1866                         var intersects = $.ui.intersect(draggable, this, this.options.tolerance);
1868                         var c = !intersects && this.isover == 1 ? 'isout' : (intersects && this.isover == 0 ? 'isover' : null);
1869                         if(!c) return;
1871                         var parentInstance;
1872                         if (this.options.greedy) {
1873                                 var parent = this.element.parents(':data(droppable):eq(0)');
1874                                 if (parent.length) {
1875                                         parentInstance = $.data(parent[0], 'droppable');
1876                                         parentInstance.greedyChild = (c == 'isover' ? 1 : 0);
1877                                 }
1878                         }
1880                         // we just moved into a greedy child
1881                         if (parentInstance && c == 'isover') {
1882                                 parentInstance['isover'] = 0;
1883                                 parentInstance['isout'] = 1;
1884                                 parentInstance._out.call(parentInstance, event);
1885                         }
1887                         this[c] = 1; this[c == 'isout' ? 'isover' : 'isout'] = 0;
1888                         this[c == "isover" ? "_over" : "_out"].call(this, event);
1890                         // we just moved out of a greedy child
1891                         if (parentInstance && c == 'isout') {
1892                                 parentInstance['isout'] = 0;
1893                                 parentInstance['isover'] = 1;
1894                                 parentInstance._over.call(parentInstance, event);
1895                         }
1896                 });
1898         }
1901 })(jQuery);
1903  * jQuery UI Resizable 1.8
1905  * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
1906  * Dual licensed under the MIT (MIT-LICENSE.txt)
1907  * and GPL (GPL-LICENSE.txt) licenses.
1909  * http://docs.jquery.com/UI/Resizables
1911  * Depends:
1912  *      jquery.ui.core.js
1913  *      jquery.ui.mouse.js
1914  *      jquery.ui.widget.js
1915  */
1916 (function($) {
1918 $.widget("ui.resizable", $.ui.mouse, {
1919         widgetEventPrefix: "resize",
1920         options: {
1921                 alsoResize: false,
1922                 animate: false,
1923                 animateDuration: "slow",
1924                 animateEasing: "swing",
1925                 aspectRatio: false,
1926                 autoHide: false,
1927                 containment: false,
1928                 ghost: false,
1929                 grid: false,
1930                 handles: "e,s,se",
1931                 helper: false,
1932                 maxHeight: null,
1933                 maxWidth: null,
1934                 minHeight: 10,
1935                 minWidth: 10,
1936                 zIndex: 1000
1937         },
1938         _create: function() {
1940                 var self = this, o = this.options;
1941                 this.element.addClass("ui-resizable");
1943                 $.extend(this, {
1944                         _aspectRatio: !!(o.aspectRatio),
1945                         aspectRatio: o.aspectRatio,
1946                         originalElement: this.element,
1947                         _proportionallyResizeElements: [],
1948                         _helper: o.helper || o.ghost || o.animate ? o.helper || 'ui-resizable-helper' : null
1949                 });
1951                 //Wrap the element if it cannot hold child nodes
1952                 if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) {
1954                         //Opera fix for relative positioning
1955                         if (/relative/.test(this.element.css('position')) && $.browser.opera)
1956                                 this.element.css({ position: 'relative', top: 'auto', left: 'auto' });
1958                         //Create a wrapper element and set the wrapper to the new current internal element
1959                         this.element.wrap(
1960                                 $('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({
1961                                         position: this.element.css('position'),
1962                                         width: this.element.outerWidth(),
1963                                         height: this.element.outerHeight(),
1964                                         top: this.element.css('top'),
1965                                         left: this.element.css('left')
1966                                 })
1967                         );
1969                         //Overwrite the original this.element
1970                         this.element = this.element.parent().data(
1971                                 "resizable", this.element.data('resizable')
1972                         );
1974                         this.elementIsWrapper = true;
1976                         //Move margins to the wrapper
1977                         this.element.css({ marginLeft: this.originalElement.css("marginLeft"), marginTop: this.originalElement.css("marginTop"), marginRight: this.originalElement.css("marginRight"), marginBottom: this.originalElement.css("marginBottom") });
1978                         this.originalElement.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0});
1980                         //Prevent Safari textarea resize
1981                         this.originalResizeStyle = this.originalElement.css('resize');
1982                         this.originalElement.css('resize', 'none');
1984                         //Push the actual element to our proportionallyResize internal array
1985                         this._proportionallyResizeElements.push(this.originalElement.css({ position: 'static', zoom: 1, display: 'block' }));
1987                         // avoid IE jump (hard set the margin)
1988                         this.originalElement.css({ margin: this.originalElement.css('margin') });
1990                         // fix handlers offset
1991                         this._proportionallyResize();
1993                 }
1995                 this.handles = o.handles || (!$('.ui-resizable-handle', this.element).length ? "e,s,se" : { n: '.ui-resizable-n', e: '.ui-resizable-e', s: '.ui-resizable-s', w: '.ui-resizable-w', se: '.ui-resizable-se', sw: '.ui-resizable-sw', ne: '.ui-resizable-ne', nw: '.ui-resizable-nw' });
1996                 if(this.handles.constructor == String) {
1998                         if(this.handles == 'all') this.handles = 'n,e,s,w,se,sw,ne,nw';
1999                         var n = this.handles.split(","); this.handles = {};
2001                         for(var i = 0; i < n.length; i++) {
2003                                 var handle = $.trim(n[i]), hname = 'ui-resizable-'+handle;
2004                                 var axis = $('<div class="ui-resizable-handle ' + hname + '"></div>');
2006                                 // increase zIndex of sw, se, ne, nw axis
2007                                 //TODO : this modifies original option
2008                                 if(/sw|se|ne|nw/.test(handle)) axis.css({ zIndex: ++o.zIndex });
2010                                 //TODO : What's going on here?
2011                                 if ('se' == handle) {
2012                                         axis.addClass('ui-icon ui-icon-gripsmall-diagonal-se');
2013                                 };
2015                                 //Insert into internal handles object and append to element
2016                                 this.handles[handle] = '.ui-resizable-'+handle;
2017                                 this.element.append(axis);
2018                         }
2020                 }
2022                 this._renderAxis = function(target) {
2024                         target = target || this.element;
2026                         for(var i in this.handles) {
2028                                 if(this.handles[i].constructor == String)
2029                                         this.handles[i] = $(this.handles[i], this.element).show();
2031                                 //Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls)
2032                                 if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) {
2034                                         var axis = $(this.handles[i], this.element), padWrapper = 0;
2036                                         //Checking the correct pad and border
2037                                         padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth();
2039                                         //The padding type i have to apply...
2040                                         var padPos = [ 'padding',
2041                                                 /ne|nw|n/.test(i) ? 'Top' :
2042                                                 /se|sw|s/.test(i) ? 'Bottom' :
2043                                                 /^e$/.test(i) ? 'Right' : 'Left' ].join("");
2045                                         target.css(padPos, padWrapper);
2047                                         this._proportionallyResize();
2049                                 }
2051                                 //TODO: What's that good for? There's not anything to be executed left
2052                                 if(!$(this.handles[i]).length)
2053                                         continue;
2055                         }
2056                 };
2058                 //TODO: make renderAxis a prototype function
2059                 this._renderAxis(this.element);
2061                 this._handles = $('.ui-resizable-handle', this.element)
2062                         .disableSelection();
2064                 //Matching axis name
2065                 this._handles.mouseover(function() {
2066                         if (!self.resizing) {
2067                                 if (this.className)
2068                                         var axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);
2069                                 //Axis, default = se
2070                                 self.axis = axis && axis[1] ? axis[1] : 'se';
2071                         }
2072                 });
2074                 //If we want to auto hide the elements
2075                 if (o.autoHide) {
2076                         this._handles.hide();
2077                         $(this.element)
2078                                 .addClass("ui-resizable-autohide")
2079                                 .hover(function() {
2080                                         $(this).removeClass("ui-resizable-autohide");
2081                                         self._handles.show();
2082                                 },
2083                                 function(){
2084                                         if (!self.resizing) {
2085                                                 $(this).addClass("ui-resizable-autohide");
2086                                                 self._handles.hide();
2087                                         }
2088                                 });
2089                 }
2091                 //Initialize the mouse interaction
2092                 this._mouseInit();
2094         },
2096         destroy: function() {
2098                 this._mouseDestroy();
2100                 var _destroy = function(exp) {
2101                         $(exp).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing")
2102                                 .removeData("resizable").unbind(".resizable").find('.ui-resizable-handle').remove();
2103                 };
2105                 //TODO: Unwrap at same DOM position
2106                 if (this.elementIsWrapper) {
2107                         _destroy(this.element);
2108                         var wrapper = this.element;
2109                         wrapper.after(
2110                                 this.originalElement.css({
2111                                         position: wrapper.css('position'),
2112                                         width: wrapper.outerWidth(),
2113                                         height: wrapper.outerHeight(),
2114                                         top: wrapper.css('top'),
2115                                         left: wrapper.css('left')
2116                                 })
2117                         ).remove();
2118                 }
2120                 this.originalElement.css('resize', this.originalResizeStyle);
2121                 _destroy(this.originalElement);
2123                 return this;
2124         },
2126         _mouseCapture: function(event) {
2127                 var handle = false;
2128                 for (var i in this.handles) {
2129                         if ($(this.handles[i])[0] == event.target) {
2130                                 handle = true;
2131                         }
2132                 }
2134                 return !this.options.disabled && handle;
2135         },
2137         _mouseStart: function(event) {
2139                 var o = this.options, iniPos = this.element.position(), el = this.element;
2141                 this.resizing = true;
2142                 this.documentScroll = { top: $(document).scrollTop(), left: $(document).scrollLeft() };
2144                 // bugfix for http://dev.jquery.com/ticket/1749
2145                 if (el.is('.ui-draggable') || (/absolute/).test(el.css('position'))) {
2146                         el.css({ position: 'absolute', top: iniPos.top, left: iniPos.left });
2147                 }
2149                 //Opera fixing relative position
2150                 if ($.browser.opera && (/relative/).test(el.css('position')))
2151                         el.css({ position: 'relative', top: 'auto', left: 'auto' });
2153                 this._renderProxy();
2155                 var curleft = num(this.helper.css('left')), curtop = num(this.helper.css('top'));
2157                 if (o.containment) {
2158                         curleft += $(o.containment).scrollLeft() || 0;
2159                         curtop += $(o.containment).scrollTop() || 0;
2160                 }
2162                 //Store needed variables
2163                 this.offset = this.helper.offset();
2164                 this.position = { left: curleft, top: curtop };
2165                 this.size = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
2166                 this.originalSize = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
2167                 this.originalPosition = { left: curleft, top: curtop };
2168                 this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() };
2169                 this.originalMousePosition = { left: event.pageX, top: event.pageY };
2171                 //Aspect Ratio
2172                 this.aspectRatio = (typeof o.aspectRatio == 'number') ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1);
2174             var cursor = $('.ui-resizable-' + this.axis).css('cursor');
2175             $('body').css('cursor', cursor == 'auto' ? this.axis + '-resize' : cursor);
2177                 el.addClass("ui-resizable-resizing");
2178                 this._propagate("start", event);
2179                 return true;
2180         },
2182         _mouseDrag: function(event) {
2184                 //Increase performance, avoid regex
2185                 var el = this.helper, o = this.options, props = {},
2186                         self = this, smp = this.originalMousePosition, a = this.axis;
2188                 var dx = (event.pageX-smp.left)||0, dy = (event.pageY-smp.top)||0;
2189                 var trigger = this._change[a];
2190                 if (!trigger) return false;
2192                 // Calculate the attrs that will be change
2193                 var data = trigger.apply(this, [event, dx, dy]), ie6 = $.browser.msie && $.browser.version < 7, csdif = this.sizeDiff;
2195                 if (this._aspectRatio || event.shiftKey)
2196                         data = this._updateRatio(data, event);
2198                 data = this._respectSize(data, event);
2200                 // plugins callbacks need to be called first
2201                 this._propagate("resize", event);
2203                 el.css({
2204                         top: this.position.top + "px", left: this.position.left + "px",
2205                         width: this.size.width + "px", height: this.size.height + "px"
2206                 });
2208                 if (!this._helper && this._proportionallyResizeElements.length)
2209                         this._proportionallyResize();
2211                 this._updateCache(data);
2213                 // calling the user callback at the end
2214                 this._trigger('resize', event, this.ui());
2216                 return false;
2217         },
2219         _mouseStop: function(event) {
2221                 this.resizing = false;
2222                 var o = this.options, self = this;
2224                 if(this._helper) {
2225                         var pr = this._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
2226                                                 soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
2227                                                         soffsetw = ista ? 0 : self.sizeDiff.width;
2229                         var s = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },
2230                                 left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
2231                                 top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
2233                         if (!o.animate)
2234                                 this.element.css($.extend(s, { top: top, left: left }));
2236                         self.helper.height(self.size.height);
2237                         self.helper.width(self.size.width);
2239                         if (this._helper && !o.animate) this._proportionallyResize();
2240                 }
2242                 $('body').css('cursor', 'auto');
2244                 this.element.removeClass("ui-resizable-resizing");
2246                 this._propagate("stop", event);
2248                 if (this._helper) this.helper.remove();
2249                 return false;
2251         },
2253         _updateCache: function(data) {
2254                 var o = this.options;
2255                 this.offset = this.helper.offset();
2256                 if (isNumber(data.left)) this.position.left = data.left;
2257                 if (isNumber(data.top)) this.position.top = data.top;
2258                 if (isNumber(data.height)) this.size.height = data.height;
2259                 if (isNumber(data.width)) this.size.width = data.width;
2260         },
2262         _updateRatio: function(data, event) {
2264                 var o = this.options, cpos = this.position, csize = this.size, a = this.axis;
2266                 if (data.height) data.width = (csize.height * this.aspectRatio);
2267                 else if (data.width) data.height = (csize.width / this.aspectRatio);
2269                 if (a == 'sw') {
2270                         data.left = cpos.left + (csize.width - data.width);
2271                         data.top = null;
2272                 }
2273                 if (a == 'nw') {
2274                         data.top = cpos.top + (csize.height - data.height);
2275                         data.left = cpos.left + (csize.width - data.width);
2276                 }
2278                 return data;
2279         },
2281         _respectSize: function(data, event) {
2283                 var el = this.helper, o = this.options, pRatio = this._aspectRatio || event.shiftKey, a = this.axis,
2284                                 ismaxw = isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh = isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height),
2285                                         isminw = isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh = isNumber(data.height) && o.minHeight && (o.minHeight > data.height);
2287                 if (isminw) data.width = o.minWidth;
2288                 if (isminh) data.height = o.minHeight;
2289                 if (ismaxw) data.width = o.maxWidth;
2290                 if (ismaxh) data.height = o.maxHeight;
2292                 var dw = this.originalPosition.left + this.originalSize.width, dh = this.position.top + this.size.height;
2293                 var cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a);
2295                 if (isminw && cw) data.left = dw - o.minWidth;
2296                 if (ismaxw && cw) data.left = dw - o.maxWidth;
2297                 if (isminh && ch)       data.top = dh - o.minHeight;
2298                 if (ismaxh && ch)       data.top = dh - o.maxHeight;
2300                 // fixing jump error on top/left - bug #2330
2301                 var isNotwh = !data.width && !data.height;
2302                 if (isNotwh && !data.left && data.top) data.top = null;
2303                 else if (isNotwh && !data.top && data.left) data.left = null;
2305                 return data;
2306         },
2308         _proportionallyResize: function() {
2310                 var o = this.options;
2311                 if (!this._proportionallyResizeElements.length) return;
2312                 var element = this.helper || this.element;
2314                 for (var i=0; i < this._proportionallyResizeElements.length; i++) {
2316                         var prel = this._proportionallyResizeElements[i];
2318                         if (!this.borderDif) {
2319                                 var b = [prel.css('borderTopWidth'), prel.css('borderRightWidth'), prel.css('borderBottomWidth'), prel.css('borderLeftWidth')],
2320                                         p = [prel.css('paddingTop'), prel.css('paddingRight'), prel.css('paddingBottom'), prel.css('paddingLeft')];
2322                                 this.borderDif = $.map(b, function(v, i) {
2323                                         var border = parseInt(v,10)||0, padding = parseInt(p[i],10)||0;
2324                                         return border + padding;
2325                                 });
2326                         }
2328                         if ($.browser.msie && !(!($(element).is(':hidden') || $(element).parents(':hidden').length)))
2329                                 continue;
2331                         prel.css({
2332                                 height: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0,
2333                                 width: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0
2334                         });
2336                 };
2338         },
2340         _renderProxy: function() {
2342                 var el = this.element, o = this.options;
2343                 this.elementOffset = el.offset();
2345                 if(this._helper) {
2347                         this.helper = this.helper || $('<div style="overflow:hidden;"></div>');
2349                         // fix ie6 offset TODO: This seems broken
2350                         var ie6 = $.browser.msie && $.browser.version < 7, ie6offset = (ie6 ? 1 : 0),
2351                         pxyoffset = ( ie6 ? 2 : -1 );
2353                         this.helper.addClass(this._helper).css({
2354                                 width: this.element.outerWidth() + pxyoffset,
2355                                 height: this.element.outerHeight() + pxyoffset,
2356                                 position: 'absolute',
2357                                 left: this.elementOffset.left - ie6offset +'px',
2358                                 top: this.elementOffset.top - ie6offset +'px',
2359                                 zIndex: ++o.zIndex //TODO: Don't modify option
2360                         });
2362                         this.helper
2363                                 .appendTo("body")
2364                                 .disableSelection();
2366                 } else {
2367                         this.helper = this.element;
2368                 }
2370         },
2372         _change: {
2373                 e: function(event, dx, dy) {
2374                         return { width: this.originalSize.width + dx };
2375                 },
2376                 w: function(event, dx, dy) {
2377                         var o = this.options, cs = this.originalSize, sp = this.originalPosition;
2378                         return { left: sp.left + dx, width: cs.width - dx };
2379                 },
2380                 n: function(event, dx, dy) {
2381                         var o = this.options, cs = this.originalSize, sp = this.originalPosition;
2382                         return { top: sp.top + dy, height: cs.height - dy };
2383                 },
2384                 s: function(event, dx, dy) {
2385                         return { height: this.originalSize.height + dy };
2386                 },
2387                 se: function(event, dx, dy) {
2388                         return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
2389                 },
2390                 sw: function(event, dx, dy) {
2391                         return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
2392                 },
2393                 ne: function(event, dx, dy) {
2394                         return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
2395                 },
2396                 nw: function(event, dx, dy) {
2397                         return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
2398                 }
2399         },
2401         _propagate: function(n, event) {
2402                 $.ui.plugin.call(this, n, [event, this.ui()]);
2403                 (n != "resize" && this._trigger(n, event, this.ui()));
2404         },
2406         plugins: {},
2408         ui: function() {
2409                 return {
2410                         originalElement: this.originalElement,
2411                         element: this.element,
2412                         helper: this.helper,
2413                         position: this.position,
2414                         size: this.size,
2415                         originalSize: this.originalSize,
2416                         originalPosition: this.originalPosition
2417                 };
2418         }
2422 $.extend($.ui.resizable, {
2423         version: "1.8"
2427  * Resizable Extensions
2428  */
2430 $.ui.plugin.add("resizable", "alsoResize", {
2432         start: function(event, ui) {
2434                 var self = $(this).data("resizable"), o = self.options;
2436                 var _store = function(exp) {
2437                         $(exp).each(function() {
2438                                 $(this).data("resizable-alsoresize", {
2439                                         width: parseInt($(this).width(), 10), height: parseInt($(this).height(), 10),
2440                                         left: parseInt($(this).css('left'), 10), top: parseInt($(this).css('top'), 10)
2441                                 });
2442                         });
2443                 };
2445                 if (typeof(o.alsoResize) == 'object' && !o.alsoResize.parentNode) {
2446                         if (o.alsoResize.length) { o.alsoResize = o.alsoResize[0];      _store(o.alsoResize); }
2447                         else { $.each(o.alsoResize, function(exp, c) { _store(exp); }); }
2448                 }else{
2449                         _store(o.alsoResize);
2450                 }
2451         },
2453         resize: function(event, ui){
2454                 var self = $(this).data("resizable"), o = self.options, os = self.originalSize, op = self.originalPosition;
2456                 var delta = {
2457                         height: (self.size.height - os.height) || 0, width: (self.size.width - os.width) || 0,
2458                         top: (self.position.top - op.top) || 0, left: (self.position.left - op.left) || 0
2459                 },
2461                 _alsoResize = function(exp, c) {
2462                         $(exp).each(function() {
2463                                 var el = $(this), start = $(this).data("resizable-alsoresize"), style = {}, css = c && c.length ? c : ['width', 'height', 'top', 'left'];
2465                                 $.each(css || ['width', 'height', 'top', 'left'], function(i, prop) {
2466                                         var sum = (start[prop]||0) + (delta[prop]||0);
2467                                         if (sum && sum >= 0)
2468                                                 style[prop] = sum || null;
2469                                 });
2471                                 //Opera fixing relative position
2472                                 if (/relative/.test(el.css('position')) && $.browser.opera) {
2473                                         self._revertToRelativePosition = true;
2474                                         el.css({ position: 'absolute', top: 'auto', left: 'auto' });
2475                                 }
2477                                 el.css(style);
2478                         });
2479                 };
2481                 if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) {
2482                         $.each(o.alsoResize, function(exp, c) { _alsoResize(exp, c); });
2483                 }else{
2484                         _alsoResize(o.alsoResize);
2485                 }
2486         },
2488         stop: function(event, ui){
2489                 var self = $(this).data("resizable");
2491                 //Opera fixing relative position
2492                 if (self._revertToRelativePosition && $.browser.opera) {
2493                         self._revertToRelativePosition = false;
2494                         el.css({ position: 'relative' });
2495                 }
2497                 $(this).removeData("resizable-alsoresize-start");
2498         }
2501 $.ui.plugin.add("resizable", "animate", {
2503         stop: function(event, ui) {
2504                 var self = $(this).data("resizable"), o = self.options;
2506                 var pr = self._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
2507                                         soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
2508                                                 soffsetw = ista ? 0 : self.sizeDiff.width;
2510                 var style = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },
2511                                         left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
2512                                                 top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
2514                 self.element.animate(
2515                         $.extend(style, top && left ? { top: top, left: left } : {}), {
2516                                 duration: o.animateDuration,
2517                                 easing: o.animateEasing,
2518                                 step: function() {
2520                                         var data = {
2521                                                 width: parseInt(self.element.css('width'), 10),
2522                                                 height: parseInt(self.element.css('height'), 10),
2523                                                 top: parseInt(self.element.css('top'), 10),
2524                                                 left: parseInt(self.element.css('left'), 10)
2525                                         };
2527                                         if (pr && pr.length) $(pr[0]).css({ width: data.width, height: data.height });
2529                                         // propagating resize, and updating values for each animation step
2530                                         self._updateCache(data);
2531                                         self._propagate("resize", event);
2533                                 }
2534                         }
2535                 );
2536         }
2540 $.ui.plugin.add("resizable", "containment", {
2542         start: function(event, ui) {
2543                 var self = $(this).data("resizable"), o = self.options, el = self.element;
2544                 var oc = o.containment, ce = (oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc;
2545                 if (!ce) return;
2547                 self.containerElement = $(ce);
2549                 if (/document/.test(oc) || oc == document) {
2550                         self.containerOffset = { left: 0, top: 0 };
2551                         self.containerPosition = { left: 0, top: 0 };
2553                         self.parentData = {
2554                                 element: $(document), left: 0, top: 0,
2555                                 width: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight
2556                         };
2557                 }
2559                 // i'm a node, so compute top, left, right, bottom
2560                 else {
2561                         var element = $(ce), p = [];
2562                         $([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) { p[i] = num(element.css("padding" + name)); });
2564                         self.containerOffset = element.offset();
2565                         self.containerPosition = element.position();
2566                         self.containerSize = { height: (element.innerHeight() - p[3]), width: (element.innerWidth() - p[1]) };
2568                         var co = self.containerOffset, ch = self.containerSize.height,  cw = self.containerSize.width,
2569                                                 width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw ), height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch);
2571                         self.parentData = {
2572                                 element: ce, left: co.left, top: co.top, width: width, height: height
2573                         };
2574                 }
2575         },
2577         resize: function(event, ui) {
2578                 var self = $(this).data("resizable"), o = self.options,
2579                                 ps = self.containerSize, co = self.containerOffset, cs = self.size, cp = self.position,
2580                                 pRatio = self._aspectRatio || event.shiftKey, cop = { top:0, left:0 }, ce = self.containerElement;
2582                 if (ce[0] != document && (/static/).test(ce.css('position'))) cop = co;
2584                 if (cp.left < (self._helper ? co.left : 0)) {
2585                         self.size.width = self.size.width + (self._helper ? (self.position.left - co.left) : (self.position.left - cop.left));
2586                         if (pRatio) self.size.height = self.size.width / o.aspectRatio;
2587                         self.position.left = o.helper ? co.left : 0;
2588                 }
2590                 if (cp.top < (self._helper ? co.top : 0)) {
2591                         self.size.height = self.size.height + (self._helper ? (self.position.top - co.top) : self.position.top);
2592                         if (pRatio) self.size.width = self.size.height * o.aspectRatio;
2593                         self.position.top = self._helper ? co.top : 0;
2594                 }
2596                 self.offset.left = self.parentData.left+self.position.left;
2597                 self.offset.top = self.parentData.top+self.position.top;
2599                 var woset = Math.abs( (self._helper ? self.offset.left - cop.left : (self.offset.left - cop.left)) + self.sizeDiff.width ),
2600                                         hoset = Math.abs( (self._helper ? self.offset.top - cop.top : (self.offset.top - co.top)) + self.sizeDiff.height );
2602                 var isParent = self.containerElement.get(0) == self.element.parent().get(0),
2603                     isOffsetRelative = /relative|absolute/.test(self.containerElement.css('position'));
2605                 if(isParent && isOffsetRelative) woset -= self.parentData.left;
2607                 if (woset + self.size.width >= self.parentData.width) {
2608                         self.size.width = self.parentData.width - woset;
2609                         if (pRatio) self.size.height = self.size.width / self.aspectRatio;
2610                 }
2612                 if (hoset + self.size.height >= self.parentData.height) {
2613                         self.size.height = self.parentData.height - hoset;
2614                         if (pRatio) self.size.width = self.size.height * self.aspectRatio;
2615                 }
2616         },
2618         stop: function(event, ui){
2619                 var self = $(this).data("resizable"), o = self.options, cp = self.position,
2620                                 co = self.containerOffset, cop = self.containerPosition, ce = self.containerElement;
2622                 var helper = $(self.helper), ho = helper.offset(), w = helper.outerWidth() - self.sizeDiff.width, h = helper.outerHeight() - self.sizeDiff.height;
2624                 if (self._helper && !o.animate && (/relative/).test(ce.css('position')))
2625                         $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
2627                 if (self._helper && !o.animate && (/static/).test(ce.css('position')))
2628                         $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
2630         }
2633 $.ui.plugin.add("resizable", "ghost", {
2635         start: function(event, ui) {
2637                 var self = $(this).data("resizable"), o = self.options, cs = self.size;
2639                 self.ghost = self.originalElement.clone();
2640                 self.ghost
2641                         .css({ opacity: .25, display: 'block', position: 'relative', height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 })
2642                         .addClass('ui-resizable-ghost')
2643                         .addClass(typeof o.ghost == 'string' ? o.ghost : '');
2645                 self.ghost.appendTo(self.helper);
2647         },
2649         resize: function(event, ui){
2650                 var self = $(this).data("resizable"), o = self.options;
2651                 if (self.ghost) self.ghost.css({ position: 'relative', height: self.size.height, width: self.size.width });
2652         },
2654         stop: function(event, ui){
2655                 var self = $(this).data("resizable"), o = self.options;
2656                 if (self.ghost && self.helper) self.helper.get(0).removeChild(self.ghost.get(0));
2657         }
2661 $.ui.plugin.add("resizable", "grid", {
2663         resize: function(event, ui) {
2664                 var self = $(this).data("resizable"), o = self.options, cs = self.size, os = self.originalSize, op = self.originalPosition, a = self.axis, ratio = o._aspectRatio || event.shiftKey;
2665                 o.grid = typeof o.grid == "number" ? [o.grid, o.grid] : o.grid;
2666                 var ox = Math.round((cs.width - os.width) / (o.grid[0]||1)) * (o.grid[0]||1), oy = Math.round((cs.height - os.height) / (o.grid[1]||1)) * (o.grid[1]||1);
2668                 if (/^(se|s|e)$/.test(a)) {
2669                         self.size.width = os.width + ox;
2670                         self.size.height = os.height + oy;
2671                 }
2672                 else if (/^(ne)$/.test(a)) {
2673                         self.size.width = os.width + ox;
2674                         self.size.height = os.height + oy;
2675                         self.position.top = op.top - oy;
2676                 }
2677                 else if (/^(sw)$/.test(a)) {
2678                         self.size.width = os.width + ox;
2679                         self.size.height = os.height + oy;
2680                         self.position.left = op.left - ox;
2681                 }
2682                 else {
2683                         self.size.width = os.width + ox;
2684                         self.size.height = os.height + oy;
2685                         self.position.top = op.top - oy;
2686                         self.position.left = op.left - ox;
2687                 }
2688         }
2692 var num = function(v) {
2693         return parseInt(v, 10) || 0;
2696 var isNumber = function(value) {
2697         return !isNaN(parseInt(value, 10));
2700 })(jQuery);
2702  * jQuery UI Selectable 1.8
2704  * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
2705  * Dual licensed under the MIT (MIT-LICENSE.txt)
2706  * and GPL (GPL-LICENSE.txt) licenses.
2708  * http://docs.jquery.com/UI/Selectables
2710  * Depends:
2711  *      jquery.ui.core.js
2712  *      jquery.ui.mouse.js
2713  *      jquery.ui.widget.js
2714  */
2715 (function($) {
2717 $.widget("ui.selectable", $.ui.mouse, {
2718         options: {
2719                 appendTo: 'body',
2720                 autoRefresh: true,
2721                 distance: 0,
2722                 filter: '*',
2723                 tolerance: 'touch'
2724         },
2725         _create: function() {
2726                 var self = this;
2728                 this.element.addClass("ui-selectable");
2730                 this.dragged = false;
2732                 // cache selectee children based on filter
2733                 var selectees;
2734                 this.refresh = function() {
2735                         selectees = $(self.options.filter, self.element[0]);
2736                         selectees.each(function() {
2737                                 var $this = $(this);
2738                                 var pos = $this.offset();
2739                                 $.data(this, "selectable-item", {
2740                                         element: this,
2741                                         $element: $this,
2742                                         left: pos.left,
2743                                         top: pos.top,
2744                                         right: pos.left + $this.outerWidth(),
2745                                         bottom: pos.top + $this.outerHeight(),
2746                                         startselected: false,
2747                                         selected: $this.hasClass('ui-selected'),
2748                                         selecting: $this.hasClass('ui-selecting'),
2749                                         unselecting: $this.hasClass('ui-unselecting')
2750                                 });
2751                         });
2752                 };
2753                 this.refresh();
2755                 this.selectees = selectees.addClass("ui-selectee");
2757                 this._mouseInit();
2759                 this.helper = $(document.createElement('div'))
2760                         .css({border:'1px dotted black'})
2761                         .addClass("ui-selectable-helper");
2762         },
2764         destroy: function() {
2765                 this.selectees
2766                         .removeClass("ui-selectee")
2767                         .removeData("selectable-item");
2768                 this.element
2769                         .removeClass("ui-selectable ui-selectable-disabled")
2770                         .removeData("selectable")
2771                         .unbind(".selectable");
2772                 this._mouseDestroy();
2774                 return this;
2775         },
2777         _mouseStart: function(event) {
2778                 var self = this;
2780                 this.opos = [event.pageX, event.pageY];
2782                 if (this.options.disabled)
2783                         return;
2785                 var options = this.options;
2787                 this.selectees = $(options.filter, this.element[0]);
2789                 this._trigger("start", event);
2791                 $(options.appendTo).append(this.helper);
2792                 // position helper (lasso)
2793                 this.helper.css({
2794                         "z-index": 100,
2795                         "position": "absolute",
2796                         "left": event.clientX,
2797                         "top": event.clientY,
2798                         "width": 0,
2799                         "height": 0
2800                 });
2802                 if (options.autoRefresh) {
2803                         this.refresh();
2804                 }
2806                 this.selectees.filter('.ui-selected').each(function() {
2807                         var selectee = $.data(this, "selectable-item");
2808                         selectee.startselected = true;
2809                         if (!event.metaKey) {
2810                                 selectee.$element.removeClass('ui-selected');
2811                                 selectee.selected = false;
2812                                 selectee.$element.addClass('ui-unselecting');
2813                                 selectee.unselecting = true;
2814                                 // selectable UNSELECTING callback
2815                                 self._trigger("unselecting", event, {
2816                                         unselecting: selectee.element
2817                                 });
2818                         }
2819                 });
2821                 $(event.target).parents().andSelf().each(function() {
2822                         var selectee = $.data(this, "selectable-item");
2823                         if (selectee) {
2824                                 selectee.$element.removeClass("ui-unselecting").addClass('ui-selecting');
2825                                 selectee.unselecting = false;
2826                                 selectee.selecting = true;
2827                                 selectee.selected = true;
2828                                 // selectable SELECTING callback
2829                                 self._trigger("selecting", event, {
2830                                         selecting: selectee.element
2831                                 });
2832                                 return false;
2833                         }
2834                 });
2836         },
2838         _mouseDrag: function(event) {
2839                 var self = this;
2840                 this.dragged = true;
2842                 if (this.options.disabled)
2843                         return;
2845                 var options = this.options;
2847                 var x1 = this.opos[0], y1 = this.opos[1], x2 = event.pageX, y2 = event.pageY;
2848                 if (x1 > x2) { var tmp = x2; x2 = x1; x1 = tmp; }
2849                 if (y1 > y2) { var tmp = y2; y2 = y1; y1 = tmp; }
2850                 this.helper.css({left: x1, top: y1, width: x2-x1, height: y2-y1});
2852                 this.selectees.each(function() {
2853                         var selectee = $.data(this, "selectable-item");
2854                         //prevent helper from being selected if appendTo: selectable
2855                         if (!selectee || selectee.element == self.element[0])
2856                                 return;
2857                         var hit = false;
2858                         if (options.tolerance == 'touch') {
2859                                 hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) );
2860                         } else if (options.tolerance == 'fit') {
2861                                 hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2);
2862                         }
2864                         if (hit) {
2865                                 // SELECT
2866                                 if (selectee.selected) {
2867                                         selectee.$element.removeClass('ui-selected');
2868                                         selectee.selected = false;
2869                                 }
2870                                 if (selectee.unselecting) {
2871                                         selectee.$element.removeClass('ui-unselecting');
2872                                         selectee.unselecting = false;
2873                                 }
2874                                 if (!selectee.selecting) {
2875                                         selectee.$element.addClass('ui-selecting');
2876                                         selectee.selecting = true;
2877                                         // selectable SELECTING callback
2878                                         self._trigger("selecting", event, {
2879                                                 selecting: selectee.element
2880                                         });
2881                                 }
2882                         } else {
2883                                 // UNSELECT
2884                                 if (selectee.selecting) {
2885                                         if (event.metaKey && selectee.startselected) {
2886                                                 selectee.$element.removeClass('ui-selecting');
2887                                                 selectee.selecting = false;
2888                                                 selectee.$element.addClass('ui-selected');
2889                                                 selectee.selected = true;
2890                                         } else {
2891                                                 selectee.$element.removeClass('ui-selecting');
2892                                                 selectee.selecting = false;
2893                                                 if (selectee.startselected) {
2894                                                         selectee.$element.addClass('ui-unselecting');
2895                                                         selectee.unselecting = true;
2896                                                 }
2897                                                 // selectable UNSELECTING callback
2898                                                 self._trigger("unselecting", event, {
2899                                                         unselecting: selectee.element
2900                                                 });
2901                                         }
2902                                 }
2903                                 if (selectee.selected) {
2904                                         if (!event.metaKey && !selectee.startselected) {
2905                                                 selectee.$element.removeClass('ui-selected');
2906                                                 selectee.selected = false;
2908                                                 selectee.$element.addClass('ui-unselecting');
2909                                                 selectee.unselecting = true;
2910                                                 // selectable UNSELECTING callback
2911                                                 self._trigger("unselecting", event, {
2912                                                         unselecting: selectee.element
2913                                                 });
2914                                         }
2915                                 }
2916                         }
2917                 });
2919                 return false;
2920         },
2922         _mouseStop: function(event) {
2923                 var self = this;
2925                 this.dragged = false;
2927                 var options = this.options;
2929                 $('.ui-unselecting', this.element[0]).each(function() {
2930                         var selectee = $.data(this, "selectable-item");
2931                         selectee.$element.removeClass('ui-unselecting');
2932                         selectee.unselecting = false;
2933                         selectee.startselected = false;
2934                         self._trigger("unselected", event, {
2935                                 unselected: selectee.element
2936                         });
2937                 });
2938                 $('.ui-selecting', this.element[0]).each(function() {
2939                         var selectee = $.data(this, "selectable-item");
2940                         selectee.$element.removeClass('ui-selecting').addClass('ui-selected');
2941                         selectee.selecting = false;
2942                         selectee.selected = true;
2943                         selectee.startselected = true;
2944                         self._trigger("selected", event, {
2945                                 selected: selectee.element
2946                         });
2947                 });
2948                 this._trigger("stop", event);
2950                 this.helper.remove();
2952                 return false;
2953         }
2957 $.extend($.ui.selectable, {
2958         version: "1.8"
2961 })(jQuery);
2963  * jQuery UI Sortable 1.8
2965  * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
2966  * Dual licensed under the MIT (MIT-LICENSE.txt)
2967  * and GPL (GPL-LICENSE.txt) licenses.
2969  * http://docs.jquery.com/UI/Sortables
2971  * Depends:
2972  *      jquery.ui.core.js
2973  *      jquery.ui.mouse.js
2974  *      jquery.ui.widget.js
2975  */
2976 (function($) {
2978 $.widget("ui.sortable", $.ui.mouse, {
2979         widgetEventPrefix: "sort",
2980         options: {
2981                 appendTo: "parent",
2982                 axis: false,
2983                 connectWith: false,
2984                 containment: false,
2985                 cursor: 'auto',
2986                 cursorAt: false,
2987                 dropOnEmpty: true,
2988                 forcePlaceholderSize: false,
2989                 forceHelperSize: false,
2990                 grid: false,
2991                 handle: false,
2992                 helper: "original",
2993                 items: '> *',
2994                 opacity: false,
2995                 placeholder: false,
2996                 revert: false,
2997                 scroll: true,
2998                 scrollSensitivity: 20,
2999                 scrollSpeed: 20,
3000                 scope: "default",
3001                 tolerance: "intersect",
3002                 zIndex: 1000
3003         },
3004         _create: function() {
3006                 var o = this.options;
3007                 this.containerCache = {};
3008                 this.element.addClass("ui-sortable");
3010                 //Get the items
3011                 this.refresh();
3013                 //Let's determine if the items are floating
3014                 this.floating = this.items.length ? (/left|right/).test(this.items[0].item.css('float')) : false;
3016                 //Let's determine the parent's offset
3017                 this.offset = this.element.offset();
3019                 //Initialize mouse events for interaction
3020                 this._mouseInit();
3022         },
3024         destroy: function() {
3025                 this.element
3026                         .removeClass("ui-sortable ui-sortable-disabled")
3027                         .removeData("sortable")
3028                         .unbind(".sortable");
3029                 this._mouseDestroy();
3031                 for ( var i = this.items.length - 1; i >= 0; i-- )
3032                         this.items[i].item.removeData("sortable-item");
3034                 return this;
3035         },
3037         _mouseCapture: function(event, overrideHandle) {
3039                 if (this.reverting) {
3040                         return false;
3041                 }
3043                 if(this.options.disabled || this.options.type == 'static') return false;
3045                 //We have to refresh the items data once first
3046                 this._refreshItems(event);
3048                 //Find out if the clicked node (or one of its parents) is a actual item in this.items
3049                 var currentItem = null, self = this, nodes = $(event.target).parents().each(function() {
3050                         if($.data(this, 'sortable-item') == self) {
3051                                 currentItem = $(this);
3052                                 return false;
3053                         }
3054                 });
3055                 if($.data(event.target, 'sortable-item') == self) currentItem = $(event.target);
3057                 if(!currentItem) return false;
3058                 if(this.options.handle && !overrideHandle) {
3059                         var validHandle = false;
3061                         $(this.options.handle, currentItem).find("*").andSelf().each(function() { if(this == event.target) validHandle = true; });
3062                         if(!validHandle) return false;
3063                 }
3065                 this.currentItem = currentItem;
3066                 this._removeCurrentsFromItems();
3067                 return true;
3069         },
3071         _mouseStart: function(event, overrideHandle, noActivation) {
3073                 var o = this.options, self = this;
3074                 this.currentContainer = this;
3076                 //We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture
3077                 this.refreshPositions();
3079                 //Create and append the visible helper
3080                 this.helper = this._createHelper(event);
3082                 //Cache the helper size
3083                 this._cacheHelperProportions();
3085                 /*
3086                  * - Position generation -
3087                  * This block generates everything position related - it's the core of draggables.
3088                  */
3090                 //Cache the margins of the original element
3091                 this._cacheMargins();
3093                 //Get the next scrolling parent
3094                 this.scrollParent = this.helper.scrollParent();
3096                 //The element's absolute position on the page minus margins
3097                 this.offset = this.currentItem.offset();
3098                 this.offset = {
3099                         top: this.offset.top - this.margins.top,
3100                         left: this.offset.left - this.margins.left
3101                 };
3103                 // Only after we got the offset, we can change the helper's position to absolute
3104                 // TODO: Still need to figure out a way to make relative sorting possible
3105                 this.helper.css("position", "absolute");
3106                 this.cssPosition = this.helper.css("position");
3108                 $.extend(this.offset, {
3109                         click: { //Where the click happened, relative to the element
3110                                 left: event.pageX - this.offset.left,
3111                                 top: event.pageY - this.offset.top
3112                         },
3113                         parent: this._getParentOffset(),
3114                         relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
3115                 });
3117                 //Generate the original position
3118                 this.originalPosition = this._generatePosition(event);
3119                 this.originalPageX = event.pageX;
3120                 this.originalPageY = event.pageY;
3122                 //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
3123                 (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
3125                 //Cache the former DOM position
3126                 this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] };
3128                 //If the helper is not the original, hide the original so it's not playing any role during the drag, won't cause anything bad this way
3129                 if(this.helper[0] != this.currentItem[0]) {
3130                         this.currentItem.hide();
3131                 }
3133                 //Create the placeholder
3134                 this._createPlaceholder();
3136                 //Set a containment if given in the options
3137                 if(o.containment)
3138                         this._setContainment();
3140                 if(o.cursor) { // cursor option
3141                         if ($('body').css("cursor")) this._storedCursor = $('body').css("cursor");
3142                         $('body').css("cursor", o.cursor);
3143                 }
3145                 if(o.opacity) { // opacity option
3146                         if (this.helper.css("opacity")) this._storedOpacity = this.helper.css("opacity");
3147                         this.helper.css("opacity", o.opacity);
3148                 }
3150                 if(o.zIndex) { // zIndex option
3151                         if (this.helper.css("zIndex")) this._storedZIndex = this.helper.css("zIndex");
3152                         this.helper.css("zIndex", o.zIndex);
3153                 }
3155                 //Prepare scrolling
3156                 if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML')
3157                         this.overflowOffset = this.scrollParent.offset();
3159                 //Call callbacks
3160                 this._trigger("start", event, this._uiHash());
3162                 //Recache the helper size
3163                 if(!this._preserveHelperProportions)
3164                         this._cacheHelperProportions();
3167                 //Post 'activate' events to possible containers
3168                 if(!noActivation) {
3169                          for (var i = this.containers.length - 1; i >= 0; i--) { this.containers[i]._trigger("activate", event, self._uiHash(this)); }
3170                 }
3172                 //Prepare possible droppables
3173                 if($.ui.ddmanager)
3174                         $.ui.ddmanager.current = this;
3176                 if ($.ui.ddmanager && !o.dropBehaviour)
3177                         $.ui.ddmanager.prepareOffsets(this, event);
3179                 this.dragging = true;
3181                 this.helper.addClass("ui-sortable-helper");
3182                 this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position
3183                 return true;
3185         },
3187         _mouseDrag: function(event) {
3189                 //Compute the helpers position
3190                 this.position = this._generatePosition(event);
3191                 this.positionAbs = this._convertPositionTo("absolute");
3193                 if (!this.lastPositionAbs) {
3194                         this.lastPositionAbs = this.positionAbs;
3195                 }
3197                 //Do scrolling
3198                 if(this.options.scroll) {
3199                         var o = this.options, scrolled = false;
3200                         if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') {
3202                                 if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
3203                                         this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed;
3204                                 else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity)
3205                                         this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed;
3207                                 if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
3208                                         this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed;
3209                                 else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity)
3210                                         this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed;
3212                         } else {
3214                                 if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
3215                                         scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
3216                                 else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
3217                                         scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
3219                                 if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
3220                                         scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
3221                                 else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
3222                                         scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
3224                         }
3226                         if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
3227                                 $.ui.ddmanager.prepareOffsets(this, event);
3228                 }
3230                 //Regenerate the absolute position used for position checks
3231                 this.positionAbs = this._convertPositionTo("absolute");
3233                 //Set the helper position
3234                 if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
3235                 if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
3237                 //Rearrange
3238                 for (var i = this.items.length - 1; i >= 0; i--) {
3240                         //Cache variables and intersection, continue if no intersection
3241                         var item = this.items[i], itemElement = item.item[0], intersection = this._intersectsWithPointer(item);
3242                         if (!intersection) continue;
3244                         if(itemElement != this.currentItem[0] //cannot intersect with itself
3245                                 &&      this.placeholder[intersection == 1 ? "next" : "prev"]()[0] != itemElement //no useless actions that have been done before
3246                                 &&      !$.ui.contains(this.placeholder[0], itemElement) //no action if the item moved is the parent of the item checked
3247                                 && (this.options.type == 'semi-dynamic' ? !$.ui.contains(this.element[0], itemElement) : true)
3248                                 //&& itemElement.parentNode == this.placeholder[0].parentNode // only rearrange items within the same container
3249                         ) {
3251                                 this.direction = intersection == 1 ? "down" : "up";
3253                                 if (this.options.tolerance == "pointer" || this._intersectsWithSides(item)) {
3254                                         this._rearrange(event, item);
3255                                 } else {
3256                                         break;
3257                                 }
3259                                 this._trigger("change", event, this._uiHash());
3260                                 break;
3261                         }
3262                 }
3264                 //Post events to containers
3265                 this._contactContainers(event);
3267                 //Interconnect with droppables
3268                 if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
3270                 //Call callbacks
3271                 this._trigger('sort', event, this._uiHash());
3273                 this.lastPositionAbs = this.positionAbs;
3274                 return false;
3276         },
3278         _mouseStop: function(event, noPropagation) {
3280                 if(!event) return;
3282                 //If we are using droppables, inform the manager about the drop
3283                 if ($.ui.ddmanager && !this.options.dropBehaviour)
3284                         $.ui.ddmanager.drop(this, event);
3286                 if(this.options.revert) {
3287                         var self = this;
3288                         var cur = self.placeholder.offset();
3290                         self.reverting = true;
3292                         $(this.helper).animate({
3293                                 left: cur.left - this.offset.parent.left - self.margins.left + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollLeft),
3294                                 top: cur.top - this.offset.parent.top - self.margins.top + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollTop)
3295                         }, parseInt(this.options.revert, 10) || 500, function() {
3296                                 self._clear(event);
3297                         });
3298                 } else {
3299                         this._clear(event, noPropagation);
3300                 }
3302                 return false;
3304         },
3306         cancel: function() {
3308                 var self = this;
3310                 if(this.dragging) {
3312                         this._mouseUp();
3314                         if(this.options.helper == "original")
3315                                 this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
3316                         else
3317                                 this.currentItem.show();
3319                         //Post deactivating events to containers
3320                         for (var i = this.containers.length - 1; i >= 0; i--){
3321                                 this.containers[i]._trigger("deactivate", null, self._uiHash(this));
3322                                 if(this.containers[i].containerCache.over) {
3323                                         this.containers[i]._trigger("out", null, self._uiHash(this));
3324                                         this.containers[i].containerCache.over = 0;
3325                                 }
3326                         }
3328                 }
3330                 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
3331                 if(this.placeholder[0].parentNode) this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
3332                 if(this.options.helper != "original" && this.helper && this.helper[0].parentNode) this.helper.remove();
3334                 $.extend(this, {
3335                         helper: null,
3336                         dragging: false,
3337                         reverting: false,
3338                         _noFinalSort: null
3339                 });
3341                 if(this.domPosition.prev) {
3342                         $(this.domPosition.prev).after(this.currentItem);
3343                 } else {
3344                         $(this.domPosition.parent).prepend(this.currentItem);
3345                 }
3347                 return this;
3349         },
3351         serialize: function(o) {
3353                 var items = this._getItemsAsjQuery(o && o.connected);
3354                 var str = []; o = o || {};
3356                 $(items).each(function() {
3357                         var res = ($(o.item || this).attr(o.attribute || 'id') || '').match(o.expression || (/(.+)[-=_](.+)/));
3358                         if(res) str.push((o.key || res[1]+'[]')+'='+(o.key && o.expression ? res[1] : res[2]));
3359                 });
3361                 return str.join('&');
3363         },
3365         toArray: function(o) {
3367                 var items = this._getItemsAsjQuery(o && o.connected);
3368                 var ret = []; o = o || {};
3370                 items.each(function() { ret.push($(o.item || this).attr(o.attribute || 'id') || ''); });
3371                 return ret;
3373         },
3375         /* Be careful with the following core functions */
3376         _intersectsWith: function(item) {
3378                 var x1 = this.positionAbs.left,
3379                         x2 = x1 + this.helperProportions.width,
3380                         y1 = this.positionAbs.top,
3381                         y2 = y1 + this.helperProportions.height;
3383                 var l = item.left,
3384                         r = l + item.width,
3385                         t = item.top,
3386                         b = t + item.height;
3388                 var dyClick = this.offset.click.top,
3389                         dxClick = this.offset.click.left;
3391                 var isOverElement = (y1 + dyClick) > t && (y1 + dyClick) < b && (x1 + dxClick) > l && (x1 + dxClick) < r;
3393                 if(        this.options.tolerance == "pointer"
3394                         || this.options.forcePointerForContainers
3395                         || (this.options.tolerance != "pointer" && this.helperProportions[this.floating ? 'width' : 'height'] > item[this.floating ? 'width' : 'height'])
3396                 ) {
3397                         return isOverElement;
3398                 } else {
3400                         return (l < x1 + (this.helperProportions.width / 2) // Right Half
3401                                 && x2 - (this.helperProportions.width / 2) < r // Left Half
3402                                 && t < y1 + (this.helperProportions.height / 2) // Bottom Half
3403                                 && y2 - (this.helperProportions.height / 2) < b ); // Top Half
3405                 }
3406         },
3408         _intersectsWithPointer: function(item) {
3410                 var isOverElementHeight = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height),
3411                         isOverElementWidth = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width),
3412                         isOverElement = isOverElementHeight && isOverElementWidth,
3413                         verticalDirection = this._getDragVerticalDirection(),
3414                         horizontalDirection = this._getDragHorizontalDirection();
3416                 if (!isOverElement)
3417                         return false;
3419                 return this.floating ?
3420                         ( ((horizontalDirection && horizontalDirection == "right") || verticalDirection == "down") ? 2 : 1 )
3421                         : ( verticalDirection && (verticalDirection == "down" ? 2 : 1) );
3423         },
3425         _intersectsWithSides: function(item) {
3427                 var isOverBottomHalf = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height),
3428                         isOverRightHalf = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width),
3429                         verticalDirection = this._getDragVerticalDirection(),
3430                         horizontalDirection = this._getDragHorizontalDirection();
3432                 if (this.floating && horizontalDirection) {
3433                         return ((horizontalDirection == "right" && isOverRightHalf) || (horizontalDirection == "left" && !isOverRightHalf));
3434                 } else {
3435                         return verticalDirection && ((verticalDirection == "down" && isOverBottomHalf) || (verticalDirection == "up" && !isOverBottomHalf));
3436                 }
3438         },
3440         _getDragVerticalDirection: function() {
3441                 var delta = this.positionAbs.top - this.lastPositionAbs.top;
3442                 return delta != 0 && (delta > 0 ? "down" : "up");
3443         },
3445         _getDragHorizontalDirection: function() {
3446                 var delta = this.positionAbs.left - this.lastPositionAbs.left;
3447                 return delta != 0 && (delta > 0 ? "right" : "left");
3448         },
3450         refresh: function(event) {
3451                 this._refreshItems(event);
3452                 this.refreshPositions();
3453                 return this;
3454         },
3456         _connectWith: function() {
3457                 var options = this.options;
3458                 return options.connectWith.constructor == String
3459                         ? [options.connectWith]
3460                         : options.connectWith;
3461         },
3462         
3463         _getItemsAsjQuery: function(connected) {
3465                 var self = this;
3466                 var items = [];
3467                 var queries = [];
3468                 var connectWith = this._connectWith();
3470                 if(connectWith && connected) {
3471                         for (var i = connectWith.length - 1; i >= 0; i--){
3472                                 var cur = $(connectWith[i]);
3473                                 for (var j = cur.length - 1; j >= 0; j--){
3474                                         var inst = $.data(cur[j], 'sortable');
3475                                         if(inst && inst != this && !inst.options.disabled) {
3476                                                 queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element) : $(inst.options.items, inst.element).not(".ui-sortable-helper").not('.ui-sortable-placeholder'), inst]);
3477                                         }
3478                                 };
3479                         };
3480                 }
3482                 queries.push([$.isFunction(this.options.items) ? this.options.items.call(this.element, null, { options: this.options, item: this.currentItem }) : $(this.options.items, this.element).not(".ui-sortable-helper").not('.ui-sortable-placeholder'), this]);
3484                 for (var i = queries.length - 1; i >= 0; i--){
3485                         queries[i][0].each(function() {
3486                                 items.push(this);
3487                         });
3488                 };
3490                 return $(items);
3492         },
3494         _removeCurrentsFromItems: function() {
3496                 var list = this.currentItem.find(":data(sortable-item)");
3498                 for (var i=0; i < this.items.length; i++) {
3500                         for (var j=0; j < list.length; j++) {
3501                                 if(list[j] == this.items[i].item[0])
3502                                         this.items.splice(i,1);
3503                         };
3505                 };
3507         },
3509         _refreshItems: function(event) {
3511                 this.items = [];
3512                 this.containers = [this];
3513                 var items = this.items;
3514                 var self = this;
3515                 var queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]];
3516                 var connectWith = this._connectWith();
3518                 if(connectWith) {
3519                         for (var i = connectWith.length - 1; i >= 0; i--){
3520                                 var cur = $(connectWith[i]);
3521                                 for (var j = cur.length - 1; j >= 0; j--){
3522                                         var inst = $.data(cur[j], 'sortable');
3523                                         if(inst && inst != this && !inst.options.disabled) {
3524                                                 queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]);
3525                                                 this.containers.push(inst);
3526                                         }
3527                                 };
3528                         };
3529                 }
3531                 for (var i = queries.length - 1; i >= 0; i--) {
3532                         var targetData = queries[i][1];
3533                         var _queries = queries[i][0];
3535                         for (var j=0, queriesLength = _queries.length; j < queriesLength; j++) {
3536                                 var item = $(_queries[j]);
3538                                 item.data('sortable-item', targetData); // Data for target checking (mouse manager)
3540                                 items.push({
3541                                         item: item,
3542                                         instance: targetData,
3543                                         width: 0, height: 0,
3544                                         left: 0, top: 0
3545                                 });
3546                         };
3547                 };
3549         },
3551         refreshPositions: function(fast) {
3553                 //This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change
3554                 if(this.offsetParent && this.helper) {
3555                         this.offset.parent = this._getParentOffset();
3556                 }
3558                 for (var i = this.items.length - 1; i >= 0; i--){
3559                         var item = this.items[i];
3561                         var t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item;
3563                         if (!fast) {
3564                                 item.width = t.outerWidth();
3565                                 item.height = t.outerHeight();
3566                         }
3568                         var p = t.offset();
3569                         item.left = p.left;
3570                         item.top = p.top;
3571                 };
3573                 if(this.options.custom && this.options.custom.refreshContainers) {
3574                         this.options.custom.refreshContainers.call(this);
3575                 } else {
3576                         for (var i = this.containers.length - 1; i >= 0; i--){
3577                                 var p = this.containers[i].element.offset();
3578                                 this.containers[i].containerCache.left = p.left;
3579                                 this.containers[i].containerCache.top = p.top;
3580                                 this.containers[i].containerCache.width = this.containers[i].element.outerWidth();
3581                                 this.containers[i].containerCache.height = this.containers[i].element.outerHeight();
3582                         };
3583                 }
3585                 return this;
3586         },
3588         _createPlaceholder: function(that) {
3590                 var self = that || this, o = self.options;
3592                 if(!o.placeholder || o.placeholder.constructor == String) {
3593                         var className = o.placeholder;
3594                         o.placeholder = {
3595                                 element: function() {
3597                                         var el = $(document.createElement(self.currentItem[0].nodeName))
3598                                                 .addClass(className || self.currentItem[0].className+" ui-sortable-placeholder")
3599                                                 .removeClass("ui-sortable-helper")[0];
3601                                         if(!className)
3602                                                 el.style.visibility = "hidden";
3604                                         return el;
3605                                 },
3606                                 update: function(container, p) {
3608                                         // 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that
3609                                         // 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified
3610                                         if(className && !o.forcePlaceholderSize) return;
3612                                         //If the element doesn't have a actual height by itself (without styles coming from a stylesheet), it receives the inline height from the dragged item
3613                                         if(!p.height()) { p.height(self.currentItem.innerHeight() - parseInt(self.currentItem.css('paddingTop')||0, 10) - parseInt(self.currentItem.css('paddingBottom')||0, 10)); };
3614                                         if(!p.width()) { p.width(self.currentItem.innerWidth() - parseInt(self.currentItem.css('paddingLeft')||0, 10) - parseInt(self.currentItem.css('paddingRight')||0, 10)); };
3615                                 }
3616                         };
3617                 }
3619                 //Create the placeholder
3620                 self.placeholder = $(o.placeholder.element.call(self.element, self.currentItem));
3622                 //Append it after the actual current item
3623                 self.currentItem.after(self.placeholder);
3625                 //Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
3626                 o.placeholder.update(self, self.placeholder);
3628         },
3630         _contactContainers: function(event) {
3631                 
3632                 // get innermost container that intersects with item 
3633                 var innermostContainer = null, innermostIndex = null;           
3634                 
3635                 
3636                 for (var i = this.containers.length - 1; i >= 0; i--){
3638                         // never consider a container that's located within the item itself 
3639                         if($.ui.contains(this.currentItem[0], this.containers[i].element[0]))
3640                                 continue;
3642                         if(this._intersectsWith(this.containers[i].containerCache)) {
3644                                 // if we've already found a container and it's more "inner" than this, then continue 
3645                                 if(innermostContainer && $.ui.contains(this.containers[i].element[0], innermostContainer.element[0]))
3646                                         continue;
3648                                 innermostContainer = this.containers[i]; 
3649                                 innermostIndex = i;
3650                                         
3651                         } else {
3652                                 // container doesn't intersect. trigger "out" event if necessary 
3653                                 if(this.containers[i].containerCache.over) {
3654                                         this.containers[i]._trigger("out", event, this._uiHash(this));
3655                                         this.containers[i].containerCache.over = 0;
3656                                 }
3657                         }
3659                 }
3660                 
3661                 // if no intersecting containers found, return 
3662                 if(!innermostContainer) return; 
3664                 // move the item into the container if it's not there already
3665                 if(this.containers.length === 1) {
3666                         this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
3667                         this.containers[innermostIndex].containerCache.over = 1;
3668                 } else if(this.currentContainer != this.containers[innermostIndex]) { 
3670                         //When entering a new container, we will find the item with the least distance and append our item near it 
3671                         var dist = 10000; var itemWithLeastDistance = null; var base = this.positionAbs[this.containers[innermostIndex].floating ? 'left' : 'top']; 
3672                         for (var j = this.items.length - 1; j >= 0; j--) { 
3673                                 if(!$.ui.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) continue; 
3674                                 var cur = this.items[j][this.containers[innermostIndex].floating ? 'left' : 'top']; 
3675                                 if(Math.abs(cur - base) < dist) { 
3676                                         dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j]; 
3677                                 } 
3678                         } 
3680                         if(!itemWithLeastDistance && !this.options.dropOnEmpty) //Check if dropOnEmpty is enabled 
3681                                 return; 
3683                         this.currentContainer = this.containers[innermostIndex]; 
3684                         itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true); 
3685                         this._trigger("change", event, this._uiHash()); 
3686                         this.containers[innermostIndex]._trigger("change", event, this._uiHash(this)); 
3688                         //Update the placeholder 
3689                         this.options.placeholder.update(this.currentContainer, this.placeholder); 
3690                 
3691                         this.containers[innermostIndex]._trigger("over", event, this._uiHash(this)); 
3692                         this.containers[innermostIndex].containerCache.over = 1;
3693                 } 
3694         
3695                 
3696         },
3698         _createHelper: function(event) {
3700                 var o = this.options;
3701                 var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper == 'clone' ? this.currentItem.clone() : this.currentItem);
3703                 if(!helper.parents('body').length) //Add the helper to the DOM if that didn't happen already
3704                         $(o.appendTo != 'parent' ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]);
3706                 if(helper[0] == this.currentItem[0])
3707                         this._storedCSS = { width: this.currentItem[0].style.width, height: this.currentItem[0].style.height, position: this.currentItem.css("position"), top: this.currentItem.css("top"), left: this.currentItem.css("left") };
3709                 if(helper[0].style.width == '' || o.forceHelperSize) helper.width(this.currentItem.width());
3710                 if(helper[0].style.height == '' || o.forceHelperSize) helper.height(this.currentItem.height());
3712                 return helper;
3714         },
3716         _adjustOffsetFromHelper: function(obj) {
3717                 if (typeof obj == 'string') {
3718                         obj = obj.split(' ');
3719                 }
3720                 if ($.isArray(obj)) {
3721                         obj = {left: +obj[0], top: +obj[1] || 0};
3722                 }
3723                 if ('left' in obj) {
3724                         this.offset.click.left = obj.left + this.margins.left;
3725                 }
3726                 if ('right' in obj) {
3727                         this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
3728                 }
3729                 if ('top' in obj) {
3730                         this.offset.click.top = obj.top + this.margins.top;
3731                 }
3732                 if ('bottom' in obj) {
3733                         this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
3734                 }
3735         },
3737         _getParentOffset: function() {
3740                 //Get the offsetParent and cache its position
3741                 this.offsetParent = this.helper.offsetParent();
3742                 var po = this.offsetParent.offset();
3744                 // This is a special case where we need to modify a offset calculated on start, since the following happened:
3745                 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
3746                 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
3747                 //    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
3748                 if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) {
3749                         po.left += this.scrollParent.scrollLeft();
3750                         po.top += this.scrollParent.scrollTop();
3751                 }
3753                 if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
3754                 || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix
3755                         po = { top: 0, left: 0 };
3757                 return {
3758                         top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
3759                         left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
3760                 };
3762         },
3764         _getRelativeOffset: function() {
3766                 if(this.cssPosition == "relative") {
3767                         var p = this.currentItem.position();
3768                         return {
3769                                 top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
3770                                 left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
3771                         };
3772                 } else {
3773                         return { top: 0, left: 0 };
3774                 }
3776         },
3778         _cacheMargins: function() {
3779                 this.margins = {
3780                         left: (parseInt(this.currentItem.css("marginLeft"),10) || 0),
3781                         top: (parseInt(this.currentItem.css("marginTop"),10) || 0)
3782                 };
3783         },
3785         _cacheHelperProportions: function() {
3786                 this.helperProportions = {
3787                         width: this.helper.outerWidth(),
3788                         height: this.helper.outerHeight()
3789                 };
3790         },
3792         _setContainment: function() {
3794                 var o = this.options;
3795                 if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
3796                 if(o.containment == 'document' || o.containment == 'window') this.containment = [
3797                         0 - this.offset.relative.left - this.offset.parent.left,
3798                         0 - this.offset.relative.top - this.offset.parent.top,
3799                         $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
3800                         ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
3801                 ];
3803                 if(!(/^(document|window|parent)$/).test(o.containment)) {
3804                         var ce = $(o.containment)[0];
3805                         var co = $(o.containment).offset();
3806                         var over = ($(ce).css("overflow") != 'hidden');
3808                         this.containment = [
3809                                 co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
3810                                 co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
3811                                 co.left+(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left,
3812                                 co.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top
3813                         ];
3814                 }
3816         },
3818         _convertPositionTo: function(d, pos) {
3820                 if(!pos) pos = this.position;
3821                 var mod = d == "absolute" ? 1 : -1;
3822                 var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
3824                 return {
3825                         top: (
3826                                 pos.top                                                                                                                                 // The absolute mouse position
3827                                 + this.offset.relative.top * mod                                                                                // Only for relative positioned nodes: Relative offset from element to offset parent
3828                                 + this.offset.parent.top * mod                                                                                  // The offsetParent's offset without borders (offset + border)
3829                                 - ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
3830                         ),
3831                         left: (
3832                                 pos.left                                                                                                                                // The absolute mouse position
3833                                 + this.offset.relative.left * mod                                                                               // Only for relative positioned nodes: Relative offset from element to offset parent
3834                                 + this.offset.parent.left * mod                                                                                 // The offsetParent's offset without borders (offset + border)
3835                                 - ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
3836                         )
3837                 };
3839         },
3841         _generatePosition: function(event) {
3843                 var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
3845                 // This is another very weird special case that only happens for relative elements:
3846                 // 1. If the css position is relative
3847                 // 2. and the scroll parent is the document or similar to the offset parent
3848                 // we have to refresh the relative offset during the scroll so there are no jumps
3849                 if(this.cssPosition == 'relative' && !(this.scrollParent[0] != document && this.scrollParent[0] != this.offsetParent[0])) {
3850                         this.offset.relative = this._getRelativeOffset();
3851                 }
3853                 var pageX = event.pageX;
3854                 var pageY = event.pageY;
3856                 /*
3857                  * - Position constraining -
3858                  * Constrain the position to a mix of grid, containment.
3859                  */
3861                 if(this.originalPosition) { //If we are not dragging yet, we won't check for options
3863                         if(this.containment) {
3864                                 if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left;
3865                                 if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top;
3866                                 if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left;
3867                                 if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top;
3868                         }
3870                         if(o.grid) {
3871                                 var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
3872                                 pageY = this.containment ? (!(top - this.offset.click.top < this.containment[1] || top - this.offset.click.top > this.containment[3]) ? top : (!(top - this.offset.click.top < this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;
3874                                 var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
3875                                 pageX = this.containment ? (!(left - this.offset.click.left < this.containment[0] || left - this.offset.click.left > this.containment[2]) ? left : (!(left - this.offset.click.left < this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
3876                         }
3878                 }
3880                 return {
3881                         top: (
3882                                 pageY                                                                                                                           // The absolute mouse position
3883                                 - this.offset.click.top                                                                                                 // Click offset (relative to the element)
3884                                 - this.offset.relative.top                                                                                              // Only for relative positioned nodes: Relative offset from element to offset parent
3885                                 - this.offset.parent.top                                                                                                // The offsetParent's offset without borders (offset + border)
3886                                 + ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
3887                         ),
3888                         left: (
3889                                 pageX                                                                                                                           // The absolute mouse position
3890                                 - this.offset.click.left                                                                                                // Click offset (relative to the element)
3891                                 - this.offset.relative.left                                                                                             // Only for relative positioned nodes: Relative offset from element to offset parent
3892                                 - this.offset.parent.left                                                                                               // The offsetParent's offset without borders (offset + border)
3893                                 + ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
3894                         )
3895                 };
3897         },
3899         _rearrange: function(event, i, a, hardRefresh) {
3901                 a ? a[0].appendChild(this.placeholder[0]) : i.item[0].parentNode.insertBefore(this.placeholder[0], (this.direction == 'down' ? i.item[0] : i.item[0].nextSibling));
3903                 //Various things done here to improve the performance:
3904                 // 1. we create a setTimeout, that calls refreshPositions
3905                 // 2. on the instance, we have a counter variable, that get's higher after every append
3906                 // 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same
3907                 // 4. this lets only the last addition to the timeout stack through
3908                 this.counter = this.counter ? ++this.counter : 1;
3909                 var self = this, counter = this.counter;
3911                 window.setTimeout(function() {
3912                         if(counter == self.counter) self.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove
3913                 },0);
3915         },
3917         _clear: function(event, noPropagation) {
3919                 this.reverting = false;
3920                 // We delay all events that have to be triggered to after the point where the placeholder has been removed and
3921                 // everything else normalized again
3922                 var delayedTriggers = [], self = this;
3924                 // We first have to update the dom position of the actual currentItem
3925                 // Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088)
3926                 if(!this._noFinalSort && this.currentItem[0].parentNode) this.placeholder.before(this.currentItem);
3927                 this._noFinalSort = null;
3929                 if(this.helper[0] == this.currentItem[0]) {
3930                         for(var i in this._storedCSS) {
3931                                 if(this._storedCSS[i] == 'auto' || this._storedCSS[i] == 'static') this._storedCSS[i] = '';
3932                         }
3933                         this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
3934                 } else {
3935                         this.currentItem.show();
3936                 }
3938                 if(this.fromOutside && !noPropagation) delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); });
3939                 if((this.fromOutside || this.domPosition.prev != this.currentItem.prev().not(".ui-sortable-helper")[0] || this.domPosition.parent != this.currentItem.parent()[0]) && !noPropagation) delayedTriggers.push(function(event) { this._trigger("update", event, this._uiHash()); }); //Trigger update callback if the DOM position has changed
3940                 if(!$.ui.contains(this.element[0], this.currentItem[0])) { //Node was moved out of the current element
3941                         if(!noPropagation) delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); });
3942                         for (var i = this.containers.length - 1; i >= 0; i--){
3943                                 if($.ui.contains(this.containers[i].element[0], this.currentItem[0]) && !noPropagation) {
3944                                         delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); };  }).call(this, this.containers[i]));
3945                                         delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this));  }; }).call(this, this.containers[i]));
3946                                 }
3947                         };
3948                 };
3950                 //Post events to containers
3951                 for (var i = this.containers.length - 1; i >= 0; i--){
3952                         if(!noPropagation) delayedTriggers.push((function(c) { return function(event) { c._trigger("deactivate", event, this._uiHash(this)); };  }).call(this, this.containers[i]));
3953                         if(this.containers[i].containerCache.over) {
3954                                 delayedTriggers.push((function(c) { return function(event) { c._trigger("out", event, this._uiHash(this)); };  }).call(this, this.containers[i]));
3955                                 this.containers[i].containerCache.over = 0;
3956                         }
3957                 }
3959                 //Do what was originally in plugins
3960                 if(this._storedCursor) $('body').css("cursor", this._storedCursor); //Reset cursor
3961                 if(this._storedOpacity) this.helper.css("opacity", this._storedOpacity); //Reset opacity
3962                 if(this._storedZIndex) this.helper.css("zIndex", this._storedZIndex == 'auto' ? '' : this._storedZIndex); //Reset z-index
3964                 this.dragging = false;
3965                 if(this.cancelHelperRemoval) {
3966                         if(!noPropagation) {
3967                                 this._trigger("beforeStop", event, this._uiHash());
3968                                 for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events
3969                                 this._trigger("stop", event, this._uiHash());
3970                         }
3971                         return false;
3972                 }
3974                 if(!noPropagation) this._trigger("beforeStop", event, this._uiHash());
3976                 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
3977                 this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
3979                 if(this.helper[0] != this.currentItem[0]) this.helper.remove(); this.helper = null;
3981                 if(!noPropagation) {
3982                         for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events
3983                         this._trigger("stop", event, this._uiHash());
3984                 }
3986                 this.fromOutside = false;
3987                 return true;
3989         },
3991         _trigger: function() {
3992                 if ($.Widget.prototype._trigger.apply(this, arguments) === false) {
3993                         this.cancel();
3994                 }
3995         },
3997         _uiHash: function(inst) {
3998                 var self = inst || this;
3999                 return {
4000                         helper: self.helper,
4001                         placeholder: self.placeholder || $([]),
4002                         position: self.position,
4003                         originalPosition: self.originalPosition,
4004                         offset: self.positionAbs,
4005                         item: self.currentItem,
4006                         sender: inst ? inst.element : null
4007                 };
4008         }
4012 $.extend($.ui.sortable, {
4013         version: "1.8"
4016 })(jQuery);
4018  * jQuery UI Accordion 1.8
4020  * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
4021  * Dual licensed under the MIT (MIT-LICENSE.txt)
4022  * and GPL (GPL-LICENSE.txt) licenses.
4024  * http://docs.jquery.com/UI/Accordion
4026  * Depends:
4027  *      jquery.ui.core.js
4028  *      jquery.ui.widget.js
4029  */
4030 (function($) {
4032 $.widget("ui.accordion", {
4033         options: {
4034                 active: 0,
4035                 animated: 'slide',
4036                 autoHeight: true,
4037                 clearStyle: false,
4038                 collapsible: false,
4039                 event: "click",
4040                 fillSpace: false,
4041                 header: "> li > :first-child,> :not(li):even",
4042                 icons: {
4043                         header: "ui-icon-triangle-1-e",
4044                         headerSelected: "ui-icon-triangle-1-s"
4045                 },
4046                 navigation: false,
4047                 navigationFilter: function() {
4048                         return this.href.toLowerCase() == location.href.toLowerCase();
4049                 }
4050         },
4051         _create: function() {
4053                 var o = this.options, self = this;
4054                 this.running = 0;
4056                 this.element.addClass("ui-accordion ui-widget ui-helper-reset");
4057                 
4058                 // in lack of child-selectors in CSS we need to mark top-LIs in a UL-accordion for some IE-fix
4059                 if (this.element[0].nodeName == "UL") {
4060                         this.element.children("li").addClass("ui-accordion-li-fix");
4061                 }
4063                 this.headers = this.element.find(o.header).addClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all")
4064                         .bind("mouseenter.accordion", function(){ $(this).addClass('ui-state-hover'); })
4065                         .bind("mouseleave.accordion", function(){ $(this).removeClass('ui-state-hover'); })
4066                         .bind("focus.accordion", function(){ $(this).addClass('ui-state-focus'); })
4067                         .bind("blur.accordion", function(){ $(this).removeClass('ui-state-focus'); });
4069                 this.headers
4070                         .next()
4071                                 .addClass("ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom");
4073                 if ( o.navigation ) {
4074                         var current = this.element.find("a").filter(o.navigationFilter);
4075                         if ( current.length ) {
4076                                 var header = current.closest(".ui-accordion-header");
4077                                 if ( header.length ) {
4078                                         // anchor within header
4079                                         this.active = header;
4080                                 } else {
4081                                         // anchor within content
4082                                         this.active = current.closest(".ui-accordion-content").prev();
4083                                 }
4084                         }
4085                 }
4087                 this.active = this._findActive(this.active || o.active).toggleClass("ui-state-default").toggleClass("ui-state-active").toggleClass("ui-corner-all").toggleClass("ui-corner-top");
4088                 this.active.next().addClass('ui-accordion-content-active');
4090                 //Append icon elements
4091                 this._createIcons();
4093                 // IE7-/Win - Extra vertical space in lists fixed
4094                 if ($.browser.msie) {
4095                         this.element.find('a').css('zoom', '1');
4096                 }
4098                 this.resize();
4100                 //ARIA
4101                 this.element.attr('role','tablist');
4103                 this.headers
4104                         .attr('role','tab')
4105                         .bind('keydown', function(event) { return self._keydown(event); })
4106                         .next()
4107                         .attr('role','tabpanel');
4109                 this.headers
4110                         .not(this.active || "")
4111                         .attr('aria-expanded','false')
4112                         .attr("tabIndex", "-1")
4113                         .next()
4114                         .hide();
4116                 // make sure at least one header is in the tab order
4117                 if (!this.active.length) {
4118                         this.headers.eq(0).attr('tabIndex','0');
4119                 } else {
4120                         this.active
4121                                 .attr('aria-expanded','true')
4122                                 .attr('tabIndex', '0');
4123                 }
4125                 // only need links in taborder for Safari
4126                 if (!$.browser.safari)
4127                         this.headers.find('a').attr('tabIndex','-1');
4129                 if (o.event) {
4130                         this.headers.bind((o.event) + ".accordion", function(event) {
4131                                 self._clickHandler.call(self, event, this);
4132                                 event.preventDefault();
4133                         });
4134                 }
4136         },
4137         
4138         _createIcons: function() {
4139                 var o = this.options;
4140                 if (o.icons) {
4141                         $("<span/>").addClass("ui-icon " + o.icons.header).prependTo(this.headers);
4142                         this.active.find(".ui-icon").toggleClass(o.icons.header).toggleClass(o.icons.headerSelected);
4143                         this.element.addClass("ui-accordion-icons");
4144                 }
4145         },
4146         
4147         _destroyIcons: function() {
4148                 this.headers.children(".ui-icon").remove();
4149                 this.element.removeClass("ui-accordion-icons");
4150         },
4152         destroy: function() {
4153                 var o = this.options;
4155                 this.element
4156                         .removeClass("ui-accordion ui-widget ui-helper-reset")
4157                         .removeAttr("role")
4158                         .unbind('.accordion')
4159                         .removeData('accordion');
4161                 this.headers
4162                         .unbind(".accordion")
4163                         .removeClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-corner-top")
4164                         .removeAttr("role").removeAttr("aria-expanded").removeAttr("tabindex");
4166                 this.headers.find("a").removeAttr("tabindex");
4167                 this._destroyIcons();
4168                 var contents = this.headers.next().css("display", "").removeAttr("role").removeClass("ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active");
4169                 if (o.autoHeight || o.fillHeight) {
4170                         contents.css("height", "");
4171                 }
4173                 return this;
4174         },
4175         
4176         _setOption: function(key, value) {
4177                 $.Widget.prototype._setOption.apply(this, arguments);
4178                         
4179                 if (key == "active") {
4180                         this.activate(value);
4181                 }
4182                 if (key == "icons") {
4183                         this._destroyIcons();
4184                         if (value) {
4185                                 this._createIcons();
4186                         }
4187                 }
4188                 
4189         },
4191         _keydown: function(event) {
4193                 var o = this.options, keyCode = $.ui.keyCode;
4195                 if (o.disabled || event.altKey || event.ctrlKey)
4196                         return;
4198                 var length = this.headers.length;
4199                 var currentIndex = this.headers.index(event.target);
4200                 var toFocus = false;
4202                 switch(event.keyCode) {
4203                         case keyCode.RIGHT:
4204                         case keyCode.DOWN:
4205                                 toFocus = this.headers[(currentIndex + 1) % length];
4206                                 break;
4207                         case keyCode.LEFT:
4208                         case keyCode.UP:
4209                                 toFocus = this.headers[(currentIndex - 1 + length) % length];
4210                                 break;
4211                         case keyCode.SPACE:
4212                         case keyCode.ENTER:
4213                                 this._clickHandler({ target: event.target }, event.target);
4214                                 event.preventDefault();
4215                 }
4217                 if (toFocus) {
4218                         $(event.target).attr('tabIndex','-1');
4219                         $(toFocus).attr('tabIndex','0');
4220                         toFocus.focus();
4221                         return false;
4222                 }
4224                 return true;
4226         },
4228         resize: function() {
4230                 var o = this.options, maxHeight;
4232                 if (o.fillSpace) {
4233                         
4234                         if($.browser.msie) { var defOverflow = this.element.parent().css('overflow'); this.element.parent().css('overflow', 'hidden'); }
4235                         maxHeight = this.element.parent().height();
4236                         if($.browser.msie) { this.element.parent().css('overflow', defOverflow); }
4237         
4238                         this.headers.each(function() {
4239                                 maxHeight -= $(this).outerHeight(true);
4240                         });
4242                         this.headers.next().each(function() {
4243                    $(this).height(Math.max(0, maxHeight - $(this).innerHeight() + $(this).height()));
4244                         }).css('overflow', 'auto');
4246                 } else if ( o.autoHeight ) {
4247                         maxHeight = 0;
4248                         this.headers.next().each(function() {
4249                                 maxHeight = Math.max(maxHeight, $(this).height());
4250                         }).height(maxHeight);
4251                 }
4253                 return this;
4254         },
4256         activate: function(index) {
4257                 // TODO this gets called on init, changing the option without an explicit call for that
4258                 this.options.active = index;
4259                 // call clickHandler with custom event
4260                 var active = this._findActive(index)[0];
4261                 this._clickHandler({ target: active }, active);
4263                 return this;
4264         },
4266         _findActive: function(selector) {
4267                 return selector
4268                         ? typeof selector == "number"
4269                                 ? this.headers.filter(":eq(" + selector + ")")
4270                                 : this.headers.not(this.headers.not(selector))
4271                         : selector === false
4272                                 ? $([])
4273                                 : this.headers.filter(":eq(0)");
4274         },
4276         // TODO isn't event.target enough? why the seperate target argument?
4277         _clickHandler: function(event, target) {
4279                 var o = this.options;
4280                 if (o.disabled)
4281                         return;
4283                 // called only when using activate(false) to close all parts programmatically
4284                 if (!event.target) {
4285                         if (!o.collapsible)
4286                                 return;
4287                         this.active.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all")
4288                                 .find(".ui-icon").removeClass(o.icons.headerSelected).addClass(o.icons.header);
4289                         this.active.next().addClass('ui-accordion-content-active');
4290                         var toHide = this.active.next(),
4291                                 data = {
4292                                         options: o,
4293                                         newHeader: $([]),
4294                                         oldHeader: o.active,
4295                                         newContent: $([]),
4296                                         oldContent: toHide
4297                                 },
4298                                 toShow = (this.active = $([]));
4299                         this._toggle(toShow, toHide, data);
4300                         return;
4301                 }
4303                 // get the click target
4304                 var clicked = $(event.currentTarget || target);
4305                 var clickedIsActive = clicked[0] == this.active[0];
4306                 
4307                 // TODO the option is changed, is that correct?
4308                 // TODO if it is correct, shouldn't that happen after determining that the click is valid?
4309                 o.active = o.collapsible && clickedIsActive ? false : $('.ui-accordion-header', this.element).index(clicked);
4311                 // if animations are still active, or the active header is the target, ignore click
4312                 if (this.running || (!o.collapsible && clickedIsActive)) {
4313                         return;
4314                 }
4316                 // switch classes
4317                 this.active.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all")
4318                         .find(".ui-icon").removeClass(o.icons.headerSelected).addClass(o.icons.header);
4319                 if (!clickedIsActive) {
4320                         clicked.removeClass("ui-state-default ui-corner-all").addClass("ui-state-active ui-corner-top")
4321                                 .find(".ui-icon").removeClass(o.icons.header).addClass(o.icons.headerSelected);
4322                         clicked.next().addClass('ui-accordion-content-active');
4323                 }
4325                 // find elements to show and hide
4326                 var toShow = clicked.next(),
4327                         toHide = this.active.next(),
4328                         data = {
4329                                 options: o,
4330                                 newHeader: clickedIsActive && o.collapsible ? $([]) : clicked,
4331                                 oldHeader: this.active,
4332                                 newContent: clickedIsActive && o.collapsible ? $([]) : toShow,
4333                                 oldContent: toHide
4334                         },
4335                         down = this.headers.index( this.active[0] ) > this.headers.index( clicked[0] );
4337                 this.active = clickedIsActive ? $([]) : clicked;
4338                 this._toggle(toShow, toHide, data, clickedIsActive, down);
4340                 return;
4342         },
4344         _toggle: function(toShow, toHide, data, clickedIsActive, down) {
4346                 var o = this.options, self = this;
4348                 this.toShow = toShow;
4349                 this.toHide = toHide;
4350                 this.data = data;
4352                 var complete = function() { if(!self) return; return self._completed.apply(self, arguments); };
4354                 // trigger changestart event
4355                 this._trigger("changestart", null, this.data);
4357                 // count elements to animate
4358                 this.running = toHide.size() === 0 ? toShow.size() : toHide.size();
4360                 if (o.animated) {
4362                         var animOptions = {};
4364                         if ( o.collapsible && clickedIsActive ) {
4365                                 animOptions = {
4366                                         toShow: $([]),
4367                                         toHide: toHide,
4368                                         complete: complete,
4369                                         down: down,
4370                                         autoHeight: o.autoHeight || o.fillSpace
4371                                 };
4372                         } else {
4373                                 animOptions = {
4374                                         toShow: toShow,
4375                                         toHide: toHide,
4376                                         complete: complete,
4377                                         down: down,
4378                                         autoHeight: o.autoHeight || o.fillSpace
4379                                 };
4380                         }
4382                         if (!o.proxied) {
4383                                 o.proxied = o.animated;
4384                         }
4386                         if (!o.proxiedDuration) {
4387                                 o.proxiedDuration = o.duration;
4388                         }
4390                         o.animated = $.isFunction(o.proxied) ?
4391                                 o.proxied(animOptions) : o.proxied;
4393                         o.duration = $.isFunction(o.proxiedDuration) ?
4394                                 o.proxiedDuration(animOptions) : o.proxiedDuration;
4396                         var animations = $.ui.accordion.animations,
4397                                 duration = o.duration,
4398                                 easing = o.animated;
4400                         if (easing && !animations[easing] && !$.easing[easing]) {
4401                                 easing = 'slide';
4402                         }
4403                         if (!animations[easing]) {
4404                                 animations[easing] = function(options) {
4405                                         this.slide(options, {
4406                                                 easing: easing,
4407                                                 duration: duration || 700
4408                                         });
4409                                 };
4410                         }
4412                         animations[easing](animOptions);
4414                 } else {
4416                         if (o.collapsible && clickedIsActive) {
4417                                 toShow.toggle();
4418                         } else {
4419                                 toHide.hide();
4420                                 toShow.show();
4421                         }
4423                         complete(true);
4425                 }
4427                 // TODO assert that the blur and focus triggers are really necessary, remove otherwise
4428                 toHide.prev().attr('aria-expanded','false').attr("tabIndex", "-1").blur();
4429                 toShow.prev().attr('aria-expanded','true').attr("tabIndex", "0").focus();
4431         },
4433         _completed: function(cancel) {
4435                 var o = this.options;
4437                 this.running = cancel ? 0 : --this.running;
4438                 if (this.running) return;
4440                 if (o.clearStyle) {
4441                         this.toShow.add(this.toHide).css({
4442                                 height: "",
4443                                 overflow: ""
4444                         });
4445                 }
4446                 
4447                 // other classes are removed before the animation; this one needs to stay until completed
4448                 this.toHide.removeClass("ui-accordion-content-active");
4450                 this._trigger('change', null, this.data);
4451         }
4456 $.extend($.ui.accordion, {
4457         version: "1.8",
4458         animations: {
4459                 slide: function(options, additions) {
4460                         options = $.extend({
4461                                 easing: "swing",
4462                                 duration: 300
4463                         }, options, additions);
4464                         if ( !options.toHide.size() ) {
4465                                 options.toShow.animate({height: "show"}, options);
4466                                 return;
4467                         }
4468                         if ( !options.toShow.size() ) {
4469                                 options.toHide.animate({height: "hide"}, options);
4470                                 return;
4471                         }
4472                         var overflow = options.toShow.css('overflow'),
4473                                 percentDone = 0,
4474                                 showProps = {},
4475                                 hideProps = {},
4476                                 fxAttrs = [ "height", "paddingTop", "paddingBottom" ],
4477                                 originalWidth;
4478                         // fix width before calculating height of hidden element
4479                         var s = options.toShow;
4480                         originalWidth = s[0].style.width;
4481                         s.width( parseInt(s.parent().width(),10) - parseInt(s.css("paddingLeft"),10) - parseInt(s.css("paddingRight"),10) - (parseInt(s.css("borderLeftWidth"),10) || 0) - (parseInt(s.css("borderRightWidth"),10) || 0) );
4482                         
4483                         $.each(fxAttrs, function(i, prop) {
4484                                 hideProps[prop] = 'hide';
4485                                 
4486                                 var parts = ('' + $.css(options.toShow[0], prop)).match(/^([\d+-.]+)(.*)$/);
4487                                 showProps[prop] = {
4488                                         value: parts[1],
4489                                         unit: parts[2] || 'px'
4490                                 };
4491                         });
4492                         options.toShow.css({ height: 0, overflow: 'hidden' }).show();
4493                         options.toHide.filter(":hidden").each(options.complete).end().filter(":visible").animate(hideProps,{
4494                                 step: function(now, settings) {
4495                                         // only calculate the percent when animating height
4496                                         // IE gets very inconsistent results when animating elements
4497                                         // with small values, which is common for padding
4498                                         if (settings.prop == 'height') {
4499                                                 percentDone = ( settings.end - settings.start === 0 ) ? 0 :
4500                                                         (settings.now - settings.start) / (settings.end - settings.start);
4501                                         }
4502                                         
4503                                         options.toShow[0].style[settings.prop] =
4504                                                 (percentDone * showProps[settings.prop].value) + showProps[settings.prop].unit;
4505                                 },
4506                                 duration: options.duration,
4507                                 easing: options.easing,
4508                                 complete: function() {
4509                                         if ( !options.autoHeight ) {
4510                                                 options.toShow.css("height", "");
4511                                         }
4512                                         options.toShow.css("width", originalWidth);
4513                                         options.toShow.css({overflow: overflow});
4514                                         options.complete();
4515                                 }
4516                         });
4517                 },
4518                 bounceslide: function(options) {
4519                         this.slide(options, {
4520                                 easing: options.down ? "easeOutBounce" : "swing",
4521                                 duration: options.down ? 1000 : 200
4522                         });
4523                 }
4524         }
4527 })(jQuery);
4529  * jQuery UI Autocomplete 1.8
4531  * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
4532  * Dual licensed under the MIT (MIT-LICENSE.txt)
4533  * and GPL (GPL-LICENSE.txt) licenses.
4535  * http://docs.jquery.com/UI/Autocomplete
4537  * Depends:
4538  *      jquery.ui.core.js
4539  *      jquery.ui.widget.js
4540  *      jquery.ui.position.js
4541  */
4542 (function( $ ) {
4544 $.widget( "ui.autocomplete", {
4545         options: {
4546                 minLength: 1,
4547                 delay: 300
4548         },
4549         _create: function() {
4550                 var self = this,
4551                         doc = this.element[ 0 ].ownerDocument;
4552                 this.element
4553                         .addClass( "ui-autocomplete-input" )
4554                         .attr( "autocomplete", "off" )
4555                         // TODO verify these actually work as intended
4556                         .attr({
4557                                 role: "textbox",
4558                                 "aria-autocomplete": "list",
4559                                 "aria-haspopup": "true"
4560                         })
4561                         .bind( "keydown.autocomplete", function( event ) {
4562                                 var keyCode = $.ui.keyCode;
4563                                 switch( event.keyCode ) {
4564                                 case keyCode.PAGE_UP:
4565                                         self._move( "previousPage", event );
4566                                         break;
4567                                 case keyCode.PAGE_DOWN:
4568                                         self._move( "nextPage", event );
4569                                         break;
4570                                 case keyCode.UP:
4571                                         self._move( "previous", event );
4572                                         // prevent moving cursor to beginning of text field in some browsers
4573                                         event.preventDefault();
4574                                         break;
4575                                 case keyCode.DOWN:
4576                                         self._move( "next", event );
4577                                         // prevent moving cursor to end of text field in some browsers
4578                                         event.preventDefault();
4579                                         break;
4580                                 case keyCode.ENTER:
4581                                         // when menu is open or has focus
4582                                         if ( self.menu.active ) {
4583                                                 event.preventDefault();
4584                                         }
4585                                         //passthrough - ENTER and TAB both select the current element
4586                                 case keyCode.TAB:
4587                                         if ( !self.menu.active ) {
4588                                                 return;
4589                                         }
4590                                         self.menu.select();
4591                                         break;
4592                                 case keyCode.ESCAPE:
4593                                         self.element.val( self.term );
4594                                         self.close( event );
4595                                         break;
4596                                 case keyCode.SHIFT:
4597                                 case keyCode.CONTROL:
4598                                 case 18:
4599                                         // ignore metakeys (shift, ctrl, alt)
4600                                         break;
4601                                 default:
4602                                         // keypress is triggered before the input value is changed
4603                                         clearTimeout( self.searching );
4604                                         self.searching = setTimeout(function() {
4605                                                 self.search( null, event );
4606                                         }, self.options.delay );
4607                                         break;
4608                                 }
4609                         })
4610                         .bind( "focus.autocomplete", function() {
4611                                 self.previous = self.element.val();
4612                         })
4613                         .bind( "blur.autocomplete", function( event ) {
4614                                 clearTimeout( self.searching );
4615                                 // clicks on the menu (or a button to trigger a search) will cause a blur event
4616                                 // TODO try to implement this without a timeout, see clearTimeout in search()
4617                                 self.closing = setTimeout(function() {
4618                                         self.close( event );
4619                                 }, 150 );
4620                         });
4621                 this._initSource();
4622                 this.response = function() {
4623                         return self._response.apply( self, arguments );
4624                 };
4625                 this.menu = $( "<ul></ul>" )
4626                         .addClass( "ui-autocomplete" )
4627                         .appendTo( "body", doc )
4628                         .menu({
4629                                 focus: function( event, ui ) {
4630                                         var item = ui.item.data( "item.autocomplete" );
4631                                         if ( false !== self._trigger( "focus", null, { item: item } ) ) {
4632                                                 // use value to match what will end up in the input
4633                                                 self.element.val( item.value );
4634                                         }
4635                                 },
4636                                 selected: function( event, ui ) {
4637                                         var item = ui.item.data( "item.autocomplete" );
4638                                         if ( false !== self._trigger( "select", event, { item: item } ) ) {
4639                                                 self.element.val( item.value );
4640                                         }
4641                                         self.close( event );
4642                                         self.previous = self.element.val();
4643                                         // only trigger when focus was lost (click on menu)
4644                                         if ( self.element[0] !== doc.activeElement ) {
4645                                                 self.element.focus();
4646                                         }
4647                                 },
4648                                 blur: function( event, ui ) {
4649                                         if ( self.menu.element.is(":visible") ) {
4650                                                 self.element.val( self.term );
4651                                         }
4652                                 }
4653                         })
4654                         .zIndex( this.element.zIndex() + 1 )
4655                         // workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
4656                         .css({ top: 0, left: 0 })
4657                         .hide()
4658                         .data( "menu" );
4659                 if ( $.fn.bgiframe ) {
4660                          this.menu.element.bgiframe();
4661                 }
4662         },
4664         destroy: function() {
4665                 this.element
4666                         .removeClass( "ui-autocomplete-input ui-widget ui-widget-content" )
4667                         .removeAttr( "autocomplete" )
4668                         .removeAttr( "role" )
4669                         .removeAttr( "aria-autocomplete" )
4670                         .removeAttr( "aria-haspopup" );
4671                 this.menu.element.remove();
4672                 $.Widget.prototype.destroy.call( this );
4673         },
4675         _setOption: function( key ) {
4676                 $.Widget.prototype._setOption.apply( this, arguments );
4677                 if ( key === "source" ) {
4678                         this._initSource();
4679                 }
4680         },
4682         _initSource: function() {
4683                 var array,
4684                         url;
4685                 if ( $.isArray(this.options.source) ) {
4686                         array = this.options.source;
4687                         this.source = function( request, response ) {
4688                                 // escape regex characters
4689                                 var matcher = new RegExp( $.ui.autocomplete.escapeRegex(request.term), "i" );
4690                                 response( $.grep( array, function(value) {
4691                                         return matcher.test( value.label || value.value || value );
4692                                 }) );
4693                         };
4694                 } else if ( typeof this.options.source === "string" ) {
4695                         url = this.options.source;
4696                         this.source = function( request, response ) {
4697                                 $.getJSON( url, request, response );
4698                         };
4699                 } else {
4700                         this.source = this.options.source;
4701                 }
4702         },
4704         search: function( value, event ) {
4705                 value = value != null ? value : this.element.val();
4706                 if ( value.length < this.options.minLength ) {
4707                         return this.close( event );
4708                 }
4710                 clearTimeout( this.closing );
4711                 if ( this._trigger("search") === false ) {
4712                         return;
4713                 }
4715                 return this._search( value );
4716         },
4718         _search: function( value ) {
4719                 this.term = this.element
4720                         .addClass( "ui-autocomplete-loading" )
4721                         // always save the actual value, not the one passed as an argument
4722                         .val();
4724                 this.source( { term: value }, this.response );
4725         },
4727         _response: function( content ) {
4728                 if ( content.length ) {
4729                         content = this._normalize( content );
4730                         this._suggest( content );
4731                         this._trigger( "open" );
4732                 } else {
4733                         this.close();
4734                 }
4735                 this.element.removeClass( "ui-autocomplete-loading" );
4736         },
4738         close: function( event ) {
4739                 clearTimeout( this.closing );
4740                 if ( this.menu.element.is(":visible") ) {
4741                         this._trigger( "close", event );
4742                         this.menu.element.hide();
4743                         this.menu.deactivate();
4744                 }
4745                 if ( this.previous !== this.element.val() ) {
4746                         this._trigger( "change", event );
4747                 }
4748         },
4750         _normalize: function( items ) {
4751                 // assume all items have the right format when the first item is complete
4752                 if ( items.length && items[0].label && items[0].value ) {
4753                         return items;
4754                 }
4755                 return $.map( items, function(item) {
4756                         if ( typeof item === "string" ) {
4757                                 return {
4758                                         label: item,
4759                                         value: item
4760                                 };
4761                         }
4762                         return $.extend({
4763                                 label: item.label || item.value,
4764                                 value: item.value || item.label
4765                         }, item );
4766                 });
4767         },
4769         _suggest: function( items ) {
4770                 var ul = this.menu.element
4771                                 .empty()
4772                                 .zIndex( this.element.zIndex() + 1 ),
4773                         menuWidth,
4774                         textWidth;
4775                 this._renderMenu( ul, items );
4776                 // TODO refresh should check if the active item is still in the dom, removing the need for a manual deactivate
4777                 this.menu.deactivate();
4778                 this.menu.refresh();
4779                 this.menu.element.show().position({
4780                         my: "left top",
4781                         at: "left bottom",
4782                         of: this.element,
4783                         collision: "none"
4784                 });
4786                 menuWidth = ul.width( "" ).width();
4787                 textWidth = this.element.width();
4788                 ul.width( Math.max( menuWidth, textWidth ) );
4789         },
4790         
4791         _renderMenu: function( ul, items ) {
4792                 var self = this;
4793                 $.each( items, function( index, item ) {
4794                         self._renderItem( ul, item );
4795                 });
4796         },
4798         _renderItem: function( ul, item) {
4799                 return $( "<li></li>" )
4800                         .data( "item.autocomplete", item )
4801                         .append( "<a>" + item.label + "</a>" )
4802                         .appendTo( ul );
4803         },
4805         _move: function( direction, event ) {
4806                 if ( !this.menu.element.is(":visible") ) {
4807                         this.search( null, event );
4808                         return;
4809                 }
4810                 if ( this.menu.first() && /^previous/.test(direction) ||
4811                                 this.menu.last() && /^next/.test(direction) ) {
4812                         this.element.val( this.term );
4813                         this.menu.deactivate();
4814                         return;
4815                 }
4816                 this.menu[ direction ]();
4817         },
4819         widget: function() {
4820                 return this.menu.element;
4821         }
4824 $.extend( $.ui.autocomplete, {
4825         escapeRegex: function( value ) {
4826                 return value.replace( /([\^\$\(\)\[\]\{\}\*\.\+\?\|\\])/gi, "\\$1" );
4827         }
4830 }( jQuery ));
4833  * jQuery UI Menu (not officially released)
4834  * 
4835  * This widget isn't yet finished and the API is subject to change. We plan to finish
4836  * it for the next release. You're welcome to give it a try anyway and give us feedback,
4837  * as long as you're okay with migrating your code later on. We can help with that, too.
4839  * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
4840  * Dual licensed under the MIT (MIT-LICENSE.txt)
4841  * and GPL (GPL-LICENSE.txt) licenses.
4843  * http://docs.jquery.com/UI/Menu
4845  * Depends:
4846  *      jquery.ui.core.js
4847  *  jquery.ui.widget.js
4848  */
4849 (function($) {
4851 $.widget("ui.menu", {
4852         _create: function() {
4853                 var self = this;
4854                 this.element
4855                         .addClass("ui-menu ui-widget ui-widget-content ui-corner-all")
4856                         .attr({
4857                                 role: "listbox",
4858                                 "aria-activedescendant": "ui-active-menuitem"
4859                         })
4860                         .click(function(e) {
4861                                 // temporary
4862                                 e.preventDefault();
4863                                 self.select();
4864                         });
4865                 this.refresh();
4866         },
4867         
4868         refresh: function() {
4869                 var self = this;
4871                 // don't refresh list items that are already adapted
4872                 var items = this.element.children("li:not(.ui-menu-item):has(a)")
4873                         .addClass("ui-menu-item")
4874                         .attr("role", "menuitem");
4875                 
4876                 items.children("a")
4877                         .addClass("ui-corner-all")
4878                         .attr("tabindex", -1)
4879                         // mouseenter doesn't work with event delegation
4880                         .mouseenter(function() {
4881                                 self.activate($(this).parent());
4882                         })
4883                         .mouseleave(function() {
4884                                 self.deactivate();
4885                         });
4886         },
4888         activate: function(item) {
4889                 this.deactivate();
4890                 if (this.hasScroll()) {
4891                         var offset = item.offset().top - this.element.offset().top,
4892                                 scroll = this.element.attr("scrollTop"),
4893                                 elementHeight = this.element.height();
4894                         if (offset < 0) {
4895                                 this.element.attr("scrollTop", scroll + offset);
4896                         } else if (offset > elementHeight) {
4897                                 this.element.attr("scrollTop", scroll + offset - elementHeight + item.height());
4898                         }
4899                 }
4900                 this.active = item.eq(0)
4901                         .children("a")
4902                                 .addClass("ui-state-hover")
4903                                 .attr("id", "ui-active-menuitem")
4904                         .end();
4905                 this._trigger("focus", null, { item: item });
4906         },
4908         deactivate: function() {
4909                 if (!this.active) { return; }
4911                 this.active.children("a")
4912                         .removeClass("ui-state-hover")
4913                         .removeAttr("id");
4914                 this._trigger("blur");
4915                 this.active = null;
4916         },
4918         next: function() {
4919                 this.move("next", "li:first");
4920         },
4922         previous: function() {
4923                 this.move("prev", "li:last");
4924         },
4926         first: function() {
4927                 return this.active && !this.active.prev().length;
4928         },
4930         last: function() {
4931                 return this.active && !this.active.next().length;
4932         },
4934         move: function(direction, edge) {
4935                 if (!this.active) {
4936                         this.activate(this.element.children(edge));
4937                         return;
4938                 }
4939                 var next = this.active[direction]();
4940                 if (next.length) {
4941                         this.activate(next);
4942                 } else {
4943                         this.activate(this.element.children(edge));
4944                 }
4945         },
4947         // TODO merge with previousPage
4948         nextPage: function() {
4949                 if (this.hasScroll()) {
4950                         // TODO merge with no-scroll-else
4951                         if (!this.active || this.last()) {
4952                                 this.activate(this.element.children(":first"));
4953                                 return;
4954                         }
4955                         var base = this.active.offset().top,
4956                                 height = this.element.height(),
4957                                 result = this.element.children("li").filter(function() {
4958                                         var close = $(this).offset().top - base - height + $(this).height();
4959                                         // TODO improve approximation
4960                                         return close < 10 && close > -10;
4961                                 });
4963                         // TODO try to catch this earlier when scrollTop indicates the last page anyway
4964                         if (!result.length) {
4965                                 result = this.element.children(":last");
4966                         }
4967                         this.activate(result);
4968                 } else {
4969                         this.activate(this.element.children(!this.active || this.last() ? ":first" : ":last"));
4970                 }
4971         },
4973         // TODO merge with nextPage
4974         previousPage: function() {
4975                 if (this.hasScroll()) {
4976                         // TODO merge with no-scroll-else
4977                         if (!this.active || this.first()) {
4978                                 this.activate(this.element.children(":last"));
4979                                 return;
4980                         }
4982                         var base = this.active.offset().top,
4983                                 height = this.element.height();
4984                                 result = this.element.children("li").filter(function() {
4985                                         var close = $(this).offset().top - base + height - $(this).height();
4986                                         // TODO improve approximation
4987                                         return close < 10 && close > -10;
4988                                 });
4990                         // TODO try to catch this earlier when scrollTop indicates the last page anyway
4991                         if (!result.length) {
4992                                 result = this.element.children(":first");
4993                         }
4994                         this.activate(result);
4995                 } else {
4996                         this.activate(this.element.children(!this.active || this.first() ? ":last" : ":first"));
4997                 }
4998         },
5000         hasScroll: function() {
5001                 return this.element.height() < this.element.attr("scrollHeight");
5002         },
5004         select: function() {
5005                 this._trigger("selected", null, { item: this.active });
5006         }
5009 }(jQuery));
5011  * jQuery UI Button 1.8
5013  * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
5014  * Dual licensed under the MIT (MIT-LICENSE.txt)
5015  * and GPL (GPL-LICENSE.txt) licenses.
5017  * http://docs.jquery.com/UI/Button
5019  * Depends:
5020  *      jquery.ui.core.js
5021  *      jquery.ui.widget.js
5022  */
5023 (function( $ ) {
5025 var lastActive,
5026         baseClasses = "ui-button ui-widget ui-state-default ui-corner-all",
5027         otherClasses = "ui-state-hover ui-state-active " +
5028                 "ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon ui-button-text-only",
5029         formResetHandler = function( event ) {
5030                 $( ":ui-button", event.target.form ).each(function() {
5031                         var inst = $( this ).data( "button" );
5032                         setTimeout(function() {
5033                                 inst.refresh();
5034                         }, 1 );
5035                 });
5036         },
5037         radioGroup = function( radio ) {
5038                 var name = radio.name,
5039                         form = radio.form,
5040                         radios = $( [] );
5041                 if ( name ) {
5042                         if ( form ) {
5043                                 radios = $( form ).find( "[name='" + name + "']" );
5044                         } else {
5045                                 radios = $( "[name='" + name + "']", radio.ownerDocument )
5046                                         .filter(function() {
5047                                                 return !this.form;
5048                                         });
5049                         }
5050                 }
5051                 return radios;
5052         };
5054 $.widget( "ui.button", {
5055         options: {
5056                 text: true,
5057                 label: null,
5058                 icons: {
5059                         primary: null,
5060                         secondary: null
5061                 }
5062         },
5063         _create: function() {
5064                 this.element.closest( "form" )
5065                         .unbind( "reset.button" )
5066                         .bind( "reset.button", formResetHandler );
5068                 this._determineButtonType();
5069                 this.hasTitle = !!this.buttonElement.attr( "title" );
5071                 var self = this,
5072                         options = this.options,
5073                         toggleButton = this.type === "checkbox" || this.type === "radio",
5074                         hoverClass = "ui-state-hover" + ( !toggleButton ? " ui-state-active" : "" ),
5075                         focusClass = "ui-state-focus";
5077                 if ( options.label === null ) {
5078                         options.label = this.buttonElement.html();
5079                 }
5081                 if ( this.element.is( ":disabled" ) ) {
5082                         options.disabled = true;
5083                 }
5085                 this.buttonElement
5086                         .addClass( baseClasses )
5087                         .attr( "role", "button" )
5088                         .bind( "mouseenter.button", function() {
5089                                 if ( options.disabled ) {
5090                                         return;
5091                                 }
5092                                 $( this ).addClass( "ui-state-hover" );
5093                                 if ( this === lastActive ) {
5094                                         $( this ).addClass( "ui-state-active" );
5095                                 }
5096                         })
5097                         .bind( "mouseleave.button", function() {
5098                                 if ( options.disabled ) {
5099                                         return;
5100                                 }
5101                                 $( this ).removeClass( hoverClass );
5102                         })
5103                         .bind( "focus.button", function() {
5104                                 // no need to check disabled, focus won't be triggered anyway
5105                                 $( this ).addClass( focusClass );
5106                         })
5107                         .bind( "blur.button", function() {
5108                                 $( this ).removeClass( focusClass );
5109                         });
5111                 if ( toggleButton ) {
5112                         this.element.bind( "change.button", function() {
5113                                 self.refresh();
5114                         });
5115                 }
5117                 if ( this.type === "checkbox" ) {
5118                         this.buttonElement.bind( "click.button", function() {
5119                                 if ( options.disabled ) {
5120                                         return false;
5121                                 }
5122                                 $( this ).toggleClass( "ui-state-active" );
5123                                 self.buttonElement.attr( "aria-pressed", self.element[0].checked );
5124                         });
5125                 } else if ( this.type === "radio" ) {
5126                         this.buttonElement.bind( "click.button", function() {
5127                                 if ( options.disabled ) {
5128                                         return false;
5129                                 }
5130                                 $( this ).addClass( "ui-state-active" );
5131                                 self.buttonElement.attr( "aria-pressed", true );
5133                                 var radio = self.element[ 0 ];
5134                                 radioGroup( radio )
5135                                         .not( radio )
5136                                         .map(function() {
5137                                                 return $( this ).button( "widget" )[ 0 ];
5138                                         })
5139                                         .removeClass( "ui-state-active" )
5140                                         .attr( "aria-pressed", false );
5141                         });
5142                 } else {
5143                         this.buttonElement
5144                                 .bind( "mousedown.button", function() {
5145                                         if ( options.disabled ) {
5146                                                 return false;
5147                                         }
5148                                         $( this ).addClass( "ui-state-active" );
5149                                         lastActive = this;
5150                                         $( document ).one( "mouseup", function() {
5151                                                 lastActive = null;
5152                                         });
5153                                 })
5154                                 .bind( "mouseup.button", function() {
5155                                         if ( options.disabled ) {
5156                                                 return false;
5157                                         }
5158                                         $( this ).removeClass( "ui-state-active" );
5159                                 })
5160                                 .bind( "keydown.button", function(event) {
5161                                         if ( options.disabled ) {
5162                                                 return false;
5163                                         }
5164                                         if ( event.keyCode == $.ui.keyCode.SPACE || event.keyCode == $.ui.keyCode.ENTER ) {
5165                                                 $( this ).addClass( "ui-state-active" );
5166                                         }
5167                                 })
5168                                 .bind( "keyup.button", function() {
5169                                         $( this ).removeClass( "ui-state-active" );
5170                                 });
5172                         if ( this.buttonElement.is("a") ) {
5173                                 this.buttonElement.keyup(function(event) {
5174                                         if ( event.keyCode === $.ui.keyCode.SPACE ) {
5175                                                 // TODO pass through original event correctly (just as 2nd argument doesn't work)
5176                                                 $( this ).click();
5177                                         }
5178                                 });
5179                         }
5180                 }
5182                 // TODO: pull out $.Widget's handling for the disabled option into
5183                 // $.Widget.prototype._setOptionDisabled so it's easy to proxy and can
5184                 // be overridden by individual plugins
5185                 this._setOption( "disabled", options.disabled );
5186         },
5188         _determineButtonType: function() {
5189                 
5190                 if ( this.element.is(":checkbox") ) {
5191                         this.type = "checkbox";
5192                 } else {
5193                         if ( this.element.is(":radio") ) {
5194                                 this.type = "radio";
5195                         } else {
5196                                 if ( this.element.is("input") ) {
5197                                         this.type = "input";
5198                                 } else {
5199                                         this.type = "button";
5200                                 }
5201                         }
5202                 }
5203                 
5204                 if ( this.type === "checkbox" || this.type === "radio" ) {
5205                         // we don't search against the document in case the element
5206                         // is disconnected from the DOM
5207                         this.buttonElement = this.element.parents().last()
5208                                 .find( "[for=" + this.element.attr("id") + "]" );
5209                         this.element.addClass( "ui-helper-hidden-accessible" );
5211                         var checked = this.element.is( ":checked" );
5212                         if ( checked ) {
5213                                 this.buttonElement.addClass( "ui-state-active" );
5214                         }
5215                         this.buttonElement.attr( "aria-pressed", checked );
5216                 } else {
5217                         this.buttonElement = this.element;
5218                 }
5219         },
5221         widget: function() {
5222                 return this.buttonElement;
5223         },
5225         destroy: function() {
5226                 this.element
5227                         .removeClass( "ui-helper-hidden-accessible" );
5228                 this.buttonElement
5229                         .removeClass( baseClasses + " " + otherClasses )
5230                         .removeAttr( "role" )
5231                         .removeAttr( "aria-pressed" )
5232                         .html( this.buttonElement.find(".ui-button-text").html() );
5234                 if ( !this.hasTitle ) {
5235                         this.buttonElement.removeAttr( "title" );
5236                 }
5238                 $.Widget.prototype.destroy.call( this );
5239         },
5241         _setOption: function( key, value ) {
5242                 $.Widget.prototype._setOption.apply( this, arguments );
5243                 if ( key === "disabled" ) {
5244                         if ( value ) {
5245                                 this.element.attr( "disabled", true );
5246                         } else {
5247                                 this.element.removeAttr( "disabled" );
5248                         }
5249                 }
5250                 this._resetButton();
5251         },
5253         refresh: function() {
5254                 var isDisabled = this.element.is( ":disabled" );
5255                 if ( isDisabled !== this.options.disabled ) {
5256                         this._setOption( "disabled", isDisabled );
5257                 }
5258                 if ( this.type === "radio" ) {
5259                         radioGroup( this.element[0] ).each(function() {
5260                                 if ( $( this ).is( ":checked" ) ) {
5261                                         $( this ).button( "widget" )
5262                                                 .addClass( "ui-state-active" )
5263                                                 .attr( "aria-pressed", true );
5264                                 } else {
5265                                         $( this ).button( "widget" )
5266                                                 .removeClass( "ui-state-active" )
5267                                                 .attr( "aria-pressed", false );
5268                                 }
5269                         });
5270                 } else if ( this.type === "checkbox" ) {
5271                         if ( this.element.is( ":checked" ) ) {
5272                                 this.buttonElement
5273                                         .addClass( "ui-state-active" )
5274                                         .attr( "aria-pressed", true );
5275                         } else {
5276                                 this.buttonElement
5277                                         .removeClass( "ui-state-active" )
5278                                         .attr( "aria-pressed", false );
5279                         }
5280                 }
5281         },
5283         _resetButton: function() {
5284                 if ( this.type === "input" ) {
5285                         if ( this.options.label ) {
5286                                 this.element.val( this.options.label );
5287                         }
5288                         return;
5289                 }
5290                 var buttonElement = this.buttonElement,
5291                         buttonText = $( "<span></span>" )
5292                                 .addClass( "ui-button-text" )
5293                                 .html( this.options.label )
5294                                 .appendTo( buttonElement.empty() )
5295                                 .text(),
5296                         icons = this.options.icons,
5297                         multipleIcons = icons.primary && icons.secondary;
5298                 if ( icons.primary || icons.secondary ) {
5299                         buttonElement.addClass( "ui-button-text-icon" +
5300                                 ( multipleIcons ? "s" : "" ) );
5301                         if ( icons.primary ) {
5302                                 buttonElement.prepend( "<span class='ui-button-icon-primary ui-icon " + icons.primary + "'></span>" );
5303                         }
5304                         if ( icons.secondary ) {
5305                                 buttonElement.append( "<span class='ui-button-icon-secondary ui-icon " + icons.secondary + "'></span>" );
5306                         }
5307                         if ( !this.options.text ) {
5308                                 buttonElement
5309                                         .addClass( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" )
5310                                         .removeClass( "ui-button-text-icons ui-button-text-icon" );
5311                                 if ( !this.hasTitle ) {
5312                                         buttonElement.attr( "title", buttonText );
5313                                 }
5314                         }
5315                 } else {
5316                         buttonElement.addClass( "ui-button-text-only" );
5317                 }
5318         }
5321 $.widget( "ui.buttonset", {
5322         _create: function() {
5323                 this.element.addClass( "ui-buttonset" );
5324                 this._init();
5325         },
5326         
5327         _init: function() {
5328                 this.refresh();
5329         },
5331         _setOption: function( key, value ) {
5332                 if ( key === "disabled" ) {
5333                         this.buttons.button( "option", key, value );
5334                 }
5336                 $.Widget.prototype._setOption.apply( this, arguments );
5337         },
5338         
5339         refresh: function() {
5340                 this.buttons = this.element.find( ":button, :submit, :reset, :checkbox, :radio, a, :data(button)" )
5341                         .filter( ":ui-button" )
5342                                 .button( "refresh" )
5343                         .end()
5344                         .not( ":ui-button" )
5345                                 .button()
5346                         .end()
5347                         .map(function() {
5348                                 return $( this ).button( "widget" )[ 0 ];
5349                         })
5350                                 .removeClass( "ui-corner-all ui-corner-left ui-corner-right" )
5351                                 .filter( ":first" )
5352                                         .addClass( "ui-corner-left" )
5353                                 .end()
5354                                 .filter( ":last" )
5355                                         .addClass( "ui-corner-right" )
5356                                 .end()
5357                         .end();
5358         },
5360         destroy: function() {
5361                 this.element.removeClass( "ui-buttonset" );
5362                 this.buttons
5363                         .map(function() {
5364                                 return $( this ).button( "widget" )[ 0 ];
5365                         })
5366                                 .removeClass( "ui-corner-left ui-corner-right" )
5367                         .end()
5368                         .button( "destroy" )
5370                 $.Widget.prototype.destroy.call( this );
5371         }
5374 }( jQuery ) );
5376  * jQuery UI Dialog 1.8
5378  * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
5379  * Dual licensed under the MIT (MIT-LICENSE.txt)
5380  * and GPL (GPL-LICENSE.txt) licenses.
5382  * http://docs.jquery.com/UI/Dialog
5384  * Depends:
5385  *      jquery.ui.core.js
5386  *      jquery.ui.widget.js
5387  *  jquery.ui.button.js
5388  *      jquery.ui.draggable.js
5389  *      jquery.ui.mouse.js
5390  *      jquery.ui.position.js
5391  *      jquery.ui.resizable.js
5392  */
5393 (function($) {
5395 var uiDialogClasses =
5396         'ui-dialog ' +
5397         'ui-widget ' +
5398         'ui-widget-content ' +
5399         'ui-corner-all ';
5401 $.widget("ui.dialog", {
5402         options: {
5403                 autoOpen: true,
5404                 buttons: {},
5405                 closeOnEscape: true,
5406                 closeText: 'close',
5407                 dialogClass: '',
5408                 draggable: true,
5409                 hide: null,
5410                 height: 'auto',
5411                 maxHeight: false,
5412                 maxWidth: false,
5413                 minHeight: 150,
5414                 minWidth: 150,
5415                 modal: false,
5416                 position: 'center',
5417                 resizable: true,
5418                 show: null,
5419                 stack: true,
5420                 title: '',
5421                 width: 300,
5422                 zIndex: 1000
5423         },
5424         _create: function() {
5425                 this.originalTitle = this.element.attr('title');
5427                 var self = this,
5428                         options = self.options,
5430                         title = options.title || self.originalTitle || '&#160;',
5431                         titleId = $.ui.dialog.getTitleId(self.element),
5433                         uiDialog = (self.uiDialog = $('<div></div>'))
5434                                 .appendTo(document.body)
5435                                 .hide()
5436                                 .addClass(uiDialogClasses + options.dialogClass)
5437                                 .css({
5438                                         zIndex: options.zIndex
5439                                 })
5440                                 // setting tabIndex makes the div focusable
5441                                 // setting outline to 0 prevents a border on focus in Mozilla
5442                                 .attr('tabIndex', -1).css('outline', 0).keydown(function(event) {
5443                                         if (options.closeOnEscape && event.keyCode &&
5444                                                 event.keyCode === $.ui.keyCode.ESCAPE) {
5445                                                 
5446                                                 self.close(event);
5447                                                 event.preventDefault();
5448                                         }
5449                                 })
5450                                 .attr({
5451                                         role: 'dialog',
5452                                         'aria-labelledby': titleId
5453                                 })
5454                                 .mousedown(function(event) {
5455                                         self.moveToTop(false, event);
5456                                 }),
5458                         uiDialogContent = self.element
5459                                 .show()
5460                                 .removeAttr('title')
5461                                 .addClass(
5462                                         'ui-dialog-content ' +
5463                                         'ui-widget-content')
5464                                 .appendTo(uiDialog),
5466                         uiDialogTitlebar = (self.uiDialogTitlebar = $('<div></div>'))
5467                                 .addClass(
5468                                         'ui-dialog-titlebar ' +
5469                                         'ui-widget-header ' +
5470                                         'ui-corner-all ' +
5471                                         'ui-helper-clearfix'
5472                                 )
5473                                 .prependTo(uiDialog),
5475                         uiDialogTitlebarClose = $('<a href="#"></a>')
5476                                 .addClass(
5477                                         'ui-dialog-titlebar-close ' +
5478                                         'ui-corner-all'
5479                                 )
5480                                 .attr('role', 'button')
5481                                 .hover(
5482                                         function() {
5483                                                 uiDialogTitlebarClose.addClass('ui-state-hover');
5484                                         },
5485                                         function() {
5486                                                 uiDialogTitlebarClose.removeClass('ui-state-hover');
5487                                         }
5488                                 )
5489                                 .focus(function() {
5490                                         uiDialogTitlebarClose.addClass('ui-state-focus');
5491                                 })
5492                                 .blur(function() {
5493                                         uiDialogTitlebarClose.removeClass('ui-state-focus');
5494                                 })
5495                                 .click(function(event) {
5496                                         self.close(event);
5497                                         return false;
5498                                 })
5499                                 .appendTo(uiDialogTitlebar),
5501                         uiDialogTitlebarCloseText = (self.uiDialogTitlebarCloseText = $('<span></span>'))
5502                                 .addClass(
5503                                         'ui-icon ' +
5504                                         'ui-icon-closethick'
5505                                 )
5506                                 .text(options.closeText)
5507                                 .appendTo(uiDialogTitlebarClose),
5509                         uiDialogTitle = $('<span></span>')
5510                                 .addClass('ui-dialog-title')
5511                                 .attr('id', titleId)
5512                                 .html(title)
5513                                 .prependTo(uiDialogTitlebar);
5515                 //handling of deprecated beforeclose (vs beforeClose) option
5516                 //Ticket #4669 http://dev.jqueryui.com/ticket/4669
5517                 //TODO: remove in 1.9pre
5518                 if ($.isFunction(options.beforeclose) && !$.isFunction(options.beforeClose)) {
5519                         options.beforeClose = options.beforeclose;
5520                 }
5522                 uiDialogTitlebar.find("*").add(uiDialogTitlebar).disableSelection();
5524                 if (options.draggable && $.fn.draggable) {
5525                         self._makeDraggable();
5526                 }
5527                 if (options.resizable && $.fn.resizable) {
5528                         self._makeResizable();
5529                 }
5531                 self._createButtons(options.buttons);
5532                 self._isOpen = false;
5534                 if ($.fn.bgiframe) {
5535                         uiDialog.bgiframe();
5536                 }
5537         },
5538         _init: function() {
5539                 if ( this.options.autoOpen ) {
5540                         this.open();
5541                 }
5542         },
5544         destroy: function() {
5545                 var self = this;
5546                 
5547                 if (self.overlay) {
5548                         self.overlay.destroy();
5549                 }
5550                 self.uiDialog.hide();
5551                 self.element
5552                         .unbind('.dialog')
5553                         .removeData('dialog')
5554                         .removeClass('ui-dialog-content ui-widget-content')
5555                         .hide().appendTo('body');
5556                 self.uiDialog.remove();
5558                 if (self.originalTitle) {
5559                         self.element.attr('title', self.originalTitle);
5560                 }
5562                 return self;
5563         },
5564         
5565         widget: function() {
5566                 return this.uiDialog;
5567         },
5569         close: function(event) {
5570                 var self = this,
5571                         maxZ;
5572                 
5573                 if (false === self._trigger('beforeClose', event)) {
5574                         return;
5575                 }
5577                 if (self.overlay) {
5578                         self.overlay.destroy();
5579                 }
5580                 self.uiDialog.unbind('keypress.ui-dialog');
5582                 self._isOpen = false;
5584                 if (self.options.hide) {
5585                         self.uiDialog.hide(self.options.hide, function() {
5586                                 self._trigger('close', event);
5587                         });
5588                 } else {
5589                         self.uiDialog.hide();
5590                         self._trigger('close', event);
5591                 }
5593                 $.ui.dialog.overlay.resize();
5595                 // adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
5596                 if (self.options.modal) {
5597                         maxZ = 0;
5598                         $('.ui-dialog').each(function() {
5599                                 if (this !== self.uiDialog[0]) {
5600                                         maxZ = Math.max(maxZ, $(this).css('z-index'));
5601                                 }
5602                         });
5603                         $.ui.dialog.maxZ = maxZ;
5604                 }
5606                 return self;
5607         },
5609         isOpen: function() {
5610                 return this._isOpen;
5611         },
5613         // the force parameter allows us to move modal dialogs to their correct
5614         // position on open
5615         moveToTop: function(force, event) {
5616                 var self = this,
5617                         options = self.options,
5618                         saveScroll;
5619                 
5620                 if ((options.modal && !force) ||
5621                         (!options.stack && !options.modal)) {
5622                         return self._trigger('focus', event);
5623                 }
5624                 
5625                 if (options.zIndex > $.ui.dialog.maxZ) {
5626                         $.ui.dialog.maxZ = options.zIndex;
5627                 }
5628                 if (self.overlay) {
5629                         $.ui.dialog.maxZ += 1;
5630                         self.overlay.$el.css('z-index', $.ui.dialog.overlay.maxZ = $.ui.dialog.maxZ);
5631                 }
5633                 //Save and then restore scroll since Opera 9.5+ resets when parent z-Index is changed.
5634                 //  http://ui.jquery.com/bugs/ticket/3193
5635                 saveScroll = { scrollTop: self.element.attr('scrollTop'), scrollLeft: self.element.attr('scrollLeft') };
5636                 $.ui.dialog.maxZ += 1;
5637                 self.uiDialog.css('z-index', $.ui.dialog.maxZ);
5638                 self.element.attr(saveScroll);
5639                 self._trigger('focus', event);
5641                 return self;
5642         },
5644         open: function() {
5645                 if (this._isOpen) { return; }
5647                 var self = this,
5648                         options = self.options,
5649                         uiDialog = self.uiDialog;
5651                 self.overlay = options.modal ? new $.ui.dialog.overlay(self) : null;
5652                 if (uiDialog.next().length) {
5653                         uiDialog.appendTo('body');
5654                 }
5655                 self._size();
5656                 self._position(options.position);
5657                 uiDialog.show(options.show);
5658                 self.moveToTop(true);
5660                 // prevent tabbing out of modal dialogs
5661                 if (options.modal) {
5662                         uiDialog.bind('keypress.ui-dialog', function(event) {
5663                                 if (event.keyCode !== $.ui.keyCode.TAB) {
5664                                         return;
5665                                 }
5666         
5667                                 var tabbables = $(':tabbable', this),
5668                                         first = tabbables.filter(':first'),
5669                                         last  = tabbables.filter(':last');
5670         
5671                                 if (event.target === last[0] && !event.shiftKey) {
5672                                         first.focus(1);
5673                                         return false;
5674                                 } else if (event.target === first[0] && event.shiftKey) {
5675                                         last.focus(1);
5676                                         return false;
5677                                 }
5678                         });
5679                 }
5681                 // set focus to the first tabbable element in the content area or the first button
5682                 // if there are no tabbable elements, set focus on the dialog itself
5683                 $([])
5684                         .add(uiDialog.find('.ui-dialog-content :tabbable:first'))
5685                         .add(uiDialog.find('.ui-dialog-buttonpane :tabbable:first'))
5686                         .add(uiDialog)
5687                         .filter(':first')
5688                         .focus();
5690                 self._trigger('open');
5691                 self._isOpen = true;
5693                 return self;
5694         },
5696         _createButtons: function(buttons) {
5697                 var self = this,
5698                         hasButtons = false,
5699                         uiDialogButtonPane = $('<div></div>')
5700                                 .addClass(
5701                                         'ui-dialog-buttonpane ' +
5702                                         'ui-widget-content ' +
5703                                         'ui-helper-clearfix'
5704                                 );
5706                 // if we already have a button pane, remove it
5707                 self.uiDialog.find('.ui-dialog-buttonpane').remove();
5709                 if (typeof buttons === 'object' && buttons !== null) {
5710                         $.each(buttons, function() {
5711                                 return !(hasButtons = true);
5712                         });
5713                 }
5714                 if (hasButtons) {
5715                         $.each(buttons, function(name, fn) {
5716                                 var button = $('<button type="button"></button>')
5717                                         .text(name)
5718                                         .click(function() { fn.apply(self.element[0], arguments); })
5719                                         .appendTo(uiDialogButtonPane);
5720                                 if ($.fn.button) {
5721                                         button.button();
5722                                 }
5723                         });
5724                         uiDialogButtonPane.appendTo(self.uiDialog);
5725                 }
5726         },
5728         _makeDraggable: function() {
5729                 var self = this,
5730                         options = self.options,
5731                         doc = $(document),
5732                         heightBeforeDrag;
5734                 function filteredUi(ui) {
5735                         return {
5736                                 position: ui.position,
5737                                 offset: ui.offset
5738                         };
5739                 }
5741                 self.uiDialog.draggable({
5742                         cancel: '.ui-dialog-content, .ui-dialog-titlebar-close',
5743                         handle: '.ui-dialog-titlebar',
5744                         containment: 'document',
5745                         start: function(event, ui) {
5746                                 heightBeforeDrag = options.height === "auto" ? "auto" : $(this).height();
5747                                 $(this).height($(this).height()).addClass("ui-dialog-dragging");
5748                                 self._trigger('dragStart', event, filteredUi(ui));
5749                         },
5750                         drag: function(event, ui) {
5751                                 self._trigger('drag', event, filteredUi(ui));
5752                         },
5753                         stop: function(event, ui) {
5754                                 options.position = [ui.position.left - doc.scrollLeft(),
5755                                         ui.position.top - doc.scrollTop()];
5756                                 $(this).removeClass("ui-dialog-dragging").height(heightBeforeDrag);
5757                                 self._trigger('dragStop', event, filteredUi(ui));
5758                                 $.ui.dialog.overlay.resize();
5759                         }
5760                 });
5761         },
5763         _makeResizable: function(handles) {
5764                 handles = (handles === undefined ? this.options.resizable : handles);
5765                 var self = this,
5766                         options = self.options,
5767                         // .ui-resizable has position: relative defined in the stylesheet
5768                         // but dialogs have to use absolute or fixed positioning
5769                         position = self.uiDialog.css('position'),
5770                         resizeHandles = (typeof handles === 'string' ?
5771                                 handles :
5772                                 'n,e,s,w,se,sw,ne,nw'
5773                         );
5775                 function filteredUi(ui) {
5776                         return {
5777                                 originalPosition: ui.originalPosition,
5778                                 originalSize: ui.originalSize,
5779                                 position: ui.position,
5780                                 size: ui.size
5781                         };
5782                 }
5784                 self.uiDialog.resizable({
5785                         cancel: '.ui-dialog-content',
5786                         containment: 'document',
5787                         alsoResize: self.element,
5788                         maxWidth: options.maxWidth,
5789                         maxHeight: options.maxHeight,
5790                         minWidth: options.minWidth,
5791                         minHeight: self._minHeight(),
5792                         handles: resizeHandles,
5793                         start: function(event, ui) {
5794                                 $(this).addClass("ui-dialog-resizing");
5795                                 self._trigger('resizeStart', event, filteredUi(ui));
5796                         },
5797                         resize: function(event, ui) {
5798                                 self._trigger('resize', event, filteredUi(ui));
5799                         },
5800                         stop: function(event, ui) {
5801                                 $(this).removeClass("ui-dialog-resizing");
5802                                 options.height = $(this).height();
5803                                 options.width = $(this).width();
5804                                 self._trigger('resizeStop', event, filteredUi(ui));
5805                                 $.ui.dialog.overlay.resize();
5806                         }
5807                 })
5808                 .css('position', position)
5809                 .find('.ui-resizable-se').addClass('ui-icon ui-icon-grip-diagonal-se');
5810         },
5812         _minHeight: function() {
5813                 var options = this.options;
5815                 if (options.height === 'auto') {
5816                         return options.minHeight;
5817                 } else {
5818                         return Math.min(options.minHeight, options.height);
5819                 }
5820         },
5822         _position: function(position) {
5823                 var myAt = [],
5824                         offset = [0, 0],
5825                         isVisible;
5827                 position = position || $.ui.dialog.prototype.options.position;
5829                 // deep extending converts arrays to objects in jQuery <= 1.3.2 :-(
5830 //              if (typeof position == 'string' || $.isArray(position)) {
5831 //                      myAt = $.isArray(position) ? position : position.split(' ');
5833                 if (typeof position === 'string' || (typeof position === 'object' && '0' in position)) {
5834                         myAt = position.split ? position.split(' ') : [position[0], position[1]];
5835                         if (myAt.length === 1) {
5836                                 myAt[1] = myAt[0];
5837                         }
5839                         $.each(['left', 'top'], function(i, offsetPosition) {
5840                                 if (+myAt[i] === myAt[i]) {
5841                                         offset[i] = myAt[i];
5842                                         myAt[i] = offsetPosition;
5843                                 }
5844                         });
5845                 } else if (typeof position === 'object') {
5846                         if ('left' in position) {
5847                                 myAt[0] = 'left';
5848                                 offset[0] = position.left;
5849                         } else if ('right' in position) {
5850                                 myAt[0] = 'right';
5851                                 offset[0] = -position.right;
5852                         }
5854                         if ('top' in position) {
5855                                 myAt[1] = 'top';
5856                                 offset[1] = position.top;
5857                         } else if ('bottom' in position) {
5858                                 myAt[1] = 'bottom';
5859                                 offset[1] = -position.bottom;
5860                         }
5861                 }
5863                 // need to show the dialog to get the actual offset in the position plugin
5864                 isVisible = this.uiDialog.is(':visible');
5865                 if (!isVisible) {
5866                         this.uiDialog.show();
5867                 }
5868                 this.uiDialog
5869                         // workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
5870                         .css({ top: 0, left: 0 })
5871                         .position({
5872                                 my: myAt.join(' '),
5873                                 at: myAt.join(' '),
5874                                 offset: offset.join(' '),
5875                                 of: window,
5876                                 collision: 'fit',
5877                                 // ensure that the titlebar is never outside the document
5878                                 using: function(pos) {
5879                                         var topOffset = $(this).css(pos).offset().top;
5880                                         if (topOffset < 0) {
5881                                                 $(this).css('top', pos.top - topOffset);
5882                                         }
5883                                 }
5884                         });
5885                 if (!isVisible) {
5886                         this.uiDialog.hide();
5887                 }
5888         },
5890         _setOption: function(key, value){
5891                 var self = this,
5892                         uiDialog = self.uiDialog,
5893                         isResizable = uiDialog.is(':data(resizable)'),
5894                         resize = false;
5895                 
5896                 switch (key) {
5897                         //handling of deprecated beforeclose (vs beforeClose) option
5898                         //Ticket #4669 http://dev.jqueryui.com/ticket/4669
5899                         //TODO: remove in 1.9pre
5900                         case "beforeclose":
5901                                 key = "beforeClose";
5902                                 break;
5903                         case "buttons":
5904                                 self._createButtons(value);
5905                                 break;
5906                         case "closeText":
5907                                 // convert whatever was passed in to a string, for text() to not throw up
5908                                 self.uiDialogTitlebarCloseText.text("" + value);
5909                                 break;
5910                         case "dialogClass":
5911                                 uiDialog
5912                                         .removeClass(self.options.dialogClass)
5913                                         .addClass(uiDialogClasses + value);
5914                                 break;
5915                         case "disabled":
5916                                 if (value) {
5917                                         uiDialog.addClass('ui-dialog-disabled');
5918                                 } else {
5919                                         uiDialog.removeClass('ui-dialog-disabled');
5920                                 }
5921                                 break;
5922                         case "draggable":
5923                                 if (value) {
5924                                         self._makeDraggable();
5925                                 } else {
5926                                         uiDialog.draggable('destroy');
5927                                 }
5928                                 break;
5929                         case "height":
5930                                 resize = true;
5931                                 break;
5932                         case "maxHeight":
5933                                 if (isResizable) {
5934                                         uiDialog.resizable('option', 'maxHeight', value);
5935                                 }
5936                                 resize = true;
5937                                 break;
5938                         case "maxWidth":
5939                                 if (isResizable) {
5940                                         uiDialog.resizable('option', 'maxWidth', value);
5941                                 }
5942                                 resize = true;
5943                                 break;
5944                         case "minHeight":
5945                                 if (isResizable) {
5946                                         uiDialog.resizable('option', 'minHeight', value);
5947                                 }
5948                                 resize = true;
5949                                 break;
5950                         case "minWidth":
5951                                 if (isResizable) {
5952                                         uiDialog.resizable('option', 'minWidth', value);
5953                                 }
5954                                 resize = true;
5955                                 break;
5956                         case "position":
5957                                 self._position(value);
5958                                 break;
5959                         case "resizable":
5960                                 // currently resizable, becoming non-resizable
5961                                 if (isResizable && !value) {
5962                                         uiDialog.resizable('destroy');
5963                                 }
5965                                 // currently resizable, changing handles
5966                                 if (isResizable && typeof value === 'string') {
5967                                         uiDialog.resizable('option', 'handles', value);
5968                                 }
5970                                 // currently non-resizable, becoming resizable
5971                                 if (!isResizable && value !== false) {
5972                                         self._makeResizable(value);
5973                                 }
5974                                 break;
5975                         case "title":
5976                                 // convert whatever was passed in o a string, for html() to not throw up
5977                                 $(".ui-dialog-title", self.uiDialogTitlebar).html("" + (value || '&#160;'));
5978                                 break;
5979                         case "width":
5980                                 resize = true;
5981                                 break;
5982                 }
5984                 $.Widget.prototype._setOption.apply(self, arguments);
5985                 if (resize) {
5986                         self._size();
5987                 }
5988         },
5990         _size: function() {
5991                 /* If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
5992                  * divs will both have width and height set, so we need to reset them
5993                  */
5994                 var options = this.options,
5995                         nonContentHeight;
5997                 // reset content sizing
5998                 // hide for non content measurement because height: 0 doesn't work in IE quirks mode (see #4350)
5999                 this.element.css('width', 'auto')
6000                         .hide();
6002                 // reset wrapper sizing
6003                 // determine the height of all the non-content elements
6004                 nonContentHeight = this.uiDialog.css({
6005                                 height: 'auto',
6006                                 width: options.width
6007                         })
6008                         .height();
6010                 this.element
6011                         .css(options.height === 'auto' ? {
6012                                         minHeight: Math.max(options.minHeight - nonContentHeight, 0),
6013                                         height: 'auto'
6014                                 } : {
6015                                         minHeight: 0,
6016                                         height: Math.max(options.height - nonContentHeight, 0)                          
6017                         })
6018                         .show();
6020                 if (this.uiDialog.is(':data(resizable)')) {
6021                         this.uiDialog.resizable('option', 'minHeight', this._minHeight());
6022                 }
6023         }
6026 $.extend($.ui.dialog, {
6027         version: "1.8",
6029         uuid: 0,
6030         maxZ: 0,
6032         getTitleId: function($el) {
6033                 var id = $el.attr('id');
6034                 if (!id) {
6035                         this.uuid += 1;
6036                         id = this.uuid;
6037                 }
6038                 return 'ui-dialog-title-' + id;
6039         },
6041         overlay: function(dialog) {
6042                 this.$el = $.ui.dialog.overlay.create(dialog);
6043         }
6046 $.extend($.ui.dialog.overlay, {
6047         instances: [],
6048         // reuse old instances due to IE memory leak with alpha transparency (see #5185)
6049         oldInstances: [],
6050         maxZ: 0,
6051         events: $.map('focus,mousedown,mouseup,keydown,keypress,click'.split(','),
6052                 function(event) { return event + '.dialog-overlay'; }).join(' '),
6053         create: function(dialog) {
6054                 if (this.instances.length === 0) {
6055                         // prevent use of anchors and inputs
6056                         // we use a setTimeout in case the overlay is created from an
6057                         // event that we're going to be cancelling (see #2804)
6058                         setTimeout(function() {
6059                                 // handle $(el).dialog().dialog('close') (see #4065)
6060                                 if ($.ui.dialog.overlay.instances.length) {
6061                                         $(document).bind($.ui.dialog.overlay.events, function(event) {
6062                                                 // stop events if the z-index of the target is < the z-index of the overlay
6063                                                 return ($(event.target).zIndex() >= $.ui.dialog.overlay.maxZ);
6064                                         });
6065                                 }
6066                         }, 1);
6068                         // allow closing by pressing the escape key
6069                         $(document).bind('keydown.dialog-overlay', function(event) {
6070                                 if (dialog.options.closeOnEscape && event.keyCode &&
6071                                         event.keyCode === $.ui.keyCode.ESCAPE) {
6072                                         
6073                                         dialog.close(event);
6074                                         event.preventDefault();
6075                                 }
6076                         });
6078                         // handle window resize
6079                         $(window).bind('resize.dialog-overlay', $.ui.dialog.overlay.resize);
6080                 }
6082                 var $el = (this.oldInstances.pop() || $('<div></div>').addClass('ui-widget-overlay'))
6083                         .appendTo(document.body)
6084                         .css({
6085                                 width: this.width(),
6086                                 height: this.height()
6087                         });
6089                 if ($.fn.bgiframe) {
6090                         $el.bgiframe();
6091                 }
6093                 this.instances.push($el);
6094                 return $el;
6095         },
6097         destroy: function($el) {
6098                 this.oldInstances.push(this.instances.splice($.inArray($el, this.instances), 1)[0]);
6100                 if (this.instances.length === 0) {
6101                         $([document, window]).unbind('.dialog-overlay');
6102                 }
6104                 $el.remove();
6105                 
6106                 // adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
6107                 var maxZ = 0;
6108                 $.each(this.instances, function() {
6109                         maxZ = Math.max(maxZ, this.css('z-index'));
6110                 });
6111                 this.maxZ = maxZ;
6112         },
6114         height: function() {
6115                 var scrollHeight,
6116                         offsetHeight;
6117                 // handle IE 6
6118                 if ($.browser.msie && $.browser.version < 7) {
6119                         scrollHeight = Math.max(
6120                                 document.documentElement.scrollHeight,
6121                                 document.body.scrollHeight
6122                         );
6123                         offsetHeight = Math.max(
6124                                 document.documentElement.offsetHeight,
6125                                 document.body.offsetHeight
6126                         );
6128                         if (scrollHeight < offsetHeight) {
6129                                 return $(window).height() + 'px';
6130                         } else {
6131                                 return scrollHeight + 'px';
6132                         }
6133                 // handle "good" browsers
6134                 } else {
6135                         return $(document).height() + 'px';
6136                 }
6137         },
6139         width: function() {
6140                 var scrollWidth,
6141                         offsetWidth;
6142                 // handle IE 6
6143                 if ($.browser.msie && $.browser.version < 7) {
6144                         scrollWidth = Math.max(
6145                                 document.documentElement.scrollWidth,
6146                                 document.body.scrollWidth
6147                         );
6148                         offsetWidth = Math.max(
6149                                 document.documentElement.offsetWidth,
6150                                 document.body.offsetWidth
6151                         );
6153                         if (scrollWidth < offsetWidth) {
6154                                 return $(window).width() + 'px';
6155                         } else {
6156                                 return scrollWidth + 'px';
6157                         }
6158                 // handle "good" browsers
6159                 } else {
6160                         return $(document).width() + 'px';
6161                 }
6162         },
6164         resize: function() {
6165                 /* If the dialog is draggable and the user drags it past the
6166                  * right edge of the window, the document becomes wider so we
6167                  * need to stretch the overlay. If the user then drags the
6168                  * dialog back to the left, the document will become narrower,
6169                  * so we need to shrink the overlay to the appropriate size.
6170                  * This is handled by shrinking the overlay before setting it
6171                  * to the full document size.
6172                  */
6173                 var $overlays = $([]);
6174                 $.each($.ui.dialog.overlay.instances, function() {
6175                         $overlays = $overlays.add(this);
6176                 });
6178                 $overlays.css({
6179                         width: 0,
6180                         height: 0
6181                 }).css({
6182                         width: $.ui.dialog.overlay.width(),
6183                         height: $.ui.dialog.overlay.height()
6184                 });
6185         }
6188 $.extend($.ui.dialog.overlay.prototype, {
6189         destroy: function() {
6190                 $.ui.dialog.overlay.destroy(this.$el);
6191         }
6194 }(jQuery));
6196  * jQuery UI Slider 1.8
6198  * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
6199  * Dual licensed under the MIT (MIT-LICENSE.txt)
6200  * and GPL (GPL-LICENSE.txt) licenses.
6202  * http://docs.jquery.com/UI/Slider
6204  * Depends:
6205  *      jquery.ui.core.js
6206  *      jquery.ui.mouse.js
6207  *      jquery.ui.widget.js
6208  */
6210 (function($) {
6212 // number of pages in a slider
6213 // (how many times can you page up/down to go through the whole range)
6214 var numPages = 5;
6216 $.widget("ui.slider", $.ui.mouse, {
6217         widgetEventPrefix: "slide",
6218         options: {
6219                 animate: false,
6220                 distance: 0,
6221                 max: 100,
6222                 min: 0,
6223                 orientation: 'horizontal',
6224                 range: false,
6225                 step: 1,
6226                 value: 0,
6227                 values: null
6228         },
6229         _create: function() {
6231                 var self = this, o = this.options;
6232                 this._keySliding = false;
6233                 this._mouseSliding = false;
6234                 this._animateOff = true;
6235                 this._handleIndex = null;
6236                 this._detectOrientation();
6237                 this._mouseInit();
6239                 this.element
6240                         .addClass("ui-slider"
6241                                 + " ui-slider-" + this.orientation
6242                                 + " ui-widget"
6243                                 + " ui-widget-content"
6244                                 + " ui-corner-all");
6245                 
6246                 if (o.disabled) {
6247                         this.element.addClass('ui-slider-disabled ui-disabled');
6248                 }
6250                 this.range = $([]);
6252                 if (o.range) {
6254                         if (o.range === true) {
6255                                 this.range = $('<div></div>');
6256                                 if (!o.values) o.values = [this._valueMin(), this._valueMin()];
6257                                 if (o.values.length && o.values.length != 2) {
6258                                         o.values = [o.values[0], o.values[0]];
6259                                 }
6260                         } else {
6261                                 this.range = $('<div></div>');
6262                         }
6264                         this.range
6265                                 .appendTo(this.element)
6266                                 .addClass("ui-slider-range");
6268                         if (o.range == "min" || o.range == "max") {
6269                                 this.range.addClass("ui-slider-range-" + o.range);
6270                         }
6272                         // note: this isn't the most fittingly semantic framework class for this element,
6273                         // but worked best visually with a variety of themes
6274                         this.range.addClass("ui-widget-header");
6276                 }
6278                 if ($(".ui-slider-handle", this.element).length == 0)
6279                         $('<a href="#"></a>')
6280                                 .appendTo(this.element)
6281                                 .addClass("ui-slider-handle");
6283                 if (o.values && o.values.length) {
6284                         while ($(".ui-slider-handle", this.element).length < o.values.length)
6285                                 $('<a href="#"></a>')
6286                                         .appendTo(this.element)
6287                                         .addClass("ui-slider-handle");
6288                 }
6290                 this.handles = $(".ui-slider-handle", this.element)
6291                         .addClass("ui-state-default"
6292                                 + " ui-corner-all");
6294                 this.handle = this.handles.eq(0);
6296                 this.handles.add(this.range).filter("a")
6297                         .click(function(event) {
6298                                 event.preventDefault();
6299                         })
6300                         .hover(function() {
6301                                 if (!o.disabled) {
6302                                         $(this).addClass('ui-state-hover');
6303                                 }
6304                         }, function() {
6305                                 $(this).removeClass('ui-state-hover');
6306                         })
6307                         .focus(function() {
6308                                 if (!o.disabled) {
6309                                         $(".ui-slider .ui-state-focus").removeClass('ui-state-focus'); $(this).addClass('ui-state-focus');
6310                                 } else {
6311                                         $(this).blur();
6312                                 }
6313                         })
6314                         .blur(function() {
6315                                 $(this).removeClass('ui-state-focus');
6316                         });
6318                 this.handles.each(function(i) {
6319                         $(this).data("index.ui-slider-handle", i);
6320                 });
6322                 this.handles.keydown(function(event) {
6324                         var ret = true;
6326                         var index = $(this).data("index.ui-slider-handle");
6328                         if (self.options.disabled)
6329                                 return;
6331                         switch (event.keyCode) {
6332                                 case $.ui.keyCode.HOME:
6333                                 case $.ui.keyCode.END:
6334                                 case $.ui.keyCode.PAGE_UP:
6335                                 case $.ui.keyCode.PAGE_DOWN:
6336                                 case $.ui.keyCode.UP:
6337                                 case $.ui.keyCode.RIGHT:
6338                                 case $.ui.keyCode.DOWN:
6339                                 case $.ui.keyCode.LEFT:
6340                                         ret = false;
6341                                         if (!self._keySliding) {
6342                                                 self._keySliding = true;
6343                                                 $(this).addClass("ui-state-active");
6344                                                 self._start(event, index);
6345                                         }
6346                                         break;
6347                         }
6349                         var curVal, newVal, step = self._step();
6350                         if (self.options.values && self.options.values.length) {
6351                                 curVal = newVal = self.values(index);
6352                         } else {
6353                                 curVal = newVal = self.value();
6354                         }
6356                         switch (event.keyCode) {
6357                                 case $.ui.keyCode.HOME:
6358                                         newVal = self._valueMin();
6359                                         break;
6360                                 case $.ui.keyCode.END:
6361                                         newVal = self._valueMax();
6362                                         break;
6363                                 case $.ui.keyCode.PAGE_UP:
6364                                         newVal = curVal + ((self._valueMax() - self._valueMin()) / numPages);
6365                                         break;
6366                                 case $.ui.keyCode.PAGE_DOWN:
6367                                         newVal = curVal - ((self._valueMax() - self._valueMin()) / numPages);
6368                                         break;
6369                                 case $.ui.keyCode.UP:
6370                                 case $.ui.keyCode.RIGHT:
6371                                         if(curVal == self._valueMax()) return;
6372                                         newVal = curVal + step;
6373                                         break;
6374                                 case $.ui.keyCode.DOWN:
6375                                 case $.ui.keyCode.LEFT:
6376                                         if(curVal == self._valueMin()) return;
6377                                         newVal = curVal - step;
6378                                         break;
6379                         }
6381                         self._slide(event, index, newVal);
6383                         return ret;
6385                 }).keyup(function(event) {
6387                         var index = $(this).data("index.ui-slider-handle");
6389                         if (self._keySliding) {
6390                                 self._keySliding = false;
6391                                 self._stop(event, index);
6392                                 self._change(event, index);
6393                                 $(this).removeClass("ui-state-active");
6394                         }
6396                 });
6398                 this._refreshValue();
6400                 this._animateOff = false;
6402         },
6404         destroy: function() {
6406                 this.handles.remove();
6407                 this.range.remove();
6409                 this.element
6410                         .removeClass("ui-slider"
6411                                 + " ui-slider-horizontal"
6412                                 + " ui-slider-vertical"
6413                                 + " ui-slider-disabled"
6414                                 + " ui-widget"
6415                                 + " ui-widget-content"
6416                                 + " ui-corner-all")
6417                         .removeData("slider")
6418                         .unbind(".slider");
6420                 this._mouseDestroy();
6422                 return this;
6423         },
6425         _mouseCapture: function(event) {
6427                 var o = this.options;
6429                 if (o.disabled)
6430                         return false;
6432                 this.elementSize = {
6433                         width: this.element.outerWidth(),
6434                         height: this.element.outerHeight()
6435                 };
6436                 this.elementOffset = this.element.offset();
6438                 var position = { x: event.pageX, y: event.pageY };
6439                 var normValue = this._normValueFromMouse(position);
6441                 var distance = this._valueMax() - this._valueMin() + 1, closestHandle;
6442                 var self = this, index;
6443                 this.handles.each(function(i) {
6444                         var thisDistance = Math.abs(normValue - self.values(i));
6445                         if (distance > thisDistance) {
6446                                 distance = thisDistance;
6447                                 closestHandle = $(this);
6448                                 index = i;
6449                         }
6450                 });
6452                 // workaround for bug #3736 (if both handles of a range are at 0,
6453                 // the first is always used as the one with least distance,
6454                 // and moving it is obviously prevented by preventing negative ranges)
6455                 if(o.range == true && this.values(1) == o.min) {
6456                         closestHandle = $(this.handles[++index]);
6457                 }
6459                 this._start(event, index);
6460                 this._mouseSliding = true;
6462                 self._handleIndex = index;
6464                 closestHandle
6465                         .addClass("ui-state-active")
6466                         .focus();
6467                 
6468                 var offset = closestHandle.offset();
6469                 var mouseOverHandle = !$(event.target).parents().andSelf().is('.ui-slider-handle');
6470                 this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
6471                         left: event.pageX - offset.left - (closestHandle.width() / 2),
6472                         top: event.pageY - offset.top
6473                                 - (closestHandle.height() / 2)
6474                                 - (parseInt(closestHandle.css('borderTopWidth'),10) || 0)
6475                                 - (parseInt(closestHandle.css('borderBottomWidth'),10) || 0)
6476                                 + (parseInt(closestHandle.css('marginTop'),10) || 0)
6477                 };
6479                 normValue = this._normValueFromMouse(position);
6480                 this._slide(event, index, normValue);
6481                 this._animateOff = true;
6482                 return true;
6484         },
6486         _mouseStart: function(event) {
6487                 return true;
6488         },
6490         _mouseDrag: function(event) {
6492                 var position = { x: event.pageX, y: event.pageY };
6493                 var normValue = this._normValueFromMouse(position);
6494                 
6495                 this._slide(event, this._handleIndex, normValue);
6497                 return false;
6499         },
6501         _mouseStop: function(event) {
6503                 this.handles.removeClass("ui-state-active");
6504                 this._mouseSliding = false;
6505                 this._stop(event, this._handleIndex);
6506                 this._change(event, this._handleIndex);
6507                 this._handleIndex = null;
6508                 this._clickOffset = null;
6510                 this._animateOff = false;
6511                 return false;
6513         },
6514         
6515         _detectOrientation: function() {
6516                 this.orientation = this.options.orientation == 'vertical' ? 'vertical' : 'horizontal';
6517         },
6519         _normValueFromMouse: function(position) {
6521                 var pixelTotal, pixelMouse;
6522                 if ('horizontal' == this.orientation) {
6523                         pixelTotal = this.elementSize.width;
6524                         pixelMouse = position.x - this.elementOffset.left - (this._clickOffset ? this._clickOffset.left : 0);
6525                 } else {
6526                         pixelTotal = this.elementSize.height;
6527                         pixelMouse = position.y - this.elementOffset.top - (this._clickOffset ? this._clickOffset.top : 0);
6528                 }
6530                 var percentMouse = (pixelMouse / pixelTotal);
6531                 if (percentMouse > 1) percentMouse = 1;
6532                 if (percentMouse < 0) percentMouse = 0;
6533                 if ('vertical' == this.orientation)
6534                         percentMouse = 1 - percentMouse;
6536                 var valueTotal = this._valueMax() - this._valueMin(),
6537                         valueMouse = percentMouse * valueTotal,
6538                         valueMouseModStep = valueMouse % this.options.step,
6539                         normValue = this._valueMin() + valueMouse - valueMouseModStep;
6541                 if (valueMouseModStep > (this.options.step / 2))
6542                         normValue += this.options.step;
6544                 // Since JavaScript has problems with large floats, round
6545                 // the final value to 5 digits after the decimal point (see #4124)
6546                 return parseFloat(normValue.toFixed(5));
6548         },
6550         _start: function(event, index) {
6551                 var uiHash = {
6552                         handle: this.handles[index],
6553                         value: this.value()
6554                 };
6555                 if (this.options.values && this.options.values.length) {
6556                         uiHash.value = this.values(index);
6557                         uiHash.values = this.values();
6558                 }
6559                 this._trigger("start", event, uiHash);
6560         },
6562         _slide: function(event, index, newVal) {
6564                 var handle = this.handles[index];
6566                 if (this.options.values && this.options.values.length) {
6568                         var otherVal = this.values(index ? 0 : 1);
6570                         if ((this.options.values.length == 2 && this.options.range === true) && 
6571                                 ((index == 0 && newVal > otherVal) || (index == 1 && newVal < otherVal))){
6572                                 newVal = otherVal;
6573                         }
6575                         if (newVal != this.values(index)) {
6576                                 var newValues = this.values();
6577                                 newValues[index] = newVal;
6578                                 // A slide can be canceled by returning false from the slide callback
6579                                 var allowed = this._trigger("slide", event, {
6580                                         handle: this.handles[index],
6581                                         value: newVal,
6582                                         values: newValues
6583                                 });
6584                                 var otherVal = this.values(index ? 0 : 1);
6585                                 if (allowed !== false) {
6586                                         this.values(index, newVal, true);
6587                                 }
6588                         }
6590                 } else {
6592                         if (newVal != this.value()) {
6593                                 // A slide can be canceled by returning false from the slide callback
6594                                 var allowed = this._trigger("slide", event, {
6595                                         handle: this.handles[index],
6596                                         value: newVal
6597                                 });
6598                                 if (allowed !== false) {
6599                                         this.value(newVal);
6600                                 }
6601                                         
6602                         }
6604                 }
6606         },
6608         _stop: function(event, index) {
6609                 var uiHash = {
6610                         handle: this.handles[index],
6611                         value: this.value()
6612                 };
6613                 if (this.options.values && this.options.values.length) {
6614                         uiHash.value = this.values(index);
6615                         uiHash.values = this.values();
6616                 }
6617                 this._trigger("stop", event, uiHash);
6618         },
6620         _change: function(event, index) {
6621                 if (!this._keySliding && !this._mouseSliding) {
6622                         var uiHash = {
6623                                 handle: this.handles[index],
6624                                 value: this.value()
6625                         };
6626                         if (this.options.values && this.options.values.length) {
6627                                 uiHash.value = this.values(index);
6628                                 uiHash.values = this.values();
6629                         }
6630                         this._trigger("change", event, uiHash);
6631                 }
6632         },
6634         value: function(newValue) {
6636                 if (arguments.length) {
6637                         this.options.value = this._trimValue(newValue);
6638                         this._refreshValue();
6639                         this._change(null, 0);
6640                 }
6642                 return this._value();
6644         },
6646         values: function(index, newValue) {
6648                 if (arguments.length > 1) {
6649                         this.options.values[index] = this._trimValue(newValue);
6650                         this._refreshValue();
6651                         this._change(null, index);
6652                 }
6654                 if (arguments.length) {
6655                         if ($.isArray(arguments[0])) {
6656                                 var vals = this.options.values, newValues = arguments[0];
6657                                 for (var i = 0, l = vals.length; i < l; i++) {
6658                                         vals[i] = this._trimValue(newValues[i]);
6659                                         this._change(null, i);
6660                                 }
6661                                 this._refreshValue();
6662                         } else {
6663                                 if (this.options.values && this.options.values.length) {
6664                                         return this._values(index);
6665                                 } else {
6666                                         return this.value();
6667                                 }
6668                         }
6669                 } else {
6670                         return this._values();
6671                 }
6673         },
6675         _setOption: function(key, value) {
6676                 
6677                 var i,
6678                         valsLength = 0;
6679                 if ( jQuery.isArray(this.options.values) ) {
6680                         valsLength = this.options.values.length;
6681                 };
6683                 $.Widget.prototype._setOption.apply(this, arguments);
6685                 switch (key) {
6686                         case 'disabled':
6687                                 if (value) {
6688                                         this.handles.filter(".ui-state-focus").blur();
6689                                         this.handles.removeClass("ui-state-hover");
6690                                         this.handles.attr("disabled", "disabled");
6691                                         this.element.addClass("ui-disabled");
6692                                 } else {
6693                                         this.handles.removeAttr("disabled");
6694                                         this.element.removeClass("ui-disabled");
6695                                 }
6696                         case 'orientation':
6698                                 this._detectOrientation();
6699                                 
6700                                 this.element
6701                                         .removeClass("ui-slider-horizontal ui-slider-vertical")
6702                                         .addClass("ui-slider-" + this.orientation);
6703                                 this._refreshValue();
6704                                 break;
6705                         case 'value':
6706                                 this._animateOff = true;
6707                                 this._refreshValue();
6708                                 this._change(null, 0);
6709                                 this._animateOff = false;
6710                                 break;
6711                         case 'values':
6712                                 this._animateOff = true;
6713                                 this._refreshValue();
6714                                 for (i = 0; i < valsLength; i++) {
6715                                         this._change(null, i);
6716                                 }
6717                                 this._animateOff = false;
6718                                 break;
6719                 }
6721         },
6723         _step: function() {
6724                 var step = this.options.step;
6725                 return step;
6726         },
6728         _value: function() {
6729                 //internal value getter
6730                 // _value() returns value trimmed by min and max
6731                 var val = this.options.value;
6732                 val = this._trimValue(val);
6734                 return val;
6735         },
6737         _values: function(index) {
6738                 //internal values getter
6739                 // _values() returns array of values trimmed by min and max
6740                 // _values(index) returns single value trimmed by min and max
6742                 if (arguments.length) {
6743                         var val = this.options.values[index];
6744                         val = this._trimValue(val);
6746                         return val;
6747                 } else {
6748                         // .slice() creates a copy of the array
6749                         // this copy gets trimmed by min and max and then returned
6750                         var vals = this.options.values.slice();
6751                         for (var i = 0, l = vals.length; i < l; i++) {
6752                                 vals[i] = this._trimValue(vals[i]);
6753                         }
6755                         return vals;
6756                 }
6758         },
6759         
6760         _trimValue: function(val) {
6761                 if (val < this._valueMin()) val = this._valueMin();
6762                 if (val > this._valueMax()) val = this._valueMax();
6764                 return val;
6765         },
6767         _valueMin: function() {
6768                 var valueMin = this.options.min;
6769                 return valueMin;
6770         },
6772         _valueMax: function() {
6773                 var valueMax = this.options.max;
6774                 return valueMax;
6775         },
6776         
6777         _refreshValue: function() {
6779                 var oRange = this.options.range, o = this.options, self = this;
6780                 var animate = (!this._animateOff) ? o.animate : false;
6782                 if (this.options.values && this.options.values.length) {
6783                         var vp0, vp1;
6784                         this.handles.each(function(i, j) {
6785                                 var valPercent = (self.values(i) - self._valueMin()) / (self._valueMax() - self._valueMin()) * 100;
6786                                 var _set = {}; _set[self.orientation == 'horizontal' ? 'left' : 'bottom'] = valPercent + '%';
6787                                 $(this).stop(1,1)[animate ? 'animate' : 'css'](_set, o.animate);
6788                                 if (self.options.range === true) {
6789                                         if (self.orientation == 'horizontal') {
6790                                                 (i == 0) && self.range.stop(1,1)[animate ? 'animate' : 'css']({ left: valPercent + '%' }, o.animate);
6791                                                 (i == 1) && self.range[animate ? 'animate' : 'css']({ width: (valPercent - lastValPercent) + '%' }, { queue: false, duration: o.animate });
6792                                         } else {
6793                                                 (i == 0) && self.range.stop(1,1)[animate ? 'animate' : 'css']({ bottom: (valPercent) + '%' }, o.animate);
6794                                                 (i == 1) && self.range[animate ? 'animate' : 'css']({ height: (valPercent - lastValPercent) + '%' }, { queue: false, duration: o.animate });
6795                                         }
6796                                 }
6797                                 lastValPercent = valPercent;
6798                         });
6799                 } else {
6800                         var value = this.value(),
6801                                 valueMin = this._valueMin(),
6802                                 valueMax = this._valueMax(),
6803                                 valPercent = valueMax != valueMin
6804                                         ? (value - valueMin) / (valueMax - valueMin) * 100
6805                                         : 0;
6806                         var _set = {}; _set[self.orientation == 'horizontal' ? 'left' : 'bottom'] = valPercent + '%';
6807                         this.handle.stop(1,1)[animate ? 'animate' : 'css'](_set, o.animate);
6809                         (oRange == "min") && (this.orientation == "horizontal") && this.range.stop(1,1)[animate ? 'animate' : 'css']({ width: valPercent + '%' }, o.animate);
6810                         (oRange == "max") && (this.orientation == "horizontal") && this.range[animate ? 'animate' : 'css']({ width: (100 - valPercent) + '%' }, { queue: false, duration: o.animate });
6811                         (oRange == "min") && (this.orientation == "vertical") && this.range.stop(1,1)[animate ? 'animate' : 'css']({ height: valPercent + '%' }, o.animate);
6812                         (oRange == "max") && (this.orientation == "vertical") && this.range[animate ? 'animate' : 'css']({ height: (100 - valPercent) + '%' }, { queue: false, duration: o.animate });
6813                 }
6815         }
6816         
6819 $.extend($.ui.slider, {
6820         version: "1.8"
6823 })(jQuery);
6825  * jQuery UI Tabs 1.8
6827  * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
6828  * Dual licensed under the MIT (MIT-LICENSE.txt)
6829  * and GPL (GPL-LICENSE.txt) licenses.
6831  * http://docs.jquery.com/UI/Tabs
6833  * Depends:
6834  *      jquery.ui.core.js
6835  *      jquery.ui.widget.js
6836  */
6837 (function($) {
6839 var tabId = 0,
6840         listId = 0;
6842 $.widget("ui.tabs", {
6843         options: {
6844                 add: null,
6845                 ajaxOptions: null,
6846                 cache: false,
6847                 cookie: null, // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true }
6848                 collapsible: false,
6849                 disable: null,
6850                 disabled: [],
6851                 enable: null,
6852                 event: 'click',
6853                 fx: null, // e.g. { height: 'toggle', opacity: 'toggle', duration: 200 }
6854                 idPrefix: 'ui-tabs-',
6855                 load: null,
6856                 panelTemplate: '<div></div>',
6857                 remove: null,
6858                 select: null,
6859                 show: null,
6860                 spinner: '<em>Loading&#8230;</em>',
6861                 tabTemplate: '<li><a href="#{href}"><span>#{label}</span></a></li>'
6862         },
6863         _create: function() {
6864                 this._tabify(true);
6865         },
6867         _setOption: function(key, value) {
6868                 if (key == 'selected') {
6869                         if (this.options.collapsible && value == this.options.selected) {
6870                                 return;
6871                         }
6872                         this.select(value);
6873                 }
6874                 else {
6875                         this.options[key] = value;
6876                         this._tabify();
6877                 }
6878         },
6880         _tabId: function(a) {
6881                 return a.title && a.title.replace(/\s/g, '_').replace(/[^A-Za-z0-9\-_:\.]/g, '') ||
6882                         this.options.idPrefix + (++tabId);
6883         },
6885         _sanitizeSelector: function(hash) {
6886                 return hash.replace(/:/g, '\\:'); // we need this because an id may contain a ":"
6887         },
6889         _cookie: function() {
6890                 var cookie = this.cookie || (this.cookie = this.options.cookie.name || 'ui-tabs-' + (++listId));
6891                 return $.cookie.apply(null, [cookie].concat($.makeArray(arguments)));
6892         },
6894         _ui: function(tab, panel) {
6895                 return {
6896                         tab: tab,
6897                         panel: panel,
6898                         index: this.anchors.index(tab)
6899                 };
6900         },
6902         _cleanup: function() {
6903                 // restore all former loading tabs labels
6904                 this.lis.filter('.ui-state-processing').removeClass('ui-state-processing')
6905                                 .find('span:data(label.tabs)')
6906                                 .each(function() {
6907                                         var el = $(this);
6908                                         el.html(el.data('label.tabs')).removeData('label.tabs');
6909                                 });
6910         },
6912         _tabify: function(init) {
6914                 this.list = this.element.find('ol,ul').eq(0);
6915                 this.lis = $('li:has(a[href])', this.list);
6916                 this.anchors = this.lis.map(function() { return $('a', this)[0]; });
6917                 this.panels = $([]);
6919                 var self = this, o = this.options;
6921                 var fragmentId = /^#.+/; // Safari 2 reports '#' for an empty hash
6922                 this.anchors.each(function(i, a) {
6923                         var href = $(a).attr('href');
6925                         // For dynamically created HTML that contains a hash as href IE < 8 expands
6926                         // such href to the full page url with hash and then misinterprets tab as ajax.
6927                         // Same consideration applies for an added tab with a fragment identifier
6928                         // since a[href=#fragment-identifier] does unexpectedly not match.
6929                         // Thus normalize href attribute...
6930                         var hrefBase = href.split('#')[0], baseEl;
6931                         if (hrefBase && (hrefBase === location.toString().split('#')[0] ||
6932                                         (baseEl = $('base')[0]) && hrefBase === baseEl.href)) {
6933                                 href = a.hash;
6934                                 a.href = href;
6935                         }
6937                         // inline tab
6938                         if (fragmentId.test(href)) {
6939                                 self.panels = self.panels.add(self._sanitizeSelector(href));
6940                         }
6942                         // remote tab
6943                         else if (href != '#') { // prevent loading the page itself if href is just "#"
6944                                 $.data(a, 'href.tabs', href); // required for restore on destroy
6946                                 // TODO until #3808 is fixed strip fragment identifier from url
6947                                 // (IE fails to load from such url)
6948                                 $.data(a, 'load.tabs', href.replace(/#.*$/, '')); // mutable data
6950                                 var id = self._tabId(a);
6951                                 a.href = '#' + id;
6952                                 var $panel = $('#' + id);
6953                                 if (!$panel.length) {
6954                                         $panel = $(o.panelTemplate).attr('id', id).addClass('ui-tabs-panel ui-widget-content ui-corner-bottom')
6955                                                 .insertAfter(self.panels[i - 1] || self.list);
6956                                         $panel.data('destroy.tabs', true);
6957                                 }
6958                                 self.panels = self.panels.add($panel);
6959                         }
6961                         // invalid tab href
6962                         else {
6963                                 o.disabled.push(i);
6964                         }
6965                 });
6967                 // initialization from scratch
6968                 if (init) {
6970                         // attach necessary classes for styling
6971                         this.element.addClass('ui-tabs ui-widget ui-widget-content ui-corner-all');
6972                         this.list.addClass('ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all');
6973                         this.lis.addClass('ui-state-default ui-corner-top');
6974                         this.panels.addClass('ui-tabs-panel ui-widget-content ui-corner-bottom');
6976                         // Selected tab
6977                         // use "selected" option or try to retrieve:
6978                         // 1. from fragment identifier in url
6979                         // 2. from cookie
6980                         // 3. from selected class attribute on <li>
6981                         if (o.selected === undefined) {
6982                                 if (location.hash) {
6983                                         this.anchors.each(function(i, a) {
6984                                                 if (a.hash == location.hash) {
6985                                                         o.selected = i;
6986                                                         return false; // break
6987                                                 }
6988                                         });
6989                                 }
6990                                 if (typeof o.selected != 'number' && o.cookie) {
6991                                         o.selected = parseInt(self._cookie(), 10);
6992                                 }
6993                                 if (typeof o.selected != 'number' && this.lis.filter('.ui-tabs-selected').length) {
6994                                         o.selected = this.lis.index(this.lis.filter('.ui-tabs-selected'));
6995                                 }
6996                                 o.selected = o.selected || (this.lis.length ? 0 : -1);
6997                         }
6998                         else if (o.selected === null) { // usage of null is deprecated, TODO remove in next release
6999                                 o.selected = -1;
7000                         }
7002                         // sanity check - default to first tab...
7003                         o.selected = ((o.selected >= 0 && this.anchors[o.selected]) || o.selected < 0) ? o.selected : 0;
7005                         // Take disabling tabs via class attribute from HTML
7006                         // into account and update option properly.
7007                         // A selected tab cannot become disabled.
7008                         o.disabled = $.unique(o.disabled.concat(
7009                                 $.map(this.lis.filter('.ui-state-disabled'),
7010                                         function(n, i) { return self.lis.index(n); } )
7011                         )).sort();
7013                         if ($.inArray(o.selected, o.disabled) != -1) {
7014                                 o.disabled.splice($.inArray(o.selected, o.disabled), 1);
7015                         }
7017                         // highlight selected tab
7018                         this.panels.addClass('ui-tabs-hide');
7019                         this.lis.removeClass('ui-tabs-selected ui-state-active');
7020                         if (o.selected >= 0 && this.anchors.length) { // check for length avoids error when initializing empty list
7021                                 this.panels.eq(o.selected).removeClass('ui-tabs-hide');
7022                                 this.lis.eq(o.selected).addClass('ui-tabs-selected ui-state-active');
7024                                 // seems to be expected behavior that the show callback is fired
7025                                 self.element.queue("tabs", function() {
7026                                         self._trigger('show', null, self._ui(self.anchors[o.selected], self.panels[o.selected]));
7027                                 });
7028                                 
7029                                 this.load(o.selected);
7030                         }
7032                         // clean up to avoid memory leaks in certain versions of IE 6
7033                         $(window).bind('unload', function() {
7034                                 self.lis.add(self.anchors).unbind('.tabs');
7035                                 self.lis = self.anchors = self.panels = null;
7036                         });
7038                 }
7039                 // update selected after add/remove
7040                 else {
7041                         o.selected = this.lis.index(this.lis.filter('.ui-tabs-selected'));
7042                 }
7044                 // update collapsible
7045                 this.element[o.collapsible ? 'addClass' : 'removeClass']('ui-tabs-collapsible');
7047                 // set or update cookie after init and add/remove respectively
7048                 if (o.cookie) {
7049                         this._cookie(o.selected, o.cookie);
7050                 }
7052                 // disable tabs
7053                 for (var i = 0, li; (li = this.lis[i]); i++) {
7054                         $(li)[$.inArray(i, o.disabled) != -1 &&
7055                                 !$(li).hasClass('ui-tabs-selected') ? 'addClass' : 'removeClass']('ui-state-disabled');
7056                 }
7058                 // reset cache if switching from cached to not cached
7059                 if (o.cache === false) {
7060                         this.anchors.removeData('cache.tabs');
7061                 }
7063                 // remove all handlers before, tabify may run on existing tabs after add or option change
7064                 this.lis.add(this.anchors).unbind('.tabs');
7066                 if (o.event != 'mouseover') {
7067                         var addState = function(state, el) {
7068                                 if (el.is(':not(.ui-state-disabled)')) {
7069                                         el.addClass('ui-state-' + state);
7070                                 }
7071                         };
7072                         var removeState = function(state, el) {
7073                                 el.removeClass('ui-state-' + state);
7074                         };
7075                         this.lis.bind('mouseover.tabs', function() {
7076                                 addState('hover', $(this));
7077                         });
7078                         this.lis.bind('mouseout.tabs', function() {
7079                                 removeState('hover', $(this));
7080                         });
7081                         this.anchors.bind('focus.tabs', function() {
7082                                 addState('focus', $(this).closest('li'));
7083                         });
7084                         this.anchors.bind('blur.tabs', function() {
7085                                 removeState('focus', $(this).closest('li'));
7086                         });
7087                 }
7089                 // set up animations
7090                 var hideFx, showFx;
7091                 if (o.fx) {
7092                         if ($.isArray(o.fx)) {
7093                                 hideFx = o.fx[0];
7094                                 showFx = o.fx[1];
7095                         }
7096                         else {
7097                                 hideFx = showFx = o.fx;
7098                         }
7099                 }
7101                 // Reset certain styles left over from animation
7102                 // and prevent IE's ClearType bug...
7103                 function resetStyle($el, fx) {
7104                         $el.css({ display: '' });
7105                         if (!$.support.opacity && fx.opacity) {
7106                                 $el[0].style.removeAttribute('filter');
7107                         }
7108                 }
7110                 // Show a tab...
7111                 var showTab = showFx ?
7112                         function(clicked, $show) {
7113                                 $(clicked).closest('li').addClass('ui-tabs-selected ui-state-active');
7114                                 $show.hide().removeClass('ui-tabs-hide') // avoid flicker that way
7115                                         .animate(showFx, showFx.duration || 'normal', function() {
7116                                                 resetStyle($show, showFx);
7117                                                 self._trigger('show', null, self._ui(clicked, $show[0]));
7118                                         });
7119                         } :
7120                         function(clicked, $show) {
7121                                 $(clicked).closest('li').addClass('ui-tabs-selected ui-state-active');
7122                                 $show.removeClass('ui-tabs-hide');
7123                                 self._trigger('show', null, self._ui(clicked, $show[0]));
7124                         };
7126                 // Hide a tab, $show is optional...
7127                 var hideTab = hideFx ?
7128                         function(clicked, $hide) {
7129                                 $hide.animate(hideFx, hideFx.duration || 'normal', function() {
7130                                         self.lis.removeClass('ui-tabs-selected ui-state-active');
7131                                         $hide.addClass('ui-tabs-hide');
7132                                         resetStyle($hide, hideFx);
7133                                         self.element.dequeue("tabs");
7134                                 });
7135                         } :
7136                         function(clicked, $hide, $show) {
7137                                 self.lis.removeClass('ui-tabs-selected ui-state-active');
7138                                 $hide.addClass('ui-tabs-hide');
7139                                 self.element.dequeue("tabs");
7140                         };
7142                 // attach tab event handler, unbind to avoid duplicates from former tabifying...
7143                 this.anchors.bind(o.event + '.tabs', function() {
7144                         var el = this, $li = $(this).closest('li'), $hide = self.panels.filter(':not(.ui-tabs-hide)'),
7145                                         $show = $(self._sanitizeSelector(this.hash));
7147                         // If tab is already selected and not collapsible or tab disabled or
7148                         // or is already loading or click callback returns false stop here.
7149                         // Check if click handler returns false last so that it is not executed
7150                         // for a disabled or loading tab!
7151                         if (($li.hasClass('ui-tabs-selected') && !o.collapsible) ||
7152                                 $li.hasClass('ui-state-disabled') ||
7153                                 $li.hasClass('ui-state-processing') ||
7154                                 self._trigger('select', null, self._ui(this, $show[0])) === false) {
7155                                 this.blur();
7156                                 return false;
7157                         }
7159                         o.selected = self.anchors.index(this);
7161                         self.abort();
7163                         // if tab may be closed
7164                         if (o.collapsible) {
7165                                 if ($li.hasClass('ui-tabs-selected')) {
7166                                         o.selected = -1;
7168                                         if (o.cookie) {
7169                                                 self._cookie(o.selected, o.cookie);
7170                                         }
7172                                         self.element.queue("tabs", function() {
7173                                                 hideTab(el, $hide);
7174                                         }).dequeue("tabs");
7175                                         
7176                                         this.blur();
7177                                         return false;
7178                                 }
7179                                 else if (!$hide.length) {
7180                                         if (o.cookie) {
7181                                                 self._cookie(o.selected, o.cookie);
7182                                         }
7183                                         
7184                                         self.element.queue("tabs", function() {
7185                                                 showTab(el, $show);
7186                                         });
7188                                         self.load(self.anchors.index(this)); // TODO make passing in node possible, see also http://dev.jqueryui.com/ticket/3171
7189                                         
7190                                         this.blur();
7191                                         return false;
7192                                 }
7193                         }
7195                         if (o.cookie) {
7196                                 self._cookie(o.selected, o.cookie);
7197                         }
7199                         // show new tab
7200                         if ($show.length) {
7201                                 if ($hide.length) {
7202                                         self.element.queue("tabs", function() {
7203                                                 hideTab(el, $hide);
7204                                         });
7205                                 }
7206                                 self.element.queue("tabs", function() {
7207                                         showTab(el, $show);
7208                                 });
7209                                 
7210                                 self.load(self.anchors.index(this));
7211                         }
7212                         else {
7213                                 throw 'jQuery UI Tabs: Mismatching fragment identifier.';
7214                         }
7216                         // Prevent IE from keeping other link focussed when using the back button
7217                         // and remove dotted border from clicked link. This is controlled via CSS
7218                         // in modern browsers; blur() removes focus from address bar in Firefox
7219                         // which can become a usability and annoying problem with tabs('rotate').
7220                         if ($.browser.msie) {
7221                                 this.blur();
7222                         }
7224                 });
7226                 // disable click in any case
7227                 this.anchors.bind('click.tabs', function(){return false;});
7229         },
7231         destroy: function() {
7232                 var o = this.options;
7234                 this.abort();
7235                 
7236                 this.element.unbind('.tabs')
7237                         .removeClass('ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible')
7238                         .removeData('tabs');
7240                 this.list.removeClass('ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all');
7242                 this.anchors.each(function() {
7243                         var href = $.data(this, 'href.tabs');
7244                         if (href) {
7245                                 this.href = href;
7246                         }
7247                         var $this = $(this).unbind('.tabs');
7248                         $.each(['href', 'load', 'cache'], function(i, prefix) {
7249                                 $this.removeData(prefix + '.tabs');
7250                         });
7251                 });
7253                 this.lis.unbind('.tabs').add(this.panels).each(function() {
7254                         if ($.data(this, 'destroy.tabs')) {
7255                                 $(this).remove();
7256                         }
7257                         else {
7258                                 $(this).removeClass([
7259                                         'ui-state-default',
7260                                         'ui-corner-top',
7261                                         'ui-tabs-selected',
7262                                         'ui-state-active',
7263                                         'ui-state-hover',
7264                                         'ui-state-focus',
7265                                         'ui-state-disabled',
7266                                         'ui-tabs-panel',
7267                                         'ui-widget-content',
7268                                         'ui-corner-bottom',
7269                                         'ui-tabs-hide'
7270                                 ].join(' '));
7271                         }
7272                 });
7274                 if (o.cookie) {
7275                         this._cookie(null, o.cookie);
7276                 }
7278                 return this;
7279         },
7281         add: function(url, label, index) {
7282                 if (index === undefined) {
7283                         index = this.anchors.length; // append by default
7284                 }
7286                 var self = this, o = this.options,
7287                         $li = $(o.tabTemplate.replace(/#\{href\}/g, url).replace(/#\{label\}/g, label)),
7288                         id = !url.indexOf('#') ? url.replace('#', '') : this._tabId($('a', $li)[0]);
7290                 $li.addClass('ui-state-default ui-corner-top').data('destroy.tabs', true);
7292                 // try to find an existing element before creating a new one
7293                 var $panel = $('#' + id);
7294                 if (!$panel.length) {
7295                         $panel = $(o.panelTemplate).attr('id', id).data('destroy.tabs', true);
7296                 }
7297                 $panel.addClass('ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide');
7299                 if (index >= this.lis.length) {
7300                         $li.appendTo(this.list);
7301                         $panel.appendTo(this.list[0].parentNode);
7302                 }
7303                 else {
7304                         $li.insertBefore(this.lis[index]);
7305                         $panel.insertBefore(this.panels[index]);
7306                 }
7308                 o.disabled = $.map(o.disabled,
7309                         function(n, i) { return n >= index ? ++n : n; });
7311                 this._tabify();
7313                 if (this.anchors.length == 1) { // after tabify
7314                         o.selected = 0;
7315                         $li.addClass('ui-tabs-selected ui-state-active');
7316                         $panel.removeClass('ui-tabs-hide');
7317                         this.element.queue("tabs", function() {
7318                                 self._trigger('show', null, self._ui(self.anchors[0], self.panels[0]));
7319                         });
7320                                 
7321                         this.load(0);
7322                 }
7324                 // callback
7325                 this._trigger('add', null, this._ui(this.anchors[index], this.panels[index]));
7326                 return this;
7327         },
7329         remove: function(index) {
7330                 var o = this.options, $li = this.lis.eq(index).remove(),
7331                         $panel = this.panels.eq(index).remove();
7333                 // If selected tab was removed focus tab to the right or
7334                 // in case the last tab was removed the tab to the left.
7335                 if ($li.hasClass('ui-tabs-selected') && this.anchors.length > 1) {
7336                         this.select(index + (index + 1 < this.anchors.length ? 1 : -1));
7337                 }
7339                 o.disabled = $.map($.grep(o.disabled, function(n, i) { return n != index; }),
7340                         function(n, i) { return n >= index ? --n : n; });
7342                 this._tabify();
7344                 // callback
7345                 this._trigger('remove', null, this._ui($li.find('a')[0], $panel[0]));
7346                 return this;
7347         },
7349         enable: function(index) {
7350                 var o = this.options;
7351                 if ($.inArray(index, o.disabled) == -1) {
7352                         return;
7353                 }
7355                 this.lis.eq(index).removeClass('ui-state-disabled');
7356                 o.disabled = $.grep(o.disabled, function(n, i) { return n != index; });
7358                 // callback
7359                 this._trigger('enable', null, this._ui(this.anchors[index], this.panels[index]));
7360                 return this;
7361         },
7363         disable: function(index) {
7364                 var self = this, o = this.options;
7365                 if (index != o.selected) { // cannot disable already selected tab
7366                         this.lis.eq(index).addClass('ui-state-disabled');
7368                         o.disabled.push(index);
7369                         o.disabled.sort();
7371                         // callback
7372                         this._trigger('disable', null, this._ui(this.anchors[index], this.panels[index]));
7373                 }
7375                 return this;
7376         },
7378         select: function(index) {
7379                 if (typeof index == 'string') {
7380                         index = this.anchors.index(this.anchors.filter('[href$=' + index + ']'));
7381                 }
7382                 else if (index === null) { // usage of null is deprecated, TODO remove in next release
7383                         index = -1;
7384                 }
7385                 if (index == -1 && this.options.collapsible) {
7386                         index = this.options.selected;
7387                 }
7389                 this.anchors.eq(index).trigger(this.options.event + '.tabs');
7390                 return this;
7391         },
7393         load: function(index) {
7394                 var self = this, o = this.options, a = this.anchors.eq(index)[0], url = $.data(a, 'load.tabs');
7396                 this.abort();
7398                 // not remote or from cache
7399                 if (!url || this.element.queue("tabs").length !== 0 && $.data(a, 'cache.tabs')) {
7400                         this.element.dequeue("tabs");
7401                         return;
7402                 }
7404                 // load remote from here on
7405                 this.lis.eq(index).addClass('ui-state-processing');
7407                 if (o.spinner) {
7408                         var span = $('span', a);
7409                         span.data('label.tabs', span.html()).html(o.spinner);
7410                 }
7412                 this.xhr = $.ajax($.extend({}, o.ajaxOptions, {
7413                         url: url,
7414                         success: function(r, s) {
7415                                 $(self._sanitizeSelector(a.hash)).html(r);
7417                                 // take care of tab labels
7418                                 self._cleanup();
7420                                 if (o.cache) {
7421                                         $.data(a, 'cache.tabs', true); // if loaded once do not load them again
7422                                 }
7424                                 // callbacks
7425                                 self._trigger('load', null, self._ui(self.anchors[index], self.panels[index]));
7426                                 try {
7427                                         o.ajaxOptions.success(r, s);
7428                                 }
7429                                 catch (e) {}
7430                         },
7431                         error: function(xhr, s, e) {
7432                                 // take care of tab labels
7433                                 self._cleanup();
7435                                 // callbacks
7436                                 self._trigger('load', null, self._ui(self.anchors[index], self.panels[index]));
7437                                 try {
7438                                         // Passing index avoid a race condition when this method is
7439                                         // called after the user has selected another tab.
7440                                         // Pass the anchor that initiated this request allows
7441                                         // loadError to manipulate the tab content panel via $(a.hash)
7442                                         o.ajaxOptions.error(xhr, s, index, a);
7443                                 }
7444                                 catch (e) {}
7445                         }
7446                 }));
7448                 // last, so that load event is fired before show...
7449                 self.element.dequeue("tabs");
7451                 return this;
7452         },
7454         abort: function() {
7455                 // stop possibly running animations
7456                 this.element.queue([]);
7457                 this.panels.stop(false, true);
7459                 // "tabs" queue must not contain more than two elements,
7460                 // which are the callbacks for the latest clicked tab...
7461                 this.element.queue("tabs", this.element.queue("tabs").splice(-2, 2));
7463                 // terminate pending requests from other tabs
7464                 if (this.xhr) {
7465                         this.xhr.abort();
7466                         delete this.xhr;
7467                 }
7469                 // take care of tab labels
7470                 this._cleanup();
7471                 return this;
7472         },
7474         url: function(index, url) {
7475                 this.anchors.eq(index).removeData('cache.tabs').data('load.tabs', url);
7476                 return this;
7477         },
7479         length: function() {
7480                 return this.anchors.length;
7481         }
7485 $.extend($.ui.tabs, {
7486         version: '1.8'
7490  * Tabs Extensions
7491  */
7494  * Rotate
7495  */
7496 $.extend($.ui.tabs.prototype, {
7497         rotation: null,
7498         rotate: function(ms, continuing) {
7500                 var self = this, o = this.options;
7501                 
7502                 var rotate = self._rotate || (self._rotate = function(e) {
7503                         clearTimeout(self.rotation);
7504                         self.rotation = setTimeout(function() {
7505                                 var t = o.selected;
7506                                 self.select( ++t < self.anchors.length ? t : 0 );
7507                         }, ms);
7508                         
7509                         if (e) {
7510                                 e.stopPropagation();
7511                         }
7512                 });
7513                 
7514                 var stop = self._unrotate || (self._unrotate = !continuing ?
7515                         function(e) {
7516                                 if (e.clientX) { // in case of a true click
7517                                         self.rotate(null);
7518                                 }
7519                         } :
7520                         function(e) {
7521                                 t = o.selected;
7522                                 rotate();
7523                         });
7525                 // start rotation
7526                 if (ms) {
7527                         this.element.bind('tabsshow', rotate);
7528                         this.anchors.bind(o.event + '.tabs', stop);
7529                         rotate();
7530                 }
7531                 // stop rotation
7532                 else {
7533                         clearTimeout(self.rotation);
7534                         this.element.unbind('tabsshow', rotate);
7535                         this.anchors.unbind(o.event + '.tabs', stop);
7536                         delete this._rotate;
7537                         delete this._unrotate;
7538                 }
7540                 return this;
7541         }
7544 })(jQuery);
7546  * jQuery UI Datepicker 1.8
7548  * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
7549  * Dual licensed under the MIT (MIT-LICENSE.txt)
7550  * and GPL (GPL-LICENSE.txt) licenses.
7552  * http://docs.jquery.com/UI/Datepicker
7554  * Depends:
7555  *      jquery.ui.core.js
7556  */
7558 (function($) { // hide the namespace
7560 $.extend($.ui, { datepicker: { version: "1.8" } });
7562 var PROP_NAME = 'datepicker';
7563 var dpuuid = new Date().getTime();
7565 /* Date picker manager.
7566    Use the singleton instance of this class, $.datepicker, to interact with the date picker.
7567    Settings for (groups of) date pickers are maintained in an instance object,
7568    allowing multiple different settings on the same page. */
7570 function Datepicker() {
7571         this.debug = false; // Change this to true to start debugging
7572         this._curInst = null; // The current instance in use
7573         this._keyEvent = false; // If the last event was a key event
7574         this._disabledInputs = []; // List of date picker inputs that have been disabled
7575         this._datepickerShowing = false; // True if the popup picker is showing , false if not
7576         this._inDialog = false; // True if showing within a "dialog", false if not
7577         this._mainDivId = 'ui-datepicker-div'; // The ID of the main datepicker division
7578         this._inlineClass = 'ui-datepicker-inline'; // The name of the inline marker class
7579         this._appendClass = 'ui-datepicker-append'; // The name of the append marker class
7580         this._triggerClass = 'ui-datepicker-trigger'; // The name of the trigger marker class
7581         this._dialogClass = 'ui-datepicker-dialog'; // The name of the dialog marker class
7582         this._disableClass = 'ui-datepicker-disabled'; // The name of the disabled covering marker class
7583         this._unselectableClass = 'ui-datepicker-unselectable'; // The name of the unselectable cell marker class
7584         this._currentClass = 'ui-datepicker-current-day'; // The name of the current day marker class
7585         this._dayOverClass = 'ui-datepicker-days-cell-over'; // The name of the day hover marker class
7586         this.regional = []; // Available regional settings, indexed by language code
7587         this.regional[''] = { // Default regional settings
7588                 closeText: 'Done', // Display text for close link
7589                 prevText: 'Prev', // Display text for previous month link
7590                 nextText: 'Next', // Display text for next month link
7591                 currentText: 'Today', // Display text for current month link
7592                 monthNames: ['January','February','March','April','May','June',
7593                         'July','August','September','October','November','December'], // Names of months for drop-down and formatting
7594                 monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], // For formatting
7595                 dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], // For formatting
7596                 dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], // For formatting
7597                 dayNamesMin: ['Su','Mo','Tu','We','Th','Fr','Sa'], // Column headings for days starting at Sunday
7598                 weekHeader: 'Wk', // Column header for week of the year
7599                 dateFormat: 'mm/dd/yy', // See format options on parseDate
7600                 firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
7601                 isRTL: false, // True if right-to-left language, false if left-to-right
7602                 showMonthAfterYear: false, // True if the year select precedes month, false for month then year
7603                 yearSuffix: '' // Additional text to append to the year in the month headers
7604         };
7605         this._defaults = { // Global defaults for all the date picker instances
7606                 showOn: 'focus', // 'focus' for popup on focus,
7607                         // 'button' for trigger button, or 'both' for either
7608                 showAnim: 'show', // Name of jQuery animation for popup
7609                 showOptions: {}, // Options for enhanced animations
7610                 defaultDate: null, // Used when field is blank: actual date,
7611                         // +/-number for offset from today, null for today
7612                 appendText: '', // Display text following the input box, e.g. showing the format
7613                 buttonText: '...', // Text for trigger button
7614                 buttonImage: '', // URL for trigger button image
7615                 buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
7616                 hideIfNoPrevNext: false, // True to hide next/previous month links
7617                         // if not applicable, false to just disable them
7618                 navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
7619                 gotoCurrent: false, // True if today link goes back to current selection instead
7620                 changeMonth: false, // True if month can be selected directly, false if only prev/next
7621                 changeYear: false, // True if year can be selected directly, false if only prev/next
7622                 yearRange: 'c-10:c+10', // Range of years to display in drop-down,
7623                         // either relative to today's year (-nn:+nn), relative to currently displayed year
7624                         // (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
7625                 showOtherMonths: false, // True to show dates in other months, false to leave blank
7626                 selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
7627                 showWeek: false, // True to show week of the year, false to not show it
7628                 calculateWeek: this.iso8601Week, // How to calculate the week of the year,
7629                         // takes a Date and returns the number of the week for it
7630                 shortYearCutoff: '+10', // Short year values < this are in the current century,
7631                         // > this are in the previous century,
7632                         // string value starting with '+' for current year + value
7633                 minDate: null, // The earliest selectable date, or null for no limit
7634                 maxDate: null, // The latest selectable date, or null for no limit
7635                 duration: '_default', // Duration of display/closure
7636                 beforeShowDay: null, // Function that takes a date and returns an array with
7637                         // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or '',
7638                         // [2] = cell title (optional), e.g. $.datepicker.noWeekends
7639                 beforeShow: null, // Function that takes an input field and
7640                         // returns a set of custom settings for the date picker
7641                 onSelect: null, // Define a callback function when a date is selected
7642                 onChangeMonthYear: null, // Define a callback function when the month or year is changed
7643                 onClose: null, // Define a callback function when the datepicker is closed
7644                 numberOfMonths: 1, // Number of months to show at a time
7645                 showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
7646                 stepMonths: 1, // Number of months to step back/forward
7647                 stepBigMonths: 12, // Number of months to step back/forward for the big links
7648                 altField: '', // Selector for an alternate field to store selected dates into
7649                 altFormat: '', // The date format to use for the alternate field
7650                 constrainInput: true, // The input is constrained by the current date format
7651                 showButtonPanel: false, // True to show button panel, false to not show it
7652                 autoSize: false // True to size the input for the date format, false to leave as is
7653         };
7654         $.extend(this._defaults, this.regional['']);
7655         this.dpDiv = $('<div id="' + this._mainDivId + '" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all ui-helper-hidden-accessible"></div>');
7658 $.extend(Datepicker.prototype, {
7659         /* Class name added to elements to indicate already configured with a date picker. */
7660         markerClassName: 'hasDatepicker',
7662         /* Debug logging (if enabled). */
7663         log: function () {
7664                 if (this.debug)
7665                         console.log.apply('', arguments);
7666         },
7667         
7668         // TODO rename to "widget" when switching to widget factory
7669         _widgetDatepicker: function() {
7670                 return this.dpDiv;
7671         },
7673         /* Override the default settings for all instances of the date picker.
7674            @param  settings  object - the new settings to use as defaults (anonymous object)
7675            @return the manager object */
7676         setDefaults: function(settings) {
7677                 extendRemove(this._defaults, settings || {});
7678                 return this;
7679         },
7681         /* Attach the date picker to a jQuery selection.
7682            @param  target    element - the target input field or division or span
7683            @param  settings  object - the new settings to use for this date picker instance (anonymous) */
7684         _attachDatepicker: function(target, settings) {
7685                 // check for settings on the control itself - in namespace 'date:'
7686                 var inlineSettings = null;
7687                 for (var attrName in this._defaults) {
7688                         var attrValue = target.getAttribute('date:' + attrName);
7689                         if (attrValue) {
7690                                 inlineSettings = inlineSettings || {};
7691                                 try {
7692                                         inlineSettings[attrName] = eval(attrValue);
7693                                 } catch (err) {
7694                                         inlineSettings[attrName] = attrValue;
7695                                 }
7696                         }
7697                 }
7698                 var nodeName = target.nodeName.toLowerCase();
7699                 var inline = (nodeName == 'div' || nodeName == 'span');
7700                 if (!target.id)
7701                         target.id = 'dp' + (++this.uuid);
7702                 var inst = this._newInst($(target), inline);
7703                 inst.settings = $.extend({}, settings || {}, inlineSettings || {});
7704                 if (nodeName == 'input') {
7705                         this._connectDatepicker(target, inst);
7706                 } else if (inline) {
7707                         this._inlineDatepicker(target, inst);
7708                 }
7709         },
7711         /* Create a new instance object. */
7712         _newInst: function(target, inline) {
7713                 var id = target[0].id.replace(/([^A-Za-z0-9_])/g, '\\\\$1'); // escape jQuery meta chars
7714                 return {id: id, input: target, // associated target
7715                         selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
7716                         drawMonth: 0, drawYear: 0, // month being drawn
7717                         inline: inline, // is datepicker inline or not
7718                         dpDiv: (!inline ? this.dpDiv : // presentation div
7719                         $('<div class="' + this._inlineClass + ' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>'))};
7720         },
7722         /* Attach the date picker to an input field. */
7723         _connectDatepicker: function(target, inst) {
7724                 var input = $(target);
7725                 inst.append = $([]);
7726                 inst.trigger = $([]);
7727                 if (input.hasClass(this.markerClassName))
7728                         return;
7729                 this._attachments(input, inst);
7730                 input.addClass(this.markerClassName).keydown(this._doKeyDown).
7731                         keypress(this._doKeyPress).keyup(this._doKeyUp).
7732                         bind("setData.datepicker", function(event, key, value) {
7733                                 inst.settings[key] = value;
7734                         }).bind("getData.datepicker", function(event, key) {
7735                                 return this._get(inst, key);
7736                         });
7737                 this._autoSize(inst);
7738                 $.data(target, PROP_NAME, inst);
7739         },
7741         /* Make attachments based on settings. */
7742         _attachments: function(input, inst) {
7743                 var appendText = this._get(inst, 'appendText');
7744                 var isRTL = this._get(inst, 'isRTL');
7745                 if (inst.append)
7746                         inst.append.remove();
7747                 if (appendText) {
7748                         inst.append = $('<span class="' + this._appendClass + '">' + appendText + '</span>');
7749                         input[isRTL ? 'before' : 'after'](inst.append);
7750                 }
7751                 input.unbind('focus', this._showDatepicker);
7752                 if (inst.trigger)
7753                         inst.trigger.remove();
7754                 var showOn = this._get(inst, 'showOn');
7755                 if (showOn == 'focus' || showOn == 'both') // pop-up date picker when in the marked field
7756                         input.focus(this._showDatepicker);
7757                 if (showOn == 'button' || showOn == 'both') { // pop-up date picker when button clicked
7758                         var buttonText = this._get(inst, 'buttonText');
7759                         var buttonImage = this._get(inst, 'buttonImage');
7760                         inst.trigger = $(this._get(inst, 'buttonImageOnly') ?
7761                                 $('<img/>').addClass(this._triggerClass).
7762                                         attr({ src: buttonImage, alt: buttonText, title: buttonText }) :
7763                                 $('<button type="button"></button>').addClass(this._triggerClass).
7764                                         html(buttonImage == '' ? buttonText : $('<img/>').attr(
7765                                         { src:buttonImage, alt:buttonText, title:buttonText })));
7766                         input[isRTL ? 'before' : 'after'](inst.trigger);
7767                         inst.trigger.click(function() {
7768                                 if ($.datepicker._datepickerShowing && $.datepicker._lastInput == input[0])
7769                                         $.datepicker._hideDatepicker();
7770                                 else
7771                                         $.datepicker._showDatepicker(input[0]);
7772                                 return false;
7773                         });
7774                 }
7775         },
7777         /* Apply the maximum length for the date format. */
7778         _autoSize: function(inst) {
7779                 if (this._get(inst, 'autoSize') && !inst.inline) {
7780                         var date = new Date(2009, 12 - 1, 20); // Ensure double digits
7781                         var dateFormat = this._get(inst, 'dateFormat');
7782                         if (dateFormat.match(/[DM]/)) {
7783                                 var findMax = function(names) {
7784                                         var max = 0;
7785                                         var maxI = 0;
7786                                         for (var i = 0; i < names.length; i++) {
7787                                                 if (names[i].length > max) {
7788                                                         max = names[i].length;
7789                                                         maxI = i;
7790                                                 }
7791                                         }
7792                                         return maxI;
7793                                 };
7794                                 date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ?
7795                                         'monthNames' : 'monthNamesShort'))));
7796                                 date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ?
7797                                         'dayNames' : 'dayNamesShort'))) + 20 - date.getDay());
7798                         }
7799                         inst.input.attr('size', this._formatDate(inst, date).length);
7800                 }
7801         },
7803         /* Attach an inline date picker to a div. */
7804         _inlineDatepicker: function(target, inst) {
7805                 var divSpan = $(target);
7806                 if (divSpan.hasClass(this.markerClassName))
7807                         return;
7808                 divSpan.addClass(this.markerClassName).append(inst.dpDiv).
7809                         bind("setData.datepicker", function(event, key, value){
7810                                 inst.settings[key] = value;
7811                         }).bind("getData.datepicker", function(event, key){
7812                                 return this._get(inst, key);
7813                         });
7814                 $.data(target, PROP_NAME, inst);
7815                 this._setDate(inst, this._getDefaultDate(inst), true);
7816                 this._updateDatepicker(inst);
7817                 this._updateAlternate(inst);
7818         },
7820         /* Pop-up the date picker in a "dialog" box.
7821            @param  input     element - ignored
7822            @param  date      string or Date - the initial date to display
7823            @param  onSelect  function - the function to call when a date is selected
7824            @param  settings  object - update the dialog date picker instance's settings (anonymous object)
7825            @param  pos       int[2] - coordinates for the dialog's position within the screen or
7826                              event - with x/y coordinates or
7827                              leave empty for default (screen centre)
7828            @return the manager object */
7829         _dialogDatepicker: function(input, date, onSelect, settings, pos) {
7830                 var inst = this._dialogInst; // internal instance
7831                 if (!inst) {
7832                         var id = 'dp' + (++this.uuid);
7833                         this._dialogInput = $('<input type="text" id="' + id +
7834                                 '" style="position: absolute; top: -100px; width: 0px; z-index: -10;"/>');
7835                         this._dialogInput.keydown(this._doKeyDown);
7836                         $('body').append(this._dialogInput);
7837                         inst = this._dialogInst = this._newInst(this._dialogInput, false);
7838                         inst.settings = {};
7839                         $.data(this._dialogInput[0], PROP_NAME, inst);
7840                 }
7841                 extendRemove(inst.settings, settings || {});
7842                 date = (date && date.constructor == Date ? this._formatDate(inst, date) : date);
7843                 this._dialogInput.val(date);
7845                 this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);
7846                 if (!this._pos) {
7847                         var browserWidth = document.documentElement.clientWidth;
7848                         var browserHeight = document.documentElement.clientHeight;
7849                         var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
7850                         var scrollY = document.documentElement.scrollTop || document.body.scrollTop;
7851                         this._pos = // should use actual width/height below
7852                                 [(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY];
7853                 }
7855                 // move input on screen for focus, but hidden behind dialog
7856                 this._dialogInput.css('left', (this._pos[0] + 20) + 'px').css('top', this._pos[1] + 'px');
7857                 inst.settings.onSelect = onSelect;
7858                 this._inDialog = true;
7859                 this.dpDiv.addClass(this._dialogClass);
7860                 this._showDatepicker(this._dialogInput[0]);
7861                 if ($.blockUI)
7862                         $.blockUI(this.dpDiv);
7863                 $.data(this._dialogInput[0], PROP_NAME, inst);
7864                 return this;
7865         },
7867         /* Detach a datepicker from its control.
7868            @param  target    element - the target input field or division or span */
7869         _destroyDatepicker: function(target) {
7870                 var $target = $(target);
7871                 var inst = $.data(target, PROP_NAME);
7872                 if (!$target.hasClass(this.markerClassName)) {
7873                         return;
7874                 }
7875                 var nodeName = target.nodeName.toLowerCase();
7876                 $.removeData(target, PROP_NAME);
7877                 if (nodeName == 'input') {
7878                         inst.append.remove();
7879                         inst.trigger.remove();
7880                         $target.removeClass(this.markerClassName).
7881                                 unbind('focus', this._showDatepicker).
7882                                 unbind('keydown', this._doKeyDown).
7883                                 unbind('keypress', this._doKeyPress).
7884                                 unbind('keyup', this._doKeyUp);
7885                 } else if (nodeName == 'div' || nodeName == 'span')
7886                         $target.removeClass(this.markerClassName).empty();
7887         },
7889         /* Enable the date picker to a jQuery selection.
7890            @param  target    element - the target input field or division or span */
7891         _enableDatepicker: function(target) {
7892                 var $target = $(target);
7893                 var inst = $.data(target, PROP_NAME);
7894                 if (!$target.hasClass(this.markerClassName)) {
7895                         return;
7896                 }
7897                 var nodeName = target.nodeName.toLowerCase();
7898                 if (nodeName == 'input') {
7899                         target.disabled = false;
7900                         inst.trigger.filter('button').
7901                                 each(function() { this.disabled = false; }).end().
7902                                 filter('img').css({opacity: '1.0', cursor: ''});
7903                 }
7904                 else if (nodeName == 'div' || nodeName == 'span') {
7905                         var inline = $target.children('.' + this._inlineClass);
7906                         inline.children().removeClass('ui-state-disabled');
7907                 }
7908                 this._disabledInputs = $.map(this._disabledInputs,
7909                         function(value) { return (value == target ? null : value); }); // delete entry
7910         },
7912         /* Disable the date picker to a jQuery selection.
7913            @param  target    element - the target input field or division or span */
7914         _disableDatepicker: function(target) {
7915                 var $target = $(target);
7916                 var inst = $.data(target, PROP_NAME);
7917                 if (!$target.hasClass(this.markerClassName)) {
7918                         return;
7919                 }
7920                 var nodeName = target.nodeName.toLowerCase();
7921                 if (nodeName == 'input') {
7922                         target.disabled = true;
7923                         inst.trigger.filter('button').
7924                                 each(function() { this.disabled = true; }).end().
7925                                 filter('img').css({opacity: '0.5', cursor: 'default'});
7926                 }
7927                 else if (nodeName == 'div' || nodeName == 'span') {
7928                         var inline = $target.children('.' + this._inlineClass);
7929                         inline.children().addClass('ui-state-disabled');
7930                 }
7931                 this._disabledInputs = $.map(this._disabledInputs,
7932                         function(value) { return (value == target ? null : value); }); // delete entry
7933                 this._disabledInputs[this._disabledInputs.length] = target;
7934         },
7936         /* Is the first field in a jQuery collection disabled as a datepicker?
7937            @param  target    element - the target input field or division or span
7938            @return boolean - true if disabled, false if enabled */
7939         _isDisabledDatepicker: function(target) {
7940                 if (!target) {
7941                         return false;
7942                 }
7943                 for (var i = 0; i < this._disabledInputs.length; i++) {
7944                         if (this._disabledInputs[i] == target)
7945                                 return true;
7946                 }
7947                 return false;
7948         },
7950         /* Retrieve the instance data for the target control.
7951            @param  target  element - the target input field or division or span
7952            @return  object - the associated instance data
7953            @throws  error if a jQuery problem getting data */
7954         _getInst: function(target) {
7955                 try {
7956                         return $.data(target, PROP_NAME);
7957                 }
7958                 catch (err) {
7959                         throw 'Missing instance data for this datepicker';
7960                 }
7961         },
7963         /* Update or retrieve the settings for a date picker attached to an input field or division.
7964            @param  target  element - the target input field or division or span
7965            @param  name    object - the new settings to update or
7966                            string - the name of the setting to change or retrieve,
7967                            when retrieving also 'all' for all instance settings or
7968                            'defaults' for all global defaults
7969            @param  value   any - the new value for the setting
7970                            (omit if above is an object or to retrieve a value) */
7971         _optionDatepicker: function(target, name, value) {
7972                 var inst = this._getInst(target);
7973                 if (arguments.length == 2 && typeof name == 'string') {
7974                         return (name == 'defaults' ? $.extend({}, $.datepicker._defaults) :
7975                                 (inst ? (name == 'all' ? $.extend({}, inst.settings) :
7976                                 this._get(inst, name)) : null));
7977                 }
7978                 var settings = name || {};
7979                 if (typeof name == 'string') {
7980                         settings = {};
7981                         settings[name] = value;
7982                 }
7983                 if (inst) {
7984                         if (this._curInst == inst) {
7985                                 this._hideDatepicker();
7986                         }
7987                         var date = this._getDateDatepicker(target, true);
7988                         extendRemove(inst.settings, settings);
7989                         this._attachments($(target), inst);
7990                         this._autoSize(inst);
7991                         this._setDateDatepicker(target, date);
7992                         this._updateDatepicker(inst);
7993                 }
7994         },
7996         // change method deprecated
7997         _changeDatepicker: function(target, name, value) {
7998                 this._optionDatepicker(target, name, value);
7999         },
8001         /* Redraw the date picker attached to an input field or division.
8002            @param  target  element - the target input field or division or span */
8003         _refreshDatepicker: function(target) {
8004                 var inst = this._getInst(target);
8005                 if (inst) {
8006                         this._updateDatepicker(inst);
8007                 }
8008         },
8010         /* Set the dates for a jQuery selection.
8011            @param  target   element - the target input field or division or span
8012            @param  date     Date - the new date */
8013         _setDateDatepicker: function(target, date) {
8014                 var inst = this._getInst(target);
8015                 if (inst) {
8016                         this._setDate(inst, date);
8017                         this._updateDatepicker(inst);
8018                         this._updateAlternate(inst);
8019                 }
8020         },
8022         /* Get the date(s) for the first entry in a jQuery selection.
8023            @param  target     element - the target input field or division or span
8024            @param  noDefault  boolean - true if no default date is to be used
8025            @return Date - the current date */
8026         _getDateDatepicker: function(target, noDefault) {
8027                 var inst = this._getInst(target);
8028                 if (inst && !inst.inline)
8029                         this._setDateFromField(inst, noDefault);
8030                 return (inst ? this._getDate(inst) : null);
8031         },
8033         /* Handle keystrokes. */
8034         _doKeyDown: function(event) {
8035                 var inst = $.datepicker._getInst(event.target);
8036                 var handled = true;
8037                 var isRTL = inst.dpDiv.is('.ui-datepicker-rtl');
8038                 inst._keyEvent = true;
8039                 if ($.datepicker._datepickerShowing)
8040                         switch (event.keyCode) {
8041                                 case 9: $.datepicker._hideDatepicker();
8042                                                 handled = false;
8043                                                 break; // hide on tab out
8044                                 case 13: var sel = $('td.' + $.datepicker._dayOverClass, inst.dpDiv).
8045                                                         add($('td.' + $.datepicker._currentClass, inst.dpDiv));
8046                                                 if (sel[0])
8047                                                         $.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);
8048                                                 else
8049                                                         $.datepicker._hideDatepicker();
8050                                                 return false; // don't submit the form
8051                                                 break; // select the value on enter
8052                                 case 27: $.datepicker._hideDatepicker();
8053                                                 break; // hide on escape
8054                                 case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
8055                                                         -$.datepicker._get(inst, 'stepBigMonths') :
8056                                                         -$.datepicker._get(inst, 'stepMonths')), 'M');
8057                                                 break; // previous month/year on page up/+ ctrl
8058                                 case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
8059                                                         +$.datepicker._get(inst, 'stepBigMonths') :
8060                                                         +$.datepicker._get(inst, 'stepMonths')), 'M');
8061                                                 break; // next month/year on page down/+ ctrl
8062                                 case 35: if (event.ctrlKey || event.metaKey) $.datepicker._clearDate(event.target);
8063                                                 handled = event.ctrlKey || event.metaKey;
8064                                                 break; // clear on ctrl or command +end
8065                                 case 36: if (event.ctrlKey || event.metaKey) $.datepicker._gotoToday(event.target);
8066                                                 handled = event.ctrlKey || event.metaKey;
8067                                                 break; // current on ctrl or command +home
8068                                 case 37: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), 'D');
8069                                                 handled = event.ctrlKey || event.metaKey;
8070                                                 // -1 day on ctrl or command +left
8071                                                 if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
8072                                                                         -$.datepicker._get(inst, 'stepBigMonths') :
8073                                                                         -$.datepicker._get(inst, 'stepMonths')), 'M');
8074                                                 // next month/year on alt +left on Mac
8075                                                 break;
8076                                 case 38: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, -7, 'D');
8077                                                 handled = event.ctrlKey || event.metaKey;
8078                                                 break; // -1 week on ctrl or command +up
8079                                 case 39: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), 'D');
8080                                                 handled = event.ctrlKey || event.metaKey;
8081                                                 // +1 day on ctrl or command +right
8082                                                 if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
8083                                                                         +$.datepicker._get(inst, 'stepBigMonths') :
8084                                                                         +$.datepicker._get(inst, 'stepMonths')), 'M');
8085                                                 // next month/year on alt +right
8086                                                 break;
8087                                 case 40: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, +7, 'D');
8088                                                 handled = event.ctrlKey || event.metaKey;
8089                                                 break; // +1 week on ctrl or command +down
8090                                 default: handled = false;
8091                         }
8092                 else if (event.keyCode == 36 && event.ctrlKey) // display the date picker on ctrl+home
8093                         $.datepicker._showDatepicker(this);
8094                 else {
8095                         handled = false;
8096                 }
8097                 if (handled) {
8098                         event.preventDefault();
8099                         event.stopPropagation();
8100                 }
8101         },
8103         /* Filter entered characters - based on date format. */
8104         _doKeyPress: function(event) {
8105                 var inst = $.datepicker._getInst(event.target);
8106                 if ($.datepicker._get(inst, 'constrainInput')) {
8107                         var chars = $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat'));
8108                         var chr = String.fromCharCode(event.charCode == undefined ? event.keyCode : event.charCode);
8109                         return event.ctrlKey || (chr < ' ' || !chars || chars.indexOf(chr) > -1);
8110                 }
8111         },
8113         /* Synchronise manual entry and field/alternate field. */
8114         _doKeyUp: function(event) {
8115                 var inst = $.datepicker._getInst(event.target);
8116                 if (inst.input.val() != inst.lastVal) {
8117                         try {
8118                                 var date = $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
8119                                         (inst.input ? inst.input.val() : null),
8120                                         $.datepicker._getFormatConfig(inst));
8121                                 if (date) { // only if valid
8122                                         $.datepicker._setDateFromField(inst);
8123                                         $.datepicker._updateAlternate(inst);
8124                                         $.datepicker._updateDatepicker(inst);
8125                                 }
8126                         }
8127                         catch (event) {
8128                                 $.datepicker.log(event);
8129                         }
8130                 }
8131                 return true;
8132         },
8134         /* Pop-up the date picker for a given input field.
8135            @param  input  element - the input field attached to the date picker or
8136                           event - if triggered by focus */
8137         _showDatepicker: function(input) {
8138                 input = input.target || input;
8139                 if (input.nodeName.toLowerCase() != 'input') // find from button/image trigger
8140                         input = $('input', input.parentNode)[0];
8141                 if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput == input) // already here
8142                         return;
8143                 var inst = $.datepicker._getInst(input);
8144                 if ($.datepicker._curInst && $.datepicker._curInst != inst) {
8145                         $.datepicker._curInst.dpDiv.stop(true, true);
8146                 }
8147                 var beforeShow = $.datepicker._get(inst, 'beforeShow');
8148                 extendRemove(inst.settings, (beforeShow ? beforeShow.apply(input, [input, inst]) : {}));
8149                 inst.lastVal = null;
8150                 $.datepicker._lastInput = input;
8151                 $.datepicker._setDateFromField(inst);
8152                 if ($.datepicker._inDialog) // hide cursor
8153                         input.value = '';
8154                 if (!$.datepicker._pos) { // position below input
8155                         $.datepicker._pos = $.datepicker._findPos(input);
8156                         $.datepicker._pos[1] += input.offsetHeight; // add the height
8157                 }
8158                 var isFixed = false;
8159                 $(input).parents().each(function() {
8160                         isFixed |= $(this).css('position') == 'fixed';
8161                         return !isFixed;
8162                 });
8163                 if (isFixed && $.browser.opera) { // correction for Opera when fixed and scrolled
8164                         $.datepicker._pos[0] -= document.documentElement.scrollLeft;
8165                         $.datepicker._pos[1] -= document.documentElement.scrollTop;
8166                 }
8167                 var offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]};
8168                 $.datepicker._pos = null;
8169                 // determine sizing offscreen
8170                 inst.dpDiv.css({position: 'absolute', display: 'block', top: '-1000px'});
8171                 $.datepicker._updateDatepicker(inst);
8172                 // fix width for dynamic number of date pickers
8173                 // and adjust position before showing
8174                 offset = $.datepicker._checkOffset(inst, offset, isFixed);
8175                 inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ?
8176                         'static' : (isFixed ? 'fixed' : 'absolute')), display: 'none',
8177                         left: offset.left + 'px', top: offset.top + 'px'});
8178                 if (!inst.inline) {
8179                         var showAnim = $.datepicker._get(inst, 'showAnim');
8180                         var duration = $.datepicker._get(inst, 'duration');
8181                         var postProcess = function() {
8182                                 $.datepicker._datepickerShowing = true;
8183                                 var borders = $.datepicker._getBorders(inst.dpDiv);
8184                                 inst.dpDiv.find('iframe.ui-datepicker-cover'). // IE6- only
8185                                         css({left: -borders[0], top: -borders[1],
8186                                                 width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()});
8187                         };
8188                         inst.dpDiv.zIndex($(input).zIndex()+1);
8189                         if ($.effects && $.effects[showAnim])
8190                                 inst.dpDiv.show(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
8191                         else
8192                                 inst.dpDiv[showAnim || 'show']((showAnim ? duration : null), postProcess);
8193                         if (!showAnim || !duration)
8194                                 postProcess();
8195                         if (inst.input.is(':visible') && !inst.input.is(':disabled'))
8196                                 inst.input.focus();
8197                         $.datepicker._curInst = inst;
8198                 }
8199         },
8201         /* Generate the date picker content. */
8202         _updateDatepicker: function(inst) {
8203                 var self = this;
8204                 var borders = $.datepicker._getBorders(inst.dpDiv);
8205                 inst.dpDiv.empty().append(this._generateHTML(inst))
8206                         .find('iframe.ui-datepicker-cover') // IE6- only
8207                                 .css({left: -borders[0], top: -borders[1],
8208                                         width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()})
8209                         .end()
8210                         .find('button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a')
8211                                 .bind('mouseout', function(){
8212                                         $(this).removeClass('ui-state-hover');
8213                                         if(this.className.indexOf('ui-datepicker-prev') != -1) $(this).removeClass('ui-datepicker-prev-hover');
8214                                         if(this.className.indexOf('ui-datepicker-next') != -1) $(this).removeClass('ui-datepicker-next-hover');
8215                                 })
8216                                 .bind('mouseover', function(){
8217                                         if (!self._isDisabledDatepicker( inst.inline ? inst.dpDiv.parent()[0] : inst.input[0])) {
8218                                                 $(this).parents('.ui-datepicker-calendar').find('a').removeClass('ui-state-hover');
8219                                                 $(this).addClass('ui-state-hover');
8220                                                 if(this.className.indexOf('ui-datepicker-prev') != -1) $(this).addClass('ui-datepicker-prev-hover');
8221                                                 if(this.className.indexOf('ui-datepicker-next') != -1) $(this).addClass('ui-datepicker-next-hover');
8222                                         }
8223                                 })
8224                         .end()
8225                         .find('.' + this._dayOverClass + ' a')
8226                                 .trigger('mouseover')
8227                         .end();
8228                 var numMonths = this._getNumberOfMonths(inst);
8229                 var cols = numMonths[1];
8230                 var width = 17;
8231                 if (cols > 1)
8232                         inst.dpDiv.addClass('ui-datepicker-multi-' + cols).css('width', (width * cols) + 'em');
8233                 else
8234                         inst.dpDiv.removeClass('ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4').width('');
8235                 inst.dpDiv[(numMonths[0] != 1 || numMonths[1] != 1 ? 'add' : 'remove') +
8236                         'Class']('ui-datepicker-multi');
8237                 inst.dpDiv[(this._get(inst, 'isRTL') ? 'add' : 'remove') +
8238                         'Class']('ui-datepicker-rtl');
8239                 if (inst == $.datepicker._curInst && $.datepicker._datepickerShowing && inst.input &&
8240                                 inst.input.is(':visible') && !inst.input.is(':disabled'))
8241                         inst.input.focus();
8242         },
8244         /* Retrieve the size of left and top borders for an element.
8245            @param  elem  (jQuery object) the element of interest
8246            @return  (number[2]) the left and top borders */
8247         _getBorders: function(elem) {
8248                 var convert = function(value) {
8249                         return {thin: 1, medium: 2, thick: 3}[value] || value;
8250                 };
8251                 return [parseFloat(convert(elem.css('border-left-width'))),
8252                         parseFloat(convert(elem.css('border-top-width')))];
8253         },
8255         /* Check positioning to remain on screen. */
8256         _checkOffset: function(inst, offset, isFixed) {
8257                 var dpWidth = inst.dpDiv.outerWidth();
8258                 var dpHeight = inst.dpDiv.outerHeight();
8259                 var inputWidth = inst.input ? inst.input.outerWidth() : 0;
8260                 var inputHeight = inst.input ? inst.input.outerHeight() : 0;
8261                 var viewWidth = document.documentElement.clientWidth + $(document).scrollLeft();
8262                 var viewHeight = document.documentElement.clientHeight + $(document).scrollTop();
8264                 offset.left -= (this._get(inst, 'isRTL') ? (dpWidth - inputWidth) : 0);
8265                 offset.left -= (isFixed && offset.left == inst.input.offset().left) ? $(document).scrollLeft() : 0;
8266                 offset.top -= (isFixed && offset.top == (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;
8268                 // now check if datepicker is showing outside window viewport - move to a better place if so.
8269                 offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?
8270                         Math.abs(offset.left + dpWidth - viewWidth) : 0);
8271                 offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?
8272                         Math.abs(dpHeight + inputHeight) : 0);
8274                 return offset;
8275         },
8277         /* Find an object's position on the screen. */
8278         _findPos: function(obj) {
8279                 var inst = this._getInst(obj);
8280                 var isRTL = this._get(inst, 'isRTL');
8281         while (obj && (obj.type == 'hidden' || obj.nodeType != 1)) {
8282             obj = obj[isRTL ? 'previousSibling' : 'nextSibling'];
8283         }
8284         var position = $(obj).offset();
8285             return [position.left, position.top];
8286         },
8288         /* Hide the date picker from view.
8289            @param  input  element - the input field attached to the date picker */
8290         _hideDatepicker: function(input) {
8291                 var inst = this._curInst;
8292                 if (!inst || (input && inst != $.data(input, PROP_NAME)))
8293                         return;
8294                 if (this._datepickerShowing) {
8295                         var showAnim = this._get(inst, 'showAnim');
8296                         var duration = this._get(inst, 'duration');
8297                         var postProcess = function() {
8298                                 $.datepicker._tidyDialog(inst);
8299                                 this._curInst = null;
8300                         };
8301                         if ($.effects && $.effects[showAnim])
8302                                 inst.dpDiv.hide(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
8303                         else
8304                                 inst.dpDiv[(showAnim == 'slideDown' ? 'slideUp' :
8305                                         (showAnim == 'fadeIn' ? 'fadeOut' : 'hide'))]((showAnim ? duration : null), postProcess);
8306                         if (!showAnim)
8307                                 postProcess();
8308                         var onClose = this._get(inst, 'onClose');
8309                         if (onClose)
8310                                 onClose.apply((inst.input ? inst.input[0] : null),
8311                                         [(inst.input ? inst.input.val() : ''), inst]);  // trigger custom callback
8312                         this._datepickerShowing = false;
8313                         this._lastInput = null;
8314                         if (this._inDialog) {
8315                                 this._dialogInput.css({ position: 'absolute', left: '0', top: '-100px' });
8316                                 if ($.blockUI) {
8317                                         $.unblockUI();
8318                                         $('body').append(this.dpDiv);
8319                                 }
8320                         }
8321                         this._inDialog = false;
8322                 }
8323         },
8325         /* Tidy up after a dialog display. */
8326         _tidyDialog: function(inst) {
8327                 inst.dpDiv.removeClass(this._dialogClass).unbind('.ui-datepicker-calendar');
8328         },
8330         /* Close date picker if clicked elsewhere. */
8331         _checkExternalClick: function(event) {
8332                 if (!$.datepicker._curInst)
8333                         return;
8334                 var $target = $(event.target);
8335                 if ($target[0].id != $.datepicker._mainDivId &&
8336                                 $target.parents('#' + $.datepicker._mainDivId).length == 0 &&
8337                                 !$target.hasClass($.datepicker.markerClassName) &&
8338                                 !$target.hasClass($.datepicker._triggerClass) &&
8339                                 $.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI))
8340                         $.datepicker._hideDatepicker();
8341         },
8343         /* Adjust one of the date sub-fields. */
8344         _adjustDate: function(id, offset, period) {
8345                 var target = $(id);
8346                 var inst = this._getInst(target[0]);
8347                 if (this._isDisabledDatepicker(target[0])) {
8348                         return;
8349                 }
8350                 this._adjustInstDate(inst, offset +
8351                         (period == 'M' ? this._get(inst, 'showCurrentAtPos') : 0), // undo positioning
8352                         period);
8353                 this._updateDatepicker(inst);
8354         },
8356         /* Action for current link. */
8357         _gotoToday: function(id) {
8358                 var target = $(id);
8359                 var inst = this._getInst(target[0]);
8360                 if (this._get(inst, 'gotoCurrent') && inst.currentDay) {
8361                         inst.selectedDay = inst.currentDay;
8362                         inst.drawMonth = inst.selectedMonth = inst.currentMonth;
8363                         inst.drawYear = inst.selectedYear = inst.currentYear;
8364                 }
8365                 else {
8366                         var date = new Date();
8367                         inst.selectedDay = date.getDate();
8368                         inst.drawMonth = inst.selectedMonth = date.getMonth();
8369                         inst.drawYear = inst.selectedYear = date.getFullYear();
8370                 }
8371                 this._notifyChange(inst);
8372                 this._adjustDate(target);
8373         },
8375         /* Action for selecting a new month/year. */
8376         _selectMonthYear: function(id, select, period) {
8377                 var target = $(id);
8378                 var inst = this._getInst(target[0]);
8379                 inst._selectingMonthYear = false;
8380                 inst['selected' + (period == 'M' ? 'Month' : 'Year')] =
8381                 inst['draw' + (period == 'M' ? 'Month' : 'Year')] =
8382                         parseInt(select.options[select.selectedIndex].value,10);
8383                 this._notifyChange(inst);
8384                 this._adjustDate(target);
8385         },
8387         /* Restore input focus after not changing month/year. */
8388         _clickMonthYear: function(id) {
8389                 var target = $(id);
8390                 var inst = this._getInst(target[0]);
8391                 if (inst.input && inst._selectingMonthYear && !$.browser.msie)
8392                         inst.input.focus();
8393                 inst._selectingMonthYear = !inst._selectingMonthYear;
8394         },
8396         /* Action for selecting a day. */
8397         _selectDay: function(id, month, year, td) {
8398                 var target = $(id);
8399                 if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) {
8400                         return;
8401                 }
8402                 var inst = this._getInst(target[0]);
8403                 inst.selectedDay = inst.currentDay = $('a', td).html();
8404                 inst.selectedMonth = inst.currentMonth = month;
8405                 inst.selectedYear = inst.currentYear = year;
8406                 this._selectDate(id, this._formatDate(inst,
8407                         inst.currentDay, inst.currentMonth, inst.currentYear));
8408         },
8410         /* Erase the input field and hide the date picker. */
8411         _clearDate: function(id) {
8412                 var target = $(id);
8413                 var inst = this._getInst(target[0]);
8414                 this._selectDate(target, '');
8415         },
8417         /* Update the input field with the selected date. */
8418         _selectDate: function(id, dateStr) {
8419                 var target = $(id);
8420                 var inst = this._getInst(target[0]);
8421                 dateStr = (dateStr != null ? dateStr : this._formatDate(inst));
8422                 if (inst.input)
8423                         inst.input.val(dateStr);
8424                 this._updateAlternate(inst);
8425                 var onSelect = this._get(inst, 'onSelect');
8426                 if (onSelect)
8427                         onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);  // trigger custom callback
8428                 else if (inst.input)
8429                         inst.input.trigger('change'); // fire the change event
8430                 if (inst.inline)
8431                         this._updateDatepicker(inst);
8432                 else {
8433                         this._hideDatepicker();
8434                         this._lastInput = inst.input[0];
8435                         if (typeof(inst.input[0]) != 'object')
8436                                 inst.input.focus(); // restore focus
8437                         this._lastInput = null;
8438                 }
8439         },
8441         /* Update any alternate field to synchronise with the main field. */
8442         _updateAlternate: function(inst) {
8443                 var altField = this._get(inst, 'altField');
8444                 if (altField) { // update alternate field too
8445                         var altFormat = this._get(inst, 'altFormat') || this._get(inst, 'dateFormat');
8446                         var date = this._getDate(inst);
8447                         var dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst));
8448                         $(altField).each(function() { $(this).val(dateStr); });
8449                 }
8450         },
8452         /* Set as beforeShowDay function to prevent selection of weekends.
8453            @param  date  Date - the date to customise
8454            @return [boolean, string] - is this date selectable?, what is its CSS class? */
8455         noWeekends: function(date) {
8456                 var day = date.getDay();
8457                 return [(day > 0 && day < 6), ''];
8458         },
8460         /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
8461            @param  date  Date - the date to get the week for
8462            @return  number - the number of the week within the year that contains this date */
8463         iso8601Week: function(date) {
8464                 var checkDate = new Date(date.getTime());
8465                 // Find Thursday of this week starting on Monday
8466                 checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7));
8467                 var time = checkDate.getTime();
8468                 checkDate.setMonth(0); // Compare with Jan 1
8469                 checkDate.setDate(1);
8470                 return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
8471         },
8473         /* Parse a string value into a date object.
8474            See formatDate below for the possible formats.
8476            @param  format    string - the expected format of the date
8477            @param  value     string - the date in the above format
8478            @param  settings  Object - attributes include:
8479                              shortYearCutoff  number - the cutoff year for determining the century (optional)
8480                              dayNamesShort    string[7] - abbreviated names of the days from Sunday (optional)
8481                              dayNames         string[7] - names of the days from Sunday (optional)
8482                              monthNamesShort  string[12] - abbreviated names of the months (optional)
8483                              monthNames       string[12] - names of the months (optional)
8484            @return  Date - the extracted date value or null if value is blank */
8485         parseDate: function (format, value, settings) {
8486                 if (format == null || value == null)
8487                         throw 'Invalid arguments';
8488                 value = (typeof value == 'object' ? value.toString() : value + '');
8489                 if (value == '')
8490                         return null;
8491                 var shortYearCutoff = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff;
8492                 var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
8493                 var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
8494                 var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
8495                 var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
8496                 var year = -1;
8497                 var month = -1;
8498                 var day = -1;
8499                 var doy = -1;
8500                 var literal = false;
8501                 // Check whether a format character is doubled
8502                 var lookAhead = function(match) {
8503                         var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
8504                         if (matches)
8505                                 iFormat++;
8506                         return matches;
8507                 };
8508                 // Extract a number from the string value
8509                 var getNumber = function(match) {
8510                         lookAhead(match);
8511                         var size = (match == '@' ? 14 : (match == '!' ? 20 :
8512                                 (match == 'y' ? 4 : (match == 'o' ? 3 : 2))));
8513                         var digits = new RegExp('^\\d{1,' + size + '}');
8514                         var num = value.substring(iValue).match(digits);
8515                         if (!num)
8516                                 throw 'Missing number at position ' + iValue;
8517                         iValue += num[0].length;
8518                         return parseInt(num[0], 10);
8519                 };
8520                 // Extract a name from the string value and convert to an index
8521                 var getName = function(match, shortNames, longNames) {
8522                         var names = (lookAhead(match) ? longNames : shortNames);
8523                         for (var i = 0; i < names.length; i++) {
8524                                 if (value.substr(iValue, names[i].length) == names[i]) {
8525                                         iValue += names[i].length;
8526                                         return i + 1;
8527                                 }
8528                         }
8529                         throw 'Unknown name at position ' + iValue;
8530                 };
8531                 // Confirm that a literal character matches the string value
8532                 var checkLiteral = function() {
8533                         if (value.charAt(iValue) != format.charAt(iFormat))
8534                                 throw 'Unexpected literal at position ' + iValue;
8535                         iValue++;
8536                 };
8537                 var iValue = 0;
8538                 for (var iFormat = 0; iFormat < format.length; iFormat++) {
8539                         if (literal)
8540                                 if (format.charAt(iFormat) == "'" && !lookAhead("'"))
8541                                         literal = false;
8542                                 else
8543                                         checkLiteral();
8544                         else
8545                                 switch (format.charAt(iFormat)) {
8546                                         case 'd':
8547                                                 day = getNumber('d');
8548                                                 break;
8549                                         case 'D':
8550                                                 getName('D', dayNamesShort, dayNames);
8551                                                 break;
8552                                         case 'o':
8553                                                 doy = getNumber('o');
8554                                                 break;
8555                                         case 'm':
8556                                                 month = getNumber('m');
8557                                                 break;
8558                                         case 'M':
8559                                                 month = getName('M', monthNamesShort, monthNames);
8560                                                 break;
8561                                         case 'y':
8562                                                 year = getNumber('y');
8563                                                 break;
8564                                         case '@':
8565                                                 var date = new Date(getNumber('@'));
8566                                                 year = date.getFullYear();
8567                                                 month = date.getMonth() + 1;
8568                                                 day = date.getDate();
8569                                                 break;
8570                                         case '!':
8571                                                 var date = new Date((getNumber('!') - this._ticksTo1970) / 10000);
8572                                                 year = date.getFullYear();
8573                                                 month = date.getMonth() + 1;
8574                                                 day = date.getDate();
8575                                                 break;
8576                                         case "'":
8577                                                 if (lookAhead("'"))
8578                                                         checkLiteral();
8579                                                 else
8580                                                         literal = true;
8581                                                 break;
8582                                         default:
8583                                                 checkLiteral();
8584                                 }
8585                 }
8586                 if (year == -1)
8587                         year = new Date().getFullYear();
8588                 else if (year < 100)
8589                         year += new Date().getFullYear() - new Date().getFullYear() % 100 +
8590                                 (year <= shortYearCutoff ? 0 : -100);
8591                 if (doy > -1) {
8592                         month = 1;
8593                         day = doy;
8594                         do {
8595                                 var dim = this._getDaysInMonth(year, month - 1);
8596                                 if (day <= dim)
8597                                         break;
8598                                 month++;
8599                                 day -= dim;
8600                         } while (true);
8601                 }
8602                 var date = this._daylightSavingAdjust(new Date(year, month - 1, day));
8603                 if (date.getFullYear() != year || date.getMonth() + 1 != month || date.getDate() != day)
8604                         throw 'Invalid date'; // E.g. 31/02/*
8605                 return date;
8606         },
8608         /* Standard date formats. */
8609         ATOM: 'yy-mm-dd', // RFC 3339 (ISO 8601)
8610         COOKIE: 'D, dd M yy',
8611         ISO_8601: 'yy-mm-dd',
8612         RFC_822: 'D, d M y',
8613         RFC_850: 'DD, dd-M-y',
8614         RFC_1036: 'D, d M y',
8615         RFC_1123: 'D, d M yy',
8616         RFC_2822: 'D, d M yy',
8617         RSS: 'D, d M y', // RFC 822
8618         TICKS: '!',
8619         TIMESTAMP: '@',
8620         W3C: 'yy-mm-dd', // ISO 8601
8622         _ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) +
8623                 Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000),
8625         /* Format a date object into a string value.
8626            The format can be combinations of the following:
8627            d  - day of month (no leading zero)
8628            dd - day of month (two digit)
8629            o  - day of year (no leading zeros)
8630            oo - day of year (three digit)
8631            D  - day name short
8632            DD - day name long
8633            m  - month of year (no leading zero)
8634            mm - month of year (two digit)
8635            M  - month name short
8636            MM - month name long
8637            y  - year (two digit)
8638            yy - year (four digit)
8639            @ - Unix timestamp (ms since 01/01/1970)
8640            ! - Windows ticks (100ns since 01/01/0001)
8641            '...' - literal text
8642            '' - single quote
8644            @param  format    string - the desired format of the date
8645            @param  date      Date - the date value to format
8646            @param  settings  Object - attributes include:
8647                              dayNamesShort    string[7] - abbreviated names of the days from Sunday (optional)
8648                              dayNames         string[7] - names of the days from Sunday (optional)
8649                              monthNamesShort  string[12] - abbreviated names of the months (optional)
8650                              monthNames       string[12] - names of the months (optional)
8651            @return  string - the date in the above format */
8652         formatDate: function (format, date, settings) {
8653                 if (!date)
8654                         return '';
8655                 var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
8656                 var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
8657                 var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
8658                 var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
8659                 // Check whether a format character is doubled
8660                 var lookAhead = function(match) {
8661                         var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
8662                         if (matches)
8663                                 iFormat++;
8664                         return matches;
8665                 };
8666                 // Format a number, with leading zero if necessary
8667                 var formatNumber = function(match, value, len) {
8668                         var num = '' + value;
8669                         if (lookAhead(match))
8670                                 while (num.length < len)
8671                                         num = '0' + num;
8672                         return num;
8673                 };
8674                 // Format a name, short or long as requested
8675                 var formatName = function(match, value, shortNames, longNames) {
8676                         return (lookAhead(match) ? longNames[value] : shortNames[value]);
8677                 };
8678                 var output = '';
8679                 var literal = false;
8680                 if (date)
8681                         for (var iFormat = 0; iFormat < format.length; iFormat++) {
8682                                 if (literal)
8683                                         if (format.charAt(iFormat) == "'" && !lookAhead("'"))
8684                                                 literal = false;
8685                                         else
8686                                                 output += format.charAt(iFormat);
8687                                 else
8688                                         switch (format.charAt(iFormat)) {
8689                                                 case 'd':
8690                                                         output += formatNumber('d', date.getDate(), 2);
8691                                                         break;
8692                                                 case 'D':
8693                                                         output += formatName('D', date.getDay(), dayNamesShort, dayNames);
8694                                                         break;
8695                                                 case 'o':
8696                                                         output += formatNumber('o',
8697                                                                 (date.getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000, 3);
8698                                                         break;
8699                                                 case 'm':
8700                                                         output += formatNumber('m', date.getMonth() + 1, 2);
8701                                                         break;
8702                                                 case 'M':
8703                                                         output += formatName('M', date.getMonth(), monthNamesShort, monthNames);
8704                                                         break;
8705                                                 case 'y':
8706                                                         output += (lookAhead('y') ? date.getFullYear() :
8707                                                                 (date.getYear() % 100 < 10 ? '0' : '') + date.getYear() % 100);
8708                                                         break;
8709                                                 case '@':
8710                                                         output += date.getTime();
8711                                                         break;
8712                                                 case '!':
8713                                                         output += date.getTime() * 10000 + this._ticksTo1970;
8714                                                         break;
8715                                                 case "'":
8716                                                         if (lookAhead("'"))
8717                                                                 output += "'";
8718                                                         else
8719                                                                 literal = true;
8720                                                         break;
8721                                                 default:
8722                                                         output += format.charAt(iFormat);
8723                                         }
8724                         }
8725                 return output;
8726         },
8728         /* Extract all possible characters from the date format. */
8729         _possibleChars: function (format) {
8730                 var chars = '';
8731                 var literal = false;
8732                 // Check whether a format character is doubled
8733                 var lookAhead = function(match) {
8734                         var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
8735                         if (matches)
8736                                 iFormat++;
8737                         return matches;
8738                 };
8739                 for (var iFormat = 0; iFormat < format.length; iFormat++)
8740                         if (literal)
8741                                 if (format.charAt(iFormat) == "'" && !lookAhead("'"))
8742                                         literal = false;
8743                                 else
8744                                         chars += format.charAt(iFormat);
8745                         else
8746                                 switch (format.charAt(iFormat)) {
8747                                         case 'd': case 'm': case 'y': case '@':
8748                                                 chars += '0123456789';
8749                                                 break;
8750                                         case 'D': case 'M':
8751                                                 return null; // Accept anything
8752                                         case "'":
8753                                                 if (lookAhead("'"))
8754                                                         chars += "'";
8755                                                 else
8756                                                         literal = true;
8757                                                 break;
8758                                         default:
8759                                                 chars += format.charAt(iFormat);
8760                                 }
8761                 return chars;
8762         },
8764         /* Get a setting value, defaulting if necessary. */
8765         _get: function(inst, name) {
8766                 return inst.settings[name] !== undefined ?
8767                         inst.settings[name] : this._defaults[name];
8768         },
8770         /* Parse existing date and initialise date picker. */
8771         _setDateFromField: function(inst, noDefault) {
8772                 if (inst.input.val() == inst.lastVal) {
8773                         return;
8774                 }
8775                 var dateFormat = this._get(inst, 'dateFormat');
8776                 var dates = inst.lastVal = inst.input ? inst.input.val() : null;
8777                 var date, defaultDate;
8778                 date = defaultDate = this._getDefaultDate(inst);
8779                 var settings = this._getFormatConfig(inst);
8780                 try {
8781                         date = this.parseDate(dateFormat, dates, settings) || defaultDate;
8782                 } catch (event) {
8783                         this.log(event);
8784                         dates = (noDefault ? '' : dates);
8785                 }
8786                 inst.selectedDay = date.getDate();
8787                 inst.drawMonth = inst.selectedMonth = date.getMonth();
8788                 inst.drawYear = inst.selectedYear = date.getFullYear();
8789                 inst.currentDay = (dates ? date.getDate() : 0);
8790                 inst.currentMonth = (dates ? date.getMonth() : 0);
8791                 inst.currentYear = (dates ? date.getFullYear() : 0);
8792                 this._adjustInstDate(inst);
8793         },
8795         /* Retrieve the default date shown on opening. */
8796         _getDefaultDate: function(inst) {
8797                 return this._restrictMinMax(inst,
8798                         this._determineDate(inst, this._get(inst, 'defaultDate'), new Date()));
8799         },
8801         /* A date may be specified as an exact value or a relative one. */
8802         _determineDate: function(inst, date, defaultDate) {
8803                 var offsetNumeric = function(offset) {
8804                         var date = new Date();
8805                         date.setDate(date.getDate() + offset);
8806                         return date;
8807                 };
8808                 var offsetString = function(offset) {
8809                         try {
8810                                 return $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
8811                                         offset, $.datepicker._getFormatConfig(inst));
8812                         }
8813                         catch (e) {
8814                                 // Ignore
8815                         }
8816                         var date = (offset.toLowerCase().match(/^c/) ?
8817                                 $.datepicker._getDate(inst) : null) || new Date();
8818                         var year = date.getFullYear();
8819                         var month = date.getMonth();
8820                         var day = date.getDate();
8821                         var pattern = /([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g;
8822                         var matches = pattern.exec(offset);
8823                         while (matches) {
8824                                 switch (matches[2] || 'd') {
8825                                         case 'd' : case 'D' :
8826                                                 day += parseInt(matches[1],10); break;
8827                                         case 'w' : case 'W' :
8828                                                 day += parseInt(matches[1],10) * 7; break;
8829                                         case 'm' : case 'M' :
8830                                                 month += parseInt(matches[1],10);
8831                                                 day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
8832                                                 break;
8833                                         case 'y': case 'Y' :
8834                                                 year += parseInt(matches[1],10);
8835                                                 day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
8836                                                 break;
8837                                 }
8838                                 matches = pattern.exec(offset);
8839                         }
8840                         return new Date(year, month, day);
8841                 };
8842                 date = (date == null ? defaultDate : (typeof date == 'string' ? offsetString(date) :
8843                         (typeof date == 'number' ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : date)));
8844                 date = (date && date.toString() == 'Invalid Date' ? defaultDate : date);
8845                 if (date) {
8846                         date.setHours(0);
8847                         date.setMinutes(0);
8848                         date.setSeconds(0);
8849                         date.setMilliseconds(0);
8850                 }
8851                 return this._daylightSavingAdjust(date);
8852         },
8854         /* Handle switch to/from daylight saving.
8855            Hours may be non-zero on daylight saving cut-over:
8856            > 12 when midnight changeover, but then cannot generate
8857            midnight datetime, so jump to 1AM, otherwise reset.
8858            @param  date  (Date) the date to check
8859            @return  (Date) the corrected date */
8860         _daylightSavingAdjust: function(date) {
8861                 if (!date) return null;
8862                 date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
8863                 return date;
8864         },
8866         /* Set the date(s) directly. */
8867         _setDate: function(inst, date, noChange) {
8868                 var clear = !(date);
8869                 var origMonth = inst.selectedMonth;
8870                 var origYear = inst.selectedYear;
8871                 date = this._restrictMinMax(inst, this._determineDate(inst, date, new Date()));
8872                 inst.selectedDay = inst.currentDay = date.getDate();
8873                 inst.drawMonth = inst.selectedMonth = inst.currentMonth = date.getMonth();
8874                 inst.drawYear = inst.selectedYear = inst.currentYear = date.getFullYear();
8875                 if ((origMonth != inst.selectedMonth || origYear != inst.selectedYear) && !noChange)
8876                         this._notifyChange(inst);
8877                 this._adjustInstDate(inst);
8878                 if (inst.input) {
8879                         inst.input.val(clear ? '' : this._formatDate(inst));
8880                 }
8881         },
8883         /* Retrieve the date(s) directly. */
8884         _getDate: function(inst) {
8885                 var startDate = (!inst.currentYear || (inst.input && inst.input.val() == '') ? null :
8886                         this._daylightSavingAdjust(new Date(
8887                         inst.currentYear, inst.currentMonth, inst.currentDay)));
8888                         return startDate;
8889         },
8891         /* Generate the HTML for the current state of the date picker. */
8892         _generateHTML: function(inst) {
8893                 var today = new Date();
8894                 today = this._daylightSavingAdjust(
8895                         new Date(today.getFullYear(), today.getMonth(), today.getDate())); // clear time
8896                 var isRTL = this._get(inst, 'isRTL');
8897                 var showButtonPanel = this._get(inst, 'showButtonPanel');
8898                 var hideIfNoPrevNext = this._get(inst, 'hideIfNoPrevNext');
8899                 var navigationAsDateFormat = this._get(inst, 'navigationAsDateFormat');
8900                 var numMonths = this._getNumberOfMonths(inst);
8901                 var showCurrentAtPos = this._get(inst, 'showCurrentAtPos');
8902                 var stepMonths = this._get(inst, 'stepMonths');
8903                 var isMultiMonth = (numMonths[0] != 1 || numMonths[1] != 1);
8904                 var currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) :
8905                         new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
8906                 var minDate = this._getMinMaxDate(inst, 'min');
8907                 var maxDate = this._getMinMaxDate(inst, 'max');
8908                 var drawMonth = inst.drawMonth - showCurrentAtPos;
8909                 var drawYear = inst.drawYear;
8910                 if (drawMonth < 0) {
8911                         drawMonth += 12;
8912                         drawYear--;
8913                 }
8914                 if (maxDate) {
8915                         var maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),
8916                                 maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate()));
8917                         maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);
8918                         while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {
8919                                 drawMonth--;
8920                                 if (drawMonth < 0) {
8921                                         drawMonth = 11;
8922                                         drawYear--;
8923                                 }
8924                         }
8925                 }
8926                 inst.drawMonth = drawMonth;
8927                 inst.drawYear = drawYear;
8928                 var prevText = this._get(inst, 'prevText');
8929                 prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText,
8930                         this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),
8931                         this._getFormatConfig(inst)));
8932                 var prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?
8933                         '<a class="ui-datepicker-prev ui-corner-all" onclick="DP_jQuery_' + dpuuid +
8934                         '.datepicker._adjustDate(\'#' + inst.id + '\', -' + stepMonths + ', \'M\');"' +
8935                         ' title="' + prevText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>' :
8936                         (hideIfNoPrevNext ? '' : '<a class="ui-datepicker-prev ui-corner-all ui-state-disabled" title="'+ prevText +'"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>'));
8937                 var nextText = this._get(inst, 'nextText');
8938                 nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText,
8939                         this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),
8940                         this._getFormatConfig(inst)));
8941                 var next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?
8942                         '<a class="ui-datepicker-next ui-corner-all" onclick="DP_jQuery_' + dpuuid +
8943                         '.datepicker._adjustDate(\'#' + inst.id + '\', +' + stepMonths + ', \'M\');"' +
8944                         ' title="' + nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>' :
8945                         (hideIfNoPrevNext ? '' : '<a class="ui-datepicker-next ui-corner-all ui-state-disabled" title="'+ nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>'));
8946                 var currentText = this._get(inst, 'currentText');
8947                 var gotoDate = (this._get(inst, 'gotoCurrent') && inst.currentDay ? currentDate : today);
8948                 currentText = (!navigationAsDateFormat ? currentText :
8949                         this.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));
8950                 var controls = (!inst.inline ? '<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" onclick="DP_jQuery_' + dpuuid +
8951                         '.datepicker._hideDatepicker();">' + this._get(inst, 'closeText') + '</button>' : '');
8952                 var buttonPanel = (showButtonPanel) ? '<div class="ui-datepicker-buttonpane ui-widget-content">' + (isRTL ? controls : '') +
8953                         (this._isInRange(inst, gotoDate) ? '<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" onclick="DP_jQuery_' + dpuuid +
8954                         '.datepicker._gotoToday(\'#' + inst.id + '\');"' +
8955                         '>' + currentText + '</button>' : '') + (isRTL ? '' : controls) + '</div>' : '';
8956                 var firstDay = parseInt(this._get(inst, 'firstDay'),10);
8957                 firstDay = (isNaN(firstDay) ? 0 : firstDay);
8958                 var showWeek = this._get(inst, 'showWeek');
8959                 var dayNames = this._get(inst, 'dayNames');
8960                 var dayNamesShort = this._get(inst, 'dayNamesShort');
8961                 var dayNamesMin = this._get(inst, 'dayNamesMin');
8962                 var monthNames = this._get(inst, 'monthNames');
8963                 var monthNamesShort = this._get(inst, 'monthNamesShort');
8964                 var beforeShowDay = this._get(inst, 'beforeShowDay');
8965                 var showOtherMonths = this._get(inst, 'showOtherMonths');
8966                 var selectOtherMonths = this._get(inst, 'selectOtherMonths');
8967                 var calculateWeek = this._get(inst, 'calculateWeek') || this.iso8601Week;
8968                 var defaultDate = this._getDefaultDate(inst);
8969                 var html = '';
8970                 for (var row = 0; row < numMonths[0]; row++) {
8971                         var group = '';
8972                         for (var col = 0; col < numMonths[1]; col++) {
8973                                 var selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay));
8974                                 var cornerClass = ' ui-corner-all';
8975                                 var calender = '';
8976                                 if (isMultiMonth) {
8977                                         calender += '<div class="ui-datepicker-group';
8978                                         if (numMonths[1] > 1)
8979                                                 switch (col) {
8980                                                         case 0: calender += ' ui-datepicker-group-first';
8981                                                                 cornerClass = ' ui-corner-' + (isRTL ? 'right' : 'left'); break;
8982                                                         case numMonths[1]-1: calender += ' ui-datepicker-group-last';
8983                                                                 cornerClass = ' ui-corner-' + (isRTL ? 'left' : 'right'); break;
8984                                                         default: calender += ' ui-datepicker-group-middle'; cornerClass = ''; break;
8985                                                 }
8986                                         calender += '">';
8987                                 }
8988                                 calender += '<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix' + cornerClass + '">' +
8989                                         (/all|left/.test(cornerClass) && row == 0 ? (isRTL ? next : prev) : '') +
8990                                         (/all|right/.test(cornerClass) && row == 0 ? (isRTL ? prev : next) : '') +
8991                                         this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,
8992                                         row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers
8993                                         '</div><table class="ui-datepicker-calendar"><thead>' +
8994                                         '<tr>';
8995                                 var thead = (showWeek ? '<th class="ui-datepicker-week-col">' + this._get(inst, 'weekHeader') + '</th>' : '');
8996                                 for (var dow = 0; dow < 7; dow++) { // days of the week
8997                                         var day = (dow + firstDay) % 7;
8998                                         thead += '<th' + ((dow + firstDay + 6) % 7 >= 5 ? ' class="ui-datepicker-week-end"' : '') + '>' +
8999                                                 '<span title="' + dayNames[day] + '">' + dayNamesMin[day] + '</span></th>';
9000                                 }
9001                                 calender += thead + '</tr></thead><tbody>';
9002                                 var daysInMonth = this._getDaysInMonth(drawYear, drawMonth);
9003                                 if (drawYear == inst.selectedYear && drawMonth == inst.selectedMonth)
9004                                         inst.selectedDay = Math.min(inst.selectedDay, daysInMonth);
9005                                 var leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;
9006                                 var numRows = (isMultiMonth ? 6 : Math.ceil((leadDays + daysInMonth) / 7)); // calculate the number of rows to generate
9007                                 var printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
9008                                 for (var dRow = 0; dRow < numRows; dRow++) { // create date picker rows
9009                                         calender += '<tr>';
9010                                         var tbody = (!showWeek ? '' : '<td class="ui-datepicker-week-col">' +
9011                                                 this._get(inst, 'calculateWeek')(printDate) + '</td>');
9012                                         for (var dow = 0; dow < 7; dow++) { // create date picker days
9013                                                 var daySettings = (beforeShowDay ?
9014                                                         beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, '']);
9015                                                 var otherMonth = (printDate.getMonth() != drawMonth);
9016                                                 var unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] ||
9017                                                         (minDate && printDate < minDate) || (maxDate && printDate > maxDate);
9018                                                 tbody += '<td class="' +
9019                                                         ((dow + firstDay + 6) % 7 >= 5 ? ' ui-datepicker-week-end' : '') + // highlight weekends
9020                                                         (otherMonth ? ' ui-datepicker-other-month' : '') + // highlight days from other months
9021                                                         ((printDate.getTime() == selectedDate.getTime() && drawMonth == inst.selectedMonth && inst._keyEvent) || // user pressed key
9022                                                         (defaultDate.getTime() == printDate.getTime() && defaultDate.getTime() == selectedDate.getTime()) ?
9023                                                         // or defaultDate is current printedDate and defaultDate is selectedDate
9024                                                         ' ' + this._dayOverClass : '') + // highlight selected day
9025                                                         (unselectable ? ' ' + this._unselectableClass + ' ui-state-disabled': '') +  // highlight unselectable days
9026                                                         (otherMonth && !showOtherMonths ? '' : ' ' + daySettings[1] + // highlight custom dates
9027                                                         (printDate.getTime() == currentDate.getTime() ? ' ' + this._currentClass : '') + // highlight selected day
9028                                                         (printDate.getTime() == today.getTime() ? ' ui-datepicker-today' : '')) + '"' + // highlight today (if different)
9029                                                         ((!otherMonth || showOtherMonths) && daySettings[2] ? ' title="' + daySettings[2] + '"' : '') + // cell title
9030                                                         (unselectable ? '' : ' onclick="DP_jQuery_' + dpuuid + '.datepicker._selectDay(\'#' +
9031                                                         inst.id + '\',' + printDate.getMonth() + ',' + printDate.getFullYear() + ', this);return false;"') + '>' + // actions
9032                                                         (otherMonth && !showOtherMonths ? '&#xa0;' : // display for other months
9033                                                         (unselectable ? '<span class="ui-state-default">' + printDate.getDate() + '</span>' : '<a class="ui-state-default' +
9034                                                         (printDate.getTime() == today.getTime() ? ' ui-state-highlight' : '') +
9035                                                         (printDate.getTime() == currentDate.getTime() ? ' ui-state-active' : '') + // highlight selected day
9036                                                         (otherMonth ? ' ui-priority-secondary' : '') + // distinguish dates from other months
9037                                                         '" href="#">' + printDate.getDate() + '</a>')) + '</td>'; // display selectable date
9038                                                 printDate.setDate(printDate.getDate() + 1);
9039                                                 printDate = this._daylightSavingAdjust(printDate);
9040                                         }
9041                                         calender += tbody + '</tr>';
9042                                 }
9043                                 drawMonth++;
9044                                 if (drawMonth > 11) {
9045                                         drawMonth = 0;
9046                                         drawYear++;
9047                                 }
9048                                 calender += '</tbody></table>' + (isMultiMonth ? '</div>' + 
9049                                                         ((numMonths[0] > 0 && col == numMonths[1]-1) ? '<div class="ui-datepicker-row-break"></div>' : '') : '');
9050                                 group += calender;
9051                         }
9052                         html += group;
9053                 }
9054                 html += buttonPanel + ($.browser.msie && parseInt($.browser.version,10) < 7 && !inst.inline ?
9055                         '<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>' : '');
9056                 inst._keyEvent = false;
9057                 return html;
9058         },
9060         /* Generate the month and year header. */
9061         _generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate,
9062                         secondary, monthNames, monthNamesShort) {
9063                 var changeMonth = this._get(inst, 'changeMonth');
9064                 var changeYear = this._get(inst, 'changeYear');
9065                 var showMonthAfterYear = this._get(inst, 'showMonthAfterYear');
9066                 var html = '<div class="ui-datepicker-title">';
9067                 var monthHtml = '';
9068                 // month selection
9069                 if (secondary || !changeMonth)
9070                         monthHtml += '<span class="ui-datepicker-month">' + monthNames[drawMonth] + '</span>';
9071                 else {
9072                         var inMinYear = (minDate && minDate.getFullYear() == drawYear);
9073                         var inMaxYear = (maxDate && maxDate.getFullYear() == drawYear);
9074                         monthHtml += '<select class="ui-datepicker-month" ' +
9075                                 'onchange="DP_jQuery_' + dpuuid + '.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'M\');" ' +
9076                                 'onclick="DP_jQuery_' + dpuuid + '.datepicker._clickMonthYear(\'#' + inst.id + '\');"' +
9077                                 '>';
9078                         for (var month = 0; month < 12; month++) {
9079                                 if ((!inMinYear || month >= minDate.getMonth()) &&
9080                                                 (!inMaxYear || month <= maxDate.getMonth()))
9081                                         monthHtml += '<option value="' + month + '"' +
9082                                                 (month == drawMonth ? ' selected="selected"' : '') +
9083                                                 '>' + monthNamesShort[month] + '</option>';
9084                         }
9085                         monthHtml += '</select>';
9086                 }
9087                 if (!showMonthAfterYear)
9088                         html += monthHtml + (secondary || !(changeMonth && changeYear) ? '&#xa0;' : '');
9089                 // year selection
9090                 if (secondary || !changeYear)
9091                         html += '<span class="ui-datepicker-year">' + drawYear + '</span>';
9092                 else {
9093                         // determine range of years to display
9094                         var years = this._get(inst, 'yearRange').split(':');
9095                         var thisYear = new Date().getFullYear();
9096                         var determineYear = function(value) {
9097                                 var year = (value.match(/c[+-].*/) ? drawYear + parseInt(value.substring(1), 10) :
9098                                         (value.match(/[+-].*/) ? thisYear + parseInt(value, 10) :
9099                                         parseInt(value, 10)));
9100                                 return (isNaN(year) ? thisYear : year);
9101                         };
9102                         var year = determineYear(years[0]);
9103                         var endYear = Math.max(year, determineYear(years[1] || ''));
9104                         year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
9105                         endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
9106                         html += '<select class="ui-datepicker-year" ' +
9107                                 'onchange="DP_jQuery_' + dpuuid + '.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'Y\');" ' +
9108                                 'onclick="DP_jQuery_' + dpuuid + '.datepicker._clickMonthYear(\'#' + inst.id + '\');"' +
9109                                 '>';
9110                         for (; year <= endYear; year++) {
9111                                 html += '<option value="' + year + '"' +
9112                                         (year == drawYear ? ' selected="selected"' : '') +
9113                                         '>' + year + '</option>';
9114                         }
9115                         html += '</select>';
9116                 }
9117                 html += this._get(inst, 'yearSuffix');
9118                 if (showMonthAfterYear)
9119                         html += (secondary || !(changeMonth && changeYear) ? '&#xa0;' : '') + monthHtml;
9120                 html += '</div>'; // Close datepicker_header
9121                 return html;
9122         },
9124         /* Adjust one of the date sub-fields. */
9125         _adjustInstDate: function(inst, offset, period) {
9126                 var year = inst.drawYear + (period == 'Y' ? offset : 0);
9127                 var month = inst.drawMonth + (period == 'M' ? offset : 0);
9128                 var day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) +
9129                         (period == 'D' ? offset : 0);
9130                 var date = this._restrictMinMax(inst,
9131                         this._daylightSavingAdjust(new Date(year, month, day)));
9132                 inst.selectedDay = date.getDate();
9133                 inst.drawMonth = inst.selectedMonth = date.getMonth();
9134                 inst.drawYear = inst.selectedYear = date.getFullYear();
9135                 if (period == 'M' || period == 'Y')
9136                         this._notifyChange(inst);
9137         },
9139         /* Ensure a date is within any min/max bounds. */
9140         _restrictMinMax: function(inst, date) {
9141                 var minDate = this._getMinMaxDate(inst, 'min');
9142                 var maxDate = this._getMinMaxDate(inst, 'max');
9143                 date = (minDate && date < minDate ? minDate : date);
9144                 date = (maxDate && date > maxDate ? maxDate : date);
9145                 return date;
9146         },
9148         /* Notify change of month/year. */
9149         _notifyChange: function(inst) {
9150                 var onChange = this._get(inst, 'onChangeMonthYear');
9151                 if (onChange)
9152                         onChange.apply((inst.input ? inst.input[0] : null),
9153                                 [inst.selectedYear, inst.selectedMonth + 1, inst]);
9154         },
9156         /* Determine the number of months to show. */
9157         _getNumberOfMonths: function(inst) {
9158                 var numMonths = this._get(inst, 'numberOfMonths');
9159                 return (numMonths == null ? [1, 1] : (typeof numMonths == 'number' ? [1, numMonths] : numMonths));
9160         },
9162         /* Determine the current maximum date - ensure no time components are set. */
9163         _getMinMaxDate: function(inst, minMax) {
9164                 return this._determineDate(inst, this._get(inst, minMax + 'Date'), null);
9165         },
9167         /* Find the number of days in a given month. */
9168         _getDaysInMonth: function(year, month) {
9169                 return 32 - new Date(year, month, 32).getDate();
9170         },
9172         /* Find the day of the week of the first of a month. */
9173         _getFirstDayOfMonth: function(year, month) {
9174                 return new Date(year, month, 1).getDay();
9175         },
9177         /* Determines if we should allow a "next/prev" month display change. */
9178         _canAdjustMonth: function(inst, offset, curYear, curMonth) {
9179                 var numMonths = this._getNumberOfMonths(inst);
9180                 var date = this._daylightSavingAdjust(new Date(curYear,
9181                         curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1));
9182                 if (offset < 0)
9183                         date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
9184                 return this._isInRange(inst, date);
9185         },
9187         /* Is the given date in the accepted range? */
9188         _isInRange: function(inst, date) {
9189                 var minDate = this._getMinMaxDate(inst, 'min');
9190                 var maxDate = this._getMinMaxDate(inst, 'max');
9191                 return ((!minDate || date.getTime() >= minDate.getTime()) &&
9192                         (!maxDate || date.getTime() <= maxDate.getTime()));
9193         },
9195         /* Provide the configuration settings for formatting/parsing. */
9196         _getFormatConfig: function(inst) {
9197                 var shortYearCutoff = this._get(inst, 'shortYearCutoff');
9198                 shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff :
9199                         new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
9200                 return {shortYearCutoff: shortYearCutoff,
9201                         dayNamesShort: this._get(inst, 'dayNamesShort'), dayNames: this._get(inst, 'dayNames'),
9202                         monthNamesShort: this._get(inst, 'monthNamesShort'), monthNames: this._get(inst, 'monthNames')};
9203         },
9205         /* Format the given date for display. */
9206         _formatDate: function(inst, day, month, year) {
9207                 if (!day) {
9208                         inst.currentDay = inst.selectedDay;
9209                         inst.currentMonth = inst.selectedMonth;
9210                         inst.currentYear = inst.selectedYear;
9211                 }
9212                 var date = (day ? (typeof day == 'object' ? day :
9213                         this._daylightSavingAdjust(new Date(year, month, day))) :
9214                         this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
9215                 return this.formatDate(this._get(inst, 'dateFormat'), date, this._getFormatConfig(inst));
9216         }
9219 /* jQuery extend now ignores nulls! */
9220 function extendRemove(target, props) {
9221         $.extend(target, props);
9222         for (var name in props)
9223                 if (props[name] == null || props[name] == undefined)
9224                         target[name] = props[name];
9225         return target;
9228 /* Determine whether an object is an array. */
9229 function isArray(a) {
9230         return (a && (($.browser.safari && typeof a == 'object' && a.length) ||
9231                 (a.constructor && a.constructor.toString().match(/\Array\(\)/))));
9234 /* Invoke the datepicker functionality.
9235    @param  options  string - a command, optionally followed by additional parameters or
9236                     Object - settings for attaching new datepicker functionality
9237    @return  jQuery object */
9238 $.fn.datepicker = function(options){
9240         /* Initialise the date picker. */
9241         if (!$.datepicker.initialized) {
9242                 $(document).mousedown($.datepicker._checkExternalClick).
9243                         find('body').append($.datepicker.dpDiv);
9244                 $.datepicker.initialized = true;
9245         }
9247         var otherArgs = Array.prototype.slice.call(arguments, 1);
9248         if (typeof options == 'string' && (options == 'isDisabled' || options == 'getDate' || options == 'widget'))
9249                 return $.datepicker['_' + options + 'Datepicker'].
9250                         apply($.datepicker, [this[0]].concat(otherArgs));
9251         if (options == 'option' && arguments.length == 2 && typeof arguments[1] == 'string')
9252                 return $.datepicker['_' + options + 'Datepicker'].
9253                         apply($.datepicker, [this[0]].concat(otherArgs));
9254         return this.each(function() {
9255                 typeof options == 'string' ?
9256                         $.datepicker['_' + options + 'Datepicker'].
9257                                 apply($.datepicker, [this].concat(otherArgs)) :
9258                         $.datepicker._attachDatepicker(this, options);
9259         });
9262 $.datepicker = new Datepicker(); // singleton instance
9263 $.datepicker.initialized = false;
9264 $.datepicker.uuid = new Date().getTime();
9265 $.datepicker.version = "1.8";
9267 // Workaround for #4055
9268 // Add another global to avoid noConflict issues with inline event handlers
9269 window['DP_jQuery_' + dpuuid] = $;
9271 })(jQuery);
9273  * jQuery UI Progressbar 1.8
9275  * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
9276  * Dual licensed under the MIT (MIT-LICENSE.txt)
9277  * and GPL (GPL-LICENSE.txt) licenses.
9279  * http://docs.jquery.com/UI/Progressbar
9281  * Depends:
9282  *   jquery.ui.core.js
9283  *   jquery.ui.widget.js
9284  */
9285 (function( $ ) {
9287 $.widget( "ui.progressbar", {
9288         options: {
9289                 value: 0
9290         },
9291         _create: function() {
9292                 this.element
9293                         .addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
9294                         .attr({
9295                                 role: "progressbar",
9296                                 "aria-valuemin": this._valueMin(),
9297                                 "aria-valuemax": this._valueMax(),
9298                                 "aria-valuenow": this._value()
9299                         });
9301                 this.valueDiv = $( "<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>" )
9302                         .appendTo( this.element );
9304                 this._refreshValue();
9305         },
9307         destroy: function() {
9308                 this.element
9309                         .removeClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
9310                         .removeAttr( "role" )
9311                         .removeAttr( "aria-valuemin" )
9312                         .removeAttr( "aria-valuemax" )
9313                         .removeAttr( "aria-valuenow" );
9315                 this.valueDiv.remove();
9317                 $.Widget.prototype.destroy.apply( this, arguments );
9318         },
9320         value: function( newValue ) {
9321                 if ( newValue === undefined ) {
9322                         return this._value();
9323                 }
9325                 this._setOption( "value", newValue );
9326                 return this;
9327         },
9329         _setOption: function( key, value ) {
9330                 switch ( key ) {
9331                         case "value":
9332                                 this.options.value = value;
9333                                 this._refreshValue();
9334                                 this._trigger( "change" );
9335                                 break;
9336                 }
9338                 $.Widget.prototype._setOption.apply( this, arguments );
9339         },
9341         _value: function() {
9342                 var val = this.options.value;
9343                 // normalize invalid value
9344                 if ( typeof val !== "number" ) {
9345                         val = 0;
9346                 }
9347                 if ( val < this._valueMin() ) {
9348                         val = this._valueMin();
9349                 }
9350                 if ( val > this._valueMax() ) {
9351                         val = this._valueMax();
9352                 }
9354                 return val;
9355         },
9357         _valueMin: function() {
9358                 return 0;
9359         },
9361         _valueMax: function() {
9362                 return 100;
9363         },
9365         _refreshValue: function() {
9366                 var value = this.value();
9367                 this.valueDiv
9368                         [ value === this._valueMax() ? "addClass" : "removeClass"]( "ui-corner-right" )
9369                         .width( value + "%" );
9370                 this.element.attr( "aria-valuenow", value );
9371         }
9374 $.extend( $.ui.progressbar, {
9375         version: "1.8"
9378 })( jQuery );
9380  * jQuery UI Effects 1.8
9382  * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
9383  * Dual licensed under the MIT (MIT-LICENSE.txt)
9384  * and GPL (GPL-LICENSE.txt) licenses.
9386  * http://docs.jquery.com/UI/Effects/
9387  */
9388 ;jQuery.effects || (function($) {
9390 $.effects = {};
9394 /******************************************************************************/
9395 /****************************** COLOR ANIMATIONS ******************************/
9396 /******************************************************************************/
9398 // override the animation for color styles
9399 $.each(['backgroundColor', 'borderBottomColor', 'borderLeftColor',
9400         'borderRightColor', 'borderTopColor', 'color', 'outlineColor'],
9401 function(i, attr) {
9402         $.fx.step[attr] = function(fx) {
9403                 if (!fx.colorInit) {
9404                         fx.start = getColor(fx.elem, attr);
9405                         fx.end = getRGB(fx.end);
9406                         fx.colorInit = true;
9407                 }
9409                 fx.elem.style[attr] = 'rgb(' +
9410                         Math.max(Math.min(parseInt((fx.pos * (fx.end[0] - fx.start[0])) + fx.start[0], 10), 255), 0) + ',' +
9411                         Math.max(Math.min(parseInt((fx.pos * (fx.end[1] - fx.start[1])) + fx.start[1], 10), 255), 0) + ',' +
9412                         Math.max(Math.min(parseInt((fx.pos * (fx.end[2] - fx.start[2])) + fx.start[2], 10), 255), 0) + ')';
9413         };
9416 // Color Conversion functions from highlightFade
9417 // By Blair Mitchelmore
9418 // http://jquery.offput.ca/highlightFade/
9420 // Parse strings looking for color tuples [255,255,255]
9421 function getRGB(color) {
9422                 var result;
9424                 // Check if we're already dealing with an array of colors
9425                 if ( color && color.constructor == Array && color.length == 3 )
9426                                 return color;
9428                 // Look for rgb(num,num,num)
9429                 if (result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(color))
9430                                 return [parseInt(result[1],10), parseInt(result[2],10), parseInt(result[3],10)];
9432                 // Look for rgb(num%,num%,num%)
9433                 if (result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(color))
9434                                 return [parseFloat(result[1])*2.55, parseFloat(result[2])*2.55, parseFloat(result[3])*2.55];
9436                 // Look for #a0b1c2
9437                 if (result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(color))
9438                                 return [parseInt(result[1],16), parseInt(result[2],16), parseInt(result[3],16)];
9440                 // Look for #fff
9441                 if (result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(color))
9442                                 return [parseInt(result[1]+result[1],16), parseInt(result[2]+result[2],16), parseInt(result[3]+result[3],16)];
9444                 // Look for rgba(0, 0, 0, 0) == transparent in Safari 3
9445                 if (result = /rgba\(0, 0, 0, 0\)/.exec(color))
9446                                 return colors['transparent'];
9448                 // Otherwise, we're most likely dealing with a named color
9449                 return colors[$.trim(color).toLowerCase()];
9452 function getColor(elem, attr) {
9453                 var color;
9455                 do {
9456                                 color = $.curCSS(elem, attr);
9458                                 // Keep going until we find an element that has color, or we hit the body
9459                                 if ( color != '' && color != 'transparent' || $.nodeName(elem, "body") )
9460                                                 break;
9462                                 attr = "backgroundColor";
9463                 } while ( elem = elem.parentNode );
9465                 return getRGB(color);
9468 // Some named colors to work with
9469 // From Interface by Stefan Petre
9470 // http://interface.eyecon.ro/
9472 var colors = {
9473         aqua:[0,255,255],
9474         azure:[240,255,255],
9475         beige:[245,245,220],
9476         black:[0,0,0],
9477         blue:[0,0,255],
9478         brown:[165,42,42],
9479         cyan:[0,255,255],
9480         darkblue:[0,0,139],
9481         darkcyan:[0,139,139],
9482         darkgrey:[169,169,169],
9483         darkgreen:[0,100,0],
9484         darkkhaki:[189,183,107],
9485         darkmagenta:[139,0,139],
9486         darkolivegreen:[85,107,47],
9487         darkorange:[255,140,0],
9488         darkorchid:[153,50,204],
9489         darkred:[139,0,0],
9490         darksalmon:[233,150,122],
9491         darkviolet:[148,0,211],
9492         fuchsia:[255,0,255],
9493         gold:[255,215,0],
9494         green:[0,128,0],
9495         indigo:[75,0,130],
9496         khaki:[240,230,140],
9497         lightblue:[173,216,230],
9498         lightcyan:[224,255,255],
9499         lightgreen:[144,238,144],
9500         lightgrey:[211,211,211],
9501         lightpink:[255,182,193],
9502         lightyellow:[255,255,224],
9503         lime:[0,255,0],
9504         magenta:[255,0,255],
9505         maroon:[128,0,0],
9506         navy:[0,0,128],
9507         olive:[128,128,0],
9508         orange:[255,165,0],
9509         pink:[255,192,203],
9510         purple:[128,0,128],
9511         violet:[128,0,128],
9512         red:[255,0,0],
9513         silver:[192,192,192],
9514         white:[255,255,255],
9515         yellow:[255,255,0],
9516         transparent: [255,255,255]
9521 /******************************************************************************/
9522 /****************************** CLASS ANIMATIONS ******************************/
9523 /******************************************************************************/
9525 var classAnimationActions = ['add', 'remove', 'toggle'],
9526         shorthandStyles = {
9527                 border: 1,
9528                 borderBottom: 1,
9529                 borderColor: 1,
9530                 borderLeft: 1,
9531                 borderRight: 1,
9532                 borderTop: 1,
9533                 borderWidth: 1,
9534                 margin: 1,
9535                 padding: 1
9536         };
9538 function getElementStyles() {
9539         var style = document.defaultView
9540                         ? document.defaultView.getComputedStyle(this, null)
9541                         : this.currentStyle,
9542                 newStyle = {},
9543                 key,
9544                 camelCase;
9546         // webkit enumerates style porperties
9547         if (style && style.length && style[0] && style[style[0]]) {
9548                 var len = style.length;
9549                 while (len--) {
9550                         key = style[len];
9551                         if (typeof style[key] == 'string') {
9552                                 camelCase = key.replace(/\-(\w)/g, function(all, letter){
9553                                         return letter.toUpperCase();
9554                                 });
9555                                 newStyle[camelCase] = style[key];
9556                         }
9557                 }
9558         } else {
9559                 for (key in style) {
9560                         if (typeof style[key] === 'string') {
9561                                 newStyle[key] = style[key];
9562                         }
9563                 }
9564         }
9565         
9566         return newStyle;
9569 function filterStyles(styles) {
9570         var name, value;
9571         for (name in styles) {
9572                 value = styles[name];
9573                 if (
9574                         // ignore null and undefined values
9575                         value == null ||
9576                         // ignore functions (when does this occur?)
9577                         $.isFunction(value) ||
9578                         // shorthand styles that need to be expanded
9579                         name in shorthandStyles ||
9580                         // ignore scrollbars (break in IE)
9581                         (/scrollbar/).test(name) ||
9583                         // only colors or values that can be converted to numbers
9584                         (!(/color/i).test(name) && isNaN(parseFloat(value)))
9585                 ) {
9586                         delete styles[name];
9587                 }
9588         }
9589         
9590         return styles;
9593 function styleDifference(oldStyle, newStyle) {
9594         var diff = { _: 0 }, // http://dev.jquery.com/ticket/5459
9595                 name;
9597         for (name in newStyle) {
9598                 if (oldStyle[name] != newStyle[name]) {
9599                         diff[name] = newStyle[name];
9600                 }
9601         }
9603         return diff;
9606 $.effects.animateClass = function(value, duration, easing, callback) {
9607         if ($.isFunction(easing)) {
9608                 callback = easing;
9609                 easing = null;
9610         }
9612         return this.each(function() {
9614                 var that = $(this),
9615                         originalStyleAttr = that.attr('style') || ' ',
9616                         originalStyle = filterStyles(getElementStyles.call(this)),
9617                         newStyle,
9618                         className = that.attr('className');
9620                 $.each(classAnimationActions, function(i, action) {
9621                         if (value[action]) {
9622                                 that[action + 'Class'](value[action]);
9623                         }
9624                 });
9625                 newStyle = filterStyles(getElementStyles.call(this));
9626                 that.attr('className', className);
9628                 that.animate(styleDifference(originalStyle, newStyle), duration, easing, function() {
9629                         $.each(classAnimationActions, function(i, action) {
9630                                 if (value[action]) { that[action + 'Class'](value[action]); }
9631                         });
9632                         // work around bug in IE by clearing the cssText before setting it
9633                         if (typeof that.attr('style') == 'object') {
9634                                 that.attr('style').cssText = '';
9635                                 that.attr('style').cssText = originalStyleAttr;
9636                         } else {
9637                                 that.attr('style', originalStyleAttr);
9638                         }
9639                         if (callback) { callback.apply(this, arguments); }
9640                 });
9641         });
9644 $.fn.extend({
9645         _addClass: $.fn.addClass,
9646         addClass: function(classNames, speed, easing, callback) {
9647                 return speed ? $.effects.animateClass.apply(this, [{ add: classNames },speed,easing,callback]) : this._addClass(classNames);
9648         },
9650         _removeClass: $.fn.removeClass,
9651         removeClass: function(classNames,speed,easing,callback) {
9652                 return speed ? $.effects.animateClass.apply(this, [{ remove: classNames },speed,easing,callback]) : this._removeClass(classNames);
9653         },
9655         _toggleClass: $.fn.toggleClass,
9656         toggleClass: function(classNames, force, speed, easing, callback) {
9657                 if ( typeof force == "boolean" || force === undefined ) {
9658                         if ( !speed ) {
9659                                 // without speed parameter;
9660                                 return this._toggleClass(classNames, force);
9661                         } else {
9662                                 return $.effects.animateClass.apply(this, [(force?{add:classNames}:{remove:classNames}),speed,easing,callback]);
9663                         }
9664                 } else {
9665                         // without switch parameter;
9666                         return $.effects.animateClass.apply(this, [{ toggle: classNames },force,speed,easing]);
9667                 }
9668         },
9670         switchClass: function(remove,add,speed,easing,callback) {
9671                 return $.effects.animateClass.apply(this, [{ add: add, remove: remove },speed,easing,callback]);
9672         }
9677 /******************************************************************************/
9678 /*********************************** EFFECTS **********************************/
9679 /******************************************************************************/
9681 $.extend($.effects, {
9682         version: "1.8",
9684         // Saves a set of properties in a data storage
9685         save: function(element, set) {
9686                 for(var i=0; i < set.length; i++) {
9687                         if(set[i] !== null) element.data("ec.storage."+set[i], element[0].style[set[i]]);
9688                 }
9689         },
9691         // Restores a set of previously saved properties from a data storage
9692         restore: function(element, set) {
9693                 for(var i=0; i < set.length; i++) {
9694                         if(set[i] !== null) element.css(set[i], element.data("ec.storage."+set[i]));
9695                 }
9696         },
9698         setMode: function(el, mode) {
9699                 if (mode == 'toggle') mode = el.is(':hidden') ? 'show' : 'hide'; // Set for toggle
9700                 return mode;
9701         },
9703         getBaseline: function(origin, original) { // Translates a [top,left] array into a baseline value
9704                 // this should be a little more flexible in the future to handle a string & hash
9705                 var y, x;
9706                 switch (origin[0]) {
9707                         case 'top': y = 0; break;
9708                         case 'middle': y = 0.5; break;
9709                         case 'bottom': y = 1; break;
9710                         default: y = origin[0] / original.height;
9711                 };
9712                 switch (origin[1]) {
9713                         case 'left': x = 0; break;
9714                         case 'center': x = 0.5; break;
9715                         case 'right': x = 1; break;
9716                         default: x = origin[1] / original.width;
9717                 };
9718                 return {x: x, y: y};
9719         },
9721         // Wraps the element around a wrapper that copies position properties
9722         createWrapper: function(element) {
9724                 // if the element is already wrapped, return it
9725                 if (element.parent().is('.ui-effects-wrapper')) {
9726                         return element.parent();
9727                 }
9729                 // wrap the element
9730                 var props = {
9731                                 width: element.outerWidth(true),
9732                                 height: element.outerHeight(true),
9733                                 'float': element.css('float')
9734                         },
9735                         wrapper = $('<div></div>')
9736                                 .addClass('ui-effects-wrapper')
9737                                 .css({
9738                                         fontSize: '100%',
9739                                         background: 'transparent',
9740                                         border: 'none',
9741                                         margin: 0,
9742                                         padding: 0
9743                                 });
9745                 element.wrap(wrapper);
9746                 wrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually loose the reference to the wrapped element
9748                 // transfer positioning properties to the wrapper
9749                 if (element.css('position') == 'static') {
9750                         wrapper.css({ position: 'relative' });
9751                         element.css({ position: 'relative' });
9752                 } else {
9753                         $.extend(props, {
9754                                 position: element.css('position'),
9755                                 zIndex: element.css('z-index')
9756                         });
9757                         $.each(['top', 'left', 'bottom', 'right'], function(i, pos) {
9758                                 props[pos] = element.css(pos);
9759                                 if (isNaN(parseInt(props[pos], 10))) {
9760                                         props[pos] = 'auto';
9761                                 }
9762                         });
9763                         element.css({position: 'relative', top: 0, left: 0 });
9764                 }
9766                 return wrapper.css(props).show();
9767         },
9769         removeWrapper: function(element) {
9770                 if (element.parent().is('.ui-effects-wrapper'))
9771                         return element.parent().replaceWith(element);
9772                 return element;
9773         },
9775         setTransition: function(element, list, factor, value) {
9776                 value = value || {};
9777                 $.each(list, function(i, x){
9778                         unit = element.cssUnit(x);
9779                         if (unit[0] > 0) value[x] = unit[0] * factor + unit[1];
9780                 });
9781                 return value;
9782         }
9786 function _normalizeArguments(effect, options, speed, callback) {
9787         // shift params for method overloading
9788         if (typeof effect == 'object') {
9789                 callback = options;
9790                 speed = null;
9791                 options = effect;
9792                 effect = options.effect;
9793         }
9794         if ($.isFunction(options)) {
9795                 callback = options;
9796                 speed = null;
9797                 options = {};
9798         }
9799         if ($.isFunction(speed)) {
9800                 callback = speed;
9801                 speed = null;
9802         }
9803         if (typeof options == 'number' || $.fx.speeds[options]) {
9804                 callback = speed;
9805                 speed = options;
9806                 options = {};
9807         }
9809         options = options || {};
9811         speed = speed || options.duration;
9812         speed = $.fx.off ? 0 : typeof speed == 'number'
9813                 ? speed : $.fx.speeds[speed] || $.fx.speeds._default;
9815         callback = callback || options.complete;
9817         return [effect, options, speed, callback];
9820 $.fn.extend({
9821         effect: function(effect, options, speed, callback) {
9822                 var args = _normalizeArguments.apply(this, arguments),
9823                         // TODO: make effects takes actual parameters instead of a hash
9824                         args2 = {
9825                                 options: args[1],
9826                                 duration: args[2],
9827                                 callback: args[3]
9828                         },
9829                         effectMethod = $.effects[effect];
9830                 
9831                 return effectMethod && !$.fx.off ? effectMethod.call(this, args2) : this;
9832         },
9834         _show: $.fn.show,
9835         show: function(speed) {
9836                 if (!speed || typeof speed == 'number' || $.fx.speeds[speed]) {
9837                         return this._show.apply(this, arguments);
9838                 } else {
9839                         var args = _normalizeArguments.apply(this, arguments);
9840                         args[1].mode = 'show';
9841                         return this.effect.apply(this, args);
9842                 }
9843         },
9845         _hide: $.fn.hide,
9846         hide: function(speed) {
9847                 if (!speed || typeof speed == 'number' || $.fx.speeds[speed]) {
9848                         return this._hide.apply(this, arguments);
9849                 } else {
9850                         var args = _normalizeArguments.apply(this, arguments);
9851                         args[1].mode = 'hide';
9852                         return this.effect.apply(this, args);
9853                 }
9854         },
9856         // jQuery core overloads toggle and create _toggle
9857         __toggle: $.fn.toggle,
9858         toggle: function(speed) {
9859                 if (!speed || typeof speed == 'number' || $.fx.speeds[speed] ||
9860                         typeof speed == 'boolean' || $.isFunction(speed)) {
9861                         return this.__toggle.apply(this, arguments);
9862                 } else {
9863                         var args = _normalizeArguments.apply(this, arguments);
9864                         args[1].mode = 'toggle';
9865                         return this.effect.apply(this, args);
9866                 }
9867         },
9869         // helper functions
9870         cssUnit: function(key) {
9871                 var style = this.css(key), val = [];
9872                 $.each( ['em','px','%','pt'], function(i, unit){
9873                         if(style.indexOf(unit) > 0)
9874                                 val = [parseFloat(style), unit];
9875                 });
9876                 return val;
9877         }
9882 /******************************************************************************/
9883 /*********************************** EASING ***********************************/
9884 /******************************************************************************/
9887  * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
9889  * Uses the built in easing capabilities added In jQuery 1.1
9890  * to offer multiple easing options
9892  * TERMS OF USE - jQuery Easing
9894  * Open source under the BSD License.
9896  * Copyright 2008 George McGinley Smith
9897  * All rights reserved.
9899  * Redistribution and use in source and binary forms, with or without modification,
9900  * are permitted provided that the following conditions are met:
9902  * Redistributions of source code must retain the above copyright notice, this list of
9903  * conditions and the following disclaimer.
9904  * Redistributions in binary form must reproduce the above copyright notice, this list
9905  * of conditions and the following disclaimer in the documentation and/or other materials
9906  * provided with the distribution.
9908  * Neither the name of the author nor the names of contributors may be used to endorse
9909  * or promote products derived from this software without specific prior written permission.
9911  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
9912  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
9913  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
9914  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
9915  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
9916  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
9917  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
9918  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
9919  * OF THE POSSIBILITY OF SUCH DAMAGE.
9923 // t: current time, b: begInnIng value, c: change In value, d: duration
9924 $.easing.jswing = $.easing.swing;
9926 $.extend($.easing,
9928         def: 'easeOutQuad',
9929         swing: function (x, t, b, c, d) {
9930                 //alert($.easing.default);
9931                 return $.easing[$.easing.def](x, t, b, c, d);
9932         },
9933         easeInQuad: function (x, t, b, c, d) {
9934                 return c*(t/=d)*t + b;
9935         },
9936         easeOutQuad: function (x, t, b, c, d) {
9937                 return -c *(t/=d)*(t-2) + b;
9938         },
9939         easeInOutQuad: function (x, t, b, c, d) {
9940                 if ((t/=d/2) < 1) return c/2*t*t + b;
9941                 return -c/2 * ((--t)*(t-2) - 1) + b;
9942         },
9943         easeInCubic: function (x, t, b, c, d) {
9944                 return c*(t/=d)*t*t + b;
9945         },
9946         easeOutCubic: function (x, t, b, c, d) {
9947                 return c*((t=t/d-1)*t*t + 1) + b;
9948         },
9949         easeInOutCubic: function (x, t, b, c, d) {
9950                 if ((t/=d/2) < 1) return c/2*t*t*t + b;
9951                 return c/2*((t-=2)*t*t + 2) + b;
9952         },
9953         easeInQuart: function (x, t, b, c, d) {
9954                 return c*(t/=d)*t*t*t + b;
9955         },
9956         easeOutQuart: function (x, t, b, c, d) {
9957                 return -c * ((t=t/d-1)*t*t*t - 1) + b;
9958         },
9959         easeInOutQuart: function (x, t, b, c, d) {
9960                 if ((t/=d/2) < 1) return c/2*t*t*t*t + b;
9961                 return -c/2 * ((t-=2)*t*t*t - 2) + b;
9962         },
9963         easeInQuint: function (x, t, b, c, d) {
9964                 return c*(t/=d)*t*t*t*t + b;
9965         },
9966         easeOutQuint: function (x, t, b, c, d) {
9967                 return c*((t=t/d-1)*t*t*t*t + 1) + b;
9968         },
9969         easeInOutQuint: function (x, t, b, c, d) {
9970                 if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b;
9971                 return c/2*((t-=2)*t*t*t*t + 2) + b;
9972         },
9973         easeInSine: function (x, t, b, c, d) {
9974                 return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
9975         },
9976         easeOutSine: function (x, t, b, c, d) {
9977                 return c * Math.sin(t/d * (Math.PI/2)) + b;
9978         },
9979         easeInOutSine: function (x, t, b, c, d) {
9980                 return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
9981         },
9982         easeInExpo: function (x, t, b, c, d) {
9983                 return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
9984         },
9985         easeOutExpo: function (x, t, b, c, d) {
9986                 return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
9987         },
9988         easeInOutExpo: function (x, t, b, c, d) {
9989                 if (t==0) return b;
9990                 if (t==d) return b+c;
9991                 if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
9992                 return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
9993         },
9994         easeInCirc: function (x, t, b, c, d) {
9995                 return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
9996         },
9997         easeOutCirc: function (x, t, b, c, d) {
9998                 return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
9999         },
10000         easeInOutCirc: function (x, t, b, c, d) {
10001                 if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
10002                 return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
10003         },
10004         easeInElastic: function (x, t, b, c, d) {
10005                 var s=1.70158;var p=0;var a=c;
10006                 if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
10007                 if (a < Math.abs(c)) { a=c; var s=p/4; }
10008                 else var s = p/(2*Math.PI) * Math.asin (c/a);
10009                 return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
10010         },
10011         easeOutElastic: function (x, t, b, c, d) {
10012                 var s=1.70158;var p=0;var a=c;
10013                 if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
10014                 if (a < Math.abs(c)) { a=c; var s=p/4; }
10015                 else var s = p/(2*Math.PI) * Math.asin (c/a);
10016                 return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
10017         },
10018         easeInOutElastic: function (x, t, b, c, d) {
10019                 var s=1.70158;var p=0;var a=c;
10020                 if (t==0) return b;  if ((t/=d/2)==2) return b+c;  if (!p) p=d*(.3*1.5);
10021                 if (a < Math.abs(c)) { a=c; var s=p/4; }
10022                 else var s = p/(2*Math.PI) * Math.asin (c/a);
10023                 if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
10024                 return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
10025         },
10026         easeInBack: function (x, t, b, c, d, s) {
10027                 if (s == undefined) s = 1.70158;
10028                 return c*(t/=d)*t*((s+1)*t - s) + b;
10029         },
10030         easeOutBack: function (x, t, b, c, d, s) {
10031                 if (s == undefined) s = 1.70158;
10032                 return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
10033         },
10034         easeInOutBack: function (x, t, b, c, d, s) {
10035                 if (s == undefined) s = 1.70158;
10036                 if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
10037                 return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
10038         },
10039         easeInBounce: function (x, t, b, c, d) {
10040                 return c - $.easing.easeOutBounce (x, d-t, 0, c, d) + b;
10041         },
10042         easeOutBounce: function (x, t, b, c, d) {
10043                 if ((t/=d) < (1/2.75)) {
10044                         return c*(7.5625*t*t) + b;
10045                 } else if (t < (2/2.75)) {
10046                         return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
10047                 } else if (t < (2.5/2.75)) {
10048                         return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
10049                 } else {
10050                         return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
10051                 }
10052         },
10053         easeInOutBounce: function (x, t, b, c, d) {
10054                 if (t < d/2) return $.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b;
10055                 return $.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b;
10056         }
10061  * TERMS OF USE - EASING EQUATIONS
10063  * Open source under the BSD License.
10065  * Copyright 2001 Robert Penner
10066  * All rights reserved.
10068  * Redistribution and use in source and binary forms, with or without modification,
10069  * are permitted provided that the following conditions are met:
10071  * Redistributions of source code must retain the above copyright notice, this list of
10072  * conditions and the following disclaimer.
10073  * Redistributions in binary form must reproduce the above copyright notice, this list
10074  * of conditions and the following disclaimer in the documentation and/or other materials
10075  * provided with the distribution.
10077  * Neither the name of the author nor the names of contributors may be used to endorse
10078  * or promote products derived from this software without specific prior written permission.
10080  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
10081  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
10082  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
10083  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
10084  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
10085  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
10086  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
10087  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
10088  * OF THE POSSIBILITY OF SUCH DAMAGE.
10090  */
10092 })(jQuery);
10094  * jQuery UI Effects Blind 1.8
10096  * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
10097  * Dual licensed under the MIT (MIT-LICENSE.txt)
10098  * and GPL (GPL-LICENSE.txt) licenses.
10100  * http://docs.jquery.com/UI/Effects/Blind
10102  * Depends:
10103  *      jquery.effects.core.js
10104  */
10105 (function($) {
10107 $.effects.blind = function(o) {
10109         return this.queue(function() {
10111                 // Create element
10112                 var el = $(this), props = ['position','top','left'];
10114                 // Set options
10115                 var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
10116                 var direction = o.options.direction || 'vertical'; // Default direction
10118                 // Adjust
10119                 $.effects.save(el, props); el.show(); // Save & Show
10120                 var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
10121                 var ref = (direction == 'vertical') ? 'height' : 'width';
10122                 var distance = (direction == 'vertical') ? wrapper.height() : wrapper.width();
10123                 if(mode == 'show') wrapper.css(ref, 0); // Shift
10125                 // Animation
10126                 var animation = {};
10127                 animation[ref] = mode == 'show' ? distance : 0;
10129                 // Animate
10130                 wrapper.animate(animation, o.duration, o.options.easing, function() {
10131                         if(mode == 'hide') el.hide(); // Hide
10132                         $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
10133                         if(o.callback) o.callback.apply(el[0], arguments); // Callback
10134                         el.dequeue();
10135                 });
10137         });
10141 })(jQuery);
10143  * jQuery UI Effects Bounce 1.8
10145  * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
10146  * Dual licensed under the MIT (MIT-LICENSE.txt)
10147  * and GPL (GPL-LICENSE.txt) licenses.
10149  * http://docs.jquery.com/UI/Effects/Bounce
10151  * Depends:
10152  *      jquery.effects.core.js
10153  */
10154 (function($) {
10156 $.effects.bounce = function(o) {
10158         return this.queue(function() {
10160                 // Create element
10161                 var el = $(this), props = ['position','top','left'];
10163                 // Set options
10164                 var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
10165                 var direction = o.options.direction || 'up'; // Default direction
10166                 var distance = o.options.distance || 20; // Default distance
10167                 var times = o.options.times || 5; // Default # of times
10168                 var speed = o.duration || 250; // Default speed per bounce
10169                 if (/show|hide/.test(mode)) props.push('opacity'); // Avoid touching opacity to prevent clearType and PNG issues in IE
10171                 // Adjust
10172                 $.effects.save(el, props); el.show(); // Save & Show
10173                 $.effects.createWrapper(el); // Create Wrapper
10174                 var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
10175                 var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
10176                 var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) / 3 : el.outerWidth({margin:true}) / 3);
10177                 if (mode == 'show') el.css('opacity', 0).css(ref, motion == 'pos' ? -distance : distance); // Shift
10178                 if (mode == 'hide') distance = distance / (times * 2);
10179                 if (mode != 'hide') times--;
10181                 // Animate
10182                 if (mode == 'show') { // Show Bounce
10183                         var animation = {opacity: 1};
10184                         animation[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
10185                         el.animate(animation, speed / 2, o.options.easing);
10186                         distance = distance / 2;
10187                         times--;
10188                 };
10189                 for (var i = 0; i < times; i++) { // Bounces
10190                         var animation1 = {}, animation2 = {};
10191                         animation1[ref] = (motion == 'pos' ? '-=' : '+=') + distance;
10192                         animation2[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
10193                         el.animate(animation1, speed / 2, o.options.easing).animate(animation2, speed / 2, o.options.easing);
10194                         distance = (mode == 'hide') ? distance * 2 : distance / 2;
10195                 };
10196                 if (mode == 'hide') { // Last Bounce
10197                         var animation = {opacity: 0};
10198                         animation[ref] = (motion == 'pos' ? '-=' : '+=')  + distance;
10199                         el.animate(animation, speed / 2, o.options.easing, function(){
10200                                 el.hide(); // Hide
10201                                 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
10202                                 if(o.callback) o.callback.apply(this, arguments); // Callback
10203                         });
10204                 } else {
10205                         var animation1 = {}, animation2 = {};
10206                         animation1[ref] = (motion == 'pos' ? '-=' : '+=') + distance;
10207                         animation2[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
10208                         el.animate(animation1, speed / 2, o.options.easing).animate(animation2, speed / 2, o.options.easing, function(){
10209                                 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
10210                                 if(o.callback) o.callback.apply(this, arguments); // Callback
10211                         });
10212                 };
10213                 el.queue('fx', function() { el.dequeue(); });
10214                 el.dequeue();
10215         });
10219 })(jQuery);
10221  * jQuery UI Effects Clip 1.8
10223  * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
10224  * Dual licensed under the MIT (MIT-LICENSE.txt)
10225  * and GPL (GPL-LICENSE.txt) licenses.
10227  * http://docs.jquery.com/UI/Effects/Clip
10229  * Depends:
10230  *      jquery.effects.core.js
10231  */
10232 (function($) {
10234 $.effects.clip = function(o) {
10236         return this.queue(function() {
10238                 // Create element
10239                 var el = $(this), props = ['position','top','left','height','width'];
10241                 // Set options
10242                 var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
10243                 var direction = o.options.direction || 'vertical'; // Default direction
10245                 // Adjust
10246                 $.effects.save(el, props); el.show(); // Save & Show
10247                 var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
10248                 var animate = el[0].tagName == 'IMG' ? wrapper : el;
10249                 var ref = {
10250                         size: (direction == 'vertical') ? 'height' : 'width',
10251                         position: (direction == 'vertical') ? 'top' : 'left'
10252                 };
10253                 var distance = (direction == 'vertical') ? animate.height() : animate.width();
10254                 if(mode == 'show') { animate.css(ref.size, 0); animate.css(ref.position, distance / 2); } // Shift
10256                 // Animation
10257                 var animation = {};
10258                 animation[ref.size] = mode == 'show' ? distance : 0;
10259                 animation[ref.position] = mode == 'show' ? 0 : distance / 2;
10261                 // Animate
10262                 animate.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
10263                         if(mode == 'hide') el.hide(); // Hide
10264                         $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
10265                         if(o.callback) o.callback.apply(el[0], arguments); // Callback
10266                         el.dequeue();
10267                 }});
10269         });
10273 })(jQuery);
10275  * jQuery UI Effects Drop 1.8
10277  * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
10278  * Dual licensed under the MIT (MIT-LICENSE.txt)
10279  * and GPL (GPL-LICENSE.txt) licenses.
10281  * http://docs.jquery.com/UI/Effects/Drop
10283  * Depends:
10284  *      jquery.effects.core.js
10285  */
10286 (function($) {
10288 $.effects.drop = function(o) {
10290         return this.queue(function() {
10292                 // Create element
10293                 var el = $(this), props = ['position','top','left','opacity'];
10295                 // Set options
10296                 var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
10297                 var direction = o.options.direction || 'left'; // Default Direction
10299                 // Adjust
10300                 $.effects.save(el, props); el.show(); // Save & Show
10301                 $.effects.createWrapper(el); // Create Wrapper
10302                 var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
10303                 var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
10304                 var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) / 2 : el.outerWidth({margin:true}) / 2);
10305                 if (mode == 'show') el.css('opacity', 0).css(ref, motion == 'pos' ? -distance : distance); // Shift
10307                 // Animation
10308                 var animation = {opacity: mode == 'show' ? 1 : 0};
10309                 animation[ref] = (mode == 'show' ? (motion == 'pos' ? '+=' : '-=') : (motion == 'pos' ? '-=' : '+=')) + distance;
10311                 // Animate
10312                 el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
10313                         if(mode == 'hide') el.hide(); // Hide
10314                         $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
10315                         if(o.callback) o.callback.apply(this, arguments); // Callback
10316                         el.dequeue();
10317                 }});
10319         });
10323 })(jQuery);
10325  * jQuery UI Effects Explode 1.8
10327  * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
10328  * Dual licensed under the MIT (MIT-LICENSE.txt)
10329  * and GPL (GPL-LICENSE.txt) licenses.
10331  * http://docs.jquery.com/UI/Effects/Explode
10333  * Depends:
10334  *      jquery.effects.core.js
10335  */
10336 (function($) {
10338 $.effects.explode = function(o) {
10340         return this.queue(function() {
10342         var rows = o.options.pieces ? Math.round(Math.sqrt(o.options.pieces)) : 3;
10343         var cells = o.options.pieces ? Math.round(Math.sqrt(o.options.pieces)) : 3;
10345         o.options.mode = o.options.mode == 'toggle' ? ($(this).is(':visible') ? 'hide' : 'show') : o.options.mode;
10346         var el = $(this).show().css('visibility', 'hidden');
10347         var offset = el.offset();
10349         //Substract the margins - not fixing the problem yet.
10350         offset.top -= parseInt(el.css("marginTop"),10) || 0;
10351         offset.left -= parseInt(el.css("marginLeft"),10) || 0;
10353         var width = el.outerWidth(true);
10354         var height = el.outerHeight(true);
10356         for(var i=0;i<rows;i++) { // =
10357                 for(var j=0;j<cells;j++) { // ||
10358                         el
10359                                 .clone()
10360                                 .appendTo('body')
10361                                 .wrap('<div></div>')
10362                                 .css({
10363                                         position: 'absolute',
10364                                         visibility: 'visible',
10365                                         left: -j*(width/cells),
10366                                         top: -i*(height/rows)
10367                                 })
10368                                 .parent()
10369                                 .addClass('ui-effects-explode')
10370                                 .css({
10371                                         position: 'absolute',
10372                                         overflow: 'hidden',
10373                                         width: width/cells,
10374                                         height: height/rows,
10375                                         left: offset.left + j*(width/cells) + (o.options.mode == 'show' ? (j-Math.floor(cells/2))*(width/cells) : 0),
10376                                         top: offset.top + i*(height/rows) + (o.options.mode == 'show' ? (i-Math.floor(rows/2))*(height/rows) : 0),
10377                                         opacity: o.options.mode == 'show' ? 0 : 1
10378                                 }).animate({
10379                                         left: offset.left + j*(width/cells) + (o.options.mode == 'show' ? 0 : (j-Math.floor(cells/2))*(width/cells)),
10380                                         top: offset.top + i*(height/rows) + (o.options.mode == 'show' ? 0 : (i-Math.floor(rows/2))*(height/rows)),
10381                                         opacity: o.options.mode == 'show' ? 1 : 0
10382                                 }, o.duration || 500);
10383                 }
10384         }
10386         // Set a timeout, to call the callback approx. when the other animations have finished
10387         setTimeout(function() {
10389                 o.options.mode == 'show' ? el.css({ visibility: 'visible' }) : el.css({ visibility: 'visible' }).hide();
10390                                 if(o.callback) o.callback.apply(el[0]); // Callback
10391                                 el.dequeue();
10393                                 $('div.ui-effects-explode').remove();
10395         }, o.duration || 500);
10398         });
10402 })(jQuery);
10404  * jQuery UI Effects Fold 1.8
10406  * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
10407  * Dual licensed under the MIT (MIT-LICENSE.txt)
10408  * and GPL (GPL-LICENSE.txt) licenses.
10410  * http://docs.jquery.com/UI/Effects/Fold
10412  * Depends:
10413  *      jquery.effects.core.js
10414  */
10415 (function($) {
10417 $.effects.fold = function(o) {
10419         return this.queue(function() {
10421                 // Create element
10422                 var el = $(this), props = ['position','top','left'];
10424                 // Set options
10425                 var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
10426                 var size = o.options.size || 15; // Default fold size
10427                 var horizFirst = !(!o.options.horizFirst); // Ensure a boolean value
10428                 var duration = o.duration ? o.duration / 2 : $.fx.speeds._default / 2;
10430                 // Adjust
10431                 $.effects.save(el, props); el.show(); // Save & Show
10432                 var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
10433                 var widthFirst = ((mode == 'show') != horizFirst);
10434                 var ref = widthFirst ? ['width', 'height'] : ['height', 'width'];
10435                 var distance = widthFirst ? [wrapper.width(), wrapper.height()] : [wrapper.height(), wrapper.width()];
10436                 var percent = /([0-9]+)%/.exec(size);
10437                 if(percent) size = parseInt(percent[1],10) / 100 * distance[mode == 'hide' ? 0 : 1];
10438                 if(mode == 'show') wrapper.css(horizFirst ? {height: 0, width: size} : {height: size, width: 0}); // Shift
10440                 // Animation
10441                 var animation1 = {}, animation2 = {};
10442                 animation1[ref[0]] = mode == 'show' ? distance[0] : size;
10443                 animation2[ref[1]] = mode == 'show' ? distance[1] : 0;
10445                 // Animate
10446                 wrapper.animate(animation1, duration, o.options.easing)
10447                 .animate(animation2, duration, o.options.easing, function() {
10448                         if(mode == 'hide') el.hide(); // Hide
10449                         $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
10450                         if(o.callback) o.callback.apply(el[0], arguments); // Callback
10451                         el.dequeue();
10452                 });
10454         });
10458 })(jQuery);
10460  * jQuery UI Effects Highlight 1.8
10462  * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
10463  * Dual licensed under the MIT (MIT-LICENSE.txt)
10464  * and GPL (GPL-LICENSE.txt) licenses.
10466  * http://docs.jquery.com/UI/Effects/Highlight
10468  * Depends:
10469  *      jquery.effects.core.js
10470  */
10471 (function($) {
10473 $.effects.highlight = function(o) {
10474         return this.queue(function() {
10475                 var elem = $(this),
10476                         props = ['backgroundImage', 'backgroundColor', 'opacity'],
10477                         mode = $.effects.setMode(elem, o.options.mode || 'show'),
10478                         animation = {
10479                                 backgroundColor: elem.css('backgroundColor')
10480                         };
10482                 if (mode == 'hide') {
10483                         animation.opacity = 0;
10484                 }
10486                 $.effects.save(elem, props);
10487                 elem
10488                         .show()
10489                         .css({
10490                                 backgroundImage: 'none',
10491                                 backgroundColor: o.options.color || '#ffff99'
10492                         })
10493                         .animate(animation, {
10494                                 queue: false,
10495                                 duration: o.duration,
10496                                 easing: o.options.easing,
10497                                 complete: function() {
10498                                         (mode == 'hide' && elem.hide());
10499                                         $.effects.restore(elem, props);
10500                                         (mode == 'show' && !$.support.opacity && this.style.removeAttribute('filter'));
10501                                         (o.callback && o.callback.apply(this, arguments));
10502                                         elem.dequeue();
10503                                 }
10504                         });
10505         });
10508 })(jQuery);
10510  * jQuery UI Effects Pulsate 1.8
10512  * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
10513  * Dual licensed under the MIT (MIT-LICENSE.txt)
10514  * and GPL (GPL-LICENSE.txt) licenses.
10516  * http://docs.jquery.com/UI/Effects/Pulsate
10518  * Depends:
10519  *      jquery.effects.core.js
10520  */
10521 (function($) {
10523 $.effects.pulsate = function(o) {
10524         return this.queue(function() {
10525                 var elem = $(this),
10526                         mode = $.effects.setMode(elem, o.options.mode || 'show');
10527                         times = ((o.options.times || 5) * 2) - 1;
10528                         duration = o.duration ? o.duration / 2 : $.fx.speeds._default / 2,
10529                         isVisible = elem.is(':visible'),
10530                         animateTo = 0;
10532                 if (!isVisible) {
10533                         elem.css('opacity', 0).show();
10534                         animateTo = 1;
10535                 }
10537                 if ((mode == 'hide' && isVisible) || (mode == 'show' && !isVisible)) {
10538                         times--;
10539                 }
10541                 for (var i = 0; i < times; i++) {
10542                         elem.animate({ opacity: animateTo }, duration, o.options.easing);
10543                         animateTo = (animateTo + 1) % 2;
10544                 }
10546                 elem.animate({ opacity: animateTo }, duration, o.options.easing, function() {
10547                         if (animateTo == 0) {
10548                                 elem.hide();
10549                         }
10550                         (o.callback && o.callback.apply(this, arguments));
10551                 });
10553                 elem
10554                         .queue('fx', function() { elem.dequeue(); })
10555                         .dequeue();
10556         });
10559 })(jQuery);
10561  * jQuery UI Effects Scale 1.8
10563  * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
10564  * Dual licensed under the MIT (MIT-LICENSE.txt)
10565  * and GPL (GPL-LICENSE.txt) licenses.
10567  * http://docs.jquery.com/UI/Effects/Scale
10569  * Depends:
10570  *      jquery.effects.core.js
10571  */
10572 (function($) {
10574 $.effects.puff = function(o) {
10575         return this.queue(function() {
10576                 var elem = $(this),
10577                         mode = $.effects.setMode(elem, o.options.mode || 'hide'),
10578                         percent = parseInt(o.options.percent, 10) || 150,
10579                         factor = percent / 100,
10580                         original = { height: elem.height(), width: elem.width() };
10582                 $.extend(o.options, {
10583                         fade: true,
10584                         mode: mode,
10585                         percent: mode == 'hide' ? percent : 100,
10586                         from: mode == 'hide'
10587                                 ? original
10588                                 : {
10589                                         height: original.height * factor,
10590                                         width: original.width * factor
10591                                 }
10592                 });
10594                 elem.effect('scale', o.options, o.duration, o.callback);
10595                 elem.dequeue();
10596         });
10599 $.effects.scale = function(o) {
10601         return this.queue(function() {
10603                 // Create element
10604                 var el = $(this);
10606                 // Set options
10607                 var options = $.extend(true, {}, o.options);
10608                 var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
10609                 var percent = parseInt(o.options.percent,10) || (parseInt(o.options.percent,10) == 0 ? 0 : (mode == 'hide' ? 0 : 100)); // Set default scaling percent
10610                 var direction = o.options.direction || 'both'; // Set default axis
10611                 var origin = o.options.origin; // The origin of the scaling
10612                 if (mode != 'effect') { // Set default origin and restore for show/hide
10613                         options.origin = origin || ['middle','center'];
10614                         options.restore = true;
10615                 }
10616                 var original = {height: el.height(), width: el.width()}; // Save original
10617                 el.from = o.options.from || (mode == 'show' ? {height: 0, width: 0} : original); // Default from state
10619                 // Adjust
10620                 var factor = { // Set scaling factor
10621                         y: direction != 'horizontal' ? (percent / 100) : 1,
10622                         x: direction != 'vertical' ? (percent / 100) : 1
10623                 };
10624                 el.to = {height: original.height * factor.y, width: original.width * factor.x}; // Set to state
10626                 if (o.options.fade) { // Fade option to support puff
10627                         if (mode == 'show') {el.from.opacity = 0; el.to.opacity = 1;};
10628                         if (mode == 'hide') {el.from.opacity = 1; el.to.opacity = 0;};
10629                 };
10631                 // Animation
10632                 options.from = el.from; options.to = el.to; options.mode = mode;
10634                 // Animate
10635                 el.effect('size', options, o.duration, o.callback);
10636                 el.dequeue();
10637         });
10641 $.effects.size = function(o) {
10643         return this.queue(function() {
10645                 // Create element
10646                 var el = $(this), props = ['position','top','left','width','height','overflow','opacity'];
10647                 var props1 = ['position','top','left','overflow','opacity']; // Always restore
10648                 var props2 = ['width','height','overflow']; // Copy for children
10649                 var cProps = ['fontSize'];
10650                 var vProps = ['borderTopWidth', 'borderBottomWidth', 'paddingTop', 'paddingBottom'];
10651                 var hProps = ['borderLeftWidth', 'borderRightWidth', 'paddingLeft', 'paddingRight'];
10653                 // Set options
10654                 var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
10655                 var restore = o.options.restore || false; // Default restore
10656                 var scale = o.options.scale || 'both'; // Default scale mode
10657                 var origin = o.options.origin; // The origin of the sizing
10658                 var original = {height: el.height(), width: el.width()}; // Save original
10659                 el.from = o.options.from || original; // Default from state
10660                 el.to = o.options.to || original; // Default to state
10661                 // Adjust
10662                 if (origin) { // Calculate baseline shifts
10663                         var baseline = $.effects.getBaseline(origin, original);
10664                         el.from.top = (original.height - el.from.height) * baseline.y;
10665                         el.from.left = (original.width - el.from.width) * baseline.x;
10666                         el.to.top = (original.height - el.to.height) * baseline.y;
10667                         el.to.left = (original.width - el.to.width) * baseline.x;
10668                 };
10669                 var factor = { // Set scaling factor
10670                         from: {y: el.from.height / original.height, x: el.from.width / original.width},
10671                         to: {y: el.to.height / original.height, x: el.to.width / original.width}
10672                 };
10673                 if (scale == 'box' || scale == 'both') { // Scale the css box
10674                         if (factor.from.y != factor.to.y) { // Vertical props scaling
10675                                 props = props.concat(vProps);
10676                                 el.from = $.effects.setTransition(el, vProps, factor.from.y, el.from);
10677                                 el.to = $.effects.setTransition(el, vProps, factor.to.y, el.to);
10678                         };
10679                         if (factor.from.x != factor.to.x) { // Horizontal props scaling
10680                                 props = props.concat(hProps);
10681                                 el.from = $.effects.setTransition(el, hProps, factor.from.x, el.from);
10682                                 el.to = $.effects.setTransition(el, hProps, factor.to.x, el.to);
10683                         };
10684                 };
10685                 if (scale == 'content' || scale == 'both') { // Scale the content
10686                         if (factor.from.y != factor.to.y) { // Vertical props scaling
10687                                 props = props.concat(cProps);
10688                                 el.from = $.effects.setTransition(el, cProps, factor.from.y, el.from);
10689                                 el.to = $.effects.setTransition(el, cProps, factor.to.y, el.to);
10690                         };
10691                 };
10692                 $.effects.save(el, restore ? props : props1); el.show(); // Save & Show
10693                 $.effects.createWrapper(el); // Create Wrapper
10694                 el.css('overflow','hidden').css(el.from); // Shift
10696                 // Animate
10697                 if (scale == 'content' || scale == 'both') { // Scale the children
10698                         vProps = vProps.concat(['marginTop','marginBottom']).concat(cProps); // Add margins/font-size
10699                         hProps = hProps.concat(['marginLeft','marginRight']); // Add margins
10700                         props2 = props.concat(vProps).concat(hProps); // Concat
10701                         el.find("*[width]").each(function(){
10702                                 child = $(this);
10703                                 if (restore) $.effects.save(child, props2);
10704                                 var c_original = {height: child.height(), width: child.width()}; // Save original
10705                                 child.from = {height: c_original.height * factor.from.y, width: c_original.width * factor.from.x};
10706                                 child.to = {height: c_original.height * factor.to.y, width: c_original.width * factor.to.x};
10707                                 if (factor.from.y != factor.to.y) { // Vertical props scaling
10708                                         child.from = $.effects.setTransition(child, vProps, factor.from.y, child.from);
10709                                         child.to = $.effects.setTransition(child, vProps, factor.to.y, child.to);
10710                                 };
10711                                 if (factor.from.x != factor.to.x) { // Horizontal props scaling
10712                                         child.from = $.effects.setTransition(child, hProps, factor.from.x, child.from);
10713                                         child.to = $.effects.setTransition(child, hProps, factor.to.x, child.to);
10714                                 };
10715                                 child.css(child.from); // Shift children
10716                                 child.animate(child.to, o.duration, o.options.easing, function(){
10717                                         if (restore) $.effects.restore(child, props2); // Restore children
10718                                 }); // Animate children
10719                         });
10720                 };
10722                 // Animate
10723                 el.animate(el.to, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
10724                         if (el.to.opacity === 0) {
10725                                 el.css('opacity', el.from.opacity);
10726                         }
10727                         if(mode == 'hide') el.hide(); // Hide
10728                         $.effects.restore(el, restore ? props : props1); $.effects.removeWrapper(el); // Restore
10729                         if(o.callback) o.callback.apply(this, arguments); // Callback
10730                         el.dequeue();
10731                 }});
10733         });
10737 })(jQuery);
10739  * jQuery UI Effects Shake 1.8
10741  * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
10742  * Dual licensed under the MIT (MIT-LICENSE.txt)
10743  * and GPL (GPL-LICENSE.txt) licenses.
10745  * http://docs.jquery.com/UI/Effects/Shake
10747  * Depends:
10748  *      jquery.effects.core.js
10749  */
10750 (function($) {
10752 $.effects.shake = function(o) {
10754         return this.queue(function() {
10756                 // Create element
10757                 var el = $(this), props = ['position','top','left'];
10759                 // Set options
10760                 var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
10761                 var direction = o.options.direction || 'left'; // Default direction
10762                 var distance = o.options.distance || 20; // Default distance
10763                 var times = o.options.times || 3; // Default # of times
10764                 var speed = o.duration || o.options.duration || 140; // Default speed per shake
10766                 // Adjust
10767                 $.effects.save(el, props); el.show(); // Save & Show
10768                 $.effects.createWrapper(el); // Create Wrapper
10769                 var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
10770                 var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
10772                 // Animation
10773                 var animation = {}, animation1 = {}, animation2 = {};
10774                 animation[ref] = (motion == 'pos' ? '-=' : '+=')  + distance;
10775                 animation1[ref] = (motion == 'pos' ? '+=' : '-=')  + distance * 2;
10776                 animation2[ref] = (motion == 'pos' ? '-=' : '+=')  + distance * 2;
10778                 // Animate
10779                 el.animate(animation, speed, o.options.easing);
10780                 for (var i = 1; i < times; i++) { // Shakes
10781                         el.animate(animation1, speed, o.options.easing).animate(animation2, speed, o.options.easing);
10782                 };
10783                 el.animate(animation1, speed, o.options.easing).
10784                 animate(animation, speed / 2, o.options.easing, function(){ // Last shake
10785                         $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
10786                         if(o.callback) o.callback.apply(this, arguments); // Callback
10787                 });
10788                 el.queue('fx', function() { el.dequeue(); });
10789                 el.dequeue();
10790         });
10794 })(jQuery);
10796  * jQuery UI Effects Slide 1.8
10798  * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
10799  * Dual licensed under the MIT (MIT-LICENSE.txt)
10800  * and GPL (GPL-LICENSE.txt) licenses.
10802  * http://docs.jquery.com/UI/Effects/Slide
10804  * Depends:
10805  *      jquery.effects.core.js
10806  */
10807 (function($) {
10809 $.effects.slide = function(o) {
10811         return this.queue(function() {
10813                 // Create element
10814                 var el = $(this), props = ['position','top','left'];
10816                 // Set options
10817                 var mode = $.effects.setMode(el, o.options.mode || 'show'); // Set Mode
10818                 var direction = o.options.direction || 'left'; // Default Direction
10820                 // Adjust
10821                 $.effects.save(el, props); el.show(); // Save & Show
10822                 $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
10823                 var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
10824                 var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
10825                 var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) : el.outerWidth({margin:true}));
10826                 if (mode == 'show') el.css(ref, motion == 'pos' ? -distance : distance); // Shift
10828                 // Animation
10829                 var animation = {};
10830                 animation[ref] = (mode == 'show' ? (motion == 'pos' ? '+=' : '-=') : (motion == 'pos' ? '-=' : '+=')) + distance;
10832                 // Animate
10833                 el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
10834                         if(mode == 'hide') el.hide(); // Hide
10835                         $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
10836                         if(o.callback) o.callback.apply(this, arguments); // Callback
10837                         el.dequeue();
10838                 }});
10840         });
10844 })(jQuery);
10846  * jQuery UI Effects Transfer 1.8
10848  * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
10849  * Dual licensed under the MIT (MIT-LICENSE.txt)
10850  * and GPL (GPL-LICENSE.txt) licenses.
10852  * http://docs.jquery.com/UI/Effects/Transfer
10854  * Depends:
10855  *      jquery.effects.core.js
10856  */
10857 (function($) {
10859 $.effects.transfer = function(o) {
10860         return this.queue(function() {
10861                 var elem = $(this),
10862                         target = $(o.options.to),
10863                         endPosition = target.offset(),
10864                         animation = {
10865                                 top: endPosition.top,
10866                                 left: endPosition.left,
10867                                 height: target.innerHeight(),
10868                                 width: target.innerWidth()
10869                         },
10870                         startPosition = elem.offset(),
10871                         transfer = $('<div class="ui-effects-transfer"></div>')
10872                                 .appendTo(document.body)
10873                                 .addClass(o.options.className)
10874                                 .css({
10875                                         top: startPosition.top,
10876                                         left: startPosition.left,
10877                                         height: elem.innerHeight(),
10878                                         width: elem.innerWidth(),
10879                                         position: 'absolute'
10880                                 })
10881                                 .animate(animation, o.duration, o.options.easing, function() {
10882                                         transfer.remove();
10883                                         (o.callback && o.callback.apply(elem[0], arguments));
10884                                         elem.dequeue();
10885                                 });
10886         });
10889 })(jQuery);