external library initial commit
[dwaf.git] / externals / jquery-ui-1.8 / ui / jquery-ui.js
blob0bf2ea33924a53322ec64c3d56ed54555c0ceec9
1 /*!\r
2  * jQuery UI 1.8\r
3  *\r
4  * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)\r
5  * Dual licensed under the MIT (MIT-LICENSE.txt)\r
6  * and GPL (GPL-LICENSE.txt) licenses.\r
7  *\r
8  * http://docs.jquery.com/UI\r
9  */\r
10 ;jQuery.ui || (function($) {\r
12 //Helper functions and ui object\r
13 $.ui = {\r
14         version: "1.8",\r
16         // $.ui.plugin is deprecated.  Use the proxy pattern instead.\r
17         plugin: {\r
18                 add: function(module, option, set) {\r
19                         var proto = $.ui[module].prototype;\r
20                         for(var i in set) {\r
21                                 proto.plugins[i] = proto.plugins[i] || [];\r
22                                 proto.plugins[i].push([option, set[i]]);\r
23                         }\r
24                 },\r
25                 call: function(instance, name, args) {\r
26                         var set = instance.plugins[name];\r
27                         if(!set || !instance.element[0].parentNode) { return; }\r
29                         for (var i = 0; i < set.length; i++) {\r
30                                 if (instance.options[set[i][0]]) {\r
31                                         set[i][1].apply(instance.element, args);\r
32                                 }\r
33                         }\r
34                 }\r
35         },\r
37         contains: function(a, b) {\r
38                 return document.compareDocumentPosition\r
39                         ? a.compareDocumentPosition(b) & 16\r
40                         : a !== b && a.contains(b);\r
41         },\r
43         hasScroll: function(el, a) {\r
45                 //If overflow is hidden, the element might have extra content, but the user wants to hide it\r
46                 if ($(el).css('overflow') == 'hidden') { return false; }\r
48                 var scroll = (a && a == 'left') ? 'scrollLeft' : 'scrollTop',\r
49                         has = false;\r
51                 if (el[scroll] > 0) { return true; }\r
53                 // TODO: determine which cases actually cause this to happen\r
54                 // if the element doesn't have the scroll set, see if it's possible to\r
55                 // set the scroll\r
56                 el[scroll] = 1;\r
57                 has = (el[scroll] > 0);\r
58                 el[scroll] = 0;\r
59                 return has;\r
60         },\r
62         isOverAxis: function(x, reference, size) {\r
63                 //Determines when x coordinate is over "b" element axis\r
64                 return (x > reference) && (x < (reference + size));\r
65         },\r
67         isOver: function(y, x, top, left, height, width) {\r
68                 //Determines when x, y coordinates is over "b" element\r
69                 return $.ui.isOverAxis(y, top, height) && $.ui.isOverAxis(x, left, width);\r
70         },\r
72         keyCode: {\r
73                 BACKSPACE: 8,\r
74                 CAPS_LOCK: 20,\r
75                 COMMA: 188,\r
76                 CONTROL: 17,\r
77                 DELETE: 46,\r
78                 DOWN: 40,\r
79                 END: 35,\r
80                 ENTER: 13,\r
81                 ESCAPE: 27,\r
82                 HOME: 36,\r
83                 INSERT: 45,\r
84                 LEFT: 37,\r
85                 NUMPAD_ADD: 107,\r
86                 NUMPAD_DECIMAL: 110,\r
87                 NUMPAD_DIVIDE: 111,\r
88                 NUMPAD_ENTER: 108,\r
89                 NUMPAD_MULTIPLY: 106,\r
90                 NUMPAD_SUBTRACT: 109,\r
91                 PAGE_DOWN: 34,\r
92                 PAGE_UP: 33,\r
93                 PERIOD: 190,\r
94                 RIGHT: 39,\r
95                 SHIFT: 16,\r
96                 SPACE: 32,\r
97                 TAB: 9,\r
98                 UP: 38\r
99         }\r
100 };\r
102 //jQuery plugins\r
103 $.fn.extend({\r
104         _focus: $.fn.focus,\r
105         focus: function(delay, fn) {\r
106                 return typeof delay === 'number'\r
107                         ? this.each(function() {\r
108                                 var elem = this;\r
109                                 setTimeout(function() {\r
110                                         $(elem).focus();\r
111                                         (fn && fn.call(elem));\r
112                                 }, delay);\r
113                         })\r
114                         : this._focus.apply(this, arguments);\r
115         },\r
116         \r
117         enableSelection: function() {\r
118                 return this\r
119                         .attr('unselectable', 'off')\r
120                         .css('MozUserSelect', '')\r
121                         .unbind('selectstart.ui');\r
122         },\r
124         disableSelection: function() {\r
125                 return this\r
126                         .attr('unselectable', 'on')\r
127                         .css('MozUserSelect', 'none')\r
128                         .bind('selectstart.ui', function() { return false; });\r
129         },\r
131         scrollParent: function() {\r
132                 var scrollParent;\r
133                 if(($.browser.msie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) {\r
134                         scrollParent = this.parents().filter(function() {\r
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));\r
136                         }).eq(0);\r
137                 } else {\r
138                         scrollParent = this.parents().filter(function() {\r
139                                 return (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));\r
140                         }).eq(0);\r
141                 }\r
143                 return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent;\r
144         },\r
146         zIndex: function(zIndex) {\r
147                 if (zIndex !== undefined) {\r
148                         return this.css('zIndex', zIndex);\r
149                 }\r
150                 \r
151                 if (this.length) {\r
152                         var elem = $(this[0]), position, value;\r
153                         while (elem.length && elem[0] !== document) {\r
154                                 // Ignore z-index if position is set to a value where z-index is ignored by the browser\r
155                                 // This makes behavior of this function consistent across browsers\r
156                                 // WebKit always returns auto if the element is positioned\r
157                                 position = elem.css('position');\r
158                                 if (position == 'absolute' || position == 'relative' || position == 'fixed')\r
159                                 {\r
160                                         // IE returns 0 when zIndex is not specified\r
161                                         // other browsers return a string\r
162                                         // we ignore the case of nested elements with an explicit value of 0\r
163                                         // <div style="z-index: -10;"><div style="z-index: 0;"></div></div>\r
164                                         value = parseInt(elem.css('zIndex'));\r
165                                         if (!isNaN(value) && value != 0) {\r
166                                                 return value;\r
167                                         }\r
168                                 }\r
169                                 elem = elem.parent();\r
170                         }\r
171                 }\r
173                 return 0;\r
174         }\r
175 });\r
178 //Additional selectors\r
179 $.extend($.expr[':'], {\r
180         data: function(elem, i, match) {\r
181                 return !!$.data(elem, match[3]);\r
182         },\r
184         focusable: function(element) {\r
185                 var nodeName = element.nodeName.toLowerCase(),\r
186                         tabIndex = $.attr(element, 'tabindex');\r
187                 return (/input|select|textarea|button|object/.test(nodeName)\r
188                         ? !element.disabled\r
189                         : 'a' == nodeName || 'area' == nodeName\r
190                                 ? element.href || !isNaN(tabIndex)\r
191                                 : !isNaN(tabIndex))\r
192                         // the element and all of its ancestors must be visible\r
193                         // the browser may report that the area is hidden\r
194                         && !$(element)['area' == nodeName ? 'parents' : 'closest'](':hidden').length;\r
195         },\r
197         tabbable: function(element) {\r
198                 var tabIndex = $.attr(element, 'tabindex');\r
199                 return (isNaN(tabIndex) || tabIndex >= 0) && $(element).is(':focusable');\r
200         }\r
201 });\r
203 })(jQuery);\r
204 /*!\r
205  * jQuery UI Widget 1.8\r
206  *\r
207  * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)\r
208  * Dual licensed under the MIT (MIT-LICENSE.txt)\r
209  * and GPL (GPL-LICENSE.txt) licenses.\r
210  *\r
211  * http://docs.jquery.com/UI/Widget\r
212  */\r
213 (function( $ ) {\r
215 var _remove = $.fn.remove;\r
217 $.fn.remove = function( selector, keepData ) {\r
218         return this.each(function() {\r
219                 if ( !keepData ) {\r
220                         if ( !selector || $.filter( selector, [ this ] ).length ) {\r
221                                 $( "*", this ).add( this ).each(function() {\r
222                                         $( this ).triggerHandler( "remove" );\r
223                                 });\r
224                         }\r
225                 }\r
226                 return _remove.call( $(this), selector, keepData );\r
227         });\r
228 };\r
230 $.widget = function( name, base, prototype ) {\r
231         var namespace = name.split( "." )[ 0 ],\r
232                 fullName;\r
233         name = name.split( "." )[ 1 ];\r
234         fullName = namespace + "-" + name;\r
236         if ( !prototype ) {\r
237                 prototype = base;\r
238                 base = $.Widget;\r
239         }\r
241         // create selector for plugin\r
242         $.expr[ ":" ][ fullName ] = function( elem ) {\r
243                 return !!$.data( elem, name );\r
244         };\r
246         $[ namespace ] = $[ namespace ] || {};\r
247         $[ namespace ][ name ] = function( options, element ) {\r
248                 // allow instantiation without initializing for simple inheritance\r
249                 if ( arguments.length ) {\r
250                         this._createWidget( options, element );\r
251                 }\r
252         };\r
254         var basePrototype = new base();\r
255         // we need to make the options hash a property directly on the new instance\r
256         // otherwise we'll modify the options hash on the prototype that we're\r
257         // inheriting from\r
258 //      $.each( basePrototype, function( key, val ) {\r
259 //              if ( $.isPlainObject(val) ) {\r
260 //                      basePrototype[ key ] = $.extend( {}, val );\r
261 //              }\r
262 //      });\r
263         basePrototype.options = $.extend( {}, basePrototype.options );\r
264         $[ namespace ][ name ].prototype = $.extend( true, basePrototype, {\r
265                 namespace: namespace,\r
266                 widgetName: name,\r
267                 widgetEventPrefix: $[ namespace ][ name ].prototype.widgetEventPrefix || name,\r
268                 widgetBaseClass: fullName\r
269         }, prototype );\r
271         $.widget.bridge( name, $[ namespace ][ name ] );\r
272 };\r
274 $.widget.bridge = function( name, object ) {\r
275         $.fn[ name ] = function( options ) {\r
276                 var isMethodCall = typeof options === "string",\r
277                         args = Array.prototype.slice.call( arguments, 1 ),\r
278                         returnValue = this;\r
280                 // allow multiple hashes to be passed on init\r
281                 options = !isMethodCall && args.length ?\r
282                         $.extend.apply( null, [ true, options ].concat(args) ) :\r
283                         options;\r
285                 // prevent calls to internal methods\r
286                 if ( isMethodCall && options.substring( 0, 1 ) === "_" ) {\r
287                         return returnValue;\r
288                 }\r
290                 if ( isMethodCall ) {\r
291                         this.each(function() {\r
292                                 var instance = $.data( this, name ),\r
293                                         methodValue = instance && $.isFunction( instance[options] ) ?\r
294                                                 instance[ options ].apply( instance, args ) :\r
295                                                 instance;\r
296                                 if ( methodValue !== instance && methodValue !== undefined ) {\r
297                                         returnValue = methodValue;\r
298                                         return false;\r
299                                 }\r
300                         });\r
301                 } else {\r
302                         this.each(function() {\r
303                                 var instance = $.data( this, name );\r
304                                 if ( instance ) {\r
305                                         if ( options ) {\r
306                                                 instance.option( options );\r
307                                         }\r
308                                         instance._init();\r
309                                 } else {\r
310                                         $.data( this, name, new object( options, this ) );\r
311                                 }\r
312                         });\r
313                 }\r
315                 return returnValue;\r
316         };\r
317 };\r
319 $.Widget = function( options, element ) {\r
320         // allow instantiation without initializing for simple inheritance\r
321         if ( arguments.length ) {\r
322                 this._createWidget( options, element );\r
323         }\r
324 };\r
326 $.Widget.prototype = {\r
327         widgetName: "widget",\r
328         widgetEventPrefix: "",\r
329         options: {\r
330                 disabled: false\r
331         },\r
332         _createWidget: function( options, element ) {\r
333                 // $.widget.bridge stores the plugin instance, but we do it anyway\r
334                 // so that it's stored even before the _create function runs\r
335                 this.element = $( element ).data( this.widgetName, this );\r
336                 this.options = $.extend( true, {},\r
337                         this.options,\r
338                         $.metadata && $.metadata.get( element )[ this.widgetName ],\r
339                         options );\r
341                 var self = this;\r
342                 this.element.bind( "remove." + this.widgetName, function() {\r
343                         self.destroy();\r
344                 });\r
346                 this._create();\r
347                 this._init();\r
348         },\r
349         _create: function() {},\r
350         _init: function() {},\r
352         destroy: function() {\r
353                 this.element\r
354                         .unbind( "." + this.widgetName )\r
355                         .removeData( this.widgetName );\r
356                 this.widget()\r
357                         .unbind( "." + this.widgetName )\r
358                         .removeAttr( "aria-disabled" )\r
359                         .removeClass(\r
360                                 this.widgetBaseClass + "-disabled " +\r
361                                 this.namespace + "-state-disabled" );\r
362         },\r
364         widget: function() {\r
365                 return this.element;\r
366         },\r
368         option: function( key, value ) {\r
369                 var options = key,\r
370                         self = this;\r
372                 if ( arguments.length === 0 ) {\r
373                         // don't return a reference to the internal hash\r
374                         return $.extend( {}, self.options );\r
375                 }\r
377                 if  (typeof key === "string" ) {\r
378                         if ( value === undefined ) {\r
379                                 return this.options[ key ];\r
380                         }\r
381                         options = {};\r
382                         options[ key ] = value;\r
383                 }\r
385                 $.each( options, function( key, value ) {\r
386                         self._setOption( key, value );\r
387                 });\r
389                 return self;\r
390         },\r
391         _setOption: function( key, value ) {\r
392                 this.options[ key ] = value;\r
394                 if ( key === "disabled" ) {\r
395                         this.widget()\r
396                                 [ value ? "addClass" : "removeClass"](\r
397                                         this.widgetBaseClass + "-disabled" + " " +\r
398                                         this.namespace + "-state-disabled" )\r
399                                 .attr( "aria-disabled", value );\r
400                 }\r
402                 return this;\r
403         },\r
405         enable: function() {\r
406                 return this._setOption( "disabled", false );\r
407         },\r
408         disable: function() {\r
409                 return this._setOption( "disabled", true );\r
410         },\r
412         _trigger: function( type, event, data ) {\r
413                 var callback = this.options[ type ];\r
415                 event = $.Event( event );\r
416                 event.type = ( type === this.widgetEventPrefix ?\r
417                         type :\r
418                         this.widgetEventPrefix + type ).toLowerCase();\r
419                 data = data || {};\r
421                 // copy original event properties over to the new event\r
422                 // this would happen if we could call $.event.fix instead of $.Event\r
423                 // but we don't have a way to force an event to be fixed multiple times\r
424                 if ( event.originalEvent ) {\r
425                         for ( var i = $.event.props.length, prop; i; ) {\r
426                                 prop = $.event.props[ --i ];\r
427                                 event[ prop ] = event.originalEvent[ prop ];\r
428                         }\r
429                 }\r
431                 this.element.trigger( event, data );\r
433                 return !( $.isFunction(callback) &&\r
434                         callback.call( this.element[0], event, data ) === false ||\r
435                         event.isDefaultPrevented() );\r
436         }\r
437 };\r
439 })( jQuery );\r
440 /*!\r
441  * jQuery UI Mouse 1.8\r
442  *\r
443  * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)\r
444  * Dual licensed under the MIT (MIT-LICENSE.txt)\r
445  * and GPL (GPL-LICENSE.txt) licenses.\r
446  *\r
447  * http://docs.jquery.com/UI/Mouse\r
448  *\r
449  * Depends:\r
450  *      jquery.ui.widget.js\r
451  */\r
452 (function($) {\r
454 $.widget("ui.mouse", {\r
455         options: {\r
456                 cancel: ':input,option',\r
457                 distance: 1,\r
458                 delay: 0\r
459         },\r
460         _mouseInit: function() {\r
461                 var self = this;\r
463                 this.element\r
464                         .bind('mousedown.'+this.widgetName, function(event) {\r
465                                 return self._mouseDown(event);\r
466                         })\r
467                         .bind('click.'+this.widgetName, function(event) {\r
468                                 if(self._preventClickEvent) {\r
469                                         self._preventClickEvent = false;\r
470                                         event.stopImmediatePropagation();\r
471                                         return false;\r
472                                 }\r
473                         });\r
475                 this.started = false;\r
476         },\r
478         // TODO: make sure destroying one instance of mouse doesn't mess with\r
479         // other instances of mouse\r
480         _mouseDestroy: function() {\r
481                 this.element.unbind('.'+this.widgetName);\r
482         },\r
484         _mouseDown: function(event) {\r
485                 // don't let more than one widget handle mouseStart\r
486                 // TODO: figure out why we have to use originalEvent\r
487                 event.originalEvent = event.originalEvent || {};\r
488                 if (event.originalEvent.mouseHandled) { return; }\r
490                 // we may have missed mouseup (out of window)\r
491                 (this._mouseStarted && this._mouseUp(event));\r
493                 this._mouseDownEvent = event;\r
495                 var self = this,\r
496                         btnIsLeft = (event.which == 1),\r
497                         elIsCancel = (typeof this.options.cancel == "string" ? $(event.target).parents().add(event.target).filter(this.options.cancel).length : false);\r
498                 if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {\r
499                         return true;\r
500                 }\r
502                 this.mouseDelayMet = !this.options.delay;\r
503                 if (!this.mouseDelayMet) {\r
504                         this._mouseDelayTimer = setTimeout(function() {\r
505                                 self.mouseDelayMet = true;\r
506                         }, this.options.delay);\r
507                 }\r
509                 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {\r
510                         this._mouseStarted = (this._mouseStart(event) !== false);\r
511                         if (!this._mouseStarted) {\r
512                                 event.preventDefault();\r
513                                 return true;\r
514                         }\r
515                 }\r
517                 // these delegates are required to keep context\r
518                 this._mouseMoveDelegate = function(event) {\r
519                         return self._mouseMove(event);\r
520                 };\r
521                 this._mouseUpDelegate = function(event) {\r
522                         return self._mouseUp(event);\r
523                 };\r
524                 $(document)\r
525                         .bind('mousemove.'+this.widgetName, this._mouseMoveDelegate)\r
526                         .bind('mouseup.'+this.widgetName, this._mouseUpDelegate);\r
528                 // preventDefault() is used to prevent the selection of text here -\r
529                 // however, in Safari, this causes select boxes not to be selectable\r
530                 // anymore, so this fix is needed\r
531                 ($.browser.safari || event.preventDefault());\r
533                 event.originalEvent.mouseHandled = true;\r
534                 return true;\r
535         },\r
537         _mouseMove: function(event) {\r
538                 // IE mouseup check - mouseup happened when mouse was out of window\r
539                 if ($.browser.msie && !event.button) {\r
540                         return this._mouseUp(event);\r
541                 }\r
543                 if (this._mouseStarted) {\r
544                         this._mouseDrag(event);\r
545                         return event.preventDefault();\r
546                 }\r
548                 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {\r
549                         this._mouseStarted =\r
550                                 (this._mouseStart(this._mouseDownEvent, event) !== false);\r
551                         (this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));\r
552                 }\r
554                 return !this._mouseStarted;\r
555         },\r
557         _mouseUp: function(event) {\r
558                 $(document)\r
559                         .unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate)\r
560                         .unbind('mouseup.'+this.widgetName, this._mouseUpDelegate);\r
562                 if (this._mouseStarted) {\r
563                         this._mouseStarted = false;\r
564                         this._preventClickEvent = (event.target == this._mouseDownEvent.target);\r
565                         this._mouseStop(event);\r
566                 }\r
568                 return false;\r
569         },\r
571         _mouseDistanceMet: function(event) {\r
572                 return (Math.max(\r
573                                 Math.abs(this._mouseDownEvent.pageX - event.pageX),\r
574                                 Math.abs(this._mouseDownEvent.pageY - event.pageY)\r
575                         ) >= this.options.distance\r
576                 );\r
577         },\r
579         _mouseDelayMet: function(event) {\r
580                 return this.mouseDelayMet;\r
581         },\r
583         // These are placeholder methods, to be overriden by extending plugin\r
584         _mouseStart: function(event) {},\r
585         _mouseDrag: function(event) {},\r
586         _mouseStop: function(event) {},\r
587         _mouseCapture: function(event) { return true; }\r
588 });\r
590 })(jQuery);\r
591 /*\r
592  * jQuery UI Draggable 1.8\r
593  *\r
594  * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)\r
595  * Dual licensed under the MIT (MIT-LICENSE.txt)\r
596  * and GPL (GPL-LICENSE.txt) licenses.\r
597  *\r
598  * http://docs.jquery.com/UI/Draggables\r
599  *\r
600  * Depends:\r
601  *      jquery.ui.core.js\r
602  *      jquery.ui.mouse.js\r
603  *      jquery.ui.widget.js\r
604  */\r
605 (function($) {\r
607 $.widget("ui.draggable", $.ui.mouse, {\r
608         widgetEventPrefix: "drag",\r
609         options: {\r
610                 addClasses: true,\r
611                 appendTo: "parent",\r
612                 axis: false,\r
613                 connectToSortable: false,\r
614                 containment: false,\r
615                 cursor: "auto",\r
616                 cursorAt: false,\r
617                 grid: false,\r
618                 handle: false,\r
619                 helper: "original",\r
620                 iframeFix: false,\r
621                 opacity: false,\r
622                 refreshPositions: false,\r
623                 revert: false,\r
624                 revertDuration: 500,\r
625                 scope: "default",\r
626                 scroll: true,\r
627                 scrollSensitivity: 20,\r
628                 scrollSpeed: 20,\r
629                 snap: false,\r
630                 snapMode: "both",\r
631                 snapTolerance: 20,\r
632                 stack: false,\r
633                 zIndex: false\r
634         },\r
635         _create: function() {\r
637                 if (this.options.helper == 'original' && !(/^(?:r|a|f)/).test(this.element.css("position")))\r
638                         this.element[0].style.position = 'relative';\r
640                 (this.options.addClasses && this.element.addClass("ui-draggable"));\r
641                 (this.options.disabled && this.element.addClass("ui-draggable-disabled"));\r
643                 this._mouseInit();\r
645         },\r
647         destroy: function() {\r
648                 if(!this.element.data('draggable')) return;\r
649                 this.element\r
650                         .removeData("draggable")\r
651                         .unbind(".draggable")\r
652                         .removeClass("ui-draggable"\r
653                                 + " ui-draggable-dragging"\r
654                                 + " ui-draggable-disabled");\r
655                 this._mouseDestroy();\r
657                 return this;\r
658         },\r
660         _mouseCapture: function(event) {\r
662                 var o = this.options;\r
664                 // among others, prevent a drag on a resizable-handle\r
665                 if (this.helper || o.disabled || $(event.target).is('.ui-resizable-handle'))\r
666                         return false;\r
668                 //Quit if we're not on a valid handle\r
669                 this.handle = this._getHandle(event);\r
670                 if (!this.handle)\r
671                         return false;\r
673                 return true;\r
675         },\r
677         _mouseStart: function(event) {\r
679                 var o = this.options;\r
681                 //Create and append the visible helper\r
682                 this.helper = this._createHelper(event);\r
684                 //Cache the helper size\r
685                 this._cacheHelperProportions();\r
687                 //If ddmanager is used for droppables, set the global draggable\r
688                 if($.ui.ddmanager)\r
689                         $.ui.ddmanager.current = this;\r
691                 /*\r
692                  * - Position generation -\r
693                  * This block generates everything position related - it's the core of draggables.\r
694                  */\r
696                 //Cache the margins of the original element\r
697                 this._cacheMargins();\r
699                 //Store the helper's css position\r
700                 this.cssPosition = this.helper.css("position");\r
701                 this.scrollParent = this.helper.scrollParent();\r
703                 //The element's absolute position on the page minus margins\r
704                 this.offset = this.positionAbs = this.element.offset();\r
705                 this.offset = {\r
706                         top: this.offset.top - this.margins.top,\r
707                         left: this.offset.left - this.margins.left\r
708                 };\r
710                 $.extend(this.offset, {\r
711                         click: { //Where the click happened, relative to the element\r
712                                 left: event.pageX - this.offset.left,\r
713                                 top: event.pageY - this.offset.top\r
714                         },\r
715                         parent: this._getParentOffset(),\r
716                         relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper\r
717                 });\r
719                 //Generate the original position\r
720                 this.originalPosition = this.position = this._generatePosition(event);\r
721                 this.originalPageX = event.pageX;\r
722                 this.originalPageY = event.pageY;\r
724                 //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied\r
725                 (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));\r
727                 //Set a containment if given in the options\r
728                 if(o.containment)\r
729                         this._setContainment();\r
731                 //Trigger event + callbacks\r
732                 if(this._trigger("start", event) === false) {\r
733                         this._clear();\r
734                         return false;\r
735                 }\r
737                 //Recache the helper size\r
738                 this._cacheHelperProportions();\r
740                 //Prepare the droppable offsets\r
741                 if ($.ui.ddmanager && !o.dropBehaviour)\r
742                         $.ui.ddmanager.prepareOffsets(this, event);\r
744                 this.helper.addClass("ui-draggable-dragging");\r
745                 this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position\r
746                 return true;\r
747         },\r
749         _mouseDrag: function(event, noPropagation) {\r
751                 //Compute the helpers position\r
752                 this.position = this._generatePosition(event);\r
753                 this.positionAbs = this._convertPositionTo("absolute");\r
755                 //Call plugins and callbacks and use the resulting position if something is returned\r
756                 if (!noPropagation) {\r
757                         var ui = this._uiHash();\r
758                         if(this._trigger('drag', event, ui) === false) {\r
759                                 this._mouseUp({});\r
760                                 return false;\r
761                         }\r
762                         this.position = ui.position;\r
763                 }\r
765                 if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';\r
766                 if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';\r
767                 if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);\r
769                 return false;\r
770         },\r
772         _mouseStop: function(event) {\r
774                 //If we are using droppables, inform the manager about the drop\r
775                 var dropped = false;\r
776                 if ($.ui.ddmanager && !this.options.dropBehaviour)\r
777                         dropped = $.ui.ddmanager.drop(this, event);\r
779                 //if a drop comes from outside (a sortable)\r
780                 if(this.dropped) {\r
781                         dropped = this.dropped;\r
782                         this.dropped = false;\r
783                 }\r
784                 \r
785                 //if the original element is removed, don't bother to continue\r
786                 if(!this.element[0] || !this.element[0].parentNode)\r
787                         return false;\r
789                 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))) {\r
790                         var self = this;\r
791                         $(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() {\r
792                                 if(self._trigger("stop", event) !== false) {\r
793                                         self._clear();\r
794                                 }\r
795                         });\r
796                 } else {\r
797                         if(this._trigger("stop", event) !== false) {\r
798                                 this._clear();\r
799                         }\r
800                 }\r
802                 return false;\r
803         },\r
804         \r
805         cancel: function() {\r
806                 \r
807                 if(this.helper.is(".ui-draggable-dragging")) {\r
808                         this._mouseUp({});\r
809                 } else {\r
810                         this._clear();\r
811                 }\r
812                 \r
813                 return this;\r
814                 \r
815         },\r
817         _getHandle: function(event) {\r
819                 var handle = !this.options.handle || !$(this.options.handle, this.element).length ? true : false;\r
820                 $(this.options.handle, this.element)\r
821                         .find("*")\r
822                         .andSelf()\r
823                         .each(function() {\r
824                                 if(this == event.target) handle = true;\r
825                         });\r
827                 return handle;\r
829         },\r
831         _createHelper: function(event) {\r
833                 var o = this.options;\r
834                 var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper == 'clone' ? this.element.clone() : this.element);\r
836                 if(!helper.parents('body').length)\r
837                         helper.appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo));\r
839                 if(helper[0] != this.element[0] && !(/(fixed|absolute)/).test(helper.css("position")))\r
840                         helper.css("position", "absolute");\r
842                 return helper;\r
844         },\r
846         _adjustOffsetFromHelper: function(obj) {\r
847                 if (typeof obj == 'string') {\r
848                         obj = obj.split(' ');\r
849                 }\r
850                 if ($.isArray(obj)) {\r
851                         obj = {left: +obj[0], top: +obj[1] || 0};\r
852                 }\r
853                 if ('left' in obj) {\r
854                         this.offset.click.left = obj.left + this.margins.left;\r
855                 }\r
856                 if ('right' in obj) {\r
857                         this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;\r
858                 }\r
859                 if ('top' in obj) {\r
860                         this.offset.click.top = obj.top + this.margins.top;\r
861                 }\r
862                 if ('bottom' in obj) {\r
863                         this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;\r
864                 }\r
865         },\r
867         _getParentOffset: function() {\r
869                 //Get the offsetParent and cache its position\r
870                 this.offsetParent = this.helper.offsetParent();\r
871                 var po = this.offsetParent.offset();\r
873                 // This is a special case where we need to modify a offset calculated on start, since the following happened:\r
874                 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent\r
875                 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that\r
876                 //    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag\r
877                 if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) {\r
878                         po.left += this.scrollParent.scrollLeft();\r
879                         po.top += this.scrollParent.scrollTop();\r
880                 }\r
882                 if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information\r
883                 || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix\r
884                         po = { top: 0, left: 0 };\r
886                 return {\r
887                         top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),\r
888                         left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)\r
889                 };\r
891         },\r
893         _getRelativeOffset: function() {\r
895                 if(this.cssPosition == "relative") {\r
896                         var p = this.element.position();\r
897                         return {\r
898                                 top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),\r
899                                 left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()\r
900                         };\r
901                 } else {\r
902                         return { top: 0, left: 0 };\r
903                 }\r
905         },\r
907         _cacheMargins: function() {\r
908                 this.margins = {\r
909                         left: (parseInt(this.element.css("marginLeft"),10) || 0),\r
910                         top: (parseInt(this.element.css("marginTop"),10) || 0)\r
911                 };\r
912         },\r
914         _cacheHelperProportions: function() {\r
915                 this.helperProportions = {\r
916                         width: this.helper.outerWidth(),\r
917                         height: this.helper.outerHeight()\r
918                 };\r
919         },\r
921         _setContainment: function() {\r
923                 var o = this.options;\r
924                 if(o.containment == 'parent') o.containment = this.helper[0].parentNode;\r
925                 if(o.containment == 'document' || o.containment == 'window') this.containment = [\r
926                         0 - this.offset.relative.left - this.offset.parent.left,\r
927                         0 - this.offset.relative.top - this.offset.parent.top,\r
928                         $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,\r
929                         ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top\r
930                 ];\r
932                 if(!(/^(document|window|parent)$/).test(o.containment) && o.containment.constructor != Array) {\r
933                         var ce = $(o.containment)[0]; if(!ce) return;\r
934                         var co = $(o.containment).offset();\r
935                         var over = ($(ce).css("overflow") != 'hidden');\r
937                         this.containment = [\r
938                                 co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,\r
939                                 co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,\r
940                                 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,\r
941                                 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\r
942                         ];\r
943                 } else if(o.containment.constructor == Array) {\r
944                         this.containment = o.containment;\r
945                 }\r
947         },\r
949         _convertPositionTo: function(d, pos) {\r
951                 if(!pos) pos = this.position;\r
952                 var mod = d == "absolute" ? 1 : -1;\r
953                 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);\r
955                 return {\r
956                         top: (\r
957                                 pos.top                                                                                                                                 // The absolute mouse position\r
958                                 + this.offset.relative.top * mod                                                                                // Only for relative positioned nodes: Relative offset from element to offset parent\r
959                                 + this.offset.parent.top * mod                                                                                  // The offsetParent's offset without borders (offset + border)\r
960                                 - ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)\r
961                         ),\r
962                         left: (\r
963                                 pos.left                                                                                                                                // The absolute mouse position\r
964                                 + this.offset.relative.left * mod                                                                               // Only for relative positioned nodes: Relative offset from element to offset parent\r
965                                 + this.offset.parent.left * mod                                                                                 // The offsetParent's offset without borders (offset + border)\r
966                                 - ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)\r
967                         )\r
968                 };\r
970         },\r
972         _generatePosition: function(event) {\r
974                 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);\r
975                 var pageX = event.pageX;\r
976                 var pageY = event.pageY;\r
978                 /*\r
979                  * - Position constraining -\r
980                  * Constrain the position to a mix of grid, containment.\r
981                  */\r
983                 if(this.originalPosition) { //If we are not dragging yet, we won't check for options\r
985                         if(this.containment) {\r
986                                 if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left;\r
987                                 if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top;\r
988                                 if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left;\r
989                                 if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top;\r
990                         }\r
992                         if(o.grid) {\r
993                                 var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];\r
994                                 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;\r
996                                 var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];\r
997                                 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;\r
998                         }\r
1000                 }\r
1002                 return {\r
1003                         top: (\r
1004                                 pageY                                                                                                                           // The absolute mouse position\r
1005                                 - this.offset.click.top                                                                                                 // Click offset (relative to the element)\r
1006                                 - this.offset.relative.top                                                                                              // Only for relative positioned nodes: Relative offset from element to offset parent\r
1007                                 - this.offset.parent.top                                                                                                // The offsetParent's offset without borders (offset + border)\r
1008                                 + ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))\r
1009                         ),\r
1010                         left: (\r
1011                                 pageX                                                                                                                           // The absolute mouse position\r
1012                                 - this.offset.click.left                                                                                                // Click offset (relative to the element)\r
1013                                 - this.offset.relative.left                                                                                             // Only for relative positioned nodes: Relative offset from element to offset parent\r
1014                                 - this.offset.parent.left                                                                                               // The offsetParent's offset without borders (offset + border)\r
1015                                 + ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))\r
1016                         )\r
1017                 };\r
1019         },\r
1021         _clear: function() {\r
1022                 this.helper.removeClass("ui-draggable-dragging");\r
1023                 if(this.helper[0] != this.element[0] && !this.cancelHelperRemoval) this.helper.remove();\r
1024                 //if($.ui.ddmanager) $.ui.ddmanager.current = null;\r
1025                 this.helper = null;\r
1026                 this.cancelHelperRemoval = false;\r
1027         },\r
1029         // From now on bulk stuff - mainly helpers\r
1031         _trigger: function(type, event, ui) {\r
1032                 ui = ui || this._uiHash();\r
1033                 $.ui.plugin.call(this, type, [event, ui]);\r
1034                 if(type == "drag") this.positionAbs = this._convertPositionTo("absolute"); //The absolute position has to be recalculated after plugins\r
1035                 return $.Widget.prototype._trigger.call(this, type, event, ui);\r
1036         },\r
1038         plugins: {},\r
1040         _uiHash: function(event) {\r
1041                 return {\r
1042                         helper: this.helper,\r
1043                         position: this.position,\r
1044                         originalPosition: this.originalPosition,\r
1045                         offset: this.positionAbs\r
1046                 };\r
1047         }\r
1049 });\r
1051 $.extend($.ui.draggable, {\r
1052         version: "1.8"\r
1053 });\r
1055 $.ui.plugin.add("draggable", "connectToSortable", {\r
1056         start: function(event, ui) {\r
1058                 var inst = $(this).data("draggable"), o = inst.options,\r
1059                         uiSortable = $.extend({}, ui, { item: inst.element });\r
1060                 inst.sortables = [];\r
1061                 $(o.connectToSortable).each(function() {\r
1062                         var sortable = $.data(this, 'sortable');\r
1063                         if (sortable && !sortable.options.disabled) {\r
1064                                 inst.sortables.push({\r
1065                                         instance: sortable,\r
1066                                         shouldRevert: sortable.options.revert\r
1067                                 });\r
1068                                 sortable._refreshItems();       //Do a one-time refresh at start to refresh the containerCache\r
1069                                 sortable._trigger("activate", event, uiSortable);\r
1070                         }\r
1071                 });\r
1073         },\r
1074         stop: function(event, ui) {\r
1076                 //If we are still over the sortable, we fake the stop event of the sortable, but also remove helper\r
1077                 var inst = $(this).data("draggable"),\r
1078                         uiSortable = $.extend({}, ui, { item: inst.element });\r
1080                 $.each(inst.sortables, function() {\r
1081                         if(this.instance.isOver) {\r
1083                                 this.instance.isOver = 0;\r
1085                                 inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance\r
1086                                 this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work)\r
1088                                 //The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: 'valid/invalid'\r
1089                                 if(this.shouldRevert) this.instance.options.revert = true;\r
1091                                 //Trigger the stop of the sortable\r
1092                                 this.instance._mouseStop(event);\r
1094                                 this.instance.options.helper = this.instance.options._helper;\r
1096                                 //If the helper has been the original item, restore properties in the sortable\r
1097                                 if(inst.options.helper == 'original')\r
1098                                         this.instance.currentItem.css({ top: 'auto', left: 'auto' });\r
1100                         } else {\r
1101                                 this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance\r
1102                                 this.instance._trigger("deactivate", event, uiSortable);\r
1103                         }\r
1105                 });\r
1107         },\r
1108         drag: function(event, ui) {\r
1110                 var inst = $(this).data("draggable"), self = this;\r
1112                 var checkPos = function(o) {\r
1113                         var dyClick = this.offset.click.top, dxClick = this.offset.click.left;\r
1114                         var helperTop = this.positionAbs.top, helperLeft = this.positionAbs.left;\r
1115                         var itemHeight = o.height, itemWidth = o.width;\r
1116                         var itemTop = o.top, itemLeft = o.left;\r
1118                         return $.ui.isOver(helperTop + dyClick, helperLeft + dxClick, itemTop, itemLeft, itemHeight, itemWidth);\r
1119                 };\r
1121                 $.each(inst.sortables, function(i) {\r
1122                         \r
1123                         //Copy over some variables to allow calling the sortable's native _intersectsWith\r
1124                         this.instance.positionAbs = inst.positionAbs;\r
1125                         this.instance.helperProportions = inst.helperProportions;\r
1126                         this.instance.offset.click = inst.offset.click;\r
1127                         \r
1128                         if(this.instance._intersectsWith(this.instance.containerCache)) {\r
1130                                 //If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once\r
1131                                 if(!this.instance.isOver) {\r
1133                                         this.instance.isOver = 1;\r
1134                                         //Now we fake the start of dragging for the sortable instance,\r
1135                                         //by cloning the list group item, appending it to the sortable and using it as inst.currentItem\r
1136                                         //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)\r
1137                                         this.instance.currentItem = $(self).clone().appendTo(this.instance.element).data("sortable-item", true);\r
1138                                         this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it\r
1139                                         this.instance.options.helper = function() { return ui.helper[0]; };\r
1141                                         event.target = this.instance.currentItem[0];\r
1142                                         this.instance._mouseCapture(event, true);\r
1143                                         this.instance._mouseStart(event, true, true);\r
1145                                         //Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes\r
1146                                         this.instance.offset.click.top = inst.offset.click.top;\r
1147                                         this.instance.offset.click.left = inst.offset.click.left;\r
1148                                         this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left;\r
1149                                         this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top;\r
1151                                         inst._trigger("toSortable", event);\r
1152                                         inst.dropped = this.instance.element; //draggable revert needs that\r
1153                                         //hack so receive/update callbacks work (mostly)\r
1154                                         inst.currentItem = inst.element;\r
1155                                         this.instance.fromOutside = inst;\r
1157                                 }\r
1159                                 //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\r
1160                                 if(this.instance.currentItem) this.instance._mouseDrag(event);\r
1162                         } else {\r
1164                                 //If it doesn't intersect with the sortable, and it intersected before,\r
1165                                 //we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval\r
1166                                 if(this.instance.isOver) {\r
1168                                         this.instance.isOver = 0;\r
1169                                         this.instance.cancelHelperRemoval = true;\r
1170                                         \r
1171                                         //Prevent reverting on this forced stop\r
1172                                         this.instance.options.revert = false;\r
1173                                         \r
1174                                         // The out event needs to be triggered independently\r
1175                                         this.instance._trigger('out', event, this.instance._uiHash(this.instance));\r
1176                                         \r
1177                                         this.instance._mouseStop(event, true);\r
1178                                         this.instance.options.helper = this.instance.options._helper;\r
1180                                         //Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size\r
1181                                         this.instance.currentItem.remove();\r
1182                                         if(this.instance.placeholder) this.instance.placeholder.remove();\r
1184                                         inst._trigger("fromSortable", event);\r
1185                                         inst.dropped = false; //draggable revert needs that\r
1186                                 }\r
1188                         };\r
1190                 });\r
1192         }\r
1193 });\r
1195 $.ui.plugin.add("draggable", "cursor", {\r
1196         start: function(event, ui) {\r
1197                 var t = $('body'), o = $(this).data('draggable').options;\r
1198                 if (t.css("cursor")) o._cursor = t.css("cursor");\r
1199                 t.css("cursor", o.cursor);\r
1200         },\r
1201         stop: function(event, ui) {\r
1202                 var o = $(this).data('draggable').options;\r
1203                 if (o._cursor) $('body').css("cursor", o._cursor);\r
1204         }\r
1205 });\r
1207 $.ui.plugin.add("draggable", "iframeFix", {\r
1208         start: function(event, ui) {\r
1209                 var o = $(this).data('draggable').options;\r
1210                 $(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() {\r
1211                         $('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>')\r
1212                         .css({\r
1213                                 width: this.offsetWidth+"px", height: this.offsetHeight+"px",\r
1214                                 position: "absolute", opacity: "0.001", zIndex: 1000\r
1215                         })\r
1216                         .css($(this).offset())\r
1217                         .appendTo("body");\r
1218                 });\r
1219         },\r
1220         stop: function(event, ui) {\r
1221                 $("div.ui-draggable-iframeFix").each(function() { this.parentNode.removeChild(this); }); //Remove frame helpers\r
1222         }\r
1223 });\r
1225 $.ui.plugin.add("draggable", "opacity", {\r
1226         start: function(event, ui) {\r
1227                 var t = $(ui.helper), o = $(this).data('draggable').options;\r
1228                 if(t.css("opacity")) o._opacity = t.css("opacity");\r
1229                 t.css('opacity', o.opacity);\r
1230         },\r
1231         stop: function(event, ui) {\r
1232                 var o = $(this).data('draggable').options;\r
1233                 if(o._opacity) $(ui.helper).css('opacity', o._opacity);\r
1234         }\r
1235 });\r
1237 $.ui.plugin.add("draggable", "scroll", {\r
1238         start: function(event, ui) {\r
1239                 var i = $(this).data("draggable");\r
1240                 if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') i.overflowOffset = i.scrollParent.offset();\r
1241         },\r
1242         drag: function(event, ui) {\r
1244                 var i = $(this).data("draggable"), o = i.options, scrolled = false;\r
1246                 if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') {\r
1248                         if(!o.axis || o.axis != 'x') {\r
1249                                 if((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)\r
1250                                         i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed;\r
1251                                 else if(event.pageY - i.overflowOffset.top < o.scrollSensitivity)\r
1252                                         i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed;\r
1253                         }\r
1255                         if(!o.axis || o.axis != 'y') {\r
1256                                 if((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)\r
1257                                         i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed;\r
1258                                 else if(event.pageX - i.overflowOffset.left < o.scrollSensitivity)\r
1259                                         i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed;\r
1260                         }\r
1262                 } else {\r
1264                         if(!o.axis || o.axis != 'x') {\r
1265                                 if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)\r
1266                                         scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);\r
1267                                 else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)\r
1268                                         scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);\r
1269                         }\r
1271                         if(!o.axis || o.axis != 'y') {\r
1272                                 if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)\r
1273                                         scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);\r
1274                                 else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)\r
1275                                         scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);\r
1276                         }\r
1278                 }\r
1280                 if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)\r
1281                         $.ui.ddmanager.prepareOffsets(i, event);\r
1283         }\r
1284 });\r
1286 $.ui.plugin.add("draggable", "snap", {\r
1287         start: function(event, ui) {\r
1289                 var i = $(this).data("draggable"), o = i.options;\r
1290                 i.snapElements = [];\r
1292                 $(o.snap.constructor != String ? ( o.snap.items || ':data(draggable)' ) : o.snap).each(function() {\r
1293                         var $t = $(this); var $o = $t.offset();\r
1294                         if(this != i.element[0]) i.snapElements.push({\r
1295                                 item: this,\r
1296                                 width: $t.outerWidth(), height: $t.outerHeight(),\r
1297                                 top: $o.top, left: $o.left\r
1298                         });\r
1299                 });\r
1301         },\r
1302         drag: function(event, ui) {\r
1304                 var inst = $(this).data("draggable"), o = inst.options;\r
1305                 var d = o.snapTolerance;\r
1307                 var x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,\r
1308                         y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;\r
1310                 for (var i = inst.snapElements.length - 1; i >= 0; i--){\r
1312                         var l = inst.snapElements[i].left, r = l + inst.snapElements[i].width,\r
1313                                 t = inst.snapElements[i].top, b = t + inst.snapElements[i].height;\r
1315                         //Yes, I know, this is insane ;)\r
1316                         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))) {\r
1317                                 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 })));\r
1318                                 inst.snapElements[i].snapping = false;\r
1319                                 continue;\r
1320                         }\r
1322                         if(o.snapMode != 'inner') {\r
1323                                 var ts = Math.abs(t - y2) <= d;\r
1324                                 var bs = Math.abs(b - y1) <= d;\r
1325                                 var ls = Math.abs(l - x2) <= d;\r
1326                                 var rs = Math.abs(r - x1) <= d;\r
1327                                 if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top;\r
1328                                 if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top;\r
1329                                 if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left;\r
1330                                 if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left;\r
1331                         }\r
1333                         var first = (ts || bs || ls || rs);\r
1335                         if(o.snapMode != 'outer') {\r
1336                                 var ts = Math.abs(t - y1) <= d;\r
1337                                 var bs = Math.abs(b - y2) <= d;\r
1338                                 var ls = Math.abs(l - x1) <= d;\r
1339                                 var rs = Math.abs(r - x2) <= d;\r
1340                                 if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top;\r
1341                                 if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top;\r
1342                                 if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left;\r
1343                                 if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left;\r
1344                         }\r
1346                         if(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first))\r
1347                                 (inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));\r
1348                         inst.snapElements[i].snapping = (ts || bs || ls || rs || first);\r
1350                 };\r
1352         }\r
1353 });\r
1355 $.ui.plugin.add("draggable", "stack", {\r
1356         start: function(event, ui) {\r
1358                 var o = $(this).data("draggable").options;\r
1360                 var group = $.makeArray($(o.stack)).sort(function(a,b) {\r
1361                         return (parseInt($(a).css("zIndex"),10) || 0) - (parseInt($(b).css("zIndex"),10) || 0);\r
1362                 });\r
1363                 if (!group.length) { return; }\r
1364                 \r
1365                 var min = parseInt(group[0].style.zIndex) || 0;\r
1366                 $(group).each(function(i) {\r
1367                         this.style.zIndex = min + i;\r
1368                 });\r
1370                 this[0].style.zIndex = min + group.length;\r
1372         }\r
1373 });\r
1375 $.ui.plugin.add("draggable", "zIndex", {\r
1376         start: function(event, ui) {\r
1377                 var t = $(ui.helper), o = $(this).data("draggable").options;\r
1378                 if(t.css("zIndex")) o._zIndex = t.css("zIndex");\r
1379                 t.css('zIndex', o.zIndex);\r
1380         },\r
1381         stop: function(event, ui) {\r
1382                 var o = $(this).data("draggable").options;\r
1383                 if(o._zIndex) $(ui.helper).css('zIndex', o._zIndex);\r
1384         }\r
1385 });\r
1387 })(jQuery);\r
1388 /*\r
1389  * jQuery UI Droppable 1.8\r
1390  *\r
1391  * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)\r
1392  * Dual licensed under the MIT (MIT-LICENSE.txt)\r
1393  * and GPL (GPL-LICENSE.txt) licenses.\r
1394  *\r
1395  * http://docs.jquery.com/UI/Droppables\r
1396  *\r
1397  * Depends:\r
1398  *      jquery.ui.core.js\r
1399  *      jquery.ui.widget.js\r
1400  *      jquery.ui.mouse.js\r
1401  *      jquery.ui.draggable.js\r
1402  */\r
1403 (function($) {\r
1405 $.widget("ui.droppable", {\r
1406         widgetEventPrefix: "drop",\r
1407         options: {\r
1408                 accept: '*',\r
1409                 activeClass: false,\r
1410                 addClasses: true,\r
1411                 greedy: false,\r
1412                 hoverClass: false,\r
1413                 scope: 'default',\r
1414                 tolerance: 'intersect'\r
1415         },\r
1416         _create: function() {\r
1418                 var o = this.options, accept = o.accept;\r
1419                 this.isover = 0; this.isout = 1;\r
1421                 this.accept = $.isFunction(accept) ? accept : function(d) {\r
1422                         return d.is(accept);\r
1423                 };\r
1425                 //Store the droppable's proportions\r
1426                 this.proportions = { width: this.element[0].offsetWidth, height: this.element[0].offsetHeight };\r
1428                 // Add the reference and positions to the manager\r
1429                 $.ui.ddmanager.droppables[o.scope] = $.ui.ddmanager.droppables[o.scope] || [];\r
1430                 $.ui.ddmanager.droppables[o.scope].push(this);\r
1432                 (o.addClasses && this.element.addClass("ui-droppable"));\r
1434         },\r
1436         destroy: function() {\r
1437                 var drop = $.ui.ddmanager.droppables[this.options.scope];\r
1438                 for ( var i = 0; i < drop.length; i++ )\r
1439                         if ( drop[i] == this )\r
1440                                 drop.splice(i, 1);\r
1442                 this.element\r
1443                         .removeClass("ui-droppable ui-droppable-disabled")\r
1444                         .removeData("droppable")\r
1445                         .unbind(".droppable");\r
1447                 return this;\r
1448         },\r
1450         _setOption: function(key, value) {\r
1452                 if(key == 'accept') {\r
1453                         this.accept = $.isFunction(value) ? value : function(d) {\r
1454                                 return d.is(value);\r
1455                         };\r
1456                 }\r
1457                 $.Widget.prototype._setOption.apply(this, arguments);\r
1458         },\r
1460         _activate: function(event) {\r
1461                 var draggable = $.ui.ddmanager.current;\r
1462                 if(this.options.activeClass) this.element.addClass(this.options.activeClass);\r
1463                 (draggable && this._trigger('activate', event, this.ui(draggable)));\r
1464         },\r
1466         _deactivate: function(event) {\r
1467                 var draggable = $.ui.ddmanager.current;\r
1468                 if(this.options.activeClass) this.element.removeClass(this.options.activeClass);\r
1469                 (draggable && this._trigger('deactivate', event, this.ui(draggable)));\r
1470         },\r
1472         _over: function(event) {\r
1474                 var draggable = $.ui.ddmanager.current;\r
1475                 if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element\r
1477                 if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {\r
1478                         if(this.options.hoverClass) this.element.addClass(this.options.hoverClass);\r
1479                         this._trigger('over', event, this.ui(draggable));\r
1480                 }\r
1482         },\r
1484         _out: function(event) {\r
1486                 var draggable = $.ui.ddmanager.current;\r
1487                 if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element\r
1489                 if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {\r
1490                         if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);\r
1491                         this._trigger('out', event, this.ui(draggable));\r
1492                 }\r
1494         },\r
1496         _drop: function(event,custom) {\r
1498                 var draggable = custom || $.ui.ddmanager.current;\r
1499                 if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return false; // Bail if draggable and droppable are same element\r
1501                 var childrenIntersection = false;\r
1502                 this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function() {\r
1503                         var inst = $.data(this, 'droppable');\r
1504                         if(\r
1505                                 inst.options.greedy\r
1506                                 && !inst.options.disabled\r
1507                                 && inst.options.scope == draggable.options.scope\r
1508                                 && inst.accept.call(inst.element[0], (draggable.currentItem || draggable.element))\r
1509                                 && $.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance)\r
1510                         ) { childrenIntersection = true; return false; }\r
1511                 });\r
1512                 if(childrenIntersection) return false;\r
1514                 if(this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {\r
1515                         if(this.options.activeClass) this.element.removeClass(this.options.activeClass);\r
1516                         if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);\r
1517                         this._trigger('drop', event, this.ui(draggable));\r
1518                         return this.element;\r
1519                 }\r
1521                 return false;\r
1523         },\r
1525         ui: function(c) {\r
1526                 return {\r
1527                         draggable: (c.currentItem || c.element),\r
1528                         helper: c.helper,\r
1529                         position: c.position,\r
1530                         offset: c.positionAbs\r
1531                 };\r
1532         }\r
1534 });\r
1536 $.extend($.ui.droppable, {\r
1537         version: "1.8"\r
1538 });\r
1540 $.ui.intersect = function(draggable, droppable, toleranceMode) {\r
1542         if (!droppable.offset) return false;\r
1544         var x1 = (draggable.positionAbs || draggable.position.absolute).left, x2 = x1 + draggable.helperProportions.width,\r
1545                 y1 = (draggable.positionAbs || draggable.position.absolute).top, y2 = y1 + draggable.helperProportions.height;\r
1546         var l = droppable.offset.left, r = l + droppable.proportions.width,\r
1547                 t = droppable.offset.top, b = t + droppable.proportions.height;\r
1549         switch (toleranceMode) {\r
1550                 case 'fit':\r
1551                         return (l < x1 && x2 < r\r
1552                                 && t < y1 && y2 < b);\r
1553                         break;\r
1554                 case 'intersect':\r
1555                         return (l < x1 + (draggable.helperProportions.width / 2) // Right Half\r
1556                                 && x2 - (draggable.helperProportions.width / 2) < r // Left Half\r
1557                                 && t < y1 + (draggable.helperProportions.height / 2) // Bottom Half\r
1558                                 && y2 - (draggable.helperProportions.height / 2) < b ); // Top Half\r
1559                         break;\r
1560                 case 'pointer':\r
1561                         var draggableLeft = ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left),\r
1562                                 draggableTop = ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top),\r
1563                                 isOver = $.ui.isOver(draggableTop, draggableLeft, t, l, droppable.proportions.height, droppable.proportions.width);\r
1564                         return isOver;\r
1565                         break;\r
1566                 case 'touch':\r
1567                         return (\r
1568                                         (y1 >= t && y1 <= b) || // Top edge touching\r
1569                                         (y2 >= t && y2 <= b) || // Bottom edge touching\r
1570                                         (y1 < t && y2 > b)              // Surrounded vertically\r
1571                                 ) && (\r
1572                                         (x1 >= l && x1 <= r) || // Left edge touching\r
1573                                         (x2 >= l && x2 <= r) || // Right edge touching\r
1574                                         (x1 < l && x2 > r)              // Surrounded horizontally\r
1575                                 );\r
1576                         break;\r
1577                 default:\r
1578                         return false;\r
1579                         break;\r
1580                 }\r
1582 };\r
1584 /*\r
1585         This manager tracks offsets of draggables and droppables\r
1586 */\r
1587 $.ui.ddmanager = {\r
1588         current: null,\r
1589         droppables: { 'default': [] },\r
1590         prepareOffsets: function(t, event) {\r
1592                 var m = $.ui.ddmanager.droppables[t.options.scope] || [];\r
1593                 var type = event ? event.type : null; // workaround for #2317\r
1594                 var list = (t.currentItem || t.element).find(":data(droppable)").andSelf();\r
1596                 droppablesLoop: for (var i = 0; i < m.length; i++) {\r
1598                         if(m[i].options.disabled || (t && !m[i].accept.call(m[i].element[0],(t.currentItem || t.element)))) continue;   //No disabled and non-accepted\r
1599                         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\r
1600                         m[i].visible = m[i].element.css("display") != "none"; if(!m[i].visible) continue;                                                                       //If the element is not visible, continue\r
1602                         m[i].offset = m[i].element.offset();\r
1603                         m[i].proportions = { width: m[i].element[0].offsetWidth, height: m[i].element[0].offsetHeight };\r
1605                         if(type == "mousedown") m[i]._activate.call(m[i], event); //Activate the droppable if used directly from draggables\r
1607                 }\r
1609         },\r
1610         drop: function(draggable, event) {\r
1612                 var dropped = false;\r
1613                 $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {\r
1615                         if(!this.options) return;\r
1616                         if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance))\r
1617                                 dropped = dropped || this._drop.call(this, event);\r
1619                         if (!this.options.disabled && this.visible && this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {\r
1620                                 this.isout = 1; this.isover = 0;\r
1621                                 this._deactivate.call(this, event);\r
1622                         }\r
1624                 });\r
1625                 return dropped;\r
1627         },\r
1628         drag: function(draggable, event) {\r
1630                 //If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse.\r
1631                 if(draggable.options.refreshPositions) $.ui.ddmanager.prepareOffsets(draggable, event);\r
1633                 //Run through all droppables and check their positions based on specific tolerance options\r
1634                 $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {\r
1636                         if(this.options.disabled || this.greedyChild || !this.visible) return;\r
1637                         var intersects = $.ui.intersect(draggable, this, this.options.tolerance);\r
1639                         var c = !intersects && this.isover == 1 ? 'isout' : (intersects && this.isover == 0 ? 'isover' : null);\r
1640                         if(!c) return;\r
1642                         var parentInstance;\r
1643                         if (this.options.greedy) {\r
1644                                 var parent = this.element.parents(':data(droppable):eq(0)');\r
1645                                 if (parent.length) {\r
1646                                         parentInstance = $.data(parent[0], 'droppable');\r
1647                                         parentInstance.greedyChild = (c == 'isover' ? 1 : 0);\r
1648                                 }\r
1649                         }\r
1651                         // we just moved into a greedy child\r
1652                         if (parentInstance && c == 'isover') {\r
1653                                 parentInstance['isover'] = 0;\r
1654                                 parentInstance['isout'] = 1;\r
1655                                 parentInstance._out.call(parentInstance, event);\r
1656                         }\r
1658                         this[c] = 1; this[c == 'isout' ? 'isover' : 'isout'] = 0;\r
1659                         this[c == "isover" ? "_over" : "_out"].call(this, event);\r
1661                         // we just moved out of a greedy child\r
1662                         if (parentInstance && c == 'isout') {\r
1663                                 parentInstance['isout'] = 0;\r
1664                                 parentInstance['isover'] = 1;\r
1665                                 parentInstance._over.call(parentInstance, event);\r
1666                         }\r
1667                 });\r
1669         }\r
1670 };\r
1672 })(jQuery);\r
1673 /*\r
1674  * jQuery UI Resizable 1.8\r
1675  *\r
1676  * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)\r
1677  * Dual licensed under the MIT (MIT-LICENSE.txt)\r
1678  * and GPL (GPL-LICENSE.txt) licenses.\r
1679  *\r
1680  * http://docs.jquery.com/UI/Resizables\r
1681  *\r
1682  * Depends:\r
1683  *      jquery.ui.core.js\r
1684  *      jquery.ui.mouse.js\r
1685  *      jquery.ui.widget.js\r
1686  */\r
1687 (function($) {\r
1689 $.widget("ui.resizable", $.ui.mouse, {\r
1690         widgetEventPrefix: "resize",\r
1691         options: {\r
1692                 alsoResize: false,\r
1693                 animate: false,\r
1694                 animateDuration: "slow",\r
1695                 animateEasing: "swing",\r
1696                 aspectRatio: false,\r
1697                 autoHide: false,\r
1698                 containment: false,\r
1699                 ghost: false,\r
1700                 grid: false,\r
1701                 handles: "e,s,se",\r
1702                 helper: false,\r
1703                 maxHeight: null,\r
1704                 maxWidth: null,\r
1705                 minHeight: 10,\r
1706                 minWidth: 10,\r
1707                 zIndex: 1000\r
1708         },\r
1709         _create: function() {\r
1711                 var self = this, o = this.options;\r
1712                 this.element.addClass("ui-resizable");\r
1714                 $.extend(this, {\r
1715                         _aspectRatio: !!(o.aspectRatio),\r
1716                         aspectRatio: o.aspectRatio,\r
1717                         originalElement: this.element,\r
1718                         _proportionallyResizeElements: [],\r
1719                         _helper: o.helper || o.ghost || o.animate ? o.helper || 'ui-resizable-helper' : null\r
1720                 });\r
1722                 //Wrap the element if it cannot hold child nodes\r
1723                 if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) {\r
1725                         //Opera fix for relative positioning\r
1726                         if (/relative/.test(this.element.css('position')) && $.browser.opera)\r
1727                                 this.element.css({ position: 'relative', top: 'auto', left: 'auto' });\r
1729                         //Create a wrapper element and set the wrapper to the new current internal element\r
1730                         this.element.wrap(\r
1731                                 $('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({\r
1732                                         position: this.element.css('position'),\r
1733                                         width: this.element.outerWidth(),\r
1734                                         height: this.element.outerHeight(),\r
1735                                         top: this.element.css('top'),\r
1736                                         left: this.element.css('left')\r
1737                                 })\r
1738                         );\r
1740                         //Overwrite the original this.element\r
1741                         this.element = this.element.parent().data(\r
1742                                 "resizable", this.element.data('resizable')\r
1743                         );\r
1745                         this.elementIsWrapper = true;\r
1747                         //Move margins to the wrapper\r
1748                         this.element.css({ marginLeft: this.originalElement.css("marginLeft"), marginTop: this.originalElement.css("marginTop"), marginRight: this.originalElement.css("marginRight"), marginBottom: this.originalElement.css("marginBottom") });\r
1749                         this.originalElement.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0});\r
1751                         //Prevent Safari textarea resize\r
1752                         this.originalResizeStyle = this.originalElement.css('resize');\r
1753                         this.originalElement.css('resize', 'none');\r
1755                         //Push the actual element to our proportionallyResize internal array\r
1756                         this._proportionallyResizeElements.push(this.originalElement.css({ position: 'static', zoom: 1, display: 'block' }));\r
1758                         // avoid IE jump (hard set the margin)\r
1759                         this.originalElement.css({ margin: this.originalElement.css('margin') });\r
1761                         // fix handlers offset\r
1762                         this._proportionallyResize();\r
1764                 }\r
1766                 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' });\r
1767                 if(this.handles.constructor == String) {\r
1769                         if(this.handles == 'all') this.handles = 'n,e,s,w,se,sw,ne,nw';\r
1770                         var n = this.handles.split(","); this.handles = {};\r
1772                         for(var i = 0; i < n.length; i++) {\r
1774                                 var handle = $.trim(n[i]), hname = 'ui-resizable-'+handle;\r
1775                                 var axis = $('<div class="ui-resizable-handle ' + hname + '"></div>');\r
1777                                 // increase zIndex of sw, se, ne, nw axis\r
1778                                 //TODO : this modifies original option\r
1779                                 if(/sw|se|ne|nw/.test(handle)) axis.css({ zIndex: ++o.zIndex });\r
1781                                 //TODO : What's going on here?\r
1782                                 if ('se' == handle) {\r
1783                                         axis.addClass('ui-icon ui-icon-gripsmall-diagonal-se');\r
1784                                 };\r
1786                                 //Insert into internal handles object and append to element\r
1787                                 this.handles[handle] = '.ui-resizable-'+handle;\r
1788                                 this.element.append(axis);\r
1789                         }\r
1791                 }\r
1793                 this._renderAxis = function(target) {\r
1795                         target = target || this.element;\r
1797                         for(var i in this.handles) {\r
1799                                 if(this.handles[i].constructor == String)\r
1800                                         this.handles[i] = $(this.handles[i], this.element).show();\r
1802                                 //Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls)\r
1803                                 if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) {\r
1805                                         var axis = $(this.handles[i], this.element), padWrapper = 0;\r
1807                                         //Checking the correct pad and border\r
1808                                         padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth();\r
1810                                         //The padding type i have to apply...\r
1811                                         var padPos = [ 'padding',\r
1812                                                 /ne|nw|n/.test(i) ? 'Top' :\r
1813                                                 /se|sw|s/.test(i) ? 'Bottom' :\r
1814                                                 /^e$/.test(i) ? 'Right' : 'Left' ].join("");\r
1816                                         target.css(padPos, padWrapper);\r
1818                                         this._proportionallyResize();\r
1820                                 }\r
1822                                 //TODO: What's that good for? There's not anything to be executed left\r
1823                                 if(!$(this.handles[i]).length)\r
1824                                         continue;\r
1826                         }\r
1827                 };\r
1829                 //TODO: make renderAxis a prototype function\r
1830                 this._renderAxis(this.element);\r
1832                 this._handles = $('.ui-resizable-handle', this.element)\r
1833                         .disableSelection();\r
1835                 //Matching axis name\r
1836                 this._handles.mouseover(function() {\r
1837                         if (!self.resizing) {\r
1838                                 if (this.className)\r
1839                                         var axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);\r
1840                                 //Axis, default = se\r
1841                                 self.axis = axis && axis[1] ? axis[1] : 'se';\r
1842                         }\r
1843                 });\r
1845                 //If we want to auto hide the elements\r
1846                 if (o.autoHide) {\r
1847                         this._handles.hide();\r
1848                         $(this.element)\r
1849                                 .addClass("ui-resizable-autohide")\r
1850                                 .hover(function() {\r
1851                                         $(this).removeClass("ui-resizable-autohide");\r
1852                                         self._handles.show();\r
1853                                 },\r
1854                                 function(){\r
1855                                         if (!self.resizing) {\r
1856                                                 $(this).addClass("ui-resizable-autohide");\r
1857                                                 self._handles.hide();\r
1858                                         }\r
1859                                 });\r
1860                 }\r
1862                 //Initialize the mouse interaction\r
1863                 this._mouseInit();\r
1865         },\r
1867         destroy: function() {\r
1869                 this._mouseDestroy();\r
1871                 var _destroy = function(exp) {\r
1872                         $(exp).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing")\r
1873                                 .removeData("resizable").unbind(".resizable").find('.ui-resizable-handle').remove();\r
1874                 };\r
1876                 //TODO: Unwrap at same DOM position\r
1877                 if (this.elementIsWrapper) {\r
1878                         _destroy(this.element);\r
1879                         var wrapper = this.element;\r
1880                         wrapper.after(\r
1881                                 this.originalElement.css({\r
1882                                         position: wrapper.css('position'),\r
1883                                         width: wrapper.outerWidth(),\r
1884                                         height: wrapper.outerHeight(),\r
1885                                         top: wrapper.css('top'),\r
1886                                         left: wrapper.css('left')\r
1887                                 })\r
1888                         ).remove();\r
1889                 }\r
1891                 this.originalElement.css('resize', this.originalResizeStyle);\r
1892                 _destroy(this.originalElement);\r
1894                 return this;\r
1895         },\r
1897         _mouseCapture: function(event) {\r
1898                 var handle = false;\r
1899                 for (var i in this.handles) {\r
1900                         if ($(this.handles[i])[0] == event.target) {\r
1901                                 handle = true;\r
1902                         }\r
1903                 }\r
1905                 return !this.options.disabled && handle;\r
1906         },\r
1908         _mouseStart: function(event) {\r
1910                 var o = this.options, iniPos = this.element.position(), el = this.element;\r
1912                 this.resizing = true;\r
1913                 this.documentScroll = { top: $(document).scrollTop(), left: $(document).scrollLeft() };\r
1915                 // bugfix for http://dev.jquery.com/ticket/1749\r
1916                 if (el.is('.ui-draggable') || (/absolute/).test(el.css('position'))) {\r
1917                         el.css({ position: 'absolute', top: iniPos.top, left: iniPos.left });\r
1918                 }\r
1920                 //Opera fixing relative position\r
1921                 if ($.browser.opera && (/relative/).test(el.css('position')))\r
1922                         el.css({ position: 'relative', top: 'auto', left: 'auto' });\r
1924                 this._renderProxy();\r
1926                 var curleft = num(this.helper.css('left')), curtop = num(this.helper.css('top'));\r
1928                 if (o.containment) {\r
1929                         curleft += $(o.containment).scrollLeft() || 0;\r
1930                         curtop += $(o.containment).scrollTop() || 0;\r
1931                 }\r
1933                 //Store needed variables\r
1934                 this.offset = this.helper.offset();\r
1935                 this.position = { left: curleft, top: curtop };\r
1936                 this.size = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };\r
1937                 this.originalSize = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };\r
1938                 this.originalPosition = { left: curleft, top: curtop };\r
1939                 this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() };\r
1940                 this.originalMousePosition = { left: event.pageX, top: event.pageY };\r
1942                 //Aspect Ratio\r
1943                 this.aspectRatio = (typeof o.aspectRatio == 'number') ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1);\r
1945             var cursor = $('.ui-resizable-' + this.axis).css('cursor');\r
1946             $('body').css('cursor', cursor == 'auto' ? this.axis + '-resize' : cursor);\r
1948                 el.addClass("ui-resizable-resizing");\r
1949                 this._propagate("start", event);\r
1950                 return true;\r
1951         },\r
1953         _mouseDrag: function(event) {\r
1955                 //Increase performance, avoid regex\r
1956                 var el = this.helper, o = this.options, props = {},\r
1957                         self = this, smp = this.originalMousePosition, a = this.axis;\r
1959                 var dx = (event.pageX-smp.left)||0, dy = (event.pageY-smp.top)||0;\r
1960                 var trigger = this._change[a];\r
1961                 if (!trigger) return false;\r
1963                 // Calculate the attrs that will be change\r
1964                 var data = trigger.apply(this, [event, dx, dy]), ie6 = $.browser.msie && $.browser.version < 7, csdif = this.sizeDiff;\r
1966                 if (this._aspectRatio || event.shiftKey)\r
1967                         data = this._updateRatio(data, event);\r
1969                 data = this._respectSize(data, event);\r
1971                 // plugins callbacks need to be called first\r
1972                 this._propagate("resize", event);\r
1974                 el.css({\r
1975                         top: this.position.top + "px", left: this.position.left + "px",\r
1976                         width: this.size.width + "px", height: this.size.height + "px"\r
1977                 });\r
1979                 if (!this._helper && this._proportionallyResizeElements.length)\r
1980                         this._proportionallyResize();\r
1982                 this._updateCache(data);\r
1984                 // calling the user callback at the end\r
1985                 this._trigger('resize', event, this.ui());\r
1987                 return false;\r
1988         },\r
1990         _mouseStop: function(event) {\r
1992                 this.resizing = false;\r
1993                 var o = this.options, self = this;\r
1995                 if(this._helper) {\r
1996                         var pr = this._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),\r
1997                                                 soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,\r
1998                                                         soffsetw = ista ? 0 : self.sizeDiff.width;\r
2000                         var s = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },\r
2001                                 left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,\r
2002                                 top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;\r
2004                         if (!o.animate)\r
2005                                 this.element.css($.extend(s, { top: top, left: left }));\r
2007                         self.helper.height(self.size.height);\r
2008                         self.helper.width(self.size.width);\r
2010                         if (this._helper && !o.animate) this._proportionallyResize();\r
2011                 }\r
2013                 $('body').css('cursor', 'auto');\r
2015                 this.element.removeClass("ui-resizable-resizing");\r
2017                 this._propagate("stop", event);\r
2019                 if (this._helper) this.helper.remove();\r
2020                 return false;\r
2022         },\r
2024         _updateCache: function(data) {\r
2025                 var o = this.options;\r
2026                 this.offset = this.helper.offset();\r
2027                 if (isNumber(data.left)) this.position.left = data.left;\r
2028                 if (isNumber(data.top)) this.position.top = data.top;\r
2029                 if (isNumber(data.height)) this.size.height = data.height;\r
2030                 if (isNumber(data.width)) this.size.width = data.width;\r
2031         },\r
2033         _updateRatio: function(data, event) {\r
2035                 var o = this.options, cpos = this.position, csize = this.size, a = this.axis;\r
2037                 if (data.height) data.width = (csize.height * this.aspectRatio);\r
2038                 else if (data.width) data.height = (csize.width / this.aspectRatio);\r
2040                 if (a == 'sw') {\r
2041                         data.left = cpos.left + (csize.width - data.width);\r
2042                         data.top = null;\r
2043                 }\r
2044                 if (a == 'nw') {\r
2045                         data.top = cpos.top + (csize.height - data.height);\r
2046                         data.left = cpos.left + (csize.width - data.width);\r
2047                 }\r
2049                 return data;\r
2050         },\r
2052         _respectSize: function(data, event) {\r
2054                 var el = this.helper, o = this.options, pRatio = this._aspectRatio || event.shiftKey, a = this.axis,\r
2055                                 ismaxw = isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh = isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height),\r
2056                                         isminw = isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh = isNumber(data.height) && o.minHeight && (o.minHeight > data.height);\r
2058                 if (isminw) data.width = o.minWidth;\r
2059                 if (isminh) data.height = o.minHeight;\r
2060                 if (ismaxw) data.width = o.maxWidth;\r
2061                 if (ismaxh) data.height = o.maxHeight;\r
2063                 var dw = this.originalPosition.left + this.originalSize.width, dh = this.position.top + this.size.height;\r
2064                 var cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a);\r
2066                 if (isminw && cw) data.left = dw - o.minWidth;\r
2067                 if (ismaxw && cw) data.left = dw - o.maxWidth;\r
2068                 if (isminh && ch)       data.top = dh - o.minHeight;\r
2069                 if (ismaxh && ch)       data.top = dh - o.maxHeight;\r
2071                 // fixing jump error on top/left - bug #2330\r
2072                 var isNotwh = !data.width && !data.height;\r
2073                 if (isNotwh && !data.left && data.top) data.top = null;\r
2074                 else if (isNotwh && !data.top && data.left) data.left = null;\r
2076                 return data;\r
2077         },\r
2079         _proportionallyResize: function() {\r
2081                 var o = this.options;\r
2082                 if (!this._proportionallyResizeElements.length) return;\r
2083                 var element = this.helper || this.element;\r
2085                 for (var i=0; i < this._proportionallyResizeElements.length; i++) {\r
2087                         var prel = this._proportionallyResizeElements[i];\r
2089                         if (!this.borderDif) {\r
2090                                 var b = [prel.css('borderTopWidth'), prel.css('borderRightWidth'), prel.css('borderBottomWidth'), prel.css('borderLeftWidth')],\r
2091                                         p = [prel.css('paddingTop'), prel.css('paddingRight'), prel.css('paddingBottom'), prel.css('paddingLeft')];\r
2093                                 this.borderDif = $.map(b, function(v, i) {\r
2094                                         var border = parseInt(v,10)||0, padding = parseInt(p[i],10)||0;\r
2095                                         return border + padding;\r
2096                                 });\r
2097                         }\r
2099                         if ($.browser.msie && !(!($(element).is(':hidden') || $(element).parents(':hidden').length)))\r
2100                                 continue;\r
2102                         prel.css({\r
2103                                 height: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0,\r
2104                                 width: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0\r
2105                         });\r
2107                 };\r
2109         },\r
2111         _renderProxy: function() {\r
2113                 var el = this.element, o = this.options;\r
2114                 this.elementOffset = el.offset();\r
2116                 if(this._helper) {\r
2118                         this.helper = this.helper || $('<div style="overflow:hidden;"></div>');\r
2120                         // fix ie6 offset TODO: This seems broken\r
2121                         var ie6 = $.browser.msie && $.browser.version < 7, ie6offset = (ie6 ? 1 : 0),\r
2122                         pxyoffset = ( ie6 ? 2 : -1 );\r
2124                         this.helper.addClass(this._helper).css({\r
2125                                 width: this.element.outerWidth() + pxyoffset,\r
2126                                 height: this.element.outerHeight() + pxyoffset,\r
2127                                 position: 'absolute',\r
2128                                 left: this.elementOffset.left - ie6offset +'px',\r
2129                                 top: this.elementOffset.top - ie6offset +'px',\r
2130                                 zIndex: ++o.zIndex //TODO: Don't modify option\r
2131                         });\r
2133                         this.helper\r
2134                                 .appendTo("body")\r
2135                                 .disableSelection();\r
2137                 } else {\r
2138                         this.helper = this.element;\r
2139                 }\r
2141         },\r
2143         _change: {\r
2144                 e: function(event, dx, dy) {\r
2145                         return { width: this.originalSize.width + dx };\r
2146                 },\r
2147                 w: function(event, dx, dy) {\r
2148                         var o = this.options, cs = this.originalSize, sp = this.originalPosition;\r
2149                         return { left: sp.left + dx, width: cs.width - dx };\r
2150                 },\r
2151                 n: function(event, dx, dy) {\r
2152                         var o = this.options, cs = this.originalSize, sp = this.originalPosition;\r
2153                         return { top: sp.top + dy, height: cs.height - dy };\r
2154                 },\r
2155                 s: function(event, dx, dy) {\r
2156                         return { height: this.originalSize.height + dy };\r
2157                 },\r
2158                 se: function(event, dx, dy) {\r
2159                         return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));\r
2160                 },\r
2161                 sw: function(event, dx, dy) {\r
2162                         return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));\r
2163                 },\r
2164                 ne: function(event, dx, dy) {\r
2165                         return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));\r
2166                 },\r
2167                 nw: function(event, dx, dy) {\r
2168                         return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));\r
2169                 }\r
2170         },\r
2172         _propagate: function(n, event) {\r
2173                 $.ui.plugin.call(this, n, [event, this.ui()]);\r
2174                 (n != "resize" && this._trigger(n, event, this.ui()));\r
2175         },\r
2177         plugins: {},\r
2179         ui: function() {\r
2180                 return {\r
2181                         originalElement: this.originalElement,\r
2182                         element: this.element,\r
2183                         helper: this.helper,\r
2184                         position: this.position,\r
2185                         size: this.size,\r
2186                         originalSize: this.originalSize,\r
2187                         originalPosition: this.originalPosition\r
2188                 };\r
2189         }\r
2191 });\r
2193 $.extend($.ui.resizable, {\r
2194         version: "1.8"\r
2195 });\r
2197 /*\r
2198  * Resizable Extensions\r
2199  */\r
2201 $.ui.plugin.add("resizable", "alsoResize", {\r
2203         start: function(event, ui) {\r
2205                 var self = $(this).data("resizable"), o = self.options;\r
2207                 var _store = function(exp) {\r
2208                         $(exp).each(function() {\r
2209                                 $(this).data("resizable-alsoresize", {\r
2210                                         width: parseInt($(this).width(), 10), height: parseInt($(this).height(), 10),\r
2211                                         left: parseInt($(this).css('left'), 10), top: parseInt($(this).css('top'), 10)\r
2212                                 });\r
2213                         });\r
2214                 };\r
2216                 if (typeof(o.alsoResize) == 'object' && !o.alsoResize.parentNode) {\r
2217                         if (o.alsoResize.length) { o.alsoResize = o.alsoResize[0];      _store(o.alsoResize); }\r
2218                         else { $.each(o.alsoResize, function(exp, c) { _store(exp); }); }\r
2219                 }else{\r
2220                         _store(o.alsoResize);\r
2221                 }\r
2222         },\r
2224         resize: function(event, ui){\r
2225                 var self = $(this).data("resizable"), o = self.options, os = self.originalSize, op = self.originalPosition;\r
2227                 var delta = {\r
2228                         height: (self.size.height - os.height) || 0, width: (self.size.width - os.width) || 0,\r
2229                         top: (self.position.top - op.top) || 0, left: (self.position.left - op.left) || 0\r
2230                 },\r
2232                 _alsoResize = function(exp, c) {\r
2233                         $(exp).each(function() {\r
2234                                 var el = $(this), start = $(this).data("resizable-alsoresize"), style = {}, css = c && c.length ? c : ['width', 'height', 'top', 'left'];\r
2236                                 $.each(css || ['width', 'height', 'top', 'left'], function(i, prop) {\r
2237                                         var sum = (start[prop]||0) + (delta[prop]||0);\r
2238                                         if (sum && sum >= 0)\r
2239                                                 style[prop] = sum || null;\r
2240                                 });\r
2242                                 //Opera fixing relative position\r
2243                                 if (/relative/.test(el.css('position')) && $.browser.opera) {\r
2244                                         self._revertToRelativePosition = true;\r
2245                                         el.css({ position: 'absolute', top: 'auto', left: 'auto' });\r
2246                                 }\r
2248                                 el.css(style);\r
2249                         });\r
2250                 };\r
2252                 if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) {\r
2253                         $.each(o.alsoResize, function(exp, c) { _alsoResize(exp, c); });\r
2254                 }else{\r
2255                         _alsoResize(o.alsoResize);\r
2256                 }\r
2257         },\r
2259         stop: function(event, ui){\r
2260                 var self = $(this).data("resizable");\r
2262                 //Opera fixing relative position\r
2263                 if (self._revertToRelativePosition && $.browser.opera) {\r
2264                         self._revertToRelativePosition = false;\r
2265                         el.css({ position: 'relative' });\r
2266                 }\r
2268                 $(this).removeData("resizable-alsoresize-start");\r
2269         }\r
2270 });\r
2272 $.ui.plugin.add("resizable", "animate", {\r
2274         stop: function(event, ui) {\r
2275                 var self = $(this).data("resizable"), o = self.options;\r
2277                 var pr = self._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),\r
2278                                         soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,\r
2279                                                 soffsetw = ista ? 0 : self.sizeDiff.width;\r
2281                 var style = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },\r
2282                                         left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,\r
2283                                                 top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;\r
2285                 self.element.animate(\r
2286                         $.extend(style, top && left ? { top: top, left: left } : {}), {\r
2287                                 duration: o.animateDuration,\r
2288                                 easing: o.animateEasing,\r
2289                                 step: function() {\r
2291                                         var data = {\r
2292                                                 width: parseInt(self.element.css('width'), 10),\r
2293                                                 height: parseInt(self.element.css('height'), 10),\r
2294                                                 top: parseInt(self.element.css('top'), 10),\r
2295                                                 left: parseInt(self.element.css('left'), 10)\r
2296                                         };\r
2298                                         if (pr && pr.length) $(pr[0]).css({ width: data.width, height: data.height });\r
2300                                         // propagating resize, and updating values for each animation step\r
2301                                         self._updateCache(data);\r
2302                                         self._propagate("resize", event);\r
2304                                 }\r
2305                         }\r
2306                 );\r
2307         }\r
2309 });\r
2311 $.ui.plugin.add("resizable", "containment", {\r
2313         start: function(event, ui) {\r
2314                 var self = $(this).data("resizable"), o = self.options, el = self.element;\r
2315                 var oc = o.containment, ce = (oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc;\r
2316                 if (!ce) return;\r
2318                 self.containerElement = $(ce);\r
2320                 if (/document/.test(oc) || oc == document) {\r
2321                         self.containerOffset = { left: 0, top: 0 };\r
2322                         self.containerPosition = { left: 0, top: 0 };\r
2324                         self.parentData = {\r
2325                                 element: $(document), left: 0, top: 0,\r
2326                                 width: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight\r
2327                         };\r
2328                 }\r
2330                 // i'm a node, so compute top, left, right, bottom\r
2331                 else {\r
2332                         var element = $(ce), p = [];\r
2333                         $([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) { p[i] = num(element.css("padding" + name)); });\r
2335                         self.containerOffset = element.offset();\r
2336                         self.containerPosition = element.position();\r
2337                         self.containerSize = { height: (element.innerHeight() - p[3]), width: (element.innerWidth() - p[1]) };\r
2339                         var co = self.containerOffset, ch = self.containerSize.height,  cw = self.containerSize.width,\r
2340                                                 width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw ), height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch);\r
2342                         self.parentData = {\r
2343                                 element: ce, left: co.left, top: co.top, width: width, height: height\r
2344                         };\r
2345                 }\r
2346         },\r
2348         resize: function(event, ui) {\r
2349                 var self = $(this).data("resizable"), o = self.options,\r
2350                                 ps = self.containerSize, co = self.containerOffset, cs = self.size, cp = self.position,\r
2351                                 pRatio = self._aspectRatio || event.shiftKey, cop = { top:0, left:0 }, ce = self.containerElement;\r
2353                 if (ce[0] != document && (/static/).test(ce.css('position'))) cop = co;\r
2355                 if (cp.left < (self._helper ? co.left : 0)) {\r
2356                         self.size.width = self.size.width + (self._helper ? (self.position.left - co.left) : (self.position.left - cop.left));\r
2357                         if (pRatio) self.size.height = self.size.width / o.aspectRatio;\r
2358                         self.position.left = o.helper ? co.left : 0;\r
2359                 }\r
2361                 if (cp.top < (self._helper ? co.top : 0)) {\r
2362                         self.size.height = self.size.height + (self._helper ? (self.position.top - co.top) : self.position.top);\r
2363                         if (pRatio) self.size.width = self.size.height * o.aspectRatio;\r
2364                         self.position.top = self._helper ? co.top : 0;\r
2365                 }\r
2367                 self.offset.left = self.parentData.left+self.position.left;\r
2368                 self.offset.top = self.parentData.top+self.position.top;\r
2370                 var woset = Math.abs( (self._helper ? self.offset.left - cop.left : (self.offset.left - cop.left)) + self.sizeDiff.width ),\r
2371                                         hoset = Math.abs( (self._helper ? self.offset.top - cop.top : (self.offset.top - co.top)) + self.sizeDiff.height );\r
2373                 var isParent = self.containerElement.get(0) == self.element.parent().get(0),\r
2374                     isOffsetRelative = /relative|absolute/.test(self.containerElement.css('position'));\r
2376                 if(isParent && isOffsetRelative) woset -= self.parentData.left;\r
2378                 if (woset + self.size.width >= self.parentData.width) {\r
2379                         self.size.width = self.parentData.width - woset;\r
2380                         if (pRatio) self.size.height = self.size.width / self.aspectRatio;\r
2381                 }\r
2383                 if (hoset + self.size.height >= self.parentData.height) {\r
2384                         self.size.height = self.parentData.height - hoset;\r
2385                         if (pRatio) self.size.width = self.size.height * self.aspectRatio;\r
2386                 }\r
2387         },\r
2389         stop: function(event, ui){\r
2390                 var self = $(this).data("resizable"), o = self.options, cp = self.position,\r
2391                                 co = self.containerOffset, cop = self.containerPosition, ce = self.containerElement;\r
2393                 var helper = $(self.helper), ho = helper.offset(), w = helper.outerWidth() - self.sizeDiff.width, h = helper.outerHeight() - self.sizeDiff.height;\r
2395                 if (self._helper && !o.animate && (/relative/).test(ce.css('position')))\r
2396                         $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });\r
2398                 if (self._helper && !o.animate && (/static/).test(ce.css('position')))\r
2399                         $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });\r
2401         }\r
2402 });\r
2404 $.ui.plugin.add("resizable", "ghost", {\r
2406         start: function(event, ui) {\r
2408                 var self = $(this).data("resizable"), o = self.options, cs = self.size;\r
2410                 self.ghost = self.originalElement.clone();\r
2411                 self.ghost\r
2412                         .css({ opacity: .25, display: 'block', position: 'relative', height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 })\r
2413                         .addClass('ui-resizable-ghost')\r
2414                         .addClass(typeof o.ghost == 'string' ? o.ghost : '');\r
2416                 self.ghost.appendTo(self.helper);\r
2418         },\r
2420         resize: function(event, ui){\r
2421                 var self = $(this).data("resizable"), o = self.options;\r
2422                 if (self.ghost) self.ghost.css({ position: 'relative', height: self.size.height, width: self.size.width });\r
2423         },\r
2425         stop: function(event, ui){\r
2426                 var self = $(this).data("resizable"), o = self.options;\r
2427                 if (self.ghost && self.helper) self.helper.get(0).removeChild(self.ghost.get(0));\r
2428         }\r
2430 });\r
2432 $.ui.plugin.add("resizable", "grid", {\r
2434         resize: function(event, ui) {\r
2435                 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;\r
2436                 o.grid = typeof o.grid == "number" ? [o.grid, o.grid] : o.grid;\r
2437                 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);\r
2439                 if (/^(se|s|e)$/.test(a)) {\r
2440                         self.size.width = os.width + ox;\r
2441                         self.size.height = os.height + oy;\r
2442                 }\r
2443                 else if (/^(ne)$/.test(a)) {\r
2444                         self.size.width = os.width + ox;\r
2445                         self.size.height = os.height + oy;\r
2446                         self.position.top = op.top - oy;\r
2447                 }\r
2448                 else if (/^(sw)$/.test(a)) {\r
2449                         self.size.width = os.width + ox;\r
2450                         self.size.height = os.height + oy;\r
2451                         self.position.left = op.left - ox;\r
2452                 }\r
2453                 else {\r
2454                         self.size.width = os.width + ox;\r
2455                         self.size.height = os.height + oy;\r
2456                         self.position.top = op.top - oy;\r
2457                         self.position.left = op.left - ox;\r
2458                 }\r
2459         }\r
2461 });\r
2463 var num = function(v) {\r
2464         return parseInt(v, 10) || 0;\r
2465 };\r
2467 var isNumber = function(value) {\r
2468         return !isNaN(parseInt(value, 10));\r
2469 };\r
2471 })(jQuery);\r
2472 /*\r
2473  * jQuery UI Selectable 1.8\r
2474  *\r
2475  * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)\r
2476  * Dual licensed under the MIT (MIT-LICENSE.txt)\r
2477  * and GPL (GPL-LICENSE.txt) licenses.\r
2478  *\r
2479  * http://docs.jquery.com/UI/Selectables\r
2480  *\r
2481  * Depends:\r
2482  *      jquery.ui.core.js\r
2483  *      jquery.ui.mouse.js\r
2484  *      jquery.ui.widget.js\r
2485  */\r
2486 (function($) {\r
2488 $.widget("ui.selectable", $.ui.mouse, {\r
2489         options: {\r
2490                 appendTo: 'body',\r
2491                 autoRefresh: true,\r
2492                 distance: 0,\r
2493                 filter: '*',\r
2494                 tolerance: 'touch'\r
2495         },\r
2496         _create: function() {\r
2497                 var self = this;\r
2499                 this.element.addClass("ui-selectable");\r
2501                 this.dragged = false;\r
2503                 // cache selectee children based on filter\r
2504                 var selectees;\r
2505                 this.refresh = function() {\r
2506                         selectees = $(self.options.filter, self.element[0]);\r
2507                         selectees.each(function() {\r
2508                                 var $this = $(this);\r
2509                                 var pos = $this.offset();\r
2510                                 $.data(this, "selectable-item", {\r
2511                                         element: this,\r
2512                                         $element: $this,\r
2513                                         left: pos.left,\r
2514                                         top: pos.top,\r
2515                                         right: pos.left + $this.outerWidth(),\r
2516                                         bottom: pos.top + $this.outerHeight(),\r
2517                                         startselected: false,\r
2518                                         selected: $this.hasClass('ui-selected'),\r
2519                                         selecting: $this.hasClass('ui-selecting'),\r
2520                                         unselecting: $this.hasClass('ui-unselecting')\r
2521                                 });\r
2522                         });\r
2523                 };\r
2524                 this.refresh();\r
2526                 this.selectees = selectees.addClass("ui-selectee");\r
2528                 this._mouseInit();\r
2530                 this.helper = $(document.createElement('div'))\r
2531                         .css({border:'1px dotted black'})\r
2532                         .addClass("ui-selectable-helper");\r
2533         },\r
2535         destroy: function() {\r
2536                 this.selectees\r
2537                         .removeClass("ui-selectee")\r
2538                         .removeData("selectable-item");\r
2539                 this.element\r
2540                         .removeClass("ui-selectable ui-selectable-disabled")\r
2541                         .removeData("selectable")\r
2542                         .unbind(".selectable");\r
2543                 this._mouseDestroy();\r
2545                 return this;\r
2546         },\r
2548         _mouseStart: function(event) {\r
2549                 var self = this;\r
2551                 this.opos = [event.pageX, event.pageY];\r
2553                 if (this.options.disabled)\r
2554                         return;\r
2556                 var options = this.options;\r
2558                 this.selectees = $(options.filter, this.element[0]);\r
2560                 this._trigger("start", event);\r
2562                 $(options.appendTo).append(this.helper);\r
2563                 // position helper (lasso)\r
2564                 this.helper.css({\r
2565                         "z-index": 100,\r
2566                         "position": "absolute",\r
2567                         "left": event.clientX,\r
2568                         "top": event.clientY,\r
2569                         "width": 0,\r
2570                         "height": 0\r
2571                 });\r
2573                 if (options.autoRefresh) {\r
2574                         this.refresh();\r
2575                 }\r
2577                 this.selectees.filter('.ui-selected').each(function() {\r
2578                         var selectee = $.data(this, "selectable-item");\r
2579                         selectee.startselected = true;\r
2580                         if (!event.metaKey) {\r
2581                                 selectee.$element.removeClass('ui-selected');\r
2582                                 selectee.selected = false;\r
2583                                 selectee.$element.addClass('ui-unselecting');\r
2584                                 selectee.unselecting = true;\r
2585                                 // selectable UNSELECTING callback\r
2586                                 self._trigger("unselecting", event, {\r
2587                                         unselecting: selectee.element\r
2588                                 });\r
2589                         }\r
2590                 });\r
2592                 $(event.target).parents().andSelf().each(function() {\r
2593                         var selectee = $.data(this, "selectable-item");\r
2594                         if (selectee) {\r
2595                                 selectee.$element.removeClass("ui-unselecting").addClass('ui-selecting');\r
2596                                 selectee.unselecting = false;\r
2597                                 selectee.selecting = true;\r
2598                                 selectee.selected = true;\r
2599                                 // selectable SELECTING callback\r
2600                                 self._trigger("selecting", event, {\r
2601                                         selecting: selectee.element\r
2602                                 });\r
2603                                 return false;\r
2604                         }\r
2605                 });\r
2607         },\r
2609         _mouseDrag: function(event) {\r
2610                 var self = this;\r
2611                 this.dragged = true;\r
2613                 if (this.options.disabled)\r
2614                         return;\r
2616                 var options = this.options;\r
2618                 var x1 = this.opos[0], y1 = this.opos[1], x2 = event.pageX, y2 = event.pageY;\r
2619                 if (x1 > x2) { var tmp = x2; x2 = x1; x1 = tmp; }\r
2620                 if (y1 > y2) { var tmp = y2; y2 = y1; y1 = tmp; }\r
2621                 this.helper.css({left: x1, top: y1, width: x2-x1, height: y2-y1});\r
2623                 this.selectees.each(function() {\r
2624                         var selectee = $.data(this, "selectable-item");\r
2625                         //prevent helper from being selected if appendTo: selectable\r
2626                         if (!selectee || selectee.element == self.element[0])\r
2627                                 return;\r
2628                         var hit = false;\r
2629                         if (options.tolerance == 'touch') {\r
2630                                 hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) );\r
2631                         } else if (options.tolerance == 'fit') {\r
2632                                 hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2);\r
2633                         }\r
2635                         if (hit) {\r
2636                                 // SELECT\r
2637                                 if (selectee.selected) {\r
2638                                         selectee.$element.removeClass('ui-selected');\r
2639                                         selectee.selected = false;\r
2640                                 }\r
2641                                 if (selectee.unselecting) {\r
2642                                         selectee.$element.removeClass('ui-unselecting');\r
2643                                         selectee.unselecting = false;\r
2644                                 }\r
2645                                 if (!selectee.selecting) {\r
2646                                         selectee.$element.addClass('ui-selecting');\r
2647                                         selectee.selecting = true;\r
2648                                         // selectable SELECTING callback\r
2649                                         self._trigger("selecting", event, {\r
2650                                                 selecting: selectee.element\r
2651                                         });\r
2652                                 }\r
2653                         } else {\r
2654                                 // UNSELECT\r
2655                                 if (selectee.selecting) {\r
2656                                         if (event.metaKey && selectee.startselected) {\r
2657                                                 selectee.$element.removeClass('ui-selecting');\r
2658                                                 selectee.selecting = false;\r
2659                                                 selectee.$element.addClass('ui-selected');\r
2660                                                 selectee.selected = true;\r
2661                                         } else {\r
2662                                                 selectee.$element.removeClass('ui-selecting');\r
2663                                                 selectee.selecting = false;\r
2664                                                 if (selectee.startselected) {\r
2665                                                         selectee.$element.addClass('ui-unselecting');\r
2666                                                         selectee.unselecting = true;\r
2667                                                 }\r
2668                                                 // selectable UNSELECTING callback\r
2669                                                 self._trigger("unselecting", event, {\r
2670                                                         unselecting: selectee.element\r
2671                                                 });\r
2672                                         }\r
2673                                 }\r
2674                                 if (selectee.selected) {\r
2675                                         if (!event.metaKey && !selectee.startselected) {\r
2676                                                 selectee.$element.removeClass('ui-selected');\r
2677                                                 selectee.selected = false;\r
2679                                                 selectee.$element.addClass('ui-unselecting');\r
2680                                                 selectee.unselecting = true;\r
2681                                                 // selectable UNSELECTING callback\r
2682                                                 self._trigger("unselecting", event, {\r
2683                                                         unselecting: selectee.element\r
2684                                                 });\r
2685                                         }\r
2686                                 }\r
2687                         }\r
2688                 });\r
2690                 return false;\r
2691         },\r
2693         _mouseStop: function(event) {\r
2694                 var self = this;\r
2696                 this.dragged = false;\r
2698                 var options = this.options;\r
2700                 $('.ui-unselecting', this.element[0]).each(function() {\r
2701                         var selectee = $.data(this, "selectable-item");\r
2702                         selectee.$element.removeClass('ui-unselecting');\r
2703                         selectee.unselecting = false;\r
2704                         selectee.startselected = false;\r
2705                         self._trigger("unselected", event, {\r
2706                                 unselected: selectee.element\r
2707                         });\r
2708                 });\r
2709                 $('.ui-selecting', this.element[0]).each(function() {\r
2710                         var selectee = $.data(this, "selectable-item");\r
2711                         selectee.$element.removeClass('ui-selecting').addClass('ui-selected');\r
2712                         selectee.selecting = false;\r
2713                         selectee.selected = true;\r
2714                         selectee.startselected = true;\r
2715                         self._trigger("selected", event, {\r
2716                                 selected: selectee.element\r
2717                         });\r
2718                 });\r
2719                 this._trigger("stop", event);\r
2721                 this.helper.remove();\r
2723                 return false;\r
2724         }\r
2726 });\r
2728 $.extend($.ui.selectable, {\r
2729         version: "1.8"\r
2730 });\r
2732 })(jQuery);\r
2733 /*\r
2734  * jQuery UI Sortable 1.8\r
2735  *\r
2736  * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)\r
2737  * Dual licensed under the MIT (MIT-LICENSE.txt)\r
2738  * and GPL (GPL-LICENSE.txt) licenses.\r
2739  *\r
2740  * http://docs.jquery.com/UI/Sortables\r
2741  *\r
2742  * Depends:\r
2743  *      jquery.ui.core.js\r
2744  *      jquery.ui.mouse.js\r
2745  *      jquery.ui.widget.js\r
2746  */\r
2747 (function($) {\r
2749 $.widget("ui.sortable", $.ui.mouse, {\r
2750         widgetEventPrefix: "sort",\r
2751         options: {\r
2752                 appendTo: "parent",\r
2753                 axis: false,\r
2754                 connectWith: false,\r
2755                 containment: false,\r
2756                 cursor: 'auto',\r
2757                 cursorAt: false,\r
2758                 dropOnEmpty: true,\r
2759                 forcePlaceholderSize: false,\r
2760                 forceHelperSize: false,\r
2761                 grid: false,\r
2762                 handle: false,\r
2763                 helper: "original",\r
2764                 items: '> *',\r
2765                 opacity: false,\r
2766                 placeholder: false,\r
2767                 revert: false,\r
2768                 scroll: true,\r
2769                 scrollSensitivity: 20,\r
2770                 scrollSpeed: 20,\r
2771                 scope: "default",\r
2772                 tolerance: "intersect",\r
2773                 zIndex: 1000\r
2774         },\r
2775         _create: function() {\r
2777                 var o = this.options;\r
2778                 this.containerCache = {};\r
2779                 this.element.addClass("ui-sortable");\r
2781                 //Get the items\r
2782                 this.refresh();\r
2784                 //Let's determine if the items are floating\r
2785                 this.floating = this.items.length ? (/left|right/).test(this.items[0].item.css('float')) : false;\r
2787                 //Let's determine the parent's offset\r
2788                 this.offset = this.element.offset();\r
2790                 //Initialize mouse events for interaction\r
2791                 this._mouseInit();\r
2793         },\r
2795         destroy: function() {\r
2796                 this.element\r
2797                         .removeClass("ui-sortable ui-sortable-disabled")\r
2798                         .removeData("sortable")\r
2799                         .unbind(".sortable");\r
2800                 this._mouseDestroy();\r
2802                 for ( var i = this.items.length - 1; i >= 0; i-- )\r
2803                         this.items[i].item.removeData("sortable-item");\r
2805                 return this;\r
2806         },\r
2808         _mouseCapture: function(event, overrideHandle) {\r
2810                 if (this.reverting) {\r
2811                         return false;\r
2812                 }\r
2814                 if(this.options.disabled || this.options.type == 'static') return false;\r
2816                 //We have to refresh the items data once first\r
2817                 this._refreshItems(event);\r
2819                 //Find out if the clicked node (or one of its parents) is a actual item in this.items\r
2820                 var currentItem = null, self = this, nodes = $(event.target).parents().each(function() {\r
2821                         if($.data(this, 'sortable-item') == self) {\r
2822                                 currentItem = $(this);\r
2823                                 return false;\r
2824                         }\r
2825                 });\r
2826                 if($.data(event.target, 'sortable-item') == self) currentItem = $(event.target);\r
2828                 if(!currentItem) return false;\r
2829                 if(this.options.handle && !overrideHandle) {\r
2830                         var validHandle = false;\r
2832                         $(this.options.handle, currentItem).find("*").andSelf().each(function() { if(this == event.target) validHandle = true; });\r
2833                         if(!validHandle) return false;\r
2834                 }\r
2836                 this.currentItem = currentItem;\r
2837                 this._removeCurrentsFromItems();\r
2838                 return true;\r
2840         },\r
2842         _mouseStart: function(event, overrideHandle, noActivation) {\r
2844                 var o = this.options, self = this;\r
2845                 this.currentContainer = this;\r
2847                 //We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture\r
2848                 this.refreshPositions();\r
2850                 //Create and append the visible helper\r
2851                 this.helper = this._createHelper(event);\r
2853                 //Cache the helper size\r
2854                 this._cacheHelperProportions();\r
2856                 /*\r
2857                  * - Position generation -\r
2858                  * This block generates everything position related - it's the core of draggables.\r
2859                  */\r
2861                 //Cache the margins of the original element\r
2862                 this._cacheMargins();\r
2864                 //Get the next scrolling parent\r
2865                 this.scrollParent = this.helper.scrollParent();\r
2867                 //The element's absolute position on the page minus margins\r
2868                 this.offset = this.currentItem.offset();\r
2869                 this.offset = {\r
2870                         top: this.offset.top - this.margins.top,\r
2871                         left: this.offset.left - this.margins.left\r
2872                 };\r
2874                 // Only after we got the offset, we can change the helper's position to absolute\r
2875                 // TODO: Still need to figure out a way to make relative sorting possible\r
2876                 this.helper.css("position", "absolute");\r
2877                 this.cssPosition = this.helper.css("position");\r
2879                 $.extend(this.offset, {\r
2880                         click: { //Where the click happened, relative to the element\r
2881                                 left: event.pageX - this.offset.left,\r
2882                                 top: event.pageY - this.offset.top\r
2883                         },\r
2884                         parent: this._getParentOffset(),\r
2885                         relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper\r
2886                 });\r
2888                 //Generate the original position\r
2889                 this.originalPosition = this._generatePosition(event);\r
2890                 this.originalPageX = event.pageX;\r
2891                 this.originalPageY = event.pageY;\r
2893                 //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied\r
2894                 (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));\r
2896                 //Cache the former DOM position\r
2897                 this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] };\r
2899                 //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\r
2900                 if(this.helper[0] != this.currentItem[0]) {\r
2901                         this.currentItem.hide();\r
2902                 }\r
2904                 //Create the placeholder\r
2905                 this._createPlaceholder();\r
2907                 //Set a containment if given in the options\r
2908                 if(o.containment)\r
2909                         this._setContainment();\r
2911                 if(o.cursor) { // cursor option\r
2912                         if ($('body').css("cursor")) this._storedCursor = $('body').css("cursor");\r
2913                         $('body').css("cursor", o.cursor);\r
2914                 }\r
2916                 if(o.opacity) { // opacity option\r
2917                         if (this.helper.css("opacity")) this._storedOpacity = this.helper.css("opacity");\r
2918                         this.helper.css("opacity", o.opacity);\r
2919                 }\r
2921                 if(o.zIndex) { // zIndex option\r
2922                         if (this.helper.css("zIndex")) this._storedZIndex = this.helper.css("zIndex");\r
2923                         this.helper.css("zIndex", o.zIndex);\r
2924                 }\r
2926                 //Prepare scrolling\r
2927                 if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML')\r
2928                         this.overflowOffset = this.scrollParent.offset();\r
2930                 //Call callbacks\r
2931                 this._trigger("start", event, this._uiHash());\r
2933                 //Recache the helper size\r
2934                 if(!this._preserveHelperProportions)\r
2935                         this._cacheHelperProportions();\r
2938                 //Post 'activate' events to possible containers\r
2939                 if(!noActivation) {\r
2940                          for (var i = this.containers.length - 1; i >= 0; i--) { this.containers[i]._trigger("activate", event, self._uiHash(this)); }\r
2941                 }\r
2943                 //Prepare possible droppables\r
2944                 if($.ui.ddmanager)\r
2945                         $.ui.ddmanager.current = this;\r
2947                 if ($.ui.ddmanager && !o.dropBehaviour)\r
2948                         $.ui.ddmanager.prepareOffsets(this, event);\r
2950                 this.dragging = true;\r
2952                 this.helper.addClass("ui-sortable-helper");\r
2953                 this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position\r
2954                 return true;\r
2956         },\r
2958         _mouseDrag: function(event) {\r
2960                 //Compute the helpers position\r
2961                 this.position = this._generatePosition(event);\r
2962                 this.positionAbs = this._convertPositionTo("absolute");\r
2964                 if (!this.lastPositionAbs) {\r
2965                         this.lastPositionAbs = this.positionAbs;\r
2966                 }\r
2968                 //Do scrolling\r
2969                 if(this.options.scroll) {\r
2970                         var o = this.options, scrolled = false;\r
2971                         if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') {\r
2973                                 if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)\r
2974                                         this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed;\r
2975                                 else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity)\r
2976                                         this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed;\r
2978                                 if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)\r
2979                                         this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed;\r
2980                                 else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity)\r
2981                                         this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed;\r
2983                         } else {\r
2985                                 if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)\r
2986                                         scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);\r
2987                                 else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)\r
2988                                         scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);\r
2990                                 if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)\r
2991                                         scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);\r
2992                                 else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)\r
2993                                         scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);\r
2995                         }\r
2997                         if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)\r
2998                                 $.ui.ddmanager.prepareOffsets(this, event);\r
2999                 }\r
3001                 //Regenerate the absolute position used for position checks\r
3002                 this.positionAbs = this._convertPositionTo("absolute");\r
3004                 //Set the helper position\r
3005                 if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';\r
3006                 if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';\r
3008                 //Rearrange\r
3009                 for (var i = this.items.length - 1; i >= 0; i--) {\r
3011                         //Cache variables and intersection, continue if no intersection\r
3012                         var item = this.items[i], itemElement = item.item[0], intersection = this._intersectsWithPointer(item);\r
3013                         if (!intersection) continue;\r
3015                         if(itemElement != this.currentItem[0] //cannot intersect with itself\r
3016                                 &&      this.placeholder[intersection == 1 ? "next" : "prev"]()[0] != itemElement //no useless actions that have been done before\r
3017                                 &&      !$.ui.contains(this.placeholder[0], itemElement) //no action if the item moved is the parent of the item checked\r
3018                                 && (this.options.type == 'semi-dynamic' ? !$.ui.contains(this.element[0], itemElement) : true)\r
3019                                 //&& itemElement.parentNode == this.placeholder[0].parentNode // only rearrange items within the same container\r
3020                         ) {\r
3022                                 this.direction = intersection == 1 ? "down" : "up";\r
3024                                 if (this.options.tolerance == "pointer" || this._intersectsWithSides(item)) {\r
3025                                         this._rearrange(event, item);\r
3026                                 } else {\r
3027                                         break;\r
3028                                 }\r
3030                                 this._trigger("change", event, this._uiHash());\r
3031                                 break;\r
3032                         }\r
3033                 }\r
3035                 //Post events to containers\r
3036                 this._contactContainers(event);\r
3038                 //Interconnect with droppables\r
3039                 if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);\r
3041                 //Call callbacks\r
3042                 this._trigger('sort', event, this._uiHash());\r
3044                 this.lastPositionAbs = this.positionAbs;\r
3045                 return false;\r
3047         },\r
3049         _mouseStop: function(event, noPropagation) {\r
3051                 if(!event) return;\r
3053                 //If we are using droppables, inform the manager about the drop\r
3054                 if ($.ui.ddmanager && !this.options.dropBehaviour)\r
3055                         $.ui.ddmanager.drop(this, event);\r
3057                 if(this.options.revert) {\r
3058                         var self = this;\r
3059                         var cur = self.placeholder.offset();\r
3061                         self.reverting = true;\r
3063                         $(this.helper).animate({\r
3064                                 left: cur.left - this.offset.parent.left - self.margins.left + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollLeft),\r
3065                                 top: cur.top - this.offset.parent.top - self.margins.top + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollTop)\r
3066                         }, parseInt(this.options.revert, 10) || 500, function() {\r
3067                                 self._clear(event);\r
3068                         });\r
3069                 } else {\r
3070                         this._clear(event, noPropagation);\r
3071                 }\r
3073                 return false;\r
3075         },\r
3077         cancel: function() {\r
3079                 var self = this;\r
3081                 if(this.dragging) {\r
3083                         this._mouseUp();\r
3085                         if(this.options.helper == "original")\r
3086                                 this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");\r
3087                         else\r
3088                                 this.currentItem.show();\r
3090                         //Post deactivating events to containers\r
3091                         for (var i = this.containers.length - 1; i >= 0; i--){\r
3092                                 this.containers[i]._trigger("deactivate", null, self._uiHash(this));\r
3093                                 if(this.containers[i].containerCache.over) {\r
3094                                         this.containers[i]._trigger("out", null, self._uiHash(this));\r
3095                                         this.containers[i].containerCache.over = 0;\r
3096                                 }\r
3097                         }\r
3099                 }\r
3101                 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!\r
3102                 if(this.placeholder[0].parentNode) this.placeholder[0].parentNode.removeChild(this.placeholder[0]);\r
3103                 if(this.options.helper != "original" && this.helper && this.helper[0].parentNode) this.helper.remove();\r
3105                 $.extend(this, {\r
3106                         helper: null,\r
3107                         dragging: false,\r
3108                         reverting: false,\r
3109                         _noFinalSort: null\r
3110                 });\r
3112                 if(this.domPosition.prev) {\r
3113                         $(this.domPosition.prev).after(this.currentItem);\r
3114                 } else {\r
3115                         $(this.domPosition.parent).prepend(this.currentItem);\r
3116                 }\r
3118                 return this;\r
3120         },\r
3122         serialize: function(o) {\r
3124                 var items = this._getItemsAsjQuery(o && o.connected);\r
3125                 var str = []; o = o || {};\r
3127                 $(items).each(function() {\r
3128                         var res = ($(o.item || this).attr(o.attribute || 'id') || '').match(o.expression || (/(.+)[-=_](.+)/));\r
3129                         if(res) str.push((o.key || res[1]+'[]')+'='+(o.key && o.expression ? res[1] : res[2]));\r
3130                 });\r
3132                 return str.join('&');\r
3134         },\r
3136         toArray: function(o) {\r
3138                 var items = this._getItemsAsjQuery(o && o.connected);\r
3139                 var ret = []; o = o || {};\r
3141                 items.each(function() { ret.push($(o.item || this).attr(o.attribute || 'id') || ''); });\r
3142                 return ret;\r
3144         },\r
3146         /* Be careful with the following core functions */\r
3147         _intersectsWith: function(item) {\r
3149                 var x1 = this.positionAbs.left,\r
3150                         x2 = x1 + this.helperProportions.width,\r
3151                         y1 = this.positionAbs.top,\r
3152                         y2 = y1 + this.helperProportions.height;\r
3154                 var l = item.left,\r
3155                         r = l + item.width,\r
3156                         t = item.top,\r
3157                         b = t + item.height;\r
3159                 var dyClick = this.offset.click.top,\r
3160                         dxClick = this.offset.click.left;\r
3162                 var isOverElement = (y1 + dyClick) > t && (y1 + dyClick) < b && (x1 + dxClick) > l && (x1 + dxClick) < r;\r
3164                 if(        this.options.tolerance == "pointer"\r
3165                         || this.options.forcePointerForContainers\r
3166                         || (this.options.tolerance != "pointer" && this.helperProportions[this.floating ? 'width' : 'height'] > item[this.floating ? 'width' : 'height'])\r
3167                 ) {\r
3168                         return isOverElement;\r
3169                 } else {\r
3171                         return (l < x1 + (this.helperProportions.width / 2) // Right Half\r
3172                                 && x2 - (this.helperProportions.width / 2) < r // Left Half\r
3173                                 && t < y1 + (this.helperProportions.height / 2) // Bottom Half\r
3174                                 && y2 - (this.helperProportions.height / 2) < b ); // Top Half\r
3176                 }\r
3177         },\r
3179         _intersectsWithPointer: function(item) {\r
3181                 var isOverElementHeight = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height),\r
3182                         isOverElementWidth = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width),\r
3183                         isOverElement = isOverElementHeight && isOverElementWidth,\r
3184                         verticalDirection = this._getDragVerticalDirection(),\r
3185                         horizontalDirection = this._getDragHorizontalDirection();\r
3187                 if (!isOverElement)\r
3188                         return false;\r
3190                 return this.floating ?\r
3191                         ( ((horizontalDirection && horizontalDirection == "right") || verticalDirection == "down") ? 2 : 1 )\r
3192                         : ( verticalDirection && (verticalDirection == "down" ? 2 : 1) );\r
3194         },\r
3196         _intersectsWithSides: function(item) {\r
3198                 var isOverBottomHalf = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height),\r
3199                         isOverRightHalf = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width),\r
3200                         verticalDirection = this._getDragVerticalDirection(),\r
3201                         horizontalDirection = this._getDragHorizontalDirection();\r
3203                 if (this.floating && horizontalDirection) {\r
3204                         return ((horizontalDirection == "right" && isOverRightHalf) || (horizontalDirection == "left" && !isOverRightHalf));\r
3205                 } else {\r
3206                         return verticalDirection && ((verticalDirection == "down" && isOverBottomHalf) || (verticalDirection == "up" && !isOverBottomHalf));\r
3207                 }\r
3209         },\r
3211         _getDragVerticalDirection: function() {\r
3212                 var delta = this.positionAbs.top - this.lastPositionAbs.top;\r
3213                 return delta != 0 && (delta > 0 ? "down" : "up");\r
3214         },\r
3216         _getDragHorizontalDirection: function() {\r
3217                 var delta = this.positionAbs.left - this.lastPositionAbs.left;\r
3218                 return delta != 0 && (delta > 0 ? "right" : "left");\r
3219         },\r
3221         refresh: function(event) {\r
3222                 this._refreshItems(event);\r
3223                 this.refreshPositions();\r
3224                 return this;\r
3225         },\r
3227         _connectWith: function() {\r
3228                 var options = this.options;\r
3229                 return options.connectWith.constructor == String\r
3230                         ? [options.connectWith]\r
3231                         : options.connectWith;\r
3232         },\r
3233         \r
3234         _getItemsAsjQuery: function(connected) {\r
3236                 var self = this;\r
3237                 var items = [];\r
3238                 var queries = [];\r
3239                 var connectWith = this._connectWith();\r
3241                 if(connectWith && connected) {\r
3242                         for (var i = connectWith.length - 1; i >= 0; i--){\r
3243                                 var cur = $(connectWith[i]);\r
3244                                 for (var j = cur.length - 1; j >= 0; j--){\r
3245                                         var inst = $.data(cur[j], 'sortable');\r
3246                                         if(inst && inst != this && !inst.options.disabled) {\r
3247                                                 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]);\r
3248                                         }\r
3249                                 };\r
3250                         };\r
3251                 }\r
3253                 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]);\r
3255                 for (var i = queries.length - 1; i >= 0; i--){\r
3256                         queries[i][0].each(function() {\r
3257                                 items.push(this);\r
3258                         });\r
3259                 };\r
3261                 return $(items);\r
3263         },\r
3265         _removeCurrentsFromItems: function() {\r
3267                 var list = this.currentItem.find(":data(sortable-item)");\r
3269                 for (var i=0; i < this.items.length; i++) {\r
3271                         for (var j=0; j < list.length; j++) {\r
3272                                 if(list[j] == this.items[i].item[0])\r
3273                                         this.items.splice(i,1);\r
3274                         };\r
3276                 };\r
3278         },\r
3280         _refreshItems: function(event) {\r
3282                 this.items = [];\r
3283                 this.containers = [this];\r
3284                 var items = this.items;\r
3285                 var self = this;\r
3286                 var queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]];\r
3287                 var connectWith = this._connectWith();\r
3289                 if(connectWith) {\r
3290                         for (var i = connectWith.length - 1; i >= 0; i--){\r
3291                                 var cur = $(connectWith[i]);\r
3292                                 for (var j = cur.length - 1; j >= 0; j--){\r
3293                                         var inst = $.data(cur[j], 'sortable');\r
3294                                         if(inst && inst != this && !inst.options.disabled) {\r
3295                                                 queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]);\r
3296                                                 this.containers.push(inst);\r
3297                                         }\r
3298                                 };\r
3299                         };\r
3300                 }\r
3302                 for (var i = queries.length - 1; i >= 0; i--) {\r
3303                         var targetData = queries[i][1];\r
3304                         var _queries = queries[i][0];\r
3306                         for (var j=0, queriesLength = _queries.length; j < queriesLength; j++) {\r
3307                                 var item = $(_queries[j]);\r
3309                                 item.data('sortable-item', targetData); // Data for target checking (mouse manager)\r
3311                                 items.push({\r
3312                                         item: item,\r
3313                                         instance: targetData,\r
3314                                         width: 0, height: 0,\r
3315                                         left: 0, top: 0\r
3316                                 });\r
3317                         };\r
3318                 };\r
3320         },\r
3322         refreshPositions: function(fast) {\r
3324                 //This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change\r
3325                 if(this.offsetParent && this.helper) {\r
3326                         this.offset.parent = this._getParentOffset();\r
3327                 }\r
3329                 for (var i = this.items.length - 1; i >= 0; i--){\r
3330                         var item = this.items[i];\r
3332                         var t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item;\r
3334                         if (!fast) {\r
3335                                 item.width = t.outerWidth();\r
3336                                 item.height = t.outerHeight();\r
3337                         }\r
3339                         var p = t.offset();\r
3340                         item.left = p.left;\r
3341                         item.top = p.top;\r
3342                 };\r
3344                 if(this.options.custom && this.options.custom.refreshContainers) {\r
3345                         this.options.custom.refreshContainers.call(this);\r
3346                 } else {\r
3347                         for (var i = this.containers.length - 1; i >= 0; i--){\r
3348                                 var p = this.containers[i].element.offset();\r
3349                                 this.containers[i].containerCache.left = p.left;\r
3350                                 this.containers[i].containerCache.top = p.top;\r
3351                                 this.containers[i].containerCache.width = this.containers[i].element.outerWidth();\r
3352                                 this.containers[i].containerCache.height = this.containers[i].element.outerHeight();\r
3353                         };\r
3354                 }\r
3356                 return this;\r
3357         },\r
3359         _createPlaceholder: function(that) {\r
3361                 var self = that || this, o = self.options;\r
3363                 if(!o.placeholder || o.placeholder.constructor == String) {\r
3364                         var className = o.placeholder;\r
3365                         o.placeholder = {\r
3366                                 element: function() {\r
3368                                         var el = $(document.createElement(self.currentItem[0].nodeName))\r
3369                                                 .addClass(className || self.currentItem[0].className+" ui-sortable-placeholder")\r
3370                                                 .removeClass("ui-sortable-helper")[0];\r
3372                                         if(!className)\r
3373                                                 el.style.visibility = "hidden";\r
3375                                         return el;\r
3376                                 },\r
3377                                 update: function(container, p) {\r
3379                                         // 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that\r
3380                                         // 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified\r
3381                                         if(className && !o.forcePlaceholderSize) return;\r
3383                                         //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\r
3384                                         if(!p.height()) { p.height(self.currentItem.innerHeight() - parseInt(self.currentItem.css('paddingTop')||0, 10) - parseInt(self.currentItem.css('paddingBottom')||0, 10)); };\r
3385                                         if(!p.width()) { p.width(self.currentItem.innerWidth() - parseInt(self.currentItem.css('paddingLeft')||0, 10) - parseInt(self.currentItem.css('paddingRight')||0, 10)); };\r
3386                                 }\r
3387                         };\r
3388                 }\r
3390                 //Create the placeholder\r
3391                 self.placeholder = $(o.placeholder.element.call(self.element, self.currentItem));\r
3393                 //Append it after the actual current item\r
3394                 self.currentItem.after(self.placeholder);\r
3396                 //Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)\r
3397                 o.placeholder.update(self, self.placeholder);\r
3399         },\r
3401         _contactContainers: function(event) {\r
3402                 \r
3403                 // get innermost container that intersects with item \r
3404                 var innermostContainer = null, innermostIndex = null;           \r
3405                 \r
3406                 \r
3407                 for (var i = this.containers.length - 1; i >= 0; i--){\r
3409                         // never consider a container that's located within the item itself \r
3410                         if($.ui.contains(this.currentItem[0], this.containers[i].element[0]))\r
3411                                 continue;\r
3413                         if(this._intersectsWith(this.containers[i].containerCache)) {\r
3415                                 // if we've already found a container and it's more "inner" than this, then continue \r
3416                                 if(innermostContainer && $.ui.contains(this.containers[i].element[0], innermostContainer.element[0]))\r
3417                                         continue;\r
3419                                 innermostContainer = this.containers[i]; \r
3420                                 innermostIndex = i;\r
3421                                         \r
3422                         } else {\r
3423                                 // container doesn't intersect. trigger "out" event if necessary \r
3424                                 if(this.containers[i].containerCache.over) {\r
3425                                         this.containers[i]._trigger("out", event, this._uiHash(this));\r
3426                                         this.containers[i].containerCache.over = 0;\r
3427                                 }\r
3428                         }\r
3430                 }\r
3431                 \r
3432                 // if no intersecting containers found, return \r
3433                 if(!innermostContainer) return; \r
3435                 // move the item into the container if it's not there already\r
3436                 if(this.containers.length === 1) {\r
3437                         this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));\r
3438                         this.containers[innermostIndex].containerCache.over = 1;\r
3439                 } else if(this.currentContainer != this.containers[innermostIndex]) { \r
3441                         //When entering a new container, we will find the item with the least distance and append our item near it \r
3442                         var dist = 10000; var itemWithLeastDistance = null; var base = this.positionAbs[this.containers[innermostIndex].floating ? 'left' : 'top']; \r
3443                         for (var j = this.items.length - 1; j >= 0; j--) { \r
3444                                 if(!$.ui.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) continue; \r
3445                                 var cur = this.items[j][this.containers[innermostIndex].floating ? 'left' : 'top']; \r
3446                                 if(Math.abs(cur - base) < dist) { \r
3447                                         dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j]; \r
3448                                 } \r
3449                         } \r
3451                         if(!itemWithLeastDistance && !this.options.dropOnEmpty) //Check if dropOnEmpty is enabled \r
3452                                 return; \r
3454                         this.currentContainer = this.containers[innermostIndex]; \r
3455                         itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true); \r
3456                         this._trigger("change", event, this._uiHash()); \r
3457                         this.containers[innermostIndex]._trigger("change", event, this._uiHash(this)); \r
3459                         //Update the placeholder \r
3460                         this.options.placeholder.update(this.currentContainer, this.placeholder); \r
3461                 \r
3462                         this.containers[innermostIndex]._trigger("over", event, this._uiHash(this)); \r
3463                         this.containers[innermostIndex].containerCache.over = 1;\r
3464                 } \r
3465         \r
3466                 \r
3467         },\r
3469         _createHelper: function(event) {\r
3471                 var o = this.options;\r
3472                 var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper == 'clone' ? this.currentItem.clone() : this.currentItem);\r
3474                 if(!helper.parents('body').length) //Add the helper to the DOM if that didn't happen already\r
3475                         $(o.appendTo != 'parent' ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]);\r
3477                 if(helper[0] == this.currentItem[0])\r
3478                         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") };\r
3480                 if(helper[0].style.width == '' || o.forceHelperSize) helper.width(this.currentItem.width());\r
3481                 if(helper[0].style.height == '' || o.forceHelperSize) helper.height(this.currentItem.height());\r
3483                 return helper;\r
3485         },\r
3487         _adjustOffsetFromHelper: function(obj) {\r
3488                 if (typeof obj == 'string') {\r
3489                         obj = obj.split(' ');\r
3490                 }\r
3491                 if ($.isArray(obj)) {\r
3492                         obj = {left: +obj[0], top: +obj[1] || 0};\r
3493                 }\r
3494                 if ('left' in obj) {\r
3495                         this.offset.click.left = obj.left + this.margins.left;\r
3496                 }\r
3497                 if ('right' in obj) {\r
3498                         this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;\r
3499                 }\r
3500                 if ('top' in obj) {\r
3501                         this.offset.click.top = obj.top + this.margins.top;\r
3502                 }\r
3503                 if ('bottom' in obj) {\r
3504                         this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;\r
3505                 }\r
3506         },\r
3508         _getParentOffset: function() {\r
3511                 //Get the offsetParent and cache its position\r
3512                 this.offsetParent = this.helper.offsetParent();\r
3513                 var po = this.offsetParent.offset();\r
3515                 // This is a special case where we need to modify a offset calculated on start, since the following happened:\r
3516                 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent\r
3517                 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that\r
3518                 //    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag\r
3519                 if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) {\r
3520                         po.left += this.scrollParent.scrollLeft();\r
3521                         po.top += this.scrollParent.scrollTop();\r
3522                 }\r
3524                 if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information\r
3525                 || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix\r
3526                         po = { top: 0, left: 0 };\r
3528                 return {\r
3529                         top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),\r
3530                         left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)\r
3531                 };\r
3533         },\r
3535         _getRelativeOffset: function() {\r
3537                 if(this.cssPosition == "relative") {\r
3538                         var p = this.currentItem.position();\r
3539                         return {\r
3540                                 top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),\r
3541                                 left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()\r
3542                         };\r
3543                 } else {\r
3544                         return { top: 0, left: 0 };\r
3545                 }\r
3547         },\r
3549         _cacheMargins: function() {\r
3550                 this.margins = {\r
3551                         left: (parseInt(this.currentItem.css("marginLeft"),10) || 0),\r
3552                         top: (parseInt(this.currentItem.css("marginTop"),10) || 0)\r
3553                 };\r
3554         },\r
3556         _cacheHelperProportions: function() {\r
3557                 this.helperProportions = {\r
3558                         width: this.helper.outerWidth(),\r
3559                         height: this.helper.outerHeight()\r
3560                 };\r
3561         },\r
3563         _setContainment: function() {\r
3565                 var o = this.options;\r
3566                 if(o.containment == 'parent') o.containment = this.helper[0].parentNode;\r
3567                 if(o.containment == 'document' || o.containment == 'window') this.containment = [\r
3568                         0 - this.offset.relative.left - this.offset.parent.left,\r
3569                         0 - this.offset.relative.top - this.offset.parent.top,\r
3570                         $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,\r
3571                         ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top\r
3572                 ];\r
3574                 if(!(/^(document|window|parent)$/).test(o.containment)) {\r
3575                         var ce = $(o.containment)[0];\r
3576                         var co = $(o.containment).offset();\r
3577                         var over = ($(ce).css("overflow") != 'hidden');\r
3579                         this.containment = [\r
3580                                 co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,\r
3581                                 co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,\r
3582                                 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,\r
3583                                 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\r
3584                         ];\r
3585                 }\r
3587         },\r
3589         _convertPositionTo: function(d, pos) {\r
3591                 if(!pos) pos = this.position;\r
3592                 var mod = d == "absolute" ? 1 : -1;\r
3593                 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);\r
3595                 return {\r
3596                         top: (\r
3597                                 pos.top                                                                                                                                 // The absolute mouse position\r
3598                                 + this.offset.relative.top * mod                                                                                // Only for relative positioned nodes: Relative offset from element to offset parent\r
3599                                 + this.offset.parent.top * mod                                                                                  // The offsetParent's offset without borders (offset + border)\r
3600                                 - ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)\r
3601                         ),\r
3602                         left: (\r
3603                                 pos.left                                                                                                                                // The absolute mouse position\r
3604                                 + this.offset.relative.left * mod                                                                               // Only for relative positioned nodes: Relative offset from element to offset parent\r
3605                                 + this.offset.parent.left * mod                                                                                 // The offsetParent's offset without borders (offset + border)\r
3606                                 - ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)\r
3607                         )\r
3608                 };\r
3610         },\r
3612         _generatePosition: function(event) {\r
3614                 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);\r
3616                 // This is another very weird special case that only happens for relative elements:\r
3617                 // 1. If the css position is relative\r
3618                 // 2. and the scroll parent is the document or similar to the offset parent\r
3619                 // we have to refresh the relative offset during the scroll so there are no jumps\r
3620                 if(this.cssPosition == 'relative' && !(this.scrollParent[0] != document && this.scrollParent[0] != this.offsetParent[0])) {\r
3621                         this.offset.relative = this._getRelativeOffset();\r
3622                 }\r
3624                 var pageX = event.pageX;\r
3625                 var pageY = event.pageY;\r
3627                 /*\r
3628                  * - Position constraining -\r
3629                  * Constrain the position to a mix of grid, containment.\r
3630                  */\r
3632                 if(this.originalPosition) { //If we are not dragging yet, we won't check for options\r
3634                         if(this.containment) {\r
3635                                 if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left;\r
3636                                 if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top;\r
3637                                 if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left;\r
3638                                 if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top;\r
3639                         }\r
3641                         if(o.grid) {\r
3642                                 var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];\r
3643                                 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;\r
3645                                 var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];\r
3646                                 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;\r
3647                         }\r
3649                 }\r
3651                 return {\r
3652                         top: (\r
3653                                 pageY                                                                                                                           // The absolute mouse position\r
3654                                 - this.offset.click.top                                                                                                 // Click offset (relative to the element)\r
3655                                 - this.offset.relative.top                                                                                              // Only for relative positioned nodes: Relative offset from element to offset parent\r
3656                                 - this.offset.parent.top                                                                                                // The offsetParent's offset without borders (offset + border)\r
3657                                 + ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))\r
3658                         ),\r
3659                         left: (\r
3660                                 pageX                                                                                                                           // The absolute mouse position\r
3661                                 - this.offset.click.left                                                                                                // Click offset (relative to the element)\r
3662                                 - this.offset.relative.left                                                                                             // Only for relative positioned nodes: Relative offset from element to offset parent\r
3663                                 - this.offset.parent.left                                                                                               // The offsetParent's offset without borders (offset + border)\r
3664                                 + ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))\r
3665                         )\r
3666                 };\r
3668         },\r
3670         _rearrange: function(event, i, a, hardRefresh) {\r
3672                 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));\r
3674                 //Various things done here to improve the performance:\r
3675                 // 1. we create a setTimeout, that calls refreshPositions\r
3676                 // 2. on the instance, we have a counter variable, that get's higher after every append\r
3677                 // 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same\r
3678                 // 4. this lets only the last addition to the timeout stack through\r
3679                 this.counter = this.counter ? ++this.counter : 1;\r
3680                 var self = this, counter = this.counter;\r
3682                 window.setTimeout(function() {\r
3683                         if(counter == self.counter) self.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove\r
3684                 },0);\r
3686         },\r
3688         _clear: function(event, noPropagation) {\r
3690                 this.reverting = false;\r
3691                 // We delay all events that have to be triggered to after the point where the placeholder has been removed and\r
3692                 // everything else normalized again\r
3693                 var delayedTriggers = [], self = this;\r
3695                 // We first have to update the dom position of the actual currentItem\r
3696                 // Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088)\r
3697                 if(!this._noFinalSort && this.currentItem[0].parentNode) this.placeholder.before(this.currentItem);\r
3698                 this._noFinalSort = null;\r
3700                 if(this.helper[0] == this.currentItem[0]) {\r
3701                         for(var i in this._storedCSS) {\r
3702                                 if(this._storedCSS[i] == 'auto' || this._storedCSS[i] == 'static') this._storedCSS[i] = '';\r
3703                         }\r
3704                         this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");\r
3705                 } else {\r
3706                         this.currentItem.show();\r
3707                 }\r
3709                 if(this.fromOutside && !noPropagation) delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); });\r
3710                 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\r
3711                 if(!$.ui.contains(this.element[0], this.currentItem[0])) { //Node was moved out of the current element\r
3712                         if(!noPropagation) delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); });\r
3713                         for (var i = this.containers.length - 1; i >= 0; i--){\r
3714                                 if($.ui.contains(this.containers[i].element[0], this.currentItem[0]) && !noPropagation) {\r
3715                                         delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); };  }).call(this, this.containers[i]));\r
3716                                         delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this));  }; }).call(this, this.containers[i]));\r
3717                                 }\r
3718                         };\r
3719                 };\r
3721                 //Post events to containers\r
3722                 for (var i = this.containers.length - 1; i >= 0; i--){\r
3723                         if(!noPropagation) delayedTriggers.push((function(c) { return function(event) { c._trigger("deactivate", event, this._uiHash(this)); };  }).call(this, this.containers[i]));\r
3724                         if(this.containers[i].containerCache.over) {\r
3725                                 delayedTriggers.push((function(c) { return function(event) { c._trigger("out", event, this._uiHash(this)); };  }).call(this, this.containers[i]));\r
3726                                 this.containers[i].containerCache.over = 0;\r
3727                         }\r
3728                 }\r
3730                 //Do what was originally in plugins\r
3731                 if(this._storedCursor) $('body').css("cursor", this._storedCursor); //Reset cursor\r
3732                 if(this._storedOpacity) this.helper.css("opacity", this._storedOpacity); //Reset opacity\r
3733                 if(this._storedZIndex) this.helper.css("zIndex", this._storedZIndex == 'auto' ? '' : this._storedZIndex); //Reset z-index\r
3735                 this.dragging = false;\r
3736                 if(this.cancelHelperRemoval) {\r
3737                         if(!noPropagation) {\r
3738                                 this._trigger("beforeStop", event, this._uiHash());\r
3739                                 for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events\r
3740                                 this._trigger("stop", event, this._uiHash());\r
3741                         }\r
3742                         return false;\r
3743                 }\r
3745                 if(!noPropagation) this._trigger("beforeStop", event, this._uiHash());\r
3747                 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!\r
3748                 this.placeholder[0].parentNode.removeChild(this.placeholder[0]);\r
3750                 if(this.helper[0] != this.currentItem[0]) this.helper.remove(); this.helper = null;\r
3752                 if(!noPropagation) {\r
3753                         for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events\r
3754                         this._trigger("stop", event, this._uiHash());\r
3755                 }\r
3757                 this.fromOutside = false;\r
3758                 return true;\r
3760         },\r
3762         _trigger: function() {\r
3763                 if ($.Widget.prototype._trigger.apply(this, arguments) === false) {\r
3764                         this.cancel();\r
3765                 }\r
3766         },\r
3768         _uiHash: function(inst) {\r
3769                 var self = inst || this;\r
3770                 return {\r
3771                         helper: self.helper,\r
3772                         placeholder: self.placeholder || $([]),\r
3773                         position: self.position,\r
3774                         originalPosition: self.originalPosition,\r
3775                         offset: self.positionAbs,\r
3776                         item: self.currentItem,\r
3777                         sender: inst ? inst.element : null\r
3778                 };\r
3779         }\r
3781 });\r
3783 $.extend($.ui.sortable, {\r
3784         version: "1.8"\r
3785 });\r
3787 })(jQuery);\r
3788 /*\r
3789  * jQuery UI Effects 1.8\r
3790  *\r
3791  * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)\r
3792  * Dual licensed under the MIT (MIT-LICENSE.txt)\r
3793  * and GPL (GPL-LICENSE.txt) licenses.\r
3794  *\r
3795  * http://docs.jquery.com/UI/Effects/\r
3796  */\r
3797 ;jQuery.effects || (function($) {\r
3799 $.effects = {};\r
3803 /******************************************************************************/\r
3804 /****************************** COLOR ANIMATIONS ******************************/\r
3805 /******************************************************************************/\r
3807 // override the animation for color styles\r
3808 $.each(['backgroundColor', 'borderBottomColor', 'borderLeftColor',\r
3809         'borderRightColor', 'borderTopColor', 'color', 'outlineColor'],\r
3810 function(i, attr) {\r
3811         $.fx.step[attr] = function(fx) {\r
3812                 if (!fx.colorInit) {\r
3813                         fx.start = getColor(fx.elem, attr);\r
3814                         fx.end = getRGB(fx.end);\r
3815                         fx.colorInit = true;\r
3816                 }\r
3818                 fx.elem.style[attr] = 'rgb(' +\r
3819                         Math.max(Math.min(parseInt((fx.pos * (fx.end[0] - fx.start[0])) + fx.start[0], 10), 255), 0) + ',' +\r
3820                         Math.max(Math.min(parseInt((fx.pos * (fx.end[1] - fx.start[1])) + fx.start[1], 10), 255), 0) + ',' +\r
3821                         Math.max(Math.min(parseInt((fx.pos * (fx.end[2] - fx.start[2])) + fx.start[2], 10), 255), 0) + ')';\r
3822         };\r
3823 });\r
3825 // Color Conversion functions from highlightFade\r
3826 // By Blair Mitchelmore\r
3827 // http://jquery.offput.ca/highlightFade/\r
3829 // Parse strings looking for color tuples [255,255,255]\r
3830 function getRGB(color) {\r
3831                 var result;\r
3833                 // Check if we're already dealing with an array of colors\r
3834                 if ( color && color.constructor == Array && color.length == 3 )\r
3835                                 return color;\r
3837                 // Look for rgb(num,num,num)\r
3838                 if (result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(color))\r
3839                                 return [parseInt(result[1],10), parseInt(result[2],10), parseInt(result[3],10)];\r
3841                 // Look for rgb(num%,num%,num%)\r
3842                 if (result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(color))\r
3843                                 return [parseFloat(result[1])*2.55, parseFloat(result[2])*2.55, parseFloat(result[3])*2.55];\r
3845                 // Look for #a0b1c2\r
3846                 if (result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(color))\r
3847                                 return [parseInt(result[1],16), parseInt(result[2],16), parseInt(result[3],16)];\r
3849                 // Look for #fff\r
3850                 if (result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(color))\r
3851                                 return [parseInt(result[1]+result[1],16), parseInt(result[2]+result[2],16), parseInt(result[3]+result[3],16)];\r
3853                 // Look for rgba(0, 0, 0, 0) == transparent in Safari 3\r
3854                 if (result = /rgba\(0, 0, 0, 0\)/.exec(color))\r
3855                                 return colors['transparent'];\r
3857                 // Otherwise, we're most likely dealing with a named color\r
3858                 return colors[$.trim(color).toLowerCase()];\r
3861 function getColor(elem, attr) {\r
3862                 var color;\r
3864                 do {\r
3865                                 color = $.curCSS(elem, attr);\r
3867                                 // Keep going until we find an element that has color, or we hit the body\r
3868                                 if ( color != '' && color != 'transparent' || $.nodeName(elem, "body") )\r
3869                                                 break;\r
3871                                 attr = "backgroundColor";\r
3872                 } while ( elem = elem.parentNode );\r
3874                 return getRGB(color);\r
3875 };\r
3877 // Some named colors to work with\r
3878 // From Interface by Stefan Petre\r
3879 // http://interface.eyecon.ro/\r
3881 var colors = {\r
3882         aqua:[0,255,255],\r
3883         azure:[240,255,255],\r
3884         beige:[245,245,220],\r
3885         black:[0,0,0],\r
3886         blue:[0,0,255],\r
3887         brown:[165,42,42],\r
3888         cyan:[0,255,255],\r
3889         darkblue:[0,0,139],\r
3890         darkcyan:[0,139,139],\r
3891         darkgrey:[169,169,169],\r
3892         darkgreen:[0,100,0],\r
3893         darkkhaki:[189,183,107],\r
3894         darkmagenta:[139,0,139],\r
3895         darkolivegreen:[85,107,47],\r
3896         darkorange:[255,140,0],\r
3897         darkorchid:[153,50,204],\r
3898         darkred:[139,0,0],\r
3899         darksalmon:[233,150,122],\r
3900         darkviolet:[148,0,211],\r
3901         fuchsia:[255,0,255],\r
3902         gold:[255,215,0],\r
3903         green:[0,128,0],\r
3904         indigo:[75,0,130],\r
3905         khaki:[240,230,140],\r
3906         lightblue:[173,216,230],\r
3907         lightcyan:[224,255,255],\r
3908         lightgreen:[144,238,144],\r
3909         lightgrey:[211,211,211],\r
3910         lightpink:[255,182,193],\r
3911         lightyellow:[255,255,224],\r
3912         lime:[0,255,0],\r
3913         magenta:[255,0,255],\r
3914         maroon:[128,0,0],\r
3915         navy:[0,0,128],\r
3916         olive:[128,128,0],\r
3917         orange:[255,165,0],\r
3918         pink:[255,192,203],\r
3919         purple:[128,0,128],\r
3920         violet:[128,0,128],\r
3921         red:[255,0,0],\r
3922         silver:[192,192,192],\r
3923         white:[255,255,255],\r
3924         yellow:[255,255,0],\r
3925         transparent: [255,255,255]\r
3926 };\r
3930 /******************************************************************************/\r
3931 /****************************** CLASS ANIMATIONS ******************************/\r
3932 /******************************************************************************/\r
3934 var classAnimationActions = ['add', 'remove', 'toggle'],\r
3935         shorthandStyles = {\r
3936                 border: 1,\r
3937                 borderBottom: 1,\r
3938                 borderColor: 1,\r
3939                 borderLeft: 1,\r
3940                 borderRight: 1,\r
3941                 borderTop: 1,\r
3942                 borderWidth: 1,\r
3943                 margin: 1,\r
3944                 padding: 1\r
3945         };\r
3947 function getElementStyles() {\r
3948         var style = document.defaultView\r
3949                         ? document.defaultView.getComputedStyle(this, null)\r
3950                         : this.currentStyle,\r
3951                 newStyle = {},\r
3952                 key,\r
3953                 camelCase;\r
3955         // webkit enumerates style porperties\r
3956         if (style && style.length && style[0] && style[style[0]]) {\r
3957                 var len = style.length;\r
3958                 while (len--) {\r
3959                         key = style[len];\r
3960                         if (typeof style[key] == 'string') {\r
3961                                 camelCase = key.replace(/\-(\w)/g, function(all, letter){\r
3962                                         return letter.toUpperCase();\r
3963                                 });\r
3964                                 newStyle[camelCase] = style[key];\r
3965                         }\r
3966                 }\r
3967         } else {\r
3968                 for (key in style) {\r
3969                         if (typeof style[key] === 'string') {\r
3970                                 newStyle[key] = style[key];\r
3971                         }\r
3972                 }\r
3973         }\r
3974         \r
3975         return newStyle;\r
3978 function filterStyles(styles) {\r
3979         var name, value;\r
3980         for (name in styles) {\r
3981                 value = styles[name];\r
3982                 if (\r
3983                         // ignore null and undefined values\r
3984                         value == null ||\r
3985                         // ignore functions (when does this occur?)\r
3986                         $.isFunction(value) ||\r
3987                         // shorthand styles that need to be expanded\r
3988                         name in shorthandStyles ||\r
3989                         // ignore scrollbars (break in IE)\r
3990                         (/scrollbar/).test(name) ||\r
3992                         // only colors or values that can be converted to numbers\r
3993                         (!(/color/i).test(name) && isNaN(parseFloat(value)))\r
3994                 ) {\r
3995                         delete styles[name];\r
3996                 }\r
3997         }\r
3998         \r
3999         return styles;\r
4002 function styleDifference(oldStyle, newStyle) {\r
4003         var diff = { _: 0 }, // http://dev.jquery.com/ticket/5459\r
4004                 name;\r
4006         for (name in newStyle) {\r
4007                 if (oldStyle[name] != newStyle[name]) {\r
4008                         diff[name] = newStyle[name];\r
4009                 }\r
4010         }\r
4012         return diff;\r
4015 $.effects.animateClass = function(value, duration, easing, callback) {\r
4016         if ($.isFunction(easing)) {\r
4017                 callback = easing;\r
4018                 easing = null;\r
4019         }\r
4021         return this.each(function() {\r
4023                 var that = $(this),\r
4024                         originalStyleAttr = that.attr('style') || ' ',\r
4025                         originalStyle = filterStyles(getElementStyles.call(this)),\r
4026                         newStyle,\r
4027                         className = that.attr('className');\r
4029                 $.each(classAnimationActions, function(i, action) {\r
4030                         if (value[action]) {\r
4031                                 that[action + 'Class'](value[action]);\r
4032                         }\r
4033                 });\r
4034                 newStyle = filterStyles(getElementStyles.call(this));\r
4035                 that.attr('className', className);\r
4037                 that.animate(styleDifference(originalStyle, newStyle), duration, easing, function() {\r
4038                         $.each(classAnimationActions, function(i, action) {\r
4039                                 if (value[action]) { that[action + 'Class'](value[action]); }\r
4040                         });\r
4041                         // work around bug in IE by clearing the cssText before setting it\r
4042                         if (typeof that.attr('style') == 'object') {\r
4043                                 that.attr('style').cssText = '';\r
4044                                 that.attr('style').cssText = originalStyleAttr;\r
4045                         } else {\r
4046                                 that.attr('style', originalStyleAttr);\r
4047                         }\r
4048                         if (callback) { callback.apply(this, arguments); }\r
4049                 });\r
4050         });\r
4051 };\r
4053 $.fn.extend({\r
4054         _addClass: $.fn.addClass,\r
4055         addClass: function(classNames, speed, easing, callback) {\r
4056                 return speed ? $.effects.animateClass.apply(this, [{ add: classNames },speed,easing,callback]) : this._addClass(classNames);\r
4057         },\r
4059         _removeClass: $.fn.removeClass,\r
4060         removeClass: function(classNames,speed,easing,callback) {\r
4061                 return speed ? $.effects.animateClass.apply(this, [{ remove: classNames },speed,easing,callback]) : this._removeClass(classNames);\r
4062         },\r
4064         _toggleClass: $.fn.toggleClass,\r
4065         toggleClass: function(classNames, force, speed, easing, callback) {\r
4066                 if ( typeof force == "boolean" || force === undefined ) {\r
4067                         if ( !speed ) {\r
4068                                 // without speed parameter;\r
4069                                 return this._toggleClass(classNames, force);\r
4070                         } else {\r
4071                                 return $.effects.animateClass.apply(this, [(force?{add:classNames}:{remove:classNames}),speed,easing,callback]);\r
4072                         }\r
4073                 } else {\r
4074                         // without switch parameter;\r
4075                         return $.effects.animateClass.apply(this, [{ toggle: classNames },force,speed,easing]);\r
4076                 }\r
4077         },\r
4079         switchClass: function(remove,add,speed,easing,callback) {\r
4080                 return $.effects.animateClass.apply(this, [{ add: add, remove: remove },speed,easing,callback]);\r
4081         }\r
4082 });\r
4086 /******************************************************************************/\r
4087 /*********************************** EFFECTS **********************************/\r
4088 /******************************************************************************/\r
4090 $.extend($.effects, {\r
4091         version: "1.8",\r
4093         // Saves a set of properties in a data storage\r
4094         save: function(element, set) {\r
4095                 for(var i=0; i < set.length; i++) {\r
4096                         if(set[i] !== null) element.data("ec.storage."+set[i], element[0].style[set[i]]);\r
4097                 }\r
4098         },\r
4100         // Restores a set of previously saved properties from a data storage\r
4101         restore: function(element, set) {\r
4102                 for(var i=0; i < set.length; i++) {\r
4103                         if(set[i] !== null) element.css(set[i], element.data("ec.storage."+set[i]));\r
4104                 }\r
4105         },\r
4107         setMode: function(el, mode) {\r
4108                 if (mode == 'toggle') mode = el.is(':hidden') ? 'show' : 'hide'; // Set for toggle\r
4109                 return mode;\r
4110         },\r
4112         getBaseline: function(origin, original) { // Translates a [top,left] array into a baseline value\r
4113                 // this should be a little more flexible in the future to handle a string & hash\r
4114                 var y, x;\r
4115                 switch (origin[0]) {\r
4116                         case 'top': y = 0; break;\r
4117                         case 'middle': y = 0.5; break;\r
4118                         case 'bottom': y = 1; break;\r
4119                         default: y = origin[0] / original.height;\r
4120                 };\r
4121                 switch (origin[1]) {\r
4122                         case 'left': x = 0; break;\r
4123                         case 'center': x = 0.5; break;\r
4124                         case 'right': x = 1; break;\r
4125                         default: x = origin[1] / original.width;\r
4126                 };\r
4127                 return {x: x, y: y};\r
4128         },\r
4130         // Wraps the element around a wrapper that copies position properties\r
4131         createWrapper: function(element) {\r
4133                 // if the element is already wrapped, return it\r
4134                 if (element.parent().is('.ui-effects-wrapper')) {\r
4135                         return element.parent();\r
4136                 }\r
4138                 // wrap the element\r
4139                 var props = {\r
4140                                 width: element.outerWidth(true),\r
4141                                 height: element.outerHeight(true),\r
4142                                 'float': element.css('float')\r
4143                         },\r
4144                         wrapper = $('<div></div>')\r
4145                                 .addClass('ui-effects-wrapper')\r
4146                                 .css({\r
4147                                         fontSize: '100%',\r
4148                                         background: 'transparent',\r
4149                                         border: 'none',\r
4150                                         margin: 0,\r
4151                                         padding: 0\r
4152                                 });\r
4154                 element.wrap(wrapper);\r
4155                 wrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually loose the reference to the wrapped element\r
4157                 // transfer positioning properties to the wrapper\r
4158                 if (element.css('position') == 'static') {\r
4159                         wrapper.css({ position: 'relative' });\r
4160                         element.css({ position: 'relative' });\r
4161                 } else {\r
4162                         $.extend(props, {\r
4163                                 position: element.css('position'),\r
4164                                 zIndex: element.css('z-index')\r
4165                         });\r
4166                         $.each(['top', 'left', 'bottom', 'right'], function(i, pos) {\r
4167                                 props[pos] = element.css(pos);\r
4168                                 if (isNaN(parseInt(props[pos], 10))) {\r
4169                                         props[pos] = 'auto';\r
4170                                 }\r
4171                         });\r
4172                         element.css({position: 'relative', top: 0, left: 0 });\r
4173                 }\r
4175                 return wrapper.css(props).show();\r
4176         },\r
4178         removeWrapper: function(element) {\r
4179                 if (element.parent().is('.ui-effects-wrapper'))\r
4180                         return element.parent().replaceWith(element);\r
4181                 return element;\r
4182         },\r
4184         setTransition: function(element, list, factor, value) {\r
4185                 value = value || {};\r
4186                 $.each(list, function(i, x){\r
4187                         unit = element.cssUnit(x);\r
4188                         if (unit[0] > 0) value[x] = unit[0] * factor + unit[1];\r
4189                 });\r
4190                 return value;\r
4191         }\r
4192 });\r
4195 function _normalizeArguments(effect, options, speed, callback) {\r
4196         // shift params for method overloading\r
4197         if (typeof effect == 'object') {\r
4198                 callback = options;\r
4199                 speed = null;\r
4200                 options = effect;\r
4201                 effect = options.effect;\r
4202         }\r
4203         if ($.isFunction(options)) {\r
4204                 callback = options;\r
4205                 speed = null;\r
4206                 options = {};\r
4207         }\r
4208         if ($.isFunction(speed)) {\r
4209                 callback = speed;\r
4210                 speed = null;\r
4211         }\r
4212         if (typeof options == 'number' || $.fx.speeds[options]) {\r
4213                 callback = speed;\r
4214                 speed = options;\r
4215                 options = {};\r
4216         }\r
4218         options = options || {};\r
4220         speed = speed || options.duration;\r
4221         speed = $.fx.off ? 0 : typeof speed == 'number'\r
4222                 ? speed : $.fx.speeds[speed] || $.fx.speeds._default;\r
4224         callback = callback || options.complete;\r
4226         return [effect, options, speed, callback];\r
4229 $.fn.extend({\r
4230         effect: function(effect, options, speed, callback) {\r
4231                 var args = _normalizeArguments.apply(this, arguments),\r
4232                         // TODO: make effects takes actual parameters instead of a hash\r
4233                         args2 = {\r
4234                                 options: args[1],\r
4235                                 duration: args[2],\r
4236                                 callback: args[3]\r
4237                         },\r
4238                         effectMethod = $.effects[effect];\r
4239                 \r
4240                 return effectMethod && !$.fx.off ? effectMethod.call(this, args2) : this;\r
4241         },\r
4243         _show: $.fn.show,\r
4244         show: function(speed) {\r
4245                 if (!speed || typeof speed == 'number' || $.fx.speeds[speed]) {\r
4246                         return this._show.apply(this, arguments);\r
4247                 } else {\r
4248                         var args = _normalizeArguments.apply(this, arguments);\r
4249                         args[1].mode = 'show';\r
4250                         return this.effect.apply(this, args);\r
4251                 }\r
4252         },\r
4254         _hide: $.fn.hide,\r
4255         hide: function(speed) {\r
4256                 if (!speed || typeof speed == 'number' || $.fx.speeds[speed]) {\r
4257                         return this._hide.apply(this, arguments);\r
4258                 } else {\r
4259                         var args = _normalizeArguments.apply(this, arguments);\r
4260                         args[1].mode = 'hide';\r
4261                         return this.effect.apply(this, args);\r
4262                 }\r
4263         },\r
4265         // jQuery core overloads toggle and create _toggle\r
4266         __toggle: $.fn.toggle,\r
4267         toggle: function(speed) {\r
4268                 if (!speed || typeof speed == 'number' || $.fx.speeds[speed] ||\r
4269                         typeof speed == 'boolean' || $.isFunction(speed)) {\r
4270                         return this.__toggle.apply(this, arguments);\r
4271                 } else {\r
4272                         var args = _normalizeArguments.apply(this, arguments);\r
4273                         args[1].mode = 'toggle';\r
4274                         return this.effect.apply(this, args);\r
4275                 }\r
4276         },\r
4278         // helper functions\r
4279         cssUnit: function(key) {\r
4280                 var style = this.css(key), val = [];\r
4281                 $.each( ['em','px','%','pt'], function(i, unit){\r
4282                         if(style.indexOf(unit) > 0)\r
4283                                 val = [parseFloat(style), unit];\r
4284                 });\r
4285                 return val;\r
4286         }\r
4287 });\r
4291 /******************************************************************************/\r
4292 /*********************************** EASING ***********************************/\r
4293 /******************************************************************************/\r
4295 /*\r
4296  * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/\r
4297  *\r
4298  * Uses the built in easing capabilities added In jQuery 1.1\r
4299  * to offer multiple easing options\r
4300  *\r
4301  * TERMS OF USE - jQuery Easing\r
4302  *\r
4303  * Open source under the BSD License.\r
4304  *\r
4305  * Copyright 2008 George McGinley Smith\r
4306  * All rights reserved.\r
4307  *\r
4308  * Redistribution and use in source and binary forms, with or without modification,\r
4309  * are permitted provided that the following conditions are met:\r
4310  *\r
4311  * Redistributions of source code must retain the above copyright notice, this list of\r
4312  * conditions and the following disclaimer.\r
4313  * Redistributions in binary form must reproduce the above copyright notice, this list\r
4314  * of conditions and the following disclaimer in the documentation and/or other materials\r
4315  * provided with the distribution.\r
4316  *\r
4317  * Neither the name of the author nor the names of contributors may be used to endorse\r
4318  * or promote products derived from this software without specific prior written permission.\r
4319  *\r
4320  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY\r
4321  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
4322  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE\r
4323  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\r
4324  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE\r
4325  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED\r
4326  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\r
4327  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\r
4328  * OF THE POSSIBILITY OF SUCH DAMAGE.\r
4329  *\r
4330 */\r
4332 // t: current time, b: begInnIng value, c: change In value, d: duration\r
4333 $.easing.jswing = $.easing.swing;\r
4335 $.extend($.easing,\r
4337         def: 'easeOutQuad',\r
4338         swing: function (x, t, b, c, d) {\r
4339                 //alert($.easing.default);\r
4340                 return $.easing[$.easing.def](x, t, b, c, d);\r
4341         },\r
4342         easeInQuad: function (x, t, b, c, d) {\r
4343                 return c*(t/=d)*t + b;\r
4344         },\r
4345         easeOutQuad: function (x, t, b, c, d) {\r
4346                 return -c *(t/=d)*(t-2) + b;\r
4347         },\r
4348         easeInOutQuad: function (x, t, b, c, d) {\r
4349                 if ((t/=d/2) < 1) return c/2*t*t + b;\r
4350                 return -c/2 * ((--t)*(t-2) - 1) + b;\r
4351         },\r
4352         easeInCubic: function (x, t, b, c, d) {\r
4353                 return c*(t/=d)*t*t + b;\r
4354         },\r
4355         easeOutCubic: function (x, t, b, c, d) {\r
4356                 return c*((t=t/d-1)*t*t + 1) + b;\r
4357         },\r
4358         easeInOutCubic: function (x, t, b, c, d) {\r
4359                 if ((t/=d/2) < 1) return c/2*t*t*t + b;\r
4360                 return c/2*((t-=2)*t*t + 2) + b;\r
4361         },\r
4362         easeInQuart: function (x, t, b, c, d) {\r
4363                 return c*(t/=d)*t*t*t + b;\r
4364         },\r
4365         easeOutQuart: function (x, t, b, c, d) {\r
4366                 return -c * ((t=t/d-1)*t*t*t - 1) + b;\r
4367         },\r
4368         easeInOutQuart: function (x, t, b, c, d) {\r
4369                 if ((t/=d/2) < 1) return c/2*t*t*t*t + b;\r
4370                 return -c/2 * ((t-=2)*t*t*t - 2) + b;\r
4371         },\r
4372         easeInQuint: function (x, t, b, c, d) {\r
4373                 return c*(t/=d)*t*t*t*t + b;\r
4374         },\r
4375         easeOutQuint: function (x, t, b, c, d) {\r
4376                 return c*((t=t/d-1)*t*t*t*t + 1) + b;\r
4377         },\r
4378         easeInOutQuint: function (x, t, b, c, d) {\r
4379                 if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b;\r
4380                 return c/2*((t-=2)*t*t*t*t + 2) + b;\r
4381         },\r
4382         easeInSine: function (x, t, b, c, d) {\r
4383                 return -c * Math.cos(t/d * (Math.PI/2)) + c + b;\r
4384         },\r
4385         easeOutSine: function (x, t, b, c, d) {\r
4386                 return c * Math.sin(t/d * (Math.PI/2)) + b;\r
4387         },\r
4388         easeInOutSine: function (x, t, b, c, d) {\r
4389                 return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;\r
4390         },\r
4391         easeInExpo: function (x, t, b, c, d) {\r
4392                 return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;\r
4393         },\r
4394         easeOutExpo: function (x, t, b, c, d) {\r
4395                 return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;\r
4396         },\r
4397         easeInOutExpo: function (x, t, b, c, d) {\r
4398                 if (t==0) return b;\r
4399                 if (t==d) return b+c;\r
4400                 if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;\r
4401                 return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;\r
4402         },\r
4403         easeInCirc: function (x, t, b, c, d) {\r
4404                 return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;\r
4405         },\r
4406         easeOutCirc: function (x, t, b, c, d) {\r
4407                 return c * Math.sqrt(1 - (t=t/d-1)*t) + b;\r
4408         },\r
4409         easeInOutCirc: function (x, t, b, c, d) {\r
4410                 if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;\r
4411                 return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;\r
4412         },\r
4413         easeInElastic: function (x, t, b, c, d) {\r
4414                 var s=1.70158;var p=0;var a=c;\r
4415                 if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;\r
4416                 if (a < Math.abs(c)) { a=c; var s=p/4; }\r
4417                 else var s = p/(2*Math.PI) * Math.asin (c/a);\r
4418                 return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;\r
4419         },\r
4420         easeOutElastic: function (x, t, b, c, d) {\r
4421                 var s=1.70158;var p=0;var a=c;\r
4422                 if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;\r
4423                 if (a < Math.abs(c)) { a=c; var s=p/4; }\r
4424                 else var s = p/(2*Math.PI) * Math.asin (c/a);\r
4425                 return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;\r
4426         },\r
4427         easeInOutElastic: function (x, t, b, c, d) {\r
4428                 var s=1.70158;var p=0;var a=c;\r
4429                 if (t==0) return b;  if ((t/=d/2)==2) return b+c;  if (!p) p=d*(.3*1.5);\r
4430                 if (a < Math.abs(c)) { a=c; var s=p/4; }\r
4431                 else var s = p/(2*Math.PI) * Math.asin (c/a);\r
4432                 if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;\r
4433                 return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;\r
4434         },\r
4435         easeInBack: function (x, t, b, c, d, s) {\r
4436                 if (s == undefined) s = 1.70158;\r
4437                 return c*(t/=d)*t*((s+1)*t - s) + b;\r
4438         },\r
4439         easeOutBack: function (x, t, b, c, d, s) {\r
4440                 if (s == undefined) s = 1.70158;\r
4441                 return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;\r
4442         },\r
4443         easeInOutBack: function (x, t, b, c, d, s) {\r
4444                 if (s == undefined) s = 1.70158;\r
4445                 if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;\r
4446                 return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;\r
4447         },\r
4448         easeInBounce: function (x, t, b, c, d) {\r
4449                 return c - $.easing.easeOutBounce (x, d-t, 0, c, d) + b;\r
4450         },\r
4451         easeOutBounce: function (x, t, b, c, d) {\r
4452                 if ((t/=d) < (1/2.75)) {\r
4453                         return c*(7.5625*t*t) + b;\r
4454                 } else if (t < (2/2.75)) {\r
4455                         return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;\r
4456                 } else if (t < (2.5/2.75)) {\r
4457                         return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;\r
4458                 } else {\r
4459                         return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;\r
4460                 }\r
4461         },\r
4462         easeInOutBounce: function (x, t, b, c, d) {\r
4463                 if (t < d/2) return $.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b;\r
4464                 return $.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b;\r
4465         }\r
4466 });\r
4468 /*\r
4469  *\r
4470  * TERMS OF USE - EASING EQUATIONS\r
4471  *\r
4472  * Open source under the BSD License.\r
4473  *\r
4474  * Copyright 2001 Robert Penner\r
4475  * All rights reserved.\r
4476  *\r
4477  * Redistribution and use in source and binary forms, with or without modification,\r
4478  * are permitted provided that the following conditions are met:\r
4479  *\r
4480  * Redistributions of source code must retain the above copyright notice, this list of\r
4481  * conditions and the following disclaimer.\r
4482  * Redistributions in binary form must reproduce the above copyright notice, this list\r
4483  * of conditions and the following disclaimer in the documentation and/or other materials\r
4484  * provided with the distribution.\r
4485  *\r
4486  * Neither the name of the author nor the names of contributors may be used to endorse\r
4487  * or promote products derived from this software without specific prior written permission.\r
4488  *\r
4489  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY\r
4490  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
4491  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE\r
4492  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\r
4493  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE\r
4494  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED\r
4495  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\r
4496  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\r
4497  * OF THE POSSIBILITY OF SUCH DAMAGE.\r
4498  *\r
4499  */\r
4501 })(jQuery);\r
4502 /*\r
4503  * jQuery UI Effects Blind 1.8\r
4504  *\r
4505  * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)\r
4506  * Dual licensed under the MIT (MIT-LICENSE.txt)\r
4507  * and GPL (GPL-LICENSE.txt) licenses.\r
4508  *\r
4509  * http://docs.jquery.com/UI/Effects/Blind\r
4510  *\r
4511  * Depends:\r
4512  *      jquery.effects.core.js\r
4513  */\r
4514 (function($) {\r
4516 $.effects.blind = function(o) {\r
4518         return this.queue(function() {\r
4520                 // Create element\r
4521                 var el = $(this), props = ['position','top','left'];\r
4523                 // Set options\r
4524                 var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode\r
4525                 var direction = o.options.direction || 'vertical'; // Default direction\r
4527                 // Adjust\r
4528                 $.effects.save(el, props); el.show(); // Save & Show\r
4529                 var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper\r
4530                 var ref = (direction == 'vertical') ? 'height' : 'width';\r
4531                 var distance = (direction == 'vertical') ? wrapper.height() : wrapper.width();\r
4532                 if(mode == 'show') wrapper.css(ref, 0); // Shift\r
4534                 // Animation\r
4535                 var animation = {};\r
4536                 animation[ref] = mode == 'show' ? distance : 0;\r
4538                 // Animate\r
4539                 wrapper.animate(animation, o.duration, o.options.easing, function() {\r
4540                         if(mode == 'hide') el.hide(); // Hide\r
4541                         $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore\r
4542                         if(o.callback) o.callback.apply(el[0], arguments); // Callback\r
4543                         el.dequeue();\r
4544                 });\r
4546         });\r
4548 };\r
4550 })(jQuery);\r
4551 /*\r
4552  * jQuery UI Effects Bounce 1.8\r
4553  *\r
4554  * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)\r
4555  * Dual licensed under the MIT (MIT-LICENSE.txt)\r
4556  * and GPL (GPL-LICENSE.txt) licenses.\r
4557  *\r
4558  * http://docs.jquery.com/UI/Effects/Bounce\r
4559  *\r
4560  * Depends:\r
4561  *      jquery.effects.core.js\r
4562  */\r
4563 (function($) {\r
4565 $.effects.bounce = function(o) {\r
4567         return this.queue(function() {\r
4569                 // Create element\r
4570                 var el = $(this), props = ['position','top','left'];\r
4572                 // Set options\r
4573                 var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode\r
4574                 var direction = o.options.direction || 'up'; // Default direction\r
4575                 var distance = o.options.distance || 20; // Default distance\r
4576                 var times = o.options.times || 5; // Default # of times\r
4577                 var speed = o.duration || 250; // Default speed per bounce\r
4578                 if (/show|hide/.test(mode)) props.push('opacity'); // Avoid touching opacity to prevent clearType and PNG issues in IE\r
4580                 // Adjust\r
4581                 $.effects.save(el, props); el.show(); // Save & Show\r
4582                 $.effects.createWrapper(el); // Create Wrapper\r
4583                 var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';\r
4584                 var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';\r
4585                 var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) / 3 : el.outerWidth({margin:true}) / 3);\r
4586                 if (mode == 'show') el.css('opacity', 0).css(ref, motion == 'pos' ? -distance : distance); // Shift\r
4587                 if (mode == 'hide') distance = distance / (times * 2);\r
4588                 if (mode != 'hide') times--;\r
4590                 // Animate\r
4591                 if (mode == 'show') { // Show Bounce\r
4592                         var animation = {opacity: 1};\r
4593                         animation[ref] = (motion == 'pos' ? '+=' : '-=') + distance;\r
4594                         el.animate(animation, speed / 2, o.options.easing);\r
4595                         distance = distance / 2;\r
4596                         times--;\r
4597                 };\r
4598                 for (var i = 0; i < times; i++) { // Bounces\r
4599                         var animation1 = {}, animation2 = {};\r
4600                         animation1[ref] = (motion == 'pos' ? '-=' : '+=') + distance;\r
4601                         animation2[ref] = (motion == 'pos' ? '+=' : '-=') + distance;\r
4602                         el.animate(animation1, speed / 2, o.options.easing).animate(animation2, speed / 2, o.options.easing);\r
4603                         distance = (mode == 'hide') ? distance * 2 : distance / 2;\r
4604                 };\r
4605                 if (mode == 'hide') { // Last Bounce\r
4606                         var animation = {opacity: 0};\r
4607                         animation[ref] = (motion == 'pos' ? '-=' : '+=')  + distance;\r
4608                         el.animate(animation, speed / 2, o.options.easing, function(){\r
4609                                 el.hide(); // Hide\r
4610                                 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore\r
4611                                 if(o.callback) o.callback.apply(this, arguments); // Callback\r
4612                         });\r
4613                 } else {\r
4614                         var animation1 = {}, animation2 = {};\r
4615                         animation1[ref] = (motion == 'pos' ? '-=' : '+=') + distance;\r
4616                         animation2[ref] = (motion == 'pos' ? '+=' : '-=') + distance;\r
4617                         el.animate(animation1, speed / 2, o.options.easing).animate(animation2, speed / 2, o.options.easing, function(){\r
4618                                 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore\r
4619                                 if(o.callback) o.callback.apply(this, arguments); // Callback\r
4620                         });\r
4621                 };\r
4622                 el.queue('fx', function() { el.dequeue(); });\r
4623                 el.dequeue();\r
4624         });\r
4626 };\r
4628 })(jQuery);\r
4629 /*\r
4630  * jQuery UI Effects Clip 1.8\r
4631  *\r
4632  * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)\r
4633  * Dual licensed under the MIT (MIT-LICENSE.txt)\r
4634  * and GPL (GPL-LICENSE.txt) licenses.\r
4635  *\r
4636  * http://docs.jquery.com/UI/Effects/Clip\r
4637  *\r
4638  * Depends:\r
4639  *      jquery.effects.core.js\r
4640  */\r
4641 (function($) {\r
4643 $.effects.clip = function(o) {\r
4645         return this.queue(function() {\r
4647                 // Create element\r
4648                 var el = $(this), props = ['position','top','left','height','width'];\r
4650                 // Set options\r
4651                 var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode\r
4652                 var direction = o.options.direction || 'vertical'; // Default direction\r
4654                 // Adjust\r
4655                 $.effects.save(el, props); el.show(); // Save & Show\r
4656                 var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper\r
4657                 var animate = el[0].tagName == 'IMG' ? wrapper : el;\r
4658                 var ref = {\r
4659                         size: (direction == 'vertical') ? 'height' : 'width',\r
4660                         position: (direction == 'vertical') ? 'top' : 'left'\r
4661                 };\r
4662                 var distance = (direction == 'vertical') ? animate.height() : animate.width();\r
4663                 if(mode == 'show') { animate.css(ref.size, 0); animate.css(ref.position, distance / 2); } // Shift\r
4665                 // Animation\r
4666                 var animation = {};\r
4667                 animation[ref.size] = mode == 'show' ? distance : 0;\r
4668                 animation[ref.position] = mode == 'show' ? 0 : distance / 2;\r
4670                 // Animate\r
4671                 animate.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {\r
4672                         if(mode == 'hide') el.hide(); // Hide\r
4673                         $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore\r
4674                         if(o.callback) o.callback.apply(el[0], arguments); // Callback\r
4675                         el.dequeue();\r
4676                 }});\r
4678         });\r
4680 };\r
4682 })(jQuery);\r
4683 /*\r
4684  * jQuery UI Effects Drop 1.8\r
4685  *\r
4686  * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)\r
4687  * Dual licensed under the MIT (MIT-LICENSE.txt)\r
4688  * and GPL (GPL-LICENSE.txt) licenses.\r
4689  *\r
4690  * http://docs.jquery.com/UI/Effects/Drop\r
4691  *\r
4692  * Depends:\r
4693  *      jquery.effects.core.js\r
4694  */\r
4695 (function($) {\r
4697 $.effects.drop = function(o) {\r
4699         return this.queue(function() {\r
4701                 // Create element\r
4702                 var el = $(this), props = ['position','top','left','opacity'];\r
4704                 // Set options\r
4705                 var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode\r
4706                 var direction = o.options.direction || 'left'; // Default Direction\r
4708                 // Adjust\r
4709                 $.effects.save(el, props); el.show(); // Save & Show\r
4710                 $.effects.createWrapper(el); // Create Wrapper\r
4711                 var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';\r
4712                 var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';\r
4713                 var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) / 2 : el.outerWidth({margin:true}) / 2);\r
4714                 if (mode == 'show') el.css('opacity', 0).css(ref, motion == 'pos' ? -distance : distance); // Shift\r
4716                 // Animation\r
4717                 var animation = {opacity: mode == 'show' ? 1 : 0};\r
4718                 animation[ref] = (mode == 'show' ? (motion == 'pos' ? '+=' : '-=') : (motion == 'pos' ? '-=' : '+=')) + distance;\r
4720                 // Animate\r
4721                 el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {\r
4722                         if(mode == 'hide') el.hide(); // Hide\r
4723                         $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore\r
4724                         if(o.callback) o.callback.apply(this, arguments); // Callback\r
4725                         el.dequeue();\r
4726                 }});\r
4728         });\r
4730 };\r
4732 })(jQuery);\r
4733 /*\r
4734  * jQuery UI Effects Explode 1.8\r
4735  *\r
4736  * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)\r
4737  * Dual licensed under the MIT (MIT-LICENSE.txt)\r
4738  * and GPL (GPL-LICENSE.txt) licenses.\r
4739  *\r
4740  * http://docs.jquery.com/UI/Effects/Explode\r
4741  *\r
4742  * Depends:\r
4743  *      jquery.effects.core.js\r
4744  */\r
4745 (function($) {\r
4747 $.effects.explode = function(o) {\r
4749         return this.queue(function() {\r
4751         var rows = o.options.pieces ? Math.round(Math.sqrt(o.options.pieces)) : 3;\r
4752         var cells = o.options.pieces ? Math.round(Math.sqrt(o.options.pieces)) : 3;\r
4754         o.options.mode = o.options.mode == 'toggle' ? ($(this).is(':visible') ? 'hide' : 'show') : o.options.mode;\r
4755         var el = $(this).show().css('visibility', 'hidden');\r
4756         var offset = el.offset();\r
4758         //Substract the margins - not fixing the problem yet.\r
4759         offset.top -= parseInt(el.css("marginTop"),10) || 0;\r
4760         offset.left -= parseInt(el.css("marginLeft"),10) || 0;\r
4762         var width = el.outerWidth(true);\r
4763         var height = el.outerHeight(true);\r
4765         for(var i=0;i<rows;i++) { // =\r
4766                 for(var j=0;j<cells;j++) { // ||\r
4767                         el\r
4768                                 .clone()\r
4769                                 .appendTo('body')\r
4770                                 .wrap('<div></div>')\r
4771                                 .css({\r
4772                                         position: 'absolute',\r
4773                                         visibility: 'visible',\r
4774                                         left: -j*(width/cells),\r
4775                                         top: -i*(height/rows)\r
4776                                 })\r
4777                                 .parent()\r
4778                                 .addClass('ui-effects-explode')\r
4779                                 .css({\r
4780                                         position: 'absolute',\r
4781                                         overflow: 'hidden',\r
4782                                         width: width/cells,\r
4783                                         height: height/rows,\r
4784                                         left: offset.left + j*(width/cells) + (o.options.mode == 'show' ? (j-Math.floor(cells/2))*(width/cells) : 0),\r
4785                                         top: offset.top + i*(height/rows) + (o.options.mode == 'show' ? (i-Math.floor(rows/2))*(height/rows) : 0),\r
4786                                         opacity: o.options.mode == 'show' ? 0 : 1\r
4787                                 }).animate({\r
4788                                         left: offset.left + j*(width/cells) + (o.options.mode == 'show' ? 0 : (j-Math.floor(cells/2))*(width/cells)),\r
4789                                         top: offset.top + i*(height/rows) + (o.options.mode == 'show' ? 0 : (i-Math.floor(rows/2))*(height/rows)),\r
4790                                         opacity: o.options.mode == 'show' ? 1 : 0\r
4791                                 }, o.duration || 500);\r
4792                 }\r
4793         }\r
4795         // Set a timeout, to call the callback approx. when the other animations have finished\r
4796         setTimeout(function() {\r
4798                 o.options.mode == 'show' ? el.css({ visibility: 'visible' }) : el.css({ visibility: 'visible' }).hide();\r
4799                                 if(o.callback) o.callback.apply(el[0]); // Callback\r
4800                                 el.dequeue();\r
4802                                 $('div.ui-effects-explode').remove();\r
4804         }, o.duration || 500);\r
4807         });\r
4809 };\r
4811 })(jQuery);\r
4812 /*\r
4813  * jQuery UI Effects Fade 1.8\r
4814  *\r
4815  * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)\r
4816  * Dual licensed under the MIT (MIT-LICENSE.txt)\r
4817  * and GPL (GPL-LICENSE.txt) licenses.\r
4818  *\r
4819  * http://docs.jquery.com/UI/Effects/Fade\r
4820  *\r
4821  * Depends:\r
4822  *      jquery.effects.core.js\r
4823  */\r
4824 (function($) {\r
4826 $.effects.fade = function(o) {\r
4827         return this.queue(function() {\r
4828                 var elem = $(this),\r
4829                         mode = $.effects.setMode(elem, o.options.mode || 'hide');\r
4831                 elem.animate({ opacity: mode }, {\r
4832                         queue: false,\r
4833                         duration: o.duration,\r
4834                         easing: o.options.easing,\r
4835                         complete: function() {\r
4836                                 (o.callback && o.callback.apply(this, arguments));\r
4837                                 elem.dequeue();\r
4838                         }\r
4839                 });\r
4840         });\r
4841 };\r
4843 })(jQuery);\r
4844 /*\r
4845  * jQuery UI Effects Fold 1.8\r
4846  *\r
4847  * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)\r
4848  * Dual licensed under the MIT (MIT-LICENSE.txt)\r
4849  * and GPL (GPL-LICENSE.txt) licenses.\r
4850  *\r
4851  * http://docs.jquery.com/UI/Effects/Fold\r
4852  *\r
4853  * Depends:\r
4854  *      jquery.effects.core.js\r
4855  */\r
4856 (function($) {\r
4858 $.effects.fold = function(o) {\r
4860         return this.queue(function() {\r
4862                 // Create element\r
4863                 var el = $(this), props = ['position','top','left'];\r
4865                 // Set options\r
4866                 var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode\r
4867                 var size = o.options.size || 15; // Default fold size\r
4868                 var horizFirst = !(!o.options.horizFirst); // Ensure a boolean value\r
4869                 var duration = o.duration ? o.duration / 2 : $.fx.speeds._default / 2;\r
4871                 // Adjust\r
4872                 $.effects.save(el, props); el.show(); // Save & Show\r
4873                 var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper\r
4874                 var widthFirst = ((mode == 'show') != horizFirst);\r
4875                 var ref = widthFirst ? ['width', 'height'] : ['height', 'width'];\r
4876                 var distance = widthFirst ? [wrapper.width(), wrapper.height()] : [wrapper.height(), wrapper.width()];\r
4877                 var percent = /([0-9]+)%/.exec(size);\r
4878                 if(percent) size = parseInt(percent[1],10) / 100 * distance[mode == 'hide' ? 0 : 1];\r
4879                 if(mode == 'show') wrapper.css(horizFirst ? {height: 0, width: size} : {height: size, width: 0}); // Shift\r
4881                 // Animation\r
4882                 var animation1 = {}, animation2 = {};\r
4883                 animation1[ref[0]] = mode == 'show' ? distance[0] : size;\r
4884                 animation2[ref[1]] = mode == 'show' ? distance[1] : 0;\r
4886                 // Animate\r
4887                 wrapper.animate(animation1, duration, o.options.easing)\r
4888                 .animate(animation2, duration, o.options.easing, function() {\r
4889                         if(mode == 'hide') el.hide(); // Hide\r
4890                         $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore\r
4891                         if(o.callback) o.callback.apply(el[0], arguments); // Callback\r
4892                         el.dequeue();\r
4893                 });\r
4895         });\r
4897 };\r
4899 })(jQuery);\r
4900 /*\r
4901  * jQuery UI Effects Highlight 1.8\r
4902  *\r
4903  * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)\r
4904  * Dual licensed under the MIT (MIT-LICENSE.txt)\r
4905  * and GPL (GPL-LICENSE.txt) licenses.\r
4906  *\r
4907  * http://docs.jquery.com/UI/Effects/Highlight\r
4908  *\r
4909  * Depends:\r
4910  *      jquery.effects.core.js\r
4911  */\r
4912 (function($) {\r
4914 $.effects.highlight = function(o) {\r
4915         return this.queue(function() {\r
4916                 var elem = $(this),\r
4917                         props = ['backgroundImage', 'backgroundColor', 'opacity'],\r
4918                         mode = $.effects.setMode(elem, o.options.mode || 'show'),\r
4919                         animation = {\r
4920                                 backgroundColor: elem.css('backgroundColor')\r
4921                         };\r
4923                 if (mode == 'hide') {\r
4924                         animation.opacity = 0;\r
4925                 }\r
4927                 $.effects.save(elem, props);\r
4928                 elem\r
4929                         .show()\r
4930                         .css({\r
4931                                 backgroundImage: 'none',\r
4932                                 backgroundColor: o.options.color || '#ffff99'\r
4933                         })\r
4934                         .animate(animation, {\r
4935                                 queue: false,\r
4936                                 duration: o.duration,\r
4937                                 easing: o.options.easing,\r
4938                                 complete: function() {\r
4939                                         (mode == 'hide' && elem.hide());\r
4940                                         $.effects.restore(elem, props);\r
4941                                         (mode == 'show' && !$.support.opacity && this.style.removeAttribute('filter'));\r
4942                                         (o.callback && o.callback.apply(this, arguments));\r
4943                                         elem.dequeue();\r
4944                                 }\r
4945                         });\r
4946         });\r
4947 };\r
4949 })(jQuery);\r
4950 /*\r
4951  * jQuery UI Effects Pulsate 1.8\r
4952  *\r
4953  * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)\r
4954  * Dual licensed under the MIT (MIT-LICENSE.txt)\r
4955  * and GPL (GPL-LICENSE.txt) licenses.\r
4956  *\r
4957  * http://docs.jquery.com/UI/Effects/Pulsate\r
4958  *\r
4959  * Depends:\r
4960  *      jquery.effects.core.js\r
4961  */\r
4962 (function($) {\r
4964 $.effects.pulsate = function(o) {\r
4965         return this.queue(function() {\r
4966                 var elem = $(this),\r
4967                         mode = $.effects.setMode(elem, o.options.mode || 'show');\r
4968                         times = ((o.options.times || 5) * 2) - 1;\r
4969                         duration = o.duration ? o.duration / 2 : $.fx.speeds._default / 2,\r
4970                         isVisible = elem.is(':visible'),\r
4971                         animateTo = 0;\r
4973                 if (!isVisible) {\r
4974                         elem.css('opacity', 0).show();\r
4975                         animateTo = 1;\r
4976                 }\r
4978                 if ((mode == 'hide' && isVisible) || (mode == 'show' && !isVisible)) {\r
4979                         times--;\r
4980                 }\r
4982                 for (var i = 0; i < times; i++) {\r
4983                         elem.animate({ opacity: animateTo }, duration, o.options.easing);\r
4984                         animateTo = (animateTo + 1) % 2;\r
4985                 }\r
4987                 elem.animate({ opacity: animateTo }, duration, o.options.easing, function() {\r
4988                         if (animateTo == 0) {\r
4989                                 elem.hide();\r
4990                         }\r
4991                         (o.callback && o.callback.apply(this, arguments));\r
4992                 });\r
4994                 elem\r
4995                         .queue('fx', function() { elem.dequeue(); })\r
4996                         .dequeue();\r
4997         });\r
4998 };\r
5000 })(jQuery);\r
5001 /*\r
5002  * jQuery UI Effects Scale 1.8\r
5003  *\r
5004  * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)\r
5005  * Dual licensed under the MIT (MIT-LICENSE.txt)\r
5006  * and GPL (GPL-LICENSE.txt) licenses.\r
5007  *\r
5008  * http://docs.jquery.com/UI/Effects/Scale\r
5009  *\r
5010  * Depends:\r
5011  *      jquery.effects.core.js\r
5012  */\r
5013 (function($) {\r
5015 $.effects.puff = function(o) {\r
5016         return this.queue(function() {\r
5017                 var elem = $(this),\r
5018                         mode = $.effects.setMode(elem, o.options.mode || 'hide'),\r
5019                         percent = parseInt(o.options.percent, 10) || 150,\r
5020                         factor = percent / 100,\r
5021                         original = { height: elem.height(), width: elem.width() };\r
5023                 $.extend(o.options, {\r
5024                         fade: true,\r
5025                         mode: mode,\r
5026                         percent: mode == 'hide' ? percent : 100,\r
5027                         from: mode == 'hide'\r
5028                                 ? original\r
5029                                 : {\r
5030                                         height: original.height * factor,\r
5031                                         width: original.width * factor\r
5032                                 }\r
5033                 });\r
5035                 elem.effect('scale', o.options, o.duration, o.callback);\r
5036                 elem.dequeue();\r
5037         });\r
5038 };\r
5040 $.effects.scale = function(o) {\r
5042         return this.queue(function() {\r
5044                 // Create element\r
5045                 var el = $(this);\r
5047                 // Set options\r
5048                 var options = $.extend(true, {}, o.options);\r
5049                 var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode\r
5050                 var percent = parseInt(o.options.percent,10) || (parseInt(o.options.percent,10) == 0 ? 0 : (mode == 'hide' ? 0 : 100)); // Set default scaling percent\r
5051                 var direction = o.options.direction || 'both'; // Set default axis\r
5052                 var origin = o.options.origin; // The origin of the scaling\r
5053                 if (mode != 'effect') { // Set default origin and restore for show/hide\r
5054                         options.origin = origin || ['middle','center'];\r
5055                         options.restore = true;\r
5056                 }\r
5057                 var original = {height: el.height(), width: el.width()}; // Save original\r
5058                 el.from = o.options.from || (mode == 'show' ? {height: 0, width: 0} : original); // Default from state\r
5060                 // Adjust\r
5061                 var factor = { // Set scaling factor\r
5062                         y: direction != 'horizontal' ? (percent / 100) : 1,\r
5063                         x: direction != 'vertical' ? (percent / 100) : 1\r
5064                 };\r
5065                 el.to = {height: original.height * factor.y, width: original.width * factor.x}; // Set to state\r
5067                 if (o.options.fade) { // Fade option to support puff\r
5068                         if (mode == 'show') {el.from.opacity = 0; el.to.opacity = 1;};\r
5069                         if (mode == 'hide') {el.from.opacity = 1; el.to.opacity = 0;};\r
5070                 };\r
5072                 // Animation\r
5073                 options.from = el.from; options.to = el.to; options.mode = mode;\r
5075                 // Animate\r
5076                 el.effect('size', options, o.duration, o.callback);\r
5077                 el.dequeue();\r
5078         });\r
5080 };\r
5082 $.effects.size = function(o) {\r
5084         return this.queue(function() {\r
5086                 // Create element\r
5087                 var el = $(this), props = ['position','top','left','width','height','overflow','opacity'];\r
5088                 var props1 = ['position','top','left','overflow','opacity']; // Always restore\r
5089                 var props2 = ['width','height','overflow']; // Copy for children\r
5090                 var cProps = ['fontSize'];\r
5091                 var vProps = ['borderTopWidth', 'borderBottomWidth', 'paddingTop', 'paddingBottom'];\r
5092                 var hProps = ['borderLeftWidth', 'borderRightWidth', 'paddingLeft', 'paddingRight'];\r
5094                 // Set options\r
5095                 var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode\r
5096                 var restore = o.options.restore || false; // Default restore\r
5097                 var scale = o.options.scale || 'both'; // Default scale mode\r
5098                 var origin = o.options.origin; // The origin of the sizing\r
5099                 var original = {height: el.height(), width: el.width()}; // Save original\r
5100                 el.from = o.options.from || original; // Default from state\r
5101                 el.to = o.options.to || original; // Default to state\r
5102                 // Adjust\r
5103                 if (origin) { // Calculate baseline shifts\r
5104                         var baseline = $.effects.getBaseline(origin, original);\r
5105                         el.from.top = (original.height - el.from.height) * baseline.y;\r
5106                         el.from.left = (original.width - el.from.width) * baseline.x;\r
5107                         el.to.top = (original.height - el.to.height) * baseline.y;\r
5108                         el.to.left = (original.width - el.to.width) * baseline.x;\r
5109                 };\r
5110                 var factor = { // Set scaling factor\r
5111                         from: {y: el.from.height / original.height, x: el.from.width / original.width},\r
5112                         to: {y: el.to.height / original.height, x: el.to.width / original.width}\r
5113                 };\r
5114                 if (scale == 'box' || scale == 'both') { // Scale the css box\r
5115                         if (factor.from.y != factor.to.y) { // Vertical props scaling\r
5116                                 props = props.concat(vProps);\r
5117                                 el.from = $.effects.setTransition(el, vProps, factor.from.y, el.from);\r
5118                                 el.to = $.effects.setTransition(el, vProps, factor.to.y, el.to);\r
5119                         };\r
5120                         if (factor.from.x != factor.to.x) { // Horizontal props scaling\r
5121                                 props = props.concat(hProps);\r
5122                                 el.from = $.effects.setTransition(el, hProps, factor.from.x, el.from);\r
5123                                 el.to = $.effects.setTransition(el, hProps, factor.to.x, el.to);\r
5124                         };\r
5125                 };\r
5126                 if (scale == 'content' || scale == 'both') { // Scale the content\r
5127                         if (factor.from.y != factor.to.y) { // Vertical props scaling\r
5128                                 props = props.concat(cProps);\r
5129                                 el.from = $.effects.setTransition(el, cProps, factor.from.y, el.from);\r
5130                                 el.to = $.effects.setTransition(el, cProps, factor.to.y, el.to);\r
5131                         };\r
5132                 };\r
5133                 $.effects.save(el, restore ? props : props1); el.show(); // Save & Show\r
5134                 $.effects.createWrapper(el); // Create Wrapper\r
5135                 el.css('overflow','hidden').css(el.from); // Shift\r
5137                 // Animate\r
5138                 if (scale == 'content' || scale == 'both') { // Scale the children\r
5139                         vProps = vProps.concat(['marginTop','marginBottom']).concat(cProps); // Add margins/font-size\r
5140                         hProps = hProps.concat(['marginLeft','marginRight']); // Add margins\r
5141                         props2 = props.concat(vProps).concat(hProps); // Concat\r
5142                         el.find("*[width]").each(function(){\r
5143                                 child = $(this);\r
5144                                 if (restore) $.effects.save(child, props2);\r
5145                                 var c_original = {height: child.height(), width: child.width()}; // Save original\r
5146                                 child.from = {height: c_original.height * factor.from.y, width: c_original.width * factor.from.x};\r
5147                                 child.to = {height: c_original.height * factor.to.y, width: c_original.width * factor.to.x};\r
5148                                 if (factor.from.y != factor.to.y) { // Vertical props scaling\r
5149                                         child.from = $.effects.setTransition(child, vProps, factor.from.y, child.from);\r
5150                                         child.to = $.effects.setTransition(child, vProps, factor.to.y, child.to);\r
5151                                 };\r
5152                                 if (factor.from.x != factor.to.x) { // Horizontal props scaling\r
5153                                         child.from = $.effects.setTransition(child, hProps, factor.from.x, child.from);\r
5154                                         child.to = $.effects.setTransition(child, hProps, factor.to.x, child.to);\r
5155                                 };\r
5156                                 child.css(child.from); // Shift children\r
5157                                 child.animate(child.to, o.duration, o.options.easing, function(){\r
5158                                         if (restore) $.effects.restore(child, props2); // Restore children\r
5159                                 }); // Animate children\r
5160                         });\r
5161                 };\r
5163                 // Animate\r
5164                 el.animate(el.to, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {\r
5165                         if (el.to.opacity === 0) {\r
5166                                 el.css('opacity', el.from.opacity);\r
5167                         }\r
5168                         if(mode == 'hide') el.hide(); // Hide\r
5169                         $.effects.restore(el, restore ? props : props1); $.effects.removeWrapper(el); // Restore\r
5170                         if(o.callback) o.callback.apply(this, arguments); // Callback\r
5171                         el.dequeue();\r
5172                 }});\r
5174         });\r
5176 };\r
5178 })(jQuery);\r
5179 /*\r
5180  * jQuery UI Effects Shake 1.8\r
5181  *\r
5182  * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)\r
5183  * Dual licensed under the MIT (MIT-LICENSE.txt)\r
5184  * and GPL (GPL-LICENSE.txt) licenses.\r
5185  *\r
5186  * http://docs.jquery.com/UI/Effects/Shake\r
5187  *\r
5188  * Depends:\r
5189  *      jquery.effects.core.js\r
5190  */\r
5191 (function($) {\r
5193 $.effects.shake = function(o) {\r
5195         return this.queue(function() {\r
5197                 // Create element\r
5198                 var el = $(this), props = ['position','top','left'];\r
5200                 // Set options\r
5201                 var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode\r
5202                 var direction = o.options.direction || 'left'; // Default direction\r
5203                 var distance = o.options.distance || 20; // Default distance\r
5204                 var times = o.options.times || 3; // Default # of times\r
5205                 var speed = o.duration || o.options.duration || 140; // Default speed per shake\r
5207                 // Adjust\r
5208                 $.effects.save(el, props); el.show(); // Save & Show\r
5209                 $.effects.createWrapper(el); // Create Wrapper\r
5210                 var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';\r
5211                 var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';\r
5213                 // Animation\r
5214                 var animation = {}, animation1 = {}, animation2 = {};\r
5215                 animation[ref] = (motion == 'pos' ? '-=' : '+=')  + distance;\r
5216                 animation1[ref] = (motion == 'pos' ? '+=' : '-=')  + distance * 2;\r
5217                 animation2[ref] = (motion == 'pos' ? '-=' : '+=')  + distance * 2;\r
5219                 // Animate\r
5220                 el.animate(animation, speed, o.options.easing);\r
5221                 for (var i = 1; i < times; i++) { // Shakes\r
5222                         el.animate(animation1, speed, o.options.easing).animate(animation2, speed, o.options.easing);\r
5223                 };\r
5224                 el.animate(animation1, speed, o.options.easing).\r
5225                 animate(animation, speed / 2, o.options.easing, function(){ // Last shake\r
5226                         $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore\r
5227                         if(o.callback) o.callback.apply(this, arguments); // Callback\r
5228                 });\r
5229                 el.queue('fx', function() { el.dequeue(); });\r
5230                 el.dequeue();\r
5231         });\r
5233 };\r
5235 })(jQuery);\r
5236 /*\r
5237  * jQuery UI Effects Slide 1.8\r
5238  *\r
5239  * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)\r
5240  * Dual licensed under the MIT (MIT-LICENSE.txt)\r
5241  * and GPL (GPL-LICENSE.txt) licenses.\r
5242  *\r
5243  * http://docs.jquery.com/UI/Effects/Slide\r
5244  *\r
5245  * Depends:\r
5246  *      jquery.effects.core.js\r
5247  */\r
5248 (function($) {\r
5250 $.effects.slide = function(o) {\r
5252         return this.queue(function() {\r
5254                 // Create element\r
5255                 var el = $(this), props = ['position','top','left'];\r
5257                 // Set options\r
5258                 var mode = $.effects.setMode(el, o.options.mode || 'show'); // Set Mode\r
5259                 var direction = o.options.direction || 'left'; // Default Direction\r
5261                 // Adjust\r
5262                 $.effects.save(el, props); el.show(); // Save & Show\r
5263                 $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper\r
5264                 var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';\r
5265                 var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';\r
5266                 var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) : el.outerWidth({margin:true}));\r
5267                 if (mode == 'show') el.css(ref, motion == 'pos' ? -distance : distance); // Shift\r
5269                 // Animation\r
5270                 var animation = {};\r
5271                 animation[ref] = (mode == 'show' ? (motion == 'pos' ? '+=' : '-=') : (motion == 'pos' ? '-=' : '+=')) + distance;\r
5273                 // Animate\r
5274                 el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {\r
5275                         if(mode == 'hide') el.hide(); // Hide\r
5276                         $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore\r
5277                         if(o.callback) o.callback.apply(this, arguments); // Callback\r
5278                         el.dequeue();\r
5279                 }});\r
5281         });\r
5283 };\r
5285 })(jQuery);\r
5286 /*\r
5287  * jQuery UI Effects Transfer 1.8\r
5288  *\r
5289  * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)\r
5290  * Dual licensed under the MIT (MIT-LICENSE.txt)\r
5291  * and GPL (GPL-LICENSE.txt) licenses.\r
5292  *\r
5293  * http://docs.jquery.com/UI/Effects/Transfer\r
5294  *\r
5295  * Depends:\r
5296  *      jquery.effects.core.js\r
5297  */\r
5298 (function($) {\r
5300 $.effects.transfer = function(o) {\r
5301         return this.queue(function() {\r
5302                 var elem = $(this),\r
5303                         target = $(o.options.to),\r
5304                         endPosition = target.offset(),\r
5305                         animation = {\r
5306                                 top: endPosition.top,\r
5307                                 left: endPosition.left,\r
5308                                 height: target.innerHeight(),\r
5309                                 width: target.innerWidth()\r
5310                         },\r
5311                         startPosition = elem.offset(),\r
5312                         transfer = $('<div class="ui-effects-transfer"></div>')\r
5313                                 .appendTo(document.body)\r
5314                                 .addClass(o.options.className)\r
5315                                 .css({\r
5316                                         top: startPosition.top,\r
5317                                         left: startPosition.left,\r
5318                                         height: elem.innerHeight(),\r
5319                                         width: elem.innerWidth(),\r
5320                                         position: 'absolute'\r
5321                                 })\r
5322                                 .animate(animation, o.duration, o.options.easing, function() {\r
5323                                         transfer.remove();\r
5324                                         (o.callback && o.callback.apply(elem[0], arguments));\r
5325                                         elem.dequeue();\r
5326                                 });\r
5327         });\r
5328 };\r
5330 })(jQuery);\r
5331 /*\r
5332  * jQuery UI Accordion 1.8\r
5333  *\r
5334  * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)\r
5335  * Dual licensed under the MIT (MIT-LICENSE.txt)\r
5336  * and GPL (GPL-LICENSE.txt) licenses.\r
5337  *\r
5338  * http://docs.jquery.com/UI/Accordion\r
5339  *\r
5340  * Depends:\r
5341  *      jquery.ui.core.js\r
5342  *      jquery.ui.widget.js\r
5343  */\r
5344 (function($) {\r
5346 $.widget("ui.accordion", {\r
5347         options: {\r
5348                 active: 0,\r
5349                 animated: 'slide',\r
5350                 autoHeight: true,\r
5351                 clearStyle: false,\r
5352                 collapsible: false,\r
5353                 event: "click",\r
5354                 fillSpace: false,\r
5355                 header: "> li > :first-child,> :not(li):even",\r
5356                 icons: {\r
5357                         header: "ui-icon-triangle-1-e",\r
5358                         headerSelected: "ui-icon-triangle-1-s"\r
5359                 },\r
5360                 navigation: false,\r
5361                 navigationFilter: function() {\r
5362                         return this.href.toLowerCase() == location.href.toLowerCase();\r
5363                 }\r
5364         },\r
5365         _create: function() {\r
5367                 var o = this.options, self = this;\r
5368                 this.running = 0;\r
5370                 this.element.addClass("ui-accordion ui-widget ui-helper-reset");\r
5371                 \r
5372                 // in lack of child-selectors in CSS we need to mark top-LIs in a UL-accordion for some IE-fix\r
5373                 if (this.element[0].nodeName == "UL") {\r
5374                         this.element.children("li").addClass("ui-accordion-li-fix");\r
5375                 }\r
5377                 this.headers = this.element.find(o.header).addClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all")\r
5378                         .bind("mouseenter.accordion", function(){ $(this).addClass('ui-state-hover'); })\r
5379                         .bind("mouseleave.accordion", function(){ $(this).removeClass('ui-state-hover'); })\r
5380                         .bind("focus.accordion", function(){ $(this).addClass('ui-state-focus'); })\r
5381                         .bind("blur.accordion", function(){ $(this).removeClass('ui-state-focus'); });\r
5383                 this.headers\r
5384                         .next()\r
5385                                 .addClass("ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom");\r
5387                 if ( o.navigation ) {\r
5388                         var current = this.element.find("a").filter(o.navigationFilter);\r
5389                         if ( current.length ) {\r
5390                                 var header = current.closest(".ui-accordion-header");\r
5391                                 if ( header.length ) {\r
5392                                         // anchor within header\r
5393                                         this.active = header;\r
5394                                 } else {\r
5395                                         // anchor within content\r
5396                                         this.active = current.closest(".ui-accordion-content").prev();\r
5397                                 }\r
5398                         }\r
5399                 }\r
5401                 this.active = this._findActive(this.active || o.active).toggleClass("ui-state-default").toggleClass("ui-state-active").toggleClass("ui-corner-all").toggleClass("ui-corner-top");\r
5402                 this.active.next().addClass('ui-accordion-content-active');\r
5404                 //Append icon elements\r
5405                 this._createIcons();\r
5407                 // IE7-/Win - Extra vertical space in lists fixed\r
5408                 if ($.browser.msie) {\r
5409                         this.element.find('a').css('zoom', '1');\r
5410                 }\r
5412                 this.resize();\r
5414                 //ARIA\r
5415                 this.element.attr('role','tablist');\r
5417                 this.headers\r
5418                         .attr('role','tab')\r
5419                         .bind('keydown', function(event) { return self._keydown(event); })\r
5420                         .next()\r
5421                         .attr('role','tabpanel');\r
5423                 this.headers\r
5424                         .not(this.active || "")\r
5425                         .attr('aria-expanded','false')\r
5426                         .attr("tabIndex", "-1")\r
5427                         .next()\r
5428                         .hide();\r
5430                 // make sure at least one header is in the tab order\r
5431                 if (!this.active.length) {\r
5432                         this.headers.eq(0).attr('tabIndex','0');\r
5433                 } else {\r
5434                         this.active\r
5435                                 .attr('aria-expanded','true')\r
5436                                 .attr('tabIndex', '0');\r
5437                 }\r
5439                 // only need links in taborder for Safari\r
5440                 if (!$.browser.safari)\r
5441                         this.headers.find('a').attr('tabIndex','-1');\r
5443                 if (o.event) {\r
5444                         this.headers.bind((o.event) + ".accordion", function(event) {\r
5445                                 self._clickHandler.call(self, event, this);\r
5446                                 event.preventDefault();\r
5447                         });\r
5448                 }\r
5450         },\r
5451         \r
5452         _createIcons: function() {\r
5453                 var o = this.options;\r
5454                 if (o.icons) {\r
5455                         $("<span/>").addClass("ui-icon " + o.icons.header).prependTo(this.headers);\r
5456                         this.active.find(".ui-icon").toggleClass(o.icons.header).toggleClass(o.icons.headerSelected);\r
5457                         this.element.addClass("ui-accordion-icons");\r
5458                 }\r
5459         },\r
5460         \r
5461         _destroyIcons: function() {\r
5462                 this.headers.children(".ui-icon").remove();\r
5463                 this.element.removeClass("ui-accordion-icons");\r
5464         },\r
5466         destroy: function() {\r
5467                 var o = this.options;\r
5469                 this.element\r
5470                         .removeClass("ui-accordion ui-widget ui-helper-reset")\r
5471                         .removeAttr("role")\r
5472                         .unbind('.accordion')\r
5473                         .removeData('accordion');\r
5475                 this.headers\r
5476                         .unbind(".accordion")\r
5477                         .removeClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-corner-top")\r
5478                         .removeAttr("role").removeAttr("aria-expanded").removeAttr("tabindex");\r
5480                 this.headers.find("a").removeAttr("tabindex");\r
5481                 this._destroyIcons();\r
5482                 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");\r
5483                 if (o.autoHeight || o.fillHeight) {\r
5484                         contents.css("height", "");\r
5485                 }\r
5487                 return this;\r
5488         },\r
5489         \r
5490         _setOption: function(key, value) {\r
5491                 $.Widget.prototype._setOption.apply(this, arguments);\r
5492                         \r
5493                 if (key == "active") {\r
5494                         this.activate(value);\r
5495                 }\r
5496                 if (key == "icons") {\r
5497                         this._destroyIcons();\r
5498                         if (value) {\r
5499                                 this._createIcons();\r
5500                         }\r
5501                 }\r
5502                 \r
5503         },\r
5505         _keydown: function(event) {\r
5507                 var o = this.options, keyCode = $.ui.keyCode;\r
5509                 if (o.disabled || event.altKey || event.ctrlKey)\r
5510                         return;\r
5512                 var length = this.headers.length;\r
5513                 var currentIndex = this.headers.index(event.target);\r
5514                 var toFocus = false;\r
5516                 switch(event.keyCode) {\r
5517                         case keyCode.RIGHT:\r
5518                         case keyCode.DOWN:\r
5519                                 toFocus = this.headers[(currentIndex + 1) % length];\r
5520                                 break;\r
5521                         case keyCode.LEFT:\r
5522                         case keyCode.UP:\r
5523                                 toFocus = this.headers[(currentIndex - 1 + length) % length];\r
5524                                 break;\r
5525                         case keyCode.SPACE:\r
5526                         case keyCode.ENTER:\r
5527                                 this._clickHandler({ target: event.target }, event.target);\r
5528                                 event.preventDefault();\r
5529                 }\r
5531                 if (toFocus) {\r
5532                         $(event.target).attr('tabIndex','-1');\r
5533                         $(toFocus).attr('tabIndex','0');\r
5534                         toFocus.focus();\r
5535                         return false;\r
5536                 }\r
5538                 return true;\r
5540         },\r
5542         resize: function() {\r
5544                 var o = this.options, maxHeight;\r
5546                 if (o.fillSpace) {\r
5547                         \r
5548                         if($.browser.msie) { var defOverflow = this.element.parent().css('overflow'); this.element.parent().css('overflow', 'hidden'); }\r
5549                         maxHeight = this.element.parent().height();\r
5550                         if($.browser.msie) { this.element.parent().css('overflow', defOverflow); }\r
5551         \r
5552                         this.headers.each(function() {\r
5553                                 maxHeight -= $(this).outerHeight(true);\r
5554                         });\r
5556                         this.headers.next().each(function() {\r
5557                    $(this).height(Math.max(0, maxHeight - $(this).innerHeight() + $(this).height()));\r
5558                         }).css('overflow', 'auto');\r
5560                 } else if ( o.autoHeight ) {\r
5561                         maxHeight = 0;\r
5562                         this.headers.next().each(function() {\r
5563                                 maxHeight = Math.max(maxHeight, $(this).height());\r
5564                         }).height(maxHeight);\r
5565                 }\r
5567                 return this;\r
5568         },\r
5570         activate: function(index) {\r
5571                 // TODO this gets called on init, changing the option without an explicit call for that\r
5572                 this.options.active = index;\r
5573                 // call clickHandler with custom event\r
5574                 var active = this._findActive(index)[0];\r
5575                 this._clickHandler({ target: active }, active);\r
5577                 return this;\r
5578         },\r
5580         _findActive: function(selector) {\r
5581                 return selector\r
5582                         ? typeof selector == "number"\r
5583                                 ? this.headers.filter(":eq(" + selector + ")")\r
5584                                 : this.headers.not(this.headers.not(selector))\r
5585                         : selector === false\r
5586                                 ? $([])\r
5587                                 : this.headers.filter(":eq(0)");\r
5588         },\r
5590         // TODO isn't event.target enough? why the seperate target argument?\r
5591         _clickHandler: function(event, target) {\r
5593                 var o = this.options;\r
5594                 if (o.disabled)\r
5595                         return;\r
5597                 // called only when using activate(false) to close all parts programmatically\r
5598                 if (!event.target) {\r
5599                         if (!o.collapsible)\r
5600                                 return;\r
5601                         this.active.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all")\r
5602                                 .find(".ui-icon").removeClass(o.icons.headerSelected).addClass(o.icons.header);\r
5603                         this.active.next().addClass('ui-accordion-content-active');\r
5604                         var toHide = this.active.next(),\r
5605                                 data = {\r
5606                                         options: o,\r
5607                                         newHeader: $([]),\r
5608                                         oldHeader: o.active,\r
5609                                         newContent: $([]),\r
5610                                         oldContent: toHide\r
5611                                 },\r
5612                                 toShow = (this.active = $([]));\r
5613                         this._toggle(toShow, toHide, data);\r
5614                         return;\r
5615                 }\r
5617                 // get the click target\r
5618                 var clicked = $(event.currentTarget || target);\r
5619                 var clickedIsActive = clicked[0] == this.active[0];\r
5620                 \r
5621                 // TODO the option is changed, is that correct?\r
5622                 // TODO if it is correct, shouldn't that happen after determining that the click is valid?\r
5623                 o.active = o.collapsible && clickedIsActive ? false : $('.ui-accordion-header', this.element).index(clicked);\r
5625                 // if animations are still active, or the active header is the target, ignore click\r
5626                 if (this.running || (!o.collapsible && clickedIsActive)) {\r
5627                         return;\r
5628                 }\r
5630                 // switch classes\r
5631                 this.active.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all")\r
5632                         .find(".ui-icon").removeClass(o.icons.headerSelected).addClass(o.icons.header);\r
5633                 if (!clickedIsActive) {\r
5634                         clicked.removeClass("ui-state-default ui-corner-all").addClass("ui-state-active ui-corner-top")\r
5635                                 .find(".ui-icon").removeClass(o.icons.header).addClass(o.icons.headerSelected);\r
5636                         clicked.next().addClass('ui-accordion-content-active');\r
5637                 }\r
5639                 // find elements to show and hide\r
5640                 var toShow = clicked.next(),\r
5641                         toHide = this.active.next(),\r
5642                         data = {\r
5643                                 options: o,\r
5644                                 newHeader: clickedIsActive && o.collapsible ? $([]) : clicked,\r
5645                                 oldHeader: this.active,\r
5646                                 newContent: clickedIsActive && o.collapsible ? $([]) : toShow,\r
5647                                 oldContent: toHide\r
5648                         },\r
5649                         down = this.headers.index( this.active[0] ) > this.headers.index( clicked[0] );\r
5651                 this.active = clickedIsActive ? $([]) : clicked;\r
5652                 this._toggle(toShow, toHide, data, clickedIsActive, down);\r
5654                 return;\r
5656         },\r
5658         _toggle: function(toShow, toHide, data, clickedIsActive, down) {\r
5660                 var o = this.options, self = this;\r
5662                 this.toShow = toShow;\r
5663                 this.toHide = toHide;\r
5664                 this.data = data;\r
5666                 var complete = function() { if(!self) return; return self._completed.apply(self, arguments); };\r
5668                 // trigger changestart event\r
5669                 this._trigger("changestart", null, this.data);\r
5671                 // count elements to animate\r
5672                 this.running = toHide.size() === 0 ? toShow.size() : toHide.size();\r
5674                 if (o.animated) {\r
5676                         var animOptions = {};\r
5678                         if ( o.collapsible && clickedIsActive ) {\r
5679                                 animOptions = {\r
5680                                         toShow: $([]),\r
5681                                         toHide: toHide,\r
5682                                         complete: complete,\r
5683                                         down: down,\r
5684                                         autoHeight: o.autoHeight || o.fillSpace\r
5685                                 };\r
5686                         } else {\r
5687                                 animOptions = {\r
5688                                         toShow: toShow,\r
5689                                         toHide: toHide,\r
5690                                         complete: complete,\r
5691                                         down: down,\r
5692                                         autoHeight: o.autoHeight || o.fillSpace\r
5693                                 };\r
5694                         }\r
5696                         if (!o.proxied) {\r
5697                                 o.proxied = o.animated;\r
5698                         }\r
5700                         if (!o.proxiedDuration) {\r
5701                                 o.proxiedDuration = o.duration;\r
5702                         }\r
5704                         o.animated = $.isFunction(o.proxied) ?\r
5705                                 o.proxied(animOptions) : o.proxied;\r
5707                         o.duration = $.isFunction(o.proxiedDuration) ?\r
5708                                 o.proxiedDuration(animOptions) : o.proxiedDuration;\r
5710                         var animations = $.ui.accordion.animations,\r
5711                                 duration = o.duration,\r
5712                                 easing = o.animated;\r
5714                         if (easing && !animations[easing] && !$.easing[easing]) {\r
5715                                 easing = 'slide';\r
5716                         }\r
5717                         if (!animations[easing]) {\r
5718                                 animations[easing] = function(options) {\r
5719                                         this.slide(options, {\r
5720                                                 easing: easing,\r
5721                                                 duration: duration || 700\r
5722                                         });\r
5723                                 };\r
5724                         }\r
5726                         animations[easing](animOptions);\r
5728                 } else {\r
5730                         if (o.collapsible && clickedIsActive) {\r
5731                                 toShow.toggle();\r
5732                         } else {\r
5733                                 toHide.hide();\r
5734                                 toShow.show();\r
5735                         }\r
5737                         complete(true);\r
5739                 }\r
5741                 // TODO assert that the blur and focus triggers are really necessary, remove otherwise\r
5742                 toHide.prev().attr('aria-expanded','false').attr("tabIndex", "-1").blur();\r
5743                 toShow.prev().attr('aria-expanded','true').attr("tabIndex", "0").focus();\r
5745         },\r
5747         _completed: function(cancel) {\r
5749                 var o = this.options;\r
5751                 this.running = cancel ? 0 : --this.running;\r
5752                 if (this.running) return;\r
5754                 if (o.clearStyle) {\r
5755                         this.toShow.add(this.toHide).css({\r
5756                                 height: "",\r
5757                                 overflow: ""\r
5758                         });\r
5759                 }\r
5760                 \r
5761                 // other classes are removed before the animation; this one needs to stay until completed\r
5762                 this.toHide.removeClass("ui-accordion-content-active");\r
5764                 this._trigger('change', null, this.data);\r
5765         }\r
5767 });\r
5770 $.extend($.ui.accordion, {\r
5771         version: "1.8",\r
5772         animations: {\r
5773                 slide: function(options, additions) {\r
5774                         options = $.extend({\r
5775                                 easing: "swing",\r
5776                                 duration: 300\r
5777                         }, options, additions);\r
5778                         if ( !options.toHide.size() ) {\r
5779                                 options.toShow.animate({height: "show"}, options);\r
5780                                 return;\r
5781                         }\r
5782                         if ( !options.toShow.size() ) {\r
5783                                 options.toHide.animate({height: "hide"}, options);\r
5784                                 return;\r
5785                         }\r
5786                         var overflow = options.toShow.css('overflow'),\r
5787                                 percentDone = 0,\r
5788                                 showProps = {},\r
5789                                 hideProps = {},\r
5790                                 fxAttrs = [ "height", "paddingTop", "paddingBottom" ],\r
5791                                 originalWidth;\r
5792                         // fix width before calculating height of hidden element\r
5793                         var s = options.toShow;\r
5794                         originalWidth = s[0].style.width;\r
5795                         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) );\r
5796                         \r
5797                         $.each(fxAttrs, function(i, prop) {\r
5798                                 hideProps[prop] = 'hide';\r
5799                                 \r
5800                                 var parts = ('' + $.css(options.toShow[0], prop)).match(/^([\d+-.]+)(.*)$/);\r
5801                                 showProps[prop] = {\r
5802                                         value: parts[1],\r
5803                                         unit: parts[2] || 'px'\r
5804                                 };\r
5805                         });\r
5806                         options.toShow.css({ height: 0, overflow: 'hidden' }).show();\r
5807                         options.toHide.filter(":hidden").each(options.complete).end().filter(":visible").animate(hideProps,{\r
5808                                 step: function(now, settings) {\r
5809                                         // only calculate the percent when animating height\r
5810                                         // IE gets very inconsistent results when animating elements\r
5811                                         // with small values, which is common for padding\r
5812                                         if (settings.prop == 'height') {\r
5813                                                 percentDone = ( settings.end - settings.start === 0 ) ? 0 :\r
5814                                                         (settings.now - settings.start) / (settings.end - settings.start);\r
5815                                         }\r
5816                                         \r
5817                                         options.toShow[0].style[settings.prop] =\r
5818                                                 (percentDone * showProps[settings.prop].value) + showProps[settings.prop].unit;\r
5819                                 },\r
5820                                 duration: options.duration,\r
5821                                 easing: options.easing,\r
5822                                 complete: function() {\r
5823                                         if ( !options.autoHeight ) {\r
5824                                                 options.toShow.css("height", "");\r
5825                                         }\r
5826                                         options.toShow.css("width", originalWidth);\r
5827                                         options.toShow.css({overflow: overflow});\r
5828                                         options.complete();\r
5829                                 }\r
5830                         });\r
5831                 },\r
5832                 bounceslide: function(options) {\r
5833                         this.slide(options, {\r
5834                                 easing: options.down ? "easeOutBounce" : "swing",\r
5835                                 duration: options.down ? 1000 : 200\r
5836                         });\r
5837                 }\r
5838         }\r
5839 });\r
5841 })(jQuery);\r
5842 /*\r
5843  * jQuery UI Autocomplete 1.8\r
5844  *\r
5845  * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)\r
5846  * Dual licensed under the MIT (MIT-LICENSE.txt)\r
5847  * and GPL (GPL-LICENSE.txt) licenses.\r
5848  *\r
5849  * http://docs.jquery.com/UI/Autocomplete\r
5850  *\r
5851  * Depends:\r
5852  *      jquery.ui.core.js\r
5853  *      jquery.ui.widget.js\r
5854  *      jquery.ui.position.js\r
5855  */\r
5856 (function( $ ) {\r
5858 $.widget( "ui.autocomplete", {\r
5859         options: {\r
5860                 minLength: 1,\r
5861                 delay: 300\r
5862         },\r
5863         _create: function() {\r
5864                 var self = this,\r
5865                         doc = this.element[ 0 ].ownerDocument;\r
5866                 this.element\r
5867                         .addClass( "ui-autocomplete-input" )\r
5868                         .attr( "autocomplete", "off" )\r
5869                         // TODO verify these actually work as intended\r
5870                         .attr({\r
5871                                 role: "textbox",\r
5872                                 "aria-autocomplete": "list",\r
5873                                 "aria-haspopup": "true"\r
5874                         })\r
5875                         .bind( "keydown.autocomplete", function( event ) {\r
5876                                 var keyCode = $.ui.keyCode;\r
5877                                 switch( event.keyCode ) {\r
5878                                 case keyCode.PAGE_UP:\r
5879                                         self._move( "previousPage", event );\r
5880                                         break;\r
5881                                 case keyCode.PAGE_DOWN:\r
5882                                         self._move( "nextPage", event );\r
5883                                         break;\r
5884                                 case keyCode.UP:\r
5885                                         self._move( "previous", event );\r
5886                                         // prevent moving cursor to beginning of text field in some browsers\r
5887                                         event.preventDefault();\r
5888                                         break;\r
5889                                 case keyCode.DOWN:\r
5890                                         self._move( "next", event );\r
5891                                         // prevent moving cursor to end of text field in some browsers\r
5892                                         event.preventDefault();\r
5893                                         break;\r
5894                                 case keyCode.ENTER:\r
5895                                         // when menu is open or has focus\r
5896                                         if ( self.menu.active ) {\r
5897                                                 event.preventDefault();\r
5898                                         }\r
5899                                         //passthrough - ENTER and TAB both select the current element\r
5900                                 case keyCode.TAB:\r
5901                                         if ( !self.menu.active ) {\r
5902                                                 return;\r
5903                                         }\r
5904                                         self.menu.select();\r
5905                                         break;\r
5906                                 case keyCode.ESCAPE:\r
5907                                         self.element.val( self.term );\r
5908                                         self.close( event );\r
5909                                         break;\r
5910                                 case keyCode.SHIFT:\r
5911                                 case keyCode.CONTROL:\r
5912                                 case 18:\r
5913                                         // ignore metakeys (shift, ctrl, alt)\r
5914                                         break;\r
5915                                 default:\r
5916                                         // keypress is triggered before the input value is changed\r
5917                                         clearTimeout( self.searching );\r
5918                                         self.searching = setTimeout(function() {\r
5919                                                 self.search( null, event );\r
5920                                         }, self.options.delay );\r
5921                                         break;\r
5922                                 }\r
5923                         })\r
5924                         .bind( "focus.autocomplete", function() {\r
5925                                 self.previous = self.element.val();\r
5926                         })\r
5927                         .bind( "blur.autocomplete", function( event ) {\r
5928                                 clearTimeout( self.searching );\r
5929                                 // clicks on the menu (or a button to trigger a search) will cause a blur event\r
5930                                 // TODO try to implement this without a timeout, see clearTimeout in search()\r
5931                                 self.closing = setTimeout(function() {\r
5932                                         self.close( event );\r
5933                                 }, 150 );\r
5934                         });\r
5935                 this._initSource();\r
5936                 this.response = function() {\r
5937                         return self._response.apply( self, arguments );\r
5938                 };\r
5939                 this.menu = $( "<ul></ul>" )\r
5940                         .addClass( "ui-autocomplete" )\r
5941                         .appendTo( "body", doc )\r
5942                         .menu({\r
5943                                 focus: function( event, ui ) {\r
5944                                         var item = ui.item.data( "item.autocomplete" );\r
5945                                         if ( false !== self._trigger( "focus", null, { item: item } ) ) {\r
5946                                                 // use value to match what will end up in the input\r
5947                                                 self.element.val( item.value );\r
5948                                         }\r
5949                                 },\r
5950                                 selected: function( event, ui ) {\r
5951                                         var item = ui.item.data( "item.autocomplete" );\r
5952                                         if ( false !== self._trigger( "select", event, { item: item } ) ) {\r
5953                                                 self.element.val( item.value );\r
5954                                         }\r
5955                                         self.close( event );\r
5956                                         self.previous = self.element.val();\r
5957                                         // only trigger when focus was lost (click on menu)\r
5958                                         if ( self.element[0] !== doc.activeElement ) {\r
5959                                                 self.element.focus();\r
5960                                         }\r
5961                                 },\r
5962                                 blur: function( event, ui ) {\r
5963                                         if ( self.menu.element.is(":visible") ) {\r
5964                                                 self.element.val( self.term );\r
5965                                         }\r
5966                                 }\r
5967                         })\r
5968                         .zIndex( this.element.zIndex() + 1 )\r
5969                         // workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781\r
5970                         .css({ top: 0, left: 0 })\r
5971                         .hide()\r
5972                         .data( "menu" );\r
5973                 if ( $.fn.bgiframe ) {\r
5974                          this.menu.element.bgiframe();\r
5975                 }\r
5976         },\r
5978         destroy: function() {\r
5979                 this.element\r
5980                         .removeClass( "ui-autocomplete-input ui-widget ui-widget-content" )\r
5981                         .removeAttr( "autocomplete" )\r
5982                         .removeAttr( "role" )\r
5983                         .removeAttr( "aria-autocomplete" )\r
5984                         .removeAttr( "aria-haspopup" );\r
5985                 this.menu.element.remove();\r
5986                 $.Widget.prototype.destroy.call( this );\r
5987         },\r
5989         _setOption: function( key ) {\r
5990                 $.Widget.prototype._setOption.apply( this, arguments );\r
5991                 if ( key === "source" ) {\r
5992                         this._initSource();\r
5993                 }\r
5994         },\r
5996         _initSource: function() {\r
5997                 var array,\r
5998                         url;\r
5999                 if ( $.isArray(this.options.source) ) {\r
6000                         array = this.options.source;\r
6001                         this.source = function( request, response ) {\r
6002                                 // escape regex characters\r
6003                                 var matcher = new RegExp( $.ui.autocomplete.escapeRegex(request.term), "i" );\r
6004                                 response( $.grep( array, function(value) {\r
6005                                         return matcher.test( value.label || value.value || value );\r
6006                                 }) );\r
6007                         };\r
6008                 } else if ( typeof this.options.source === "string" ) {\r
6009                         url = this.options.source;\r
6010                         this.source = function( request, response ) {\r
6011                                 $.getJSON( url, request, response );\r
6012                         };\r
6013                 } else {\r
6014                         this.source = this.options.source;\r
6015                 }\r
6016         },\r
6018         search: function( value, event ) {\r
6019                 value = value != null ? value : this.element.val();\r
6020                 if ( value.length < this.options.minLength ) {\r
6021                         return this.close( event );\r
6022                 }\r
6024                 clearTimeout( this.closing );\r
6025                 if ( this._trigger("search") === false ) {\r
6026                         return;\r
6027                 }\r
6029                 return this._search( value );\r
6030         },\r
6032         _search: function( value ) {\r
6033                 this.term = this.element\r
6034                         .addClass( "ui-autocomplete-loading" )\r
6035                         // always save the actual value, not the one passed as an argument\r
6036                         .val();\r
6038                 this.source( { term: value }, this.response );\r
6039         },\r
6041         _response: function( content ) {\r
6042                 if ( content.length ) {\r
6043                         content = this._normalize( content );\r
6044                         this._suggest( content );\r
6045                         this._trigger( "open" );\r
6046                 } else {\r
6047                         this.close();\r
6048                 }\r
6049                 this.element.removeClass( "ui-autocomplete-loading" );\r
6050         },\r
6052         close: function( event ) {\r
6053                 clearTimeout( this.closing );\r
6054                 if ( this.menu.element.is(":visible") ) {\r
6055                         this._trigger( "close", event );\r
6056                         this.menu.element.hide();\r
6057                         this.menu.deactivate();\r
6058                 }\r
6059                 if ( this.previous !== this.element.val() ) {\r
6060                         this._trigger( "change", event );\r
6061                 }\r
6062         },\r
6064         _normalize: function( items ) {\r
6065                 // assume all items have the right format when the first item is complete\r
6066                 if ( items.length && items[0].label && items[0].value ) {\r
6067                         return items;\r
6068                 }\r
6069                 return $.map( items, function(item) {\r
6070                         if ( typeof item === "string" ) {\r
6071                                 return {\r
6072                                         label: item,\r
6073                                         value: item\r
6074                                 };\r
6075                         }\r
6076                         return $.extend({\r
6077                                 label: item.label || item.value,\r
6078                                 value: item.value || item.label\r
6079                         }, item );\r
6080                 });\r
6081         },\r
6083         _suggest: function( items ) {\r
6084                 var ul = this.menu.element\r
6085                                 .empty()\r
6086                                 .zIndex( this.element.zIndex() + 1 ),\r
6087                         menuWidth,\r
6088                         textWidth;\r
6089                 this._renderMenu( ul, items );\r
6090                 // TODO refresh should check if the active item is still in the dom, removing the need for a manual deactivate\r
6091                 this.menu.deactivate();\r
6092                 this.menu.refresh();\r
6093                 this.menu.element.show().position({\r
6094                         my: "left top",\r
6095                         at: "left bottom",\r
6096                         of: this.element,\r
6097                         collision: "none"\r
6098                 });\r
6100                 menuWidth = ul.width( "" ).width();\r
6101                 textWidth = this.element.width();\r
6102                 ul.width( Math.max( menuWidth, textWidth ) );\r
6103         },\r
6104         \r
6105         _renderMenu: function( ul, items ) {\r
6106                 var self = this;\r
6107                 $.each( items, function( index, item ) {\r
6108                         self._renderItem( ul, item );\r
6109                 });\r
6110         },\r
6112         _renderItem: function( ul, item) {\r
6113                 return $( "<li></li>" )\r
6114                         .data( "item.autocomplete", item )\r
6115                         .append( "<a>" + item.label + "</a>" )\r
6116                         .appendTo( ul );\r
6117         },\r
6119         _move: function( direction, event ) {\r
6120                 if ( !this.menu.element.is(":visible") ) {\r
6121                         this.search( null, event );\r
6122                         return;\r
6123                 }\r
6124                 if ( this.menu.first() && /^previous/.test(direction) ||\r
6125                                 this.menu.last() && /^next/.test(direction) ) {\r
6126                         this.element.val( this.term );\r
6127                         this.menu.deactivate();\r
6128                         return;\r
6129                 }\r
6130                 this.menu[ direction ]();\r
6131         },\r
6133         widget: function() {\r
6134                 return this.menu.element;\r
6135         }\r
6136 });\r
6138 $.extend( $.ui.autocomplete, {\r
6139         escapeRegex: function( value ) {\r
6140                 return value.replace( /([\^\$\(\)\[\]\{\}\*\.\+\?\|\\])/gi, "\\$1" );\r
6141         }\r
6142 });\r
6144 }( jQuery ));\r
6146 /*\r
6147  * jQuery UI Menu (not officially released)\r
6148  * \r
6149  * This widget isn't yet finished and the API is subject to change. We plan to finish\r
6150  * it for the next release. You're welcome to give it a try anyway and give us feedback,\r
6151  * as long as you're okay with migrating your code later on. We can help with that, too.\r
6152  *\r
6153  * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)\r
6154  * Dual licensed under the MIT (MIT-LICENSE.txt)\r
6155  * and GPL (GPL-LICENSE.txt) licenses.\r
6156  *\r
6157  * http://docs.jquery.com/UI/Menu\r
6158  *\r
6159  * Depends:\r
6160  *      jquery.ui.core.js\r
6161  *  jquery.ui.widget.js\r
6162  */\r
6163 (function($) {\r
6165 $.widget("ui.menu", {\r
6166         _create: function() {\r
6167                 var self = this;\r
6168                 this.element\r
6169                         .addClass("ui-menu ui-widget ui-widget-content ui-corner-all")\r
6170                         .attr({\r
6171                                 role: "listbox",\r
6172                                 "aria-activedescendant": "ui-active-menuitem"\r
6173                         })\r
6174                         .click(function(e) {\r
6175                                 // temporary\r
6176                                 e.preventDefault();\r
6177                                 self.select();\r
6178                         });\r
6179                 this.refresh();\r
6180         },\r
6181         \r
6182         refresh: function() {\r
6183                 var self = this;\r
6185                 // don't refresh list items that are already adapted\r
6186                 var items = this.element.children("li:not(.ui-menu-item):has(a)")\r
6187                         .addClass("ui-menu-item")\r
6188                         .attr("role", "menuitem");\r
6189                 \r
6190                 items.children("a")\r
6191                         .addClass("ui-corner-all")\r
6192                         .attr("tabindex", -1)\r
6193                         // mouseenter doesn't work with event delegation\r
6194                         .mouseenter(function() {\r
6195                                 self.activate($(this).parent());\r
6196                         })\r
6197                         .mouseleave(function() {\r
6198                                 self.deactivate();\r
6199                         });\r
6200         },\r
6202         activate: function(item) {\r
6203                 this.deactivate();\r
6204                 if (this.hasScroll()) {\r
6205                         var offset = item.offset().top - this.element.offset().top,\r
6206                                 scroll = this.element.attr("scrollTop"),\r
6207                                 elementHeight = this.element.height();\r
6208                         if (offset < 0) {\r
6209                                 this.element.attr("scrollTop", scroll + offset);\r
6210                         } else if (offset > elementHeight) {\r
6211                                 this.element.attr("scrollTop", scroll + offset - elementHeight + item.height());\r
6212                         }\r
6213                 }\r
6214                 this.active = item.eq(0)\r
6215                         .children("a")\r
6216                                 .addClass("ui-state-hover")\r
6217                                 .attr("id", "ui-active-menuitem")\r
6218                         .end();\r
6219                 this._trigger("focus", null, { item: item });\r
6220         },\r
6222         deactivate: function() {\r
6223                 if (!this.active) { return; }\r
6225                 this.active.children("a")\r
6226                         .removeClass("ui-state-hover")\r
6227                         .removeAttr("id");\r
6228                 this._trigger("blur");\r
6229                 this.active = null;\r
6230         },\r
6232         next: function() {\r
6233                 this.move("next", "li:first");\r
6234         },\r
6236         previous: function() {\r
6237                 this.move("prev", "li:last");\r
6238         },\r
6240         first: function() {\r
6241                 return this.active && !this.active.prev().length;\r
6242         },\r
6244         last: function() {\r
6245                 return this.active && !this.active.next().length;\r
6246         },\r
6248         move: function(direction, edge) {\r
6249                 if (!this.active) {\r
6250                         this.activate(this.element.children(edge));\r
6251                         return;\r
6252                 }\r
6253                 var next = this.active[direction]();\r
6254                 if (next.length) {\r
6255                         this.activate(next);\r
6256                 } else {\r
6257                         this.activate(this.element.children(edge));\r
6258                 }\r
6259         },\r
6261         // TODO merge with previousPage\r
6262         nextPage: function() {\r
6263                 if (this.hasScroll()) {\r
6264                         // TODO merge with no-scroll-else\r
6265                         if (!this.active || this.last()) {\r
6266                                 this.activate(this.element.children(":first"));\r
6267                                 return;\r
6268                         }\r
6269                         var base = this.active.offset().top,\r
6270                                 height = this.element.height(),\r
6271                                 result = this.element.children("li").filter(function() {\r
6272                                         var close = $(this).offset().top - base - height + $(this).height();\r
6273                                         // TODO improve approximation\r
6274                                         return close < 10 && close > -10;\r
6275                                 });\r
6277                         // TODO try to catch this earlier when scrollTop indicates the last page anyway\r
6278                         if (!result.length) {\r
6279                                 result = this.element.children(":last");\r
6280                         }\r
6281                         this.activate(result);\r
6282                 } else {\r
6283                         this.activate(this.element.children(!this.active || this.last() ? ":first" : ":last"));\r
6284                 }\r
6285         },\r
6287         // TODO merge with nextPage\r
6288         previousPage: function() {\r
6289                 if (this.hasScroll()) {\r
6290                         // TODO merge with no-scroll-else\r
6291                         if (!this.active || this.first()) {\r
6292                                 this.activate(this.element.children(":last"));\r
6293                                 return;\r
6294                         }\r
6296                         var base = this.active.offset().top,\r
6297                                 height = this.element.height();\r
6298                                 result = this.element.children("li").filter(function() {\r
6299                                         var close = $(this).offset().top - base + height - $(this).height();\r
6300                                         // TODO improve approximation\r
6301                                         return close < 10 && close > -10;\r
6302                                 });\r
6304                         // TODO try to catch this earlier when scrollTop indicates the last page anyway\r
6305                         if (!result.length) {\r
6306                                 result = this.element.children(":first");\r
6307                         }\r
6308                         this.activate(result);\r
6309                 } else {\r
6310                         this.activate(this.element.children(!this.active || this.first() ? ":last" : ":first"));\r
6311                 }\r
6312         },\r
6314         hasScroll: function() {\r
6315                 return this.element.height() < this.element.attr("scrollHeight");\r
6316         },\r
6318         select: function() {\r
6319                 this._trigger("selected", null, { item: this.active });\r
6320         }\r
6321 });\r
6323 }(jQuery));\r
6324 /*\r
6325  * jQuery UI Button 1.8\r
6326  *\r
6327  * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)\r
6328  * Dual licensed under the MIT (MIT-LICENSE.txt)\r
6329  * and GPL (GPL-LICENSE.txt) licenses.\r
6330  *\r
6331  * http://docs.jquery.com/UI/Button\r
6332  *\r
6333  * Depends:\r
6334  *      jquery.ui.core.js\r
6335  *      jquery.ui.widget.js\r
6336  */\r
6337 (function( $ ) {\r
6339 var lastActive,\r
6340         baseClasses = "ui-button ui-widget ui-state-default ui-corner-all",\r
6341         otherClasses = "ui-state-hover ui-state-active " +\r
6342                 "ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon ui-button-text-only",\r
6343         formResetHandler = function( event ) {\r
6344                 $( ":ui-button", event.target.form ).each(function() {\r
6345                         var inst = $( this ).data( "button" );\r
6346                         setTimeout(function() {\r
6347                                 inst.refresh();\r
6348                         }, 1 );\r
6349                 });\r
6350         },\r
6351         radioGroup = function( radio ) {\r
6352                 var name = radio.name,\r
6353                         form = radio.form,\r
6354                         radios = $( [] );\r
6355                 if ( name ) {\r
6356                         if ( form ) {\r
6357                                 radios = $( form ).find( "[name='" + name + "']" );\r
6358                         } else {\r
6359                                 radios = $( "[name='" + name + "']", radio.ownerDocument )\r
6360                                         .filter(function() {\r
6361                                                 return !this.form;\r
6362                                         });\r
6363                         }\r
6364                 }\r
6365                 return radios;\r
6366         };\r
6368 $.widget( "ui.button", {\r
6369         options: {\r
6370                 text: true,\r
6371                 label: null,\r
6372                 icons: {\r
6373                         primary: null,\r
6374                         secondary: null\r
6375                 }\r
6376         },\r
6377         _create: function() {\r
6378                 this.element.closest( "form" )\r
6379                         .unbind( "reset.button" )\r
6380                         .bind( "reset.button", formResetHandler );\r
6382                 this._determineButtonType();\r
6383                 this.hasTitle = !!this.buttonElement.attr( "title" );\r
6385                 var self = this,\r
6386                         options = this.options,\r
6387                         toggleButton = this.type === "checkbox" || this.type === "radio",\r
6388                         hoverClass = "ui-state-hover" + ( !toggleButton ? " ui-state-active" : "" ),\r
6389                         focusClass = "ui-state-focus";\r
6391                 if ( options.label === null ) {\r
6392                         options.label = this.buttonElement.html();\r
6393                 }\r
6395                 if ( this.element.is( ":disabled" ) ) {\r
6396                         options.disabled = true;\r
6397                 }\r
6399                 this.buttonElement\r
6400                         .addClass( baseClasses )\r
6401                         .attr( "role", "button" )\r
6402                         .bind( "mouseenter.button", function() {\r
6403                                 if ( options.disabled ) {\r
6404                                         return;\r
6405                                 }\r
6406                                 $( this ).addClass( "ui-state-hover" );\r
6407                                 if ( this === lastActive ) {\r
6408                                         $( this ).addClass( "ui-state-active" );\r
6409                                 }\r
6410                         })\r
6411                         .bind( "mouseleave.button", function() {\r
6412                                 if ( options.disabled ) {\r
6413                                         return;\r
6414                                 }\r
6415                                 $( this ).removeClass( hoverClass );\r
6416                         })\r
6417                         .bind( "focus.button", function() {\r
6418                                 // no need to check disabled, focus won't be triggered anyway\r
6419                                 $( this ).addClass( focusClass );\r
6420                         })\r
6421                         .bind( "blur.button", function() {\r
6422                                 $( this ).removeClass( focusClass );\r
6423                         });\r
6425                 if ( toggleButton ) {\r
6426                         this.element.bind( "change.button", function() {\r
6427                                 self.refresh();\r
6428                         });\r
6429                 }\r
6431                 if ( this.type === "checkbox" ) {\r
6432                         this.buttonElement.bind( "click.button", function() {\r
6433                                 if ( options.disabled ) {\r
6434                                         return false;\r
6435                                 }\r
6436                                 $( this ).toggleClass( "ui-state-active" );\r
6437                                 self.buttonElement.attr( "aria-pressed", self.element[0].checked );\r
6438                         });\r
6439                 } else if ( this.type === "radio" ) {\r
6440                         this.buttonElement.bind( "click.button", function() {\r
6441                                 if ( options.disabled ) {\r
6442                                         return false;\r
6443                                 }\r
6444                                 $( this ).addClass( "ui-state-active" );\r
6445                                 self.buttonElement.attr( "aria-pressed", true );\r
6447                                 var radio = self.element[ 0 ];\r
6448                                 radioGroup( radio )\r
6449                                         .not( radio )\r
6450                                         .map(function() {\r
6451                                                 return $( this ).button( "widget" )[ 0 ];\r
6452                                         })\r
6453                                         .removeClass( "ui-state-active" )\r
6454                                         .attr( "aria-pressed", false );\r
6455                         });\r
6456                 } else {\r
6457                         this.buttonElement\r
6458                                 .bind( "mousedown.button", function() {\r
6459                                         if ( options.disabled ) {\r
6460                                                 return false;\r
6461                                         }\r
6462                                         $( this ).addClass( "ui-state-active" );\r
6463                                         lastActive = this;\r
6464                                         $( document ).one( "mouseup", function() {\r
6465                                                 lastActive = null;\r
6466                                         });\r
6467                                 })\r
6468                                 .bind( "mouseup.button", function() {\r
6469                                         if ( options.disabled ) {\r
6470                                                 return false;\r
6471                                         }\r
6472                                         $( this ).removeClass( "ui-state-active" );\r
6473                                 })\r
6474                                 .bind( "keydown.button", function(event) {\r
6475                                         if ( options.disabled ) {\r
6476                                                 return false;\r
6477                                         }\r
6478                                         if ( event.keyCode == $.ui.keyCode.SPACE || event.keyCode == $.ui.keyCode.ENTER ) {\r
6479                                                 $( this ).addClass( "ui-state-active" );\r
6480                                         }\r
6481                                 })\r
6482                                 .bind( "keyup.button", function() {\r
6483                                         $( this ).removeClass( "ui-state-active" );\r
6484                                 });\r
6486                         if ( this.buttonElement.is("a") ) {\r
6487                                 this.buttonElement.keyup(function(event) {\r
6488                                         if ( event.keyCode === $.ui.keyCode.SPACE ) {\r
6489                                                 // TODO pass through original event correctly (just as 2nd argument doesn't work)\r
6490                                                 $( this ).click();\r
6491                                         }\r
6492                                 });\r
6493                         }\r
6494                 }\r
6496                 // TODO: pull out $.Widget's handling for the disabled option into\r
6497                 // $.Widget.prototype._setOptionDisabled so it's easy to proxy and can\r
6498                 // be overridden by individual plugins\r
6499                 this._setOption( "disabled", options.disabled );\r
6500         },\r
6502         _determineButtonType: function() {\r
6503                 \r
6504                 if ( this.element.is(":checkbox") ) {\r
6505                         this.type = "checkbox";\r
6506                 } else {\r
6507                         if ( this.element.is(":radio") ) {\r
6508                                 this.type = "radio";\r
6509                         } else {\r
6510                                 if ( this.element.is("input") ) {\r
6511                                         this.type = "input";\r
6512                                 } else {\r
6513                                         this.type = "button";\r
6514                                 }\r
6515                         }\r
6516                 }\r
6517                 \r
6518                 if ( this.type === "checkbox" || this.type === "radio" ) {\r
6519                         // we don't search against the document in case the element\r
6520                         // is disconnected from the DOM\r
6521                         this.buttonElement = this.element.parents().last()\r
6522                                 .find( "[for=" + this.element.attr("id") + "]" );\r
6523                         this.element.addClass( "ui-helper-hidden-accessible" );\r
6525                         var checked = this.element.is( ":checked" );\r
6526                         if ( checked ) {\r
6527                                 this.buttonElement.addClass( "ui-state-active" );\r
6528                         }\r
6529                         this.buttonElement.attr( "aria-pressed", checked );\r
6530                 } else {\r
6531                         this.buttonElement = this.element;\r
6532                 }\r
6533         },\r
6535         widget: function() {\r
6536                 return this.buttonElement;\r
6537         },\r
6539         destroy: function() {\r
6540                 this.element\r
6541                         .removeClass( "ui-helper-hidden-accessible" );\r
6542                 this.buttonElement\r
6543                         .removeClass( baseClasses + " " + otherClasses )\r
6544                         .removeAttr( "role" )\r
6545                         .removeAttr( "aria-pressed" )\r
6546                         .html( this.buttonElement.find(".ui-button-text").html() );\r
6548                 if ( !this.hasTitle ) {\r
6549                         this.buttonElement.removeAttr( "title" );\r
6550                 }\r
6552                 $.Widget.prototype.destroy.call( this );\r
6553         },\r
6555         _setOption: function( key, value ) {\r
6556                 $.Widget.prototype._setOption.apply( this, arguments );\r
6557                 if ( key === "disabled" ) {\r
6558                         if ( value ) {\r
6559                                 this.element.attr( "disabled", true );\r
6560                         } else {\r
6561                                 this.element.removeAttr( "disabled" );\r
6562                         }\r
6563                 }\r
6564                 this._resetButton();\r
6565         },\r
6567         refresh: function() {\r
6568                 var isDisabled = this.element.is( ":disabled" );\r
6569                 if ( isDisabled !== this.options.disabled ) {\r
6570                         this._setOption( "disabled", isDisabled );\r
6571                 }\r
6572                 if ( this.type === "radio" ) {\r
6573                         radioGroup( this.element[0] ).each(function() {\r
6574                                 if ( $( this ).is( ":checked" ) ) {\r
6575                                         $( this ).button( "widget" )\r
6576                                                 .addClass( "ui-state-active" )\r
6577                                                 .attr( "aria-pressed", true );\r
6578                                 } else {\r
6579                                         $( this ).button( "widget" )\r
6580                                                 .removeClass( "ui-state-active" )\r
6581                                                 .attr( "aria-pressed", false );\r
6582                                 }\r
6583                         });\r
6584                 } else if ( this.type === "checkbox" ) {\r
6585                         if ( this.element.is( ":checked" ) ) {\r
6586                                 this.buttonElement\r
6587                                         .addClass( "ui-state-active" )\r
6588                                         .attr( "aria-pressed", true );\r
6589                         } else {\r
6590                                 this.buttonElement\r
6591                                         .removeClass( "ui-state-active" )\r
6592                                         .attr( "aria-pressed", false );\r
6593                         }\r
6594                 }\r
6595         },\r
6597         _resetButton: function() {\r
6598                 if ( this.type === "input" ) {\r
6599                         if ( this.options.label ) {\r
6600                                 this.element.val( this.options.label );\r
6601                         }\r
6602                         return;\r
6603                 }\r
6604                 var buttonElement = this.buttonElement,\r
6605                         buttonText = $( "<span></span>" )\r
6606                                 .addClass( "ui-button-text" )\r
6607                                 .html( this.options.label )\r
6608                                 .appendTo( buttonElement.empty() )\r
6609                                 .text(),\r
6610                         icons = this.options.icons,\r
6611                         multipleIcons = icons.primary && icons.secondary;\r
6612                 if ( icons.primary || icons.secondary ) {\r
6613                         buttonElement.addClass( "ui-button-text-icon" +\r
6614                                 ( multipleIcons ? "s" : "" ) );\r
6615                         if ( icons.primary ) {\r
6616                                 buttonElement.prepend( "<span class='ui-button-icon-primary ui-icon " + icons.primary + "'></span>" );\r
6617                         }\r
6618                         if ( icons.secondary ) {\r
6619                                 buttonElement.append( "<span class='ui-button-icon-secondary ui-icon " + icons.secondary + "'></span>" );\r
6620                         }\r
6621                         if ( !this.options.text ) {\r
6622                                 buttonElement\r
6623                                         .addClass( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" )\r
6624                                         .removeClass( "ui-button-text-icons ui-button-text-icon" );\r
6625                                 if ( !this.hasTitle ) {\r
6626                                         buttonElement.attr( "title", buttonText );\r
6627                                 }\r
6628                         }\r
6629                 } else {\r
6630                         buttonElement.addClass( "ui-button-text-only" );\r
6631                 }\r
6632         }\r
6633 });\r
6635 $.widget( "ui.buttonset", {\r
6636         _create: function() {\r
6637                 this.element.addClass( "ui-buttonset" );\r
6638                 this._init();\r
6639         },\r
6640         \r
6641         _init: function() {\r
6642                 this.refresh();\r
6643         },\r
6645         _setOption: function( key, value ) {\r
6646                 if ( key === "disabled" ) {\r
6647                         this.buttons.button( "option", key, value );\r
6648                 }\r
6650                 $.Widget.prototype._setOption.apply( this, arguments );\r
6651         },\r
6652         \r
6653         refresh: function() {\r
6654                 this.buttons = this.element.find( ":button, :submit, :reset, :checkbox, :radio, a, :data(button)" )\r
6655                         .filter( ":ui-button" )\r
6656                                 .button( "refresh" )\r
6657                         .end()\r
6658                         .not( ":ui-button" )\r
6659                                 .button()\r
6660                         .end()\r
6661                         .map(function() {\r
6662                                 return $( this ).button( "widget" )[ 0 ];\r
6663                         })\r
6664                                 .removeClass( "ui-corner-all ui-corner-left ui-corner-right" )\r
6665                                 .filter( ":first" )\r
6666                                         .addClass( "ui-corner-left" )\r
6667                                 .end()\r
6668                                 .filter( ":last" )\r
6669                                         .addClass( "ui-corner-right" )\r
6670                                 .end()\r
6671                         .end();\r
6672         },\r
6674         destroy: function() {\r
6675                 this.element.removeClass( "ui-buttonset" );\r
6676                 this.buttons\r
6677                         .map(function() {\r
6678                                 return $( this ).button( "widget" )[ 0 ];\r
6679                         })\r
6680                                 .removeClass( "ui-corner-left ui-corner-right" )\r
6681                         .end()\r
6682                         .button( "destroy" )\r
6684                 $.Widget.prototype.destroy.call( this );\r
6685         }\r
6686 });\r
6688 }( jQuery ) );\r
6689 /*\r
6690  * jQuery UI Datepicker 1.8\r
6691  *\r
6692  * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)\r
6693  * Dual licensed under the MIT (MIT-LICENSE.txt)\r
6694  * and GPL (GPL-LICENSE.txt) licenses.\r
6695  *\r
6696  * http://docs.jquery.com/UI/Datepicker\r
6697  *\r
6698  * Depends:\r
6699  *      jquery.ui.core.js\r
6700  */\r
6702 (function($) { // hide the namespace\r
6704 $.extend($.ui, { datepicker: { version: "1.8" } });\r
6706 var PROP_NAME = 'datepicker';\r
6707 var dpuuid = new Date().getTime();\r
6709 /* Date picker manager.\r
6710    Use the singleton instance of this class, $.datepicker, to interact with the date picker.\r
6711    Settings for (groups of) date pickers are maintained in an instance object,\r
6712    allowing multiple different settings on the same page. */\r
6714 function Datepicker() {\r
6715         this.debug = false; // Change this to true to start debugging\r
6716         this._curInst = null; // The current instance in use\r
6717         this._keyEvent = false; // If the last event was a key event\r
6718         this._disabledInputs = []; // List of date picker inputs that have been disabled\r
6719         this._datepickerShowing = false; // True if the popup picker is showing , false if not\r
6720         this._inDialog = false; // True if showing within a "dialog", false if not\r
6721         this._mainDivId = 'ui-datepicker-div'; // The ID of the main datepicker division\r
6722         this._inlineClass = 'ui-datepicker-inline'; // The name of the inline marker class\r
6723         this._appendClass = 'ui-datepicker-append'; // The name of the append marker class\r
6724         this._triggerClass = 'ui-datepicker-trigger'; // The name of the trigger marker class\r
6725         this._dialogClass = 'ui-datepicker-dialog'; // The name of the dialog marker class\r
6726         this._disableClass = 'ui-datepicker-disabled'; // The name of the disabled covering marker class\r
6727         this._unselectableClass = 'ui-datepicker-unselectable'; // The name of the unselectable cell marker class\r
6728         this._currentClass = 'ui-datepicker-current-day'; // The name of the current day marker class\r
6729         this._dayOverClass = 'ui-datepicker-days-cell-over'; // The name of the day hover marker class\r
6730         this.regional = []; // Available regional settings, indexed by language code\r
6731         this.regional[''] = { // Default regional settings\r
6732                 closeText: 'Done', // Display text for close link\r
6733                 prevText: 'Prev', // Display text for previous month link\r
6734                 nextText: 'Next', // Display text for next month link\r
6735                 currentText: 'Today', // Display text for current month link\r
6736                 monthNames: ['January','February','March','April','May','June',\r
6737                         'July','August','September','October','November','December'], // Names of months for drop-down and formatting\r
6738                 monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], // For formatting\r
6739                 dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], // For formatting\r
6740                 dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], // For formatting\r
6741                 dayNamesMin: ['Su','Mo','Tu','We','Th','Fr','Sa'], // Column headings for days starting at Sunday\r
6742                 weekHeader: 'Wk', // Column header for week of the year\r
6743                 dateFormat: 'mm/dd/yy', // See format options on parseDate\r
6744                 firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...\r
6745                 isRTL: false, // True if right-to-left language, false if left-to-right\r
6746                 showMonthAfterYear: false, // True if the year select precedes month, false for month then year\r
6747                 yearSuffix: '' // Additional text to append to the year in the month headers\r
6748         };\r
6749         this._defaults = { // Global defaults for all the date picker instances\r
6750                 showOn: 'focus', // 'focus' for popup on focus,\r
6751                         // 'button' for trigger button, or 'both' for either\r
6752                 showAnim: 'show', // Name of jQuery animation for popup\r
6753                 showOptions: {}, // Options for enhanced animations\r
6754                 defaultDate: null, // Used when field is blank: actual date,\r
6755                         // +/-number for offset from today, null for today\r
6756                 appendText: '', // Display text following the input box, e.g. showing the format\r
6757                 buttonText: '...', // Text for trigger button\r
6758                 buttonImage: '', // URL for trigger button image\r
6759                 buttonImageOnly: false, // True if the image appears alone, false if it appears on a button\r
6760                 hideIfNoPrevNext: false, // True to hide next/previous month links\r
6761                         // if not applicable, false to just disable them\r
6762                 navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links\r
6763                 gotoCurrent: false, // True if today link goes back to current selection instead\r
6764                 changeMonth: false, // True if month can be selected directly, false if only prev/next\r
6765                 changeYear: false, // True if year can be selected directly, false if only prev/next\r
6766                 yearRange: 'c-10:c+10', // Range of years to display in drop-down,\r
6767                         // either relative to today's year (-nn:+nn), relative to currently displayed year\r
6768                         // (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)\r
6769                 showOtherMonths: false, // True to show dates in other months, false to leave blank\r
6770                 selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable\r
6771                 showWeek: false, // True to show week of the year, false to not show it\r
6772                 calculateWeek: this.iso8601Week, // How to calculate the week of the year,\r
6773                         // takes a Date and returns the number of the week for it\r
6774                 shortYearCutoff: '+10', // Short year values < this are in the current century,\r
6775                         // > this are in the previous century,\r
6776                         // string value starting with '+' for current year + value\r
6777                 minDate: null, // The earliest selectable date, or null for no limit\r
6778                 maxDate: null, // The latest selectable date, or null for no limit\r
6779                 duration: '_default', // Duration of display/closure\r
6780                 beforeShowDay: null, // Function that takes a date and returns an array with\r
6781                         // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or '',\r
6782                         // [2] = cell title (optional), e.g. $.datepicker.noWeekends\r
6783                 beforeShow: null, // Function that takes an input field and\r
6784                         // returns a set of custom settings for the date picker\r
6785                 onSelect: null, // Define a callback function when a date is selected\r
6786                 onChangeMonthYear: null, // Define a callback function when the month or year is changed\r
6787                 onClose: null, // Define a callback function when the datepicker is closed\r
6788                 numberOfMonths: 1, // Number of months to show at a time\r
6789                 showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)\r
6790                 stepMonths: 1, // Number of months to step back/forward\r
6791                 stepBigMonths: 12, // Number of months to step back/forward for the big links\r
6792                 altField: '', // Selector for an alternate field to store selected dates into\r
6793                 altFormat: '', // The date format to use for the alternate field\r
6794                 constrainInput: true, // The input is constrained by the current date format\r
6795                 showButtonPanel: false, // True to show button panel, false to not show it\r
6796                 autoSize: false // True to size the input for the date format, false to leave as is\r
6797         };\r
6798         $.extend(this._defaults, this.regional['']);\r
6799         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>');\r
6802 $.extend(Datepicker.prototype, {\r
6803         /* Class name added to elements to indicate already configured with a date picker. */\r
6804         markerClassName: 'hasDatepicker',\r
6806         /* Debug logging (if enabled). */\r
6807         log: function () {\r
6808                 if (this.debug)\r
6809                         console.log.apply('', arguments);\r
6810         },\r
6811         \r
6812         // TODO rename to "widget" when switching to widget factory\r
6813         _widgetDatepicker: function() {\r
6814                 return this.dpDiv;\r
6815         },\r
6817         /* Override the default settings for all instances of the date picker.\r
6818            @param  settings  object - the new settings to use as defaults (anonymous object)\r
6819            @return the manager object */\r
6820         setDefaults: function(settings) {\r
6821                 extendRemove(this._defaults, settings || {});\r
6822                 return this;\r
6823         },\r
6825         /* Attach the date picker to a jQuery selection.\r
6826            @param  target    element - the target input field or division or span\r
6827            @param  settings  object - the new settings to use for this date picker instance (anonymous) */\r
6828         _attachDatepicker: function(target, settings) {\r
6829                 // check for settings on the control itself - in namespace 'date:'\r
6830                 var inlineSettings = null;\r
6831                 for (var attrName in this._defaults) {\r
6832                         var attrValue = target.getAttribute('date:' + attrName);\r
6833                         if (attrValue) {\r
6834                                 inlineSettings = inlineSettings || {};\r
6835                                 try {\r
6836                                         inlineSettings[attrName] = eval(attrValue);\r
6837                                 } catch (err) {\r
6838                                         inlineSettings[attrName] = attrValue;\r
6839                                 }\r
6840                         }\r
6841                 }\r
6842                 var nodeName = target.nodeName.toLowerCase();\r
6843                 var inline = (nodeName == 'div' || nodeName == 'span');\r
6844                 if (!target.id)\r
6845                         target.id = 'dp' + (++this.uuid);\r
6846                 var inst = this._newInst($(target), inline);\r
6847                 inst.settings = $.extend({}, settings || {}, inlineSettings || {});\r
6848                 if (nodeName == 'input') {\r
6849                         this._connectDatepicker(target, inst);\r
6850                 } else if (inline) {\r
6851                         this._inlineDatepicker(target, inst);\r
6852                 }\r
6853         },\r
6855         /* Create a new instance object. */\r
6856         _newInst: function(target, inline) {\r
6857                 var id = target[0].id.replace(/([^A-Za-z0-9_])/g, '\\\\$1'); // escape jQuery meta chars\r
6858                 return {id: id, input: target, // associated target\r
6859                         selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection\r
6860                         drawMonth: 0, drawYear: 0, // month being drawn\r
6861                         inline: inline, // is datepicker inline or not\r
6862                         dpDiv: (!inline ? this.dpDiv : // presentation div\r
6863                         $('<div class="' + this._inlineClass + ' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>'))};\r
6864         },\r
6866         /* Attach the date picker to an input field. */\r
6867         _connectDatepicker: function(target, inst) {\r
6868                 var input = $(target);\r
6869                 inst.append = $([]);\r
6870                 inst.trigger = $([]);\r
6871                 if (input.hasClass(this.markerClassName))\r
6872                         return;\r
6873                 this._attachments(input, inst);\r
6874                 input.addClass(this.markerClassName).keydown(this._doKeyDown).\r
6875                         keypress(this._doKeyPress).keyup(this._doKeyUp).\r
6876                         bind("setData.datepicker", function(event, key, value) {\r
6877                                 inst.settings[key] = value;\r
6878                         }).bind("getData.datepicker", function(event, key) {\r
6879                                 return this._get(inst, key);\r
6880                         });\r
6881                 this._autoSize(inst);\r
6882                 $.data(target, PROP_NAME, inst);\r
6883         },\r
6885         /* Make attachments based on settings. */\r
6886         _attachments: function(input, inst) {\r
6887                 var appendText = this._get(inst, 'appendText');\r
6888                 var isRTL = this._get(inst, 'isRTL');\r
6889                 if (inst.append)\r
6890                         inst.append.remove();\r
6891                 if (appendText) {\r
6892                         inst.append = $('<span class="' + this._appendClass + '">' + appendText + '</span>');\r
6893                         input[isRTL ? 'before' : 'after'](inst.append);\r
6894                 }\r
6895                 input.unbind('focus', this._showDatepicker);\r
6896                 if (inst.trigger)\r
6897                         inst.trigger.remove();\r
6898                 var showOn = this._get(inst, 'showOn');\r
6899                 if (showOn == 'focus' || showOn == 'both') // pop-up date picker when in the marked field\r
6900                         input.focus(this._showDatepicker);\r
6901                 if (showOn == 'button' || showOn == 'both') { // pop-up date picker when button clicked\r
6902                         var buttonText = this._get(inst, 'buttonText');\r
6903                         var buttonImage = this._get(inst, 'buttonImage');\r
6904                         inst.trigger = $(this._get(inst, 'buttonImageOnly') ?\r
6905                                 $('<img/>').addClass(this._triggerClass).\r
6906                                         attr({ src: buttonImage, alt: buttonText, title: buttonText }) :\r
6907                                 $('<button type="button"></button>').addClass(this._triggerClass).\r
6908                                         html(buttonImage == '' ? buttonText : $('<img/>').attr(\r
6909                                         { src:buttonImage, alt:buttonText, title:buttonText })));\r
6910                         input[isRTL ? 'before' : 'after'](inst.trigger);\r
6911                         inst.trigger.click(function() {\r
6912                                 if ($.datepicker._datepickerShowing && $.datepicker._lastInput == input[0])\r
6913                                         $.datepicker._hideDatepicker();\r
6914                                 else\r
6915                                         $.datepicker._showDatepicker(input[0]);\r
6916                                 return false;\r
6917                         });\r
6918                 }\r
6919         },\r
6921         /* Apply the maximum length for the date format. */\r
6922         _autoSize: function(inst) {\r
6923                 if (this._get(inst, 'autoSize') && !inst.inline) {\r
6924                         var date = new Date(2009, 12 - 1, 20); // Ensure double digits\r
6925                         var dateFormat = this._get(inst, 'dateFormat');\r
6926                         if (dateFormat.match(/[DM]/)) {\r
6927                                 var findMax = function(names) {\r
6928                                         var max = 0;\r
6929                                         var maxI = 0;\r
6930                                         for (var i = 0; i < names.length; i++) {\r
6931                                                 if (names[i].length > max) {\r
6932                                                         max = names[i].length;\r
6933                                                         maxI = i;\r
6934                                                 }\r
6935                                         }\r
6936                                         return maxI;\r
6937                                 };\r
6938                                 date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ?\r
6939                                         'monthNames' : 'monthNamesShort'))));\r
6940                                 date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ?\r
6941                                         'dayNames' : 'dayNamesShort'))) + 20 - date.getDay());\r
6942                         }\r
6943                         inst.input.attr('size', this._formatDate(inst, date).length);\r
6944                 }\r
6945         },\r
6947         /* Attach an inline date picker to a div. */\r
6948         _inlineDatepicker: function(target, inst) {\r
6949                 var divSpan = $(target);\r
6950                 if (divSpan.hasClass(this.markerClassName))\r
6951                         return;\r
6952                 divSpan.addClass(this.markerClassName).append(inst.dpDiv).\r
6953                         bind("setData.datepicker", function(event, key, value){\r
6954                                 inst.settings[key] = value;\r
6955                         }).bind("getData.datepicker", function(event, key){\r
6956                                 return this._get(inst, key);\r
6957                         });\r
6958                 $.data(target, PROP_NAME, inst);\r
6959                 this._setDate(inst, this._getDefaultDate(inst), true);\r
6960                 this._updateDatepicker(inst);\r
6961                 this._updateAlternate(inst);\r
6962         },\r
6964         /* Pop-up the date picker in a "dialog" box.\r
6965            @param  input     element - ignored\r
6966            @param  date      string or Date - the initial date to display\r
6967            @param  onSelect  function - the function to call when a date is selected\r
6968            @param  settings  object - update the dialog date picker instance's settings (anonymous object)\r
6969            @param  pos       int[2] - coordinates for the dialog's position within the screen or\r
6970                              event - with x/y coordinates or\r
6971                              leave empty for default (screen centre)\r
6972            @return the manager object */\r
6973         _dialogDatepicker: function(input, date, onSelect, settings, pos) {\r
6974                 var inst = this._dialogInst; // internal instance\r
6975                 if (!inst) {\r
6976                         var id = 'dp' + (++this.uuid);\r
6977                         this._dialogInput = $('<input type="text" id="' + id +\r
6978                                 '" style="position: absolute; top: -100px; width: 0px; z-index: -10;"/>');\r
6979                         this._dialogInput.keydown(this._doKeyDown);\r
6980                         $('body').append(this._dialogInput);\r
6981                         inst = this._dialogInst = this._newInst(this._dialogInput, false);\r
6982                         inst.settings = {};\r
6983                         $.data(this._dialogInput[0], PROP_NAME, inst);\r
6984                 }\r
6985                 extendRemove(inst.settings, settings || {});\r
6986                 date = (date && date.constructor == Date ? this._formatDate(inst, date) : date);\r
6987                 this._dialogInput.val(date);\r
6989                 this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);\r
6990                 if (!this._pos) {\r
6991                         var browserWidth = document.documentElement.clientWidth;\r
6992                         var browserHeight = document.documentElement.clientHeight;\r
6993                         var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;\r
6994                         var scrollY = document.documentElement.scrollTop || document.body.scrollTop;\r
6995                         this._pos = // should use actual width/height below\r
6996                                 [(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY];\r
6997                 }\r
6999                 // move input on screen for focus, but hidden behind dialog\r
7000                 this._dialogInput.css('left', (this._pos[0] + 20) + 'px').css('top', this._pos[1] + 'px');\r
7001                 inst.settings.onSelect = onSelect;\r
7002                 this._inDialog = true;\r
7003                 this.dpDiv.addClass(this._dialogClass);\r
7004                 this._showDatepicker(this._dialogInput[0]);\r
7005                 if ($.blockUI)\r
7006                         $.blockUI(this.dpDiv);\r
7007                 $.data(this._dialogInput[0], PROP_NAME, inst);\r
7008                 return this;\r
7009         },\r
7011         /* Detach a datepicker from its control.\r
7012            @param  target    element - the target input field or division or span */\r
7013         _destroyDatepicker: function(target) {\r
7014                 var $target = $(target);\r
7015                 var inst = $.data(target, PROP_NAME);\r
7016                 if (!$target.hasClass(this.markerClassName)) {\r
7017                         return;\r
7018                 }\r
7019                 var nodeName = target.nodeName.toLowerCase();\r
7020                 $.removeData(target, PROP_NAME);\r
7021                 if (nodeName == 'input') {\r
7022                         inst.append.remove();\r
7023                         inst.trigger.remove();\r
7024                         $target.removeClass(this.markerClassName).\r
7025                                 unbind('focus', this._showDatepicker).\r
7026                                 unbind('keydown', this._doKeyDown).\r
7027                                 unbind('keypress', this._doKeyPress).\r
7028                                 unbind('keyup', this._doKeyUp);\r
7029                 } else if (nodeName == 'div' || nodeName == 'span')\r
7030                         $target.removeClass(this.markerClassName).empty();\r
7031         },\r
7033         /* Enable the date picker to a jQuery selection.\r
7034            @param  target    element - the target input field or division or span */\r
7035         _enableDatepicker: function(target) {\r
7036                 var $target = $(target);\r
7037                 var inst = $.data(target, PROP_NAME);\r
7038                 if (!$target.hasClass(this.markerClassName)) {\r
7039                         return;\r
7040                 }\r
7041                 var nodeName = target.nodeName.toLowerCase();\r
7042                 if (nodeName == 'input') {\r
7043                         target.disabled = false;\r
7044                         inst.trigger.filter('button').\r
7045                                 each(function() { this.disabled = false; }).end().\r
7046                                 filter('img').css({opacity: '1.0', cursor: ''});\r
7047                 }\r
7048                 else if (nodeName == 'div' || nodeName == 'span') {\r
7049                         var inline = $target.children('.' + this._inlineClass);\r
7050                         inline.children().removeClass('ui-state-disabled');\r
7051                 }\r
7052                 this._disabledInputs = $.map(this._disabledInputs,\r
7053                         function(value) { return (value == target ? null : value); }); // delete entry\r
7054         },\r
7056         /* Disable the date picker to a jQuery selection.\r
7057            @param  target    element - the target input field or division or span */\r
7058         _disableDatepicker: function(target) {\r
7059                 var $target = $(target);\r
7060                 var inst = $.data(target, PROP_NAME);\r
7061                 if (!$target.hasClass(this.markerClassName)) {\r
7062                         return;\r
7063                 }\r
7064                 var nodeName = target.nodeName.toLowerCase();\r
7065                 if (nodeName == 'input') {\r
7066                         target.disabled = true;\r
7067                         inst.trigger.filter('button').\r
7068                                 each(function() { this.disabled = true; }).end().\r
7069                                 filter('img').css({opacity: '0.5', cursor: 'default'});\r
7070                 }\r
7071                 else if (nodeName == 'div' || nodeName == 'span') {\r
7072                         var inline = $target.children('.' + this._inlineClass);\r
7073                         inline.children().addClass('ui-state-disabled');\r
7074                 }\r
7075                 this._disabledInputs = $.map(this._disabledInputs,\r
7076                         function(value) { return (value == target ? null : value); }); // delete entry\r
7077                 this._disabledInputs[this._disabledInputs.length] = target;\r
7078         },\r
7080         /* Is the first field in a jQuery collection disabled as a datepicker?\r
7081            @param  target    element - the target input field or division or span\r
7082            @return boolean - true if disabled, false if enabled */\r
7083         _isDisabledDatepicker: function(target) {\r
7084                 if (!target) {\r
7085                         return false;\r
7086                 }\r
7087                 for (var i = 0; i < this._disabledInputs.length; i++) {\r
7088                         if (this._disabledInputs[i] == target)\r
7089                                 return true;\r
7090                 }\r
7091                 return false;\r
7092         },\r
7094         /* Retrieve the instance data for the target control.\r
7095            @param  target  element - the target input field or division or span\r
7096            @return  object - the associated instance data\r
7097            @throws  error if a jQuery problem getting data */\r
7098         _getInst: function(target) {\r
7099                 try {\r
7100                         return $.data(target, PROP_NAME);\r
7101                 }\r
7102                 catch (err) {\r
7103                         throw 'Missing instance data for this datepicker';\r
7104                 }\r
7105         },\r
7107         /* Update or retrieve the settings for a date picker attached to an input field or division.\r
7108            @param  target  element - the target input field or division or span\r
7109            @param  name    object - the new settings to update or\r
7110                            string - the name of the setting to change or retrieve,\r
7111                            when retrieving also 'all' for all instance settings or\r
7112                            'defaults' for all global defaults\r
7113            @param  value   any - the new value for the setting\r
7114                            (omit if above is an object or to retrieve a value) */\r
7115         _optionDatepicker: function(target, name, value) {\r
7116                 var inst = this._getInst(target);\r
7117                 if (arguments.length == 2 && typeof name == 'string') {\r
7118                         return (name == 'defaults' ? $.extend({}, $.datepicker._defaults) :\r
7119                                 (inst ? (name == 'all' ? $.extend({}, inst.settings) :\r
7120                                 this._get(inst, name)) : null));\r
7121                 }\r
7122                 var settings = name || {};\r
7123                 if (typeof name == 'string') {\r
7124                         settings = {};\r
7125                         settings[name] = value;\r
7126                 }\r
7127                 if (inst) {\r
7128                         if (this._curInst == inst) {\r
7129                                 this._hideDatepicker();\r
7130                         }\r
7131                         var date = this._getDateDatepicker(target, true);\r
7132                         extendRemove(inst.settings, settings);\r
7133                         this._attachments($(target), inst);\r
7134                         this._autoSize(inst);\r
7135                         this._setDateDatepicker(target, date);\r
7136                         this._updateDatepicker(inst);\r
7137                 }\r
7138         },\r
7140         // change method deprecated\r
7141         _changeDatepicker: function(target, name, value) {\r
7142                 this._optionDatepicker(target, name, value);\r
7143         },\r
7145         /* Redraw the date picker attached to an input field or division.\r
7146            @param  target  element - the target input field or division or span */\r
7147         _refreshDatepicker: function(target) {\r
7148                 var inst = this._getInst(target);\r
7149                 if (inst) {\r
7150                         this._updateDatepicker(inst);\r
7151                 }\r
7152         },\r
7154         /* Set the dates for a jQuery selection.\r
7155            @param  target   element - the target input field or division or span\r
7156            @param  date     Date - the new date */\r
7157         _setDateDatepicker: function(target, date) {\r
7158                 var inst = this._getInst(target);\r
7159                 if (inst) {\r
7160                         this._setDate(inst, date);\r
7161                         this._updateDatepicker(inst);\r
7162                         this._updateAlternate(inst);\r
7163                 }\r
7164         },\r
7166         /* Get the date(s) for the first entry in a jQuery selection.\r
7167            @param  target     element - the target input field or division or span\r
7168            @param  noDefault  boolean - true if no default date is to be used\r
7169            @return Date - the current date */\r
7170         _getDateDatepicker: function(target, noDefault) {\r
7171                 var inst = this._getInst(target);\r
7172                 if (inst && !inst.inline)\r
7173                         this._setDateFromField(inst, noDefault);\r
7174                 return (inst ? this._getDate(inst) : null);\r
7175         },\r
7177         /* Handle keystrokes. */\r
7178         _doKeyDown: function(event) {\r
7179                 var inst = $.datepicker._getInst(event.target);\r
7180                 var handled = true;\r
7181                 var isRTL = inst.dpDiv.is('.ui-datepicker-rtl');\r
7182                 inst._keyEvent = true;\r
7183                 if ($.datepicker._datepickerShowing)\r
7184                         switch (event.keyCode) {\r
7185                                 case 9: $.datepicker._hideDatepicker();\r
7186                                                 handled = false;\r
7187                                                 break; // hide on tab out\r
7188                                 case 13: var sel = $('td.' + $.datepicker._dayOverClass, inst.dpDiv).\r
7189                                                         add($('td.' + $.datepicker._currentClass, inst.dpDiv));\r
7190                                                 if (sel[0])\r
7191                                                         $.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);\r
7192                                                 else\r
7193                                                         $.datepicker._hideDatepicker();\r
7194                                                 return false; // don't submit the form\r
7195                                                 break; // select the value on enter\r
7196                                 case 27: $.datepicker._hideDatepicker();\r
7197                                                 break; // hide on escape\r
7198                                 case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ?\r
7199                                                         -$.datepicker._get(inst, 'stepBigMonths') :\r
7200                                                         -$.datepicker._get(inst, 'stepMonths')), 'M');\r
7201                                                 break; // previous month/year on page up/+ ctrl\r
7202                                 case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ?\r
7203                                                         +$.datepicker._get(inst, 'stepBigMonths') :\r
7204                                                         +$.datepicker._get(inst, 'stepMonths')), 'M');\r
7205                                                 break; // next month/year on page down/+ ctrl\r
7206                                 case 35: if (event.ctrlKey || event.metaKey) $.datepicker._clearDate(event.target);\r
7207                                                 handled = event.ctrlKey || event.metaKey;\r
7208                                                 break; // clear on ctrl or command +end\r
7209                                 case 36: if (event.ctrlKey || event.metaKey) $.datepicker._gotoToday(event.target);\r
7210                                                 handled = event.ctrlKey || event.metaKey;\r
7211                                                 break; // current on ctrl or command +home\r
7212                                 case 37: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), 'D');\r
7213                                                 handled = event.ctrlKey || event.metaKey;\r
7214                                                 // -1 day on ctrl or command +left\r
7215                                                 if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?\r
7216                                                                         -$.datepicker._get(inst, 'stepBigMonths') :\r
7217                                                                         -$.datepicker._get(inst, 'stepMonths')), 'M');\r
7218                                                 // next month/year on alt +left on Mac\r
7219                                                 break;\r
7220                                 case 38: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, -7, 'D');\r
7221                                                 handled = event.ctrlKey || event.metaKey;\r
7222                                                 break; // -1 week on ctrl or command +up\r
7223                                 case 39: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), 'D');\r
7224                                                 handled = event.ctrlKey || event.metaKey;\r
7225                                                 // +1 day on ctrl or command +right\r
7226                                                 if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?\r
7227                                                                         +$.datepicker._get(inst, 'stepBigMonths') :\r
7228                                                                         +$.datepicker._get(inst, 'stepMonths')), 'M');\r
7229                                                 // next month/year on alt +right\r
7230                                                 break;\r
7231                                 case 40: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, +7, 'D');\r
7232                                                 handled = event.ctrlKey || event.metaKey;\r
7233                                                 break; // +1 week on ctrl or command +down\r
7234                                 default: handled = false;\r
7235                         }\r
7236                 else if (event.keyCode == 36 && event.ctrlKey) // display the date picker on ctrl+home\r
7237                         $.datepicker._showDatepicker(this);\r
7238                 else {\r
7239                         handled = false;\r
7240                 }\r
7241                 if (handled) {\r
7242                         event.preventDefault();\r
7243                         event.stopPropagation();\r
7244                 }\r
7245         },\r
7247         /* Filter entered characters - based on date format. */\r
7248         _doKeyPress: function(event) {\r
7249                 var inst = $.datepicker._getInst(event.target);\r
7250                 if ($.datepicker._get(inst, 'constrainInput')) {\r
7251                         var chars = $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat'));\r
7252                         var chr = String.fromCharCode(event.charCode == undefined ? event.keyCode : event.charCode);\r
7253                         return event.ctrlKey || (chr < ' ' || !chars || chars.indexOf(chr) > -1);\r
7254                 }\r
7255         },\r
7257         /* Synchronise manual entry and field/alternate field. */\r
7258         _doKeyUp: function(event) {\r
7259                 var inst = $.datepicker._getInst(event.target);\r
7260                 if (inst.input.val() != inst.lastVal) {\r
7261                         try {\r
7262                                 var date = $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),\r
7263                                         (inst.input ? inst.input.val() : null),\r
7264                                         $.datepicker._getFormatConfig(inst));\r
7265                                 if (date) { // only if valid\r
7266                                         $.datepicker._setDateFromField(inst);\r
7267                                         $.datepicker._updateAlternate(inst);\r
7268                                         $.datepicker._updateDatepicker(inst);\r
7269                                 }\r
7270                         }\r
7271                         catch (event) {\r
7272                                 $.datepicker.log(event);\r
7273                         }\r
7274                 }\r
7275                 return true;\r
7276         },\r
7278         /* Pop-up the date picker for a given input field.\r
7279            @param  input  element - the input field attached to the date picker or\r
7280                           event - if triggered by focus */\r
7281         _showDatepicker: function(input) {\r
7282                 input = input.target || input;\r
7283                 if (input.nodeName.toLowerCase() != 'input') // find from button/image trigger\r
7284                         input = $('input', input.parentNode)[0];\r
7285                 if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput == input) // already here\r
7286                         return;\r
7287                 var inst = $.datepicker._getInst(input);\r
7288                 if ($.datepicker._curInst && $.datepicker._curInst != inst) {\r
7289                         $.datepicker._curInst.dpDiv.stop(true, true);\r
7290                 }\r
7291                 var beforeShow = $.datepicker._get(inst, 'beforeShow');\r
7292                 extendRemove(inst.settings, (beforeShow ? beforeShow.apply(input, [input, inst]) : {}));\r
7293                 inst.lastVal = null;\r
7294                 $.datepicker._lastInput = input;\r
7295                 $.datepicker._setDateFromField(inst);\r
7296                 if ($.datepicker._inDialog) // hide cursor\r
7297                         input.value = '';\r
7298                 if (!$.datepicker._pos) { // position below input\r
7299                         $.datepicker._pos = $.datepicker._findPos(input);\r
7300                         $.datepicker._pos[1] += input.offsetHeight; // add the height\r
7301                 }\r
7302                 var isFixed = false;\r
7303                 $(input).parents().each(function() {\r
7304                         isFixed |= $(this).css('position') == 'fixed';\r
7305                         return !isFixed;\r
7306                 });\r
7307                 if (isFixed && $.browser.opera) { // correction for Opera when fixed and scrolled\r
7308                         $.datepicker._pos[0] -= document.documentElement.scrollLeft;\r
7309                         $.datepicker._pos[1] -= document.documentElement.scrollTop;\r
7310                 }\r
7311                 var offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]};\r
7312                 $.datepicker._pos = null;\r
7313                 // determine sizing offscreen\r
7314                 inst.dpDiv.css({position: 'absolute', display: 'block', top: '-1000px'});\r
7315                 $.datepicker._updateDatepicker(inst);\r
7316                 // fix width for dynamic number of date pickers\r
7317                 // and adjust position before showing\r
7318                 offset = $.datepicker._checkOffset(inst, offset, isFixed);\r
7319                 inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ?\r
7320                         'static' : (isFixed ? 'fixed' : 'absolute')), display: 'none',\r
7321                         left: offset.left + 'px', top: offset.top + 'px'});\r
7322                 if (!inst.inline) {\r
7323                         var showAnim = $.datepicker._get(inst, 'showAnim');\r
7324                         var duration = $.datepicker._get(inst, 'duration');\r
7325                         var postProcess = function() {\r
7326                                 $.datepicker._datepickerShowing = true;\r
7327                                 var borders = $.datepicker._getBorders(inst.dpDiv);\r
7328                                 inst.dpDiv.find('iframe.ui-datepicker-cover'). // IE6- only\r
7329                                         css({left: -borders[0], top: -borders[1],\r
7330                                                 width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()});\r
7331                         };\r
7332                         inst.dpDiv.zIndex($(input).zIndex()+1);\r
7333                         if ($.effects && $.effects[showAnim])\r
7334                                 inst.dpDiv.show(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);\r
7335                         else\r
7336                                 inst.dpDiv[showAnim || 'show']((showAnim ? duration : null), postProcess);\r
7337                         if (!showAnim || !duration)\r
7338                                 postProcess();\r
7339                         if (inst.input.is(':visible') && !inst.input.is(':disabled'))\r
7340                                 inst.input.focus();\r
7341                         $.datepicker._curInst = inst;\r
7342                 }\r
7343         },\r
7345         /* Generate the date picker content. */\r
7346         _updateDatepicker: function(inst) {\r
7347                 var self = this;\r
7348                 var borders = $.datepicker._getBorders(inst.dpDiv);\r
7349                 inst.dpDiv.empty().append(this._generateHTML(inst))\r
7350                         .find('iframe.ui-datepicker-cover') // IE6- only\r
7351                                 .css({left: -borders[0], top: -borders[1],\r
7352                                         width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()})\r
7353                         .end()\r
7354                         .find('button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a')\r
7355                                 .bind('mouseout', function(){\r
7356                                         $(this).removeClass('ui-state-hover');\r
7357                                         if(this.className.indexOf('ui-datepicker-prev') != -1) $(this).removeClass('ui-datepicker-prev-hover');\r
7358                                         if(this.className.indexOf('ui-datepicker-next') != -1) $(this).removeClass('ui-datepicker-next-hover');\r
7359                                 })\r
7360                                 .bind('mouseover', function(){\r
7361                                         if (!self._isDisabledDatepicker( inst.inline ? inst.dpDiv.parent()[0] : inst.input[0])) {\r
7362                                                 $(this).parents('.ui-datepicker-calendar').find('a').removeClass('ui-state-hover');\r
7363                                                 $(this).addClass('ui-state-hover');\r
7364                                                 if(this.className.indexOf('ui-datepicker-prev') != -1) $(this).addClass('ui-datepicker-prev-hover');\r
7365                                                 if(this.className.indexOf('ui-datepicker-next') != -1) $(this).addClass('ui-datepicker-next-hover');\r
7366                                         }\r
7367                                 })\r
7368                         .end()\r
7369                         .find('.' + this._dayOverClass + ' a')\r
7370                                 .trigger('mouseover')\r
7371                         .end();\r
7372                 var numMonths = this._getNumberOfMonths(inst);\r
7373                 var cols = numMonths[1];\r
7374                 var width = 17;\r
7375                 if (cols > 1)\r
7376                         inst.dpDiv.addClass('ui-datepicker-multi-' + cols).css('width', (width * cols) + 'em');\r
7377                 else\r
7378                         inst.dpDiv.removeClass('ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4').width('');\r
7379                 inst.dpDiv[(numMonths[0] != 1 || numMonths[1] != 1 ? 'add' : 'remove') +\r
7380                         'Class']('ui-datepicker-multi');\r
7381                 inst.dpDiv[(this._get(inst, 'isRTL') ? 'add' : 'remove') +\r
7382                         'Class']('ui-datepicker-rtl');\r
7383                 if (inst == $.datepicker._curInst && $.datepicker._datepickerShowing && inst.input &&\r
7384                                 inst.input.is(':visible') && !inst.input.is(':disabled'))\r
7385                         inst.input.focus();\r
7386         },\r
7388         /* Retrieve the size of left and top borders for an element.\r
7389            @param  elem  (jQuery object) the element of interest\r
7390            @return  (number[2]) the left and top borders */\r
7391         _getBorders: function(elem) {\r
7392                 var convert = function(value) {\r
7393                         return {thin: 1, medium: 2, thick: 3}[value] || value;\r
7394                 };\r
7395                 return [parseFloat(convert(elem.css('border-left-width'))),\r
7396                         parseFloat(convert(elem.css('border-top-width')))];\r
7397         },\r
7399         /* Check positioning to remain on screen. */\r
7400         _checkOffset: function(inst, offset, isFixed) {\r
7401                 var dpWidth = inst.dpDiv.outerWidth();\r
7402                 var dpHeight = inst.dpDiv.outerHeight();\r
7403                 var inputWidth = inst.input ? inst.input.outerWidth() : 0;\r
7404                 var inputHeight = inst.input ? inst.input.outerHeight() : 0;\r
7405                 var viewWidth = document.documentElement.clientWidth + $(document).scrollLeft();\r
7406                 var viewHeight = document.documentElement.clientHeight + $(document).scrollTop();\r
7408                 offset.left -= (this._get(inst, 'isRTL') ? (dpWidth - inputWidth) : 0);\r
7409                 offset.left -= (isFixed && offset.left == inst.input.offset().left) ? $(document).scrollLeft() : 0;\r
7410                 offset.top -= (isFixed && offset.top == (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;\r
7412                 // now check if datepicker is showing outside window viewport - move to a better place if so.\r
7413                 offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?\r
7414                         Math.abs(offset.left + dpWidth - viewWidth) : 0);\r
7415                 offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?\r
7416                         Math.abs(dpHeight + inputHeight) : 0);\r
7418                 return offset;\r
7419         },\r
7421         /* Find an object's position on the screen. */\r
7422         _findPos: function(obj) {\r
7423                 var inst = this._getInst(obj);\r
7424                 var isRTL = this._get(inst, 'isRTL');\r
7425         while (obj && (obj.type == 'hidden' || obj.nodeType != 1)) {\r
7426             obj = obj[isRTL ? 'previousSibling' : 'nextSibling'];\r
7427         }\r
7428         var position = $(obj).offset();\r
7429             return [position.left, position.top];\r
7430         },\r
7432         /* Hide the date picker from view.\r
7433            @param  input  element - the input field attached to the date picker */\r
7434         _hideDatepicker: function(input) {\r
7435                 var inst = this._curInst;\r
7436                 if (!inst || (input && inst != $.data(input, PROP_NAME)))\r
7437                         return;\r
7438                 if (this._datepickerShowing) {\r
7439                         var showAnim = this._get(inst, 'showAnim');\r
7440                         var duration = this._get(inst, 'duration');\r
7441                         var postProcess = function() {\r
7442                                 $.datepicker._tidyDialog(inst);\r
7443                                 this._curInst = null;\r
7444                         };\r
7445                         if ($.effects && $.effects[showAnim])\r
7446                                 inst.dpDiv.hide(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);\r
7447                         else\r
7448                                 inst.dpDiv[(showAnim == 'slideDown' ? 'slideUp' :\r
7449                                         (showAnim == 'fadeIn' ? 'fadeOut' : 'hide'))]((showAnim ? duration : null), postProcess);\r
7450                         if (!showAnim)\r
7451                                 postProcess();\r
7452                         var onClose = this._get(inst, 'onClose');\r
7453                         if (onClose)\r
7454                                 onClose.apply((inst.input ? inst.input[0] : null),\r
7455                                         [(inst.input ? inst.input.val() : ''), inst]);  // trigger custom callback\r
7456                         this._datepickerShowing = false;\r
7457                         this._lastInput = null;\r
7458                         if (this._inDialog) {\r
7459                                 this._dialogInput.css({ position: 'absolute', left: '0', top: '-100px' });\r
7460                                 if ($.blockUI) {\r
7461                                         $.unblockUI();\r
7462                                         $('body').append(this.dpDiv);\r
7463                                 }\r
7464                         }\r
7465                         this._inDialog = false;\r
7466                 }\r
7467         },\r
7469         /* Tidy up after a dialog display. */\r
7470         _tidyDialog: function(inst) {\r
7471                 inst.dpDiv.removeClass(this._dialogClass).unbind('.ui-datepicker-calendar');\r
7472         },\r
7474         /* Close date picker if clicked elsewhere. */\r
7475         _checkExternalClick: function(event) {\r
7476                 if (!$.datepicker._curInst)\r
7477                         return;\r
7478                 var $target = $(event.target);\r
7479                 if ($target[0].id != $.datepicker._mainDivId &&\r
7480                                 $target.parents('#' + $.datepicker._mainDivId).length == 0 &&\r
7481                                 !$target.hasClass($.datepicker.markerClassName) &&\r
7482                                 !$target.hasClass($.datepicker._triggerClass) &&\r
7483                                 $.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI))\r
7484                         $.datepicker._hideDatepicker();\r
7485         },\r
7487         /* Adjust one of the date sub-fields. */\r
7488         _adjustDate: function(id, offset, period) {\r
7489                 var target = $(id);\r
7490                 var inst = this._getInst(target[0]);\r
7491                 if (this._isDisabledDatepicker(target[0])) {\r
7492                         return;\r
7493                 }\r
7494                 this._adjustInstDate(inst, offset +\r
7495                         (period == 'M' ? this._get(inst, 'showCurrentAtPos') : 0), // undo positioning\r
7496                         period);\r
7497                 this._updateDatepicker(inst);\r
7498         },\r
7500         /* Action for current link. */\r
7501         _gotoToday: function(id) {\r
7502                 var target = $(id);\r
7503                 var inst = this._getInst(target[0]);\r
7504                 if (this._get(inst, 'gotoCurrent') && inst.currentDay) {\r
7505                         inst.selectedDay = inst.currentDay;\r
7506                         inst.drawMonth = inst.selectedMonth = inst.currentMonth;\r
7507                         inst.drawYear = inst.selectedYear = inst.currentYear;\r
7508                 }\r
7509                 else {\r
7510                         var date = new Date();\r
7511                         inst.selectedDay = date.getDate();\r
7512                         inst.drawMonth = inst.selectedMonth = date.getMonth();\r
7513                         inst.drawYear = inst.selectedYear = date.getFullYear();\r
7514                 }\r
7515                 this._notifyChange(inst);\r
7516                 this._adjustDate(target);\r
7517         },\r
7519         /* Action for selecting a new month/year. */\r
7520         _selectMonthYear: function(id, select, period) {\r
7521                 var target = $(id);\r
7522                 var inst = this._getInst(target[0]);\r
7523                 inst._selectingMonthYear = false;\r
7524                 inst['selected' + (period == 'M' ? 'Month' : 'Year')] =\r
7525                 inst['draw' + (period == 'M' ? 'Month' : 'Year')] =\r
7526                         parseInt(select.options[select.selectedIndex].value,10);\r
7527                 this._notifyChange(inst);\r
7528                 this._adjustDate(target);\r
7529         },\r
7531         /* Restore input focus after not changing month/year. */\r
7532         _clickMonthYear: function(id) {\r
7533                 var target = $(id);\r
7534                 var inst = this._getInst(target[0]);\r
7535                 if (inst.input && inst._selectingMonthYear && !$.browser.msie)\r
7536                         inst.input.focus();\r
7537                 inst._selectingMonthYear = !inst._selectingMonthYear;\r
7538         },\r
7540         /* Action for selecting a day. */\r
7541         _selectDay: function(id, month, year, td) {\r
7542                 var target = $(id);\r
7543                 if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) {\r
7544                         return;\r
7545                 }\r
7546                 var inst = this._getInst(target[0]);\r
7547                 inst.selectedDay = inst.currentDay = $('a', td).html();\r
7548                 inst.selectedMonth = inst.currentMonth = month;\r
7549                 inst.selectedYear = inst.currentYear = year;\r
7550                 this._selectDate(id, this._formatDate(inst,\r
7551                         inst.currentDay, inst.currentMonth, inst.currentYear));\r
7552         },\r
7554         /* Erase the input field and hide the date picker. */\r
7555         _clearDate: function(id) {\r
7556                 var target = $(id);\r
7557                 var inst = this._getInst(target[0]);\r
7558                 this._selectDate(target, '');\r
7559         },\r
7561         /* Update the input field with the selected date. */\r
7562         _selectDate: function(id, dateStr) {\r
7563                 var target = $(id);\r
7564                 var inst = this._getInst(target[0]);\r
7565                 dateStr = (dateStr != null ? dateStr : this._formatDate(inst));\r
7566                 if (inst.input)\r
7567                         inst.input.val(dateStr);\r
7568                 this._updateAlternate(inst);\r
7569                 var onSelect = this._get(inst, 'onSelect');\r
7570                 if (onSelect)\r
7571                         onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);  // trigger custom callback\r
7572                 else if (inst.input)\r
7573                         inst.input.trigger('change'); // fire the change event\r
7574                 if (inst.inline)\r
7575                         this._updateDatepicker(inst);\r
7576                 else {\r
7577                         this._hideDatepicker();\r
7578                         this._lastInput = inst.input[0];\r
7579                         if (typeof(inst.input[0]) != 'object')\r
7580                                 inst.input.focus(); // restore focus\r
7581                         this._lastInput = null;\r
7582                 }\r
7583         },\r
7585         /* Update any alternate field to synchronise with the main field. */\r
7586         _updateAlternate: function(inst) {\r
7587                 var altField = this._get(inst, 'altField');\r
7588                 if (altField) { // update alternate field too\r
7589                         var altFormat = this._get(inst, 'altFormat') || this._get(inst, 'dateFormat');\r
7590                         var date = this._getDate(inst);\r
7591                         var dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst));\r
7592                         $(altField).each(function() { $(this).val(dateStr); });\r
7593                 }\r
7594         },\r
7596         /* Set as beforeShowDay function to prevent selection of weekends.\r
7597            @param  date  Date - the date to customise\r
7598            @return [boolean, string] - is this date selectable?, what is its CSS class? */\r
7599         noWeekends: function(date) {\r
7600                 var day = date.getDay();\r
7601                 return [(day > 0 && day < 6), ''];\r
7602         },\r
7604         /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.\r
7605            @param  date  Date - the date to get the week for\r
7606            @return  number - the number of the week within the year that contains this date */\r
7607         iso8601Week: function(date) {\r
7608                 var checkDate = new Date(date.getTime());\r
7609                 // Find Thursday of this week starting on Monday\r
7610                 checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7));\r
7611                 var time = checkDate.getTime();\r
7612                 checkDate.setMonth(0); // Compare with Jan 1\r
7613                 checkDate.setDate(1);\r
7614                 return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;\r
7615         },\r
7617         /* Parse a string value into a date object.\r
7618            See formatDate below for the possible formats.\r
7620            @param  format    string - the expected format of the date\r
7621            @param  value     string - the date in the above format\r
7622            @param  settings  Object - attributes include:\r
7623                              shortYearCutoff  number - the cutoff year for determining the century (optional)\r
7624                              dayNamesShort    string[7] - abbreviated names of the days from Sunday (optional)\r
7625                              dayNames         string[7] - names of the days from Sunday (optional)\r
7626                              monthNamesShort  string[12] - abbreviated names of the months (optional)\r
7627                              monthNames       string[12] - names of the months (optional)\r
7628            @return  Date - the extracted date value or null if value is blank */\r
7629         parseDate: function (format, value, settings) {\r
7630                 if (format == null || value == null)\r
7631                         throw 'Invalid arguments';\r
7632                 value = (typeof value == 'object' ? value.toString() : value + '');\r
7633                 if (value == '')\r
7634                         return null;\r
7635                 var shortYearCutoff = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff;\r
7636                 var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;\r
7637                 var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;\r
7638                 var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;\r
7639                 var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;\r
7640                 var year = -1;\r
7641                 var month = -1;\r
7642                 var day = -1;\r
7643                 var doy = -1;\r
7644                 var literal = false;\r
7645                 // Check whether a format character is doubled\r
7646                 var lookAhead = function(match) {\r
7647                         var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);\r
7648                         if (matches)\r
7649                                 iFormat++;\r
7650                         return matches;\r
7651                 };\r
7652                 // Extract a number from the string value\r
7653                 var getNumber = function(match) {\r
7654                         lookAhead(match);\r
7655                         var size = (match == '@' ? 14 : (match == '!' ? 20 :\r
7656                                 (match == 'y' ? 4 : (match == 'o' ? 3 : 2))));\r
7657                         var digits = new RegExp('^\\d{1,' + size + '}');\r
7658                         var num = value.substring(iValue).match(digits);\r
7659                         if (!num)\r
7660                                 throw 'Missing number at position ' + iValue;\r
7661                         iValue += num[0].length;\r
7662                         return parseInt(num[0], 10);\r
7663                 };\r
7664                 // Extract a name from the string value and convert to an index\r
7665                 var getName = function(match, shortNames, longNames) {\r
7666                         var names = (lookAhead(match) ? longNames : shortNames);\r
7667                         for (var i = 0; i < names.length; i++) {\r
7668                                 if (value.substr(iValue, names[i].length) == names[i]) {\r
7669                                         iValue += names[i].length;\r
7670                                         return i + 1;\r
7671                                 }\r
7672                         }\r
7673                         throw 'Unknown name at position ' + iValue;\r
7674                 };\r
7675                 // Confirm that a literal character matches the string value\r
7676                 var checkLiteral = function() {\r
7677                         if (value.charAt(iValue) != format.charAt(iFormat))\r
7678                                 throw 'Unexpected literal at position ' + iValue;\r
7679                         iValue++;\r
7680                 };\r
7681                 var iValue = 0;\r
7682                 for (var iFormat = 0; iFormat < format.length; iFormat++) {\r
7683                         if (literal)\r
7684                                 if (format.charAt(iFormat) == "'" && !lookAhead("'"))\r
7685                                         literal = false;\r
7686                                 else\r
7687                                         checkLiteral();\r
7688                         else\r
7689                                 switch (format.charAt(iFormat)) {\r
7690                                         case 'd':\r
7691                                                 day = getNumber('d');\r
7692                                                 break;\r
7693                                         case 'D':\r
7694                                                 getName('D', dayNamesShort, dayNames);\r
7695                                                 break;\r
7696                                         case 'o':\r
7697                                                 doy = getNumber('o');\r
7698                                                 break;\r
7699                                         case 'm':\r
7700                                                 month = getNumber('m');\r
7701                                                 break;\r
7702                                         case 'M':\r
7703                                                 month = getName('M', monthNamesShort, monthNames);\r
7704                                                 break;\r
7705                                         case 'y':\r
7706                                                 year = getNumber('y');\r
7707                                                 break;\r
7708                                         case '@':\r
7709                                                 var date = new Date(getNumber('@'));\r
7710                                                 year = date.getFullYear();\r
7711                                                 month = date.getMonth() + 1;\r
7712                                                 day = date.getDate();\r
7713                                                 break;\r
7714                                         case '!':\r
7715                                                 var date = new Date((getNumber('!') - this._ticksTo1970) / 10000);\r
7716                                                 year = date.getFullYear();\r
7717                                                 month = date.getMonth() + 1;\r
7718                                                 day = date.getDate();\r
7719                                                 break;\r
7720                                         case "'":\r
7721                                                 if (lookAhead("'"))\r
7722                                                         checkLiteral();\r
7723                                                 else\r
7724                                                         literal = true;\r
7725                                                 break;\r
7726                                         default:\r
7727                                                 checkLiteral();\r
7728                                 }\r
7729                 }\r
7730                 if (year == -1)\r
7731                         year = new Date().getFullYear();\r
7732                 else if (year < 100)\r
7733                         year += new Date().getFullYear() - new Date().getFullYear() % 100 +\r
7734                                 (year <= shortYearCutoff ? 0 : -100);\r
7735                 if (doy > -1) {\r
7736                         month = 1;\r
7737                         day = doy;\r
7738                         do {\r
7739                                 var dim = this._getDaysInMonth(year, month - 1);\r
7740                                 if (day <= dim)\r
7741                                         break;\r
7742                                 month++;\r
7743                                 day -= dim;\r
7744                         } while (true);\r
7745                 }\r
7746                 var date = this._daylightSavingAdjust(new Date(year, month - 1, day));\r
7747                 if (date.getFullYear() != year || date.getMonth() + 1 != month || date.getDate() != day)\r
7748                         throw 'Invalid date'; // E.g. 31/02/*\r
7749                 return date;\r
7750         },\r
7752         /* Standard date formats. */\r
7753         ATOM: 'yy-mm-dd', // RFC 3339 (ISO 8601)\r
7754         COOKIE: 'D, dd M yy',\r
7755         ISO_8601: 'yy-mm-dd',\r
7756         RFC_822: 'D, d M y',\r
7757         RFC_850: 'DD, dd-M-y',\r
7758         RFC_1036: 'D, d M y',\r
7759         RFC_1123: 'D, d M yy',\r
7760         RFC_2822: 'D, d M yy',\r
7761         RSS: 'D, d M y', // RFC 822\r
7762         TICKS: '!',\r
7763         TIMESTAMP: '@',\r
7764         W3C: 'yy-mm-dd', // ISO 8601\r
7766         _ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) +\r
7767                 Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000),\r
7769         /* Format a date object into a string value.\r
7770            The format can be combinations of the following:\r
7771            d  - day of month (no leading zero)\r
7772            dd - day of month (two digit)\r
7773            o  - day of year (no leading zeros)\r
7774            oo - day of year (three digit)\r
7775            D  - day name short\r
7776            DD - day name long\r
7777            m  - month of year (no leading zero)\r
7778            mm - month of year (two digit)\r
7779            M  - month name short\r
7780            MM - month name long\r
7781            y  - year (two digit)\r
7782            yy - year (four digit)\r
7783            @ - Unix timestamp (ms since 01/01/1970)\r
7784            ! - Windows ticks (100ns since 01/01/0001)\r
7785            '...' - literal text\r
7786            '' - single quote\r
7788            @param  format    string - the desired format of the date\r
7789            @param  date      Date - the date value to format\r
7790            @param  settings  Object - attributes include:\r
7791                              dayNamesShort    string[7] - abbreviated names of the days from Sunday (optional)\r
7792                              dayNames         string[7] - names of the days from Sunday (optional)\r
7793                              monthNamesShort  string[12] - abbreviated names of the months (optional)\r
7794                              monthNames       string[12] - names of the months (optional)\r
7795            @return  string - the date in the above format */\r
7796         formatDate: function (format, date, settings) {\r
7797                 if (!date)\r
7798                         return '';\r
7799                 var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;\r
7800                 var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;\r
7801                 var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;\r
7802                 var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;\r
7803                 // Check whether a format character is doubled\r
7804                 var lookAhead = function(match) {\r
7805                         var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);\r
7806                         if (matches)\r
7807                                 iFormat++;\r
7808                         return matches;\r
7809                 };\r
7810                 // Format a number, with leading zero if necessary\r
7811                 var formatNumber = function(match, value, len) {\r
7812                         var num = '' + value;\r
7813                         if (lookAhead(match))\r
7814                                 while (num.length < len)\r
7815                                         num = '0' + num;\r
7816                         return num;\r
7817                 };\r
7818                 // Format a name, short or long as requested\r
7819                 var formatName = function(match, value, shortNames, longNames) {\r
7820                         return (lookAhead(match) ? longNames[value] : shortNames[value]);\r
7821                 };\r
7822                 var output = '';\r
7823                 var literal = false;\r
7824                 if (date)\r
7825                         for (var iFormat = 0; iFormat < format.length; iFormat++) {\r
7826                                 if (literal)\r
7827                                         if (format.charAt(iFormat) == "'" && !lookAhead("'"))\r
7828                                                 literal = false;\r
7829                                         else\r
7830                                                 output += format.charAt(iFormat);\r
7831                                 else\r
7832                                         switch (format.charAt(iFormat)) {\r
7833                                                 case 'd':\r
7834                                                         output += formatNumber('d', date.getDate(), 2);\r
7835                                                         break;\r
7836                                                 case 'D':\r
7837                                                         output += formatName('D', date.getDay(), dayNamesShort, dayNames);\r
7838                                                         break;\r
7839                                                 case 'o':\r
7840                                                         output += formatNumber('o',\r
7841                                                                 (date.getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000, 3);\r
7842                                                         break;\r
7843                                                 case 'm':\r
7844                                                         output += formatNumber('m', date.getMonth() + 1, 2);\r
7845                                                         break;\r
7846                                                 case 'M':\r
7847                                                         output += formatName('M', date.getMonth(), monthNamesShort, monthNames);\r
7848                                                         break;\r
7849                                                 case 'y':\r
7850                                                         output += (lookAhead('y') ? date.getFullYear() :\r
7851                                                                 (date.getYear() % 100 < 10 ? '0' : '') + date.getYear() % 100);\r
7852                                                         break;\r
7853                                                 case '@':\r
7854                                                         output += date.getTime();\r
7855                                                         break;\r
7856                                                 case '!':\r
7857                                                         output += date.getTime() * 10000 + this._ticksTo1970;\r
7858                                                         break;\r
7859                                                 case "'":\r
7860                                                         if (lookAhead("'"))\r
7861                                                                 output += "'";\r
7862                                                         else\r
7863                                                                 literal = true;\r
7864                                                         break;\r
7865                                                 default:\r
7866                                                         output += format.charAt(iFormat);\r
7867                                         }\r
7868                         }\r
7869                 return output;\r
7870         },\r
7872         /* Extract all possible characters from the date format. */\r
7873         _possibleChars: function (format) {\r
7874                 var chars = '';\r
7875                 var literal = false;\r
7876                 // Check whether a format character is doubled\r
7877                 var lookAhead = function(match) {\r
7878                         var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);\r
7879                         if (matches)\r
7880                                 iFormat++;\r
7881                         return matches;\r
7882                 };\r
7883                 for (var iFormat = 0; iFormat < format.length; iFormat++)\r
7884                         if (literal)\r
7885                                 if (format.charAt(iFormat) == "'" && !lookAhead("'"))\r
7886                                         literal = false;\r
7887                                 else\r
7888                                         chars += format.charAt(iFormat);\r
7889                         else\r
7890                                 switch (format.charAt(iFormat)) {\r
7891                                         case 'd': case 'm': case 'y': case '@':\r
7892                                                 chars += '0123456789';\r
7893                                                 break;\r
7894                                         case 'D': case 'M':\r
7895                                                 return null; // Accept anything\r
7896                                         case "'":\r
7897                                                 if (lookAhead("'"))\r
7898                                                         chars += "'";\r
7899                                                 else\r
7900                                                         literal = true;\r
7901                                                 break;\r
7902                                         default:\r
7903                                                 chars += format.charAt(iFormat);\r
7904                                 }\r
7905                 return chars;\r
7906         },\r
7908         /* Get a setting value, defaulting if necessary. */\r
7909         _get: function(inst, name) {\r
7910                 return inst.settings[name] !== undefined ?\r
7911                         inst.settings[name] : this._defaults[name];\r
7912         },\r
7914         /* Parse existing date and initialise date picker. */\r
7915         _setDateFromField: function(inst, noDefault) {\r
7916                 if (inst.input.val() == inst.lastVal) {\r
7917                         return;\r
7918                 }\r
7919                 var dateFormat = this._get(inst, 'dateFormat');\r
7920                 var dates = inst.lastVal = inst.input ? inst.input.val() : null;\r
7921                 var date, defaultDate;\r
7922                 date = defaultDate = this._getDefaultDate(inst);\r
7923                 var settings = this._getFormatConfig(inst);\r
7924                 try {\r
7925                         date = this.parseDate(dateFormat, dates, settings) || defaultDate;\r
7926                 } catch (event) {\r
7927                         this.log(event);\r
7928                         dates = (noDefault ? '' : dates);\r
7929                 }\r
7930                 inst.selectedDay = date.getDate();\r
7931                 inst.drawMonth = inst.selectedMonth = date.getMonth();\r
7932                 inst.drawYear = inst.selectedYear = date.getFullYear();\r
7933                 inst.currentDay = (dates ? date.getDate() : 0);\r
7934                 inst.currentMonth = (dates ? date.getMonth() : 0);\r
7935                 inst.currentYear = (dates ? date.getFullYear() : 0);\r
7936                 this._adjustInstDate(inst);\r
7937         },\r
7939         /* Retrieve the default date shown on opening. */\r
7940         _getDefaultDate: function(inst) {\r
7941                 return this._restrictMinMax(inst,\r
7942                         this._determineDate(inst, this._get(inst, 'defaultDate'), new Date()));\r
7943         },\r
7945         /* A date may be specified as an exact value or a relative one. */\r
7946         _determineDate: function(inst, date, defaultDate) {\r
7947                 var offsetNumeric = function(offset) {\r
7948                         var date = new Date();\r
7949                         date.setDate(date.getDate() + offset);\r
7950                         return date;\r
7951                 };\r
7952                 var offsetString = function(offset) {\r
7953                         try {\r
7954                                 return $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),\r
7955                                         offset, $.datepicker._getFormatConfig(inst));\r
7956                         }\r
7957                         catch (e) {\r
7958                                 // Ignore\r
7959                         }\r
7960                         var date = (offset.toLowerCase().match(/^c/) ?\r
7961                                 $.datepicker._getDate(inst) : null) || new Date();\r
7962                         var year = date.getFullYear();\r
7963                         var month = date.getMonth();\r
7964                         var day = date.getDate();\r
7965                         var pattern = /([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g;\r
7966                         var matches = pattern.exec(offset);\r
7967                         while (matches) {\r
7968                                 switch (matches[2] || 'd') {\r
7969                                         case 'd' : case 'D' :\r
7970                                                 day += parseInt(matches[1],10); break;\r
7971                                         case 'w' : case 'W' :\r
7972                                                 day += parseInt(matches[1],10) * 7; break;\r
7973                                         case 'm' : case 'M' :\r
7974                                                 month += parseInt(matches[1],10);\r
7975                                                 day = Math.min(day, $.datepicker._getDaysInMonth(year, month));\r
7976                                                 break;\r
7977                                         case 'y': case 'Y' :\r
7978                                                 year += parseInt(matches[1],10);\r
7979                                                 day = Math.min(day, $.datepicker._getDaysInMonth(year, month));\r
7980                                                 break;\r
7981                                 }\r
7982                                 matches = pattern.exec(offset);\r
7983                         }\r
7984                         return new Date(year, month, day);\r
7985                 };\r
7986                 date = (date == null ? defaultDate : (typeof date == 'string' ? offsetString(date) :\r
7987                         (typeof date == 'number' ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : date)));\r
7988                 date = (date && date.toString() == 'Invalid Date' ? defaultDate : date);\r
7989                 if (date) {\r
7990                         date.setHours(0);\r
7991                         date.setMinutes(0);\r
7992                         date.setSeconds(0);\r
7993                         date.setMilliseconds(0);\r
7994                 }\r
7995                 return this._daylightSavingAdjust(date);\r
7996         },\r
7998         /* Handle switch to/from daylight saving.\r
7999            Hours may be non-zero on daylight saving cut-over:\r
8000            > 12 when midnight changeover, but then cannot generate\r
8001            midnight datetime, so jump to 1AM, otherwise reset.\r
8002            @param  date  (Date) the date to check\r
8003            @return  (Date) the corrected date */\r
8004         _daylightSavingAdjust: function(date) {\r
8005                 if (!date) return null;\r
8006                 date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);\r
8007                 return date;\r
8008         },\r
8010         /* Set the date(s) directly. */\r
8011         _setDate: function(inst, date, noChange) {\r
8012                 var clear = !(date);\r
8013                 var origMonth = inst.selectedMonth;\r
8014                 var origYear = inst.selectedYear;\r
8015                 date = this._restrictMinMax(inst, this._determineDate(inst, date, new Date()));\r
8016                 inst.selectedDay = inst.currentDay = date.getDate();\r
8017                 inst.drawMonth = inst.selectedMonth = inst.currentMonth = date.getMonth();\r
8018                 inst.drawYear = inst.selectedYear = inst.currentYear = date.getFullYear();\r
8019                 if ((origMonth != inst.selectedMonth || origYear != inst.selectedYear) && !noChange)\r
8020                         this._notifyChange(inst);\r
8021                 this._adjustInstDate(inst);\r
8022                 if (inst.input) {\r
8023                         inst.input.val(clear ? '' : this._formatDate(inst));\r
8024                 }\r
8025         },\r
8027         /* Retrieve the date(s) directly. */\r
8028         _getDate: function(inst) {\r
8029                 var startDate = (!inst.currentYear || (inst.input && inst.input.val() == '') ? null :\r
8030                         this._daylightSavingAdjust(new Date(\r
8031                         inst.currentYear, inst.currentMonth, inst.currentDay)));\r
8032                         return startDate;\r
8033         },\r
8035         /* Generate the HTML for the current state of the date picker. */\r
8036         _generateHTML: function(inst) {\r
8037                 var today = new Date();\r
8038                 today = this._daylightSavingAdjust(\r
8039                         new Date(today.getFullYear(), today.getMonth(), today.getDate())); // clear time\r
8040                 var isRTL = this._get(inst, 'isRTL');\r
8041                 var showButtonPanel = this._get(inst, 'showButtonPanel');\r
8042                 var hideIfNoPrevNext = this._get(inst, 'hideIfNoPrevNext');\r
8043                 var navigationAsDateFormat = this._get(inst, 'navigationAsDateFormat');\r
8044                 var numMonths = this._getNumberOfMonths(inst);\r
8045                 var showCurrentAtPos = this._get(inst, 'showCurrentAtPos');\r
8046                 var stepMonths = this._get(inst, 'stepMonths');\r
8047                 var isMultiMonth = (numMonths[0] != 1 || numMonths[1] != 1);\r
8048                 var currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) :\r
8049                         new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));\r
8050                 var minDate = this._getMinMaxDate(inst, 'min');\r
8051                 var maxDate = this._getMinMaxDate(inst, 'max');\r
8052                 var drawMonth = inst.drawMonth - showCurrentAtPos;\r
8053                 var drawYear = inst.drawYear;\r
8054                 if (drawMonth < 0) {\r
8055                         drawMonth += 12;\r
8056                         drawYear--;\r
8057                 }\r
8058                 if (maxDate) {\r
8059                         var maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),\r
8060                                 maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate()));\r
8061                         maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);\r
8062                         while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {\r
8063                                 drawMonth--;\r
8064                                 if (drawMonth < 0) {\r
8065                                         drawMonth = 11;\r
8066                                         drawYear--;\r
8067                                 }\r
8068                         }\r
8069                 }\r
8070                 inst.drawMonth = drawMonth;\r
8071                 inst.drawYear = drawYear;\r
8072                 var prevText = this._get(inst, 'prevText');\r
8073                 prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText,\r
8074                         this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),\r
8075                         this._getFormatConfig(inst)));\r
8076                 var prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?\r
8077                         '<a class="ui-datepicker-prev ui-corner-all" onclick="DP_jQuery_' + dpuuid +\r
8078                         '.datepicker._adjustDate(\'#' + inst.id + '\', -' + stepMonths + ', \'M\');"' +\r
8079                         ' title="' + prevText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>' :\r
8080                         (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>'));\r
8081                 var nextText = this._get(inst, 'nextText');\r
8082                 nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText,\r
8083                         this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),\r
8084                         this._getFormatConfig(inst)));\r
8085                 var next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?\r
8086                         '<a class="ui-datepicker-next ui-corner-all" onclick="DP_jQuery_' + dpuuid +\r
8087                         '.datepicker._adjustDate(\'#' + inst.id + '\', +' + stepMonths + ', \'M\');"' +\r
8088                         ' title="' + nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>' :\r
8089                         (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>'));\r
8090                 var currentText = this._get(inst, 'currentText');\r
8091                 var gotoDate = (this._get(inst, 'gotoCurrent') && inst.currentDay ? currentDate : today);\r
8092                 currentText = (!navigationAsDateFormat ? currentText :\r
8093                         this.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));\r
8094                 var controls = (!inst.inline ? '<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" onclick="DP_jQuery_' + dpuuid +\r
8095                         '.datepicker._hideDatepicker();">' + this._get(inst, 'closeText') + '</button>' : '');\r
8096                 var buttonPanel = (showButtonPanel) ? '<div class="ui-datepicker-buttonpane ui-widget-content">' + (isRTL ? controls : '') +\r
8097                         (this._isInRange(inst, gotoDate) ? '<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" onclick="DP_jQuery_' + dpuuid +\r
8098                         '.datepicker._gotoToday(\'#' + inst.id + '\');"' +\r
8099                         '>' + currentText + '</button>' : '') + (isRTL ? '' : controls) + '</div>' : '';\r
8100                 var firstDay = parseInt(this._get(inst, 'firstDay'),10);\r
8101                 firstDay = (isNaN(firstDay) ? 0 : firstDay);\r
8102                 var showWeek = this._get(inst, 'showWeek');\r
8103                 var dayNames = this._get(inst, 'dayNames');\r
8104                 var dayNamesShort = this._get(inst, 'dayNamesShort');\r
8105                 var dayNamesMin = this._get(inst, 'dayNamesMin');\r
8106                 var monthNames = this._get(inst, 'monthNames');\r
8107                 var monthNamesShort = this._get(inst, 'monthNamesShort');\r
8108                 var beforeShowDay = this._get(inst, 'beforeShowDay');\r
8109                 var showOtherMonths = this._get(inst, 'showOtherMonths');\r
8110                 var selectOtherMonths = this._get(inst, 'selectOtherMonths');\r
8111                 var calculateWeek = this._get(inst, 'calculateWeek') || this.iso8601Week;\r
8112                 var defaultDate = this._getDefaultDate(inst);\r
8113                 var html = '';\r
8114                 for (var row = 0; row < numMonths[0]; row++) {\r
8115                         var group = '';\r
8116                         for (var col = 0; col < numMonths[1]; col++) {\r
8117                                 var selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay));\r
8118                                 var cornerClass = ' ui-corner-all';\r
8119                                 var calender = '';\r
8120                                 if (isMultiMonth) {\r
8121                                         calender += '<div class="ui-datepicker-group';\r
8122                                         if (numMonths[1] > 1)\r
8123                                                 switch (col) {\r
8124                                                         case 0: calender += ' ui-datepicker-group-first';\r
8125                                                                 cornerClass = ' ui-corner-' + (isRTL ? 'right' : 'left'); break;\r
8126                                                         case numMonths[1]-1: calender += ' ui-datepicker-group-last';\r
8127                                                                 cornerClass = ' ui-corner-' + (isRTL ? 'left' : 'right'); break;\r
8128                                                         default: calender += ' ui-datepicker-group-middle'; cornerClass = ''; break;\r
8129                                                 }\r
8130                                         calender += '">';\r
8131                                 }\r
8132                                 calender += '<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix' + cornerClass + '">' +\r
8133                                         (/all|left/.test(cornerClass) && row == 0 ? (isRTL ? next : prev) : '') +\r
8134                                         (/all|right/.test(cornerClass) && row == 0 ? (isRTL ? prev : next) : '') +\r
8135                                         this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,\r
8136                                         row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers\r
8137                                         '</div><table class="ui-datepicker-calendar"><thead>' +\r
8138                                         '<tr>';\r
8139                                 var thead = (showWeek ? '<th class="ui-datepicker-week-col">' + this._get(inst, 'weekHeader') + '</th>' : '');\r
8140                                 for (var dow = 0; dow < 7; dow++) { // days of the week\r
8141                                         var day = (dow + firstDay) % 7;\r
8142                                         thead += '<th' + ((dow + firstDay + 6) % 7 >= 5 ? ' class="ui-datepicker-week-end"' : '') + '>' +\r
8143                                                 '<span title="' + dayNames[day] + '">' + dayNamesMin[day] + '</span></th>';\r
8144                                 }\r
8145                                 calender += thead + '</tr></thead><tbody>';\r
8146                                 var daysInMonth = this._getDaysInMonth(drawYear, drawMonth);\r
8147                                 if (drawYear == inst.selectedYear && drawMonth == inst.selectedMonth)\r
8148                                         inst.selectedDay = Math.min(inst.selectedDay, daysInMonth);\r
8149                                 var leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;\r
8150                                 var numRows = (isMultiMonth ? 6 : Math.ceil((leadDays + daysInMonth) / 7)); // calculate the number of rows to generate\r
8151                                 var printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));\r
8152                                 for (var dRow = 0; dRow < numRows; dRow++) { // create date picker rows\r
8153                                         calender += '<tr>';\r
8154                                         var tbody = (!showWeek ? '' : '<td class="ui-datepicker-week-col">' +\r
8155                                                 this._get(inst, 'calculateWeek')(printDate) + '</td>');\r
8156                                         for (var dow = 0; dow < 7; dow++) { // create date picker days\r
8157                                                 var daySettings = (beforeShowDay ?\r
8158                                                         beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, '']);\r
8159                                                 var otherMonth = (printDate.getMonth() != drawMonth);\r
8160                                                 var unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] ||\r
8161                                                         (minDate && printDate < minDate) || (maxDate && printDate > maxDate);\r
8162                                                 tbody += '<td class="' +\r
8163                                                         ((dow + firstDay + 6) % 7 >= 5 ? ' ui-datepicker-week-end' : '') + // highlight weekends\r
8164                                                         (otherMonth ? ' ui-datepicker-other-month' : '') + // highlight days from other months\r
8165                                                         ((printDate.getTime() == selectedDate.getTime() && drawMonth == inst.selectedMonth && inst._keyEvent) || // user pressed key\r
8166                                                         (defaultDate.getTime() == printDate.getTime() && defaultDate.getTime() == selectedDate.getTime()) ?\r
8167                                                         // or defaultDate is current printedDate and defaultDate is selectedDate\r
8168                                                         ' ' + this._dayOverClass : '') + // highlight selected day\r
8169                                                         (unselectable ? ' ' + this._unselectableClass + ' ui-state-disabled': '') +  // highlight unselectable days\r
8170                                                         (otherMonth && !showOtherMonths ? '' : ' ' + daySettings[1] + // highlight custom dates\r
8171                                                         (printDate.getTime() == currentDate.getTime() ? ' ' + this._currentClass : '') + // highlight selected day\r
8172                                                         (printDate.getTime() == today.getTime() ? ' ui-datepicker-today' : '')) + '"' + // highlight today (if different)\r
8173                                                         ((!otherMonth || showOtherMonths) && daySettings[2] ? ' title="' + daySettings[2] + '"' : '') + // cell title\r
8174                                                         (unselectable ? '' : ' onclick="DP_jQuery_' + dpuuid + '.datepicker._selectDay(\'#' +\r
8175                                                         inst.id + '\',' + printDate.getMonth() + ',' + printDate.getFullYear() + ', this);return false;"') + '>' + // actions\r
8176                                                         (otherMonth && !showOtherMonths ? '&#xa0;' : // display for other months\r
8177                                                         (unselectable ? '<span class="ui-state-default">' + printDate.getDate() + '</span>' : '<a class="ui-state-default' +\r
8178                                                         (printDate.getTime() == today.getTime() ? ' ui-state-highlight' : '') +\r
8179                                                         (printDate.getTime() == currentDate.getTime() ? ' ui-state-active' : '') + // highlight selected day\r
8180                                                         (otherMonth ? ' ui-priority-secondary' : '') + // distinguish dates from other months\r
8181                                                         '" href="#">' + printDate.getDate() + '</a>')) + '</td>'; // display selectable date\r
8182                                                 printDate.setDate(printDate.getDate() + 1);\r
8183                                                 printDate = this._daylightSavingAdjust(printDate);\r
8184                                         }\r
8185                                         calender += tbody + '</tr>';\r
8186                                 }\r
8187                                 drawMonth++;\r
8188                                 if (drawMonth > 11) {\r
8189                                         drawMonth = 0;\r
8190                                         drawYear++;\r
8191                                 }\r
8192                                 calender += '</tbody></table>' + (isMultiMonth ? '</div>' + \r
8193                                                         ((numMonths[0] > 0 && col == numMonths[1]-1) ? '<div class="ui-datepicker-row-break"></div>' : '') : '');\r
8194                                 group += calender;\r
8195                         }\r
8196                         html += group;\r
8197                 }\r
8198                 html += buttonPanel + ($.browser.msie && parseInt($.browser.version,10) < 7 && !inst.inline ?\r
8199                         '<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>' : '');\r
8200                 inst._keyEvent = false;\r
8201                 return html;\r
8202         },\r
8204         /* Generate the month and year header. */\r
8205         _generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate,\r
8206                         secondary, monthNames, monthNamesShort) {\r
8207                 var changeMonth = this._get(inst, 'changeMonth');\r
8208                 var changeYear = this._get(inst, 'changeYear');\r
8209                 var showMonthAfterYear = this._get(inst, 'showMonthAfterYear');\r
8210                 var html = '<div class="ui-datepicker-title">';\r
8211                 var monthHtml = '';\r
8212                 // month selection\r
8213                 if (secondary || !changeMonth)\r
8214                         monthHtml += '<span class="ui-datepicker-month">' + monthNames[drawMonth] + '</span>';\r
8215                 else {\r
8216                         var inMinYear = (minDate && minDate.getFullYear() == drawYear);\r
8217                         var inMaxYear = (maxDate && maxDate.getFullYear() == drawYear);\r
8218                         monthHtml += '<select class="ui-datepicker-month" ' +\r
8219                                 'onchange="DP_jQuery_' + dpuuid + '.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'M\');" ' +\r
8220                                 'onclick="DP_jQuery_' + dpuuid + '.datepicker._clickMonthYear(\'#' + inst.id + '\');"' +\r
8221                                 '>';\r
8222                         for (var month = 0; month < 12; month++) {\r
8223                                 if ((!inMinYear || month >= minDate.getMonth()) &&\r
8224                                                 (!inMaxYear || month <= maxDate.getMonth()))\r
8225                                         monthHtml += '<option value="' + month + '"' +\r
8226                                                 (month == drawMonth ? ' selected="selected"' : '') +\r
8227                                                 '>' + monthNamesShort[month] + '</option>';\r
8228                         }\r
8229                         monthHtml += '</select>';\r
8230                 }\r
8231                 if (!showMonthAfterYear)\r
8232                         html += monthHtml + (secondary || !(changeMonth && changeYear) ? '&#xa0;' : '');\r
8233                 // year selection\r
8234                 if (secondary || !changeYear)\r
8235                         html += '<span class="ui-datepicker-year">' + drawYear + '</span>';\r
8236                 else {\r
8237                         // determine range of years to display\r
8238                         var years = this._get(inst, 'yearRange').split(':');\r
8239                         var thisYear = new Date().getFullYear();\r
8240                         var determineYear = function(value) {\r
8241                                 var year = (value.match(/c[+-].*/) ? drawYear + parseInt(value.substring(1), 10) :\r
8242                                         (value.match(/[+-].*/) ? thisYear + parseInt(value, 10) :\r
8243                                         parseInt(value, 10)));\r
8244                                 return (isNaN(year) ? thisYear : year);\r
8245                         };\r
8246                         var year = determineYear(years[0]);\r
8247                         var endYear = Math.max(year, determineYear(years[1] || ''));\r
8248                         year = (minDate ? Math.max(year, minDate.getFullYear()) : year);\r
8249                         endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);\r
8250                         html += '<select class="ui-datepicker-year" ' +\r
8251                                 'onchange="DP_jQuery_' + dpuuid + '.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'Y\');" ' +\r
8252                                 'onclick="DP_jQuery_' + dpuuid + '.datepicker._clickMonthYear(\'#' + inst.id + '\');"' +\r
8253                                 '>';\r
8254                         for (; year <= endYear; year++) {\r
8255                                 html += '<option value="' + year + '"' +\r
8256                                         (year == drawYear ? ' selected="selected"' : '') +\r
8257                                         '>' + year + '</option>';\r
8258                         }\r
8259                         html += '</select>';\r
8260                 }\r
8261                 html += this._get(inst, 'yearSuffix');\r
8262                 if (showMonthAfterYear)\r
8263                         html += (secondary || !(changeMonth && changeYear) ? '&#xa0;' : '') + monthHtml;\r
8264                 html += '</div>'; // Close datepicker_header\r
8265                 return html;\r
8266         },\r
8268         /* Adjust one of the date sub-fields. */\r
8269         _adjustInstDate: function(inst, offset, period) {\r
8270                 var year = inst.drawYear + (period == 'Y' ? offset : 0);\r
8271                 var month = inst.drawMonth + (period == 'M' ? offset : 0);\r
8272                 var day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) +\r
8273                         (period == 'D' ? offset : 0);\r
8274                 var date = this._restrictMinMax(inst,\r
8275                         this._daylightSavingAdjust(new Date(year, month, day)));\r
8276                 inst.selectedDay = date.getDate();\r
8277                 inst.drawMonth = inst.selectedMonth = date.getMonth();\r
8278                 inst.drawYear = inst.selectedYear = date.getFullYear();\r
8279                 if (period == 'M' || period == 'Y')\r
8280                         this._notifyChange(inst);\r
8281         },\r
8283         /* Ensure a date is within any min/max bounds. */\r
8284         _restrictMinMax: function(inst, date) {\r
8285                 var minDate = this._getMinMaxDate(inst, 'min');\r
8286                 var maxDate = this._getMinMaxDate(inst, 'max');\r
8287                 date = (minDate && date < minDate ? minDate : date);\r
8288                 date = (maxDate && date > maxDate ? maxDate : date);\r
8289                 return date;\r
8290         },\r
8292         /* Notify change of month/year. */\r
8293         _notifyChange: function(inst) {\r
8294                 var onChange = this._get(inst, 'onChangeMonthYear');\r
8295                 if (onChange)\r
8296                         onChange.apply((inst.input ? inst.input[0] : null),\r
8297                                 [inst.selectedYear, inst.selectedMonth + 1, inst]);\r
8298         },\r
8300         /* Determine the number of months to show. */\r
8301         _getNumberOfMonths: function(inst) {\r
8302                 var numMonths = this._get(inst, 'numberOfMonths');\r
8303                 return (numMonths == null ? [1, 1] : (typeof numMonths == 'number' ? [1, numMonths] : numMonths));\r
8304         },\r
8306         /* Determine the current maximum date - ensure no time components are set. */\r
8307         _getMinMaxDate: function(inst, minMax) {\r
8308                 return this._determineDate(inst, this._get(inst, minMax + 'Date'), null);\r
8309         },\r
8311         /* Find the number of days in a given month. */\r
8312         _getDaysInMonth: function(year, month) {\r
8313                 return 32 - new Date(year, month, 32).getDate();\r
8314         },\r
8316         /* Find the day of the week of the first of a month. */\r
8317         _getFirstDayOfMonth: function(year, month) {\r
8318                 return new Date(year, month, 1).getDay();\r
8319         },\r
8321         /* Determines if we should allow a "next/prev" month display change. */\r
8322         _canAdjustMonth: function(inst, offset, curYear, curMonth) {\r
8323                 var numMonths = this._getNumberOfMonths(inst);\r
8324                 var date = this._daylightSavingAdjust(new Date(curYear,\r
8325                         curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1));\r
8326                 if (offset < 0)\r
8327                         date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));\r
8328                 return this._isInRange(inst, date);\r
8329         },\r
8331         /* Is the given date in the accepted range? */\r
8332         _isInRange: function(inst, date) {\r
8333                 var minDate = this._getMinMaxDate(inst, 'min');\r
8334                 var maxDate = this._getMinMaxDate(inst, 'max');\r
8335                 return ((!minDate || date.getTime() >= minDate.getTime()) &&\r
8336                         (!maxDate || date.getTime() <= maxDate.getTime()));\r
8337         },\r
8339         /* Provide the configuration settings for formatting/parsing. */\r
8340         _getFormatConfig: function(inst) {\r
8341                 var shortYearCutoff = this._get(inst, 'shortYearCutoff');\r
8342                 shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff :\r
8343                         new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));\r
8344                 return {shortYearCutoff: shortYearCutoff,\r
8345                         dayNamesShort: this._get(inst, 'dayNamesShort'), dayNames: this._get(inst, 'dayNames'),\r
8346                         monthNamesShort: this._get(inst, 'monthNamesShort'), monthNames: this._get(inst, 'monthNames')};\r
8347         },\r
8349         /* Format the given date for display. */\r
8350         _formatDate: function(inst, day, month, year) {\r
8351                 if (!day) {\r
8352                         inst.currentDay = inst.selectedDay;\r
8353                         inst.currentMonth = inst.selectedMonth;\r
8354                         inst.currentYear = inst.selectedYear;\r
8355                 }\r
8356                 var date = (day ? (typeof day == 'object' ? day :\r
8357                         this._daylightSavingAdjust(new Date(year, month, day))) :\r
8358                         this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));\r
8359                 return this.formatDate(this._get(inst, 'dateFormat'), date, this._getFormatConfig(inst));\r
8360         }\r
8361 });\r
8363 /* jQuery extend now ignores nulls! */\r
8364 function extendRemove(target, props) {\r
8365         $.extend(target, props);\r
8366         for (var name in props)\r
8367                 if (props[name] == null || props[name] == undefined)\r
8368                         target[name] = props[name];\r
8369         return target;\r
8370 };\r
8372 /* Determine whether an object is an array. */\r
8373 function isArray(a) {\r
8374         return (a && (($.browser.safari && typeof a == 'object' && a.length) ||\r
8375                 (a.constructor && a.constructor.toString().match(/\Array\(\)/))));\r
8376 };\r
8378 /* Invoke the datepicker functionality.\r
8379    @param  options  string - a command, optionally followed by additional parameters or\r
8380                     Object - settings for attaching new datepicker functionality\r
8381    @return  jQuery object */\r
8382 $.fn.datepicker = function(options){\r
8384         /* Initialise the date picker. */\r
8385         if (!$.datepicker.initialized) {\r
8386                 $(document).mousedown($.datepicker._checkExternalClick).\r
8387                         find('body').append($.datepicker.dpDiv);\r
8388                 $.datepicker.initialized = true;\r
8389         }\r
8391         var otherArgs = Array.prototype.slice.call(arguments, 1);\r
8392         if (typeof options == 'string' && (options == 'isDisabled' || options == 'getDate' || options == 'widget'))\r
8393                 return $.datepicker['_' + options + 'Datepicker'].\r
8394                         apply($.datepicker, [this[0]].concat(otherArgs));\r
8395         if (options == 'option' && arguments.length == 2 && typeof arguments[1] == 'string')\r
8396                 return $.datepicker['_' + options + 'Datepicker'].\r
8397                         apply($.datepicker, [this[0]].concat(otherArgs));\r
8398         return this.each(function() {\r
8399                 typeof options == 'string' ?\r
8400                         $.datepicker['_' + options + 'Datepicker'].\r
8401                                 apply($.datepicker, [this].concat(otherArgs)) :\r
8402                         $.datepicker._attachDatepicker(this, options);\r
8403         });\r
8404 };\r
8406 $.datepicker = new Datepicker(); // singleton instance\r
8407 $.datepicker.initialized = false;\r
8408 $.datepicker.uuid = new Date().getTime();\r
8409 $.datepicker.version = "1.8";\r
8411 // Workaround for #4055\r
8412 // Add another global to avoid noConflict issues with inline event handlers\r
8413 window['DP_jQuery_' + dpuuid] = $;\r
8415 })(jQuery);\r
8416 /*\r
8417  * jQuery UI Dialog 1.8\r
8418  *\r
8419  * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)\r
8420  * Dual licensed under the MIT (MIT-LICENSE.txt)\r
8421  * and GPL (GPL-LICENSE.txt) licenses.\r
8422  *\r
8423  * http://docs.jquery.com/UI/Dialog\r
8424  *\r
8425  * Depends:\r
8426  *      jquery.ui.core.js\r
8427  *      jquery.ui.widget.js\r
8428  *  jquery.ui.button.js\r
8429  *      jquery.ui.draggable.js\r
8430  *      jquery.ui.mouse.js\r
8431  *      jquery.ui.position.js\r
8432  *      jquery.ui.resizable.js\r
8433  */\r
8434 (function($) {\r
8436 var uiDialogClasses =\r
8437         'ui-dialog ' +\r
8438         'ui-widget ' +\r
8439         'ui-widget-content ' +\r
8440         'ui-corner-all ';\r
8442 $.widget("ui.dialog", {\r
8443         options: {\r
8444                 autoOpen: true,\r
8445                 buttons: {},\r
8446                 closeOnEscape: true,\r
8447                 closeText: 'close',\r
8448                 dialogClass: '',\r
8449                 draggable: true,\r
8450                 hide: null,\r
8451                 height: 'auto',\r
8452                 maxHeight: false,\r
8453                 maxWidth: false,\r
8454                 minHeight: 150,\r
8455                 minWidth: 150,\r
8456                 modal: false,\r
8457                 position: 'center',\r
8458                 resizable: true,\r
8459                 show: null,\r
8460                 stack: true,\r
8461                 title: '',\r
8462                 width: 300,\r
8463                 zIndex: 1000\r
8464         },\r
8465         _create: function() {\r
8466                 this.originalTitle = this.element.attr('title');\r
8468                 var self = this,\r
8469                         options = self.options,\r
8471                         title = options.title || self.originalTitle || '&#160;',\r
8472                         titleId = $.ui.dialog.getTitleId(self.element),\r
8474                         uiDialog = (self.uiDialog = $('<div></div>'))\r
8475                                 .appendTo(document.body)\r
8476                                 .hide()\r
8477                                 .addClass(uiDialogClasses + options.dialogClass)\r
8478                                 .css({\r
8479                                         zIndex: options.zIndex\r
8480                                 })\r
8481                                 // setting tabIndex makes the div focusable\r
8482                                 // setting outline to 0 prevents a border on focus in Mozilla\r
8483                                 .attr('tabIndex', -1).css('outline', 0).keydown(function(event) {\r
8484                                         if (options.closeOnEscape && event.keyCode &&\r
8485                                                 event.keyCode === $.ui.keyCode.ESCAPE) {\r
8486                                                 \r
8487                                                 self.close(event);\r
8488                                                 event.preventDefault();\r
8489                                         }\r
8490                                 })\r
8491                                 .attr({\r
8492                                         role: 'dialog',\r
8493                                         'aria-labelledby': titleId\r
8494                                 })\r
8495                                 .mousedown(function(event) {\r
8496                                         self.moveToTop(false, event);\r
8497                                 }),\r
8499                         uiDialogContent = self.element\r
8500                                 .show()\r
8501                                 .removeAttr('title')\r
8502                                 .addClass(\r
8503                                         'ui-dialog-content ' +\r
8504                                         'ui-widget-content')\r
8505                                 .appendTo(uiDialog),\r
8507                         uiDialogTitlebar = (self.uiDialogTitlebar = $('<div></div>'))\r
8508                                 .addClass(\r
8509                                         'ui-dialog-titlebar ' +\r
8510                                         'ui-widget-header ' +\r
8511                                         'ui-corner-all ' +\r
8512                                         'ui-helper-clearfix'\r
8513                                 )\r
8514                                 .prependTo(uiDialog),\r
8516                         uiDialogTitlebarClose = $('<a href="#"></a>')\r
8517                                 .addClass(\r
8518                                         'ui-dialog-titlebar-close ' +\r
8519                                         'ui-corner-all'\r
8520                                 )\r
8521                                 .attr('role', 'button')\r
8522                                 .hover(\r
8523                                         function() {\r
8524                                                 uiDialogTitlebarClose.addClass('ui-state-hover');\r
8525                                         },\r
8526                                         function() {\r
8527                                                 uiDialogTitlebarClose.removeClass('ui-state-hover');\r
8528                                         }\r
8529                                 )\r
8530                                 .focus(function() {\r
8531                                         uiDialogTitlebarClose.addClass('ui-state-focus');\r
8532                                 })\r
8533                                 .blur(function() {\r
8534                                         uiDialogTitlebarClose.removeClass('ui-state-focus');\r
8535                                 })\r
8536                                 .click(function(event) {\r
8537                                         self.close(event);\r
8538                                         return false;\r
8539                                 })\r
8540                                 .appendTo(uiDialogTitlebar),\r
8542                         uiDialogTitlebarCloseText = (self.uiDialogTitlebarCloseText = $('<span></span>'))\r
8543                                 .addClass(\r
8544                                         'ui-icon ' +\r
8545                                         'ui-icon-closethick'\r
8546                                 )\r
8547                                 .text(options.closeText)\r
8548                                 .appendTo(uiDialogTitlebarClose),\r
8550                         uiDialogTitle = $('<span></span>')\r
8551                                 .addClass('ui-dialog-title')\r
8552                                 .attr('id', titleId)\r
8553                                 .html(title)\r
8554                                 .prependTo(uiDialogTitlebar);\r
8556                 //handling of deprecated beforeclose (vs beforeClose) option\r
8557                 //Ticket #4669 http://dev.jqueryui.com/ticket/4669\r
8558                 //TODO: remove in 1.9pre\r
8559                 if ($.isFunction(options.beforeclose) && !$.isFunction(options.beforeClose)) {\r
8560                         options.beforeClose = options.beforeclose;\r
8561                 }\r
8563                 uiDialogTitlebar.find("*").add(uiDialogTitlebar).disableSelection();\r
8565                 if (options.draggable && $.fn.draggable) {\r
8566                         self._makeDraggable();\r
8567                 }\r
8568                 if (options.resizable && $.fn.resizable) {\r
8569                         self._makeResizable();\r
8570                 }\r
8572                 self._createButtons(options.buttons);\r
8573                 self._isOpen = false;\r
8575                 if ($.fn.bgiframe) {\r
8576                         uiDialog.bgiframe();\r
8577                 }\r
8578         },\r
8579         _init: function() {\r
8580                 if ( this.options.autoOpen ) {\r
8581                         this.open();\r
8582                 }\r
8583         },\r
8585         destroy: function() {\r
8586                 var self = this;\r
8587                 \r
8588                 if (self.overlay) {\r
8589                         self.overlay.destroy();\r
8590                 }\r
8591                 self.uiDialog.hide();\r
8592                 self.element\r
8593                         .unbind('.dialog')\r
8594                         .removeData('dialog')\r
8595                         .removeClass('ui-dialog-content ui-widget-content')\r
8596                         .hide().appendTo('body');\r
8597                 self.uiDialog.remove();\r
8599                 if (self.originalTitle) {\r
8600                         self.element.attr('title', self.originalTitle);\r
8601                 }\r
8603                 return self;\r
8604         },\r
8605         \r
8606         widget: function() {\r
8607                 return this.uiDialog;\r
8608         },\r
8610         close: function(event) {\r
8611                 var self = this,\r
8612                         maxZ;\r
8613                 \r
8614                 if (false === self._trigger('beforeClose', event)) {\r
8615                         return;\r
8616                 }\r
8618                 if (self.overlay) {\r
8619                         self.overlay.destroy();\r
8620                 }\r
8621                 self.uiDialog.unbind('keypress.ui-dialog');\r
8623                 self._isOpen = false;\r
8625                 if (self.options.hide) {\r
8626                         self.uiDialog.hide(self.options.hide, function() {\r
8627                                 self._trigger('close', event);\r
8628                         });\r
8629                 } else {\r
8630                         self.uiDialog.hide();\r
8631                         self._trigger('close', event);\r
8632                 }\r
8634                 $.ui.dialog.overlay.resize();\r
8636                 // adjust the maxZ to allow other modal dialogs to continue to work (see #4309)\r
8637                 if (self.options.modal) {\r
8638                         maxZ = 0;\r
8639                         $('.ui-dialog').each(function() {\r
8640                                 if (this !== self.uiDialog[0]) {\r
8641                                         maxZ = Math.max(maxZ, $(this).css('z-index'));\r
8642                                 }\r
8643                         });\r
8644                         $.ui.dialog.maxZ = maxZ;\r
8645                 }\r
8647                 return self;\r
8648         },\r
8650         isOpen: function() {\r
8651                 return this._isOpen;\r
8652         },\r
8654         // the force parameter allows us to move modal dialogs to their correct\r
8655         // position on open\r
8656         moveToTop: function(force, event) {\r
8657                 var self = this,\r
8658                         options = self.options,\r
8659                         saveScroll;\r
8660                 \r
8661                 if ((options.modal && !force) ||\r
8662                         (!options.stack && !options.modal)) {\r
8663                         return self._trigger('focus', event);\r
8664                 }\r
8665                 \r
8666                 if (options.zIndex > $.ui.dialog.maxZ) {\r
8667                         $.ui.dialog.maxZ = options.zIndex;\r
8668                 }\r
8669                 if (self.overlay) {\r
8670                         $.ui.dialog.maxZ += 1;\r
8671                         self.overlay.$el.css('z-index', $.ui.dialog.overlay.maxZ = $.ui.dialog.maxZ);\r
8672                 }\r
8674                 //Save and then restore scroll since Opera 9.5+ resets when parent z-Index is changed.\r
8675                 //  http://ui.jquery.com/bugs/ticket/3193\r
8676                 saveScroll = { scrollTop: self.element.attr('scrollTop'), scrollLeft: self.element.attr('scrollLeft') };\r
8677                 $.ui.dialog.maxZ += 1;\r
8678                 self.uiDialog.css('z-index', $.ui.dialog.maxZ);\r
8679                 self.element.attr(saveScroll);\r
8680                 self._trigger('focus', event);\r
8682                 return self;\r
8683         },\r
8685         open: function() {\r
8686                 if (this._isOpen) { return; }\r
8688                 var self = this,\r
8689                         options = self.options,\r
8690                         uiDialog = self.uiDialog;\r
8692                 self.overlay = options.modal ? new $.ui.dialog.overlay(self) : null;\r
8693                 if (uiDialog.next().length) {\r
8694                         uiDialog.appendTo('body');\r
8695                 }\r
8696                 self._size();\r
8697                 self._position(options.position);\r
8698                 uiDialog.show(options.show);\r
8699                 self.moveToTop(true);\r
8701                 // prevent tabbing out of modal dialogs\r
8702                 if (options.modal) {\r
8703                         uiDialog.bind('keypress.ui-dialog', function(event) {\r
8704                                 if (event.keyCode !== $.ui.keyCode.TAB) {\r
8705                                         return;\r
8706                                 }\r
8707         \r
8708                                 var tabbables = $(':tabbable', this),\r
8709                                         first = tabbables.filter(':first'),\r
8710                                         last  = tabbables.filter(':last');\r
8711         \r
8712                                 if (event.target === last[0] && !event.shiftKey) {\r
8713                                         first.focus(1);\r
8714                                         return false;\r
8715                                 } else if (event.target === first[0] && event.shiftKey) {\r
8716                                         last.focus(1);\r
8717                                         return false;\r
8718                                 }\r
8719                         });\r
8720                 }\r
8722                 // set focus to the first tabbable element in the content area or the first button\r
8723                 // if there are no tabbable elements, set focus on the dialog itself\r
8724                 $([])\r
8725                         .add(uiDialog.find('.ui-dialog-content :tabbable:first'))\r
8726                         .add(uiDialog.find('.ui-dialog-buttonpane :tabbable:first'))\r
8727                         .add(uiDialog)\r
8728                         .filter(':first')\r
8729                         .focus();\r
8731                 self._trigger('open');\r
8732                 self._isOpen = true;\r
8734                 return self;\r
8735         },\r
8737         _createButtons: function(buttons) {\r
8738                 var self = this,\r
8739                         hasButtons = false,\r
8740                         uiDialogButtonPane = $('<div></div>')\r
8741                                 .addClass(\r
8742                                         'ui-dialog-buttonpane ' +\r
8743                                         'ui-widget-content ' +\r
8744                                         'ui-helper-clearfix'\r
8745                                 );\r
8747                 // if we already have a button pane, remove it\r
8748                 self.uiDialog.find('.ui-dialog-buttonpane').remove();\r
8750                 if (typeof buttons === 'object' && buttons !== null) {\r
8751                         $.each(buttons, function() {\r
8752                                 return !(hasButtons = true);\r
8753                         });\r
8754                 }\r
8755                 if (hasButtons) {\r
8756                         $.each(buttons, function(name, fn) {\r
8757                                 var button = $('<button type="button"></button>')\r
8758                                         .text(name)\r
8759                                         .click(function() { fn.apply(self.element[0], arguments); })\r
8760                                         .appendTo(uiDialogButtonPane);\r
8761                                 if ($.fn.button) {\r
8762                                         button.button();\r
8763                                 }\r
8764                         });\r
8765                         uiDialogButtonPane.appendTo(self.uiDialog);\r
8766                 }\r
8767         },\r
8769         _makeDraggable: function() {\r
8770                 var self = this,\r
8771                         options = self.options,\r
8772                         doc = $(document),\r
8773                         heightBeforeDrag;\r
8775                 function filteredUi(ui) {\r
8776                         return {\r
8777                                 position: ui.position,\r
8778                                 offset: ui.offset\r
8779                         };\r
8780                 }\r
8782                 self.uiDialog.draggable({\r
8783                         cancel: '.ui-dialog-content, .ui-dialog-titlebar-close',\r
8784                         handle: '.ui-dialog-titlebar',\r
8785                         containment: 'document',\r
8786                         start: function(event, ui) {\r
8787                                 heightBeforeDrag = options.height === "auto" ? "auto" : $(this).height();\r
8788                                 $(this).height($(this).height()).addClass("ui-dialog-dragging");\r
8789                                 self._trigger('dragStart', event, filteredUi(ui));\r
8790                         },\r
8791                         drag: function(event, ui) {\r
8792                                 self._trigger('drag', event, filteredUi(ui));\r
8793                         },\r
8794                         stop: function(event, ui) {\r
8795                                 options.position = [ui.position.left - doc.scrollLeft(),\r
8796                                         ui.position.top - doc.scrollTop()];\r
8797                                 $(this).removeClass("ui-dialog-dragging").height(heightBeforeDrag);\r
8798                                 self._trigger('dragStop', event, filteredUi(ui));\r
8799                                 $.ui.dialog.overlay.resize();\r
8800                         }\r
8801                 });\r
8802         },\r
8804         _makeResizable: function(handles) {\r
8805                 handles = (handles === undefined ? this.options.resizable : handles);\r
8806                 var self = this,\r
8807                         options = self.options,\r
8808                         // .ui-resizable has position: relative defined in the stylesheet\r
8809                         // but dialogs have to use absolute or fixed positioning\r
8810                         position = self.uiDialog.css('position'),\r
8811                         resizeHandles = (typeof handles === 'string' ?\r
8812                                 handles :\r
8813                                 'n,e,s,w,se,sw,ne,nw'\r
8814                         );\r
8816                 function filteredUi(ui) {\r
8817                         return {\r
8818                                 originalPosition: ui.originalPosition,\r
8819                                 originalSize: ui.originalSize,\r
8820                                 position: ui.position,\r
8821                                 size: ui.size\r
8822                         };\r
8823                 }\r
8825                 self.uiDialog.resizable({\r
8826                         cancel: '.ui-dialog-content',\r
8827                         containment: 'document',\r
8828                         alsoResize: self.element,\r
8829                         maxWidth: options.maxWidth,\r
8830                         maxHeight: options.maxHeight,\r
8831                         minWidth: options.minWidth,\r
8832                         minHeight: self._minHeight(),\r
8833                         handles: resizeHandles,\r
8834                         start: function(event, ui) {\r
8835                                 $(this).addClass("ui-dialog-resizing");\r
8836                                 self._trigger('resizeStart', event, filteredUi(ui));\r
8837                         },\r
8838                         resize: function(event, ui) {\r
8839                                 self._trigger('resize', event, filteredUi(ui));\r
8840                         },\r
8841                         stop: function(event, ui) {\r
8842                                 $(this).removeClass("ui-dialog-resizing");\r
8843                                 options.height = $(this).height();\r
8844                                 options.width = $(this).width();\r
8845                                 self._trigger('resizeStop', event, filteredUi(ui));\r
8846                                 $.ui.dialog.overlay.resize();\r
8847                         }\r
8848                 })\r
8849                 .css('position', position)\r
8850                 .find('.ui-resizable-se').addClass('ui-icon ui-icon-grip-diagonal-se');\r
8851         },\r
8853         _minHeight: function() {\r
8854                 var options = this.options;\r
8856                 if (options.height === 'auto') {\r
8857                         return options.minHeight;\r
8858                 } else {\r
8859                         return Math.min(options.minHeight, options.height);\r
8860                 }\r
8861         },\r
8863         _position: function(position) {\r
8864                 var myAt = [],\r
8865                         offset = [0, 0],\r
8866                         isVisible;\r
8868                 position = position || $.ui.dialog.prototype.options.position;\r
8870                 // deep extending converts arrays to objects in jQuery <= 1.3.2 :-(\r
8871 //              if (typeof position == 'string' || $.isArray(position)) {\r
8872 //                      myAt = $.isArray(position) ? position : position.split(' ');\r
8874                 if (typeof position === 'string' || (typeof position === 'object' && '0' in position)) {\r
8875                         myAt = position.split ? position.split(' ') : [position[0], position[1]];\r
8876                         if (myAt.length === 1) {\r
8877                                 myAt[1] = myAt[0];\r
8878                         }\r
8880                         $.each(['left', 'top'], function(i, offsetPosition) {\r
8881                                 if (+myAt[i] === myAt[i]) {\r
8882                                         offset[i] = myAt[i];\r
8883                                         myAt[i] = offsetPosition;\r
8884                                 }\r
8885                         });\r
8886                 } else if (typeof position === 'object') {\r
8887                         if ('left' in position) {\r
8888                                 myAt[0] = 'left';\r
8889                                 offset[0] = position.left;\r
8890                         } else if ('right' in position) {\r
8891                                 myAt[0] = 'right';\r
8892                                 offset[0] = -position.right;\r
8893                         }\r
8895                         if ('top' in position) {\r
8896                                 myAt[1] = 'top';\r
8897                                 offset[1] = position.top;\r
8898                         } else if ('bottom' in position) {\r
8899                                 myAt[1] = 'bottom';\r
8900                                 offset[1] = -position.bottom;\r
8901                         }\r
8902                 }\r
8904                 // need to show the dialog to get the actual offset in the position plugin\r
8905                 isVisible = this.uiDialog.is(':visible');\r
8906                 if (!isVisible) {\r
8907                         this.uiDialog.show();\r
8908                 }\r
8909                 this.uiDialog\r
8910                         // workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781\r
8911                         .css({ top: 0, left: 0 })\r
8912                         .position({\r
8913                                 my: myAt.join(' '),\r
8914                                 at: myAt.join(' '),\r
8915                                 offset: offset.join(' '),\r
8916                                 of: window,\r
8917                                 collision: 'fit',\r
8918                                 // ensure that the titlebar is never outside the document\r
8919                                 using: function(pos) {\r
8920                                         var topOffset = $(this).css(pos).offset().top;\r
8921                                         if (topOffset < 0) {\r
8922                                                 $(this).css('top', pos.top - topOffset);\r
8923                                         }\r
8924                                 }\r
8925                         });\r
8926                 if (!isVisible) {\r
8927                         this.uiDialog.hide();\r
8928                 }\r
8929         },\r
8931         _setOption: function(key, value){\r
8932                 var self = this,\r
8933                         uiDialog = self.uiDialog,\r
8934                         isResizable = uiDialog.is(':data(resizable)'),\r
8935                         resize = false;\r
8936                 \r
8937                 switch (key) {\r
8938                         //handling of deprecated beforeclose (vs beforeClose) option\r
8939                         //Ticket #4669 http://dev.jqueryui.com/ticket/4669\r
8940                         //TODO: remove in 1.9pre\r
8941                         case "beforeclose":\r
8942                                 key = "beforeClose";\r
8943                                 break;\r
8944                         case "buttons":\r
8945                                 self._createButtons(value);\r
8946                                 break;\r
8947                         case "closeText":\r
8948                                 // convert whatever was passed in to a string, for text() to not throw up\r
8949                                 self.uiDialogTitlebarCloseText.text("" + value);\r
8950                                 break;\r
8951                         case "dialogClass":\r
8952                                 uiDialog\r
8953                                         .removeClass(self.options.dialogClass)\r
8954                                         .addClass(uiDialogClasses + value);\r
8955                                 break;\r
8956                         case "disabled":\r
8957                                 if (value) {\r
8958                                         uiDialog.addClass('ui-dialog-disabled');\r
8959                                 } else {\r
8960                                         uiDialog.removeClass('ui-dialog-disabled');\r
8961                                 }\r
8962                                 break;\r
8963                         case "draggable":\r
8964                                 if (value) {\r
8965                                         self._makeDraggable();\r
8966                                 } else {\r
8967                                         uiDialog.draggable('destroy');\r
8968                                 }\r
8969                                 break;\r
8970                         case "height":\r
8971                                 resize = true;\r
8972                                 break;\r
8973                         case "maxHeight":\r
8974                                 if (isResizable) {\r
8975                                         uiDialog.resizable('option', 'maxHeight', value);\r
8976                                 }\r
8977                                 resize = true;\r
8978                                 break;\r
8979                         case "maxWidth":\r
8980                                 if (isResizable) {\r
8981                                         uiDialog.resizable('option', 'maxWidth', value);\r
8982                                 }\r
8983                                 resize = true;\r
8984                                 break;\r
8985                         case "minHeight":\r
8986                                 if (isResizable) {\r
8987                                         uiDialog.resizable('option', 'minHeight', value);\r
8988                                 }\r
8989                                 resize = true;\r
8990                                 break;\r
8991                         case "minWidth":\r
8992                                 if (isResizable) {\r
8993                                         uiDialog.resizable('option', 'minWidth', value);\r
8994                                 }\r
8995                                 resize = true;\r
8996                                 break;\r
8997                         case "position":\r
8998                                 self._position(value);\r
8999                                 break;\r
9000                         case "resizable":\r
9001                                 // currently resizable, becoming non-resizable\r
9002                                 if (isResizable && !value) {\r
9003                                         uiDialog.resizable('destroy');\r
9004                                 }\r
9006                                 // currently resizable, changing handles\r
9007                                 if (isResizable && typeof value === 'string') {\r
9008                                         uiDialog.resizable('option', 'handles', value);\r
9009                                 }\r
9011                                 // currently non-resizable, becoming resizable\r
9012                                 if (!isResizable && value !== false) {\r
9013                                         self._makeResizable(value);\r
9014                                 }\r
9015                                 break;\r
9016                         case "title":\r
9017                                 // convert whatever was passed in o a string, for html() to not throw up\r
9018                                 $(".ui-dialog-title", self.uiDialogTitlebar).html("" + (value || '&#160;'));\r
9019                                 break;\r
9020                         case "width":\r
9021                                 resize = true;\r
9022                                 break;\r
9023                 }\r
9025                 $.Widget.prototype._setOption.apply(self, arguments);\r
9026                 if (resize) {\r
9027                         self._size();\r
9028                 }\r
9029         },\r
9031         _size: function() {\r
9032                 /* If the user has resized the dialog, the .ui-dialog and .ui-dialog-content\r
9033                  * divs will both have width and height set, so we need to reset them\r
9034                  */\r
9035                 var options = this.options,\r
9036                         nonContentHeight;\r
9038                 // reset content sizing\r
9039                 // hide for non content measurement because height: 0 doesn't work in IE quirks mode (see #4350)\r
9040                 this.element.css('width', 'auto')\r
9041                         .hide();\r
9043                 // reset wrapper sizing\r
9044                 // determine the height of all the non-content elements\r
9045                 nonContentHeight = this.uiDialog.css({\r
9046                                 height: 'auto',\r
9047                                 width: options.width\r
9048                         })\r
9049                         .height();\r
9051                 this.element\r
9052                         .css(options.height === 'auto' ? {\r
9053                                         minHeight: Math.max(options.minHeight - nonContentHeight, 0),\r
9054                                         height: 'auto'\r
9055                                 } : {\r
9056                                         minHeight: 0,\r
9057                                         height: Math.max(options.height - nonContentHeight, 0)                          \r
9058                         })\r
9059                         .show();\r
9061                 if (this.uiDialog.is(':data(resizable)')) {\r
9062                         this.uiDialog.resizable('option', 'minHeight', this._minHeight());\r
9063                 }\r
9064         }\r
9065 });\r
9067 $.extend($.ui.dialog, {\r
9068         version: "1.8",\r
9070         uuid: 0,\r
9071         maxZ: 0,\r
9073         getTitleId: function($el) {\r
9074                 var id = $el.attr('id');\r
9075                 if (!id) {\r
9076                         this.uuid += 1;\r
9077                         id = this.uuid;\r
9078                 }\r
9079                 return 'ui-dialog-title-' + id;\r
9080         },\r
9082         overlay: function(dialog) {\r
9083                 this.$el = $.ui.dialog.overlay.create(dialog);\r
9084         }\r
9085 });\r
9087 $.extend($.ui.dialog.overlay, {\r
9088         instances: [],\r
9089         // reuse old instances due to IE memory leak with alpha transparency (see #5185)\r
9090         oldInstances: [],\r
9091         maxZ: 0,\r
9092         events: $.map('focus,mousedown,mouseup,keydown,keypress,click'.split(','),\r
9093                 function(event) { return event + '.dialog-overlay'; }).join(' '),\r
9094         create: function(dialog) {\r
9095                 if (this.instances.length === 0) {\r
9096                         // prevent use of anchors and inputs\r
9097                         // we use a setTimeout in case the overlay is created from an\r
9098                         // event that we're going to be cancelling (see #2804)\r
9099                         setTimeout(function() {\r
9100                                 // handle $(el).dialog().dialog('close') (see #4065)\r
9101                                 if ($.ui.dialog.overlay.instances.length) {\r
9102                                         $(document).bind($.ui.dialog.overlay.events, function(event) {\r
9103                                                 // stop events if the z-index of the target is < the z-index of the overlay\r
9104                                                 return ($(event.target).zIndex() >= $.ui.dialog.overlay.maxZ);\r
9105                                         });\r
9106                                 }\r
9107                         }, 1);\r
9109                         // allow closing by pressing the escape key\r
9110                         $(document).bind('keydown.dialog-overlay', function(event) {\r
9111                                 if (dialog.options.closeOnEscape && event.keyCode &&\r
9112                                         event.keyCode === $.ui.keyCode.ESCAPE) {\r
9113                                         \r
9114                                         dialog.close(event);\r
9115                                         event.preventDefault();\r
9116                                 }\r
9117                         });\r
9119                         // handle window resize\r
9120                         $(window).bind('resize.dialog-overlay', $.ui.dialog.overlay.resize);\r
9121                 }\r
9123                 var $el = (this.oldInstances.pop() || $('<div></div>').addClass('ui-widget-overlay'))\r
9124                         .appendTo(document.body)\r
9125                         .css({\r
9126                                 width: this.width(),\r
9127                                 height: this.height()\r
9128                         });\r
9130                 if ($.fn.bgiframe) {\r
9131                         $el.bgiframe();\r
9132                 }\r
9134                 this.instances.push($el);\r
9135                 return $el;\r
9136         },\r
9138         destroy: function($el) {\r
9139                 this.oldInstances.push(this.instances.splice($.inArray($el, this.instances), 1)[0]);\r
9141                 if (this.instances.length === 0) {\r
9142                         $([document, window]).unbind('.dialog-overlay');\r
9143                 }\r
9145                 $el.remove();\r
9146                 \r
9147                 // adjust the maxZ to allow other modal dialogs to continue to work (see #4309)\r
9148                 var maxZ = 0;\r
9149                 $.each(this.instances, function() {\r
9150                         maxZ = Math.max(maxZ, this.css('z-index'));\r
9151                 });\r
9152                 this.maxZ = maxZ;\r
9153         },\r
9155         height: function() {\r
9156                 var scrollHeight,\r
9157                         offsetHeight;\r
9158                 // handle IE 6\r
9159                 if ($.browser.msie && $.browser.version < 7) {\r
9160                         scrollHeight = Math.max(\r
9161                                 document.documentElement.scrollHeight,\r
9162                                 document.body.scrollHeight\r
9163                         );\r
9164                         offsetHeight = Math.max(\r
9165                                 document.documentElement.offsetHeight,\r
9166                                 document.body.offsetHeight\r
9167                         );\r
9169                         if (scrollHeight < offsetHeight) {\r
9170                                 return $(window).height() + 'px';\r
9171                         } else {\r
9172                                 return scrollHeight + 'px';\r
9173                         }\r
9174                 // handle "good" browsers\r
9175                 } else {\r
9176                         return $(document).height() + 'px';\r
9177                 }\r
9178         },\r
9180         width: function() {\r
9181                 var scrollWidth,\r
9182                         offsetWidth;\r
9183                 // handle IE 6\r
9184                 if ($.browser.msie && $.browser.version < 7) {\r
9185                         scrollWidth = Math.max(\r
9186                                 document.documentElement.scrollWidth,\r
9187                                 document.body.scrollWidth\r
9188                         );\r
9189                         offsetWidth = Math.max(\r
9190                                 document.documentElement.offsetWidth,\r
9191                                 document.body.offsetWidth\r
9192                         );\r
9194                         if (scrollWidth < offsetWidth) {\r
9195                                 return $(window).width() + 'px';\r
9196                         } else {\r
9197                                 return scrollWidth + 'px';\r
9198                         }\r
9199                 // handle "good" browsers\r
9200                 } else {\r
9201                         return $(document).width() + 'px';\r
9202                 }\r
9203         },\r
9205         resize: function() {\r
9206                 /* If the dialog is draggable and the user drags it past the\r
9207                  * right edge of the window, the document becomes wider so we\r
9208                  * need to stretch the overlay. If the user then drags the\r
9209                  * dialog back to the left, the document will become narrower,\r
9210                  * so we need to shrink the overlay to the appropriate size.\r
9211                  * This is handled by shrinking the overlay before setting it\r
9212                  * to the full document size.\r
9213                  */\r
9214                 var $overlays = $([]);\r
9215                 $.each($.ui.dialog.overlay.instances, function() {\r
9216                         $overlays = $overlays.add(this);\r
9217                 });\r
9219                 $overlays.css({\r
9220                         width: 0,\r
9221                         height: 0\r
9222                 }).css({\r
9223                         width: $.ui.dialog.overlay.width(),\r
9224                         height: $.ui.dialog.overlay.height()\r
9225                 });\r
9226         }\r
9227 });\r
9229 $.extend($.ui.dialog.overlay.prototype, {\r
9230         destroy: function() {\r
9231                 $.ui.dialog.overlay.destroy(this.$el);\r
9232         }\r
9233 });\r
9235 }(jQuery));\r
9236 /*\r
9237  * jQuery UI Position 1.8\r
9238  *\r
9239  * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)\r
9240  * Dual licensed under the MIT (MIT-LICENSE.txt)\r
9241  * and GPL (GPL-LICENSE.txt) licenses.\r
9242  *\r
9243  * http://docs.jquery.com/UI/Position\r
9244  */\r
9245 (function( $ ) {\r
9247 $.ui = $.ui || {};\r
9249 var horizontalPositions = /left|center|right/,\r
9250         horizontalDefault = "center",\r
9251         verticalPositions = /top|center|bottom/,\r
9252         verticalDefault = "center",\r
9253         _position = $.fn.position,\r
9254         _offset = $.fn.offset;\r
9256 $.fn.position = function( options ) {\r
9257         if ( !options || !options.of ) {\r
9258                 return _position.apply( this, arguments );\r
9259         }\r
9261         // make a copy, we don't want to modify arguments\r
9262         options = $.extend( {}, options );\r
9264         var target = $( options.of ),\r
9265                 collision = ( options.collision || "flip" ).split( " " ),\r
9266                 offset = options.offset ? options.offset.split( " " ) : [ 0, 0 ],\r
9267                 targetWidth,\r
9268                 targetHeight,\r
9269                 basePosition;\r
9271         if ( options.of.nodeType === 9 ) {\r
9272                 targetWidth = target.width();\r
9273                 targetHeight = target.height();\r
9274                 basePosition = { top: 0, left: 0 };\r
9275         } else if ( options.of.scrollTo && options.of.document ) {\r
9276                 targetWidth = target.width();\r
9277                 targetHeight = target.height();\r
9278                 basePosition = { top: target.scrollTop(), left: target.scrollLeft() };\r
9279         } else if ( options.of.preventDefault ) {\r
9280                 // force left top to allow flipping\r
9281                 options.at = "left top";\r
9282                 targetWidth = targetHeight = 0;\r
9283                 basePosition = { top: options.of.pageY, left: options.of.pageX };\r
9284         } else {\r
9285                 targetWidth = target.outerWidth();\r
9286                 targetHeight = target.outerHeight();\r
9287                 basePosition = target.offset();\r
9288         }\r
9290         // force my and at to have valid horizontal and veritcal positions\r
9291         // if a value is missing or invalid, it will be converted to center \r
9292         $.each( [ "my", "at" ], function() {\r
9293                 var pos = ( options[this] || "" ).split( " " );\r
9294                 if ( pos.length === 1) {\r
9295                         pos = horizontalPositions.test( pos[0] ) ?\r
9296                                 pos.concat( [verticalDefault] ) :\r
9297                                 verticalPositions.test( pos[0] ) ?\r
9298                                         [ horizontalDefault ].concat( pos ) :\r
9299                                         [ horizontalDefault, verticalDefault ];\r
9300                 }\r
9301                 pos[ 0 ] = horizontalPositions.test( pos[0] ) ? pos[ 0 ] : horizontalDefault;\r
9302                 pos[ 1 ] = verticalPositions.test( pos[1] ) ? pos[ 1 ] : verticalDefault;\r
9303                 options[ this ] = pos;\r
9304         });\r
9306         // normalize collision option\r
9307         if ( collision.length === 1 ) {\r
9308                 collision[ 1 ] = collision[ 0 ];\r
9309         }\r
9311         // normalize offset option\r
9312         offset[ 0 ] = parseInt( offset[0], 10 ) || 0;\r
9313         if ( offset.length === 1 ) {\r
9314                 offset[ 1 ] = offset[ 0 ];\r
9315         }\r
9316         offset[ 1 ] = parseInt( offset[1], 10 ) || 0;\r
9318         if ( options.at[0] === "right" ) {\r
9319                 basePosition.left += targetWidth;\r
9320         } else if (options.at[0] === horizontalDefault ) {\r
9321                 basePosition.left += targetWidth / 2;\r
9322         }\r
9324         if ( options.at[1] === "bottom" ) {\r
9325                 basePosition.top += targetHeight;\r
9326         } else if ( options.at[1] === verticalDefault ) {\r
9327                 basePosition.top += targetHeight / 2;\r
9328         }\r
9330         basePosition.left += offset[ 0 ];\r
9331         basePosition.top += offset[ 1 ];\r
9333         return this.each(function() {\r
9334                 var elem = $( this ),\r
9335                         elemWidth = elem.outerWidth(),\r
9336                         elemHeight = elem.outerHeight(),\r
9337                         position = $.extend( {}, basePosition );\r
9339                 if ( options.my[0] === "right" ) {\r
9340                         position.left -= elemWidth;\r
9341                 } else if ( options.my[0] === horizontalDefault ) {\r
9342                         position.left -= elemWidth / 2;\r
9343                 }\r
9345                 if ( options.my[1] === "bottom" ) {\r
9346                         position.top -= elemHeight;\r
9347                 } else if ( options.my[1] === verticalDefault ) {\r
9348                         position.top -= elemHeight / 2;\r
9349                 }\r
9351                 $.each( [ "left", "top" ], function( i, dir ) {\r
9352                         if ( $.ui.position[ collision[i] ] ) {\r
9353                                 $.ui.position[ collision[i] ][ dir ]( position, {\r
9354                                         targetWidth: targetWidth,\r
9355                                         targetHeight: targetHeight,\r
9356                                         elemWidth: elemWidth,\r
9357                                         elemHeight: elemHeight,\r
9358                                         offset: offset,\r
9359                                         my: options.my,\r
9360                                         at: options.at\r
9361                                 });\r
9362                         }\r
9363                 });\r
9365                 if ( $.fn.bgiframe ) {\r
9366                         elem.bgiframe();\r
9367                 }\r
9368                 elem.offset( $.extend( position, { using: options.using } ) );\r
9369         });\r
9370 };\r
9372 $.ui.position = {\r
9373         fit: {\r
9374                 left: function( position, data ) {\r
9375                         var win = $( window ),\r
9376                                 over = position.left + data.elemWidth - win.width() - win.scrollLeft();\r
9377                         position.left = over > 0 ? position.left - over : Math.max( 0, position.left );\r
9378                 },\r
9379                 top: function( position, data ) {\r
9380                         var win = $( window ),\r
9381                                 over = position.top + data.elemHeight - win.height() - win.scrollTop();\r
9382                         position.top = over > 0 ? position.top - over : Math.max( 0, position.top );\r
9383                 }\r
9384         },\r
9386         flip: {\r
9387                 left: function( position, data ) {\r
9388                         if ( data.at[0] === "center" ) {\r
9389                                 return;\r
9390                         }\r
9391                         var win = $( window ),\r
9392                                 over = position.left + data.elemWidth - win.width() - win.scrollLeft(),\r
9393                                 myOffset = data.my[ 0 ] === "left" ?\r
9394                                         -data.elemWidth :\r
9395                                         data.my[ 0 ] === "right" ?\r
9396                                                 data.elemWidth :\r
9397                                                 0,\r
9398                                 offset = -2 * data.offset[ 0 ];\r
9399                         position.left += position.left < 0 ?\r
9400                                 myOffset + data.targetWidth + offset :\r
9401                                 over > 0 ?\r
9402                                         myOffset - data.targetWidth + offset :\r
9403                                         0;\r
9404                 },\r
9405                 top: function( position, data ) {\r
9406                         if ( data.at[1] === "center" ) {\r
9407                                 return;\r
9408                         }\r
9409                         var win = $( window ),\r
9410                                 over = position.top + data.elemHeight - win.height() - win.scrollTop(),\r
9411                                 myOffset = data.my[ 1 ] === "top" ?\r
9412                                         -data.elemHeight :\r
9413                                         data.my[ 1 ] === "bottom" ?\r
9414                                                 data.elemHeight :\r
9415                                                 0,\r
9416                                 atOffset = data.at[ 1 ] === "top" ?\r
9417                                         data.targetHeight :\r
9418                                         -data.targetHeight,\r
9419                                 offset = -2 * data.offset[ 1 ];\r
9420                         position.top += position.top < 0 ?\r
9421                                 myOffset + data.targetHeight + offset :\r
9422                                 over > 0 ?\r
9423                                         myOffset + atOffset + offset :\r
9424                                         0;\r
9425                 }\r
9426         }\r
9427 };\r
9429 // offset setter from jQuery 1.4\r
9430 if ( !$.offset.setOffset ) {\r
9431         $.offset.setOffset = function( elem, options ) {\r
9432                 // set position first, in-case top/left are set even on static elem\r
9433                 if ( /static/.test( $.curCSS( elem, "position" ) ) ) {\r
9434                         elem.style.position = "relative";\r
9435                 }\r
9436                 var curElem   = $( elem ),\r
9437                         curOffset = curElem.offset(),\r
9438                         curTop    = parseInt( $.curCSS( elem, "top",  true ), 10 ) || 0,\r
9439                         curLeft   = parseInt( $.curCSS( elem, "left", true ), 10)  || 0,\r
9440                         props     = {\r
9441                                 top:  (options.top  - curOffset.top)  + curTop,\r
9442                                 left: (options.left - curOffset.left) + curLeft\r
9443                         };\r
9444                 \r
9445                 if ( 'using' in options ) {\r
9446                         options.using.call( elem, props );\r
9447                 } else {\r
9448                         curElem.css( props );\r
9449                 }\r
9450         };\r
9452         $.fn.offset = function( options ) {\r
9453                 var elem = this[ 0 ];\r
9454                 if ( !elem || !elem.ownerDocument ) { return null; }\r
9455                 if ( options ) { \r
9456                         return this.each(function() {\r
9457                                 $.offset.setOffset( this, options );\r
9458                         });\r
9459                 }\r
9460                 return _offset.call( this );\r
9461         };\r
9464 }( jQuery ));\r
9465 /*\r
9466  * jQuery UI Progressbar 1.8\r
9467  *\r
9468  * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)\r
9469  * Dual licensed under the MIT (MIT-LICENSE.txt)\r
9470  * and GPL (GPL-LICENSE.txt) licenses.\r
9471  *\r
9472  * http://docs.jquery.com/UI/Progressbar\r
9473  *\r
9474  * Depends:\r
9475  *   jquery.ui.core.js\r
9476  *   jquery.ui.widget.js\r
9477  */\r
9478 (function( $ ) {\r
9480 $.widget( "ui.progressbar", {\r
9481         options: {\r
9482                 value: 0\r
9483         },\r
9484         _create: function() {\r
9485                 this.element\r
9486                         .addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )\r
9487                         .attr({\r
9488                                 role: "progressbar",\r
9489                                 "aria-valuemin": this._valueMin(),\r
9490                                 "aria-valuemax": this._valueMax(),\r
9491                                 "aria-valuenow": this._value()\r
9492                         });\r
9494                 this.valueDiv = $( "<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>" )\r
9495                         .appendTo( this.element );\r
9497                 this._refreshValue();\r
9498         },\r
9500         destroy: function() {\r
9501                 this.element\r
9502                         .removeClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )\r
9503                         .removeAttr( "role" )\r
9504                         .removeAttr( "aria-valuemin" )\r
9505                         .removeAttr( "aria-valuemax" )\r
9506                         .removeAttr( "aria-valuenow" );\r
9508                 this.valueDiv.remove();\r
9510                 $.Widget.prototype.destroy.apply( this, arguments );\r
9511         },\r
9513         value: function( newValue ) {\r
9514                 if ( newValue === undefined ) {\r
9515                         return this._value();\r
9516                 }\r
9518                 this._setOption( "value", newValue );\r
9519                 return this;\r
9520         },\r
9522         _setOption: function( key, value ) {\r
9523                 switch ( key ) {\r
9524                         case "value":\r
9525                                 this.options.value = value;\r
9526                                 this._refreshValue();\r
9527                                 this._trigger( "change" );\r
9528                                 break;\r
9529                 }\r
9531                 $.Widget.prototype._setOption.apply( this, arguments );\r
9532         },\r
9534         _value: function() {\r
9535                 var val = this.options.value;\r
9536                 // normalize invalid value\r
9537                 if ( typeof val !== "number" ) {\r
9538                         val = 0;\r
9539                 }\r
9540                 if ( val < this._valueMin() ) {\r
9541                         val = this._valueMin();\r
9542                 }\r
9543                 if ( val > this._valueMax() ) {\r
9544                         val = this._valueMax();\r
9545                 }\r
9547                 return val;\r
9548         },\r
9550         _valueMin: function() {\r
9551                 return 0;\r
9552         },\r
9554         _valueMax: function() {\r
9555                 return 100;\r
9556         },\r
9558         _refreshValue: function() {\r
9559                 var value = this.value();\r
9560                 this.valueDiv\r
9561                         [ value === this._valueMax() ? "addClass" : "removeClass"]( "ui-corner-right" )\r
9562                         .width( value + "%" );\r
9563                 this.element.attr( "aria-valuenow", value );\r
9564         }\r
9565 });\r
9567 $.extend( $.ui.progressbar, {\r
9568         version: "1.8"\r
9569 });\r
9571 })( jQuery );\r
9572 /*\r
9573  * jQuery UI Slider 1.8\r
9574  *\r
9575  * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)\r
9576  * Dual licensed under the MIT (MIT-LICENSE.txt)\r
9577  * and GPL (GPL-LICENSE.txt) licenses.\r
9578  *\r
9579  * http://docs.jquery.com/UI/Slider\r
9580  *\r
9581  * Depends:\r
9582  *      jquery.ui.core.js\r
9583  *      jquery.ui.mouse.js\r
9584  *      jquery.ui.widget.js\r
9585  */\r
9587 (function($) {\r
9589 // number of pages in a slider\r
9590 // (how many times can you page up/down to go through the whole range)\r
9591 var numPages = 5;\r
9593 $.widget("ui.slider", $.ui.mouse, {\r
9594         widgetEventPrefix: "slide",\r
9595         options: {\r
9596                 animate: false,\r
9597                 distance: 0,\r
9598                 max: 100,\r
9599                 min: 0,\r
9600                 orientation: 'horizontal',\r
9601                 range: false,\r
9602                 step: 1,\r
9603                 value: 0,\r
9604                 values: null\r
9605         },\r
9606         _create: function() {\r
9608                 var self = this, o = this.options;\r
9609                 this._keySliding = false;\r
9610                 this._mouseSliding = false;\r
9611                 this._animateOff = true;\r
9612                 this._handleIndex = null;\r
9613                 this._detectOrientation();\r
9614                 this._mouseInit();\r
9616                 this.element\r
9617                         .addClass("ui-slider"\r
9618                                 + " ui-slider-" + this.orientation\r
9619                                 + " ui-widget"\r
9620                                 + " ui-widget-content"\r
9621                                 + " ui-corner-all");\r
9622                 \r
9623                 if (o.disabled) {\r
9624                         this.element.addClass('ui-slider-disabled ui-disabled');\r
9625                 }\r
9627                 this.range = $([]);\r
9629                 if (o.range) {\r
9631                         if (o.range === true) {\r
9632                                 this.range = $('<div></div>');\r
9633                                 if (!o.values) o.values = [this._valueMin(), this._valueMin()];\r
9634                                 if (o.values.length && o.values.length != 2) {\r
9635                                         o.values = [o.values[0], o.values[0]];\r
9636                                 }\r
9637                         } else {\r
9638                                 this.range = $('<div></div>');\r
9639                         }\r
9641                         this.range\r
9642                                 .appendTo(this.element)\r
9643                                 .addClass("ui-slider-range");\r
9645                         if (o.range == "min" || o.range == "max") {\r
9646                                 this.range.addClass("ui-slider-range-" + o.range);\r
9647                         }\r
9649                         // note: this isn't the most fittingly semantic framework class for this element,\r
9650                         // but worked best visually with a variety of themes\r
9651                         this.range.addClass("ui-widget-header");\r
9653                 }\r
9655                 if ($(".ui-slider-handle", this.element).length == 0)\r
9656                         $('<a href="#"></a>')\r
9657                                 .appendTo(this.element)\r
9658                                 .addClass("ui-slider-handle");\r
9660                 if (o.values && o.values.length) {\r
9661                         while ($(".ui-slider-handle", this.element).length < o.values.length)\r
9662                                 $('<a href="#"></a>')\r
9663                                         .appendTo(this.element)\r
9664                                         .addClass("ui-slider-handle");\r
9665                 }\r
9667                 this.handles = $(".ui-slider-handle", this.element)\r
9668                         .addClass("ui-state-default"\r
9669                                 + " ui-corner-all");\r
9671                 this.handle = this.handles.eq(0);\r
9673                 this.handles.add(this.range).filter("a")\r
9674                         .click(function(event) {\r
9675                                 event.preventDefault();\r
9676                         })\r
9677                         .hover(function() {\r
9678                                 if (!o.disabled) {\r
9679                                         $(this).addClass('ui-state-hover');\r
9680                                 }\r
9681                         }, function() {\r
9682                                 $(this).removeClass('ui-state-hover');\r
9683                         })\r
9684                         .focus(function() {\r
9685                                 if (!o.disabled) {\r
9686                                         $(".ui-slider .ui-state-focus").removeClass('ui-state-focus'); $(this).addClass('ui-state-focus');\r
9687                                 } else {\r
9688                                         $(this).blur();\r
9689                                 }\r
9690                         })\r
9691                         .blur(function() {\r
9692                                 $(this).removeClass('ui-state-focus');\r
9693                         });\r
9695                 this.handles.each(function(i) {\r
9696                         $(this).data("index.ui-slider-handle", i);\r
9697                 });\r
9699                 this.handles.keydown(function(event) {\r
9701                         var ret = true;\r
9703                         var index = $(this).data("index.ui-slider-handle");\r
9705                         if (self.options.disabled)\r
9706                                 return;\r
9708                         switch (event.keyCode) {\r
9709                                 case $.ui.keyCode.HOME:\r
9710                                 case $.ui.keyCode.END:\r
9711                                 case $.ui.keyCode.PAGE_UP:\r
9712                                 case $.ui.keyCode.PAGE_DOWN:\r
9713                                 case $.ui.keyCode.UP:\r
9714                                 case $.ui.keyCode.RIGHT:\r
9715                                 case $.ui.keyCode.DOWN:\r
9716                                 case $.ui.keyCode.LEFT:\r
9717                                         ret = false;\r
9718                                         if (!self._keySliding) {\r
9719                                                 self._keySliding = true;\r
9720                                                 $(this).addClass("ui-state-active");\r
9721                                                 self._start(event, index);\r
9722                                         }\r
9723                                         break;\r
9724                         }\r
9726                         var curVal, newVal, step = self._step();\r
9727                         if (self.options.values && self.options.values.length) {\r
9728                                 curVal = newVal = self.values(index);\r
9729                         } else {\r
9730                                 curVal = newVal = self.value();\r
9731                         }\r
9733                         switch (event.keyCode) {\r
9734                                 case $.ui.keyCode.HOME:\r
9735                                         newVal = self._valueMin();\r
9736                                         break;\r
9737                                 case $.ui.keyCode.END:\r
9738                                         newVal = self._valueMax();\r
9739                                         break;\r
9740                                 case $.ui.keyCode.PAGE_UP:\r
9741                                         newVal = curVal + ((self._valueMax() - self._valueMin()) / numPages);\r
9742                                         break;\r
9743                                 case $.ui.keyCode.PAGE_DOWN:\r
9744                                         newVal = curVal - ((self._valueMax() - self._valueMin()) / numPages);\r
9745                                         break;\r
9746                                 case $.ui.keyCode.UP:\r
9747                                 case $.ui.keyCode.RIGHT:\r
9748                                         if(curVal == self._valueMax()) return;\r
9749                                         newVal = curVal + step;\r
9750                                         break;\r
9751                                 case $.ui.keyCode.DOWN:\r
9752                                 case $.ui.keyCode.LEFT:\r
9753                                         if(curVal == self._valueMin()) return;\r
9754                                         newVal = curVal - step;\r
9755                                         break;\r
9756                         }\r
9758                         self._slide(event, index, newVal);\r
9760                         return ret;\r
9762                 }).keyup(function(event) {\r
9764                         var index = $(this).data("index.ui-slider-handle");\r
9766                         if (self._keySliding) {\r
9767                                 self._keySliding = false;\r
9768                                 self._stop(event, index);\r
9769                                 self._change(event, index);\r
9770                                 $(this).removeClass("ui-state-active");\r
9771                         }\r
9773                 });\r
9775                 this._refreshValue();\r
9777                 this._animateOff = false;\r
9779         },\r
9781         destroy: function() {\r
9783                 this.handles.remove();\r
9784                 this.range.remove();\r
9786                 this.element\r
9787                         .removeClass("ui-slider"\r
9788                                 + " ui-slider-horizontal"\r
9789                                 + " ui-slider-vertical"\r
9790                                 + " ui-slider-disabled"\r
9791                                 + " ui-widget"\r
9792                                 + " ui-widget-content"\r
9793                                 + " ui-corner-all")\r
9794                         .removeData("slider")\r
9795                         .unbind(".slider");\r
9797                 this._mouseDestroy();\r
9799                 return this;\r
9800         },\r
9802         _mouseCapture: function(event) {\r
9804                 var o = this.options;\r
9806                 if (o.disabled)\r
9807                         return false;\r
9809                 this.elementSize = {\r
9810                         width: this.element.outerWidth(),\r
9811                         height: this.element.outerHeight()\r
9812                 };\r
9813                 this.elementOffset = this.element.offset();\r
9815                 var position = { x: event.pageX, y: event.pageY };\r
9816                 var normValue = this._normValueFromMouse(position);\r
9818                 var distance = this._valueMax() - this._valueMin() + 1, closestHandle;\r
9819                 var self = this, index;\r
9820                 this.handles.each(function(i) {\r
9821                         var thisDistance = Math.abs(normValue - self.values(i));\r
9822                         if (distance > thisDistance) {\r
9823                                 distance = thisDistance;\r
9824                                 closestHandle = $(this);\r
9825                                 index = i;\r
9826                         }\r
9827                 });\r
9829                 // workaround for bug #3736 (if both handles of a range are at 0,\r
9830                 // the first is always used as the one with least distance,\r
9831                 // and moving it is obviously prevented by preventing negative ranges)\r
9832                 if(o.range == true && this.values(1) == o.min) {\r
9833                         closestHandle = $(this.handles[++index]);\r
9834                 }\r
9836                 this._start(event, index);\r
9837                 this._mouseSliding = true;\r
9839                 self._handleIndex = index;\r
9841                 closestHandle\r
9842                         .addClass("ui-state-active")\r
9843                         .focus();\r
9844                 \r
9845                 var offset = closestHandle.offset();\r
9846                 var mouseOverHandle = !$(event.target).parents().andSelf().is('.ui-slider-handle');\r
9847                 this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {\r
9848                         left: event.pageX - offset.left - (closestHandle.width() / 2),\r
9849                         top: event.pageY - offset.top\r
9850                                 - (closestHandle.height() / 2)\r
9851                                 - (parseInt(closestHandle.css('borderTopWidth'),10) || 0)\r
9852                                 - (parseInt(closestHandle.css('borderBottomWidth'),10) || 0)\r
9853                                 + (parseInt(closestHandle.css('marginTop'),10) || 0)\r
9854                 };\r
9856                 normValue = this._normValueFromMouse(position);\r
9857                 this._slide(event, index, normValue);\r
9858                 this._animateOff = true;\r
9859                 return true;\r
9861         },\r
9863         _mouseStart: function(event) {\r
9864                 return true;\r
9865         },\r
9867         _mouseDrag: function(event) {\r
9869                 var position = { x: event.pageX, y: event.pageY };\r
9870                 var normValue = this._normValueFromMouse(position);\r
9871                 \r
9872                 this._slide(event, this._handleIndex, normValue);\r
9874                 return false;\r
9876         },\r
9878         _mouseStop: function(event) {\r
9880                 this.handles.removeClass("ui-state-active");\r
9881                 this._mouseSliding = false;\r
9882                 this._stop(event, this._handleIndex);\r
9883                 this._change(event, this._handleIndex);\r
9884                 this._handleIndex = null;\r
9885                 this._clickOffset = null;\r
9887                 this._animateOff = false;\r
9888                 return false;\r
9890         },\r
9891         \r
9892         _detectOrientation: function() {\r
9893                 this.orientation = this.options.orientation == 'vertical' ? 'vertical' : 'horizontal';\r
9894         },\r
9896         _normValueFromMouse: function(position) {\r
9898                 var pixelTotal, pixelMouse;\r
9899                 if ('horizontal' == this.orientation) {\r
9900                         pixelTotal = this.elementSize.width;\r
9901                         pixelMouse = position.x - this.elementOffset.left - (this._clickOffset ? this._clickOffset.left : 0);\r
9902                 } else {\r
9903                         pixelTotal = this.elementSize.height;\r
9904                         pixelMouse = position.y - this.elementOffset.top - (this._clickOffset ? this._clickOffset.top : 0);\r
9905                 }\r
9907                 var percentMouse = (pixelMouse / pixelTotal);\r
9908                 if (percentMouse > 1) percentMouse = 1;\r
9909                 if (percentMouse < 0) percentMouse = 0;\r
9910                 if ('vertical' == this.orientation)\r
9911                         percentMouse = 1 - percentMouse;\r
9913                 var valueTotal = this._valueMax() - this._valueMin(),\r
9914                         valueMouse = percentMouse * valueTotal,\r
9915                         valueMouseModStep = valueMouse % this.options.step,\r
9916                         normValue = this._valueMin() + valueMouse - valueMouseModStep;\r
9918                 if (valueMouseModStep > (this.options.step / 2))\r
9919                         normValue += this.options.step;\r
9921                 // Since JavaScript has problems with large floats, round\r
9922                 // the final value to 5 digits after the decimal point (see #4124)\r
9923                 return parseFloat(normValue.toFixed(5));\r
9925         },\r
9927         _start: function(event, index) {\r
9928                 var uiHash = {\r
9929                         handle: this.handles[index],\r
9930                         value: this.value()\r
9931                 };\r
9932                 if (this.options.values && this.options.values.length) {\r
9933                         uiHash.value = this.values(index);\r
9934                         uiHash.values = this.values();\r
9935                 }\r
9936                 this._trigger("start", event, uiHash);\r
9937         },\r
9939         _slide: function(event, index, newVal) {\r
9941                 var handle = this.handles[index];\r
9943                 if (this.options.values && this.options.values.length) {\r
9945                         var otherVal = this.values(index ? 0 : 1);\r
9947                         if ((this.options.values.length == 2 && this.options.range === true) && \r
9948                                 ((index == 0 && newVal > otherVal) || (index == 1 && newVal < otherVal))){\r
9949                                 newVal = otherVal;\r
9950                         }\r
9952                         if (newVal != this.values(index)) {\r
9953                                 var newValues = this.values();\r
9954                                 newValues[index] = newVal;\r
9955                                 // A slide can be canceled by returning false from the slide callback\r
9956                                 var allowed = this._trigger("slide", event, {\r
9957                                         handle: this.handles[index],\r
9958                                         value: newVal,\r
9959                                         values: newValues\r
9960                                 });\r
9961                                 var otherVal = this.values(index ? 0 : 1);\r
9962                                 if (allowed !== false) {\r
9963                                         this.values(index, newVal, true);\r
9964                                 }\r
9965                         }\r
9967                 } else {\r
9969                         if (newVal != this.value()) {\r
9970                                 // A slide can be canceled by returning false from the slide callback\r
9971                                 var allowed = this._trigger("slide", event, {\r
9972                                         handle: this.handles[index],\r
9973                                         value: newVal\r
9974                                 });\r
9975                                 if (allowed !== false) {\r
9976                                         this.value(newVal);\r
9977                                 }\r
9978                                         \r
9979                         }\r
9981                 }\r
9983         },\r
9985         _stop: function(event, index) {\r
9986                 var uiHash = {\r
9987                         handle: this.handles[index],\r
9988                         value: this.value()\r
9989                 };\r
9990                 if (this.options.values && this.options.values.length) {\r
9991                         uiHash.value = this.values(index);\r
9992                         uiHash.values = this.values();\r
9993                 }\r
9994                 this._trigger("stop", event, uiHash);\r
9995         },\r
9997         _change: function(event, index) {\r
9998                 if (!this._keySliding && !this._mouseSliding) {\r
9999                         var uiHash = {\r
10000                                 handle: this.handles[index],\r
10001                                 value: this.value()\r
10002                         };\r
10003                         if (this.options.values && this.options.values.length) {\r
10004                                 uiHash.value = this.values(index);\r
10005                                 uiHash.values = this.values();\r
10006                         }\r
10007                         this._trigger("change", event, uiHash);\r
10008                 }\r
10009         },\r
10011         value: function(newValue) {\r
10013                 if (arguments.length) {\r
10014                         this.options.value = this._trimValue(newValue);\r
10015                         this._refreshValue();\r
10016                         this._change(null, 0);\r
10017                 }\r
10019                 return this._value();\r
10021         },\r
10023         values: function(index, newValue) {\r
10025                 if (arguments.length > 1) {\r
10026                         this.options.values[index] = this._trimValue(newValue);\r
10027                         this._refreshValue();\r
10028                         this._change(null, index);\r
10029                 }\r
10031                 if (arguments.length) {\r
10032                         if ($.isArray(arguments[0])) {\r
10033                                 var vals = this.options.values, newValues = arguments[0];\r
10034                                 for (var i = 0, l = vals.length; i < l; i++) {\r
10035                                         vals[i] = this._trimValue(newValues[i]);\r
10036                                         this._change(null, i);\r
10037                                 }\r
10038                                 this._refreshValue();\r
10039                         } else {\r
10040                                 if (this.options.values && this.options.values.length) {\r
10041                                         return this._values(index);\r
10042                                 } else {\r
10043                                         return this.value();\r
10044                                 }\r
10045                         }\r
10046                 } else {\r
10047                         return this._values();\r
10048                 }\r
10050         },\r
10052         _setOption: function(key, value) {\r
10053                 \r
10054                 var i,\r
10055                         valsLength = 0;\r
10056                 if ( jQuery.isArray(this.options.values) ) {\r
10057                         valsLength = this.options.values.length;\r
10058                 };\r
10060                 $.Widget.prototype._setOption.apply(this, arguments);\r
10062                 switch (key) {\r
10063                         case 'disabled':\r
10064                                 if (value) {\r
10065                                         this.handles.filter(".ui-state-focus").blur();\r
10066                                         this.handles.removeClass("ui-state-hover");\r
10067                                         this.handles.attr("disabled", "disabled");\r
10068                                         this.element.addClass("ui-disabled");\r
10069                                 } else {\r
10070                                         this.handles.removeAttr("disabled");\r
10071                                         this.element.removeClass("ui-disabled");\r
10072                                 }\r
10073                         case 'orientation':\r
10075                                 this._detectOrientation();\r
10076                                 \r
10077                                 this.element\r
10078                                         .removeClass("ui-slider-horizontal ui-slider-vertical")\r
10079                                         .addClass("ui-slider-" + this.orientation);\r
10080                                 this._refreshValue();\r
10081                                 break;\r
10082                         case 'value':\r
10083                                 this._animateOff = true;\r
10084                                 this._refreshValue();\r
10085                                 this._change(null, 0);\r
10086                                 this._animateOff = false;\r
10087                                 break;\r
10088                         case 'values':\r
10089                                 this._animateOff = true;\r
10090                                 this._refreshValue();\r
10091                                 for (i = 0; i < valsLength; i++) {\r
10092                                         this._change(null, i);\r
10093                                 }\r
10094                                 this._animateOff = false;\r
10095                                 break;\r
10096                 }\r
10098         },\r
10100         _step: function() {\r
10101                 var step = this.options.step;\r
10102                 return step;\r
10103         },\r
10105         _value: function() {\r
10106                 //internal value getter\r
10107                 // _value() returns value trimmed by min and max\r
10108                 var val = this.options.value;\r
10109                 val = this._trimValue(val);\r
10111                 return val;\r
10112         },\r
10114         _values: function(index) {\r
10115                 //internal values getter\r
10116                 // _values() returns array of values trimmed by min and max\r
10117                 // _values(index) returns single value trimmed by min and max\r
10119                 if (arguments.length) {\r
10120                         var val = this.options.values[index];\r
10121                         val = this._trimValue(val);\r
10123                         return val;\r
10124                 } else {\r
10125                         // .slice() creates a copy of the array\r
10126                         // this copy gets trimmed by min and max and then returned\r
10127                         var vals = this.options.values.slice();\r
10128                         for (var i = 0, l = vals.length; i < l; i++) {\r
10129                                 vals[i] = this._trimValue(vals[i]);\r
10130                         }\r
10132                         return vals;\r
10133                 }\r
10135         },\r
10136         \r
10137         _trimValue: function(val) {\r
10138                 if (val < this._valueMin()) val = this._valueMin();\r
10139                 if (val > this._valueMax()) val = this._valueMax();\r
10141                 return val;\r
10142         },\r
10144         _valueMin: function() {\r
10145                 var valueMin = this.options.min;\r
10146                 return valueMin;\r
10147         },\r
10149         _valueMax: function() {\r
10150                 var valueMax = this.options.max;\r
10151                 return valueMax;\r
10152         },\r
10153         \r
10154         _refreshValue: function() {\r
10156                 var oRange = this.options.range, o = this.options, self = this;\r
10157                 var animate = (!this._animateOff) ? o.animate : false;\r
10159                 if (this.options.values && this.options.values.length) {\r
10160                         var vp0, vp1;\r
10161                         this.handles.each(function(i, j) {\r
10162                                 var valPercent = (self.values(i) - self._valueMin()) / (self._valueMax() - self._valueMin()) * 100;\r
10163                                 var _set = {}; _set[self.orientation == 'horizontal' ? 'left' : 'bottom'] = valPercent + '%';\r
10164                                 $(this).stop(1,1)[animate ? 'animate' : 'css'](_set, o.animate);\r
10165                                 if (self.options.range === true) {\r
10166                                         if (self.orientation == 'horizontal') {\r
10167                                                 (i == 0) && self.range.stop(1,1)[animate ? 'animate' : 'css']({ left: valPercent + '%' }, o.animate);\r
10168                                                 (i == 1) && self.range[animate ? 'animate' : 'css']({ width: (valPercent - lastValPercent) + '%' }, { queue: false, duration: o.animate });\r
10169                                         } else {\r
10170                                                 (i == 0) && self.range.stop(1,1)[animate ? 'animate' : 'css']({ bottom: (valPercent) + '%' }, o.animate);\r
10171                                                 (i == 1) && self.range[animate ? 'animate' : 'css']({ height: (valPercent - lastValPercent) + '%' }, { queue: false, duration: o.animate });\r
10172                                         }\r
10173                                 }\r
10174                                 lastValPercent = valPercent;\r
10175                         });\r
10176                 } else {\r
10177                         var value = this.value(),\r
10178                                 valueMin = this._valueMin(),\r
10179                                 valueMax = this._valueMax(),\r
10180                                 valPercent = valueMax != valueMin\r
10181                                         ? (value - valueMin) / (valueMax - valueMin) * 100\r
10182                                         : 0;\r
10183                         var _set = {}; _set[self.orientation == 'horizontal' ? 'left' : 'bottom'] = valPercent + '%';\r
10184                         this.handle.stop(1,1)[animate ? 'animate' : 'css'](_set, o.animate);\r
10186                         (oRange == "min") && (this.orientation == "horizontal") && this.range.stop(1,1)[animate ? 'animate' : 'css']({ width: valPercent + '%' }, o.animate);\r
10187                         (oRange == "max") && (this.orientation == "horizontal") && this.range[animate ? 'animate' : 'css']({ width: (100 - valPercent) + '%' }, { queue: false, duration: o.animate });\r
10188                         (oRange == "min") && (this.orientation == "vertical") && this.range.stop(1,1)[animate ? 'animate' : 'css']({ height: valPercent + '%' }, o.animate);\r
10189                         (oRange == "max") && (this.orientation == "vertical") && this.range[animate ? 'animate' : 'css']({ height: (100 - valPercent) + '%' }, { queue: false, duration: o.animate });\r
10190                 }\r
10192         }\r
10193         \r
10194 });\r
10196 $.extend($.ui.slider, {\r
10197         version: "1.8"\r
10198 });\r
10200 })(jQuery);\r
10201 /*\r
10202  * jQuery UI Tabs 1.8\r
10203  *\r
10204  * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)\r
10205  * Dual licensed under the MIT (MIT-LICENSE.txt)\r
10206  * and GPL (GPL-LICENSE.txt) licenses.\r
10207  *\r
10208  * http://docs.jquery.com/UI/Tabs\r
10209  *\r
10210  * Depends:\r
10211  *      jquery.ui.core.js\r
10212  *      jquery.ui.widget.js\r
10213  */\r
10214 (function($) {\r
10216 var tabId = 0,\r
10217         listId = 0;\r
10219 $.widget("ui.tabs", {\r
10220         options: {\r
10221                 add: null,\r
10222                 ajaxOptions: null,\r
10223                 cache: false,\r
10224                 cookie: null, // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true }\r
10225                 collapsible: false,\r
10226                 disable: null,\r
10227                 disabled: [],\r
10228                 enable: null,\r
10229                 event: 'click',\r
10230                 fx: null, // e.g. { height: 'toggle', opacity: 'toggle', duration: 200 }\r
10231                 idPrefix: 'ui-tabs-',\r
10232                 load: null,\r
10233                 panelTemplate: '<div></div>',\r
10234                 remove: null,\r
10235                 select: null,\r
10236                 show: null,\r
10237                 spinner: '<em>Loading&#8230;</em>',\r
10238                 tabTemplate: '<li><a href="#{href}"><span>#{label}</span></a></li>'\r
10239         },\r
10240         _create: function() {\r
10241                 this._tabify(true);\r
10242         },\r
10244         _setOption: function(key, value) {\r
10245                 if (key == 'selected') {\r
10246                         if (this.options.collapsible && value == this.options.selected) {\r
10247                                 return;\r
10248                         }\r
10249                         this.select(value);\r
10250                 }\r
10251                 else {\r
10252                         this.options[key] = value;\r
10253                         this._tabify();\r
10254                 }\r
10255         },\r
10257         _tabId: function(a) {\r
10258                 return a.title && a.title.replace(/\s/g, '_').replace(/[^A-Za-z0-9\-_:\.]/g, '') ||\r
10259                         this.options.idPrefix + (++tabId);\r
10260         },\r
10262         _sanitizeSelector: function(hash) {\r
10263                 return hash.replace(/:/g, '\\:'); // we need this because an id may contain a ":"\r
10264         },\r
10266         _cookie: function() {\r
10267                 var cookie = this.cookie || (this.cookie = this.options.cookie.name || 'ui-tabs-' + (++listId));\r
10268                 return $.cookie.apply(null, [cookie].concat($.makeArray(arguments)));\r
10269         },\r
10271         _ui: function(tab, panel) {\r
10272                 return {\r
10273                         tab: tab,\r
10274                         panel: panel,\r
10275                         index: this.anchors.index(tab)\r
10276                 };\r
10277         },\r
10279         _cleanup: function() {\r
10280                 // restore all former loading tabs labels\r
10281                 this.lis.filter('.ui-state-processing').removeClass('ui-state-processing')\r
10282                                 .find('span:data(label.tabs)')\r
10283                                 .each(function() {\r
10284                                         var el = $(this);\r
10285                                         el.html(el.data('label.tabs')).removeData('label.tabs');\r
10286                                 });\r
10287         },\r
10289         _tabify: function(init) {\r
10291                 this.list = this.element.find('ol,ul').eq(0);\r
10292                 this.lis = $('li:has(a[href])', this.list);\r
10293                 this.anchors = this.lis.map(function() { return $('a', this)[0]; });\r
10294                 this.panels = $([]);\r
10296                 var self = this, o = this.options;\r
10298                 var fragmentId = /^#.+/; // Safari 2 reports '#' for an empty hash\r
10299                 this.anchors.each(function(i, a) {\r
10300                         var href = $(a).attr('href');\r
10302                         // For dynamically created HTML that contains a hash as href IE < 8 expands\r
10303                         // such href to the full page url with hash and then misinterprets tab as ajax.\r
10304                         // Same consideration applies for an added tab with a fragment identifier\r
10305                         // since a[href=#fragment-identifier] does unexpectedly not match.\r
10306                         // Thus normalize href attribute...\r
10307                         var hrefBase = href.split('#')[0], baseEl;\r
10308                         if (hrefBase && (hrefBase === location.toString().split('#')[0] ||\r
10309                                         (baseEl = $('base')[0]) && hrefBase === baseEl.href)) {\r
10310                                 href = a.hash;\r
10311                                 a.href = href;\r
10312                         }\r
10314                         // inline tab\r
10315                         if (fragmentId.test(href)) {\r
10316                                 self.panels = self.panels.add(self._sanitizeSelector(href));\r
10317                         }\r
10319                         // remote tab\r
10320                         else if (href != '#') { // prevent loading the page itself if href is just "#"\r
10321                                 $.data(a, 'href.tabs', href); // required for restore on destroy\r
10323                                 // TODO until #3808 is fixed strip fragment identifier from url\r
10324                                 // (IE fails to load from such url)\r
10325                                 $.data(a, 'load.tabs', href.replace(/#.*$/, '')); // mutable data\r
10327                                 var id = self._tabId(a);\r
10328                                 a.href = '#' + id;\r
10329                                 var $panel = $('#' + id);\r
10330                                 if (!$panel.length) {\r
10331                                         $panel = $(o.panelTemplate).attr('id', id).addClass('ui-tabs-panel ui-widget-content ui-corner-bottom')\r
10332                                                 .insertAfter(self.panels[i - 1] || self.list);\r
10333                                         $panel.data('destroy.tabs', true);\r
10334                                 }\r
10335                                 self.panels = self.panels.add($panel);\r
10336                         }\r
10338                         // invalid tab href\r
10339                         else {\r
10340                                 o.disabled.push(i);\r
10341                         }\r
10342                 });\r
10344                 // initialization from scratch\r
10345                 if (init) {\r
10347                         // attach necessary classes for styling\r
10348                         this.element.addClass('ui-tabs ui-widget ui-widget-content ui-corner-all');\r
10349                         this.list.addClass('ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all');\r
10350                         this.lis.addClass('ui-state-default ui-corner-top');\r
10351                         this.panels.addClass('ui-tabs-panel ui-widget-content ui-corner-bottom');\r
10353                         // Selected tab\r
10354                         // use "selected" option or try to retrieve:\r
10355                         // 1. from fragment identifier in url\r
10356                         // 2. from cookie\r
10357                         // 3. from selected class attribute on <li>\r
10358                         if (o.selected === undefined) {\r
10359                                 if (location.hash) {\r
10360                                         this.anchors.each(function(i, a) {\r
10361                                                 if (a.hash == location.hash) {\r
10362                                                         o.selected = i;\r
10363                                                         return false; // break\r
10364                                                 }\r
10365                                         });\r
10366                                 }\r
10367                                 if (typeof o.selected != 'number' && o.cookie) {\r
10368                                         o.selected = parseInt(self._cookie(), 10);\r
10369                                 }\r
10370                                 if (typeof o.selected != 'number' && this.lis.filter('.ui-tabs-selected').length) {\r
10371                                         o.selected = this.lis.index(this.lis.filter('.ui-tabs-selected'));\r
10372                                 }\r
10373                                 o.selected = o.selected || (this.lis.length ? 0 : -1);\r
10374                         }\r
10375                         else if (o.selected === null) { // usage of null is deprecated, TODO remove in next release\r
10376                                 o.selected = -1;\r
10377                         }\r
10379                         // sanity check - default to first tab...\r
10380                         o.selected = ((o.selected >= 0 && this.anchors[o.selected]) || o.selected < 0) ? o.selected : 0;\r
10382                         // Take disabling tabs via class attribute from HTML\r
10383                         // into account and update option properly.\r
10384                         // A selected tab cannot become disabled.\r
10385                         o.disabled = $.unique(o.disabled.concat(\r
10386                                 $.map(this.lis.filter('.ui-state-disabled'),\r
10387                                         function(n, i) { return self.lis.index(n); } )\r
10388                         )).sort();\r
10390                         if ($.inArray(o.selected, o.disabled) != -1) {\r
10391                                 o.disabled.splice($.inArray(o.selected, o.disabled), 1);\r
10392                         }\r
10394                         // highlight selected tab\r
10395                         this.panels.addClass('ui-tabs-hide');\r
10396                         this.lis.removeClass('ui-tabs-selected ui-state-active');\r
10397                         if (o.selected >= 0 && this.anchors.length) { // check for length avoids error when initializing empty list\r
10398                                 this.panels.eq(o.selected).removeClass('ui-tabs-hide');\r
10399                                 this.lis.eq(o.selected).addClass('ui-tabs-selected ui-state-active');\r
10401                                 // seems to be expected behavior that the show callback is fired\r
10402                                 self.element.queue("tabs", function() {\r
10403                                         self._trigger('show', null, self._ui(self.anchors[o.selected], self.panels[o.selected]));\r
10404                                 });\r
10405                                 \r
10406                                 this.load(o.selected);\r
10407                         }\r
10409                         // clean up to avoid memory leaks in certain versions of IE 6\r
10410                         $(window).bind('unload', function() {\r
10411                                 self.lis.add(self.anchors).unbind('.tabs');\r
10412                                 self.lis = self.anchors = self.panels = null;\r
10413                         });\r
10415                 }\r
10416                 // update selected after add/remove\r
10417                 else {\r
10418                         o.selected = this.lis.index(this.lis.filter('.ui-tabs-selected'));\r
10419                 }\r
10421                 // update collapsible\r
10422                 this.element[o.collapsible ? 'addClass' : 'removeClass']('ui-tabs-collapsible');\r
10424                 // set or update cookie after init and add/remove respectively\r
10425                 if (o.cookie) {\r
10426                         this._cookie(o.selected, o.cookie);\r
10427                 }\r
10429                 // disable tabs\r
10430                 for (var i = 0, li; (li = this.lis[i]); i++) {\r
10431                         $(li)[$.inArray(i, o.disabled) != -1 &&\r
10432                                 !$(li).hasClass('ui-tabs-selected') ? 'addClass' : 'removeClass']('ui-state-disabled');\r
10433                 }\r
10435                 // reset cache if switching from cached to not cached\r
10436                 if (o.cache === false) {\r
10437                         this.anchors.removeData('cache.tabs');\r
10438                 }\r
10440                 // remove all handlers before, tabify may run on existing tabs after add or option change\r
10441                 this.lis.add(this.anchors).unbind('.tabs');\r
10443                 if (o.event != 'mouseover') {\r
10444                         var addState = function(state, el) {\r
10445                                 if (el.is(':not(.ui-state-disabled)')) {\r
10446                                         el.addClass('ui-state-' + state);\r
10447                                 }\r
10448                         };\r
10449                         var removeState = function(state, el) {\r
10450                                 el.removeClass('ui-state-' + state);\r
10451                         };\r
10452                         this.lis.bind('mouseover.tabs', function() {\r
10453                                 addState('hover', $(this));\r
10454                         });\r
10455                         this.lis.bind('mouseout.tabs', function() {\r
10456                                 removeState('hover', $(this));\r
10457                         });\r
10458                         this.anchors.bind('focus.tabs', function() {\r
10459                                 addState('focus', $(this).closest('li'));\r
10460                         });\r
10461                         this.anchors.bind('blur.tabs', function() {\r
10462                                 removeState('focus', $(this).closest('li'));\r
10463                         });\r
10464                 }\r
10466                 // set up animations\r
10467                 var hideFx, showFx;\r
10468                 if (o.fx) {\r
10469                         if ($.isArray(o.fx)) {\r
10470                                 hideFx = o.fx[0];\r
10471                                 showFx = o.fx[1];\r
10472                         }\r
10473                         else {\r
10474                                 hideFx = showFx = o.fx;\r
10475                         }\r
10476                 }\r
10478                 // Reset certain styles left over from animation\r
10479                 // and prevent IE's ClearType bug...\r
10480                 function resetStyle($el, fx) {\r
10481                         $el.css({ display: '' });\r
10482                         if (!$.support.opacity && fx.opacity) {\r
10483                                 $el[0].style.removeAttribute('filter');\r
10484                         }\r
10485                 }\r
10487                 // Show a tab...\r
10488                 var showTab = showFx ?\r
10489                         function(clicked, $show) {\r
10490                                 $(clicked).closest('li').addClass('ui-tabs-selected ui-state-active');\r
10491                                 $show.hide().removeClass('ui-tabs-hide') // avoid flicker that way\r
10492                                         .animate(showFx, showFx.duration || 'normal', function() {\r
10493                                                 resetStyle($show, showFx);\r
10494                                                 self._trigger('show', null, self._ui(clicked, $show[0]));\r
10495                                         });\r
10496                         } :\r
10497                         function(clicked, $show) {\r
10498                                 $(clicked).closest('li').addClass('ui-tabs-selected ui-state-active');\r
10499                                 $show.removeClass('ui-tabs-hide');\r
10500                                 self._trigger('show', null, self._ui(clicked, $show[0]));\r
10501                         };\r
10503                 // Hide a tab, $show is optional...\r
10504                 var hideTab = hideFx ?\r
10505                         function(clicked, $hide) {\r
10506                                 $hide.animate(hideFx, hideFx.duration || 'normal', function() {\r
10507                                         self.lis.removeClass('ui-tabs-selected ui-state-active');\r
10508                                         $hide.addClass('ui-tabs-hide');\r
10509                                         resetStyle($hide, hideFx);\r
10510                                         self.element.dequeue("tabs");\r
10511                                 });\r
10512                         } :\r
10513                         function(clicked, $hide, $show) {\r
10514                                 self.lis.removeClass('ui-tabs-selected ui-state-active');\r
10515                                 $hide.addClass('ui-tabs-hide');\r
10516                                 self.element.dequeue("tabs");\r
10517                         };\r
10519                 // attach tab event handler, unbind to avoid duplicates from former tabifying...\r
10520                 this.anchors.bind(o.event + '.tabs', function() {\r
10521                         var el = this, $li = $(this).closest('li'), $hide = self.panels.filter(':not(.ui-tabs-hide)'),\r
10522                                         $show = $(self._sanitizeSelector(this.hash));\r
10524                         // If tab is already selected and not collapsible or tab disabled or\r
10525                         // or is already loading or click callback returns false stop here.\r
10526                         // Check if click handler returns false last so that it is not executed\r
10527                         // for a disabled or loading tab!\r
10528                         if (($li.hasClass('ui-tabs-selected') && !o.collapsible) ||\r
10529                                 $li.hasClass('ui-state-disabled') ||\r
10530                                 $li.hasClass('ui-state-processing') ||\r
10531                                 self._trigger('select', null, self._ui(this, $show[0])) === false) {\r
10532                                 this.blur();\r
10533                                 return false;\r
10534                         }\r
10536                         o.selected = self.anchors.index(this);\r
10538                         self.abort();\r
10540                         // if tab may be closed\r
10541                         if (o.collapsible) {\r
10542                                 if ($li.hasClass('ui-tabs-selected')) {\r
10543                                         o.selected = -1;\r
10545                                         if (o.cookie) {\r
10546                                                 self._cookie(o.selected, o.cookie);\r
10547                                         }\r
10549                                         self.element.queue("tabs", function() {\r
10550                                                 hideTab(el, $hide);\r
10551                                         }).dequeue("tabs");\r
10552                                         \r
10553                                         this.blur();\r
10554                                         return false;\r
10555                                 }\r
10556                                 else if (!$hide.length) {\r
10557                                         if (o.cookie) {\r
10558                                                 self._cookie(o.selected, o.cookie);\r
10559                                         }\r
10560                                         \r
10561                                         self.element.queue("tabs", function() {\r
10562                                                 showTab(el, $show);\r
10563                                         });\r
10565                                         self.load(self.anchors.index(this)); // TODO make passing in node possible, see also http://dev.jqueryui.com/ticket/3171\r
10566                                         \r
10567                                         this.blur();\r
10568                                         return false;\r
10569                                 }\r
10570                         }\r
10572                         if (o.cookie) {\r
10573                                 self._cookie(o.selected, o.cookie);\r
10574                         }\r
10576                         // show new tab\r
10577                         if ($show.length) {\r
10578                                 if ($hide.length) {\r
10579                                         self.element.queue("tabs", function() {\r
10580                                                 hideTab(el, $hide);\r
10581                                         });\r
10582                                 }\r
10583                                 self.element.queue("tabs", function() {\r
10584                                         showTab(el, $show);\r
10585                                 });\r
10586                                 \r
10587                                 self.load(self.anchors.index(this));\r
10588                         }\r
10589                         else {\r
10590                                 throw 'jQuery UI Tabs: Mismatching fragment identifier.';\r
10591                         }\r
10593                         // Prevent IE from keeping other link focussed when using the back button\r
10594                         // and remove dotted border from clicked link. This is controlled via CSS\r
10595                         // in modern browsers; blur() removes focus from address bar in Firefox\r
10596                         // which can become a usability and annoying problem with tabs('rotate').\r
10597                         if ($.browser.msie) {\r
10598                                 this.blur();\r
10599                         }\r
10601                 });\r
10603                 // disable click in any case\r
10604                 this.anchors.bind('click.tabs', function(){return false;});\r
10606         },\r
10608         destroy: function() {\r
10609                 var o = this.options;\r
10611                 this.abort();\r
10612                 \r
10613                 this.element.unbind('.tabs')\r
10614                         .removeClass('ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible')\r
10615                         .removeData('tabs');\r
10617                 this.list.removeClass('ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all');\r
10619                 this.anchors.each(function() {\r
10620                         var href = $.data(this, 'href.tabs');\r
10621                         if (href) {\r
10622                                 this.href = href;\r
10623                         }\r
10624                         var $this = $(this).unbind('.tabs');\r
10625                         $.each(['href', 'load', 'cache'], function(i, prefix) {\r
10626                                 $this.removeData(prefix + '.tabs');\r
10627                         });\r
10628                 });\r
10630                 this.lis.unbind('.tabs').add(this.panels).each(function() {\r
10631                         if ($.data(this, 'destroy.tabs')) {\r
10632                                 $(this).remove();\r
10633                         }\r
10634                         else {\r
10635                                 $(this).removeClass([\r
10636                                         'ui-state-default',\r
10637                                         'ui-corner-top',\r
10638                                         'ui-tabs-selected',\r
10639                                         'ui-state-active',\r
10640                                         'ui-state-hover',\r
10641                                         'ui-state-focus',\r
10642                                         'ui-state-disabled',\r
10643                                         'ui-tabs-panel',\r
10644                                         'ui-widget-content',\r
10645                                         'ui-corner-bottom',\r
10646                                         'ui-tabs-hide'\r
10647                                 ].join(' '));\r
10648                         }\r
10649                 });\r
10651                 if (o.cookie) {\r
10652                         this._cookie(null, o.cookie);\r
10653                 }\r
10655                 return this;\r
10656         },\r
10658         add: function(url, label, index) {\r
10659                 if (index === undefined) {\r
10660                         index = this.anchors.length; // append by default\r
10661                 }\r
10663                 var self = this, o = this.options,\r
10664                         $li = $(o.tabTemplate.replace(/#\{href\}/g, url).replace(/#\{label\}/g, label)),\r
10665                         id = !url.indexOf('#') ? url.replace('#', '') : this._tabId($('a', $li)[0]);\r
10667                 $li.addClass('ui-state-default ui-corner-top').data('destroy.tabs', true);\r
10669                 // try to find an existing element before creating a new one\r
10670                 var $panel = $('#' + id);\r
10671                 if (!$panel.length) {\r
10672                         $panel = $(o.panelTemplate).attr('id', id).data('destroy.tabs', true);\r
10673                 }\r
10674                 $panel.addClass('ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide');\r
10676                 if (index >= this.lis.length) {\r
10677                         $li.appendTo(this.list);\r
10678                         $panel.appendTo(this.list[0].parentNode);\r
10679                 }\r
10680                 else {\r
10681                         $li.insertBefore(this.lis[index]);\r
10682                         $panel.insertBefore(this.panels[index]);\r
10683                 }\r
10685                 o.disabled = $.map(o.disabled,\r
10686                         function(n, i) { return n >= index ? ++n : n; });\r
10688                 this._tabify();\r
10690                 if (this.anchors.length == 1) { // after tabify\r
10691                         o.selected = 0;\r
10692                         $li.addClass('ui-tabs-selected ui-state-active');\r
10693                         $panel.removeClass('ui-tabs-hide');\r
10694                         this.element.queue("tabs", function() {\r
10695                                 self._trigger('show', null, self._ui(self.anchors[0], self.panels[0]));\r
10696                         });\r
10697                                 \r
10698                         this.load(0);\r
10699                 }\r
10701                 // callback\r
10702                 this._trigger('add', null, this._ui(this.anchors[index], this.panels[index]));\r
10703                 return this;\r
10704         },\r
10706         remove: function(index) {\r
10707                 var o = this.options, $li = this.lis.eq(index).remove(),\r
10708                         $panel = this.panels.eq(index).remove();\r
10710                 // If selected tab was removed focus tab to the right or\r
10711                 // in case the last tab was removed the tab to the left.\r
10712                 if ($li.hasClass('ui-tabs-selected') && this.anchors.length > 1) {\r
10713                         this.select(index + (index + 1 < this.anchors.length ? 1 : -1));\r
10714                 }\r
10716                 o.disabled = $.map($.grep(o.disabled, function(n, i) { return n != index; }),\r
10717                         function(n, i) { return n >= index ? --n : n; });\r
10719                 this._tabify();\r
10721                 // callback\r
10722                 this._trigger('remove', null, this._ui($li.find('a')[0], $panel[0]));\r
10723                 return this;\r
10724         },\r
10726         enable: function(index) {\r
10727                 var o = this.options;\r
10728                 if ($.inArray(index, o.disabled) == -1) {\r
10729                         return;\r
10730                 }\r
10732                 this.lis.eq(index).removeClass('ui-state-disabled');\r
10733                 o.disabled = $.grep(o.disabled, function(n, i) { return n != index; });\r
10735                 // callback\r
10736                 this._trigger('enable', null, this._ui(this.anchors[index], this.panels[index]));\r
10737                 return this;\r
10738         },\r
10740         disable: function(index) {\r
10741                 var self = this, o = this.options;\r
10742                 if (index != o.selected) { // cannot disable already selected tab\r
10743                         this.lis.eq(index).addClass('ui-state-disabled');\r
10745                         o.disabled.push(index);\r
10746                         o.disabled.sort();\r
10748                         // callback\r
10749                         this._trigger('disable', null, this._ui(this.anchors[index], this.panels[index]));\r
10750                 }\r
10752                 return this;\r
10753         },\r
10755         select: function(index) {\r
10756                 if (typeof index == 'string') {\r
10757                         index = this.anchors.index(this.anchors.filter('[href$=' + index + ']'));\r
10758                 }\r
10759                 else if (index === null) { // usage of null is deprecated, TODO remove in next release\r
10760                         index = -1;\r
10761                 }\r
10762                 if (index == -1 && this.options.collapsible) {\r
10763                         index = this.options.selected;\r
10764                 }\r
10766                 this.anchors.eq(index).trigger(this.options.event + '.tabs');\r
10767                 return this;\r
10768         },\r
10770         load: function(index) {\r
10771                 var self = this, o = this.options, a = this.anchors.eq(index)[0], url = $.data(a, 'load.tabs');\r
10773                 this.abort();\r
10775                 // not remote or from cache\r
10776                 if (!url || this.element.queue("tabs").length !== 0 && $.data(a, 'cache.tabs')) {\r
10777                         this.element.dequeue("tabs");\r
10778                         return;\r
10779                 }\r
10781                 // load remote from here on\r
10782                 this.lis.eq(index).addClass('ui-state-processing');\r
10784                 if (o.spinner) {\r
10785                         var span = $('span', a);\r
10786                         span.data('label.tabs', span.html()).html(o.spinner);\r
10787                 }\r
10789                 this.xhr = $.ajax($.extend({}, o.ajaxOptions, {\r
10790                         url: url,\r
10791                         success: function(r, s) {\r
10792                                 $(self._sanitizeSelector(a.hash)).html(r);\r
10794                                 // take care of tab labels\r
10795                                 self._cleanup();\r
10797                                 if (o.cache) {\r
10798                                         $.data(a, 'cache.tabs', true); // if loaded once do not load them again\r
10799                                 }\r
10801                                 // callbacks\r
10802                                 self._trigger('load', null, self._ui(self.anchors[index], self.panels[index]));\r
10803                                 try {\r
10804                                         o.ajaxOptions.success(r, s);\r
10805                                 }\r
10806                                 catch (e) {}\r
10807                         },\r
10808                         error: function(xhr, s, e) {\r
10809                                 // take care of tab labels\r
10810                                 self._cleanup();\r
10812                                 // callbacks\r
10813                                 self._trigger('load', null, self._ui(self.anchors[index], self.panels[index]));\r
10814                                 try {\r
10815                                         // Passing index avoid a race condition when this method is\r
10816                                         // called after the user has selected another tab.\r
10817                                         // Pass the anchor that initiated this request allows\r
10818                                         // loadError to manipulate the tab content panel via $(a.hash)\r
10819                                         o.ajaxOptions.error(xhr, s, index, a);\r
10820                                 }\r
10821                                 catch (e) {}\r
10822                         }\r
10823                 }));\r
10825                 // last, so that load event is fired before show...\r
10826                 self.element.dequeue("tabs");\r
10828                 return this;\r
10829         },\r
10831         abort: function() {\r
10832                 // stop possibly running animations\r
10833                 this.element.queue([]);\r
10834                 this.panels.stop(false, true);\r
10836                 // "tabs" queue must not contain more than two elements,\r
10837                 // which are the callbacks for the latest clicked tab...\r
10838                 this.element.queue("tabs", this.element.queue("tabs").splice(-2, 2));\r
10840                 // terminate pending requests from other tabs\r
10841                 if (this.xhr) {\r
10842                         this.xhr.abort();\r
10843                         delete this.xhr;\r
10844                 }\r
10846                 // take care of tab labels\r
10847                 this._cleanup();\r
10848                 return this;\r
10849         },\r
10851         url: function(index, url) {\r
10852                 this.anchors.eq(index).removeData('cache.tabs').data('load.tabs', url);\r
10853                 return this;\r
10854         },\r
10856         length: function() {\r
10857                 return this.anchors.length;\r
10858         }\r
10860 });\r
10862 $.extend($.ui.tabs, {\r
10863         version: '1.8'\r
10864 });\r
10866 /*\r
10867  * Tabs Extensions\r
10868  */\r
10870 /*\r
10871  * Rotate\r
10872  */\r
10873 $.extend($.ui.tabs.prototype, {\r
10874         rotation: null,\r
10875         rotate: function(ms, continuing) {\r
10877                 var self = this, o = this.options;\r
10878                 \r
10879                 var rotate = self._rotate || (self._rotate = function(e) {\r
10880                         clearTimeout(self.rotation);\r
10881                         self.rotation = setTimeout(function() {\r
10882                                 var t = o.selected;\r
10883                                 self.select( ++t < self.anchors.length ? t : 0 );\r
10884                         }, ms);\r
10885                         \r
10886                         if (e) {\r
10887                                 e.stopPropagation();\r
10888                         }\r
10889                 });\r
10890                 \r
10891                 var stop = self._unrotate || (self._unrotate = !continuing ?\r
10892                         function(e) {\r
10893                                 if (e.clientX) { // in case of a true click\r
10894                                         self.rotate(null);\r
10895                                 }\r
10896                         } :\r
10897                         function(e) {\r
10898                                 t = o.selected;\r
10899                                 rotate();\r
10900                         });\r
10902                 // start rotation\r
10903                 if (ms) {\r
10904                         this.element.bind('tabsshow', rotate);\r
10905                         this.anchors.bind(o.event + '.tabs', stop);\r
10906                         rotate();\r
10907                 }\r
10908                 // stop rotation\r
10909                 else {\r
10910                         clearTimeout(self.rotation);\r
10911                         this.element.unbind('tabsshow', rotate);\r
10912                         this.anchors.unbind(o.event + '.tabs', stop);\r
10913                         delete this._rotate;\r
10914                         delete this._unrotate;\r
10915                 }\r
10917                 return this;\r
10918         }\r
10919 });\r
10921 })(jQuery);\r